@flaxia/node 0.3.7 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +43 -19
  2. package/dist/__tests__/consent-policy.test.d.ts +2 -0
  3. package/dist/__tests__/consent-policy.test.d.ts.map +1 -0
  4. package/dist/assets/VectorStoreEngine.js +140 -85
  5. package/dist/assets/ai-inference.js +336 -40
  6. package/dist/assets/container.js +368 -260
  7. package/dist/assets/egress-guard.js +174 -0
  8. package/dist/assets/image-process.js +184 -19
  9. package/dist/assets/nudenet.js +2 -2
  10. package/dist/assets/webgpuProbe.js +357 -0
  11. package/dist/client/SignalingClient.d.ts +6 -0
  12. package/dist/client/SignalingClient.d.ts.map +1 -1
  13. package/dist/client/__tests__/mobile-lifecycle.test.d.ts +2 -0
  14. package/dist/client/__tests__/mobile-lifecycle.test.d.ts.map +1 -0
  15. package/dist/client/mobile-lifecycle.d.ts +20 -0
  16. package/dist/client/mobile-lifecycle.d.ts.map +1 -0
  17. package/dist/consent/ConsentUI.d.ts +44 -5
  18. package/dist/consent/ConsentUI.d.ts.map +1 -1
  19. package/dist/consent/notice.d.ts +29 -0
  20. package/dist/consent/notice.d.ts.map +1 -0
  21. package/dist/consent/storage.d.ts +91 -7
  22. package/dist/consent/storage.d.ts.map +1 -1
  23. package/dist/executor/WorkerPool.d.ts +42 -2
  24. package/dist/executor/WorkerPool.d.ts.map +1 -1
  25. package/dist/executor/__tests__/WorkerPool.swarm.test.d.ts +13 -0
  26. package/dist/executor/__tests__/WorkerPool.swarm.test.d.ts.map +1 -0
  27. package/dist/executor/__tests__/container-executor.test.d.ts +2 -0
  28. package/dist/executor/__tests__/container-executor.test.d.ts.map +1 -0
  29. package/dist/executor/__tests__/egress-guard.test.d.ts +2 -0
  30. package/dist/executor/__tests__/egress-guard.test.d.ts.map +1 -0
  31. package/dist/executor/__tests__/resourceReporter.test.d.ts +2 -0
  32. package/dist/executor/__tests__/resourceReporter.test.d.ts.map +1 -0
  33. package/dist/executor/__tests__/webgpuProbe.test.d.ts +2 -0
  34. package/dist/executor/__tests__/webgpuProbe.test.d.ts.map +1 -0
  35. package/dist/executor/container-executor.d.ts +49 -1
  36. package/dist/executor/container-executor.d.ts.map +1 -1
  37. package/dist/executor/egress-guard.d.ts +105 -0
  38. package/dist/executor/egress-guard.d.ts.map +1 -0
  39. package/dist/executor/memoryProbe.d.ts +30 -0
  40. package/dist/executor/memoryProbe.d.ts.map +1 -1
  41. package/dist/executor/resourceReporter.d.ts +15 -0
  42. package/dist/executor/resourceReporter.d.ts.map +1 -0
  43. package/dist/executor/throttle.d.ts +62 -4
  44. package/dist/executor/throttle.d.ts.map +1 -1
  45. package/dist/executor/webgpuProbe.d.ts +20 -0
  46. package/dist/executor/webgpuProbe.d.ts.map +1 -0
  47. package/dist/index.d.ts +2 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1423 -235
  50. package/dist/swarm/__tests__/adapter.test.d.ts +2 -0
  51. package/dist/swarm/__tests__/adapter.test.d.ts.map +1 -0
  52. package/dist/swarm/__tests__/controller.test.d.ts +2 -0
  53. package/dist/swarm/__tests__/controller.test.d.ts.map +1 -0
  54. package/dist/swarm/__tests__/defects.test.d.ts +16 -0
  55. package/dist/swarm/__tests__/defects.test.d.ts.map +1 -0
  56. package/dist/swarm/__tests__/hardening.test.d.ts +2 -0
  57. package/dist/swarm/__tests__/hardening.test.d.ts.map +1 -0
  58. package/dist/swarm/__tests__/peer-quality.test.d.ts +2 -0
  59. package/dist/swarm/__tests__/peer-quality.test.d.ts.map +1 -0
  60. package/dist/swarm/__tests__/peer-transport.test.d.ts +2 -0
  61. package/dist/swarm/__tests__/peer-transport.test.d.ts.map +1 -0
  62. package/dist/swarm/__tests__/runtime.test.d.ts +2 -0
  63. package/dist/swarm/__tests__/runtime.test.d.ts.map +1 -0
  64. package/dist/swarm/__tests__/session.test.d.ts +2 -0
  65. package/dist/swarm/__tests__/session.test.d.ts.map +1 -0
  66. package/dist/swarm/adapter.d.ts +115 -0
  67. package/dist/swarm/adapter.d.ts.map +1 -0
  68. package/dist/swarm/controller.d.ts +91 -0
  69. package/dist/swarm/controller.d.ts.map +1 -0
  70. package/dist/swarm/messages.d.ts +41 -0
  71. package/dist/swarm/messages.d.ts.map +1 -0
  72. package/dist/swarm/peer-quality.d.ts +14 -0
  73. package/dist/swarm/peer-quality.d.ts.map +1 -0
  74. package/dist/swarm/peer-transport.d.ts +81 -0
  75. package/dist/swarm/peer-transport.d.ts.map +1 -0
  76. package/dist/swarm/runtime.d.ts +20 -0
  77. package/dist/swarm/runtime.d.ts.map +1 -0
  78. package/dist/swarm/session.d.ts +73 -0
  79. package/dist/swarm/session.d.ts.map +1 -0
  80. package/dist/swarm-engine.js +7496 -0
  81. package/dist/vector-store/HNSWIndex.d.ts +30 -0
  82. package/dist/vector-store/HNSWIndex.d.ts.map +1 -1
  83. package/dist/vector-store/VectorStoreEngine.d.ts +43 -0
  84. package/dist/vector-store/VectorStoreEngine.d.ts.map +1 -1
  85. package/dist/vector-store/__tests__/HNSWIndex.test.d.ts +2 -0
  86. package/dist/vector-store/__tests__/HNSWIndex.test.d.ts.map +1 -0
  87. package/dist/vector-store/__tests__/VectorStoreEngine.test.d.ts +2 -0
  88. package/dist/vector-store/__tests__/VectorStoreEngine.test.d.ts.map +1 -0
  89. package/dist/worker/__tests__/main.worker.abort.test.d.ts +2 -0
  90. package/dist/worker/__tests__/main.worker.abort.test.d.ts.map +1 -0
  91. package/dist/worker/__tests__/main.worker.control.test.d.ts +2 -0
  92. package/dist/worker/__tests__/main.worker.control.test.d.ts.map +1 -0
  93. package/dist/worker.js +766 -67
  94. package/dist/workloads/__tests__/model-pipeline-cache.test.d.ts +2 -0
  95. package/dist/workloads/__tests__/model-pipeline-cache.test.d.ts.map +1 -0
  96. package/dist/workloads/__tests__/nudenet.test.d.ts +2 -0
  97. package/dist/workloads/__tests__/nudenet.test.d.ts.map +1 -0
  98. package/dist/workloads/ai-inference.d.ts +8 -1
  99. package/dist/workloads/ai-inference.d.ts.map +1 -1
  100. package/dist/workloads/ai-model-registry.d.ts +72 -0
  101. package/dist/workloads/ai-model-registry.d.ts.map +1 -0
  102. package/dist/workloads/container.d.ts +1 -1
  103. package/dist/workloads/container.d.ts.map +1 -1
  104. package/dist/workloads/image-process.d.ts +27 -0
  105. package/dist/workloads/image-process.d.ts.map +1 -1
  106. package/dist/workloads/model-pipeline-cache.d.ts +48 -0
  107. package/dist/workloads/model-pipeline-cache.d.ts.map +1 -0
  108. package/dist/workloads/nudenet.d.ts +8 -0
  109. package/dist/workloads/nudenet.d.ts.map +1 -1
  110. package/package.json +3 -2
  111. package/dist/assets/memoryProbe.js +0 -28
  112. package/dist/client/WebRTCPeer.d.ts +0 -8
  113. package/dist/client/WebRTCPeer.d.ts.map +0 -1
package/dist/worker.js CHANGED
@@ -1,36 +1,55 @@
1
- import { n as e, r as t, t as n } from "./assets/memoryProbe.js";
2
- //#region ../sdk/dist/index.js
3
- var r = new Set([
4
- "ai-inference",
5
- "image-process",
6
- "container",
7
- "vector-embed",
8
- "vector-query",
9
- "nudenet"
10
- ]);
11
- //#endregion
1
+ import { M as e, N as t, O as n, a as r, c as i, f as a, h as o, j as s, k as c, l, m as u, o as d, r as f, t as p, u as m, v as h, x as g, y as _ } from "./assets/webgpuProbe.js";
12
2
  //#region src/executor/throttle.ts
13
- function i(e) {
3
+ function v(e) {
14
4
  return new Promise((t) => setTimeout(t, e));
15
5
  }
16
- var a = 3e4, o = 3e4, s = class {
6
+ var y = 3e4, ee = 500, b = class extends Error {
7
+ constructor(e, t, n) {
8
+ super(`device is over its CPU budget (load ${e.toFixed(2)} > max ${t.toFixed(2)}) after waiting ${Math.round(n)}ms; task not started`), this.load = e, this.maxLoad = t, this.waitedMs = n, this.retryable = !0, this.name = "ThrottleBusyError";
9
+ }
10
+ }, te = class {
17
11
  constructor(e = .15) {
18
- this.windowStart = performance.now(), this.windowBusyMs = 0, this.lastLoad = 0, this.maxLoad = Math.max(.05, Math.min(.3, e));
12
+ this.windowStart = performance.now(), this.windowBusyMs = 0, this.lastLoad = 0, this.dutyStartedAt = null, this.maxLoad = Math.max(.05, Math.min(.3, e));
19
13
  }
20
14
  markTaskComplete(e) {
21
- let t = performance.now();
22
- t - this.windowStart > a && (this.windowStart = t, this.windowBusyMs = 0), this.windowBusyMs += Math.max(0, e), this.lastLoad = this.estimate();
15
+ this.estimate(this.windowBusyMs + Math.max(0, e)), this.resetDutyCycle();
16
+ }
17
+ beginWork() {
18
+ this.dutyStartedAt = performance.now();
23
19
  }
24
- estimate() {
25
- let e = performance.now() - this.windowStart;
26
- return e <= 0 ? 0 : Math.min(1, Math.max(0, this.windowBusyMs / e));
20
+ resetDutyCycle() {
21
+ this.dutyStartedAt = null;
22
+ }
23
+ rollWindow(e) {
24
+ e - this.windowStart > 3e4 && (this.windowStart = e, this.windowBusyMs = 0, this.resetDutyCycle());
25
+ }
26
+ estimate(e) {
27
+ let t = performance.now();
28
+ this.rollWindow(t), this.windowBusyMs = e;
29
+ let n = t - this.windowStart;
30
+ if (n <= 0) return 0;
31
+ let r = e / n;
32
+ return this.lastLoad = Math.min(1, Math.max(0, r)), this.lastLoad;
27
33
  }
28
34
  async shouldPause() {
29
- return this.estimate() > this.maxLoad;
35
+ return this.rollWindow(performance.now()), this.estimate(this.windowBusyMs) > this.maxLoad;
30
36
  }
31
- async waitForSlot(e = o) {
37
+ async waitForSlot(e = y) {
38
+ if (!Number.isFinite(e) || e < 0) throw Error(`waitForSlot: maxWaitMs must be a non-negative number, got ${String(e)}`);
32
39
  let t = performance.now();
33
- for (; await this.shouldPause() && !(performance.now() - t > e);) await i(500);
40
+ for (; await this.shouldPause();) {
41
+ let n = performance.now() - t;
42
+ if (n >= e) throw new b(this.lastLoad, this.maxLoad, n);
43
+ await v(Math.min(ee, Math.max(1, e - n)));
44
+ }
45
+ }
46
+ async yieldIfOverloaded() {
47
+ let e = performance.now();
48
+ this.rollWindow(e), this.dutyStartedAt === null && (this.dutyStartedAt = e);
49
+ let t = Math.max(0, e - this.dutyStartedAt);
50
+ if (t < 200) return 0;
51
+ let n = Math.ceil(t * (1 / this.maxLoad - 1));
52
+ return this.dutyStartedAt = null, n > 0 && await v(n), this.estimate(this.windowBusyMs), n;
34
53
  }
35
54
  get lastMeasuredLoad() {
36
55
  return this.lastLoad;
@@ -38,80 +57,760 @@ var a = 3e4, o = 3e4, s = class {
38
57
  get maxLoadValue() {
39
58
  return this.maxLoad;
40
59
  }
41
- }, c = null, l = 6e4, u = t(), d = u >= n;
42
- console.log(`[flaxia-node:worker] startup memory probe wasmMemoryBytes=${u} capable=${d}`);
43
- function f() {
44
- return e();
60
+ }, x = 4096;
61
+ function ne(e) {
62
+ let t = e.maxSeq;
63
+ return typeof t == "number" && Number.isInteger(t) && t > 0 ? t : x;
64
+ }
65
+ function S(e, t, n) {
66
+ let { pos: r, tokens: i } = e.header, a = ne(t);
67
+ if (!Number.isInteger(i) || i < 1) return {
68
+ kind: "corrupt",
69
+ reason: `carried ${i} token columns`
70
+ };
71
+ if (!Number.isInteger(r) || r < 0 || r + i > a) return {
72
+ kind: "corrupt",
73
+ reason: `position ${r}+${i} is outside the ${a}-token context`
74
+ };
75
+ let o;
76
+ try {
77
+ o = n.unpackHidden(e.payload);
78
+ } catch (e) {
79
+ return {
80
+ kind: "corrupt",
81
+ reason: e instanceof Error ? e.message : String(e)
82
+ };
83
+ }
84
+ let s = t.dim * i;
85
+ if (o.length !== s) return {
86
+ kind: "corrupt",
87
+ reason: `carried ${o.length} values, expected ${s}`
88
+ };
89
+ for (let e = 0; e < o.length; e++) if (!Number.isFinite(o[e])) return {
90
+ kind: "corrupt",
91
+ reason: `carried a non-finite value at index ${e}`
92
+ };
93
+ return {
94
+ kind: "ok",
95
+ hidden: o
96
+ };
97
+ }
98
+ function re(e, t, n, r) {
99
+ let i = _(e);
100
+ return i ? i.header.pos !== t || i.header.requestId !== t ? { kind: "stale" } : S(i, n, r) : {
101
+ kind: "corrupt",
102
+ reason: "malformed frame header"
103
+ };
104
+ }
105
+ async function ie(n) {
106
+ let { engine: r, link: i, semantics: a, promptTokens: o, chainLength: s, maxNewTokens: c } = n;
107
+ if (o.length === 0) throw Error("swarm host requires at least one prompt token");
108
+ r.reset();
109
+ let l = null;
110
+ i.onFrame((e) => {
111
+ if (t(e)) return;
112
+ let n = l;
113
+ if (!n) return;
114
+ let i = re(e, n.pos, r, a);
115
+ if (i.kind !== "stale") {
116
+ if (l = null, i.kind === "corrupt") {
117
+ n.reject(/* @__PURE__ */ Error(`swarm hop failed: ${i.reason}`));
118
+ return;
119
+ }
120
+ n.resolve(i.hidden);
121
+ }
122
+ });
123
+ let u = (e, t) => s <= 1 ? Promise.resolve(e) : new Promise((n, r) => {
124
+ l = {
125
+ pos: t,
126
+ resolve: n,
127
+ reject: r
128
+ }, i.send(h({
129
+ requestId: t,
130
+ pos: t,
131
+ tokens: 1
132
+ }, a.packHidden(e)));
133
+ }), d = async (e, t) => u(await r.embedRun(e, t), t), f = null;
134
+ for (let e = 0; e < o.length; e++) {
135
+ let t = await d(o[e], e);
136
+ e === o.length - 1 && (f = await r.headFromHidden(t));
137
+ }
138
+ if (!f) throw Error("swarm host produced no logits for the prompt");
139
+ let p = [], m = o.length, g = a.argmax(f);
140
+ for (; p.length < c && !(n.eosIds?.has(g) || (p.push(g), await n.onToken?.(g), p.length >= c));) {
141
+ let e = await d(g, m++);
142
+ f = await r.headFromHidden(e), g = a.argmax(f);
143
+ }
144
+ return s > 1 && i.send(e()), { tokens: p };
145
+ }
146
+ function ae(e) {
147
+ let { engine: n, link: r, semantics: i } = e;
148
+ return n.reset(), new Promise((e, a) => {
149
+ let o = Promise.resolve(), s = !1;
150
+ r.onFrame((c) => {
151
+ if (!s) {
152
+ if (t(c)) {
153
+ s = !0, r.send(c), o = o.then(() => e());
154
+ return;
155
+ }
156
+ o = o.then(async () => {
157
+ if (s) return;
158
+ let e = _(c);
159
+ if (!e) throw Error("swarm frame has a malformed frame header");
160
+ let t = S(e, n, i);
161
+ if (t.kind === "corrupt") throw Error(`swarm frame is unusable: ${t.reason}`);
162
+ let a = await n.runHidden(t.hidden, e.header.pos);
163
+ r.send(h({
164
+ requestId: e.header.requestId,
165
+ pos: e.header.pos,
166
+ tokens: e.header.tokens
167
+ }, i.packHidden(a)));
168
+ }).catch((e) => {
169
+ s = !0, a(e instanceof Error ? e : Error(String(e)));
170
+ });
171
+ }
172
+ });
173
+ });
174
+ }
175
+ //#endregion
176
+ //#region src/swarm/controller.ts
177
+ var oe = class {
178
+ constructor(e) {
179
+ this.options = e, this.frameHandler = null, this.engine = null, this.semantics = null, this.sessionId = "", this.model = "", this.chainLength = 1, this.chain = [], this.slice = null, this.hostWarm = void 0, this.prompt = "", this.maxNewTokens = 128, this.sliceLoaded = !1, this.generationStarted = !1, this.settled = !1, this.flowPaused = !1, this.flowWaiters = /* @__PURE__ */ new Set();
180
+ }
181
+ async start() {
182
+ if (this.settled) return;
183
+ let e = this.options.initial;
184
+ try {
185
+ if (e.type === "swarm-init") {
186
+ if (this.sessionId = e.sessionId, this.model = e.model, !Array.isArray(e.members) || e.members.length < 1 || e.members.length > 16) throw Error(`swarm-init has an invalid member count: ${JSON.stringify(e.members?.length)}`);
187
+ this.chainLength = e.members.length, this.prompt = e.prompt, e.maxNewTokens !== void 0 && (this.maxNewTokens = e.maxNewTokens);
188
+ let t = await this.options.runtime.plan(e.members, e.model);
189
+ this.chain = t, this.options.sendControl({
190
+ type: "swarm-plan",
191
+ sessionId: e.sessionId,
192
+ chain: t
193
+ });
194
+ return;
195
+ }
196
+ await this.loadSlice(e);
197
+ } catch (e) {
198
+ this.fail(e);
199
+ }
200
+ }
201
+ async handleControl(e) {
202
+ if (!this.settled && e.sessionId === this.sessionId) try {
203
+ e.type === "swarm-slice" ? await this.loadSlice(e) : e.type === "swarm-start" ? await this.startHost() : e.type === "swarm-error" ? this.fail(Error(e.error || "swarm session aborted by the coordinator")) : e.type === "swarm-flow" && (this.flowPaused = e.paused, this.flowPaused || this.releaseFlowWaiters());
204
+ } catch (e) {
205
+ this.fail(e);
206
+ }
207
+ }
208
+ handleFrame(e) {
209
+ this.settled || this.frameHandler?.(e);
210
+ }
211
+ abort(e) {
212
+ this.fail(Error(e));
213
+ }
214
+ link() {
215
+ return {
216
+ send: (e) => this.options.sendFrame(e),
217
+ onFrame: (e) => {
218
+ this.frameHandler = e;
219
+ }
220
+ };
221
+ }
222
+ validateSlice(e) {
223
+ if (!Number.isInteger(e.chainLength) || e.chainLength < 1 || e.chainLength > 16) throw Error(`swarm slice has an invalid chain length: ${JSON.stringify(e.chainLength)}`);
224
+ if (!Number.isInteger(e.index) || e.index < 0 || e.index >= e.chainLength) throw Error(`swarm slice has an invalid index: ${JSON.stringify(e.index)}`);
225
+ if (e.role !== (e.index === 0 ? "host" : "worker")) throw Error(`swarm slice role ${e.role} does not match index ${e.index}`);
226
+ if (!u(e.slice)) throw Error(`swarm slice is out of bounds: ${JSON.stringify(e.slice)}`);
227
+ let t = e.index === 0;
228
+ if (e.slice.hasEmbed !== t || e.slice.hasHead !== t) throw Error("swarm slice embed/head ownership does not match the host position");
229
+ }
230
+ async loadSlice(e) {
231
+ if (this.settled || this.sliceLoaded) return;
232
+ this.validateSlice(e), this.sessionId = e.sessionId, this.model = e.model, this.chainLength = e.chainLength, this.slice = e.slice;
233
+ let { engine: t, semantics: n, warm: r } = await this.options.runtime.load(e.slice, e.model);
234
+ if (this.settled) {
235
+ t.dispose();
236
+ return;
237
+ }
238
+ this.engine = t, this.semantics = n, this.hostWarm = r, this.sliceLoaded = !0, this.options.sendControl({
239
+ type: "swarm-ready",
240
+ sessionId: e.sessionId
241
+ }), e.role === "worker" && (this.generationStarted = !0, ae({
242
+ engine: t,
243
+ link: this.link(),
244
+ semantics: n
245
+ }).then(() => this.finish(se())).catch((e) => this.fail(e)));
246
+ }
247
+ async startHost() {
248
+ if (this.generationStarted) return;
249
+ let e = this.engine, t = this.semantics;
250
+ if (!e || !t) throw Error("swarm host received start before loading its slice");
251
+ if (!t.encodePrompt || !t.decodeTokens) throw Error("host semantics must provide encodePrompt and decodeTokens");
252
+ let n = this.maxNewTokens;
253
+ if (!Number.isInteger(n) || n < 1) throw Error(`swarm maxNewTokens must be a positive integer, got ${JSON.stringify(n)}`);
254
+ let r = t.encodePrompt(this.prompt), i = e.maxSeq ?? 4096;
255
+ if (r.length + n > i) throw Error(`swarm request needs ${r.length + n} tokens but the model context holds ${i}`);
256
+ this.generationStarted = !0;
257
+ let a = performance.now(), { tokens: o } = await ie({
258
+ chainLength: this.chainLength,
259
+ promptTokens: r,
260
+ maxNewTokens: n,
261
+ engine: e,
262
+ link: this.link(),
263
+ semantics: t,
264
+ eosIds: t.eosIds,
265
+ onToken: async (e) => {
266
+ if (await this.waitForFlow(), this.settled) throw Error("swarm session stopped while generation was paused");
267
+ await this.options.emitToken(t.decodeTokens([e]));
268
+ }
269
+ }), s = t.decodeTokens;
270
+ this.finish({
271
+ output: s(o),
272
+ tokens: o.map((e) => s([e])),
273
+ nodes: this.nodeInfos(),
274
+ durationMs: Math.round(performance.now() - a)
275
+ });
276
+ }
277
+ nodeInfos() {
278
+ return (this.chain.length > 0 ? this.chain.map((e) => ({
279
+ slice: e.slice,
280
+ host: e.role === "host"
281
+ })) : this.slice ? [{
282
+ slice: this.slice,
283
+ host: !0
284
+ }] : []).map((e) => {
285
+ let t = {
286
+ layers: [e.slice.start, e.slice.end],
287
+ host: e.host
288
+ };
289
+ return e.host && this.hostWarm !== void 0 && (t.warm = this.hostWarm), t;
290
+ });
291
+ }
292
+ teardown() {
293
+ this.frameHandler = null;
294
+ let e = this.engine;
295
+ if (this.engine = null, this.semantics = null, e) try {
296
+ e.dispose();
297
+ } catch {}
298
+ }
299
+ finish(e) {
300
+ this.settled || (this.settled = !0, this.releaseFlowWaiters(), this.teardown(), this.options.onDone(e));
301
+ }
302
+ fail(e) {
303
+ this.settled || (this.settled = !0, this.releaseFlowWaiters(), this.teardown(), this.options.onError(e instanceof Error ? e.message : String(e)));
304
+ }
305
+ waitForFlow() {
306
+ return !this.flowPaused || this.settled ? Promise.resolve() : new Promise((e) => this.flowWaiters.add(e));
307
+ }
308
+ releaseFlowWaiters() {
309
+ for (let e of this.flowWaiters) e();
310
+ this.flowWaiters.clear();
311
+ }
312
+ };
313
+ function se() {
314
+ return {
315
+ output: "",
316
+ tokens: [],
317
+ nodes: [],
318
+ durationMs: 0
319
+ };
320
+ }
321
+ //#endregion
322
+ //#region src/swarm/adapter.ts
323
+ var C = class extends Error {
324
+ constructor(e) {
325
+ super(e), this.name = "SwarmEngineUnavailableError";
326
+ }
327
+ };
328
+ async function w(e, t) {
329
+ if (!(await p()).webgpu) throw new C("WebGPU is not available in this context");
330
+ let n = t ?? ((e) => import(
331
+ /* @vite-ignore */
332
+ e
333
+ )), r;
334
+ try {
335
+ r = await n(e);
336
+ } catch (e) {
337
+ throw new C(`failed to load swarm engine module: ${e instanceof Error ? e.message : String(e)}`);
338
+ }
339
+ let i = r?.Qwen35Engine;
340
+ if (!i || typeof i.create != "function") throw new C(`module at ${e} does not export Qwen35Engine.create`);
341
+ return r;
342
+ }
343
+ function ce(e, t, n, r) {
344
+ let i = !1, a = async (e) => {
345
+ r?.();
346
+ let t = await e();
347
+ return r?.(), t;
348
+ };
349
+ return {
350
+ get dim() {
351
+ return e.dims.dim;
352
+ },
353
+ get nc() {
354
+ return e.NC;
355
+ },
356
+ get maxSeq() {
357
+ return e.maxSeq;
358
+ },
359
+ reset: () => {
360
+ r?.(), e.reset();
361
+ },
362
+ embedRun: (t, n) => a(() => e.embedRun(t, n)),
363
+ runHidden: (t, n) => a(() => e.runHidden(t, n)),
364
+ headFromHidden: (t) => a(() => e.headFromHidden(t)),
365
+ setHidden: (t) => {
366
+ r?.(), e.setHidden(t);
367
+ },
368
+ dispose: () => {
369
+ if (!i) {
370
+ i = !0;
371
+ try {
372
+ e.dispose?.();
373
+ } catch {}
374
+ try {
375
+ t?.destroy?.();
376
+ } catch {}
377
+ try {
378
+ n?.();
379
+ } catch {}
380
+ }
381
+ }
382
+ };
383
+ }
384
+ //#endregion
385
+ //#region src/swarm/runtime.ts
386
+ var T = {
387
+ "qwen3.5-2b": "https://huggingface.co/unsloth/Qwen3.5-2B-GGUF/resolve/main/Qwen3.5-2B-Q4_0.gguf",
388
+ "qwen3.8-27b": "https://huggingface.co/unsloth/Qwen3.8-27B-GGUF/resolve/main/Qwen3.8-27B-Q4_0.gguf",
389
+ "qwen3.6-35b-moe": "https://huggingface.co/bartowski/Qwen_Qwen3.6-35B-A3B-GGUF/resolve/main/Qwen_Qwen3.6-35B-A3B-Q4_0.gguf"
390
+ }, le = "flaxia-swarm-weights-v1", ue = 12 * 1024 * 1024, E = 256 * 1024 * 1024, D = /* @__PURE__ */ new Map();
391
+ function O(e, t) {
392
+ D.set(e, {
393
+ status: t,
394
+ failedExpiresAt: t.state === "failed" ? Date.now() + 3e4 : void 0
395
+ });
396
+ }
397
+ function k(e, t, n, r) {
398
+ let i = j(e);
399
+ return {
400
+ modelId: e,
401
+ revision: /\/resolve\/([^/]+)\//.exec(new URL(i).pathname)?.[1] ?? "unknown",
402
+ dtype: /-(q\d+_\d+)\.gguf/i.exec(i)?.[1] ?? "unknown",
403
+ backend: "webgpu",
404
+ layerRange: [t.start, t.end],
405
+ state: n,
406
+ referenceCount: r
407
+ };
408
+ }
409
+ function A(e = Date.now()) {
410
+ let t = [];
411
+ for (let [n, r] of D) {
412
+ if (r.failedExpiresAt !== void 0 && r.failedExpiresAt <= e) {
413
+ D.delete(n);
414
+ continue;
415
+ }
416
+ t.push(r.status);
417
+ }
418
+ return {
419
+ version: 1,
420
+ sampledAt: e,
421
+ expiresAt: e + s,
422
+ entries: t.slice(0, 8)
423
+ };
424
+ }
425
+ function j(e) {
426
+ let t = Object.prototype.hasOwnProperty.call(T, e) ? T[e] : void 0;
427
+ if (t) return t;
428
+ throw new C(`unknown swarm model: ${e}`);
429
+ }
430
+ var M = null, N = 0, P = 0;
431
+ async function de() {
432
+ if (M !== null) return M;
433
+ try {
434
+ M = typeof caches < "u" ? await caches.open(le) : !1;
435
+ } catch {
436
+ M = !1;
437
+ }
438
+ return M;
439
+ }
440
+ function fe(e, t, n) {
441
+ return `https://flaxia-weights.local/${encodeURIComponent(e)}/${t}-${n}`;
442
+ }
443
+ async function F(e, t, n) {
444
+ let r = await I(e, t, n), i = new Uint8Array(await r.arrayBuffer()), a = n - t + 1;
445
+ if (i.byteLength !== a) throw Error(`short range ${i.byteLength}/${a}`);
446
+ return i;
447
+ }
448
+ async function I(e, t, n) {
449
+ let r = n - t + 1, i = await de(), a = fe(e, t, n);
450
+ if (i) try {
451
+ let e = await i.match(a);
452
+ if (e) {
453
+ let t = new Uint8Array(await e.arrayBuffer());
454
+ if (t.byteLength === r) return N++, new Response(t, { status: 200 });
455
+ await i.delete(a).catch(() => {});
456
+ }
457
+ } catch {}
458
+ let o;
459
+ for (let s = 0; s < 4; s++) {
460
+ try {
461
+ let s = await fetch(e, { headers: { Range: `bytes=${t}-${n}` } });
462
+ if (s.status !== 206) o = /* @__PURE__ */ Error(`model host refused range requests (${s.status})`);
463
+ else return P++, i && s.clone().arrayBuffer().then((e) => {
464
+ if (e.byteLength === r) return i.put(a, new Response(e, {
465
+ status: 200,
466
+ headers: { "content-type": "application/octet-stream" }
467
+ }));
468
+ }).catch(() => {}), s;
469
+ } catch (e) {
470
+ o = e;
471
+ }
472
+ await new Promise((e) => setTimeout(e, 150 * (s + 1)));
473
+ }
474
+ throw Error(`range fetch ${t}-${n} failed: ${o instanceof Error ? o.message : String(o)}`);
475
+ }
476
+ async function pe(e, t) {
477
+ let n = ue;
478
+ for (;;) {
479
+ let r = await F(t, 0, n - 1), i = r.buffer.slice(r.byteOffset, r.byteOffset + r.byteLength);
480
+ try {
481
+ return e.parseGGUFHeader(i);
482
+ } catch (e) {
483
+ if (n >= E) throw e;
484
+ n = Math.min(n * 2, E);
485
+ }
486
+ }
487
+ }
488
+ async function me() {
489
+ let e = navigator.gpu;
490
+ if (!e) throw new C("WebGPU is not available in this context");
491
+ let t = await e.requestAdapter({ powerPreference: "high-performance" });
492
+ if (!t) throw new C("no WebGPU adapter");
493
+ return t.requestDevice({ requiredLimits: {
494
+ maxBufferSize: t.limits.maxBufferSize,
495
+ maxStorageBufferBindingSize: t.limits.maxStorageBufferBindingSize
496
+ } });
497
+ }
498
+ function he(e, t) {
499
+ let n = t.vocab, r = n["<|im_start|>"], i = n["<|im_end|>"], a = n["<think>"], o = n["</think>"], s = (e) => [
500
+ r,
501
+ ...t.encode("user\n" + e),
502
+ i,
503
+ ...t.encode("\n"),
504
+ r,
505
+ ...t.encode("assistant\n"),
506
+ a,
507
+ ...t.encode("\n\n"),
508
+ o,
509
+ ...t.encode("\n\n")
510
+ ].filter((e) => typeof e == "number" && e >= 0), c = [i, n["<|endoftext|>"]].filter((e) => typeof e == "number");
511
+ return {
512
+ packHidden: (t) => {
513
+ let n = new Uint16Array(t.length);
514
+ for (let r = 0; r < t.length; r++) n[r] = e.f32ToF16(t[r]);
515
+ return new Uint8Array(n.buffer);
516
+ },
517
+ unpackHidden: (t) => {
518
+ let n = t.slice(), r = new Uint16Array(n.buffer), i = new Float32Array(r.length);
519
+ for (let t = 0; t < r.length; t++) i[t] = e.f16ToF32(r[t]);
520
+ return i;
521
+ },
522
+ argmax: (t) => e.argmax(t),
523
+ encodePrompt: (e) => s(Array.isArray(e) ? e.join("\n") : e),
524
+ decodeTokens: (e) => t.decode(e),
525
+ eosIds: new Set(c)
526
+ };
527
+ }
528
+ function L(e) {
529
+ let t = null, n = null, r = () => {
530
+ if (!t) {
531
+ let n = new URL("./swarm-engine.js", "" + import.meta.url).href;
532
+ t = e ? e() : w(n).then((e) => e);
533
+ }
534
+ return t;
535
+ }, i = async (e) => {
536
+ let t = await r(), i = j(e);
537
+ (!n || n.url !== i) && (n = {
538
+ url: i,
539
+ gguf: await pe(t, i)
540
+ });
541
+ let a = Number(n.gguf.meta["qwen35.block_count"]) - Number(n.gguf.meta["qwen35.nextn_predict_layers"] || 0);
542
+ if (!Number.isInteger(a) || a < 1) throw new C(`model ${e} has no qwen35 trunk layers`);
543
+ return {
544
+ mod: t,
545
+ url: i,
546
+ gguf: n.gguf,
547
+ layers: a
548
+ };
549
+ };
550
+ return {
551
+ async plan(e, t) {
552
+ let { layers: n } = await i(t);
553
+ return g({
554
+ sessionId: "",
555
+ taskId: "",
556
+ model: t,
557
+ layers: n,
558
+ nodes: e.map((e) => ({
559
+ nodeId: e.nodeId,
560
+ capacity: e.capacity
561
+ }))
562
+ }).chain;
563
+ },
564
+ async load(e, t) {
565
+ N = 0, P = 0;
566
+ let n = JSON.stringify([
567
+ t,
568
+ e.start,
569
+ e.end
570
+ ]);
571
+ O(n, k(t, e, "loading", 1));
572
+ let r, a = !1;
573
+ try {
574
+ let { mod: o, url: s, gguf: c } = await i(t);
575
+ r = await me();
576
+ let l = null, u = r;
577
+ u.addEventListener?.("uncapturederror", () => {
578
+ l = "swarm GPU validation failed";
579
+ }), u.lost?.then(() => {
580
+ l = "swarm GPU device lost";
581
+ });
582
+ let d = () => {
583
+ if (l) throw new C(l);
584
+ }, f = he(o, o.makeTokenizer(o.tokenizerFromGGUF(c.meta))), p = (e) => F(s, e.byteOffset, e.byteOffset + e.byteLength - 1);
585
+ c.streamEntry = (e) => o.streamEntryToGPU(r, e, (e) => I(s, e.byteOffset, e.byteOffset + e.byteLength - 1), { staging: 4 * 1024 * 1024 });
586
+ let m = await o.qwen35Weights(c, p, {
587
+ lo: e.start,
588
+ hi: e.end,
589
+ hasEmbed: e.hasEmbed,
590
+ hasHead: e.hasHead,
591
+ mtp: e.hasHead
592
+ }, void 0, (e, t) => o.gpuUploadEntry(r, e, t === o.GGML_EMBED)), h = c.tensors[o.GGML_EMBED]?.shape[0] ?? 0, g = await o.Qwen35Engine.create({
593
+ device: r,
594
+ meta: c.meta,
595
+ layerRange: [e.start, e.end],
596
+ hasEmbed: e.hasEmbed,
597
+ hasHead: e.hasHead,
598
+ vocab: h,
599
+ maxSeq: Math.min(x, Number(c.meta["qwen35.context_length"]) || 4096),
600
+ batchCols: 4,
601
+ weights: m
602
+ });
603
+ d();
604
+ let _ = ce(g, r, () => {
605
+ O(n, k(t, e, "evicting", 0)), queueMicrotask(() => D.delete(n));
606
+ }, d);
607
+ return a = !0, O(n, k(t, e, "ready", 1)), {
608
+ engine: _,
609
+ semantics: f,
610
+ warm: N > 0 && P === 0
611
+ };
612
+ } catch (i) {
613
+ if (O(n, k(t, e, "failed", 0)), !a) try {
614
+ r?.destroy?.();
615
+ } catch {}
616
+ throw i;
617
+ }
618
+ }
619
+ };
620
+ }
621
+ //#endregion
622
+ //#region src/swarm/messages.ts
623
+ function ge(e) {
624
+ return a(e) || m(e) || o(e) || c(e) || i(e) || n(e);
625
+ }
626
+ function _e(e) {
627
+ if (!e || typeof e != "object") return !1;
628
+ let t = e;
629
+ return t.type === "swarm-control" && typeof t.id == "string" && ge(t.message);
630
+ }
631
+ //#endregion
632
+ //#region src/worker/main.worker.ts
633
+ var R = null, ve = y, ye = 1, z = 15e3, B = /* @__PURE__ */ new Map(), V = /* @__PURE__ */ new Set(), H = /* @__PURE__ */ new Map();
634
+ function U(e) {
635
+ V.delete(e);
636
+ let t = H.get(e);
637
+ if (t) {
638
+ H.delete(e);
639
+ for (let e of t) e();
640
+ }
641
+ }
642
+ function be(e) {
643
+ return V.has(e) ? new Promise((t) => {
644
+ let n = H.get(e) ?? /* @__PURE__ */ new Set();
645
+ n.add(t), H.set(e, n);
646
+ }) : Promise.resolve();
45
647
  }
46
- var p = /* @__PURE__ */ new Map(), m = null;
47
- function h() {
48
- for (let e of p.values()) try {
648
+ var W = null, G = null, K = null, xe = 6e4;
649
+ async function Se() {
650
+ for (let e = 0;; e++) try {
651
+ await R.waitForSlot(ve);
652
+ return;
653
+ } catch (t) {
654
+ if (!(t instanceof b)) throw t;
655
+ if (e >= ye) throw Error(`device CPU busy: ${t.message}; task not started, retry on an idle node (retryable)`);
656
+ console.warn(`[flaxia-node:worker] ${t.message}; cooling down ${z}ms before retrying`), await new Promise((e) => setTimeout(e, z));
657
+ }
658
+ }
659
+ function Ce(e) {
660
+ let t = (t) => {
661
+ let n = B.get(e);
662
+ if (n !== void 0) throw Error(n);
663
+ self.postMessage({
664
+ id: e,
665
+ type: "token",
666
+ token: t
667
+ });
668
+ };
669
+ return async (n) => {
670
+ await be(e), t(n), await R?.yieldIfOverloaded();
671
+ };
672
+ }
673
+ var q = d(), J = q >= f;
674
+ console.log(`[flaxia-node:worker] startup memory probe wasmMemoryBytes=${q} capable=${J}`);
675
+ function Y() {
676
+ return r();
677
+ }
678
+ var X = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Map();
679
+ Z.set("swarm-inference", A);
680
+ var Q = null;
681
+ function we() {
682
+ for (let e of X.values()) try {
49
683
  e();
50
684
  } catch {}
51
- p.clear();
685
+ X.clear(), Z.clear(), Z.set("swarm-inference", A);
52
686
  }
53
- function g() {
54
- m && clearTimeout(m), m = setTimeout(() => {
55
- m = null, h();
56
- }, l);
687
+ function $() {
688
+ let e = Date.now(), t = [...Z.values()].flatMap((e) => {
689
+ try {
690
+ return e().entries;
691
+ } catch {
692
+ return [];
693
+ }
694
+ }).slice(0, 8);
695
+ return {
696
+ version: 1,
697
+ sampledAt: e,
698
+ expiresAt: e + 6e4,
699
+ entries: t
700
+ };
57
701
  }
58
- async function _(e, t, n) {
702
+ function Te() {
703
+ Q && clearTimeout(Q), Q = setTimeout(() => {
704
+ Q = null, we();
705
+ }, xe);
706
+ }
707
+ async function Ee(e, t, n, r) {
59
708
  switch (e) {
60
709
  case "ai-inference":
61
- let r = await import("./assets/ai-inference.js");
62
- return p.set(e, r.releaseCache), await r.handleAiInference(t, n);
710
+ let i = await import("./assets/ai-inference.js");
711
+ return X.set(e, i.releaseCache), Z.set(e, i.getModelCacheSnapshot), await i.handleAiInference(t, n);
63
712
  case "image-process": return await (await import("./assets/image-process.js")).handleImageProcess(t);
64
- case "container": return await (await import("./assets/container.js")).handleContainer(t);
713
+ case "container": return await (await import("./assets/container.js")).handleContainer(t, r?.fileSourceOrigins ?? [], r?.containerImageOrigins ?? []);
65
714
  case "vector-embed":
66
- let i = await import("./assets/vector-embed.js");
67
- return p.set(e, i.releaseCache), await i.handleVectorEmbed(t);
715
+ let a = await import("./assets/vector-embed.js");
716
+ return X.set(e, a.releaseCache), await a.handleVectorEmbed(t);
68
717
  case "vector-store":
69
- let a = await import("./assets/vector-store.js");
70
- return p.set(e, a.releaseCache), await a.handleVectorStore(t);
718
+ let o = await import("./assets/vector-store.js");
719
+ return X.set(e, o.releaseCache), await o.handleVectorStore(t);
71
720
  case "vector-query":
72
- let o = await import("./assets/vector-query.js");
73
- return p.set(e, o.releaseCache), await o.handleVectorQuery(t);
721
+ let s = await import("./assets/vector-query.js");
722
+ return X.set(e, s.releaseCache), await s.handleVectorQuery(t);
74
723
  case "nudenet":
75
- let s = await import("./assets/nudenet.js");
76
- return p.set(e, s.releaseCache), await s.handleNudeNet(t);
724
+ let c = await import("./assets/nudenet.js");
725
+ return X.set(e, c.releaseCache), await c.handleNudeNet(t);
77
726
  default: throw Error(`Unknown workload type: ${e}`);
78
727
  }
79
728
  }
729
+ function De(e, t, n) {
730
+ return new Promise((r, i) => {
731
+ let a = new oe({
732
+ initial: t,
733
+ runtime: L(),
734
+ sendControl: (t) => self.postMessage({
735
+ id: e,
736
+ type: "swarm-message",
737
+ message: t
738
+ }),
739
+ sendFrame: (t) => self.postMessage({
740
+ id: e,
741
+ type: "swarm-frame",
742
+ frame: t
743
+ }, [t]),
744
+ emitToken: n,
745
+ onDone: (e) => {
746
+ W === a && (W = null, G = null), r(e);
747
+ },
748
+ onError: (e) => {
749
+ W === a && (W = null, G = null), i(Error(e));
750
+ }
751
+ });
752
+ W = a, G = e, a.start();
753
+ });
754
+ }
80
755
  self.onmessage = async (e) => {
81
- let { id: t, workload: i, payload: a, config: o } = e.data, l = performance.now();
756
+ let t = e.data;
757
+ if (t?.type === "token-flow") {
758
+ let e = typeof t.id == "string" ? t.id : "";
759
+ e && K === e && typeof t.paused == "boolean" && (t.paused ? V.add(e) : U(e));
760
+ return;
761
+ }
762
+ if (t?.type === "swarm-control") {
763
+ if (!_e(t)) {
764
+ console.warn("[flaxia-node:worker] dropped malformed swarm-control message");
765
+ return;
766
+ }
767
+ W && W.handleControl(t.message);
768
+ return;
769
+ }
770
+ if (t?.type === "swarm-frame") {
771
+ t.frame instanceof ArrayBuffer ? W?.handleFrame(t.frame) : console.warn("[flaxia-node:worker] dropped malformed swarm-frame message");
772
+ return;
773
+ }
774
+ if (t?.type === "abort") {
775
+ let e = t.id, n = typeof t.reason == "string" && t.reason ? t.reason : "aborted by the coordinator";
776
+ U(e), W && G === e ? W.abort(n) : K === e && B.set(e, n);
777
+ return;
778
+ }
779
+ let { id: n, workload: r, payload: i, config: a } = t, o = performance.now();
780
+ K = n, U(n);
82
781
  try {
83
- if (c ||= new s(o?.maxCpuLoad), console.log(`[flaxia-node:worker] task start id=${t} workload=${i}`), !d) throw Error(`node incapable: insufficient WASM memory (${u} bytes < ${n}); rejecting all tasks`);
84
- if (r.has(i) && !f()) throw Error(`${i}: insufficient WASM memory (${u} bytes < ${n})`);
85
- await c.waitForSlot();
782
+ if (R ||= new te(a?.maxCpuLoad), console.log(`[flaxia-node:worker] task start id=${n} workload=${r}`), !J) throw Error(`node incapable: insufficient WASM memory (${q} bytes < ${f}); rejecting all tasks`);
783
+ if (l.has(r) && !Y()) throw Error(`${r}: insufficient WASM memory (${q} bytes < ${f})`);
784
+ await Se(), R.beginWork();
86
785
  let e = setInterval(() => {
87
786
  self.postMessage({
88
- id: t,
787
+ id: n,
89
788
  type: "heartbeat",
90
- cpuLoad: c?.lastMeasuredLoad ?? 0
789
+ cpuLoad: R?.lastMeasuredLoad ?? 0,
790
+ modelCache: $()
91
791
  });
92
- }, 1e4), p = performance.now();
792
+ }, 1e4), t = performance.now();
93
793
  try {
94
- let e = await _(i, a, (e) => {
95
- self.postMessage({
96
- id: t,
97
- type: "token",
98
- token: e
99
- });
794
+ let e = Ce(n), t = Array.isArray(a?.fileSourceOrigins) ? a.fileSourceOrigins.filter((e) => typeof e == "string") : [], s = Array.isArray(a?.containerImageOrigins) ? a.containerImageOrigins.filter((e) => typeof e == "string") : [], c = r === "swarm-inference" ? await De(n, i, e) : await Ee(r, i, e, {
795
+ fileSourceOrigins: t,
796
+ containerImageOrigins: s
100
797
  });
101
798
  self.postMessage({
102
- id: t,
799
+ id: n,
103
800
  type: "done",
104
- result: e
105
- }), console.log(`[flaxia-node:worker] task done id=${t} workload=${i} durationMs=${Math.round(performance.now() - l)}`);
801
+ result: c,
802
+ modelCache: $()
803
+ }), console.log(`[flaxia-node:worker] task done id=${n} workload=${r} durationMs=${Math.round(performance.now() - o)}`);
106
804
  } finally {
107
- clearInterval(e), c.markTaskComplete(performance.now() - p), g();
805
+ K = null, B.delete(n), U(n), clearInterval(e), R.markTaskComplete(performance.now() - t), Te();
108
806
  }
109
807
  } catch (e) {
110
- let n = e instanceof Error ? e.message : String(e);
111
- console.error(`[flaxia-node:worker] task error id=${t} workload=${i} error=${n}`), self.postMessage({
112
- id: t,
808
+ let t = e instanceof Error ? e.message : String(e);
809
+ console.error(`[flaxia-node:worker] task error id=${n} workload=${r} error=${t}`), K === n && (K = null), U(n), self.postMessage({
810
+ id: n,
113
811
  type: "error",
114
- error: n
812
+ error: t,
813
+ modelCache: $()
115
814
  });
116
815
  }
117
816
  };