@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.
- package/README.md +43 -19
- package/dist/__tests__/consent-policy.test.d.ts +2 -0
- package/dist/__tests__/consent-policy.test.d.ts.map +1 -0
- package/dist/assets/VectorStoreEngine.js +140 -85
- package/dist/assets/ai-inference.js +336 -40
- package/dist/assets/container.js +368 -260
- package/dist/assets/egress-guard.js +174 -0
- package/dist/assets/image-process.js +184 -19
- package/dist/assets/nudenet.js +2 -2
- package/dist/assets/webgpuProbe.js +357 -0
- package/dist/client/SignalingClient.d.ts +6 -0
- package/dist/client/SignalingClient.d.ts.map +1 -1
- package/dist/client/__tests__/mobile-lifecycle.test.d.ts +2 -0
- package/dist/client/__tests__/mobile-lifecycle.test.d.ts.map +1 -0
- package/dist/client/mobile-lifecycle.d.ts +20 -0
- package/dist/client/mobile-lifecycle.d.ts.map +1 -0
- package/dist/consent/ConsentUI.d.ts +44 -5
- package/dist/consent/ConsentUI.d.ts.map +1 -1
- package/dist/consent/notice.d.ts +29 -0
- package/dist/consent/notice.d.ts.map +1 -0
- package/dist/consent/storage.d.ts +91 -7
- package/dist/consent/storage.d.ts.map +1 -1
- package/dist/executor/WorkerPool.d.ts +42 -2
- package/dist/executor/WorkerPool.d.ts.map +1 -1
- package/dist/executor/__tests__/WorkerPool.swarm.test.d.ts +13 -0
- package/dist/executor/__tests__/WorkerPool.swarm.test.d.ts.map +1 -0
- package/dist/executor/__tests__/container-executor.test.d.ts +2 -0
- package/dist/executor/__tests__/container-executor.test.d.ts.map +1 -0
- package/dist/executor/__tests__/egress-guard.test.d.ts +2 -0
- package/dist/executor/__tests__/egress-guard.test.d.ts.map +1 -0
- package/dist/executor/__tests__/resourceReporter.test.d.ts +2 -0
- package/dist/executor/__tests__/resourceReporter.test.d.ts.map +1 -0
- package/dist/executor/__tests__/webgpuProbe.test.d.ts +2 -0
- package/dist/executor/__tests__/webgpuProbe.test.d.ts.map +1 -0
- package/dist/executor/container-executor.d.ts +49 -1
- package/dist/executor/container-executor.d.ts.map +1 -1
- package/dist/executor/egress-guard.d.ts +105 -0
- package/dist/executor/egress-guard.d.ts.map +1 -0
- package/dist/executor/memoryProbe.d.ts +30 -0
- package/dist/executor/memoryProbe.d.ts.map +1 -1
- package/dist/executor/resourceReporter.d.ts +15 -0
- package/dist/executor/resourceReporter.d.ts.map +1 -0
- package/dist/executor/throttle.d.ts +62 -4
- package/dist/executor/throttle.d.ts.map +1 -1
- package/dist/executor/webgpuProbe.d.ts +20 -0
- package/dist/executor/webgpuProbe.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1423 -235
- package/dist/swarm/__tests__/adapter.test.d.ts +2 -0
- package/dist/swarm/__tests__/adapter.test.d.ts.map +1 -0
- package/dist/swarm/__tests__/controller.test.d.ts +2 -0
- package/dist/swarm/__tests__/controller.test.d.ts.map +1 -0
- package/dist/swarm/__tests__/defects.test.d.ts +16 -0
- package/dist/swarm/__tests__/defects.test.d.ts.map +1 -0
- package/dist/swarm/__tests__/hardening.test.d.ts +2 -0
- package/dist/swarm/__tests__/hardening.test.d.ts.map +1 -0
- package/dist/swarm/__tests__/peer-quality.test.d.ts +2 -0
- package/dist/swarm/__tests__/peer-quality.test.d.ts.map +1 -0
- package/dist/swarm/__tests__/peer-transport.test.d.ts +2 -0
- package/dist/swarm/__tests__/peer-transport.test.d.ts.map +1 -0
- package/dist/swarm/__tests__/runtime.test.d.ts +2 -0
- package/dist/swarm/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/swarm/__tests__/session.test.d.ts +2 -0
- package/dist/swarm/__tests__/session.test.d.ts.map +1 -0
- package/dist/swarm/adapter.d.ts +115 -0
- package/dist/swarm/adapter.d.ts.map +1 -0
- package/dist/swarm/controller.d.ts +91 -0
- package/dist/swarm/controller.d.ts.map +1 -0
- package/dist/swarm/messages.d.ts +41 -0
- package/dist/swarm/messages.d.ts.map +1 -0
- package/dist/swarm/peer-quality.d.ts +14 -0
- package/dist/swarm/peer-quality.d.ts.map +1 -0
- package/dist/swarm/peer-transport.d.ts +81 -0
- package/dist/swarm/peer-transport.d.ts.map +1 -0
- package/dist/swarm/runtime.d.ts +20 -0
- package/dist/swarm/runtime.d.ts.map +1 -0
- package/dist/swarm/session.d.ts +73 -0
- package/dist/swarm/session.d.ts.map +1 -0
- package/dist/swarm-engine.js +7496 -0
- package/dist/vector-store/HNSWIndex.d.ts +30 -0
- package/dist/vector-store/HNSWIndex.d.ts.map +1 -1
- package/dist/vector-store/VectorStoreEngine.d.ts +43 -0
- package/dist/vector-store/VectorStoreEngine.d.ts.map +1 -1
- package/dist/vector-store/__tests__/HNSWIndex.test.d.ts +2 -0
- package/dist/vector-store/__tests__/HNSWIndex.test.d.ts.map +1 -0
- package/dist/vector-store/__tests__/VectorStoreEngine.test.d.ts +2 -0
- package/dist/vector-store/__tests__/VectorStoreEngine.test.d.ts.map +1 -0
- package/dist/worker/__tests__/main.worker.abort.test.d.ts +2 -0
- package/dist/worker/__tests__/main.worker.abort.test.d.ts.map +1 -0
- package/dist/worker/__tests__/main.worker.control.test.d.ts +2 -0
- package/dist/worker/__tests__/main.worker.control.test.d.ts.map +1 -0
- package/dist/worker.js +766 -67
- package/dist/workloads/__tests__/model-pipeline-cache.test.d.ts +2 -0
- package/dist/workloads/__tests__/model-pipeline-cache.test.d.ts.map +1 -0
- package/dist/workloads/__tests__/nudenet.test.d.ts +2 -0
- package/dist/workloads/__tests__/nudenet.test.d.ts.map +1 -0
- package/dist/workloads/ai-inference.d.ts +8 -1
- package/dist/workloads/ai-inference.d.ts.map +1 -1
- package/dist/workloads/ai-model-registry.d.ts +72 -0
- package/dist/workloads/ai-model-registry.d.ts.map +1 -0
- package/dist/workloads/container.d.ts +1 -1
- package/dist/workloads/container.d.ts.map +1 -1
- package/dist/workloads/image-process.d.ts +27 -0
- package/dist/workloads/image-process.d.ts.map +1 -1
- package/dist/workloads/model-pipeline-cache.d.ts +48 -0
- package/dist/workloads/model-pipeline-cache.d.ts.map +1 -0
- package/dist/workloads/nudenet.d.ts +8 -0
- package/dist/workloads/nudenet.d.ts.map +1 -1
- package/package.json +3 -2
- package/dist/assets/memoryProbe.js +0 -28
- package/dist/client/WebRTCPeer.d.ts +0 -8
- package/dist/client/WebRTCPeer.d.ts.map +0 -1
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type { WorkloadType } from "@flaxia/sdk";
|
|
1
|
+
import type { NodeModelCacheSnapshot, WorkloadType } from "@flaxia/sdk";
|
|
2
|
+
/** Swarm tasks exchange control messages and binary frames mid-task. */
|
|
3
|
+
export interface SwarmCallbacks {
|
|
4
|
+
onFrame?: (frame: ArrayBuffer) => void;
|
|
5
|
+
onMessage?: (message: unknown) => void;
|
|
6
|
+
}
|
|
2
7
|
/**
|
|
3
8
|
* Executes tasks against a single Web Worker.
|
|
4
9
|
*
|
|
@@ -16,18 +21,53 @@ export declare class WorkerPool {
|
|
|
16
21
|
private workerUrl;
|
|
17
22
|
private queue;
|
|
18
23
|
private active;
|
|
24
|
+
/** Control messages that arrived for a task that has not started yet. */
|
|
25
|
+
private pendingControls;
|
|
26
|
+
private static readonly MAX_PENDING_CONTROLS;
|
|
19
27
|
private _lastCpuLoad;
|
|
28
|
+
private _hasCpuLoadSample;
|
|
29
|
+
private _modelCacheSnapshot;
|
|
20
30
|
constructor(workerUrl?: string, timeoutMs?: number);
|
|
21
31
|
private initWorker;
|
|
22
32
|
run(id: string, workload: WorkloadType, payload: unknown, timeoutMs?: number, onToken?: (token: string) => void, config?: {
|
|
23
33
|
maxCpuLoad?: number;
|
|
24
|
-
|
|
34
|
+
fileSourceOrigins?: string[];
|
|
35
|
+
containerImageOrigins?: string[];
|
|
36
|
+
}, swarm?: SwarmCallbacks): Promise<unknown>;
|
|
25
37
|
private execute;
|
|
38
|
+
/** Hand over the control messages that were waiting for this task to start. */
|
|
39
|
+
private flushControls;
|
|
40
|
+
/**
|
|
41
|
+
* Post a message to the active task's worker. Used by the signaling client to
|
|
42
|
+
* push swarm control messages and hidden-state frames into a running session.
|
|
43
|
+
*/
|
|
44
|
+
private postToActive;
|
|
45
|
+
/**
|
|
46
|
+
* Deliver a swarm control message to the task it names. A message that
|
|
47
|
+
* arrives while that task is still queued is held until it starts; posting it
|
|
48
|
+
* into whichever task happens to be running would hand it to the wrong
|
|
49
|
+
* session (and drop the intended one).
|
|
50
|
+
*/
|
|
51
|
+
sendControl(message: unknown, executionId?: string): boolean;
|
|
52
|
+
sendFrame(frame: ArrayBuffer): boolean;
|
|
53
|
+
/** Pause or resume a normal workload's asynchronous token sink. */
|
|
54
|
+
setTokenFlow(taskId: string, paused: boolean): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* The coordinator settled this task elsewhere (timeout, a peer failed, the
|
|
57
|
+
* plan was rejected): stop it.
|
|
58
|
+
*
|
|
59
|
+
* A queued task is dropped before it ever starts. A running task is asked to
|
|
60
|
+
* stop and the slot is released only when the worker itself reports done or
|
|
61
|
+
* error, so two tasks can never end up in the same worker.
|
|
62
|
+
*/
|
|
63
|
+
abort(id: string, reason: string): boolean;
|
|
26
64
|
private handleWorkerError;
|
|
27
65
|
private dequeue;
|
|
28
66
|
private cleanupWorker;
|
|
29
67
|
terminate(): void;
|
|
30
68
|
resume(): void;
|
|
31
69
|
get lastCpuLoad(): number;
|
|
70
|
+
get hasCpuLoadSample(): boolean;
|
|
71
|
+
get modelCacheSnapshot(): NodeModelCacheSnapshot | null;
|
|
32
72
|
}
|
|
33
73
|
//# sourceMappingURL=WorkerPool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../../src/executor/WorkerPool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WorkerPool.d.ts","sourceRoot":"","sources":["../../src/executor/WorkerPool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoBxE,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,MAAM,CAA2B;IACzC,yEAAyE;IACzE,OAAO,CAAC,eAAe,CAAmD;IAC1E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAM;IAClD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,mBAAmB,CAAuC;gBAEtD,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,SAAS;IAMlD,OAAO,CAAC,UAAU;IAYlB,GAAG,CACD,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,OAAO,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACjC,MAAM,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,EAChG,KAAK,CAAC,EAAE,cAAc,GACrB,OAAO,CAAC,OAAO,CAAC;IAgBnB,OAAO,CAAC,OAAO;IAkGf,+EAA+E;IAC/E,OAAO,CAAC,aAAa;IAOrB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAUpB;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO;IAW5D,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO;IAItC,mEAAmE;IACnE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO;IAKtD;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAmB1C,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,aAAa;IASrB,SAAS;IAmBT,MAAM;IAMN,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,kBAAkB,IAAI,sBAAsB,GAAG,IAAI,CAItD;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for swarm control-message routing, written from the
|
|
3
|
+
* feature/swarm-inference quality review and kept after the fix landed.
|
|
4
|
+
*
|
|
5
|
+
* Do not weaken it to make the suite green — if it starts failing, the defect
|
|
6
|
+
* it documents has come back.
|
|
7
|
+
*
|
|
8
|
+
* M3 `sendControl` must post to the task the message names, never to
|
|
9
|
+
* whichever task happens to be running; a queued swarm session has to
|
|
10
|
+
* receive its control message when it starts.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=WorkerPool.swarm.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkerPool.swarm.test.d.ts","sourceRoot":"","sources":["../../../src/executor/__tests__/WorkerPool.swarm.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container-executor.test.d.ts","sourceRoot":"","sources":["../../../src/executor/__tests__/container-executor.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress-guard.test.d.ts","sourceRoot":"","sources":["../../../src/executor/__tests__/egress-guard.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceReporter.test.d.ts","sourceRoot":"","sources":["../../../src/executor/__tests__/resourceReporter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgpuProbe.test.d.ts","sourceRoot":"","sources":["../../../src/executor/__tests__/webgpuProbe.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,3 +1,51 @@
|
|
|
1
1
|
import type { ContainerPayload, ContainerResult } from "@flaxia/sdk";
|
|
2
|
-
|
|
2
|
+
/** Maximum size of a container WASM image (128 MiB). */
|
|
3
|
+
export declare const MAX_CONTAINER_IMAGE_BYTES: number;
|
|
4
|
+
/** Aggregate decoded input-file ceiling; keeps reference downloads bounded. */
|
|
5
|
+
export declare const MAX_CONTAINER_INPUT_BYTES: number;
|
|
6
|
+
/** Memory bounds for `memoryLimitMb` (clamped): 32 MiB .. 4 GiB. */
|
|
7
|
+
export declare const MIN_CONTAINER_MEMORY_MB = 32;
|
|
8
|
+
export declare const MAX_CONTAINER_MEMORY_MB = 4096;
|
|
9
|
+
/** Default memory cap when the payload omits `memoryLimitMb`. */
|
|
10
|
+
export declare const DEFAULT_CONTAINER_MEMORY_MB = 512;
|
|
11
|
+
/**
|
|
12
|
+
* Replace the container image origin allowlist. Hosts/operators call this once
|
|
13
|
+
* at start-up; entries must be exact origins (`https://cdn.example.com`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function configureContainerImageOrigins(origins: readonly string[]): void;
|
|
16
|
+
/** Origins currently allowed to serve container images (empty = disabled). */
|
|
17
|
+
export declare function getAllowedContainerImageOrigins(): readonly string[];
|
|
18
|
+
/**
|
|
19
|
+
* Validate a container image URL. The origin allowlist is the primary control;
|
|
20
|
+
* the shared egress guard additionally rejects loopback/private hosts,
|
|
21
|
+
* non-default ports, credentials, non-HTTPS schemes and non-`.wasm` paths.
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateImageUrl(urlStr: string, origins?: readonly string[]): URL;
|
|
24
|
+
export interface WasmMemoryLimits {
|
|
25
|
+
/** Declared minimum memory in bytes (0 when the module does not declare any). */
|
|
26
|
+
initialBytes: number;
|
|
27
|
+
/** Declared maximum memory in bytes, or null when the module declares none. */
|
|
28
|
+
maximumBytes: number | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Read the memory section of a WASM binary.
|
|
32
|
+
*
|
|
33
|
+
* A WASI module exports its own `WebAssembly.Memory`, so the shim cannot inject
|
|
34
|
+
* a capped memory: the only pre-execution guarantee available in the browser is
|
|
35
|
+
* to inspect what the module *declares* and refuse to instantiate when it is
|
|
36
|
+
* allowed to exceed `memoryLimitMb`. See `docs/04-workloads.md` for the exact
|
|
37
|
+
* guarantee this does (and does not) provide.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseWasmMemoryLimits(binary: Uint8Array): WasmMemoryLimits;
|
|
40
|
+
/** Clamp `memoryLimitMb` into the supported range. */
|
|
41
|
+
export declare function resolveMemoryLimitMb(requested?: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* Enforce the payload's memory cap against the module's declared memory limits.
|
|
44
|
+
* Rejects a module without an explicit maximum, one that could grow past the
|
|
45
|
+
* cap, or one that needs more than the cap just to start.
|
|
46
|
+
*/
|
|
47
|
+
export declare function assertWasmMemoryWithinLimit(binary: Uint8Array, limitMb: number): WasmMemoryLimits;
|
|
48
|
+
/** Decode inline files and download scoped references before mounting either. */
|
|
49
|
+
export declare function resolveContainerFiles(payload: Pick<ContainerPayload, 'files' | 'fileSources'>, allowedFileSourceOrigins?: readonly string[]): Promise<Map<string, Uint8Array>>;
|
|
50
|
+
export declare const runContainer: (payload: ContainerPayload, allowedFileSourceOrigins?: readonly string[], containerImageOrigins?: readonly string[]) => Promise<ContainerResult>;
|
|
3
51
|
//# sourceMappingURL=container-executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container-executor.d.ts","sourceRoot":"","sources":["../../src/executor/container-executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"container-executor.d.ts","sourceRoot":"","sources":["../../src/executor/container-executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAuB,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAc1F,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,QAAoB,CAAC;AAK3D,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAG1D,oEAAoE;AACpE,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,iEAAiE;AACjE,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAa/C;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAa/E;AAED,8EAA8E;AAC9E,wBAAgB,+BAA+B,IAAI,SAAS,MAAM,EAAE,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,MAAM,EAAwB,GAAG,GAAG,CAyBtG;AAED,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,CAmD1E;AAgBD,sDAAsD;AACtD,wBAAgB,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAM/D;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAiBjG;AA+CD,iFAAiF;AACjF,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,aAAa,CAAC,EACxD,wBAAwB,GAAE,SAAS,MAAM,EAAO,GAC/C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAgElC;AAED,eAAO,MAAM,YAAY,GACvB,SAAS,gBAAgB,EACzB,2BAA0B,SAAS,MAAM,EAAO,EAChD,wBAAuB,SAAS,MAAM,EAAwB,KAC7D,OAAO,CAAC,eAAe,CA8FzB,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-side egress guard for every workload that fetches a customer-supplied
|
|
3
|
+
* URL (container WASM images, nudenet image URLs, ...).
|
|
4
|
+
*
|
|
5
|
+
* A volunteer node runs inside the visitor's browser, so a customer-supplied
|
|
6
|
+
* URL turns that visitor's residential IP into a request proxy (SSRF): the
|
|
7
|
+
* browser will happily reach loopback, the visitor's LAN, CGNAT/Tailscale
|
|
8
|
+
* addresses, cloud metadata endpoints and `.local`/`.internal` names. The guard
|
|
9
|
+
* below is the single place that decides whether a URL may be fetched at all.
|
|
10
|
+
*
|
|
11
|
+
* What it enforces:
|
|
12
|
+
* - `https:` only, no embedded credentials (`user:pass@host`);
|
|
13
|
+
* - the host may not be, or resolve syntactically to, loopback / private /
|
|
14
|
+
* link-local / CGNAT / ULA / IPv4-mapped-IPv6 / unspecified / `0.0.0.0/8` /
|
|
15
|
+
* multicast / reserved space, and may not end in `.local` or `.internal`;
|
|
16
|
+
* - only the default HTTPS port is allowed;
|
|
17
|
+
* - redirects are followed manually and every hop is re-validated (an
|
|
18
|
+
* environment that hides `Location` on a manual redirect gets the request
|
|
19
|
+
* rejected instead — fail closed);
|
|
20
|
+
* - `Content-Type` must be on the caller's allowlist;
|
|
21
|
+
* - the body is streamed and aborted once it passes the byte cap (the
|
|
22
|
+
* `Content-Length` header is never trusted);
|
|
23
|
+
* - an `AbortSignal` timeout bounds the whole exchange.
|
|
24
|
+
*
|
|
25
|
+
* Residual risk (documented, not silently ignored): the browser resolves the
|
|
26
|
+
* hostname, so a DNS name that only *later* resolves to a private address
|
|
27
|
+
* cannot be detected from JavaScript without a DNS API. IP literals and
|
|
28
|
+
* private-looking names are rejected here; public names are additionally
|
|
29
|
+
* protected by the browser's Private Network Access checks.
|
|
30
|
+
*/
|
|
31
|
+
/** Hard default response-size cap (8 MiB) when a caller does not set one. */
|
|
32
|
+
export declare const DEFAULT_MAX_EGRESS_BYTES: number;
|
|
33
|
+
/** Hard ceiling for any caller-provided cap (256 MiB). */
|
|
34
|
+
export declare const MAX_EGRESS_BYTES: number;
|
|
35
|
+
/** Default whole-exchange timeout. */
|
|
36
|
+
export declare const DEFAULT_EGRESS_TIMEOUT_MS = 30000;
|
|
37
|
+
/** Redirect hops we are willing to re-validate. */
|
|
38
|
+
export declare const MAX_EGRESS_REDIRECTS = 3;
|
|
39
|
+
/** Only the default HTTPS port is allowed: odd ports are a common SSRF pivot. */
|
|
40
|
+
export declare const ALLOWED_EGRESS_PORTS: number[];
|
|
41
|
+
export interface EgressRequest {
|
|
42
|
+
/** Absolute URL to fetch. */
|
|
43
|
+
url: string | URL;
|
|
44
|
+
/** `Content-Type` prefixes (or exact media types) accepted for the body. */
|
|
45
|
+
allowContentTypes: readonly string[];
|
|
46
|
+
/** Maximum response body size in bytes (clamped to `MAX_EGRESS_BYTES`). */
|
|
47
|
+
maxBytes?: number;
|
|
48
|
+
/** Whole-exchange timeout in ms (applied with `AbortSignal.timeout`). */
|
|
49
|
+
timeoutMs?: number;
|
|
50
|
+
/** Extra request headers (validated: hop-by-hop headers are not allowed). */
|
|
51
|
+
headers?: Record<string, string>;
|
|
52
|
+
/** HTTP method; only GET/HEAD are meaningful for these workloads. */
|
|
53
|
+
method?: 'GET' | 'HEAD';
|
|
54
|
+
}
|
|
55
|
+
export interface EgressResult {
|
|
56
|
+
/** Final URL after the (manually validated) redirect chain. */
|
|
57
|
+
url: string;
|
|
58
|
+
status: number;
|
|
59
|
+
ok: boolean;
|
|
60
|
+
/** `Content-Type` of the final response, lowercased without parameters. */
|
|
61
|
+
contentType: string;
|
|
62
|
+
/** Full body bytes; empty for HEAD or an error status. */
|
|
63
|
+
bytes: Uint8Array<ArrayBuffer>;
|
|
64
|
+
byteLength: number;
|
|
65
|
+
}
|
|
66
|
+
export interface EgressGuardOptions {
|
|
67
|
+
/** Override the accepted ports (tests / non-default deployments). */
|
|
68
|
+
allowedPorts?: readonly number[];
|
|
69
|
+
/** Allow `http:` as well as `https:`. Never enable in production. */
|
|
70
|
+
allowInsecure?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* True when a dotted-decimal IPv4 literal belongs to a range a volunteer node
|
|
74
|
+
* must never reach.
|
|
75
|
+
*/
|
|
76
|
+
export declare function isBlockedIPv4(host: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Expand an IPv6 literal to its eight 16-bit groups, or return null when the
|
|
79
|
+
* text is not a valid IPv6 address. Handles `::` compression, a trailing
|
|
80
|
+
* embedded IPv4 (`::ffff:10.0.0.5`) and IPv4-compatible forms.
|
|
81
|
+
*/
|
|
82
|
+
export declare function parseIPv6(host: string): number[] | null;
|
|
83
|
+
/**
|
|
84
|
+
* True when an IPv6 literal is an address a volunteer node must never reach:
|
|
85
|
+
* unspecified (`::`), loopback (`::1`), IPv4-mapped/compatible IPv6 (the
|
|
86
|
+
* browser connects to the embedded IPv4), ULA (`fc00::/7`), link-local
|
|
87
|
+
* (`fe80::/10`), multicast (`ff00::/8`) and reserved space.
|
|
88
|
+
*/
|
|
89
|
+
export declare function isBlockedIPv6(host: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Validate a hostname (or IP literal) independently of the URL parser. Exported
|
|
92
|
+
* so workloads can pre-check a host and so the rules are unit-testable.
|
|
93
|
+
*/
|
|
94
|
+
export declare function assertPublicHostname(hostname: string, options?: EgressGuardOptions): void;
|
|
95
|
+
/**
|
|
96
|
+
* Validate an egress URL: protocol, credentials, port and host. Returns the
|
|
97
|
+
* parsed `URL` so callers can reuse it (and so redirect hops share one path).
|
|
98
|
+
*/
|
|
99
|
+
export declare function assertPublicUrl(input: string | URL, options?: EgressGuardOptions): URL;
|
|
100
|
+
/**
|
|
101
|
+
* Fetch a customer-supplied URL through the guard. Redirects are resolved
|
|
102
|
+
* manually so each hop is re-validated; the body is capped while streaming.
|
|
103
|
+
*/
|
|
104
|
+
export declare function fetchGuarded(request: EgressRequest, options?: EgressGuardOptions): Promise<EgressResult>;
|
|
105
|
+
//# sourceMappingURL=egress-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress-guard.d.ts","sourceRoot":"","sources":["../../src/executor/egress-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,wBAAwB,QAAkB,CAAC;AACxD,0DAA0D;AAC1D,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAClD,sCAAsC;AACtC,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAChD,mDAAmD;AACnD,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,UAAQ,CAAC;AAM1C,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAClB,4EAA4E;IAC5E,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,qEAAqE;IACrE,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAaD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAyBnD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAqDvD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgBnD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,IAAI,CAoB7F;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,OAAO,GAAE,kBAAuB,GAAG,GAAG,CAyB1F;AAmFD;;;GAGG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAqEvB"}
|
|
@@ -1,4 +1,34 @@
|
|
|
1
1
|
export declare const HEAVY_WORKLOAD_WASM_MEMORY_BYTES: number;
|
|
2
|
+
/**
|
|
3
|
+
* Probe a bounded lower bound of memory this runtime can commit. The function
|
|
4
|
+
* stops at `targetBytes`; it deliberately does not explore the engine maximum.
|
|
5
|
+
* Only the first call per page allocates/touches memory. If a later caller asks
|
|
6
|
+
* for a higher target, return the already-proven lower bound instead of
|
|
7
|
+
* committing more memory during startup.
|
|
8
|
+
*/
|
|
2
9
|
export declare function probeMaxWasmMemoryBytes(targetBytes?: number, chunkBytes?: number): number;
|
|
10
|
+
/**
|
|
11
|
+
* The device's committed WebAssembly memory, probed at most once per page.
|
|
12
|
+
* This is the cheap accessor every call site (registration, reconnect,
|
|
13
|
+
* capability reporting) should use instead of `probeMaxWasmMemoryBytes()`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getWasmMemoryBytes(): number;
|
|
16
|
+
/** The one-shot lower-bound observation, including when the runtime could not create WASM memory. */
|
|
17
|
+
export declare function getWasmMemoryProbeObservation(): {
|
|
18
|
+
bytes: number | null;
|
|
19
|
+
sampledAt: number | null;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Whether the device can commit the memory a heavy (multi-GB model) workload
|
|
23
|
+
* needs. Uses the cached probe, so it never re-allocates.
|
|
24
|
+
*/
|
|
3
25
|
export declare function hasEnoughWasmMemoryForHeavy(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Drop the memoized probe and reset the run counter. Only for tests that
|
|
28
|
+
* install a fake WebAssembly implementation; production code never needs to
|
|
29
|
+
* reset the cache.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resetWasmMemoryProbeCache(): void;
|
|
32
|
+
/** How many times the real probe ran (diagnostics / tests). */
|
|
33
|
+
export declare function getWasmMemoryProbeRuns(): number;
|
|
4
34
|
//# sourceMappingURL=memoryProbe.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memoryProbe.d.ts","sourceRoot":"","sources":["../../src/executor/memoryProbe.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memoryProbe.d.ts","sourceRoot":"","sources":["../../src/executor/memoryProbe.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gCAAgC,QAAgB,CAAC;AA8B9D;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,GAAE,MAAyC,EACtD,UAAU,GAAE,MAA0B,GACrC,MAAM,CA6BR;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,qGAAqG;AACrG,wBAAgB,6BAA6B,IAAI;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAMlG;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD;AAED,+DAA+D;AAC/D,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { NodeResourceReport } from '@flaxia/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Collect current resource telemetry for an already-consented signaling
|
|
4
|
+
* session. The 2 GiB WASM lower-bound probe remains one-shot; the tiny GPU
|
|
5
|
+
* compute sample refreshes only after its ten minute TTL.
|
|
6
|
+
*/
|
|
7
|
+
export declare function collectNodeResourceReport(options: {
|
|
8
|
+
cpuLoad?: number | null;
|
|
9
|
+
deviceMemory?: number;
|
|
10
|
+
probeGpu?: boolean;
|
|
11
|
+
now?: number;
|
|
12
|
+
}): Promise<NodeResourceReport>;
|
|
13
|
+
/** Clear the GPU result cache in isolated probe tests. */
|
|
14
|
+
export declare function resetNodeResourceReportCache(): void;
|
|
15
|
+
//# sourceMappingURL=resourceReporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceReporter.d.ts","sourceRoot":"","sources":["../../src/executor/resourceReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,aAAa,CAAC;AAuCtE;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE;IACvD,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2C9B;AAED,0DAA0D;AAC1D,wBAAgB,4BAA4B,IAAI,IAAI,CAGnD"}
|
|
@@ -1,22 +1,80 @@
|
|
|
1
|
+
/** Rolling window over which the busy ratio is estimated. */
|
|
2
|
+
export declare const THROTTLE_WINDOW_MS = 30000;
|
|
3
|
+
/** How long `waitForSlot()` waits for the rolling load to drop. */
|
|
4
|
+
export declare const DEFAULT_WAIT_SLOT_MS = 30000;
|
|
5
|
+
/** Continuous work allowed between two mid-execution duty-cycle pauses. */
|
|
6
|
+
export declare const DUTY_CYCLE_BUDGET_MS = 200;
|
|
7
|
+
/**
|
|
8
|
+
* Thrown when `waitForSlot()` cannot find a slot within its budget.
|
|
9
|
+
*
|
|
10
|
+
* It replaces the old behaviour of starting the task anyway: a node that is
|
|
11
|
+
* already over its CPU budget must not force-start a heavy task at 100% CPU.
|
|
12
|
+
* The worker turns this into a retryable task error so the orchestrator can
|
|
13
|
+
* move the task to an idle node.
|
|
14
|
+
*/
|
|
15
|
+
export declare class ThrottleBusyError extends Error {
|
|
16
|
+
readonly load: number;
|
|
17
|
+
readonly maxLoad: number;
|
|
18
|
+
readonly waitedMs: number;
|
|
19
|
+
readonly retryable = true;
|
|
20
|
+
constructor(load: number, maxLoad: number, waitedMs: number);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Keeps the Worker's average CPU usage within `maxLoad` without busy-waiting.
|
|
24
|
+
*
|
|
25
|
+
* Load is estimated from the work the worker charges over a rolling window
|
|
26
|
+
* (`markTaskComplete` plus the duty-cycle pauses below) rather than from a
|
|
27
|
+
* calibrated busy-loop, which itself burned CPU on slow devices.
|
|
28
|
+
*
|
|
29
|
+
* Two controls exist:
|
|
30
|
+
* - `waitForSlot()` gates the *start* of a task. When the budget is exhausted
|
|
31
|
+
* it throws `ThrottleBusyError` instead of starting the task anyway.
|
|
32
|
+
* - `yieldIfOverloaded()` limits the *execution* of a long task. Workloads
|
|
33
|
+
* call it between streaming tokens/batches; after `DUTY_CYCLE_BUDGET_MS` of
|
|
34
|
+
* continuous work it sleeps for the time needed to hold the configured duty
|
|
35
|
+
* cycle, so a 10-minute generation cannot pin a core at 100%.
|
|
36
|
+
*/
|
|
1
37
|
export declare class CpuThrottle {
|
|
2
38
|
private readonly maxLoad;
|
|
3
39
|
private windowStart;
|
|
4
40
|
private windowBusyMs;
|
|
5
41
|
private lastLoad;
|
|
42
|
+
/** Timestamp of the first unpaused work unit of the current duty cycle. */
|
|
43
|
+
private dutyStartedAt;
|
|
6
44
|
constructor(maxLoad?: number);
|
|
7
45
|
/**
|
|
8
|
-
* Charge a completed task's wall-clock duration (in ms) against the CPU
|
|
9
|
-
* Call this from the worker once a workload has finished (incl.
|
|
46
|
+
* Charge a completed task's wall-clock duration (in ms) against the CPU
|
|
47
|
+
* budget. Call this from the worker once a workload has finished (incl.
|
|
48
|
+
* errors/timeouts).
|
|
10
49
|
*/
|
|
11
50
|
markTaskComplete(durationMs: number): void;
|
|
51
|
+
/** Start a fresh duty cycle before executing a task. */
|
|
52
|
+
beginWork(): void;
|
|
53
|
+
private resetDutyCycle;
|
|
54
|
+
private rollWindow;
|
|
55
|
+
/**
|
|
56
|
+
* Recompute the rolling busy ratio, treating `work` ms as the work charged
|
|
57
|
+
* into the current window. Returns the ratio (0..1).
|
|
58
|
+
*/
|
|
12
59
|
private estimate;
|
|
13
60
|
shouldPause(): Promise<boolean>;
|
|
14
61
|
/**
|
|
15
62
|
* Waits until the rolling busy ratio is back under `maxLoad`.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
63
|
+
*
|
|
64
|
+
* @throws ThrottleBusyError when the budget is exhausted while the device is
|
|
65
|
+
* still over budget. Starting the task anyway is what made the previous
|
|
66
|
+
* implementation a no-op, so this is deliberately fail-closed.
|
|
18
67
|
*/
|
|
19
68
|
waitForSlot(maxWaitMs?: number): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Cooperative mid-execution limiting: after a continuous burst of
|
|
71
|
+
* `DUTY_CYCLE_BUDGET_MS`, sleep long enough that the burst's share of wall
|
|
72
|
+
* time matches `maxLoad`. Call between streaming tokens or batch iterations.
|
|
73
|
+
*
|
|
74
|
+
* Returns the number of ms slept (0 when the caller is inside its duty
|
|
75
|
+
* cycle), which makes the behaviour directly testable.
|
|
76
|
+
*/
|
|
77
|
+
yieldIfOverloaded(): Promise<number>;
|
|
20
78
|
get lastMeasuredLoad(): number;
|
|
21
79
|
get maxLoadValue(): number;
|
|
22
80
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/executor/throttle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/executor/throttle.ts"],"names":[],"mappings":"AAIA,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,mEAAmE;AACnE,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAG3C,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAGxC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAJ3B,QAAQ,CAAC,SAAS,QAAQ;gBAEf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM;CAO5B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAK;IACrB,2EAA2E;IAC3E,OAAO,CAAC,aAAa,CAAuB;gBAEhC,OAAO,SAAO;IAI1B;;;;OAIG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAK1C,wDAAwD;IACxD,SAAS,IAAI,IAAI;IAIjB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,UAAU;IAQlB;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAWV,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAKrC;;;;;;OAMG;IACG,WAAW,CAAC,SAAS,SAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAclE;;;;;;;OAOG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAkB1C,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { GpuProbeStatus, SwarmNodeCapabilities } from '@flaxia/sdk';
|
|
2
|
+
export interface WebGpuProbeResult {
|
|
3
|
+
capabilities: SwarmNodeCapabilities;
|
|
4
|
+
status: GpuProbeStatus;
|
|
5
|
+
sampledAt: number;
|
|
6
|
+
expiresAt: number;
|
|
7
|
+
architecture: string | null;
|
|
8
|
+
maxStorageBufferBindingSize: number | null;
|
|
9
|
+
computeCompletionMs: number | null;
|
|
10
|
+
sampleCount: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Request a device and time three tiny no-buffer compute submissions. This is
|
|
14
|
+
* a scheduling hint, not a benchmark: it allocates no model-sized resources,
|
|
15
|
+
* has a per-sample timeout, and destroys the temporary device in all cases.
|
|
16
|
+
*/
|
|
17
|
+
export declare function probeWebGpuDetailed(): Promise<WebGpuProbeResult>;
|
|
18
|
+
/** Backwards-compatible capability probe; eligibility requires a working device. */
|
|
19
|
+
export declare function probeWebGpu(): Promise<SwarmNodeCapabilities>;
|
|
20
|
+
//# sourceMappingURL=webgpuProbe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgpuProbe.d.ts","sourceRoot":"","sources":["../../src/executor/webgpuProbe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAkEzE,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,qBAAqB,CAAC;IACpC,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AAmCD;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAqFtE;AAED,oFAAoF;AACpF,wBAAsB,WAAW,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAElE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { initFlaxiaNode } from './client/SignalingClient';
|
|
2
2
|
export { getConsentState as getFlaxiaNodeConsentState } from './consent/storage';
|
|
3
|
+
export { initConsentIntegrity as initFlaxiaNodeConsent } from './consent/storage';
|
|
4
|
+
export { setHostManagedConsentAllowed as setFlaxiaNodeHostManagedConsent } from './consent/storage';
|
|
3
5
|
export { initFlaxiaNode };
|
|
4
6
|
export type { ConsentControls, ConsentState, FlaxiaNodeController } from '@flaxia/sdk';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAO1D,OAAO,EAAE,eAAe,IAAI,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAGjF,OAAO,EAAE,oBAAoB,IAAI,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAIlF,OAAO,EAAE,4BAA4B,IAAI,+BAA+B,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
|