@flaxia/node 0.5.0 → 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 (44) hide show
  1. package/dist/assets/ai-inference.js +241 -85
  2. package/dist/assets/webgpuProbe.js +357 -0
  3. package/dist/client/SignalingClient.d.ts.map +1 -1
  4. package/dist/client/__tests__/mobile-lifecycle.test.d.ts +2 -0
  5. package/dist/client/__tests__/mobile-lifecycle.test.d.ts.map +1 -0
  6. package/dist/client/mobile-lifecycle.d.ts +20 -0
  7. package/dist/client/mobile-lifecycle.d.ts.map +1 -0
  8. package/dist/executor/WorkerPool.d.ts +7 -1
  9. package/dist/executor/WorkerPool.d.ts.map +1 -1
  10. package/dist/executor/__tests__/resourceReporter.test.d.ts +2 -0
  11. package/dist/executor/__tests__/resourceReporter.test.d.ts.map +1 -0
  12. package/dist/executor/memoryProbe.d.ts +5 -0
  13. package/dist/executor/memoryProbe.d.ts.map +1 -1
  14. package/dist/executor/resourceReporter.d.ts +15 -0
  15. package/dist/executor/resourceReporter.d.ts.map +1 -0
  16. package/dist/executor/webgpuProbe.d.ts +16 -5
  17. package/dist/executor/webgpuProbe.d.ts.map +1 -1
  18. package/dist/index.js +943 -291
  19. package/dist/swarm/__tests__/peer-quality.test.d.ts +2 -0
  20. package/dist/swarm/__tests__/peer-quality.test.d.ts.map +1 -0
  21. package/dist/swarm/__tests__/peer-transport.test.d.ts +2 -0
  22. package/dist/swarm/__tests__/peer-transport.test.d.ts.map +1 -0
  23. package/dist/swarm/adapter.d.ts +1 -1
  24. package/dist/swarm/adapter.d.ts.map +1 -1
  25. package/dist/swarm/controller.d.ts +4 -0
  26. package/dist/swarm/controller.d.ts.map +1 -1
  27. package/dist/swarm/messages.d.ts +2 -2
  28. package/dist/swarm/messages.d.ts.map +1 -1
  29. package/dist/swarm/peer-quality.d.ts +14 -0
  30. package/dist/swarm/peer-quality.d.ts.map +1 -0
  31. package/dist/swarm/peer-transport.d.ts +81 -0
  32. package/dist/swarm/peer-transport.d.ts.map +1 -0
  33. package/dist/swarm/runtime.d.ts +5 -1
  34. package/dist/swarm/runtime.d.ts.map +1 -1
  35. package/dist/swarm-engine.js +39 -20
  36. package/dist/worker.js +331 -208
  37. package/dist/workloads/__tests__/model-pipeline-cache.test.d.ts +2 -0
  38. package/dist/workloads/__tests__/model-pipeline-cache.test.d.ts.map +1 -0
  39. package/dist/workloads/ai-inference.d.ts +6 -0
  40. package/dist/workloads/ai-inference.d.ts.map +1 -1
  41. package/dist/workloads/model-pipeline-cache.d.ts +48 -0
  42. package/dist/workloads/model-pipeline-cache.d.ts.map +1 -0
  43. package/package.json +1 -1
  44. package/dist/assets/dist.js +0 -209
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { d as e, f as t, m as n, p as r, r as i, u as a, v as o, x as s, y as c } from "./assets/dist.js";
2
- import { t as l } from "./assets/egress-guard.js";
1
+ import { A as e, C as t, D as n, E as r, S as i, T as a, _ as o, b as s, d as c, g as l, i as u, n as d, o as f, p, r as m, s as h, w as g } from "./assets/webgpuProbe.js";
2
+ import { t as _ } from "./assets/egress-guard.js";
3
3
  //#region src/consent/notice.ts
4
- var u = {
4
+ var v = {
5
5
  summary: "同意すると、このブラウザは第三者から依頼された処理をバックグラウンドで実行します。",
6
6
  items: [
7
7
  "実行する処理: 顧客(第三者)が依頼したワークロード。任意の WebAssembly コンテナの実行や、画像の NSFW(成人向け)判定などを含みます。",
@@ -12,34 +12,34 @@ var u = {
12
12
  acceptGateHint: "開示内容を確認できるよう、「同意して開始」はしばらくの間押せません。",
13
13
  acceptLabel: "同意して開始",
14
14
  rejectLabel: "拒否"
15
- }, d = 4320 * 60 * 60 * 1e3, f = "flaxia_consent_record", p = "flaxia_consent_granted", m = "flaxia_consent_expiry", h = "flaxia_consent_denied", g = 1, _ = 1e4, v = 2e3, ee = "flaxia-consent-integrity", te = 1, y = "keys", b = "consent-hmac-sha256-v1", x = (...e) => console.warn("[flaxia-node]", ...e), S = /* @__PURE__ */ new Map();
16
- function C(e) {
15
+ }, y = 4320 * 60 * 60 * 1e3, b = "flaxia_consent_record", x = "flaxia_consent_granted", ee = "flaxia_consent_expiry", S = "flaxia_consent_denied", C = 1, te = 1e4, w = 2e3, ne = "flaxia-consent-integrity", re = 1, T = "keys", E = "consent-hmac-sha256-v1", ie = (...e) => console.warn("[flaxia-node]", ...e), ae = /* @__PURE__ */ new Map();
16
+ function oe(e) {
17
17
  try {
18
18
  return localStorage.getItem(e);
19
19
  } catch {
20
- return S.get(e) ?? null;
20
+ return ae.get(e) ?? null;
21
21
  }
22
22
  }
23
- function ne(e, t) {
23
+ function se(e, t) {
24
24
  try {
25
25
  localStorage.setItem(e, t);
26
26
  } catch {
27
- S.set(e, t);
27
+ ae.set(e, t);
28
28
  }
29
29
  }
30
- function w(e) {
30
+ function D(e) {
31
31
  try {
32
32
  localStorage.removeItem(e);
33
33
  } catch {
34
- S.delete(e);
34
+ ae.delete(e);
35
35
  }
36
36
  }
37
- function re(e) {
37
+ function ce(e) {
38
38
  return new Promise((t, n) => {
39
39
  e.onsuccess = () => t(e.result), e.onerror = () => n(e.error ?? /* @__PURE__ */ Error("IndexedDB request failed"));
40
40
  });
41
41
  }
42
- function T() {
42
+ function le() {
43
43
  return new Promise((e, t) => {
44
44
  let n;
45
45
  try {
@@ -53,37 +53,37 @@ function T() {
53
53
  }
54
54
  let r;
55
55
  try {
56
- r = n.open(ee, te);
56
+ r = n.open(ne, re);
57
57
  } catch (e) {
58
58
  t(e);
59
59
  return;
60
60
  }
61
61
  r.onupgradeneeded = () => {
62
62
  let e = r.result;
63
- e.objectStoreNames.contains(y) || e.createObjectStore(y);
63
+ e.objectStoreNames.contains(T) || e.createObjectStore(T);
64
64
  }, r.onsuccess = () => e(r.result), r.onerror = () => t(r.error ?? /* @__PURE__ */ Error("IndexedDB open failed")), r.onblocked = () => t(/* @__PURE__ */ Error("IndexedDB open blocked"));
65
65
  });
66
66
  }
67
- function ie(e) {
67
+ function ue(e) {
68
68
  if (!e || typeof e != "object") return !1;
69
69
  let t = e;
70
70
  return t.type === "secret" && t.algorithm?.name === "HMAC";
71
71
  }
72
- var ae = {
72
+ var de = {
73
73
  async load() {
74
- let e = await T();
74
+ let e = await le();
75
75
  try {
76
- let t = await re(e.transaction(y, "readonly").objectStore(y).get(b));
77
- return ie(t) ? t : null;
76
+ let t = await ce(e.transaction(T, "readonly").objectStore(T).get(E));
77
+ return ue(t) ? t : null;
78
78
  } finally {
79
79
  e.close();
80
80
  }
81
81
  },
82
82
  async save(e) {
83
- let t = await T();
83
+ let t = await le();
84
84
  try {
85
- let n = t.transaction(y, "readwrite");
86
- n.objectStore(y).put(e, b), await new Promise((e, t) => {
85
+ let n = t.transaction(T, "readwrite");
86
+ n.objectStore(T).put(e, E), await new Promise((e, t) => {
87
87
  n.oncomplete = () => e(), n.onerror = () => t(n.error ?? /* @__PURE__ */ Error("IndexedDB write failed")), n.onabort = () => t(n.error ?? /* @__PURE__ */ Error("IndexedDB write aborted"));
88
88
  });
89
89
  } finally {
@@ -91,10 +91,10 @@ var ae = {
91
91
  }
92
92
  },
93
93
  async clear() {
94
- let e = await T();
94
+ let e = await le();
95
95
  try {
96
- let t = e.transaction(y, "readwrite");
97
- t.objectStore(y).delete(b), await new Promise((e, n) => {
96
+ let t = e.transaction(T, "readwrite");
97
+ t.objectStore(T).delete(E), await new Promise((e, n) => {
98
98
  t.oncomplete = () => e(), t.onerror = () => n(t.error ?? /* @__PURE__ */ Error("IndexedDB delete failed")), t.onabort = () => n(t.error ?? /* @__PURE__ */ Error("IndexedDB delete aborted"));
99
99
  });
100
100
  } finally {
@@ -102,7 +102,7 @@ var ae = {
102
102
  }
103
103
  }
104
104
  };
105
- function E(e, t, n) {
105
+ function fe(e, t, n) {
106
106
  return new Promise((r) => {
107
107
  let i = !1, a, o = (e) => {
108
108
  i || (i = !0, a !== void 0 && clearTimeout(a), r(e));
@@ -110,15 +110,15 @@ function E(e, t, n) {
110
110
  a = setTimeout(() => o(t), n), e.then((e) => o(e), () => o(t));
111
111
  });
112
112
  }
113
- var D = ae, O = null, k = null, A = !1, j = !1, M = null, N = 0, P = 0, F = null, oe = !1;
114
- function se() {
113
+ var pe = de, O = null, k = null, A = !1, j = !1, M = null, N = 0, P = 0, F = null, me = !1;
114
+ function he() {
115
115
  try {
116
116
  let e = globalThis.location?.origin;
117
117
  if (typeof e == "string" && e.length > 0) return e;
118
118
  } catch {}
119
119
  return "unknown";
120
120
  }
121
- var ce = se, le = () => ce(), ue = {
121
+ var ge = he, _e = () => ge(), ve = {
122
122
  name: "HMAC",
123
123
  hash: "SHA-256"
124
124
  };
@@ -129,7 +129,7 @@ function I() {
129
129
  } catch {}
130
130
  return null;
131
131
  }
132
- function de(e) {
132
+ function ye(e) {
133
133
  let t = new TextEncoder().encode(JSON.stringify([
134
134
  e.v,
135
135
  e.noticeVersion,
@@ -139,12 +139,12 @@ function de(e) {
139
139
  ])), n = new Uint8Array(t.byteLength);
140
140
  return n.set(t), n;
141
141
  }
142
- function fe(e) {
142
+ function be(e) {
143
143
  let t = "";
144
144
  for (let n of e) t += String.fromCharCode(n);
145
145
  return btoa(t).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
146
146
  }
147
- function pe(e) {
147
+ function xe(e) {
148
148
  try {
149
149
  let t = e.replace(/-/g, "+").replace(/_/g, "/"), n = t + "=".repeat((4 - t.length % 4) % 4), r = atob(n), i = new Uint8Array(r.length);
150
150
  for (let e = 0; e < r.length; e += 1) i[e] = r.charCodeAt(e);
@@ -153,40 +153,40 @@ function pe(e) {
153
153
  return null;
154
154
  }
155
155
  }
156
- async function me() {
157
- let e = await E(D.load(), null, v);
156
+ async function Se() {
157
+ let e = await fe(pe.load(), null, w);
158
158
  if (e) return e;
159
159
  let t = I();
160
160
  if (!t) return null;
161
161
  try {
162
- let e = await t.generateKey(ue, !1, ["sign", "verify"]);
163
- return await E(D.save(e), void 0, v), e;
162
+ let e = await t.generateKey(ve, !1, ["sign", "verify"]);
163
+ return await fe(pe.save(e), void 0, w), e;
164
164
  } catch {
165
165
  return null;
166
166
  }
167
167
  }
168
- async function he(e) {
168
+ async function Ce(e) {
169
169
  let t = I();
170
170
  if (!t || !O) return null;
171
171
  try {
172
- let n = await t.sign("HMAC", O, de(e));
173
- return fe(new Uint8Array(n));
172
+ let n = await t.sign("HMAC", O, ye(e));
173
+ return be(new Uint8Array(n));
174
174
  } catch {
175
175
  return null;
176
176
  }
177
177
  }
178
- async function ge(e) {
178
+ async function we(e) {
179
179
  let t = I();
180
180
  if (!t || !O || !e.mac) return !1;
181
- let n = pe(e.mac);
181
+ let n = xe(e.mac);
182
182
  if (!n) return !1;
183
183
  try {
184
- return await t.verify("HMAC", O, n, de(e));
184
+ return await t.verify("HMAC", O, n, ye(e));
185
185
  } catch {
186
186
  return !1;
187
187
  }
188
188
  }
189
- function _e(e) {
189
+ function Te(e) {
190
190
  if (!e) return null;
191
191
  try {
192
192
  let t = JSON.parse(e);
@@ -204,128 +204,128 @@ function _e(e) {
204
204
  return null;
205
205
  }
206
206
  }
207
- function L(e, t) {
207
+ function Ee(e, t) {
208
208
  return !(!Number.isFinite(e.grantedAt) || !Number.isFinite(e.expiry) || e.expiry <= t || e.grantedAt > e.expiry || e.expiry - e.grantedAt > 15552e6);
209
209
  }
210
- function R(e) {
211
- return e.v === g && e.noticeVersion === 2 && e.origin === le();
210
+ function De(e) {
211
+ return e.v === C && e.noticeVersion === 2 && e.origin === _e();
212
212
  }
213
- function z() {
214
- return _e(C(f));
213
+ function Oe() {
214
+ return Te(oe(b));
215
215
  }
216
- function ve(e) {
217
- ne(f, JSON.stringify(e));
216
+ function ke(e) {
217
+ se(b, JSON.stringify(e));
218
218
  }
219
- function B() {
220
- w(f);
219
+ function L() {
220
+ D(b);
221
221
  }
222
- function V() {
223
- w(p), w(m);
222
+ function R() {
223
+ D(x), D(ee);
224
224
  }
225
- var ye = () => {
225
+ var Ae = () => {
226
226
  let e = k;
227
- return !e || !A ? !1 : L(e, Date.now()) && R(e);
228
- }, be = () => C(h) === "true", H = () => ye() ? "granted" : be() ? "denied" : "unset", U = () => (M ||= xe(), M);
229
- async function xe() {
227
+ return !e || !A ? !1 : Ee(e, Date.now()) && De(e);
228
+ }, je = () => oe(S) === "true", z = () => Ae() ? "granted" : je() ? "denied" : "unset", B = () => (M ||= Me(), M);
229
+ async function Me() {
230
230
  let e = ++N, t = P, n = null;
231
231
  try {
232
- n = await me();
232
+ n = await Se();
233
233
  } catch {
234
234
  n = null;
235
235
  }
236
- if (e !== N) return H();
237
- O = n, V();
238
- let r = z();
239
- return r !== null && await ge(r) && L(r, Date.now()) && R(r) && r ? t === P && e === N && (k = r, A = !0) : r && !j && (B(), t === P && e === N && (k = null, A = !1)), H();
236
+ if (e !== N) return z();
237
+ O = n, R();
238
+ let r = Oe();
239
+ return r !== null && await we(r) && Ee(r, Date.now()) && De(r) && r ? t === P && e === N && (k = r, A = !0) : r && !j && (L(), t === P && e === N && (k = null, A = !1)), z();
240
240
  }
241
- function Se() {
241
+ function Ne() {
242
242
  let e = F;
243
- return F = null, e && Date.now() - e.at <= _ ? {
243
+ return F = null, e && Date.now() - e.at <= te ? {
244
244
  noticeVersion: e.noticeVersion,
245
245
  source: "user-gesture"
246
- } : oe ? {
246
+ } : me ? {
247
247
  noticeVersion: 2,
248
248
  source: "host-managed"
249
249
  } : null;
250
250
  }
251
- function Ce(e) {
252
- return typeof e != "number" || !Number.isFinite(e) || e <= 0 ? d : Math.min(Math.floor(e), d);
251
+ function Pe(e) {
252
+ return typeof e != "number" || !Number.isFinite(e) || e <= 0 ? y : Math.min(Math.floor(e), y);
253
253
  }
254
- function we(e, t) {
254
+ function Fe(e, t) {
255
255
  let n = Date.now();
256
256
  return {
257
- v: g,
257
+ v: C,
258
258
  noticeVersion: e,
259
- origin: le(),
259
+ origin: _e(),
260
260
  grantedAt: n,
261
- expiry: n + Ce(t),
261
+ expiry: n + Pe(t),
262
262
  mac: ""
263
263
  };
264
264
  }
265
- function Te(e, t) {
266
- w(h), V();
267
- let n = we(e.noticeVersion, t);
268
- return k = n, A = !0, j = !0, P += 1, ve(n), n;
265
+ function Ie(e, t) {
266
+ D(S), R();
267
+ let n = Fe(e.noticeVersion, t);
268
+ return k = n, A = !0, j = !0, P += 1, ke(n), n;
269
269
  }
270
- async function Ee(e) {
270
+ async function Le(e) {
271
271
  try {
272
- if (await U(), k !== e) return;
273
- let t = await he(e);
272
+ if (await B(), k !== e) return;
273
+ let t = await Ce(e);
274
274
  if (k !== e) return;
275
275
  if (!t) {
276
- B(), j = !1;
276
+ L(), j = !1;
277
277
  return;
278
278
  }
279
279
  let n = {
280
280
  ...e,
281
281
  mac: t
282
282
  };
283
- k = n, A = !0, ve(n), j = !1;
283
+ k = n, A = !0, ke(n), j = !1;
284
284
  } catch {
285
- k === e && (B(), j = !1);
285
+ k === e && (L(), j = !1);
286
286
  }
287
287
  }
288
- var W = () => {
289
- let e = Se();
288
+ var Re = () => {
289
+ let e = Ne();
290
290
  if (!e) {
291
- x("refusing programmatic consent grant: consent requires the built-in banner to be rendered and accepted by the visitor (see setHostManagedConsentAllowed for host-managed UIs)");
291
+ ie("refusing programmatic consent grant: consent requires the built-in banner to be rendered and accepted by the visitor (see setHostManagedConsentAllowed for host-managed UIs)");
292
292
  return;
293
293
  }
294
- Ee(Te(e));
295
- }, De = (e = 2) => {
294
+ Le(Ie(e));
295
+ }, ze = (e = 2) => {
296
296
  F = {
297
297
  noticeVersion: e,
298
298
  at: Date.now()
299
299
  };
300
- }, Oe = (e) => {
301
- oe = e === !0;
302
- }, G = () => {
303
- B(), V(), k = null, A = !1, j = !1, P += 1, ne(h, "true");
304
- }, ke = () => {
305
- B(), V(), w(h), k = null, A = !1, j = !1, F = null, O = null, N += 1, P += 1, M = null, E(D.clear(), void 0, v);
306
- }, Ae = C, je = ne, K = w;
307
- async function Me() {
308
- let e = P, t = z();
300
+ }, Be = (e) => {
301
+ me = e === !0;
302
+ }, Ve = () => {
303
+ L(), R(), k = null, A = !1, j = !1, P += 1, se(S, "true");
304
+ }, He = () => {
305
+ L(), R(), D(S), k = null, A = !1, j = !1, F = null, O = null, N += 1, P += 1, M = null, fe(pe.clear(), void 0, w);
306
+ }, Ue = oe, We = se, Ge = D;
307
+ async function Ke() {
308
+ let e = P, t = Oe();
309
309
  if (!t) {
310
310
  k = null, A = !1;
311
311
  return;
312
312
  }
313
313
  if (!I()) return;
314
314
  if (!O) {
315
- M = null, await U();
315
+ M = null, await B();
316
316
  return;
317
317
  }
318
- let n = await ge(t), r = z();
318
+ let n = await we(t), r = Oe();
319
319
  if (e !== P || !r || JSON.stringify(r) !== JSON.stringify(t)) return;
320
- let i = n && L(t, Date.now()) && R(t);
320
+ let i = n && Ee(t, Date.now()) && De(t);
321
321
  k = i ? t : null, A = i;
322
322
  }
323
323
  try {
324
324
  typeof globalThis.addEventListener == "function" && globalThis.addEventListener("storage", (e) => {
325
- e.key !== null && e.key !== f && e.key !== h || (P += 1, Me());
325
+ e.key !== null && e.key !== b && e.key !== S || (P += 1, Ke());
326
326
  });
327
327
  } catch {}
328
- var Ne = () => {
328
+ var qe = () => {
329
329
  try {
330
330
  if (typeof crypto < "u" && typeof crypto.randomUUID == "function") return crypto.randomUUID();
331
331
  } catch {}
@@ -334,38 +334,38 @@ var Ne = () => {
334
334
  return (e === "x" ? t : t & 3 | 8).toString(16);
335
335
  });
336
336
  };
337
- U();
337
+ B();
338
338
  //#endregion
339
339
  //#region src/consent/ConsentUI.ts
340
- var q = "#6366f1", Pe = 1500, Fe = 1500, Ie = 6e4, Le = 80, Re = 40, ze = [
340
+ var V = "#6366f1", Je = 1500, Ye = 1500, Xe = 6e4, Ze = 80, Qe = 40, $e = [
341
341
  "bottom-right",
342
342
  "bottom-left",
343
343
  "top-right",
344
344
  "top-left"
345
- ], Be = /^#[0-9a-f]{3}$/i, Ve = /^#[0-9a-f]{6}$/i, He = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i, Ue = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+)\s*\)$/i, We = new Map((/* @__PURE__ */ "black.white.red.green.blue.indigo.violet.purple.teal.cyan.orange.pink.brown.gray.grey.slate.navy.maroon.olive.gold.crimson.tomato.salmon.coral.seagreen.steelblue.royalblue.dodgerblue.mediumseagreen.mediumpurple.rebeccapurple".split(".")).map((e) => [e, e]));
346
- function Ge(e) {
347
- if (typeof e != "string") return q;
345
+ ], et = /^#[0-9a-f]{3}$/i, tt = /^#[0-9a-f]{6}$/i, nt = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i, rt = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+)\s*\)$/i, it = new Map((/* @__PURE__ */ "black.white.red.green.blue.indigo.violet.purple.teal.cyan.orange.pink.brown.gray.grey.slate.navy.maroon.olive.gold.crimson.tomato.salmon.coral.seagreen.steelblue.royalblue.dodgerblue.mediumseagreen.mediumpurple.rebeccapurple".split(".")).map((e) => [e, e]));
346
+ function at(e) {
347
+ if (typeof e != "string") return V;
348
348
  let t = e.trim();
349
- if (t.length === 0 || t.length > 64) return q;
350
- if (Be.test(t) || Ve.test(t)) return t.toLowerCase();
351
- let n = He.exec(t);
349
+ if (t.length === 0 || t.length > 64) return V;
350
+ if (et.test(t) || tt.test(t)) return t.toLowerCase();
351
+ let n = nt.exec(t);
352
352
  if (n) {
353
353
  let [e, t, r] = n.slice(1).map(Number);
354
- return e <= 255 && t <= 255 && r <= 255 ? `rgb(${e}, ${t}, ${r})` : q;
354
+ return e <= 255 && t <= 255 && r <= 255 ? `rgb(${e}, ${t}, ${r})` : V;
355
355
  }
356
- let r = Ue.exec(t);
356
+ let r = rt.exec(t);
357
357
  if (r) {
358
358
  let [e, t, n] = r.slice(1, 4).map(Number), i = Number(r[4]);
359
- return e <= 255 && t <= 255 && n <= 255 && i >= 0 && i <= 1 ? `rgba(${e}, ${t}, ${n}, ${i})` : q;
359
+ return e <= 255 && t <= 255 && n <= 255 && i >= 0 && i <= 1 ? `rgba(${e}, ${t}, ${n}, ${i})` : V;
360
360
  }
361
- return We.get(t.toLowerCase()) ?? q;
361
+ return it.get(t.toLowerCase()) ?? V;
362
362
  }
363
- function Ke(e, t, n) {
363
+ function ot(e, t, n) {
364
364
  if (typeof e != "string") return t;
365
365
  let r = e.replace(/[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u202a-\u202e\u2066-\u2069]/g, "").replace(/\s+/g, " ").trim();
366
366
  return r.length === 0 ? t : r.length > n ? `${r.slice(0, n)}…` : r;
367
367
  }
368
- function qe(e) {
368
+ function st(e) {
369
369
  if (typeof e != "string" || e.trim().length === 0) return null;
370
370
  try {
371
371
  let t = new URL(e.trim());
@@ -374,75 +374,75 @@ function qe(e) {
374
374
  return null;
375
375
  }
376
376
  }
377
- function Je(e) {
377
+ function ct(e) {
378
378
  return {
379
- brandName: Ke(e?.brandName, "Flaxia Crowd", Le),
380
- position: ze.includes(e?.position) ? e.position : "bottom-right",
381
- accentColor: Ge(e?.accentColor),
382
- acceptLabel: Ke(e?.acceptLabel, u.acceptLabel, Re),
383
- rejectLabel: Ke(e?.rejectLabel, u.rejectLabel, Re),
384
- privacyPolicyUrl: qe(e?.privacyPolicyUrl),
385
- minVisibleMs: Ye(e?.minVisibleMs)
379
+ brandName: ot(e?.brandName, "Flaxia Crowd", Ze),
380
+ position: $e.includes(e?.position) ? e.position : "bottom-right",
381
+ accentColor: at(e?.accentColor),
382
+ acceptLabel: ot(e?.acceptLabel, v.acceptLabel, Qe),
383
+ rejectLabel: ot(e?.rejectLabel, v.rejectLabel, Qe),
384
+ privacyPolicyUrl: st(e?.privacyPolicyUrl),
385
+ minVisibleMs: lt(e?.minVisibleMs)
386
386
  };
387
387
  }
388
- function Ye(e) {
389
- return typeof e != "number" || !Number.isFinite(e) ? Pe : Math.min(Math.max(Math.floor(e), Fe), Ie);
388
+ function lt(e) {
389
+ return typeof e != "number" || !Number.isFinite(e) ? Je : Math.min(Math.max(Math.floor(e), Ye), Xe);
390
390
  }
391
- function Xe(e, t) {
392
- return typeof t.minVisibleMs == "number" && Number.isFinite(t.minVisibleMs) ? Math.min(Math.max(Math.floor(t.minVisibleMs), 0), Ie) : e;
391
+ function ut(e, t) {
392
+ return typeof t.minVisibleMs == "number" && Number.isFinite(t.minVisibleMs) ? Math.min(Math.max(Math.floor(t.minVisibleMs), 0), Xe) : e;
393
393
  }
394
- var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n padding: 20px;\n background: #fff;\n color: #1f2937;\n border: 1px solid #ccc;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n z-index: 9999;\n border-radius: 8px;\n max-width: 300px;\n font-family: sans-serif;\n }\n .overlay h3 {\n margin: 0 0 8px;\n color: #111827;\n font-size: 16px;\n }\n .overlay p {\n margin: 0 0 12px;\n color: #4b5563;\n font-size: 14px;\n line-height: 1.4;\n }\n .overlay ul {\n margin: 0 0 12px;\n padding-left: 18px;\n color: #4b5563;\n font-size: 13px;\n line-height: 1.45;\n }\n .overlay li {\n margin-bottom: 6px;\n }\n .overlay .hint {\n margin: 0 0 8px;\n color: #6b7280;\n font-size: 12px;\n }\n .overlay .privacy {\n margin: 0 0 8px;\n font-size: 12px;\n }\n .overlay .privacy a {\n color: __flaxia_accent__;\n }\n button {\n background: __flaxia_accent__;\n color: white;\n border: none;\n padding: 10px 15px;\n border-radius: 4px;\n cursor: pointer;\n margin-top: 10px;\n width: 100%;\n font-size: 14px;\n }\n button:disabled {\n opacity: 0.6;\n cursor: default;\n }\n button.reject {\n background: transparent;\n color: #4b5563;\n border: 1px solid #ccc;\n }\n @media (prefers-color-scheme: dark) {\n .overlay {\n background: #1f2937;\n color: #f9fafb;\n border-color: #374151;\n box-shadow: 0 4px 6px rgba(0,0,0,0.4);\n }\n .overlay h3 {\n color: #f9fafb;\n }\n .overlay p,\n .overlay ul {\n color: #d1d5db;\n }\n .overlay .hint {\n color: #9ca3af;\n }\n button.reject {\n color: #d1d5db;\n border-color: #4b5563;\n }\n }\n", Qe = class {
394
+ var dt = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n padding: 20px;\n background: #fff;\n color: #1f2937;\n border: 1px solid #ccc;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n z-index: 9999;\n border-radius: 8px;\n max-width: 300px;\n font-family: sans-serif;\n }\n .overlay h3 {\n margin: 0 0 8px;\n color: #111827;\n font-size: 16px;\n }\n .overlay p {\n margin: 0 0 12px;\n color: #4b5563;\n font-size: 14px;\n line-height: 1.4;\n }\n .overlay ul {\n margin: 0 0 12px;\n padding-left: 18px;\n color: #4b5563;\n font-size: 13px;\n line-height: 1.45;\n }\n .overlay li {\n margin-bottom: 6px;\n }\n .overlay .hint {\n margin: 0 0 8px;\n color: #6b7280;\n font-size: 12px;\n }\n .overlay .privacy {\n margin: 0 0 8px;\n font-size: 12px;\n }\n .overlay .privacy a {\n color: __flaxia_accent__;\n }\n button {\n background: __flaxia_accent__;\n color: white;\n border: none;\n padding: 10px 15px;\n border-radius: 4px;\n cursor: pointer;\n margin-top: 10px;\n width: 100%;\n font-size: 14px;\n }\n button:disabled {\n opacity: 0.6;\n cursor: default;\n }\n button.reject {\n background: transparent;\n color: #4b5563;\n border: 1px solid #ccc;\n }\n @media (prefers-color-scheme: dark) {\n .overlay {\n background: #1f2937;\n color: #f9fafb;\n border-color: #374151;\n box-shadow: 0 4px 6px rgba(0,0,0,0.4);\n }\n .overlay h3 {\n color: #f9fafb;\n }\n .overlay p,\n .overlay ul {\n color: #d1d5db;\n }\n .overlay .hint {\n color: #9ca3af;\n }\n button.reject {\n color: #d1d5db;\n border-color: #4b5563;\n }\n }\n", ft = class {
395
395
  constructor(e, t, n, r, i) {
396
- this.config = Je(t), this.options = i ?? {}, this.root = e.attachShadow({ mode: "closed" }), this.render(n, r);
396
+ this.config = ct(t), this.options = i ?? {}, this.root = e.attachShadow({ mode: "closed" }), this.render(n, r);
397
397
  }
398
398
  shadowRootForTesting() {
399
399
  return this.root;
400
400
  }
401
401
  render(e, t) {
402
- let { brandName: n, position: r, accentColor: i, acceptLabel: a, rejectLabel: o, privacyPolicyUrl: s } = this.config, [c, l] = r.split("-"), d = document.createElement("style");
403
- d.textContent = Ze.replace(/__flaxia_accent__/g, i).replace("__flaxia_position__", `${c}: 20px; ${l}: 20px`);
404
- let f = document.createElement("div");
405
- f.className = "overlay", f.setAttribute("role", "dialog"), f.setAttribute("aria-labelledby", "flaxia-consent-title");
406
- let p = document.createElement("h3");
407
- p.id = "flaxia-consent-title", p.textContent = n;
408
- let m = document.createElement("p");
409
- m.textContent = u.summary;
410
- let h = document.createElement("ul");
411
- for (let e of u.items) {
402
+ let { brandName: n, position: r, accentColor: i, acceptLabel: a, rejectLabel: o, privacyPolicyUrl: s } = this.config, [c, l] = r.split("-"), u = document.createElement("style");
403
+ u.textContent = dt.replace(/__flaxia_accent__/g, i).replace("__flaxia_position__", `${c}: 20px; ${l}: 20px`);
404
+ let d = document.createElement("div");
405
+ d.className = "overlay", d.setAttribute("role", "dialog"), d.setAttribute("aria-labelledby", "flaxia-consent-title");
406
+ let f = document.createElement("h3");
407
+ f.id = "flaxia-consent-title", f.textContent = n;
408
+ let p = document.createElement("p");
409
+ p.textContent = v.summary;
410
+ let m = document.createElement("ul");
411
+ for (let e of v.items) {
412
412
  let t = document.createElement("li");
413
- t.textContent = e, h.appendChild(t);
413
+ t.textContent = e, m.appendChild(t);
414
414
  }
415
- if (f.append(p, m, h), s) {
415
+ if (d.append(f, p, m), s) {
416
416
  let e = document.createElement("p");
417
417
  e.className = "privacy";
418
418
  let t = document.createElement("a");
419
- t.href = s, t.target = "_blank", t.rel = "noopener noreferrer", t.textContent = "プライバシーポリシー", e.appendChild(t), f.appendChild(e);
419
+ t.href = s, t.target = "_blank", t.rel = "noopener noreferrer", t.textContent = "プライバシーポリシー", e.appendChild(t), d.appendChild(e);
420
420
  }
421
- let g = document.createElement("p");
422
- g.className = "hint", g.textContent = u.acceptGateHint;
421
+ let h = document.createElement("p");
422
+ h.className = "hint", h.textContent = v.acceptGateHint;
423
+ let g = document.createElement("button");
424
+ g.id = "consent-btn", g.type = "button", g.textContent = a;
423
425
  let _ = document.createElement("button");
424
- _.id = "consent-btn", _.type = "button", _.textContent = a;
425
- let v = document.createElement("button");
426
- v.id = "reject-btn", v.type = "button", v.className = "reject", v.textContent = o;
427
- let ee = this.options.now ?? (() => Date.now()), te = this.options.schedule ?? ((e, t) => void setTimeout(e, t)), y = Xe(this.config.minVisibleMs, this.options), b = ee() + y, x = y <= 0, S = !1;
428
- x || (_.disabled = !0, _.setAttribute("aria-disabled", "true"), te(() => {
429
- x = !0, _.disabled = !1, _.removeAttribute("aria-disabled"), g.remove();
430
- }, y));
431
- let C = (e) => {
432
- S || (S = !0, f.remove(), e?.());
426
+ _.id = "reject-btn", _.type = "button", _.className = "reject", _.textContent = o;
427
+ let y = this.options.now ?? (() => Date.now()), b = this.options.schedule ?? ((e, t) => void setTimeout(e, t)), x = ut(this.config.minVisibleMs, this.options), ee = y() + x, S = x <= 0, C = !1;
428
+ S || (g.disabled = !0, g.setAttribute("aria-disabled", "true"), b(() => {
429
+ S = !0, g.disabled = !1, g.removeAttribute("aria-disabled"), h.remove();
430
+ }, x));
431
+ let te = (e) => {
432
+ C || (C = !0, d.remove(), e?.());
433
433
  };
434
- _.addEventListener("click", () => {
435
- !x || ee() < b || (De(2), C(e));
436
- }), v.addEventListener("click", () => {
437
- C(t);
438
- }), x || f.appendChild(g), f.append(_, v), this.root.append(d, f);
434
+ g.addEventListener("click", () => {
435
+ !S || y() < ee || (ze(2), te(e));
436
+ }), _.addEventListener("click", () => {
437
+ te(t);
438
+ }), S || d.appendChild(h), d.append(g, _), this.root.append(u, d);
439
439
  }
440
- }, J = (...e) => console.log("[flaxia-node]", ...e), $e = class e {
440
+ }, H = (...e) => console.log("[flaxia-node]", ...e), pt = class e {
441
441
  static {
442
442
  this.MAX_PENDING_CONTROLS = 64;
443
443
  }
444
444
  constructor(e, t = 3e5) {
445
- this.worker = null, this.queue = [], this.active = null, this.pendingControls = [], this._lastCpuLoad = 0, this.workerUrl = e || "/worker.js", this.defaultTimeoutMs = t, this.initWorker();
445
+ this.worker = null, this.queue = [], this.active = null, this.pendingControls = [], this._lastCpuLoad = 0, this._hasCpuLoadSample = !1, this._modelCacheSnapshot = null, this.workerUrl = e || "/worker.js", this.defaultTimeoutMs = t, this.initWorker();
446
446
  }
447
447
  initWorker() {
448
448
  if (typeof Worker > "u") return;
@@ -460,7 +460,7 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
460
460
  return;
461
461
  }
462
462
  let l = () => this.execute(e, t, n, r, i, a, s, c, o);
463
- this.active ? (J(`task queued id=${e} workload=${t} (active task running)`), this.queue.push({
463
+ this.active ? (H(`task queued id=${e} workload=${t} (active task running)`), this.queue.push({
464
464
  id: e,
465
465
  job: l,
466
466
  reject: c
@@ -474,7 +474,7 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
474
474
  return;
475
475
  }
476
476
  let u = r ?? this.defaultTimeoutMs, d = !1, f = performance.now();
477
- J(`task start id=${e} workload=${t} timeoutMs=${u}`);
477
+ H(`task start id=${e} workload=${t} timeoutMs=${u}`);
478
478
  let p = (t) => {
479
479
  if (d) return;
480
480
  d = !0;
@@ -483,12 +483,12 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
483
483
  }, m = (n) => {
484
484
  let { id: r, type: a, result: l, error: u, token: d, cpuLoad: m } = n.data;
485
485
  if (r === e) {
486
- if (a === "token") {
486
+ if (g(n.data.modelCache) && (this._modelCacheSnapshot = n.data.modelCache), a === "token") {
487
487
  i?.(d);
488
488
  return;
489
489
  }
490
490
  if (a === "heartbeat") {
491
- typeof m == "number" && Number.isFinite(m) && (this._lastCpuLoad = Math.min(1, Math.max(0, m)));
491
+ typeof m == "number" && Number.isFinite(m) && (this._lastCpuLoad = Math.min(1, Math.max(0, m)), this._hasCpuLoadSample = !0);
492
492
  return;
493
493
  }
494
494
  if (a === "swarm-frame") {
@@ -499,16 +499,16 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
499
499
  c?.onMessage?.(n.data.message);
500
500
  return;
501
501
  }
502
- a === "done" ? (J(`task done id=${e} workload=${t} durationMs=${Math.round(performance.now() - f)}`), p(() => o(l))) : a === "error" ? (J(`task failed id=${e} workload=${t} error=${u}`), p(() => s(Error(u)))) : (J(`task unknown-message id=${e} type=${String(a)}`), p(() => s(/* @__PURE__ */ Error(`Unknown message type: ${String(a)}`))));
502
+ a === "done" ? (H(`task done id=${e} workload=${t} durationMs=${Math.round(performance.now() - f)}`), p(() => o(l))) : a === "error" ? (H(`task failed id=${e} workload=${t} error=${u}`), p(() => s(Error(u)))) : (H(`task unknown-message id=${e} type=${String(a)}`), p(() => s(/* @__PURE__ */ Error(`Unknown message type: ${String(a)}`))));
503
503
  }
504
- }, h = () => l.removeEventListener("message", m), g = setTimeout(() => {
505
- J(`task timeout id=${e} workload=${t} (worker terminated after ${u}ms)`), this.cleanupWorker(), p(() => s(/* @__PURE__ */ Error("TIMEOUT")));
504
+ }, h = () => l.removeEventListener("message", m), _ = setTimeout(() => {
505
+ H(`task timeout id=${e} workload=${t} (worker terminated after ${u}ms)`), this.cleanupWorker(), p(() => s(/* @__PURE__ */ Error("TIMEOUT")));
506
506
  }, u);
507
507
  this.active = {
508
508
  id: e,
509
509
  resolve: o,
510
510
  reject: s,
511
- timer: g,
511
+ timer: _,
512
512
  worker: l,
513
513
  removeListener: h
514
514
  }, l.addEventListener("message", m);
@@ -560,11 +560,17 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
560
560
  frame: e
561
561
  }, [e]);
562
562
  }
563
+ setTokenFlow(e, t) {
564
+ return this.active?.id === e ? this.postToActive({
565
+ type: "token-flow",
566
+ paused: t
567
+ }) : !1;
568
+ }
563
569
  abort(e, t) {
564
570
  let n = this.queue.findIndex((t) => t.id === e);
565
571
  if (n >= 0) {
566
572
  let [r] = this.queue.splice(n, 1);
567
- return this.pendingControls = this.pendingControls.filter((t) => t.taskId !== e), J(`task aborted before start id=${e} reason=${t}`), r.reject(Error(t)), !0;
573
+ return this.pendingControls = this.pendingControls.filter((t) => t.taskId !== e), H(`task aborted before start id=${e} reason=${t}`), r.reject(Error(t)), !0;
568
574
  }
569
575
  if (this.active?.id !== e || !this.worker) return !1;
570
576
  try {
@@ -572,13 +578,13 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
572
578
  id: e,
573
579
  type: "abort",
574
580
  reason: t
575
- }), J(`task abort sent id=${e} reason=${t}`), !0;
581
+ }), H(`task abort sent id=${e} reason=${t}`), !0;
576
582
  } catch {
577
583
  return !1;
578
584
  }
579
585
  }
580
586
  handleWorkerError(e) {
581
- J(`worker error error=${e.message}`);
587
+ H(`worker error error=${e.message}`);
582
588
  let t = this.active;
583
589
  this.cleanupWorker(), t && (clearTimeout(t.timer), this.active = null, t.reject(e), this.dequeue());
584
590
  }
@@ -587,13 +593,13 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
587
593
  e && e.job();
588
594
  }
589
595
  cleanupWorker() {
590
- this.worker &&= (this.worker.terminate(), null), this.initWorker();
596
+ this.worker &&= (this.worker.terminate(), null), this._modelCacheSnapshot = null, this.initWorker();
591
597
  }
592
598
  terminate() {
593
599
  let e = this.queue;
594
600
  this.queue = [], this.pendingControls = [];
595
601
  for (let t of e) t.reject(/* @__PURE__ */ Error("TERMINATED"));
596
- this.active &&= (clearTimeout(this.active.timer), this.active.reject(/* @__PURE__ */ Error("TERMINATED")), null), this.worker &&= (this.worker.terminate(), null);
602
+ this.active &&= (clearTimeout(this.active.timer), this.active.reject(/* @__PURE__ */ Error("TERMINATED")), null), this.worker &&= (this.worker.terminate(), null), this._modelCacheSnapshot = null;
597
603
  }
598
604
  resume() {
599
605
  this.worker || this.initWorker();
@@ -601,26 +607,577 @@ var Ze = "\n .overlay {\n position: fixed;\n __flaxia_position__;\n pa
601
607
  get lastCpuLoad() {
602
608
  return this._lastCpuLoad;
603
609
  }
604
- }, Y = (...e) => console.log("[flaxia-node]", ...e), X = (...e) => console.error("[flaxia-node]", ...e);
610
+ get hasCpuLoadSample() {
611
+ return this._hasCpuLoadSample;
612
+ }
613
+ get modelCacheSnapshot() {
614
+ let e = this._modelCacheSnapshot;
615
+ return !e || e.expiresAt <= Date.now() ? null : e;
616
+ }
617
+ }, U = null, mt = null;
618
+ function W(e, t, n, r, i, a) {
619
+ return {
620
+ value: e,
621
+ unit: t,
622
+ source: n,
623
+ sampledAt: r,
624
+ expiresAt: i,
625
+ sampleCount: a
626
+ };
627
+ }
628
+ function G(e, t, n) {
629
+ return W(null, e, "unknown", t, t + n, 0);
630
+ }
631
+ async function ht(e, t) {
632
+ return e ? ((!U || U.expiresAt <= t) && (mt ||= d().then((e) => (U = e, e)).finally(() => {
633
+ mt = null;
634
+ }), U = await mt), U) : null;
635
+ }
636
+ async function gt(e) {
637
+ let t = e.now ?? Date.now(), r = t + n, i = u(), a = i.bytes !== null && i.sampledAt !== null && t - i.sampledAt <= 864e5, s = Number.isFinite(e.deviceMemory) && e.deviceMemory > 0 && e.deviceMemory <= 1024, c = await ht(e.probeGpu === !0, t), l = c?.sampledAt ?? t, d = c?.expiresAt ?? t + 6e5;
638
+ return {
639
+ version: 1,
640
+ sampledAt: t,
641
+ expiresAt: r,
642
+ cpuLoad: typeof e.cpuLoad == "number" && Number.isFinite(e.cpuLoad) && e.cpuLoad >= 0 && e.cpuLoad <= 1 ? W(e.cpuLoad, "ratio", "estimated", t, r, 1) : G("ratio", t, n),
643
+ wasmMemoryLowerBound: a ? W(i.bytes, "bytes", "measured", i.sampledAt, i.sampledAt + o, 1) : G("bytes", t, o),
644
+ deviceMemory: s ? W(e.deviceMemory, "GiB", "estimated", t, t + o, 1) : G("GiB", t, o),
645
+ gpu: {
646
+ status: c?.status ?? "unknown",
647
+ sampledAt: l,
648
+ expiresAt: d,
649
+ architecture: c?.architecture ? W(c.architecture, "text", "measured", l, d, 1) : G("text", l, p),
650
+ maxStorageBufferBindingSize: c?.maxStorageBufferBindingSize !== null && c?.maxStorageBufferBindingSize !== void 0 ? W(c.maxStorageBufferBindingSize, "bytes", "measured", l, d, 1) : G("bytes", l, p),
651
+ computeCompletionMs: c?.computeCompletionMs !== null && c?.computeCompletionMs !== void 0 ? W(c.computeCompletionMs, "ms", "measured", l, d, c.sampleCount) : G("ms", l, p),
652
+ memoryBytes: G("bytes", l, p)
653
+ }
654
+ };
655
+ }
656
+ //#endregion
657
+ //#region src/swarm/peer-quality.ts
658
+ var _t = 15e3;
659
+ function vt(e) {
660
+ let t = e.filter((e) => Number.isFinite(e) && e >= 0).slice(-5);
661
+ if (!t.length) return [];
662
+ let n = [...t].sort((e, t) => e - t), r = n[Math.floor(n.length / 2)], i = r + Math.max(20, r * 4);
663
+ return t.filter((e) => e <= i);
664
+ }
665
+ function K(e, t) {
666
+ return !Number.isFinite(e) || e < 0 || !Number.isFinite(t) || t <= 0 ? null : e * 8 / t / 1e3;
667
+ }
668
+ function yt(e, t) {
669
+ let n = vt(e);
670
+ if (!n.length) return {
671
+ value: null,
672
+ sampledAt: t,
673
+ sampleCount: 0
674
+ };
675
+ let r = [...n].sort((e, t) => e - t);
676
+ return {
677
+ value: r[Math.floor(r.length / 2)],
678
+ sampledAt: t,
679
+ sampleCount: n.length
680
+ };
681
+ }
682
+ function bt(e, n, r, i, a) {
683
+ let o = (e, t) => {
684
+ let r = (r) => {
685
+ let i = t?.[r] ?? n;
686
+ return n - i >= 6e4 ? yt([], n) : yt(e[r] ?? [], i);
687
+ };
688
+ return {
689
+ rttMs: r("rttMs"),
690
+ jitterMs: r("jitterMs"),
691
+ sendMbps: r("sendMbps"),
692
+ receiveMbps: r("receiveMbps")
693
+ };
694
+ };
695
+ return {
696
+ version: 1,
697
+ peerNodeId: e,
698
+ sampledAt: n,
699
+ expiresAt: n + t,
700
+ webRtc: o(r, a?.webRtc),
701
+ application: o(i, a?.application)
702
+ };
703
+ }
704
+ //#endregion
705
+ //#region src/swarm/peer-transport.ts
706
+ var xt = 5e3, q = 16 * 1024, St = l, Ct = 256 * 1024, wt = 1129860166, J = 16, Tt = 2, Et = 64, Dt = "flaxia-swarm-v1", Ot = "flaxia-peer-quality-v1", kt = 128, At = [{ urls: "stun:stun.cloudflare.com:3478" }];
707
+ function jt() {
708
+ return {
709
+ rttMs: [],
710
+ jitterMs: [],
711
+ sendMbps: [],
712
+ receiveMbps: []
713
+ };
714
+ }
715
+ function Mt(e) {
716
+ if (e.byteLength < J || e.byteLength > 16400) return null;
717
+ let t = new DataView(e);
718
+ if (t.getUint32(0, !0) !== wt) return null;
719
+ let n = t.getUint32(4, !0), r = t.getUint16(8, !0), i = t.getUint16(10, !0), a = t.getUint32(12, !0);
720
+ if (a < 1 || a > St || i < 1 || i !== Math.ceil(a / 16384) || r >= i) return null;
721
+ let o = Math.min(q, a - r * q);
722
+ return e.byteLength - J === o ? {
723
+ messageId: n,
724
+ index: r,
725
+ count: i,
726
+ totalBytes: a,
727
+ payload: new Uint8Array(e, J)
728
+ } : null;
729
+ }
730
+ function Nt(e, t) {
731
+ if (e.byteLength < 1 || e.byteLength > St) throw Error(`swarm peer frame size is outside 1..${St} bytes`);
732
+ let n = Math.ceil(e.byteLength / q), r = [];
733
+ for (let i = 0; i < n; i++) {
734
+ let a = i * q, o = Math.min(a + q, e.byteLength), s = new Uint8Array(e, a, o - a), c = new ArrayBuffer(J + s.byteLength), l = new DataView(c);
735
+ l.setUint32(0, wt, !0), l.setUint32(4, t >>> 0, !0), l.setUint16(8, i, !0), l.setUint16(10, n, !0), l.setUint32(12, e.byteLength, !0), new Uint8Array(c, J).set(s), r.push(c);
736
+ }
737
+ return r;
738
+ }
739
+ var Pt = class {
740
+ constructor() {
741
+ this.assemblies = /* @__PURE__ */ new Map();
742
+ }
743
+ accept(e, t = Date.now()) {
744
+ this.expire(t);
745
+ let n = Mt(e);
746
+ if (!n) return null;
747
+ let r = this.assemblies.get(n.messageId);
748
+ if (!r) {
749
+ if (this.assemblies.size >= Tt) return null;
750
+ r = {
751
+ count: n.count,
752
+ totalBytes: n.totalBytes,
753
+ parts: Array(n.count),
754
+ received: 0,
755
+ receivedBytes: 0,
756
+ createdAt: t
757
+ }, this.assemblies.set(n.messageId, r);
758
+ }
759
+ if (r.count !== n.count || r.totalBytes !== n.totalBytes) return this.assemblies.delete(n.messageId), null;
760
+ let i = r.parts[n.index];
761
+ if (i) return i.byteLength === n.payload.byteLength && i.every((e, t) => e === n.payload[t]) || this.assemblies.delete(n.messageId), null;
762
+ let a = n.payload.slice();
763
+ if (r.parts[n.index] = a, r.received++, r.receivedBytes += a.byteLength, r.receivedBytes > r.totalBytes) return this.assemblies.delete(n.messageId), null;
764
+ if (r.received !== r.count) return null;
765
+ if (r.receivedBytes !== r.totalBytes) return this.assemblies.delete(n.messageId), null;
766
+ let o = new Uint8Array(r.totalBytes), s = 0;
767
+ for (let e of r.parts) {
768
+ if (!e) return this.assemblies.delete(n.messageId), null;
769
+ o.set(e, s), s += e.byteLength;
770
+ }
771
+ return this.assemblies.delete(n.messageId), o.buffer;
772
+ }
773
+ clear() {
774
+ this.assemblies.clear();
775
+ }
776
+ expire(e) {
777
+ for (let [t, n] of this.assemblies) e - n.createdAt > 5e3 * 2 && this.assemblies.delete(t);
778
+ }
779
+ }, Ft = class {
780
+ constructor(e) {
781
+ this.options = e, this.peers = /* @__PURE__ */ new Map(), this.reassembler = new Pt(), this.nextMessageId = 1, this.mode = "undecided", this.closed = !1, this.failed = !1, this.readyPromise = null, this.readyResolve = null, this.readyTimer = null, this.qualityTimer = null, this.samplingQuality = !1;
782
+ }
783
+ get selectedMode() {
784
+ return this.mode;
785
+ }
786
+ async start() {
787
+ if (this.closed || this.peers.size) return;
788
+ if (typeof RTCPeerConnection > "u" && !this.options.createPeerConnection) {
789
+ this.unavailable();
790
+ return;
791
+ }
792
+ let e = [...new Set([this.options.previousNodeId, this.options.nextNodeId])].filter((e) => !!e && e !== this.options.nodeId);
793
+ try {
794
+ for (let t of e) {
795
+ let e = (this.options.createPeerConnection ?? ((e) => new RTCPeerConnection(e)))({ iceServers: At }), n = {
796
+ nodeId: t,
797
+ connection: e,
798
+ channel: null,
799
+ remoteDescriptionSet: !1,
800
+ pendingCandidates: [],
801
+ quality: {
802
+ webRtc: jt(),
803
+ application: jt()
804
+ },
805
+ qualitySampledAt: {
806
+ webRtc: {},
807
+ application: {}
808
+ },
809
+ applicationBytesSent: 0,
810
+ applicationBytesReceived: 0,
811
+ lastApplicationBytesSent: 0,
812
+ lastApplicationBytesReceived: 0,
813
+ nextProbeId: 1
814
+ };
815
+ this.peers.set(t, n), e.onicecandidate = (e) => {
816
+ let n = e.candidate;
817
+ this.options.onSignal(t, {
818
+ kind: "candidate",
819
+ candidate: n?.candidate ? {
820
+ candidate: n.candidate,
821
+ sdpMid: n.sdpMid,
822
+ sdpMLineIndex: n.sdpMLineIndex,
823
+ usernameFragment: n.usernameFragment
824
+ } : null
825
+ });
826
+ }, e.ondatachannel = (e) => this.bindChannel(n, e.channel), e.onconnectionstatechange = () => {
827
+ (e.connectionState === "failed" || e.connectionState === "closed") && this.unavailable();
828
+ };
829
+ }
830
+ for (let e of this.peers.values()) {
831
+ let { nodeId: t, connection: n } = e;
832
+ if (this.options.nodeId.localeCompare(t) < 0) {
833
+ this.bindChannel(e, n.createDataChannel(Dt, { ordered: !0 }));
834
+ let r = await n.createOffer();
835
+ if (this.closed || this.failed) return;
836
+ await n.setLocalDescription(r);
837
+ let i = n.localDescription;
838
+ if (!i?.sdp || i.type !== "offer" && i.type !== "answer") throw Error("empty local SDP offer");
839
+ this.options.onSignal(t, {
840
+ kind: "description",
841
+ description: {
842
+ type: i.type,
843
+ sdp: i.sdp
844
+ }
845
+ });
846
+ }
847
+ }
848
+ this.resolveReadyIfOpen();
849
+ } catch (e) {
850
+ this.unavailable(e instanceof Error ? e : Error(String(e)));
851
+ }
852
+ }
853
+ async handleSignal(e, t) {
854
+ if (this.closed || this.failed) return;
855
+ let n = this.peers.get(e);
856
+ if (n) try {
857
+ if (t.kind === "description") {
858
+ await n.connection.setRemoteDescription(t.description), n.remoteDescriptionSet = !0;
859
+ for (let e of n.pendingCandidates.splice(0)) await n.connection.addIceCandidate(e);
860
+ if (t.description.type === "offer") {
861
+ let t = await n.connection.createAnswer();
862
+ await n.connection.setLocalDescription(t);
863
+ let r = n.connection.localDescription;
864
+ if (!r?.sdp || r.type !== "offer" && r.type !== "answer") throw Error("empty local SDP answer");
865
+ this.options.onSignal(e, {
866
+ kind: "description",
867
+ description: {
868
+ type: r.type,
869
+ sdp: r.sdp
870
+ }
871
+ });
872
+ }
873
+ } else if (t.candidate !== null) if (n.remoteDescriptionSet) await n.connection.addIceCandidate(t.candidate);
874
+ else {
875
+ if (n.pendingCandidates.length >= Et) throw Error("too many ICE candidates before remote description");
876
+ n.pendingCandidates.push(t.candidate);
877
+ }
878
+ } catch (e) {
879
+ this.unavailable(e instanceof Error ? e : Error(String(e)));
880
+ }
881
+ }
882
+ waitUntilReady(e = this.options.connectTimeoutMs ?? 5e3) {
883
+ return this.mode === "undecided" ? this.readyPromise ? this.readyPromise : this.failed || this.closed || !this.peers.size ? Promise.resolve(!1) : this.allPeersOpen() ? Promise.resolve(!0) : (this.readyPromise = new Promise((t) => {
884
+ this.readyResolve = t, this.readyTimer = setTimeout(() => this.resolveReady(this.allPeersOpen()), e);
885
+ }), this.readyPromise) : Promise.resolve(this.mode === "peer");
886
+ }
887
+ selectMode(e) {
888
+ if (!(this.closed || this.mode !== "undecided")) {
889
+ if (this.mode = e, e === "relay") {
890
+ this.stopQualitySampling(), this.closePeerConnections();
891
+ return;
892
+ }
893
+ this.allPeersOpen() ? this.startQualitySampling() : this.unavailable(/* @__PURE__ */ Error("peer mode selected without every data channel open"));
894
+ }
895
+ }
896
+ async sendFrame(e) {
897
+ if (this.mode !== "peer") return !1;
898
+ let t = this.options.nextNodeId, n = t ? this.peers.get(t)?.channel : void 0;
899
+ if (!n || n.readyState !== "open") {
900
+ let e = /* @__PURE__ */ Error("swarm peer data channel closed during the session");
901
+ throw this.unavailable(e), e;
902
+ }
903
+ let r = this.nextMessageId++ >>> 0;
904
+ try {
905
+ for (let t of Nt(e, r)) {
906
+ if (await this.waitForBuffer(n), n.readyState !== "open") throw Error("swarm peer data channel closed while sending");
907
+ n.send(t);
908
+ }
909
+ let i = t ? this.peers.get(t) : void 0;
910
+ return i && (i.applicationBytesSent += e.byteLength), !0;
911
+ } catch (e) {
912
+ let t = e instanceof Error ? e : Error(String(e));
913
+ throw this.unavailable(t), t;
914
+ }
915
+ }
916
+ close() {
917
+ this.closed || (this.closed = !0, this.stopQualitySampling(), this.resolveReady(!1), this.closePeerConnections(), this.reassembler.clear());
918
+ }
919
+ bindChannel(e, t) {
920
+ if (e.channel && e.channel !== t) {
921
+ try {
922
+ t.close();
923
+ } catch {}
924
+ return;
925
+ }
926
+ e.channel = t, t.binaryType = "arraybuffer", t.bufferedAmountLowThreshold = Ct / 2, t.onopen = () => this.resolveReadyIfOpen(), t.onmessage = (t) => {
927
+ if (typeof t.data == "string") {
928
+ this.handleQualityProbe(e, t.data);
929
+ return;
930
+ }
931
+ if (e.nodeId !== this.options.previousNodeId || !(t.data instanceof ArrayBuffer)) return;
932
+ let n = this.reassembler.accept(t.data, this.options.now?.());
933
+ n && (e.applicationBytesReceived += n.byteLength, this.options.onFrame(n));
934
+ }, t.onclose = () => this.unavailable(/* @__PURE__ */ Error("swarm peer data channel closed")), t.onerror = () => this.unavailable(/* @__PURE__ */ Error("swarm peer data channel failed")), this.resolveReadyIfOpen();
935
+ }
936
+ allPeersOpen() {
937
+ return this.peers.size ? [...this.peers.values()].every((e) => e.channel?.readyState === "open") : !1;
938
+ }
939
+ resolveReadyIfOpen() {
940
+ this.allPeersOpen() && this.resolveReady(!0);
941
+ }
942
+ resolveReady(e) {
943
+ this.readyTimer && clearTimeout(this.readyTimer), this.readyTimer = null;
944
+ let t = this.readyResolve;
945
+ this.readyResolve = null, t?.(e && !this.failed && !this.closed);
946
+ }
947
+ unavailable(e = /* @__PURE__ */ Error("swarm peer link unavailable")) {
948
+ this.closed || this.failed || (this.failed = !0, this.stopQualitySampling(), this.resolveReady(!1), this.mode === "peer" && this.options.onFailure(e));
949
+ }
950
+ async waitForBuffer(e) {
951
+ e.bufferedAmount <= 262144 || await new Promise((t, n) => {
952
+ let r = setTimeout(() => i(/* @__PURE__ */ Error("swarm peer send buffer stalled")), xt), i = (i) => {
953
+ clearTimeout(r), e.removeEventListener("bufferedamountlow", a), e.removeEventListener("close", o), i ? n(i) : t();
954
+ }, a = () => i(), o = () => i(/* @__PURE__ */ Error("swarm peer data channel closed while backpressured"));
955
+ e.addEventListener("bufferedamountlow", a, { once: !0 }), e.addEventListener("close", o, { once: !0 });
956
+ });
957
+ }
958
+ closePeerConnections() {
959
+ this.stopQualitySampling();
960
+ for (let e of this.peers.values()) e.channel?.close(), e.connection.close();
961
+ this.peers.clear();
962
+ }
963
+ startQualitySampling() {
964
+ this.qualityTimer || !this.options.onQuality || (this.samplePeerQuality(), this.qualityTimer = setInterval(() => void this.samplePeerQuality(), _t));
965
+ }
966
+ stopQualitySampling() {
967
+ this.qualityTimer && clearInterval(this.qualityTimer), this.qualityTimer = null;
968
+ for (let e of this.peers.values()) e.pendingProbe = void 0;
969
+ }
970
+ wallNow() {
971
+ return this.options.now?.() ?? Date.now();
972
+ }
973
+ monotonicNow() {
974
+ return this.options.monotonicNow?.() ?? (typeof performance < "u" ? performance.now() : Date.now());
975
+ }
976
+ recordQuality(e, t, n, r) {
977
+ if (!Number.isFinite(r) || r < 0) return;
978
+ let i = e.quality[t][n], a = this.wallNow(), o = e.qualitySampledAt[t][n];
979
+ o !== void 0 && a - o >= 6e4 && (i.length = 0), i.push(r), e.qualitySampledAt[t][n] = a, i.length > 5 && i.splice(0, i.length - 5);
980
+ }
981
+ sendQualityProbe(e) {
982
+ let t = e.channel;
983
+ if (e.pendingProbe && this.monotonicNow() - e.pendingProbe.sentAt > 15e3 * 2 && (e.pendingProbe = void 0), !t || t.readyState !== "open" || t.bufferedAmount > 262144 || e.pendingProbe) return;
984
+ let n = e.nextProbeId++;
985
+ e.pendingProbe = {
986
+ id: n,
987
+ sentAt: this.monotonicNow()
988
+ };
989
+ try {
990
+ t.send(JSON.stringify({
991
+ type: Ot,
992
+ kind: "ping",
993
+ id: n
994
+ }));
995
+ } catch {
996
+ e.pendingProbe = void 0;
997
+ }
998
+ }
999
+ handleQualityProbe(e, t) {
1000
+ if (t.length > kt) return;
1001
+ let n;
1002
+ try {
1003
+ let e = JSON.parse(t);
1004
+ if (!e || typeof e != "object" || Array.isArray(e)) return;
1005
+ n = e;
1006
+ } catch {
1007
+ return;
1008
+ }
1009
+ if (n.type !== Ot || !Number.isSafeInteger(n.id) || n.id < 1) return;
1010
+ if (n.kind === "ping") {
1011
+ if (e.channel?.readyState !== "open" || e.channel.bufferedAmount > 262144) return;
1012
+ try {
1013
+ e.channel.send(JSON.stringify({
1014
+ type: Ot,
1015
+ kind: "pong",
1016
+ id: n.id
1017
+ }));
1018
+ } catch {}
1019
+ return;
1020
+ }
1021
+ let r = e.pendingProbe;
1022
+ if (n.kind !== "pong" || !r || r.id !== n.id) return;
1023
+ e.pendingProbe = void 0;
1024
+ let i = Math.max(0, this.monotonicNow() - r.sentAt);
1025
+ this.recordQuality(e, "application", "rttMs", i), e.lastApplicationRttMs !== void 0 && this.recordQuality(e, "application", "jitterMs", Math.abs(i - e.lastApplicationRttMs)), e.lastApplicationRttMs = i;
1026
+ }
1027
+ async samplePeerQuality() {
1028
+ if (!(this.closed || this.failed || this.mode !== "peer" || !this.options.onQuality || this.samplingQuality)) {
1029
+ this.samplingQuality = !0;
1030
+ try {
1031
+ let e = this.wallNow(), t = [];
1032
+ for (let n of this.peers.values()) {
1033
+ if (n.channel?.readyState !== "open") continue;
1034
+ this.sendQualityProbe(n);
1035
+ let r = this.monotonicNow();
1036
+ if (await this.sampleWebRtc(n, r), n.lastApplicationSampleAt !== void 0) {
1037
+ let e = r - n.lastApplicationSampleAt, t = K(n.applicationBytesSent - n.lastApplicationBytesSent, e), i = K(n.applicationBytesReceived - n.lastApplicationBytesReceived, e);
1038
+ t !== null && this.recordQuality(n, "application", "sendMbps", t), i !== null && this.recordQuality(n, "application", "receiveMbps", i);
1039
+ }
1040
+ n.lastApplicationSampleAt = r, n.lastApplicationBytesSent = n.applicationBytesSent, n.lastApplicationBytesReceived = n.applicationBytesReceived, t.push(bt(n.nodeId, e, n.quality.webRtc, n.quality.application, n.qualitySampledAt));
1041
+ }
1042
+ t.length && this.options.onQuality(t.slice(0, 2));
1043
+ } finally {
1044
+ this.samplingQuality = !1;
1045
+ }
1046
+ }
1047
+ }
1048
+ async sampleWebRtc(e, t) {
1049
+ try {
1050
+ let n = await e.connection.getStats(), r = [];
1051
+ n.forEach((e) => r.push(e));
1052
+ let i = r.filter((e) => e.type === "candidate-pair" && e.state === "succeeded"), a = i.find((e) => e.selected === !0) ?? i.find((e) => e.nominated === !0) ?? i[0], o = a?.currentRoundTripTime;
1053
+ typeof o == "number" && Number.isFinite(o) && o >= 0 && this.recordQuality(e, "webRtc", "rttMs", o * 1e3);
1054
+ let s = a?.availableOutgoingBitrate;
1055
+ typeof s == "number" && Number.isFinite(s) && s >= 0 && this.recordQuality(e, "webRtc", "sendMbps", s / 1e6);
1056
+ let c = a?.availableIncomingBitrate;
1057
+ typeof c == "number" && Number.isFinite(c) && c >= 0 && this.recordQuality(e, "webRtc", "receiveMbps", c / 1e6);
1058
+ let l = r.filter((e) => e.type === "data-channel"), u = (e) => {
1059
+ let t = l.map((t) => t[e]).filter((e) => typeof e == "number" && Number.isFinite(e) && e >= 0);
1060
+ return t.length ? t.reduce((e, t) => e + t, 0) : void 0;
1061
+ }, d = u("bytesSent"), f = u("bytesReceived");
1062
+ if (e.lastRtcSampleAt !== void 0) {
1063
+ let n = t - e.lastRtcSampleAt;
1064
+ if (d !== void 0 && e.lastRtcBytesSent !== void 0 && s === void 0) {
1065
+ let t = K(d - e.lastRtcBytesSent, n);
1066
+ t !== null && this.recordQuality(e, "webRtc", "sendMbps", t);
1067
+ }
1068
+ if (f !== void 0 && e.lastRtcBytesReceived !== void 0 && c === void 0) {
1069
+ let t = K(f - e.lastRtcBytesReceived, n);
1070
+ t !== null && this.recordQuality(e, "webRtc", "receiveMbps", t);
1071
+ }
1072
+ }
1073
+ d !== void 0 && (e.lastRtcBytesSent = d), f !== void 0 && (e.lastRtcBytesReceived = f), e.lastRtcSampleAt = t;
1074
+ } catch {}
1075
+ }
1076
+ };
1077
+ function It(e, t) {
1078
+ if (!h(e)) return !1;
1079
+ let n = e;
1080
+ return n.type === "swarm-peer-signal" && n.taskId === t.taskId && n.sessionId === t.sessionId && n.attemptId === t.attemptId && n.toNodeId === t.nodeId && typeof n.fromNodeId == "string" && t.peers.includes(n.fromNodeId) && typeof n.signal == "object" && n.signal !== null;
1081
+ }
1082
+ //#endregion
1083
+ //#region src/client/mobile-lifecycle.ts
1084
+ var Lt = .25, Rt = .08, zt = .45;
1085
+ function Bt(e, t) {
1086
+ let n = e.batteryCharging === !1, r = n && typeof e.batteryLevel == "number" && e.batteryLevel <= Lt, i = n && typeof e.batteryLevel == "number" && e.batteryLevel <= Rt, a = e.effectiveType === "slow-2g" || e.effectiveType === "2g", o = r || a || e.saveData === !0;
1087
+ return {
1088
+ suspend: e.hidden || e.pageHidden || !e.online || i,
1089
+ constrained: o,
1090
+ maxCpuLoad: o ? Math.min(t ?? zt, zt) : t
1091
+ };
1092
+ }
1093
+ //#endregion
1094
+ //#region src/client/SignalingClient.ts
1095
+ var Y = (...e) => console.log("[flaxia-node]", ...e), X = (...e) => console.error("[flaxia-node]", ...e);
605
1096
  function Z(e) {
606
1097
  let t = /* @__PURE__ */ new Set();
607
1098
  if (!Array.isArray(e)) return [];
608
1099
  for (let n of e.slice(0, 32)) try {
609
- let e = l(n);
1100
+ let e = _(n);
610
1101
  e.origin === n && t.add(e.origin);
611
1102
  } catch {}
612
1103
  return [...t];
613
1104
  }
614
- var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
1105
+ var Vt = "flaxia_node_id", Q = "flaxia_node_token", Ht = class {
1106
+ receiveSwarmEnvelope(t) {
1107
+ let n = e(t);
1108
+ !n || ![...this.swarmSessions.values()].includes(n.sessionId) || (this.swarmInboundChain = this.swarmInboundChain.then(async () => {
1109
+ let e = this.swarmHopKeys.get(n.sessionId);
1110
+ if (e && e.chainLength > 1) {
1111
+ if (!n.mac || !e.inboundKey) return;
1112
+ if (!await a(e.inboundKey, n.sessionId, n.frame, n.mac)) {
1113
+ X(`swarm frame rejected: bad hop MAC sessionId=${n.sessionId}`);
1114
+ return;
1115
+ }
1116
+ }
1117
+ this.workerPool.sendFrame(n.frame);
1118
+ }).catch(() => {}));
1119
+ }
1120
+ ensureSwarmPeerTransport(e) {
1121
+ let t = typeof e.sessionId == "string" ? e.sessionId : "", n = typeof e.taskId == "string" ? e.taskId : "", r = typeof e.attemptId == "string" ? e.attemptId : "";
1122
+ if (!t || !n || !r || this.swarmPeerTransports.has(t)) return;
1123
+ let i = typeof e.previousNodeId == "string" ? e.previousNodeId : void 0, a = typeof e.nextNodeId == "string" ? e.nextNodeId : void 0, o = [...new Set([i, a].filter((e) => !!e))];
1124
+ this.swarmPeerMetadata.set(t, {
1125
+ taskId: n,
1126
+ attemptId: r,
1127
+ peers: o
1128
+ });
1129
+ let s = new Ft({
1130
+ sessionId: t,
1131
+ taskId: n,
1132
+ attemptId: r,
1133
+ nodeId: this.nodeId,
1134
+ previousNodeId: i,
1135
+ nextNodeId: a,
1136
+ onSignal: (e, i) => this.send({
1137
+ type: "swarm-peer-signal",
1138
+ taskId: n,
1139
+ sessionId: t,
1140
+ attemptId: r,
1141
+ toNodeId: e,
1142
+ signal: i
1143
+ }),
1144
+ onFrame: (e) => this.receiveSwarmEnvelope(e),
1145
+ onQuality: (e) => this.send({
1146
+ type: "swarm-peer-quality",
1147
+ taskId: n,
1148
+ sessionId: t,
1149
+ attemptId: r,
1150
+ reports: e
1151
+ }),
1152
+ onFailure: (e) => {
1153
+ this.swarmFailureReported.add(t), this.send({
1154
+ type: "swarm-error",
1155
+ taskId: n,
1156
+ sessionId: t,
1157
+ attemptId: r,
1158
+ error: e.message
1159
+ });
1160
+ }
1161
+ });
1162
+ this.swarmPeerTransports.set(t, s), s.start();
1163
+ }
1164
+ handleSwarmPeerSignal(e) {
1165
+ let t = typeof e.sessionId == "string" ? e.sessionId : "", n = this.swarmPeerMetadata.get(t), r = this.swarmPeerTransports.get(t);
1166
+ !n || !r || !It(e, {
1167
+ ...n,
1168
+ sessionId: t,
1169
+ nodeId: this.nodeId
1170
+ }) || r.handleSignal(e.fromNodeId, e.signal);
1171
+ }
615
1172
  retireSwarmSession(e) {
616
- this.swarmHopKeys.delete(e), this.retiredSwarmSessions.add(e), this.retiredSwarmSessions.size > 64 && this.retiredSwarmSessions.delete(this.retiredSwarmSessions.values().next().value);
1173
+ this.swarmHopKeys.delete(e), this.swarmPeerTransports.get(e)?.close(), this.swarmPeerTransports.delete(e), this.swarmPeerMetadata.delete(e), this.swarmFailureReported.delete(e), this.retiredSwarmSessions.add(e), this.retiredSwarmSessions.size > 64 && this.retiredSwarmSessions.delete(this.retiredSwarmSessions.values().next().value);
617
1174
  }
618
1175
  constructor(e, t, n) {
619
- 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(), this.abortedTasks = /* @__PURE__ */ new Set(), this.swarmSessions = /* @__PURE__ */ new Map(), this.retiredSwarmSessions = /* @__PURE__ */ new Set(), this.swarmHopKeys = /* @__PURE__ */ new Map(), this.swarmInboundChain = Promise.resolve(), this.swarmOutboundChain = Promise.resolve(), this.attempts = /* @__PURE__ */ new Map(), this.cachedToken = null;
1176
+ 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.lifecycleCleanup = [], this.lifecyclePageHidden = !1, this.lifecycleOffline = !1, this.lifecycleEpoch = 0, this.batteryState = null, this.networkState = null, this.inflightTasks = /* @__PURE__ */ new Set(), this.abortedTasks = /* @__PURE__ */ new Set(), this.swarmSessions = /* @__PURE__ */ new Map(), this.retiredSwarmSessions = /* @__PURE__ */ new Set(), this.swarmHopKeys = /* @__PURE__ */ new Map(), this.swarmPeerTransports = /* @__PURE__ */ new Map(), this.swarmPeerMetadata = /* @__PURE__ */ new Map(), this.swarmFailureReported = /* @__PURE__ */ new Set(), this.swarmInboundChain = Promise.resolve(), this.swarmOutboundChain = Promise.resolve(), this.attempts = /* @__PURE__ */ new Map(), this.cachedToken = null;
620
1177
  }
621
1178
  async connect() {
622
1179
  if (this.destroyed) return;
623
- if (H() !== "granted") {
1180
+ if (z() !== "granted") {
624
1181
  this.disconnect();
625
1182
  return;
626
1183
  }
@@ -632,102 +1189,109 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
632
1189
  } catch {}
633
1190
  this.ws = null;
634
1191
  }
635
- this.setupVisibilityHandler();
636
- let r = await this.obtainToken();
637
- if (H() !== "granted") {
1192
+ if (this.setupMobileLifecycleHandlers(), this.suspended) return;
1193
+ let e = await this.obtainToken();
1194
+ if (this.destroyed || this.suspended) return;
1195
+ if (z() !== "granted") {
638
1196
  Y("connect cancelled because consent was revoked while obtaining a token");
639
1197
  return;
640
1198
  }
641
- if (!r) {
1199
+ if (!e) {
642
1200
  X("token acquisition failed; scheduling reconnect"), this.scheduleReconnect();
643
1201
  return;
644
1202
  }
645
- let i = e(this.config.orchestratorUrl, "/crowd/signal"), o = new WebSocket(i, a(r.token));
646
- o.binaryType = "arraybuffer", this.ws = o;
647
- let s = !1;
648
- o.onopen = () => {
649
- s = !0, this.reconnectAttempts = 0, Y(`signal connected ${i}`);
650
- }, o.onmessage = async (e) => {
651
- if (this.ws !== o) return;
1203
+ let t = i(this.config.orchestratorUrl, "/crowd/signal"), n = new WebSocket(t, s(e.token));
1204
+ n.binaryType = "arraybuffer", this.ws = n;
1205
+ let r = !1;
1206
+ n.onopen = () => {
1207
+ r = !0, this.reconnectAttempts = 0, Y(`signal connected ${t}`), this.sendHeartbeat(n);
1208
+ }, n.onmessage = async (e) => {
1209
+ if (this.ws !== n) return;
652
1210
  if (typeof e.data != "string") {
653
- let r = n(e.data);
654
- if (!r || ![...this.swarmSessions.values()].includes(r.sessionId)) return;
655
- this.swarmInboundChain = this.swarmInboundChain.then(async () => {
656
- let e = this.swarmHopKeys.get(r.sessionId);
657
- if (e && e.chainLength > 1) {
658
- if (!r.mac || !e.inboundKey) return;
659
- if (!await t(e.inboundKey, r.sessionId, r.frame, r.mac)) {
660
- X(`swarm frame rejected: bad hop MAC sessionId=${r.sessionId}`);
661
- return;
662
- }
663
- }
664
- this.workerPool.sendFrame(r.frame);
665
- }).catch(() => {});
1211
+ this.receiveSwarmEnvelope(e.data);
666
1212
  return;
667
1213
  }
668
- let r;
1214
+ let t;
669
1215
  try {
670
- r = JSON.parse(e.data);
1216
+ t = JSON.parse(e.data);
671
1217
  } catch {
672
1218
  return;
673
1219
  }
674
- if (r.type === "ping") {
675
- this.send({
676
- type: "pong",
677
- cpuLoad: this.workerPool.lastCpuLoad
678
- });
1220
+ if (t.type === "ping") {
1221
+ this.sendHeartbeat(n);
679
1222
  return;
680
1223
  }
681
- if (r.type === "task") {
682
- let e = r;
1224
+ if (t.type === "task") {
1225
+ let e = t;
683
1226
  Y(`task received taskId=${e.taskId} workload=${e.workload} timeoutMs=${e.timeoutMs ?? "default"}`), typeof e.attemptId == "string" && this.attempts.set(e.taskId, e.attemptId);
684
- let t = e.attemptId ?? this.attempts.get(e.taskId);
1227
+ let n = e.attemptId ?? this.attempts.get(e.taskId);
685
1228
  try {
686
1229
  await this.handleTask(e);
687
- } catch (n) {
688
- let i = n instanceof Error ? n.message : String(n);
1230
+ } catch (r) {
1231
+ let i = r instanceof Error ? r.message : String(r);
689
1232
  if (this.abortedTasks.delete(e.taskId)) {
690
1233
  Y(`task stopped on coordinator abort taskId=${e.taskId} error=${i}`);
691
1234
  return;
692
1235
  }
693
1236
  X(`task failed taskId=${e.taskId} workload=${e.workload} error=${i}`), this.send({
694
1237
  type: "error",
695
- taskId: String(r.taskId ?? ""),
1238
+ taskId: String(t.taskId ?? ""),
696
1239
  error: i,
697
- attemptId: t
1240
+ attemptId: n
698
1241
  });
699
1242
  }
700
1243
  return;
701
1244
  }
702
- if (r.type === "swarm-init" || r.type === "swarm-slice") {
703
- let e = String(r.taskId ?? "");
704
- if (!e || typeof r.sessionId != "string" || this.retiredSwarmSessions.has(r.sessionId)) return;
705
- if (r.type === "swarm-slice" && this.swarmHopKeys.set(r.sessionId, {
706
- inboundKey: typeof r.inboundKey == "string" ? r.inboundKey : void 0,
707
- outboundKey: typeof r.outboundKey == "string" ? r.outboundKey : void 0,
708
- chainLength: typeof r.chainLength == "number" ? r.chainLength : 1
709
- }), typeof r.attemptId == "string" && this.attempts.set(e, r.attemptId), this.swarmSessions.get(e) === r.sessionId) {
710
- this.workerPool.sendControl(r, r.sessionId);
1245
+ if (t.type === "swarm-init" || t.type === "swarm-slice") {
1246
+ let e = String(t.taskId ?? "");
1247
+ if (!e || typeof t.sessionId != "string" || this.retiredSwarmSessions.has(t.sessionId)) return;
1248
+ if (t.type === "swarm-slice" && (this.ensureSwarmPeerTransport(t), this.swarmHopKeys.set(t.sessionId, {
1249
+ inboundKey: typeof t.inboundKey == "string" ? t.inboundKey : void 0,
1250
+ outboundKey: typeof t.outboundKey == "string" ? t.outboundKey : void 0,
1251
+ chainLength: typeof t.chainLength == "number" ? t.chainLength : 1
1252
+ })), typeof t.attemptId == "string" && this.attempts.set(e, t.attemptId), this.swarmSessions.get(e) === t.sessionId) {
1253
+ this.workerPool.sendControl(t, t.sessionId);
711
1254
  return;
712
1255
  }
713
- this.startSwarm(e, r);
1256
+ this.startSwarm(e, t);
1257
+ return;
1258
+ }
1259
+ if (t.type === "swarm-peer-signal") {
1260
+ this.handleSwarmPeerSignal(t);
1261
+ return;
1262
+ }
1263
+ if (t.type === "swarm-transport") {
1264
+ let e = typeof t.sessionId == "string" ? t.sessionId : "", n = this.swarmPeerMetadata.get(e), r = this.swarmPeerTransports.get(e);
1265
+ n && r && t.taskId === n.taskId && t.attemptId === n.attemptId && (t.mode === "peer" || t.mode === "relay") && r.selectMode(t.mode);
1266
+ return;
1267
+ }
1268
+ if (t.type === "swarm-flow") {
1269
+ let e = typeof t.taskId == "string" ? t.taskId : "", n = typeof t.sessionId == "string" ? t.sessionId : "", r = typeof t.attemptId == "string" ? t.attemptId : "";
1270
+ e && n && this.swarmSessions.get(e) === n && this.attempts.get(e) === r && typeof t.paused == "boolean" && this.workerPool.sendControl(t, n);
714
1271
  return;
715
1272
  }
716
- if (r.type === "swarm-start") {
717
- this.swarmSessions.get(String(r.taskId)) === r.sessionId && this.workerPool.sendControl(r, r.sessionId);
1273
+ if (t.type === "task-flow") {
1274
+ let e = typeof t.taskId == "string" ? t.taskId : "", n = typeof t.attemptId == "string" ? t.attemptId : "";
1275
+ e && this.attempts.get(e) === n && typeof t.paused == "boolean" && this.workerPool.setTokenFlow(e, t.paused);
718
1276
  return;
719
1277
  }
720
- if (r.type === "swarm-error") {
721
- let e = String(r.taskId ?? "");
722
- e && this.swarmSessions.get(e) === r.sessionId && this.workerPool.sendControl(r, r.sessionId);
1278
+ if (t.type === "swarm-start") {
1279
+ this.swarmSessions.get(String(t.taskId)) === t.sessionId && this.workerPool.sendControl(t, t.sessionId);
723
1280
  return;
724
1281
  }
725
- if (r.type === "abort") {
726
- this.handleAbort(r);
1282
+ if (t.type === "swarm-error") {
1283
+ let e = String(t.taskId ?? "");
1284
+ e && this.swarmSessions.get(e) === t.sessionId && this.workerPool.sendControl(t, t.sessionId);
727
1285
  return;
728
1286
  }
729
- }, o.onclose = () => {
730
- o.onclose = null, this.ws === o && (this.ws = null, s || (this.cachedToken = null), !this.destroyed && (Y(`signal disconnected; scheduling reconnect attempt=${this.reconnectAttempts + 1}`), this.scheduleReconnect()));
1287
+ if (t.type === "abort") {
1288
+ this.handleAbort(t);
1289
+ return;
1290
+ }
1291
+ }, n.onerror = () => {
1292
+ this.ws === n && X("signal websocket error");
1293
+ }, n.onclose = (e) => {
1294
+ n.onclose = null, this.ws === n && (this.ws = null, r || (this.cachedToken = null), !this.destroyed && (Y(`signal disconnected code=${e.code} reason=${JSON.stringify(e.reason)} clean=${e.wasClean}; scheduling reconnect attempt=${this.reconnectAttempts + 1}`), this.scheduleReconnect()));
731
1295
  };
732
1296
  }
733
1297
  handleAbort(e) {
@@ -738,6 +1302,20 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
738
1302
  let i = r ?? t;
739
1303
  r && this.retireSwarmSession(r), this.workerPool.abort(i, n) && this.abortedTasks.add(i), Y(`task abort received taskId=${t} error=${n}`);
740
1304
  }
1305
+ async sendHeartbeat(e) {
1306
+ if (this.ws !== e || e.readyState !== WebSocket.OPEN || z() !== "granted") return;
1307
+ let t = (this.config.capabilities ?? ["ai-inference", "image-process"]).includes("swarm-inference") && this.config.allowModelDownload === !0, n = navigator.deviceMemory, r = await gt({
1308
+ cpuLoad: this.workerPool.hasCpuLoadSample ? this.workerPool.lastCpuLoad : null,
1309
+ deviceMemory: n,
1310
+ probeGpu: t
1311
+ });
1312
+ this.ws !== e || e.readyState !== WebSocket.OPEN || z() !== "granted" || this.send({
1313
+ type: "pong",
1314
+ cpuLoad: this.workerPool.hasCpuLoadSample ? this.workerPool.lastCpuLoad : null,
1315
+ resources: r,
1316
+ modelCache: this.workerPool.modelCacheSnapshot
1317
+ });
1318
+ }
741
1319
  scheduleReconnect() {
742
1320
  let e = Math.min(1e3 * 2 ** this.reconnectAttempts, this.MAX_RECONNECT_DELAY);
743
1321
  setTimeout(() => {
@@ -745,13 +1323,15 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
745
1323
  }, e);
746
1324
  }
747
1325
  disconnect() {
748
- Y(`disconnect nodeId=${this.nodeId}`), this.destroyed = !0, this.suspended = !1, this.removeVisibilityHandler();
1326
+ Y(`disconnect nodeId=${this.nodeId}`), this.destroyed = !0, this.suspended = !1, this.removeMobileLifecycleHandlers();
749
1327
  try {
750
1328
  this.ws?.close();
751
1329
  } catch {}
752
1330
  this.ws = null;
1331
+ for (let e of this.swarmPeerTransports.values()) e.close();
1332
+ this.swarmPeerTransports.clear(), this.swarmPeerMetadata.clear();
753
1333
  try {
754
- delete window[$];
1334
+ delete window[Ut];
755
1335
  } catch {}
756
1336
  try {
757
1337
  this.workerPool.terminate();
@@ -774,36 +1354,41 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
774
1354
  !this.suspended || this.destroyed || (Y("resumed"), this.suspended = !1, this.workerPool.resume(), this.connect());
775
1355
  }
776
1356
  async obtainToken() {
777
- let e = () => H() === "granted";
1357
+ let e = () => z() === "granted";
778
1358
  if (!e()) return null;
779
1359
  try {
780
1360
  if (this.cachedToken && this.cachedToken.expiresAt > Date.now() + 6e4) return Y(`token cached nodeId=${this.cachedToken.nodeId} expiresIn=${Math.round((this.cachedToken.expiresAt - Date.now()) / 1e3)}s`), this.cachedToken;
781
- let t = s(), n = t >= c, r = this.config.capabilities ?? ["ai-inference", "image-process"], i = n ? [...r] : [];
1361
+ let t = f(), n = t >= m, r = this.config.capabilities ?? ["ai-inference", "image-process"], i = n ? [...r] : [];
782
1362
  Z(this.config.containerImageOrigins).length === 0 && (i = i.filter((e) => e !== "container"));
783
1363
  let a;
784
1364
  if (n && r.includes("swarm-inference") && this.config.allowModelDownload === !0) {
785
- if (a = await o(), !e()) return null;
786
- a.webgpu || (i = i.filter((e) => e !== "swarm-inference"), a = void 0);
1365
+ let t = await gt({
1366
+ cpuLoad: this.workerPool.hasCpuLoadSample ? this.workerPool.lastCpuLoad : null,
1367
+ deviceMemory: navigator.deviceMemory,
1368
+ probeGpu: !0
1369
+ });
1370
+ if (!e()) return null;
1371
+ t.gpu.status === "available" ? (a = { webgpu: !0 }, t.gpu.architecture.value && (a.gpuArchitecture = t.gpu.architecture.value), t.gpu.maxStorageBufferBindingSize.value !== null && (a.maxStorageBufferBindingSize = t.gpu.maxStorageBufferBindingSize.value)) : i = i.filter((e) => e !== "swarm-inference");
787
1372
  } else i = i.filter((e) => e !== "swarm-inference");
788
1373
  Y(`register capability probe capable=${n} wasmMemoryBytes=${t} capabilities=${JSON.stringify(i)} webgpu=${a?.webgpu ?? !1}`);
789
- let l = this.config.orchestratorUrl.replace(/\/+$/, "");
1374
+ let o = this.config.orchestratorUrl.replace(/\/+$/, "");
790
1375
  if (!e()) return null;
791
- let u = await fetch(`${l}/crowd/nodes/register`, {
1376
+ let s = await fetch(`${o}/crowd/nodes/register`, {
792
1377
  method: "POST",
793
1378
  headers: { "Content-Type": "application/json" },
794
1379
  body: JSON.stringify({
795
1380
  siteId: this.config.siteId,
796
1381
  capabilities: i,
797
1382
  fileSources: Z(this.config.fileSourceOrigins).length > 0,
798
- wasmMemoryBytes: s(),
1383
+ wasmMemoryBytes: f(),
799
1384
  deviceMemory: typeof navigator.deviceMemory == "number" ? navigator.deviceMemory : null,
800
1385
  swarm: a
801
1386
  })
802
1387
  });
803
1388
  if (!e()) return null;
804
- if (!u.ok) return X(`node register failed HTTP ${u.status} (${l}/crowd/nodes/register)`), null;
805
- let d = await u.json();
806
- return e() ? d.token ? (typeof d.nodeId == "string" && d.nodeId && (this.nodeId = d.nodeId), this.cachedToken = d, Y(`node registered nodeId=${this.nodeId} expiresIn=${Math.round((d.expiresAt - Date.now()) / 1e3)}s`), d) : (X("node register returned no token"), null) : null;
1389
+ if (!s.ok) return X(`node register failed HTTP ${s.status} (${o}/crowd/nodes/register)`), null;
1390
+ let c = await s.json();
1391
+ return e() ? c.token ? (typeof c.nodeId == "string" && c.nodeId && (this.nodeId = c.nodeId), this.cachedToken = c, Y(`node registered nodeId=${this.nodeId} expiresIn=${Math.round((c.expiresAt - Date.now()) / 1e3)}s`), c) : (X("node register returned no token"), null) : null;
807
1392
  } catch (e) {
808
1393
  return X("node register threw", e instanceof Error ? e.message : e), null;
809
1394
  }
@@ -822,11 +1407,22 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
822
1407
  X(`swarm frame not sent: no hop key sessionId=${e}`);
823
1408
  return;
824
1409
  }
825
- this.sendBinary(await r(n.outboundKey, e, t));
1410
+ let i = await r(n.outboundKey, e, t), a = this.swarmPeerTransports.get(e);
1411
+ (!a || !await a.sendFrame(i)) && this.sendBinary(i);
826
1412
  return;
827
1413
  }
828
- this.sendBinary(i(e, t));
829
- }).catch(() => {});
1414
+ let i = c(e, t), a = this.swarmPeerTransports.get(e);
1415
+ (!a || !await a.sendFrame(i)) && this.sendBinary(i);
1416
+ }).catch((t) => {
1417
+ let n = this.swarmPeerMetadata.get(e);
1418
+ !n || this.swarmFailureReported.has(e) || (this.swarmFailureReported.add(e), this.send({
1419
+ type: "swarm-error",
1420
+ taskId: n.taskId,
1421
+ sessionId: e,
1422
+ attemptId: n.attemptId,
1423
+ error: t instanceof Error ? t.message : String(t)
1424
+ }));
1425
+ });
830
1426
  }
831
1427
  async startSwarm(e, t) {
832
1428
  let n = t.sessionId;
@@ -842,12 +1438,26 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
842
1438
  token: t,
843
1439
  attemptId: a
844
1440
  });
845
- }, { maxCpuLoad: this.config.maxCpuLoad }, {
1441
+ }, { maxCpuLoad: this.effectiveMaxCpuLoad() }, {
846
1442
  onFrame: (e) => this.queueSwarmFrame(n, e),
847
- onMessage: (e) => this.send(e && typeof e == "object" && !("attemptId" in e) ? {
848
- ...e,
849
- attemptId: a
850
- } : e)
1443
+ onMessage: (e) => {
1444
+ let t = e && typeof e == "object" && !("attemptId" in e) ? {
1445
+ ...e,
1446
+ attemptId: a
1447
+ } : e;
1448
+ if (t?.type === "swarm-ready") {
1449
+ let e = this.swarmPeerTransports.get(n);
1450
+ (async () => {
1451
+ let n = e ? await e.waitUntilReady() : !1;
1452
+ this.send({
1453
+ ...t,
1454
+ peerReady: n
1455
+ });
1456
+ })();
1457
+ return;
1458
+ }
1459
+ this.send(t);
1460
+ }
851
1461
  });
852
1462
  this.abortedTasks.delete(n) || this.send({
853
1463
  type: "result",
@@ -882,7 +1492,7 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
882
1492
  attemptId: n
883
1493
  });
884
1494
  }, {
885
- maxCpuLoad: this.config.maxCpuLoad,
1495
+ maxCpuLoad: this.effectiveMaxCpuLoad(),
886
1496
  fileSourceOrigins: Z(this.config.fileSourceOrigins),
887
1497
  containerImageOrigins: Z(this.config.containerImageOrigins)
888
1498
  });
@@ -896,74 +1506,116 @@ var et = "flaxia_node_id", tt = "flaxia_node_token", nt = class {
896
1506
  this.inflightTasks.delete(e.taskId), this.attempts.delete(e.taskId);
897
1507
  }
898
1508
  }
899
- setupVisibilityHandler() {
900
- this.removeVisibilityHandler(), this.visibilityHandler = () => {
901
- document.hidden ? this.suspend() : this.suspended && this.resume();
902
- }, document.addEventListener("visibilitychange", this.visibilityHandler);
1509
+ listenForLifecycle(e, t, n) {
1510
+ e.addEventListener(t, n), this.lifecycleCleanup.push(() => e.removeEventListener(t, n));
1511
+ }
1512
+ setupMobileLifecycleHandlers() {
1513
+ this.removeMobileLifecycleHandlers();
1514
+ let e = this.lifecycleEpoch;
1515
+ this.lifecyclePageHidden = document.hidden, this.lifecycleOffline = navigator.onLine === !1;
1516
+ let t = navigator;
1517
+ if (this.networkState = t.connection ?? null, this.listenForLifecycle(document, "visibilitychange", () => {
1518
+ this.lifecyclePageHidden = document.hidden, this.refreshMobileLifecycle();
1519
+ }), this.listenForLifecycle(window, "offline", () => {
1520
+ this.lifecycleOffline = !0, this.refreshMobileLifecycle();
1521
+ }), this.listenForLifecycle(window, "online", () => {
1522
+ this.lifecycleOffline = !1, this.refreshMobileLifecycle();
1523
+ }), this.listenForLifecycle(window, "pagehide", () => {
1524
+ this.lifecyclePageHidden = !0, this.refreshMobileLifecycle();
1525
+ }), this.listenForLifecycle(window, "pageshow", () => {
1526
+ this.lifecyclePageHidden = !1, this.refreshMobileLifecycle();
1527
+ }), this.networkState && this.listenForLifecycle(this.networkState, "change", () => this.refreshMobileLifecycle()), typeof t.getBattery == "function") try {
1528
+ t.getBattery.call(navigator).then((t) => {
1529
+ if (this.destroyed || e !== this.lifecycleEpoch) return;
1530
+ this.batteryState = t;
1531
+ let n = () => this.refreshMobileLifecycle();
1532
+ this.listenForLifecycle(t, "levelchange", n), this.listenForLifecycle(t, "chargingchange", n), this.refreshMobileLifecycle();
1533
+ }).catch(() => {});
1534
+ } catch {}
1535
+ this.refreshMobileLifecycle();
1536
+ }
1537
+ removeMobileLifecycleHandlers() {
1538
+ this.lifecycleEpoch++;
1539
+ for (let e of this.lifecycleCleanup.splice(0)) e();
1540
+ this.batteryState = null, this.networkState = null;
1541
+ }
1542
+ mobileLifecycleDecision() {
1543
+ return Bt({
1544
+ hidden: document.hidden,
1545
+ pageHidden: this.lifecyclePageHidden,
1546
+ online: !this.lifecycleOffline && navigator.onLine !== !1,
1547
+ batteryLevel: this.batteryState?.level,
1548
+ batteryCharging: this.batteryState?.charging,
1549
+ effectiveType: this.networkState?.effectiveType,
1550
+ saveData: this.networkState?.saveData
1551
+ }, this.config.maxCpuLoad);
903
1552
  }
904
- removeVisibilityHandler() {
905
- this.visibilityHandler &&= (document.removeEventListener("visibilitychange", this.visibilityHandler), null);
1553
+ effectiveMaxCpuLoad() {
1554
+ return this.mobileLifecycleDecision().maxCpuLoad;
906
1555
  }
907
- }, Q = "__flaxia_node_signal_client", $ = "__flaxia_node_init_started", rt = "__flaxia_node_controller", it = (e) => {
908
- if (H() !== "granted") {
1556
+ refreshMobileLifecycle() {
1557
+ this.mobileLifecycleDecision().suspend ? this.suspend() : this.suspended && this.resume();
1558
+ }
1559
+ }, $ = "__flaxia_node_signal_client", Ut = "__flaxia_node_init_started", Wt = "__flaxia_node_controller", Gt = (e) => {
1560
+ if (z() !== "granted") {
909
1561
  X("refusing to start the node without a granted consent record");
910
1562
  return;
911
1563
  }
912
- let t = window[Q];
913
- t && t.disconnect(), K(tt);
914
- let n = new URL("./worker.js", "" + import.meta.url).href, r = new $e(n), i = Ae(et);
915
- i || (i = Ne(), je(et, i));
916
- let a = new nt(e, r, i);
917
- window[Q] = a, a.connect();
918
- }, at = class {
1564
+ let t = window[$];
1565
+ t && t.disconnect(), Ge(Q);
1566
+ let n = new URL("./worker.js", "" + import.meta.url).href, r = new pt(n), i = Ue(Vt);
1567
+ i || (i = qe(), We(Vt, i));
1568
+ let a = new Ht(e, r, i);
1569
+ window[$] = a, a.connect();
1570
+ }, Kt = class {
919
1571
  constructor(e) {
920
1572
  this.config = e;
921
1573
  }
922
1574
  start() {
923
- this.isRunning() || !ye() || it(this.config);
1575
+ this.isRunning() || !Ae() || Gt(this.config);
924
1576
  }
925
1577
  stop() {
926
- let e = window[Q];
927
- e && e.disconnect(), delete window[Q], delete window[$];
1578
+ let e = window[$];
1579
+ e && e.disconnect(), delete window[$], delete window[Ut];
928
1580
  }
929
1581
  isRunning() {
930
- return !!window[Q];
1582
+ return !!window[$];
931
1583
  }
932
1584
  getConsentState() {
933
- return H();
1585
+ return z();
934
1586
  }
935
1587
  grant() {
936
- W();
1588
+ Re();
937
1589
  }
938
1590
  deny() {
939
- G(), this.stop(), K(tt);
1591
+ Ve(), this.stop(), Ge(Q);
940
1592
  }
941
1593
  clearConsent() {
942
- ke(), this.stop(), K(tt);
1594
+ He(), this.stop(), Ge(Q);
943
1595
  }
944
- }, ot = (e) => {
945
- let t = window[rt];
1596
+ }, qt = (e) => {
1597
+ let t = window[Wt];
946
1598
  if (t) return t;
947
- let n = new at(e);
948
- window[rt] = n, window[$] = !0;
949
- let r = H();
1599
+ let n = new Kt(e);
1600
+ window[Wt] = n, window[Ut] = !0;
1601
+ let r = z();
950
1602
  if (r === "granted") return n.start(), n;
951
1603
  if (r === "denied") return n;
952
1604
  if (e.consent.onConsentRequired) return e.consent.onConsentRequired({
953
1605
  state: r,
954
1606
  accept: () => {
955
- W(), n.start();
1607
+ Re(), n.start();
956
1608
  },
957
1609
  reject: () => {
958
- G();
1610
+ Ve();
959
1611
  }
960
1612
  }), n;
961
1613
  let i = document.createElement("div");
962
- return i.id = "flaxia-consent-container", document.body.appendChild(i), new Qe(i, e.consent, () => {
963
- W(), i.remove(), n.start();
1614
+ return i.id = "flaxia-consent-container", document.body.appendChild(i), new ft(i, e.consent, () => {
1615
+ Re(), i.remove(), n.start();
964
1616
  }, () => {
965
- G(), i.remove();
1617
+ Ve(), i.remove();
966
1618
  }), n;
967
1619
  };
968
1620
  //#endregion
969
- export { H as getFlaxiaNodeConsentState, ot as initFlaxiaNode, U as initFlaxiaNodeConsent, Oe as setFlaxiaNodeHostManagedConsent };
1621
+ export { z as getFlaxiaNodeConsentState, qt as initFlaxiaNode, B as initFlaxiaNodeConsent, Be as setFlaxiaNodeHostManagedConsent };