@flaxia/node 0.3.0 → 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.
- package/dist/assets/ai-inference.js +30 -21
- package/dist/assets/container.js +9 -1
- package/dist/assets/image-process.js +16 -16
- package/dist/assets/nudenet.js +21 -12
- package/dist/assets/vector-embed.js +19 -10
- package/dist/assets/vector-query.js +13 -5
- package/dist/assets/vector-store.js +13 -5
- package/dist/client/SignalingClient.d.ts.map +1 -1
- package/dist/executor/WorkerPool.d.ts.map +1 -1
- package/dist/executor/throttle.d.ts +13 -24
- package/dist/executor/throttle.d.ts.map +1 -1
- package/dist/index.js +94 -77
- package/dist/worker.js +78 -71
- package/dist/workloads/ai-inference.d.ts +6 -0
- package/dist/workloads/ai-inference.d.ts.map +1 -1
- package/dist/workloads/container.d.ts.map +1 -1
- package/dist/workloads/image-process.d.ts.map +1 -1
- package/dist/workloads/nudenet.d.ts +1 -0
- package/dist/workloads/nudenet.d.ts.map +1 -1
- package/dist/workloads/vector-embed.d.ts +1 -0
- package/dist/workloads/vector-embed.d.ts.map +1 -1
- package/dist/workloads/vector-query.d.ts +1 -0
- package/dist/workloads/vector-query.d.ts.map +1 -1
- package/dist/workloads/vector-store.d.ts +1 -0
- package/dist/workloads/vector-store.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -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 =
|
|
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,36 +36,43 @@ var r = [
|
|
|
34
36
|
return (e) => {
|
|
35
37
|
n += e, r ||= setTimeout(a, i);
|
|
36
38
|
};
|
|
37
|
-
},
|
|
38
|
-
let { task:
|
|
39
|
-
if (!r.includes(
|
|
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 =
|
|
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
|
|
45
|
-
if (!
|
|
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:
|
|
48
|
-
device:
|
|
49
|
-
};
|
|
53
|
+
dtype: f.dtype ?? "q4f16",
|
|
54
|
+
device: f.device
|
|
55
|
+
}, t = performance.now();
|
|
56
|
+
console.log(`[flaxia-node] ai-inference: loading pipeline task=${l} model=${u} dtype=${e.dtype} device=${e.device ?? "wasm"}`);
|
|
50
57
|
try {
|
|
51
|
-
|
|
58
|
+
m = await n(l, u, e);
|
|
52
59
|
} catch (t) {
|
|
53
|
-
if (
|
|
54
|
-
else throw 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;
|
|
55
62
|
}
|
|
56
|
-
i.set(
|
|
63
|
+
console.log(`[flaxia-node] ai-inference: pipeline ready task=${l} model=${u} loadMs=${Math.round(performance.now() - t)}`), i.set(p, m);
|
|
57
64
|
}
|
|
58
|
-
let
|
|
59
|
-
max_new_tokens:
|
|
60
|
-
do_sample:
|
|
65
|
+
let h = {
|
|
66
|
+
max_new_tokens: f.max_new_tokens ?? 128,
|
|
67
|
+
do_sample: f.do_sample ?? !1
|
|
61
68
|
};
|
|
62
|
-
|
|
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, {
|
|
63
70
|
skip_prompt: !0,
|
|
64
71
|
skip_special_tokens: !0,
|
|
65
|
-
callback_function:
|
|
66
|
-
}))
|
|
72
|
+
callback_function: s(c, f)
|
|
73
|
+
}));
|
|
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: _ };
|
|
67
76
|
};
|
|
68
77
|
//#endregion
|
|
69
|
-
export {
|
|
78
|
+
export { c as handleAiInference, o as releaseCache };
|
package/dist/assets/container.js
CHANGED
|
@@ -1118,6 +1118,14 @@ var T = async (e) => {
|
|
|
1118
1118
|
exitCode: -1
|
|
1119
1119
|
};
|
|
1120
1120
|
}
|
|
1121
|
-
}, E = async (e) =>
|
|
1121
|
+
}, E = async (e) => {
|
|
1122
|
+
let t = performance.now();
|
|
1123
|
+
try {
|
|
1124
|
+
let n = await T(e);
|
|
1125
|
+
return console.log(`[flaxia-node] container: done durationMs=${Math.round(performance.now() - t)} exitCode=${n.exitCode ?? "?"}`), n;
|
|
1126
|
+
} catch (e) {
|
|
1127
|
+
throw console.error(`[flaxia-node] container: failed error=${e instanceof Error ? e.message : String(e)}`), e;
|
|
1128
|
+
}
|
|
1129
|
+
};
|
|
1122
1130
|
//#endregion
|
|
1123
1131
|
export { E as handleContainer };
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
//#region src/workloads/image-process.ts
|
|
2
2
|
var e = async (e) => {
|
|
3
|
-
let { operation: t, imageBase64: n, mimeType: r, options: i } = e, a = await (await fetch(`data:${r};base64,${n}`)).blob(),
|
|
4
|
-
if (!
|
|
5
|
-
t === "grayscale" && (
|
|
6
|
-
let
|
|
7
|
-
type:
|
|
3
|
+
let { operation: t, imageBase64: n, mimeType: r, options: i } = e, a = performance.now(), o = Math.round(n.length * .75), s = await (await fetch(`data:${r};base64,${n}`)).blob(), c = await createImageBitmap(s), l = new OffscreenCanvas(i.width || c.width, i.height || c.height), u = l.getContext("2d");
|
|
4
|
+
if (!u) throw Error("Failed to get OffscreenCanvas context");
|
|
5
|
+
t === "grayscale" && (u.filter = "grayscale(100%)"), u.drawImage(c, 0, 0, l.width, l.height);
|
|
6
|
+
let d = i.outputFormat || r.split("/")[1], f = `image/${d}`, p = await l.convertToBlob({
|
|
7
|
+
type: f,
|
|
8
8
|
quality: i.quality || .8
|
|
9
|
-
}),
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
mimeType:
|
|
18
|
-
originalSizeBytes:
|
|
19
|
-
resultSizeBytes:
|
|
9
|
+
}), m = new FileReader(), h = await new Promise((e, t) => {
|
|
10
|
+
m.onloadend = () => {
|
|
11
|
+
let t = m.result.split(",")[1];
|
|
12
|
+
e(t);
|
|
13
|
+
}, m.onerror = t, m.readAsDataURL(p);
|
|
14
|
+
});
|
|
15
|
+
return console.log(`[flaxia-node] image-process: done operation=${t} output=${d} inputBytes=${o} resultBytes=${p.size} durationMs=${Math.round(performance.now() - a)}`), {
|
|
16
|
+
imageBase64: h,
|
|
17
|
+
mimeType: f,
|
|
18
|
+
originalSizeBytes: s.size,
|
|
19
|
+
resultSizeBytes: p.size
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
//#endregion
|
package/dist/assets/nudenet.js
CHANGED
|
@@ -13953,10 +13953,14 @@ var Ed = /* @__PURE__ */ new Map();
|
|
|
13953
13953
|
function Dd(e) {
|
|
13954
13954
|
let t = Ed.get(e);
|
|
13955
13955
|
return t || (t = (async () => {
|
|
13956
|
-
let t =
|
|
13957
|
-
|
|
13958
|
-
let
|
|
13959
|
-
|
|
13956
|
+
let t = e.split("/").pop() ?? e, n = performance.now();
|
|
13957
|
+
console.log(`[flaxia-node] nudenet: downloading model ${t}`);
|
|
13958
|
+
let r = await fetch(e);
|
|
13959
|
+
if (!r.ok) throw Error(`Failed to download ONNX model: ${e} (HTTP ${r.status})`);
|
|
13960
|
+
let i = await r.arrayBuffer();
|
|
13961
|
+
console.log(`[flaxia-node] nudenet: model loaded ${t} bytes=${i.byteLength} downloadMs=${Math.round(performance.now() - n)}`);
|
|
13962
|
+
let a = performance.now(), o = await Se.create(i, { executionProviders: ["wasm"] });
|
|
13963
|
+
return console.log(`[flaxia-node] nudenet: session ready ${t} sessionMs=${Math.round(performance.now() - a)}`), o;
|
|
13960
13964
|
})(), Ed.set(e, t)), t;
|
|
13961
13965
|
}
|
|
13962
13966
|
async function Od(e) {
|
|
@@ -14025,21 +14029,26 @@ var jd = async (e) => {
|
|
|
14025
14029
|
Td();
|
|
14026
14030
|
let n = e.topK ?? 100, r = e.iouThreshold ?? .45, i = e.scoreThreshold ?? .25, a = await Od(e);
|
|
14027
14031
|
try {
|
|
14028
|
-
let { tensor: e, ratio: o } = kd(a),
|
|
14032
|
+
let { tensor: e, ratio: o } = kd(a), s = performance.now(), [c, l] = await Promise.all([Dd(xd), Dd(Sd)]);
|
|
14033
|
+
console.log(`[flaxia-node] nudenet: sessions ready loadMs=${Math.round(performance.now() - s)}`);
|
|
14034
|
+
let u = performance.now(), { output0: d } = await c.run({ images: e }), f = new pe("float32", new Float32Array([
|
|
14029
14035
|
n,
|
|
14030
14036
|
r,
|
|
14031
14037
|
i
|
|
14032
|
-
]), [3]), { selected:
|
|
14033
|
-
detection:
|
|
14034
|
-
config:
|
|
14035
|
-
});
|
|
14036
|
-
return {
|
|
14037
|
-
detections:
|
|
14038
|
+
]), [3]), { selected: p } = await l.run({
|
|
14039
|
+
detection: d,
|
|
14040
|
+
config: f
|
|
14041
|
+
}), m = Ad(p, o);
|
|
14042
|
+
return console.log(`[flaxia-node] nudenet: done detections=${m.length} inferMs=${Math.round(performance.now() - u)} totalMs=${Math.round(performance.now() - t)}`), {
|
|
14043
|
+
detections: m,
|
|
14038
14044
|
durationMs: Date.now() - t
|
|
14039
14045
|
};
|
|
14040
14046
|
} finally {
|
|
14041
14047
|
a.close();
|
|
14042
14048
|
}
|
|
14043
14049
|
};
|
|
14050
|
+
function Md() {
|
|
14051
|
+
Ed.clear();
|
|
14052
|
+
}
|
|
14044
14053
|
//#endregion
|
|
14045
|
-
export { jd as handleNudeNet };
|
|
14054
|
+
export { jd as handleNudeNet, Md as releaseCache };
|
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
//#region src/workloads/vector-embed.ts
|
|
2
|
-
var e = null
|
|
3
|
-
|
|
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
|
-
let
|
|
7
|
-
|
|
8
|
+
let t = performance.now();
|
|
9
|
+
console.log("[flaxia-node] vector-embed: loading pipeline model=onnx-community/Qwen3-Embedding-0.6B-ONNX device=wasm");
|
|
10
|
+
let { pipeline: n } = await import("./transformers.web.js");
|
|
11
|
+
try {
|
|
12
|
+
e = await n("feature-extraction", "onnx-community/Qwen3-Embedding-0.6B-ONNX", { device: "wasm" });
|
|
13
|
+
} catch (e) {
|
|
14
|
+
throw console.error(`[flaxia-node] vector-embed: pipeline load FAILED error=${e instanceof Error ? e.message : String(e)}`), e;
|
|
15
|
+
}
|
|
16
|
+
console.log(`[flaxia-node] vector-embed: pipeline ready loadMs=${Math.round(performance.now() - t)}`);
|
|
8
17
|
}
|
|
9
|
-
let r = await e(t.text, {
|
|
18
|
+
let r = performance.now(), i = await e(t.text, {
|
|
10
19
|
pooling: "mean",
|
|
11
20
|
normalize: !0
|
|
12
|
-
}),
|
|
13
|
-
return {
|
|
14
|
-
vector:
|
|
21
|
+
}), a = Array.from(i.data), o = performance.now() - n;
|
|
22
|
+
return console.log(`[flaxia-node] vector-embed: done dims=${a.length} modelMs=${Math.round(performance.now() - r)} totalMs=${Math.round(o)} textLen=${t.text.length}`), {
|
|
23
|
+
vector: a,
|
|
15
24
|
model: "Qwen/Qwen3-Embedding-0.6B",
|
|
16
25
|
dimensions: 1024,
|
|
17
|
-
durationMs: Math.round(
|
|
26
|
+
durationMs: Math.round(o)
|
|
18
27
|
};
|
|
19
28
|
}
|
|
20
29
|
//#endregion
|
|
21
|
-
export {
|
|
30
|
+
export { n as handleVectorEmbed, t as releaseCache };
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { t as e } from "./VectorStoreEngine.js";
|
|
2
2
|
//#region src/workloads/vector-query.ts
|
|
3
|
-
var t = null
|
|
4
|
-
|
|
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
|
|
8
|
-
|
|
9
|
+
async function i(e) {
|
|
10
|
+
let t = await r(), n = performance.now();
|
|
11
|
+
try {
|
|
12
|
+
let r = await t.query(e);
|
|
13
|
+
return console.log(`[flaxia-node] vector-query: done durationMs=${Math.round(performance.now() - n)}`), r;
|
|
14
|
+
} catch (e) {
|
|
15
|
+
throw console.error(`[flaxia-node] vector-query: failed error=${e instanceof Error ? e.message : String(e)}`), e;
|
|
16
|
+
}
|
|
9
17
|
}
|
|
10
18
|
//#endregion
|
|
11
|
-
export {
|
|
19
|
+
export { i as handleVectorQuery, n as releaseCache };
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { t as e } from "./VectorStoreEngine.js";
|
|
2
2
|
//#region src/workloads/vector-store.ts
|
|
3
|
-
var t = null
|
|
4
|
-
|
|
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
|
|
8
|
-
|
|
9
|
+
async function i(e) {
|
|
10
|
+
let t = await r(), n = performance.now();
|
|
11
|
+
try {
|
|
12
|
+
let r = await t.store(e);
|
|
13
|
+
return console.log(`[flaxia-node] vector-store: done durationMs=${Math.round(performance.now() - n)}`), r;
|
|
14
|
+
} catch (e) {
|
|
15
|
+
throw console.error(`[flaxia-node] vector-store: failed error=${e instanceof Error ? e.message : String(e)}`), e;
|
|
16
|
+
}
|
|
9
17
|
}
|
|
10
18
|
//#endregion
|
|
11
|
-
export {
|
|
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;
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../../src/executor/WorkerPool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../../src/executor/WorkerPool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAahD;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,YAAY,CAAK;gBAEb,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,SAAS;IAMlD,OAAO,CAAC,UAAU;IAYlB,GAAG,CACD,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,OAAO,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,MAAM,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,OAAO,CAAC;IAgBnB,OAAO,CAAC,OAAO;IAiFf,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,aAAa;IAQrB,SAAS;IAaT,MAAM;IAMN,IAAI,WAAW,IAAI,MAAM,CAExB;CACF"}
|
|
@@ -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
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
27
|
-
* Bounded by `maxWaitMs` so a
|
|
28
|
-
*
|
|
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":"
|
|
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
|
@@ -49,7 +49,7 @@ var e = class {
|
|
|
49
49
|
return !0;
|
|
50
50
|
}, a = () => {
|
|
51
51
|
localStorage.setItem(t, "true"), localStorage.setItem(n, String(Date.now() + r));
|
|
52
|
-
}, o = class {
|
|
52
|
+
}, o = (...e) => console.log("[flaxia-node]", ...e), s = class {
|
|
53
53
|
constructor(e, t = 3e5) {
|
|
54
54
|
this.worker = null, this.queue = [], this.active = null, this._lastCpuLoad = 0, this.workerUrl = e || "/worker.js", this.defaultTimeoutMs = t, this.initWorker();
|
|
55
55
|
}
|
|
@@ -63,63 +63,66 @@ var e = class {
|
|
|
63
63
|
}, this.worker = e;
|
|
64
64
|
}
|
|
65
65
|
run(e, t, n, r, i, a) {
|
|
66
|
-
return new Promise((
|
|
66
|
+
return new Promise((s, c) => {
|
|
67
67
|
if (!this.worker) {
|
|
68
|
-
|
|
68
|
+
c(/* @__PURE__ */ Error("Worker not available"));
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
|
-
let
|
|
72
|
-
this.active ? this.queue.push(
|
|
71
|
+
let l = () => this.execute(e, t, n, r, i, a, s, c);
|
|
72
|
+
this.active ? (o(`task queued id=${e} workload=${t} (active task running)`), this.queue.push(l)) : l();
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
-
execute(e, t, n, r, i, a,
|
|
76
|
-
let
|
|
77
|
-
if (!
|
|
78
|
-
|
|
75
|
+
execute(e, t, n, r, i, a, s, c) {
|
|
76
|
+
let l = this.worker;
|
|
77
|
+
if (!l) {
|
|
78
|
+
c(/* @__PURE__ */ Error("Worker not available")), this.dequeue();
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
let
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
let u = r ?? this.defaultTimeoutMs, d = !1, f = performance.now();
|
|
82
|
+
o(`task start id=${e} workload=${t} timeoutMs=${u}`);
|
|
83
|
+
let p = (e) => {
|
|
84
|
+
if (d) return;
|
|
85
|
+
d = !0;
|
|
84
86
|
let t = this.active;
|
|
85
87
|
t && (clearTimeout(t.timer), t.removeListener()), this.active = null, e(), this.dequeue();
|
|
86
|
-
},
|
|
87
|
-
let { id:
|
|
88
|
-
if (
|
|
89
|
-
if (
|
|
90
|
-
i?.(
|
|
88
|
+
}, m = (n) => {
|
|
89
|
+
let { id: r, type: a, result: l, error: u, token: d, cpuLoad: m } = n.data;
|
|
90
|
+
if (r === e) {
|
|
91
|
+
if (a === "token") {
|
|
92
|
+
i?.(d);
|
|
91
93
|
return;
|
|
92
94
|
}
|
|
93
|
-
if (
|
|
94
|
-
typeof
|
|
95
|
+
if (a === "heartbeat") {
|
|
96
|
+
typeof m == "number" && Number.isFinite(m) && (this._lastCpuLoad = Math.min(1, Math.max(0, m)));
|
|
95
97
|
return;
|
|
96
98
|
}
|
|
97
|
-
|
|
99
|
+
a === "done" ? (o(`task done id=${e} workload=${t} durationMs=${Math.round(performance.now() - f)}`), p(() => s(l))) : a === "error" ? (o(`task failed id=${e} workload=${t} error=${u}`), p(() => c(Error(u)))) : (o(`task unknown-message id=${e} type=${String(a)}`), p(() => c(/* @__PURE__ */ Error(`Unknown message type: ${String(a)}`))));
|
|
98
100
|
}
|
|
99
|
-
},
|
|
100
|
-
this.cleanupWorker(),
|
|
101
|
-
},
|
|
101
|
+
}, h = () => l.removeEventListener("message", m), g = setTimeout(() => {
|
|
102
|
+
o(`task timeout id=${e} workload=${t} (worker terminated after ${u}ms)`), this.cleanupWorker(), p(() => c(/* @__PURE__ */ Error("TIMEOUT")));
|
|
103
|
+
}, u);
|
|
102
104
|
this.active = {
|
|
103
105
|
id: e,
|
|
104
|
-
resolve:
|
|
105
|
-
reject:
|
|
106
|
-
timer:
|
|
107
|
-
worker:
|
|
108
|
-
removeListener:
|
|
109
|
-
},
|
|
106
|
+
resolve: s,
|
|
107
|
+
reject: c,
|
|
108
|
+
timer: g,
|
|
109
|
+
worker: l,
|
|
110
|
+
removeListener: h
|
|
111
|
+
}, l.addEventListener("message", m);
|
|
110
112
|
try {
|
|
111
|
-
|
|
113
|
+
l.postMessage({
|
|
112
114
|
id: e,
|
|
113
115
|
workload: t,
|
|
114
116
|
payload: n,
|
|
115
|
-
timeoutMs:
|
|
117
|
+
timeoutMs: u,
|
|
116
118
|
config: a
|
|
117
119
|
});
|
|
118
120
|
} catch (e) {
|
|
119
|
-
|
|
121
|
+
p(() => c(e instanceof Error ? e : Error(String(e))));
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
handleWorkerError(e) {
|
|
125
|
+
o(`worker error error=${e.message}`);
|
|
123
126
|
let t = this.active;
|
|
124
127
|
this.cleanupWorker(), t && (clearTimeout(t.timer), this.active = null, t.reject(e), this.dequeue());
|
|
125
128
|
}
|
|
@@ -139,13 +142,13 @@ var e = class {
|
|
|
139
142
|
get lastCpuLoad() {
|
|
140
143
|
return this._lastCpuLoad;
|
|
141
144
|
}
|
|
142
|
-
},
|
|
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 {
|
|
143
146
|
constructor(e, t, n) {
|
|
144
|
-
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();
|
|
145
148
|
}
|
|
146
149
|
async connect() {
|
|
147
150
|
if (this.destroyed) return;
|
|
148
|
-
if (this.ws) {
|
|
151
|
+
if (c(`connect nodeId=${this.nodeId}`), this.ws) {
|
|
149
152
|
let e = this.ws;
|
|
150
153
|
e.onclose = null;
|
|
151
154
|
try {
|
|
@@ -156,14 +159,14 @@ var e = class {
|
|
|
156
159
|
this.setupVisibilityHandler();
|
|
157
160
|
let e = await this.obtainToken();
|
|
158
161
|
if (!e) {
|
|
159
|
-
this.scheduleReconnect();
|
|
162
|
+
l("token acquisition failed; scheduling reconnect"), this.scheduleReconnect();
|
|
160
163
|
return;
|
|
161
164
|
}
|
|
162
165
|
let t = this.config.orchestratorUrl.replace(/\/+$/, "").replace(/^http/, "ws"), n = new URL(`${t}/crowd/signal`);
|
|
163
166
|
n.searchParams.set("token", e.token);
|
|
164
167
|
let r = new WebSocket(n.toString());
|
|
165
168
|
this.ws = r, r.onopen = () => {
|
|
166
|
-
this.reconnectAttempts = 0;
|
|
169
|
+
this.reconnectAttempts = 0, c(`signal connected ${n.toString()}`);
|
|
167
170
|
}, r.onmessage = async (e) => {
|
|
168
171
|
let t;
|
|
169
172
|
try {
|
|
@@ -178,17 +181,22 @@ var e = class {
|
|
|
178
181
|
});
|
|
179
182
|
return;
|
|
180
183
|
}
|
|
181
|
-
if (t.type === "task")
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
184
|
+
if (t.type === "task") {
|
|
185
|
+
let e = t;
|
|
186
|
+
c(`task received taskId=${e.taskId} workload=${e.workload} timeoutMs=${e.timeoutMs ?? "default"}`);
|
|
187
|
+
try {
|
|
188
|
+
await this.handleTask(e);
|
|
189
|
+
} catch (n) {
|
|
190
|
+
let r = n instanceof Error ? n.message : String(n);
|
|
191
|
+
l(`task failed taskId=${e.taskId} workload=${e.workload} error=${r}`), this.send({
|
|
192
|
+
type: "error",
|
|
193
|
+
taskId: String(t.taskId ?? ""),
|
|
194
|
+
error: r
|
|
195
|
+
});
|
|
196
|
+
}
|
|
189
197
|
}
|
|
190
198
|
}, r.onclose = () => {
|
|
191
|
-
r.onclose = null, this.ws === r && (this.ws = null, !this.destroyed && this.scheduleReconnect());
|
|
199
|
+
r.onclose = null, this.ws === r && (this.ws = null, !this.destroyed && (c(`signal disconnected; scheduling reconnect attempt=${this.reconnectAttempts + 1}`), this.scheduleReconnect()));
|
|
192
200
|
};
|
|
193
201
|
}
|
|
194
202
|
scheduleReconnect() {
|
|
@@ -198,7 +206,7 @@ var e = class {
|
|
|
198
206
|
}, e);
|
|
199
207
|
}
|
|
200
208
|
disconnect() {
|
|
201
|
-
this.destroyed = !0, this.suspended = !1, this.removeVisibilityHandler();
|
|
209
|
+
c(`disconnect nodeId=${this.nodeId}`), this.destroyed = !0, this.suspended = !1, this.removeVisibilityHandler();
|
|
202
210
|
try {
|
|
203
211
|
this.ws?.close();
|
|
204
212
|
} catch {}
|
|
@@ -206,7 +214,7 @@ var e = class {
|
|
|
206
214
|
}
|
|
207
215
|
suspend() {
|
|
208
216
|
if (!(this.suspended || this.destroyed)) {
|
|
209
|
-
if (this.suspended = !0, this.ws) {
|
|
217
|
+
if (c("suspended (visibility or manual)"), this.suspended = !0, this.ws) {
|
|
210
218
|
let e = this.ws;
|
|
211
219
|
e.onclose = null;
|
|
212
220
|
try {
|
|
@@ -218,14 +226,14 @@ var e = class {
|
|
|
218
226
|
}
|
|
219
227
|
}
|
|
220
228
|
resume() {
|
|
221
|
-
!this.suspended || this.destroyed || (this.suspended = !1, this.workerPool.resume(), this.connect());
|
|
229
|
+
!this.suspended || this.destroyed || (c("resumed"), this.suspended = !1, this.workerPool.resume(), this.connect());
|
|
222
230
|
}
|
|
223
231
|
async obtainToken() {
|
|
224
232
|
try {
|
|
225
|
-
let e = localStorage.getItem(
|
|
233
|
+
let e = localStorage.getItem(d);
|
|
226
234
|
if (e) try {
|
|
227
235
|
let t = JSON.parse(e);
|
|
228
|
-
if (t.token && t.nodeId && t.expiresAt > Date.now() + 6e4) return t;
|
|
236
|
+
if (t.token && t.nodeId && t.expiresAt > Date.now() + 6e4) return c(`token cached nodeId=${t.nodeId} expiresIn=${Math.round((t.expiresAt - Date.now()) / 1e3)}s`), t;
|
|
229
237
|
} catch {}
|
|
230
238
|
let t = this.config.orchestratorUrl.replace(/\/+$/, ""), n = await fetch(`${t}/crowd/nodes/register`, {
|
|
231
239
|
method: "POST",
|
|
@@ -233,36 +241,45 @@ var e = class {
|
|
|
233
241
|
body: JSON.stringify({
|
|
234
242
|
siteId: this.config.siteId,
|
|
235
243
|
nodeId: this.nodeId,
|
|
236
|
-
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
|
|
237
246
|
})
|
|
238
247
|
});
|
|
239
|
-
if (!n.ok) return null;
|
|
248
|
+
if (!n.ok) return l(`node register failed HTTP ${n.status} (${t}/crowd/nodes/register)`), null;
|
|
240
249
|
let r = await n.json();
|
|
241
|
-
if (!r.token) return null;
|
|
250
|
+
if (!r.token) return l("node register returned no token"), null;
|
|
251
|
+
c(`node registered nodeId=${this.nodeId} expiresIn=${Math.round((r.expiresAt - Date.now()) / 1e3)}s`);
|
|
242
252
|
try {
|
|
243
|
-
localStorage.setItem(
|
|
253
|
+
localStorage.setItem(d, JSON.stringify(r));
|
|
244
254
|
} catch {}
|
|
245
255
|
return r;
|
|
246
|
-
} catch {
|
|
247
|
-
return null;
|
|
256
|
+
} catch (e) {
|
|
257
|
+
return l("node register threw", e instanceof Error ? e.message : e), null;
|
|
248
258
|
}
|
|
249
259
|
}
|
|
250
260
|
send(e) {
|
|
251
261
|
this.ws && this.ws.readyState === WebSocket.OPEN && this.ws.send(JSON.stringify(e));
|
|
252
262
|
}
|
|
253
263
|
async handleTask(e) {
|
|
254
|
-
|
|
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 });
|
|
255
275
|
this.send({
|
|
256
|
-
type: "
|
|
276
|
+
type: "result",
|
|
257
277
|
taskId: e.taskId,
|
|
258
|
-
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
taskId: e.taskId,
|
|
264
|
-
payload: n
|
|
265
|
-
});
|
|
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
|
+
}
|
|
266
283
|
}
|
|
267
284
|
setupVisibilityHandler() {
|
|
268
285
|
this.removeVisibilityHandler(), this.visibilityHandler = () => {
|
|
@@ -272,22 +289,22 @@ var e = class {
|
|
|
272
289
|
removeVisibilityHandler() {
|
|
273
290
|
this.visibilityHandler &&= (document.removeEventListener("visibilitychange", this.visibilityHandler), null);
|
|
274
291
|
}
|
|
275
|
-
},
|
|
276
|
-
let t = window[
|
|
292
|
+
}, p = "__flaxia_node_signal_client", m = (e) => {
|
|
293
|
+
let t = window[p];
|
|
277
294
|
t && t.disconnect();
|
|
278
|
-
let n = new URL("./worker.js", "" + import.meta.url).href, r = new
|
|
279
|
-
i || (i = crypto.randomUUID(), localStorage.setItem(
|
|
280
|
-
let a = new
|
|
281
|
-
window[
|
|
282
|
-
},
|
|
295
|
+
let n = new URL("./worker.js", "" + import.meta.url).href, r = new s(n), i = localStorage.getItem(u);
|
|
296
|
+
i || (i = crypto.randomUUID(), localStorage.setItem(u, i));
|
|
297
|
+
let a = new f(e, r, i);
|
|
298
|
+
window[p] = a, a.connect();
|
|
299
|
+
}, h = (t) => {
|
|
283
300
|
if (i()) {
|
|
284
|
-
|
|
301
|
+
m(t);
|
|
285
302
|
return;
|
|
286
303
|
}
|
|
287
304
|
let n = document.createElement("div");
|
|
288
305
|
n.id = "flaxia-consent-container", document.body.appendChild(n), new e(n, t.consent, () => {
|
|
289
|
-
a(), n.remove(),
|
|
306
|
+
a(), n.remove(), m(t);
|
|
290
307
|
});
|
|
291
308
|
};
|
|
292
309
|
//#endregion
|
|
293
|
-
export {
|
|
310
|
+
export { h as initFlaxiaNode };
|
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
|
|
7
|
-
this.
|
|
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
|
-
|
|
10
|
-
let
|
|
11
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
18
|
+
return this.estimate() > this.maxLoad;
|
|
31
19
|
}
|
|
32
|
-
async waitForSlot(t =
|
|
33
|
-
let
|
|
34
|
-
for (; await this.shouldPause() && !(performance.now() -
|
|
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,70 +27,89 @@ var t = class {
|
|
|
39
27
|
get maxLoadValue() {
|
|
40
28
|
return this.maxLoad;
|
|
41
29
|
}
|
|
42
|
-
},
|
|
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:
|
|
77
|
+
let { id: t, workload: n, payload: o, config: c } = e.data, l = performance.now();
|
|
45
78
|
try {
|
|
46
|
-
|
|
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:
|
|
86
|
+
id: t,
|
|
50
87
|
type: "heartbeat",
|
|
51
|
-
cpuLoad:
|
|
88
|
+
cpuLoad: i?.lastMeasuredLoad ?? 0
|
|
52
89
|
});
|
|
53
|
-
}, 1e4);
|
|
90
|
+
}, 1e4), u = performance.now();
|
|
54
91
|
try {
|
|
55
|
-
let e
|
|
92
|
+
let e = await f(n, o, (e) => {
|
|
56
93
|
self.postMessage({
|
|
57
|
-
id:
|
|
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:
|
|
100
|
+
id: t,
|
|
95
101
|
type: "done",
|
|
96
102
|
result: e
|
|
97
|
-
});
|
|
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
|
-
|
|
103
|
-
|
|
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,
|
|
104
111
|
type: "error",
|
|
105
|
-
error:
|
|
112
|
+
error: r
|
|
106
113
|
});
|
|
107
114
|
}
|
|
108
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;
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/workloads/container.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAErE,eAAO,MAAM,eAAe,GAAU,SAAS,gBAAgB,KAAG,OAAO,CAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/workloads/container.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAErE,eAAO,MAAM,eAAe,GAAU,SAAS,gBAAgB,KAAG,OAAO,CAAC,eAAe,CAYxF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-process.d.ts","sourceRoot":"","sources":["../../src/workloads/image-process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE3E,eAAO,MAAM,kBAAkB,GAAU,SAAS,mBAAmB,KAAG,OAAO,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"image-process.d.ts","sourceRoot":"","sources":["../../src/workloads/image-process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE3E,eAAO,MAAM,kBAAkB,GAAU,SAAS,mBAAmB,KAAG,OAAO,CAAC,kBAAkB,CAwDjG,CAAC"}
|
|
@@ -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;
|
|
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 +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,
|
|
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 +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;
|
|
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;
|
|
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"}
|