@flaxia/node 0.3.1 → 0.3.2

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.
@@ -26,7 +26,9 @@ var r = [
26
26
  "depth-estimation",
27
27
  "feature-extraction",
28
28
  "image-feature-extraction"
29
- ], i = /* @__PURE__ */ new Map(), a = (e, t) => {
29
+ ], i = /* @__PURE__ */ new Map(), a = 2, o = () => {
30
+ i.clear();
31
+ }, s = (e, t) => {
30
32
  if (!t.tokenBuffer) return e;
31
33
  let n = "", r = null, i = t.tokenBufferIntervalMs ?? 50, a = () => {
32
34
  n &&= (e(n), ""), r = null;
@@ -34,39 +36,43 @@ var r = [
34
36
  return (e) => {
35
37
  n += e, r ||= setTimeout(a, i);
36
38
  };
37
- }, o = async (o, s) => {
38
- let { task: c, model: l, input: u, options: d = {} } = o;
39
- if (!r.includes(c)) throw Error(`Invalid or unsupported task: ${c}. Supported tasks are: ${r.join(", ")}`);
39
+ }, c = async (o, c) => {
40
+ let { task: l, model: u, input: d, options: f = {} } = o;
41
+ if (!r.includes(l)) throw Error(`Invalid or unsupported task: ${l}. Supported tasks are: ${r.join(", ")}`);
40
42
  if (self.crossOriginIsolated) {
41
- let e = d.numThreads ?? navigator.hardwareConcurrency;
43
+ let e = f.numThreads ?? navigator.hardwareConcurrency;
42
44
  t.backends.onnx?.wasm && (t.backends.onnx.wasm.numThreads = Math.max(1, Math.min(e, navigator.hardwareConcurrency || 4)));
43
45
  }
44
- let f = `${c}:${l}`, p = i.get(f);
45
- if (!p) {
46
+ let p = `${l}:${u}`, m = i.get(p);
47
+ if (!m) {
48
+ if (i.size >= a) {
49
+ let e = i.keys().next().value;
50
+ i.delete(e);
51
+ }
46
52
  let e = {
47
- dtype: d.dtype ?? "q4f16",
48
- device: d.device
53
+ dtype: f.dtype ?? "q4f16",
54
+ device: f.device
49
55
  }, t = performance.now();
50
- console.log(`[flaxia-node] ai-inference: loading pipeline task=${c} model=${l} dtype=${e.dtype} device=${e.device ?? "wasm"}`);
56
+ console.log(`[flaxia-node] ai-inference: loading pipeline task=${l} model=${u} dtype=${e.dtype} device=${e.device ?? "wasm"}`);
51
57
  try {
52
- p = await n(c, l, e);
58
+ m = await n(l, u, e);
53
59
  } catch (t) {
54
- if (d.device && d.device !== "wasm") console.warn(`[AiInference] ${d.device} failed, falling back to wasm:`, t), e.device = "wasm", p = await n(c, l, e);
55
- else throw console.error(`[flaxia-node] ai-inference: pipeline load FAILED task=${c} model=${l} error=${t instanceof Error ? t.message : String(t)}`), t;
60
+ if (f.device && f.device !== "wasm") console.warn(`[AiInference] ${f.device} failed, falling back to wasm:`, t), e.device = "wasm", m = await n(l, u, e);
61
+ else throw console.error(`[flaxia-node] ai-inference: pipeline load FAILED task=${l} model=${u} error=${t instanceof Error ? t.message : String(t)}`), t;
56
62
  }
57
- console.log(`[flaxia-node] ai-inference: pipeline ready task=${c} model=${l} loadMs=${Math.round(performance.now() - t)}`), i.set(f, p);
63
+ console.log(`[flaxia-node] ai-inference: pipeline ready task=${l} model=${u} loadMs=${Math.round(performance.now() - t)}`), i.set(p, m);
58
64
  }
59
- let m = {
60
- max_new_tokens: d.max_new_tokens ?? 128,
61
- do_sample: d.do_sample ?? !1
65
+ let h = {
66
+ max_new_tokens: f.max_new_tokens ?? 128,
67
+ do_sample: f.do_sample ?? !1
62
68
  };
63
- d.temperature != null && (m.temperature = d.temperature), d.top_p != null && (m.top_p = d.top_p), d.top_k != null && (m.top_k = d.top_k), d.repetition_penalty != null && (m.repetition_penalty = d.repetition_penalty), d.src_lang != null && (m.src_lang = d.src_lang), d.tgt_lang != null && (m.tgt_lang = d.tgt_lang), s && p.tokenizer && (m.streamer = new e(p.tokenizer, {
69
+ f.temperature != null && (h.temperature = f.temperature), f.top_p != null && (h.top_p = f.top_p), f.top_k != null && (h.top_k = f.top_k), f.repetition_penalty != null && (h.repetition_penalty = f.repetition_penalty), f.src_lang != null && (h.src_lang = f.src_lang), f.tgt_lang != null && (h.tgt_lang = f.tgt_lang), c && m.tokenizer && (h.streamer = new e(m.tokenizer, {
64
70
  skip_prompt: !0,
65
71
  skip_special_tokens: !0,
66
- callback_function: a(s, d)
72
+ callback_function: s(c, f)
67
73
  }));
68
- let h = performance.now(), g = await p(u, m);
69
- return console.log(`[flaxia-node] ai-inference: done task=${c} model=${l} execMs=${Math.round(performance.now() - h)} inputLen=${String(u).length}`), { output: g };
74
+ let g = performance.now(), _ = await m(d, h);
75
+ return console.log(`[flaxia-node] ai-inference: done task=${l} model=${u} execMs=${Math.round(performance.now() - g)} inputLen=${String(d).length}`), { output: _ };
70
76
  };
71
77
  //#endregion
72
- export { o as handleAiInference };
78
+ export { c as handleAiInference, o as releaseCache };
@@ -14047,5 +14047,8 @@ var jd = async (e) => {
14047
14047
  a.close();
14048
14048
  }
14049
14049
  };
14050
+ function Md() {
14051
+ Ed.clear();
14052
+ }
14050
14053
  //#endregion
14051
- export { jd as handleNudeNet };
14054
+ export { jd as handleNudeNet, Md as releaseCache };
@@ -1,6 +1,8 @@
1
1
  //#region src/workloads/vector-embed.ts
2
- var e = null;
3
- async function t(t) {
2
+ var e = null, t = () => {
3
+ e = null;
4
+ };
5
+ async function n(t) {
4
6
  let n = performance.now();
5
7
  if (!e) {
6
8
  let t = performance.now();
@@ -25,4 +27,4 @@ async function t(t) {
25
27
  };
26
28
  }
27
29
  //#endregion
28
- export { t as handleVectorEmbed };
30
+ export { n as handleVectorEmbed, t as releaseCache };
@@ -1,17 +1,19 @@
1
1
  import { t as e } from "./VectorStoreEngine.js";
2
2
  //#region src/workloads/vector-query.ts
3
- var t = null;
4
- async function n() {
3
+ var t = null, n = () => {
4
+ t = null;
5
+ };
6
+ async function r() {
5
7
  return t || (t = new e(), await t.initialize()), t;
6
8
  }
7
- async function r(e) {
8
- let t = await n(), r = performance.now();
9
+ async function i(e) {
10
+ let t = await r(), n = performance.now();
9
11
  try {
10
- let n = await t.query(e);
11
- return console.log(`[flaxia-node] vector-query: done durationMs=${Math.round(performance.now() - r)}`), n;
12
+ let r = await t.query(e);
13
+ return console.log(`[flaxia-node] vector-query: done durationMs=${Math.round(performance.now() - n)}`), r;
12
14
  } catch (e) {
13
15
  throw console.error(`[flaxia-node] vector-query: failed error=${e instanceof Error ? e.message : String(e)}`), e;
14
16
  }
15
17
  }
16
18
  //#endregion
17
- export { r as handleVectorQuery };
19
+ export { i as handleVectorQuery, n as releaseCache };
@@ -1,17 +1,19 @@
1
1
  import { t as e } from "./VectorStoreEngine.js";
2
2
  //#region src/workloads/vector-store.ts
3
- var t = null;
4
- async function n() {
3
+ var t = null, n = () => {
4
+ t = null;
5
+ };
6
+ async function r() {
5
7
  return t || (t = new e(), await t.initialize()), t;
6
8
  }
7
- async function r(e) {
8
- let t = await n(), r = performance.now();
9
+ async function i(e) {
10
+ let t = await r(), n = performance.now();
9
11
  try {
10
- let n = await t.store(e);
11
- return console.log(`[flaxia-node] vector-store: done durationMs=${Math.round(performance.now() - r)}`), n;
12
+ let r = await t.store(e);
13
+ return console.log(`[flaxia-node] vector-store: done durationMs=${Math.round(performance.now() - n)}`), r;
12
14
  } catch (e) {
13
15
  throw console.error(`[flaxia-node] vector-store: failed error=${e instanceof Error ? e.message : String(e)}`), e;
14
16
  }
15
17
  }
16
18
  //#endregion
17
- export { r as handleVectorStore };
19
+ export { i as handleVectorStore, n as releaseCache };
@@ -1 +1 @@
1
- {"version":3,"file":"SignalingClient.d.ts","sourceRoot":"","sources":["../../src/client/SignalingClient.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsPD,eAAO,MAAM,cAAc,GAAI,QAAQ,UAAU,SAehD,CAAC"}
1
+ {"version":3,"file":"SignalingClient.d.ts","sourceRoot":"","sources":["../../src/client/SignalingClient.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqQD,eAAO,MAAM,cAAc,GAAI,QAAQ,UAAU,SAehD,CAAC"}
@@ -1,31 +1,20 @@
1
- /**
2
- * Estimates current CPU contention and throttles work accordingly.
3
- *
4
- * Runs inside the compute Worker (where the actual workload executes) rather
5
- * than on the main thread, so the measurement reflects the thread that does
6
- * the work. Load is estimated with a calibrated busy-loop: a fixed-iteration
7
- * loop takes longer to finish when the system is busy, and the ratio to the
8
- * idle baseline is the estimated load.
9
- *
10
- * There is no direct API for CPU usage in the browser, so this is a heuristic
11
- * used to (a) avoid starting work while the machine is already loaded and
12
- * (b) space out task starts so average CPU stays near `maxLoad`.
13
- */
14
1
  export declare class CpuThrottle {
15
- private baselineMs;
16
- private lastLoad;
17
2
  private readonly maxLoad;
18
- private readonly loopIterations;
19
- constructor(maxLoad?: number, loopIterations?: number);
20
- private busyLoop;
21
- private sample;
22
- calibrate(): Promise<void>;
23
- getCurrentLoad(): Promise<number>;
3
+ private windowStart;
4
+ private windowBusyMs;
5
+ private lastLoad;
6
+ constructor(maxLoad?: number);
7
+ /**
8
+ * Charge a completed task's wall-clock duration (in ms) against the CPU budget.
9
+ * Call this from the worker once a workload has finished (incl. errors/timeouts).
10
+ */
11
+ markTaskComplete(durationMs: number): void;
12
+ private estimate;
24
13
  shouldPause(): Promise<boolean>;
25
14
  /**
26
- * Waits until the system is calm enough to run a task.
27
- * Bounded by `maxWaitMs` so a persistently busy machine cannot stall
28
- * the queue forever.
15
+ * Waits until the rolling busy ratio is back under `maxLoad`.
16
+ * Bounded by `maxWaitMs` so a sustained heavy device cannot stall the queue
17
+ * forever.
29
18
  */
30
19
  waitForSlot(maxWaitMs?: number): Promise<void>;
31
20
  get lastMeasuredLoad(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/executor/throttle.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,OAAO,SAAO,EAAE,cAAc,SAAY;IAKtD,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,MAAM;IAKR,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAM1B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAWjC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;OAIG;IACG,WAAW,CAAC,SAAS,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnD,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF"}
1
+ {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/executor/throttle.ts"],"names":[],"mappings":"AAmBA,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAK;gBAET,OAAO,SAAO;IAI1B;;;OAGG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAU1C,OAAO,CAAC,QAAQ;IAMV,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;OAIG;IACG,WAAW,CAAC,SAAS,SAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9D,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF"}
package/dist/index.js CHANGED
@@ -144,7 +144,7 @@ var e = class {
144
144
  }
145
145
  }, c = (...e) => console.log("[flaxia-node]", ...e), l = (...e) => console.error("[flaxia-node]", ...e), u = "flaxia_node_id", d = "flaxia_node_token", f = class {
146
146
  constructor(e, t, n) {
147
- this.config = e, this.workerPool = t, this.nodeId = n, this.ws = null, this.reconnectAttempts = 0, this.MAX_RECONNECT_DELAY = 3e4, this.destroyed = !1, this.suspended = !1, this.visibilityHandler = null;
147
+ this.config = e, this.workerPool = t, this.nodeId = n, this.ws = null, this.reconnectAttempts = 0, this.MAX_RECONNECT_DELAY = 3e4, this.destroyed = !1, this.suspended = !1, this.visibilityHandler = null, this.inflightTasks = /* @__PURE__ */ new Set();
148
148
  }
149
149
  async connect() {
150
150
  if (this.destroyed) return;
@@ -241,7 +241,8 @@ var e = class {
241
241
  body: JSON.stringify({
242
242
  siteId: this.config.siteId,
243
243
  nodeId: this.nodeId,
244
- capabilities: this.config.capabilities ?? ["ai-inference", "image-process"]
244
+ capabilities: this.config.capabilities ?? ["ai-inference", "image-process"],
245
+ deviceMemory: typeof navigator.deviceMemory == "number" ? navigator.deviceMemory : null
245
246
  })
246
247
  });
247
248
  if (!n.ok) return l(`node register failed HTTP ${n.status} (${t}/crowd/nodes/register)`), null;
@@ -260,18 +261,25 @@ var e = class {
260
261
  this.ws && this.ws.readyState === WebSocket.OPEN && this.ws.send(JSON.stringify(e));
261
262
  }
262
263
  async handleTask(e) {
263
- let t = e.timeoutMs ? e.timeoutMs + 3e4 : void 0, n = performance.now(), r = await this.workerPool.run(e.taskId, e.workload, e.payload, t, (t) => {
264
+ if (this.inflightTasks.has(e.taskId)) return;
265
+ this.inflightTasks.add(e.taskId);
266
+ let t = performance.now();
267
+ try {
268
+ let n = e.timeoutMs ? e.timeoutMs + 3e4 : void 0, r = await this.workerPool.run(e.taskId, e.workload, e.payload, n, (t) => {
269
+ this.send({
270
+ type: "progress",
271
+ taskId: e.taskId,
272
+ token: t
273
+ });
274
+ }, { maxCpuLoad: this.config.maxCpuLoad });
264
275
  this.send({
265
- type: "progress",
276
+ type: "result",
266
277
  taskId: e.taskId,
267
- token: t
268
- });
269
- }, { maxCpuLoad: this.config.maxCpuLoad });
270
- this.send({
271
- type: "result",
272
- taskId: e.taskId,
273
- payload: r
274
- }), c(`task result sent taskId=${e.taskId} workload=${e.workload} durationMs=${Math.round(performance.now() - n)}`);
278
+ payload: r
279
+ }), c(`task result sent taskId=${e.taskId} workload=${e.workload} durationMs=${Math.round(performance.now() - t)}`);
280
+ } finally {
281
+ this.inflightTasks.delete(e.taskId);
282
+ }
275
283
  }
276
284
  setupVisibilityHandler() {
277
285
  this.removeVisibilityHandler(), this.visibilityHandler = () => {
package/dist/worker.js CHANGED
@@ -2,36 +2,24 @@
2
2
  function e(e) {
3
3
  return new Promise((t) => setTimeout(t, e));
4
4
  }
5
- var t = class {
6
- constructor(e = .15, t = 2e6) {
7
- this.baselineMs = null, this.lastLoad = 0, this.maxLoad = Math.max(.05, Math.min(.3, e)), this.loopIterations = t;
5
+ var t = 3e4, n = 3e4, r = class {
6
+ constructor(e = .15) {
7
+ this.windowStart = performance.now(), this.windowBusyMs = 0, this.lastLoad = 0, this.maxLoad = Math.max(.05, Math.min(.3, e));
8
8
  }
9
- busyLoop() {
10
- let e = this.loopIterations, t = performance.now(), n = 0;
11
- for (; n < e;) n++;
12
- return performance.now() - t;
13
- }
14
- sample() {
15
- return [
16
- this.busyLoop(),
17
- this.busyLoop(),
18
- this.busyLoop()
19
- ].sort((e, t) => e - t)[1];
20
- }
21
- async calibrate() {
22
- this.busyLoop(), this.baselineMs = this.sample(), this.lastLoad = 0;
9
+ markTaskComplete(e) {
10
+ let n = performance.now();
11
+ n - this.windowStart > t && (this.windowStart = n, this.windowBusyMs = 0), this.windowBusyMs += Math.max(0, e), this.lastLoad = this.estimate();
23
12
  }
24
- async getCurrentLoad() {
25
- if (this.baselineMs === null) return await this.calibrate(), 0;
26
- let e = this.sample(), t = Math.min(1, Math.max(0, e / this.baselineMs - 1));
27
- return this.lastLoad = t, t;
13
+ estimate() {
14
+ let e = performance.now() - this.windowStart;
15
+ return e <= 0 ? 0 : Math.min(1, Math.max(0, this.windowBusyMs / e));
28
16
  }
29
17
  async shouldPause() {
30
- return await this.getCurrentLoad() > this.maxLoad;
18
+ return this.estimate() > this.maxLoad;
31
19
  }
32
- async waitForSlot(t = 3e4) {
33
- let n = performance.now();
34
- for (; await this.shouldPause() && !(performance.now() - n > t);) await e(500);
20
+ async waitForSlot(t = n) {
21
+ let r = performance.now();
22
+ for (; await this.shouldPause() && !(performance.now() - r > t);) await e(500);
35
23
  }
36
24
  get lastMeasuredLoad() {
37
25
  return this.lastLoad;
@@ -39,71 +27,89 @@ var t = class {
39
27
  get maxLoadValue() {
40
28
  return this.maxLoad;
41
29
  }
42
- }, n = null;
30
+ }, i = null, a = new Set([
31
+ "ai-inference",
32
+ "vector-embed",
33
+ "vector-query",
34
+ "nudenet",
35
+ "image-process",
36
+ "container"
37
+ ]), o = 6e4;
38
+ function s() {
39
+ let e = navigator.deviceMemory;
40
+ return typeof e == "number" && e >= 4;
41
+ }
42
+ var c = /* @__PURE__ */ new Map(), l = null;
43
+ function u() {
44
+ for (let e of c.values()) try {
45
+ e();
46
+ } catch {}
47
+ c.clear();
48
+ }
49
+ function d() {
50
+ l && clearTimeout(l), l = setTimeout(() => {
51
+ l = null, u();
52
+ }, o);
53
+ }
54
+ async function f(e, t, n) {
55
+ switch (e) {
56
+ case "ai-inference":
57
+ let r = await import("./assets/ai-inference.js");
58
+ return c.set(e, r.releaseCache), await r.handleAiInference(t, n);
59
+ case "image-process": return await (await import("./assets/image-process.js")).handleImageProcess(t);
60
+ case "container": return await (await import("./assets/container.js")).handleContainer(t);
61
+ case "vector-embed":
62
+ let i = await import("./assets/vector-embed.js");
63
+ return c.set(e, i.releaseCache), await i.handleVectorEmbed(t);
64
+ case "vector-store":
65
+ let a = await import("./assets/vector-store.js");
66
+ return c.set(e, a.releaseCache), await a.handleVectorStore(t);
67
+ case "vector-query":
68
+ let o = await import("./assets/vector-query.js");
69
+ return c.set(e, o.releaseCache), await o.handleVectorQuery(t);
70
+ case "nudenet":
71
+ let s = await import("./assets/nudenet.js");
72
+ return c.set(e, s.releaseCache), await s.handleNudeNet(t);
73
+ default: throw Error(`Unknown workload type: ${e}`);
74
+ }
75
+ }
43
76
  self.onmessage = async (e) => {
44
- let { id: r, workload: i, payload: a, config: o } = e.data, s = performance.now();
77
+ let { id: t, workload: n, payload: o, config: c } = e.data, l = performance.now();
45
78
  try {
46
- n ||= new t(o?.maxCpuLoad), console.log(`[flaxia-node:worker] task start id=${r} workload=${i}`), await n.waitForSlot();
79
+ if (i ||= new r(c?.maxCpuLoad), console.log(`[flaxia-node:worker] task start id=${t} workload=${n}`), a.has(n) && !s()) {
80
+ let e = navigator.deviceMemory;
81
+ throw Error(`${n}: insufficient device memory (deviceMemory=${e ?? "unknown"})`);
82
+ }
83
+ await i.waitForSlot();
47
84
  let e = setInterval(() => {
48
85
  self.postMessage({
49
- id: r,
86
+ id: t,
50
87
  type: "heartbeat",
51
- cpuLoad: n?.lastMeasuredLoad ?? 0
88
+ cpuLoad: i?.lastMeasuredLoad ?? 0
52
89
  });
53
- }, 1e4);
90
+ }, 1e4), u = performance.now();
54
91
  try {
55
- let e, t = (e) => {
92
+ let e = await f(n, o, (e) => {
56
93
  self.postMessage({
57
- id: r,
94
+ id: t,
58
95
  type: "token",
59
96
  token: e
60
97
  });
61
- };
62
- switch (i) {
63
- case "ai-inference":
64
- let { handleAiInference: n } = await import("./assets/ai-inference.js");
65
- e = await n(a, t);
66
- break;
67
- case "image-process":
68
- let { handleImageProcess: r } = await import("./assets/image-process.js");
69
- e = await r(a);
70
- break;
71
- case "container":
72
- let { handleContainer: o } = await import("./assets/container.js");
73
- e = await o(a);
74
- break;
75
- case "vector-embed":
76
- let { handleVectorEmbed: s } = await import("./assets/vector-embed.js");
77
- e = await s(a);
78
- break;
79
- case "vector-store":
80
- let { handleVectorStore: c } = await import("./assets/vector-store.js");
81
- e = await c(a);
82
- break;
83
- case "vector-query":
84
- let { handleVectorQuery: l } = await import("./assets/vector-query.js");
85
- e = await l(a);
86
- break;
87
- case "nudenet":
88
- let { handleNudeNet: u } = await import("./assets/nudenet.js");
89
- e = await u(a);
90
- break;
91
- default: throw Error(`Unknown workload type: ${i}`);
92
- }
98
+ });
93
99
  self.postMessage({
94
- id: r,
100
+ id: t,
95
101
  type: "done",
96
102
  result: e
97
- }), console.log(`[flaxia-node:worker] task done id=${r} workload=${i} durationMs=${Math.round(performance.now() - s)}`);
103
+ }), console.log(`[flaxia-node:worker] task done id=${t} workload=${n} durationMs=${Math.round(performance.now() - l)}`);
98
104
  } finally {
99
- clearInterval(e);
105
+ clearInterval(e), i.markTaskComplete(performance.now() - u), d();
100
106
  }
101
107
  } catch (e) {
102
- let t = e instanceof Error ? e.message : String(e);
103
- console.error(`[flaxia-node:worker] task error id=${r} workload=${i} error=${t}`), self.postMessage({
104
- id: r,
108
+ let r = e instanceof Error ? e.message : String(e);
109
+ console.error(`[flaxia-node:worker] task error id=${t} workload=${n} error=${r}`), self.postMessage({
110
+ id: t,
105
111
  type: "error",
106
- error: t
112
+ error: r
107
113
  });
108
114
  }
109
115
  };
@@ -1,3 +1,9 @@
1
1
  import type { AiInferencePayload, AiInferenceResult } from '@flaxia/sdk';
2
+ /**
3
+ * Drops all cached model pipelines so the (potentially hundreds of MB of)
4
+ * transformers/onnxruntime memory can be garbage-collected. Called by the
5
+ * worker after an idle period so a node does not pin every model it ever saw.
6
+ */
7
+ export declare const releaseCache: () => void;
2
8
  export declare const handleAiInference: (payload: AiInferencePayload, onToken?: (token: string) => void) => Promise<AiInferenceResult>;
3
9
  //# sourceMappingURL=ai-inference.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-inference.d.ts","sourceRoot":"","sources":["../../src/workloads/ai-inference.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AAwC7F,eAAO,MAAM,iBAAiB,GAC5B,SAAS,kBAAkB,EAC3B,UAAU,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,KAChC,OAAO,CAAC,iBAAiB,CAsE3B,CAAC"}
1
+ {"version":3,"file":"ai-inference.d.ts","sourceRoot":"","sources":["../../src/workloads/ai-inference.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AAe7F;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAO,IAE/B,CAAC;AA4BF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,kBAAkB,EAC3B,UAAU,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,KAChC,OAAO,CAAC,iBAAiB,CA2E3B,CAAC"}
@@ -1,3 +1,4 @@
1
1
  import type { NudeNetPayload, NudeNetResult } from '@flaxia/sdk';
2
2
  export declare const handleNudeNet: (payload: NudeNetPayload) => Promise<NudeNetResult>;
3
+ export declare function releaseCache(): void;
3
4
  //# sourceMappingURL=nudenet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nudenet.d.ts","sourceRoot":"","sources":["../../src/workloads/nudenet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA+KnF,eAAO,MAAM,aAAa,GAAU,SAAS,cAAc,KAAG,OAAO,CAAC,aAAa,CA6BlF,CAAC"}
1
+ {"version":3,"file":"nudenet.d.ts","sourceRoot":"","sources":["../../src/workloads/nudenet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA+KnF,eAAO,MAAM,aAAa,GAAU,SAAS,cAAc,KAAG,OAAO,CAAC,aAAa,CA6BlF,CAAC;AAEF,wBAAgB,YAAY,IAAI,IAAI,CAEnC"}
@@ -1,3 +1,4 @@
1
1
  import type { VectorEmbedPayload, VectorEmbedResult } from '@flaxia/sdk';
2
+ export declare const releaseCache: () => void;
2
3
  export declare function handleVectorEmbed(payload: VectorEmbedPayload): Promise<VectorEmbedResult>;
3
4
  //# sourceMappingURL=vector-embed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vector-embed.d.ts","sourceRoot":"","sources":["../../src/workloads/vector-embed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIzE,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA2C/F"}
1
+ {"version":3,"file":"vector-embed.d.ts","sourceRoot":"","sources":["../../src/workloads/vector-embed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIzE,eAAO,MAAM,YAAY,QAAO,IAE/B,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA2C/F"}
@@ -1,3 +1,4 @@
1
1
  import type { VectorQueryPayload, VectorQueryResult } from '@flaxia/sdk';
2
+ export declare const releaseCache: () => void;
2
3
  export declare function handleVectorQuery(payload: VectorQueryPayload): Promise<VectorQueryResult>;
3
4
  //# sourceMappingURL=vector-query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vector-query.d.ts","sourceRoot":"","sources":["../../src/workloads/vector-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAazE,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAW/F"}
1
+ {"version":3,"file":"vector-query.d.ts","sourceRoot":"","sources":["../../src/workloads/vector-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKzE,eAAO,MAAM,YAAY,QAAO,IAE/B,CAAC;AAUF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAW/F"}
@@ -1,4 +1,5 @@
1
1
  import type { VectorStorePayload, VectorStoreResult } from '@flaxia/sdk';
2
+ export declare const releaseCache: () => void;
2
3
  export declare function handleVectorStore(payload: VectorStorePayload): Promise<VectorStoreResult>;
3
4
  export declare function handleVectorStoreAssignShard(rangeStart: number, rangeEnd: number): Promise<void>;
4
5
  //# sourceMappingURL=vector-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vector-store.d.ts","sourceRoot":"","sources":["../../src/workloads/vector-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAazE,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAW/F;AAED,wBAAsB,4BAA4B,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtG"}
1
+ {"version":3,"file":"vector-store.d.ts","sourceRoot":"","sources":["../../src/workloads/vector-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKzE,eAAO,MAAM,YAAY,QAAO,IAE/B,CAAC;AAUF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAW/F;AAED,wBAAsB,4BAA4B,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flaxia/node",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "./dist/index.d.ts",