@flaxia/node 0.3.2 → 0.3.4
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 +21 -23
- package/dist/assets/memoryProbe.js +28 -0
- package/dist/assets/nudenet.js +1 -1
- package/dist/assets/vector-embed.js +2 -1
- package/dist/client/SignalingClient.d.ts.map +1 -1
- package/dist/client/__tests__/SignalingClient.incapable.test.d.ts +2 -0
- package/dist/client/__tests__/SignalingClient.incapable.test.d.ts.map +1 -0
- package/dist/consent/storage.d.ts +13 -0
- package/dist/consent/storage.d.ts.map +1 -1
- package/dist/executor/__tests__/memoryProbe.test.d.ts +2 -0
- package/dist/executor/__tests__/memoryProbe.test.d.ts.map +1 -0
- package/dist/executor/memoryProbe.d.ts +4 -0
- package/dist/executor/memoryProbe.d.ts.map +1 -0
- package/dist/index.js +117 -76
- package/dist/worker/__tests__/main.worker.capable.test.d.ts +2 -0
- package/dist/worker/__tests__/main.worker.capable.test.d.ts.map +1 -0
- package/dist/worker/__tests__/main.worker.incapable.test.d.ts +2 -0
- package/dist/worker/__tests__/main.worker.incapable.test.d.ts.map +1 -0
- package/dist/worker.js +39 -40
- package/dist/workloads/__tests__/wasm-threads.test.d.ts +2 -0
- package/dist/workloads/__tests__/wasm-threads.test.d.ts.map +1 -0
- package/dist/workloads/ai-inference.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.map +1 -1
- package/package.json +1 -1
|
@@ -36,43 +36,41 @@ var r = [
|
|
|
36
36
|
return (e) => {
|
|
37
37
|
n += e, r ||= setTimeout(a, i);
|
|
38
38
|
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
let p = `${l}:${u}`, m = i.get(p);
|
|
47
|
-
if (!m) {
|
|
39
|
+
};
|
|
40
|
+
t.backends?.onnx?.wasm && (t.backends.onnx.wasm.numThreads = 1, t.backends.onnx.wasm.proxy = !1);
|
|
41
|
+
var c = async (t, o) => {
|
|
42
|
+
let { task: c, model: l, input: u, options: d = {} } = t;
|
|
43
|
+
if (!r.includes(c)) throw Error(`Invalid or unsupported task: ${c}. Supported tasks are: ${r.join(", ")}`);
|
|
44
|
+
let f = `${c}:${l}`, p = i.get(f);
|
|
45
|
+
if (!p) {
|
|
48
46
|
if (i.size >= a) {
|
|
49
47
|
let e = i.keys().next().value;
|
|
50
48
|
i.delete(e);
|
|
51
49
|
}
|
|
52
50
|
let e = {
|
|
53
|
-
dtype:
|
|
54
|
-
device:
|
|
51
|
+
dtype: d.dtype ?? "q4f16",
|
|
52
|
+
device: d.device
|
|
55
53
|
}, t = performance.now();
|
|
56
|
-
console.log(`[flaxia-node] ai-inference: loading pipeline task=${
|
|
54
|
+
console.log(`[flaxia-node] ai-inference: loading pipeline task=${c} model=${l} dtype=${e.dtype} device=${e.device ?? "wasm"}`);
|
|
57
55
|
try {
|
|
58
|
-
|
|
56
|
+
p = await n(c, l, e);
|
|
59
57
|
} catch (t) {
|
|
60
|
-
if (
|
|
61
|
-
else throw console.error(`[flaxia-node] ai-inference: pipeline load FAILED task=${
|
|
58
|
+
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);
|
|
59
|
+
else throw console.error(`[flaxia-node] ai-inference: pipeline load FAILED task=${c} model=${l} error=${t instanceof Error ? t.message : String(t)}`), t;
|
|
62
60
|
}
|
|
63
|
-
console.log(`[flaxia-node] ai-inference: pipeline ready task=${
|
|
61
|
+
console.log(`[flaxia-node] ai-inference: pipeline ready task=${c} model=${l} loadMs=${Math.round(performance.now() - t)}`), i.set(f, p);
|
|
64
62
|
}
|
|
65
|
-
let
|
|
66
|
-
max_new_tokens:
|
|
67
|
-
do_sample:
|
|
63
|
+
let m = {
|
|
64
|
+
max_new_tokens: d.max_new_tokens ?? 128,
|
|
65
|
+
do_sample: d.do_sample ?? !1
|
|
68
66
|
};
|
|
69
|
-
|
|
67
|
+
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), o && p.tokenizer && (m.streamer = new e(p.tokenizer, {
|
|
70
68
|
skip_prompt: !0,
|
|
71
69
|
skip_special_tokens: !0,
|
|
72
|
-
callback_function: s(
|
|
70
|
+
callback_function: s(o, d)
|
|
73
71
|
}));
|
|
74
|
-
let
|
|
75
|
-
return console.log(`[flaxia-node] ai-inference: done task=${
|
|
72
|
+
let h = performance.now(), g = await p(u, m);
|
|
73
|
+
return console.log(`[flaxia-node] ai-inference: done task=${c} model=${l} execMs=${Math.round(performance.now() - h)} inputLen=${String(u).length}`), { output: g };
|
|
76
74
|
};
|
|
77
75
|
//#endregion
|
|
78
76
|
export { c as handleAiInference, o as releaseCache };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/executor/memoryProbe.ts
|
|
2
|
+
var e = 2 * 1024 ** 3, t = 65536, n = 16 * 1024 * 1024;
|
|
3
|
+
function r(r = e, i = n) {
|
|
4
|
+
let a;
|
|
5
|
+
try {
|
|
6
|
+
a = new WebAssembly.Memory({ initial: 0 });
|
|
7
|
+
} catch {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
let o = 0;
|
|
11
|
+
for (; o < r;) {
|
|
12
|
+
let e = r - o, n = Math.ceil(Math.min(i, e) / t);
|
|
13
|
+
try {
|
|
14
|
+
a.grow(n);
|
|
15
|
+
} catch {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
let s = new Uint8Array(a.buffer);
|
|
19
|
+
for (let e = 0; e < n; e++) s[o + e * t] = 0;
|
|
20
|
+
o += n * t;
|
|
21
|
+
}
|
|
22
|
+
return o;
|
|
23
|
+
}
|
|
24
|
+
function i() {
|
|
25
|
+
return r() >= e;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { i as n, r, e as t };
|
package/dist/assets/nudenet.js
CHANGED
|
@@ -13947,7 +13947,7 @@ var yd = 320, bd = "1.26.0", xd = "https://huggingface.co/deepghs/nudenet_onnx/r
|
|
|
13947
13947
|
"BUTTOCKS_COVERED"
|
|
13948
13948
|
], wd = !1;
|
|
13949
13949
|
function Td() {
|
|
13950
|
-
wd ||= (S.wasm.wasmPaths = `https://cdn.jsdelivr.net/npm/onnxruntime-web@${bd}/dist/`, !0);
|
|
13950
|
+
wd ||= (S.wasm.wasmPaths = `https://cdn.jsdelivr.net/npm/onnxruntime-web@${bd}/dist/`, S.wasm.numThreads = 1, S.wasm.proxy = !1, !0);
|
|
13951
13951
|
}
|
|
13952
13952
|
var Ed = /* @__PURE__ */ new Map();
|
|
13953
13953
|
function Dd(e) {
|
|
@@ -7,7 +7,8 @@ async function n(t) {
|
|
|
7
7
|
if (!e) {
|
|
8
8
|
let t = performance.now();
|
|
9
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");
|
|
10
|
+
let { pipeline: n, env: r } = await import("./transformers.web.js");
|
|
11
|
+
r?.backends?.onnx?.wasm && (r.backends.onnx.wasm.numThreads = 1, r.backends.onnx.wasm.proxy = !1);
|
|
11
12
|
try {
|
|
12
13
|
e = await n("feature-extraction", "onnx-community/Qwen3-Embedding-0.6B-ONNX", { device: "wasm" });
|
|
13
14
|
} catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SignalingClient.d.ts","sourceRoot":"","sources":["../../src/client/SignalingClient.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SignalingClient.d.ts","sourceRoot":"","sources":["../../src/client/SignalingClient.ts"],"names":[],"mappings":"AAcA,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;AA2RD,eAAO,MAAM,cAAc,GAAI,QAAQ,UAAU,SAsBhD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignalingClient.incapable.test.d.ts","sourceRoot":"","sources":["../../../src/client/__tests__/SignalingClient.incapable.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
declare function safeGet(key: string): string | null;
|
|
2
|
+
declare function safeSet(key: string, value: string): void;
|
|
3
|
+
declare function safeRemove(key: string): void;
|
|
1
4
|
export declare const hasConsent: () => boolean;
|
|
2
5
|
export declare const saveConsent: () => void;
|
|
6
|
+
export declare const safeLocalStorageGet: typeof safeGet;
|
|
7
|
+
export declare const safeLocalStorageSet: typeof safeSet;
|
|
8
|
+
export declare const safeLocalStorageRemove: typeof safeRemove;
|
|
9
|
+
/**
|
|
10
|
+
* Returns a UUID, falling back to a random v4 when `crypto.randomUUID` is
|
|
11
|
+
* unavailable (older browsers, or non-secure contexts where `crypto.randomUUID`
|
|
12
|
+
* is undefined on mobile Chrome). Never throws.
|
|
13
|
+
*/
|
|
14
|
+
export declare const safeRandomUUID: () => string;
|
|
15
|
+
export {};
|
|
3
16
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/consent/storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/consent/storage.ts"],"names":[],"mappings":"AAWA,iBAAS,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3C;AAED,iBAAS,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAMjD;AAED,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAMrC;AAED,eAAO,MAAM,UAAU,QAAO,OAgB7B,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,IAG9B,CAAC;AAEF,eAAO,MAAM,mBAAmB,gBAAU,CAAC;AAC3C,eAAO,MAAM,mBAAmB,gBAAU,CAAC;AAC3C,eAAO,MAAM,sBAAsB,mBAAa,CAAC;AAEjD;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAAO,MAajC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoryProbe.test.d.ts","sourceRoot":"","sources":["../../../src/executor/__tests__/memoryProbe.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const HEAVY_WORKLOAD_WASM_MEMORY_BYTES: number;
|
|
2
|
+
export declare function probeMaxWasmMemoryBytes(targetBytes?: number, chunkBytes?: number): number;
|
|
3
|
+
export declare function hasEnoughWasmMemoryForHeavy(): boolean;
|
|
4
|
+
//# sourceMappingURL=memoryProbe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoryProbe.d.ts","sourceRoot":"","sources":["../../src/executor/memoryProbe.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,gCAAgC,QAAgB,CAAC;AAI9D,wBAAgB,uBAAuB,CACrC,WAAW,GAAE,MAAyC,EACtD,UAAU,GAAE,MAA0B,GACrC,MAAM,CA4BR;AAED,wBAAgB,2BAA2B,IAAI,OAAO,CAErD"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { r as e, t } from "./assets/memoryProbe.js";
|
|
1
2
|
//#region src/consent/ConsentUI.ts
|
|
2
|
-
var
|
|
3
|
+
var n = class {
|
|
3
4
|
constructor(e, t, n) {
|
|
4
5
|
this.shadow = e.attachShadow({ mode: "open" }), this.render(t, n);
|
|
5
6
|
}
|
|
@@ -39,17 +40,47 @@ var e = class {
|
|
|
39
40
|
c.remove(), t();
|
|
40
41
|
}), this.shadow.appendChild(s), this.shadow.appendChild(c);
|
|
41
42
|
}
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
}, r = "flaxia_consent_granted", i = "flaxia_consent_expiry", a = 720 * 60 * 60 * 1e3, o = /* @__PURE__ */ new Map();
|
|
44
|
+
function s(e) {
|
|
45
|
+
try {
|
|
46
|
+
return localStorage.getItem(e);
|
|
47
|
+
} catch {
|
|
48
|
+
return o.get(e) ?? null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function c(e, t) {
|
|
52
|
+
try {
|
|
53
|
+
localStorage.setItem(e, t);
|
|
54
|
+
} catch {
|
|
55
|
+
o.set(e, t);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function l(e) {
|
|
59
|
+
try {
|
|
60
|
+
localStorage.removeItem(e);
|
|
61
|
+
} catch {
|
|
62
|
+
o.delete(e);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
var u = () => {
|
|
66
|
+
if (s(r) !== "true") return !1;
|
|
67
|
+
let e = s(i);
|
|
45
68
|
if (e) {
|
|
46
|
-
let
|
|
47
|
-
if (Date.now() >
|
|
69
|
+
let t = parseInt(e, 10);
|
|
70
|
+
if (!Number.isFinite(t) || Date.now() > t) return l(r), l(i), !1;
|
|
48
71
|
}
|
|
49
72
|
return !0;
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
},
|
|
73
|
+
}, d = () => {
|
|
74
|
+
c(r, "true"), c(i, String(Date.now() + a));
|
|
75
|
+
}, f = s, p = c, m = () => {
|
|
76
|
+
try {
|
|
77
|
+
if (typeof crypto < "u" && typeof crypto.randomUUID == "function") return crypto.randomUUID();
|
|
78
|
+
} catch {}
|
|
79
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (e) => {
|
|
80
|
+
let t = Math.random() * 16 | 0;
|
|
81
|
+
return (e === "x" ? t : t & 3 | 8).toString(16);
|
|
82
|
+
});
|
|
83
|
+
}, h = (...e) => console.log("[flaxia-node]", ...e), g = class {
|
|
53
84
|
constructor(e, t = 3e5) {
|
|
54
85
|
this.worker = null, this.queue = [], this.active = null, this._lastCpuLoad = 0, this.workerUrl = e || "/worker.js", this.defaultTimeoutMs = t, this.initWorker();
|
|
55
86
|
}
|
|
@@ -63,66 +94,66 @@ var e = class {
|
|
|
63
94
|
}, this.worker = e;
|
|
64
95
|
}
|
|
65
96
|
run(e, t, n, r, i, a) {
|
|
66
|
-
return new Promise((
|
|
97
|
+
return new Promise((o, s) => {
|
|
67
98
|
if (!this.worker) {
|
|
68
|
-
|
|
99
|
+
s(/* @__PURE__ */ Error("Worker not available"));
|
|
69
100
|
return;
|
|
70
101
|
}
|
|
71
|
-
let
|
|
72
|
-
this.active ? (
|
|
102
|
+
let c = () => this.execute(e, t, n, r, i, a, o, s);
|
|
103
|
+
this.active ? (h(`task queued id=${e} workload=${t} (active task running)`), this.queue.push(c)) : c();
|
|
73
104
|
});
|
|
74
105
|
}
|
|
75
|
-
execute(e, t, n, r, i, a,
|
|
76
|
-
let
|
|
77
|
-
if (!
|
|
78
|
-
|
|
106
|
+
execute(e, t, n, r, i, a, o, s) {
|
|
107
|
+
let c = this.worker;
|
|
108
|
+
if (!c) {
|
|
109
|
+
s(/* @__PURE__ */ Error("Worker not available")), this.dequeue();
|
|
79
110
|
return;
|
|
80
111
|
}
|
|
81
|
-
let
|
|
82
|
-
|
|
83
|
-
let
|
|
84
|
-
if (
|
|
85
|
-
|
|
112
|
+
let l = r ?? this.defaultTimeoutMs, u = !1, d = performance.now();
|
|
113
|
+
h(`task start id=${e} workload=${t} timeoutMs=${l}`);
|
|
114
|
+
let f = (e) => {
|
|
115
|
+
if (u) return;
|
|
116
|
+
u = !0;
|
|
86
117
|
let t = this.active;
|
|
87
118
|
t && (clearTimeout(t.timer), t.removeListener()), this.active = null, e(), this.dequeue();
|
|
88
|
-
},
|
|
89
|
-
let { id: r, type: a, result:
|
|
119
|
+
}, p = (n) => {
|
|
120
|
+
let { id: r, type: a, result: c, error: l, token: u, cpuLoad: p } = n.data;
|
|
90
121
|
if (r === e) {
|
|
91
122
|
if (a === "token") {
|
|
92
|
-
i?.(
|
|
123
|
+
i?.(u);
|
|
93
124
|
return;
|
|
94
125
|
}
|
|
95
126
|
if (a === "heartbeat") {
|
|
96
|
-
typeof
|
|
127
|
+
typeof p == "number" && Number.isFinite(p) && (this._lastCpuLoad = Math.min(1, Math.max(0, p)));
|
|
97
128
|
return;
|
|
98
129
|
}
|
|
99
|
-
a === "done" ? (
|
|
130
|
+
a === "done" ? (h(`task done id=${e} workload=${t} durationMs=${Math.round(performance.now() - d)}`), f(() => o(c))) : a === "error" ? (h(`task failed id=${e} workload=${t} error=${l}`), f(() => s(Error(l)))) : (h(`task unknown-message id=${e} type=${String(a)}`), f(() => s(/* @__PURE__ */ Error(`Unknown message type: ${String(a)}`))));
|
|
100
131
|
}
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
},
|
|
132
|
+
}, m = () => c.removeEventListener("message", p), g = setTimeout(() => {
|
|
133
|
+
h(`task timeout id=${e} workload=${t} (worker terminated after ${l}ms)`), this.cleanupWorker(), f(() => s(/* @__PURE__ */ Error("TIMEOUT")));
|
|
134
|
+
}, l);
|
|
104
135
|
this.active = {
|
|
105
136
|
id: e,
|
|
106
|
-
resolve:
|
|
107
|
-
reject:
|
|
137
|
+
resolve: o,
|
|
138
|
+
reject: s,
|
|
108
139
|
timer: g,
|
|
109
|
-
worker:
|
|
110
|
-
removeListener:
|
|
111
|
-
},
|
|
140
|
+
worker: c,
|
|
141
|
+
removeListener: m
|
|
142
|
+
}, c.addEventListener("message", p);
|
|
112
143
|
try {
|
|
113
|
-
|
|
144
|
+
c.postMessage({
|
|
114
145
|
id: e,
|
|
115
146
|
workload: t,
|
|
116
147
|
payload: n,
|
|
117
|
-
timeoutMs:
|
|
148
|
+
timeoutMs: l,
|
|
118
149
|
config: a
|
|
119
150
|
});
|
|
120
151
|
} catch (e) {
|
|
121
|
-
|
|
152
|
+
f(() => s(e instanceof Error ? e : Error(String(e))));
|
|
122
153
|
}
|
|
123
154
|
}
|
|
124
155
|
handleWorkerError(e) {
|
|
125
|
-
|
|
156
|
+
h(`worker error error=${e.message}`);
|
|
126
157
|
let t = this.active;
|
|
127
158
|
this.cleanupWorker(), t && (clearTimeout(t.timer), this.active = null, t.reject(e), this.dequeue());
|
|
128
159
|
}
|
|
@@ -142,13 +173,13 @@ var e = class {
|
|
|
142
173
|
get lastCpuLoad() {
|
|
143
174
|
return this._lastCpuLoad;
|
|
144
175
|
}
|
|
145
|
-
},
|
|
176
|
+
}, _ = (...e) => console.log("[flaxia-node]", ...e), v = (...e) => console.error("[flaxia-node]", ...e), y = "flaxia_node_id", b = "flaxia_node_token", x = class {
|
|
146
177
|
constructor(e, t, n) {
|
|
147
178
|
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
179
|
}
|
|
149
180
|
async connect() {
|
|
150
181
|
if (this.destroyed) return;
|
|
151
|
-
if (
|
|
182
|
+
if (_(`connect nodeId=${this.nodeId}`), this.ws) {
|
|
152
183
|
let e = this.ws;
|
|
153
184
|
e.onclose = null;
|
|
154
185
|
try {
|
|
@@ -159,14 +190,14 @@ var e = class {
|
|
|
159
190
|
this.setupVisibilityHandler();
|
|
160
191
|
let e = await this.obtainToken();
|
|
161
192
|
if (!e) {
|
|
162
|
-
|
|
193
|
+
v("token acquisition failed; scheduling reconnect"), this.scheduleReconnect();
|
|
163
194
|
return;
|
|
164
195
|
}
|
|
165
196
|
let t = this.config.orchestratorUrl.replace(/\/+$/, "").replace(/^http/, "ws"), n = new URL(`${t}/crowd/signal`);
|
|
166
197
|
n.searchParams.set("token", e.token);
|
|
167
198
|
let r = new WebSocket(n.toString());
|
|
168
199
|
this.ws = r, r.onopen = () => {
|
|
169
|
-
this.reconnectAttempts = 0,
|
|
200
|
+
this.reconnectAttempts = 0, _(`signal connected ${n.toString()}`);
|
|
170
201
|
}, r.onmessage = async (e) => {
|
|
171
202
|
let t;
|
|
172
203
|
try {
|
|
@@ -183,12 +214,12 @@ var e = class {
|
|
|
183
214
|
}
|
|
184
215
|
if (t.type === "task") {
|
|
185
216
|
let e = t;
|
|
186
|
-
|
|
217
|
+
_(`task received taskId=${e.taskId} workload=${e.workload} timeoutMs=${e.timeoutMs ?? "default"}`);
|
|
187
218
|
try {
|
|
188
219
|
await this.handleTask(e);
|
|
189
220
|
} catch (n) {
|
|
190
221
|
let r = n instanceof Error ? n.message : String(n);
|
|
191
|
-
|
|
222
|
+
v(`task failed taskId=${e.taskId} workload=${e.workload} error=${r}`), this.send({
|
|
192
223
|
type: "error",
|
|
193
224
|
taskId: String(t.taskId ?? ""),
|
|
194
225
|
error: r
|
|
@@ -196,7 +227,7 @@ var e = class {
|
|
|
196
227
|
}
|
|
197
228
|
}
|
|
198
229
|
}, r.onclose = () => {
|
|
199
|
-
r.onclose = null, this.ws === r && (this.ws = null, !this.destroyed && (
|
|
230
|
+
r.onclose = null, this.ws === r && (this.ws = null, !this.destroyed && (_(`signal disconnected; scheduling reconnect attempt=${this.reconnectAttempts + 1}`), this.scheduleReconnect()));
|
|
200
231
|
};
|
|
201
232
|
}
|
|
202
233
|
scheduleReconnect() {
|
|
@@ -206,15 +237,21 @@ var e = class {
|
|
|
206
237
|
}, e);
|
|
207
238
|
}
|
|
208
239
|
disconnect() {
|
|
209
|
-
|
|
240
|
+
_(`disconnect nodeId=${this.nodeId}`), this.destroyed = !0, this.suspended = !1, this.removeVisibilityHandler();
|
|
210
241
|
try {
|
|
211
242
|
this.ws?.close();
|
|
212
243
|
} catch {}
|
|
213
244
|
this.ws = null;
|
|
245
|
+
try {
|
|
246
|
+
delete window[C];
|
|
247
|
+
} catch {}
|
|
248
|
+
try {
|
|
249
|
+
this.workerPool.terminate();
|
|
250
|
+
} catch {}
|
|
214
251
|
}
|
|
215
252
|
suspend() {
|
|
216
253
|
if (!(this.suspended || this.destroyed)) {
|
|
217
|
-
if (
|
|
254
|
+
if (_("suspended (visibility or manual)"), this.suspended = !0, this.ws) {
|
|
218
255
|
let e = this.ws;
|
|
219
256
|
e.onclose = null;
|
|
220
257
|
try {
|
|
@@ -226,35 +263,38 @@ var e = class {
|
|
|
226
263
|
}
|
|
227
264
|
}
|
|
228
265
|
resume() {
|
|
229
|
-
!this.suspended || this.destroyed || (
|
|
266
|
+
!this.suspended || this.destroyed || (_("resumed"), this.suspended = !1, this.workerPool.resume(), this.connect());
|
|
230
267
|
}
|
|
231
268
|
async obtainToken() {
|
|
232
269
|
try {
|
|
233
|
-
let
|
|
234
|
-
if (
|
|
235
|
-
let
|
|
236
|
-
if (
|
|
270
|
+
let n = f(b);
|
|
271
|
+
if (n) try {
|
|
272
|
+
let e = JSON.parse(n);
|
|
273
|
+
if (e.token && e.nodeId && e.expiresAt > Date.now() + 6e4) return _(`token cached nodeId=${e.nodeId} expiresIn=${Math.round((e.expiresAt - Date.now()) / 1e3)}s`), e;
|
|
237
274
|
} catch {}
|
|
238
|
-
let t = this.config.
|
|
275
|
+
let r = e(), i = r >= t, a = i ? this.config.capabilities ?? ["ai-inference", "image-process"] : [];
|
|
276
|
+
_(`register capability probe capable=${i} wasmMemoryBytes=${r} capabilities=${JSON.stringify(a)}`);
|
|
277
|
+
let o = this.config.orchestratorUrl.replace(/\/+$/, ""), s = await fetch(`${o}/crowd/nodes/register`, {
|
|
239
278
|
method: "POST",
|
|
240
279
|
headers: { "Content-Type": "application/json" },
|
|
241
280
|
body: JSON.stringify({
|
|
242
281
|
siteId: this.config.siteId,
|
|
243
282
|
nodeId: this.nodeId,
|
|
244
|
-
capabilities:
|
|
283
|
+
capabilities: a,
|
|
284
|
+
wasmMemoryBytes: e(),
|
|
245
285
|
deviceMemory: typeof navigator.deviceMemory == "number" ? navigator.deviceMemory : null
|
|
246
286
|
})
|
|
247
287
|
});
|
|
248
|
-
if (!
|
|
249
|
-
let
|
|
250
|
-
if (!
|
|
251
|
-
|
|
288
|
+
if (!s.ok) return v(`node register failed HTTP ${s.status} (${o}/crowd/nodes/register)`), null;
|
|
289
|
+
let c = await s.json();
|
|
290
|
+
if (!c.token) return v("node register returned no token"), null;
|
|
291
|
+
_(`node registered nodeId=${this.nodeId} expiresIn=${Math.round((c.expiresAt - Date.now()) / 1e3)}s`);
|
|
252
292
|
try {
|
|
253
|
-
|
|
293
|
+
p(b, JSON.stringify(c));
|
|
254
294
|
} catch {}
|
|
255
|
-
return
|
|
295
|
+
return c;
|
|
256
296
|
} catch (e) {
|
|
257
|
-
return
|
|
297
|
+
return v("node register threw", e instanceof Error ? e.message : e), null;
|
|
258
298
|
}
|
|
259
299
|
}
|
|
260
300
|
send(e) {
|
|
@@ -276,7 +316,7 @@ var e = class {
|
|
|
276
316
|
type: "result",
|
|
277
317
|
taskId: e.taskId,
|
|
278
318
|
payload: r
|
|
279
|
-
}),
|
|
319
|
+
}), _(`task result sent taskId=${e.taskId} workload=${e.workload} durationMs=${Math.round(performance.now() - t)}`);
|
|
280
320
|
} finally {
|
|
281
321
|
this.inflightTasks.delete(e.taskId);
|
|
282
322
|
}
|
|
@@ -289,22 +329,23 @@ var e = class {
|
|
|
289
329
|
removeVisibilityHandler() {
|
|
290
330
|
this.visibilityHandler &&= (document.removeEventListener("visibilitychange", this.visibilityHandler), null);
|
|
291
331
|
}
|
|
292
|
-
},
|
|
293
|
-
let t = window[
|
|
332
|
+
}, S = "__flaxia_node_signal_client", C = "__flaxia_node_init_started", w = (e) => {
|
|
333
|
+
let t = window[S];
|
|
294
334
|
t && t.disconnect();
|
|
295
|
-
let n = new URL("./worker.js", "" + import.meta.url).href, r = new
|
|
296
|
-
i || (i =
|
|
297
|
-
let a = new
|
|
298
|
-
window[
|
|
299
|
-
},
|
|
300
|
-
if (
|
|
301
|
-
|
|
335
|
+
let n = new URL("./worker.js", "" + import.meta.url).href, r = new g(n), i = f(y);
|
|
336
|
+
i || (i = m(), p(y, i));
|
|
337
|
+
let a = new x(e, r, i);
|
|
338
|
+
window[S] = a, a.connect();
|
|
339
|
+
}, T = (e) => {
|
|
340
|
+
if (window[C]) return;
|
|
341
|
+
if (window[C] = !0, u()) {
|
|
342
|
+
w(e);
|
|
302
343
|
return;
|
|
303
344
|
}
|
|
304
|
-
let
|
|
305
|
-
|
|
306
|
-
|
|
345
|
+
let t = document.createElement("div");
|
|
346
|
+
t.id = "flaxia-consent-container", document.body.appendChild(t), new n(t, e.consent, () => {
|
|
347
|
+
d(), t.remove(), w(e);
|
|
307
348
|
});
|
|
308
349
|
};
|
|
309
350
|
//#endregion
|
|
310
|
-
export {
|
|
351
|
+
export { T as initFlaxiaNode };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.worker.capable.test.d.ts","sourceRoot":"","sources":["../../../src/worker/__tests__/main.worker.capable.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.worker.incapable.test.d.ts","sourceRoot":"","sources":["../../../src/worker/__tests__/main.worker.incapable.test.ts"],"names":[],"mappings":""}
|
package/dist/worker.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { n as e, r as t, t as n } from "./assets/memoryProbe.js";
|
|
1
2
|
//#region src/executor/throttle.ts
|
|
2
|
-
function
|
|
3
|
+
function r(e) {
|
|
3
4
|
return new Promise((t) => setTimeout(t, e));
|
|
4
5
|
}
|
|
5
|
-
var
|
|
6
|
+
var i = 3e4, a = 3e4, o = class {
|
|
6
7
|
constructor(e = .15) {
|
|
7
8
|
this.windowStart = performance.now(), this.windowBusyMs = 0, this.lastLoad = 0, this.maxLoad = Math.max(.05, Math.min(.3, e));
|
|
8
9
|
}
|
|
9
10
|
markTaskComplete(e) {
|
|
10
|
-
let
|
|
11
|
-
|
|
11
|
+
let t = performance.now();
|
|
12
|
+
t - this.windowStart > i && (this.windowStart = t, this.windowBusyMs = 0), this.windowBusyMs += Math.max(0, e), this.lastLoad = this.estimate();
|
|
12
13
|
}
|
|
13
14
|
estimate() {
|
|
14
15
|
let e = performance.now() - this.windowStart;
|
|
@@ -17,9 +18,9 @@ var t = 3e4, n = 3e4, r = class {
|
|
|
17
18
|
async shouldPause() {
|
|
18
19
|
return this.estimate() > this.maxLoad;
|
|
19
20
|
}
|
|
20
|
-
async waitForSlot(
|
|
21
|
-
let
|
|
22
|
-
for (; await this.shouldPause() && !(performance.now() -
|
|
21
|
+
async waitForSlot(e = a) {
|
|
22
|
+
let t = performance.now();
|
|
23
|
+
for (; await this.shouldPause() && !(performance.now() - t > e);) await r(500);
|
|
23
24
|
}
|
|
24
25
|
get lastMeasuredLoad() {
|
|
25
26
|
return this.lastLoad;
|
|
@@ -27,69 +28,67 @@ var t = 3e4, n = 3e4, r = class {
|
|
|
27
28
|
get maxLoadValue() {
|
|
28
29
|
return this.maxLoad;
|
|
29
30
|
}
|
|
30
|
-
},
|
|
31
|
+
}, s = null, c = new Set([
|
|
31
32
|
"ai-inference",
|
|
32
33
|
"vector-embed",
|
|
33
34
|
"vector-query",
|
|
34
35
|
"nudenet",
|
|
35
36
|
"image-process",
|
|
36
37
|
"container"
|
|
37
|
-
]),
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return
|
|
38
|
+
]), l = 6e4, u = t(), d = u >= n;
|
|
39
|
+
console.log(`[flaxia-node:worker] startup memory probe wasmMemoryBytes=${u} capable=${d}`);
|
|
40
|
+
function f() {
|
|
41
|
+
return e();
|
|
41
42
|
}
|
|
42
|
-
var
|
|
43
|
-
function
|
|
44
|
-
for (let e of
|
|
43
|
+
var p = /* @__PURE__ */ new Map(), m = null;
|
|
44
|
+
function h() {
|
|
45
|
+
for (let e of p.values()) try {
|
|
45
46
|
e();
|
|
46
47
|
} catch {}
|
|
47
|
-
|
|
48
|
+
p.clear();
|
|
48
49
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
},
|
|
50
|
+
function g() {
|
|
51
|
+
m && clearTimeout(m), m = setTimeout(() => {
|
|
52
|
+
m = null, h();
|
|
53
|
+
}, l);
|
|
53
54
|
}
|
|
54
|
-
async function
|
|
55
|
+
async function _(e, t, n) {
|
|
55
56
|
switch (e) {
|
|
56
57
|
case "ai-inference":
|
|
57
58
|
let r = await import("./assets/ai-inference.js");
|
|
58
|
-
return
|
|
59
|
+
return p.set(e, r.releaseCache), await r.handleAiInference(t, n);
|
|
59
60
|
case "image-process": return await (await import("./assets/image-process.js")).handleImageProcess(t);
|
|
60
61
|
case "container": return await (await import("./assets/container.js")).handleContainer(t);
|
|
61
62
|
case "vector-embed":
|
|
62
63
|
let i = await import("./assets/vector-embed.js");
|
|
63
|
-
return
|
|
64
|
+
return p.set(e, i.releaseCache), await i.handleVectorEmbed(t);
|
|
64
65
|
case "vector-store":
|
|
65
66
|
let a = await import("./assets/vector-store.js");
|
|
66
|
-
return
|
|
67
|
+
return p.set(e, a.releaseCache), await a.handleVectorStore(t);
|
|
67
68
|
case "vector-query":
|
|
68
69
|
let o = await import("./assets/vector-query.js");
|
|
69
|
-
return
|
|
70
|
+
return p.set(e, o.releaseCache), await o.handleVectorQuery(t);
|
|
70
71
|
case "nudenet":
|
|
71
72
|
let s = await import("./assets/nudenet.js");
|
|
72
|
-
return
|
|
73
|
+
return p.set(e, s.releaseCache), await s.handleNudeNet(t);
|
|
73
74
|
default: throw Error(`Unknown workload type: ${e}`);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
self.onmessage = async (e) => {
|
|
77
|
-
let { id: t, workload:
|
|
78
|
+
let { id: t, workload: r, payload: i, config: a } = e.data, l = performance.now();
|
|
78
79
|
try {
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
await i.waitForSlot();
|
|
80
|
+
if (s ||= new o(a?.maxCpuLoad), console.log(`[flaxia-node:worker] task start id=${t} workload=${r}`), !d) throw Error(`node incapable: insufficient WASM memory (${u} bytes < ${n}); rejecting all tasks`);
|
|
81
|
+
if (c.has(r) && !f()) throw Error(`${r}: insufficient WASM memory (${u} bytes < ${n})`);
|
|
82
|
+
await s.waitForSlot();
|
|
84
83
|
let e = setInterval(() => {
|
|
85
84
|
self.postMessage({
|
|
86
85
|
id: t,
|
|
87
86
|
type: "heartbeat",
|
|
88
|
-
cpuLoad:
|
|
87
|
+
cpuLoad: s?.lastMeasuredLoad ?? 0
|
|
89
88
|
});
|
|
90
|
-
}, 1e4),
|
|
89
|
+
}, 1e4), p = performance.now();
|
|
91
90
|
try {
|
|
92
|
-
let e = await
|
|
91
|
+
let e = await _(r, i, (e) => {
|
|
93
92
|
self.postMessage({
|
|
94
93
|
id: t,
|
|
95
94
|
type: "token",
|
|
@@ -100,16 +99,16 @@ self.onmessage = async (e) => {
|
|
|
100
99
|
id: t,
|
|
101
100
|
type: "done",
|
|
102
101
|
result: e
|
|
103
|
-
}), console.log(`[flaxia-node:worker] task done id=${t} workload=${
|
|
102
|
+
}), console.log(`[flaxia-node:worker] task done id=${t} workload=${r} durationMs=${Math.round(performance.now() - l)}`);
|
|
104
103
|
} finally {
|
|
105
|
-
clearInterval(e),
|
|
104
|
+
clearInterval(e), s.markTaskComplete(performance.now() - p), g();
|
|
106
105
|
}
|
|
107
106
|
} catch (e) {
|
|
108
|
-
let
|
|
109
|
-
console.error(`[flaxia-node:worker] task error id=${t} workload=${
|
|
107
|
+
let n = e instanceof Error ? e.message : String(e);
|
|
108
|
+
console.error(`[flaxia-node:worker] task error id=${t} workload=${r} error=${n}`), self.postMessage({
|
|
110
109
|
id: t,
|
|
111
110
|
type: "error",
|
|
112
|
-
error:
|
|
111
|
+
error: n
|
|
113
112
|
});
|
|
114
113
|
}
|
|
115
114
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm-threads.test.d.ts","sourceRoot":"","sources":["../../../src/workloads/__tests__/wasm-threads.test.ts"],"names":[],"mappings":"AAuBA,OAAO,iBAAiB,CAAC"}
|
|
@@ -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;AAe7F;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAO,IAE/B,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;AAuCF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,kBAAkB,EAC3B,UAAU,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,KAChC,OAAO,CAAC,iBAAiB,CAoE3B,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { NudeNetPayload, NudeNetResult } from '@flaxia/sdk';
|
|
2
|
+
export declare function configureOrt(): void;
|
|
2
3
|
export declare const handleNudeNet: (payload: NudeNetPayload) => Promise<NudeNetResult>;
|
|
3
4
|
export declare function releaseCache(): void;
|
|
4
5
|
//# 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;
|
|
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;AAoCnF,wBAAgB,YAAY,IAAI,IAAI,CAUnC;AAuID,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,eAAO,MAAM,YAAY,QAAO,IAE/B,CAAC;AAEF,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,CAiD/F"}
|