@openfluke/welvet 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @openfluke/welvet - Browser Entry Point
3
+ *
4
+ * Browser-only build without Node.js dependencies
5
+ * Isomorphic wrapper that mirrors main.go WASM exports
6
+ */
7
+ import { Network } from "./types.js";
8
+ import { loadLoomWASMBrowser } from "./loader.browser.js";
9
+ export * from "./types.js";
10
+ export { loadLoomWASMBrowser };
11
+ /**
12
+ * Initialize WASM for Browser environment
13
+ */
14
+ export declare function initBrowser(): Promise<void>;
15
+ /**
16
+ * Initialize - alias for initBrowser in browser context
17
+ */
18
+ export declare function init(): Promise<void>;
19
+ /**
20
+ * Create a network from JSON config
21
+ * Wrapper around the global createLoomNetwork function exposed by WASM
22
+ */
23
+ export declare function createNetwork(config: object | string): Network;
24
+ /**
25
+ * Default export with all functions
26
+ */
27
+ declare const _default: {
28
+ init: typeof init;
29
+ initBrowser: typeof initBrowser;
30
+ createNetwork: typeof createNetwork;
31
+ };
32
+ export default _default;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @openfluke/welvet - Browser Entry Point
3
+ *
4
+ * Browser-only build without Node.js dependencies
5
+ * Isomorphic wrapper that mirrors main.go WASM exports
6
+ */
7
+ import { loadLoomWASMBrowser } from "./loader.browser.js";
8
+ export * from "./types.js";
9
+ export { loadLoomWASMBrowser };
10
+ /**
11
+ * Initialize WASM for Browser environment
12
+ */
13
+ export async function initBrowser() {
14
+ await loadLoomWASMBrowser();
15
+ }
16
+ /**
17
+ * Initialize - alias for initBrowser in browser context
18
+ */
19
+ export async function init() {
20
+ return initBrowser();
21
+ }
22
+ /**
23
+ * Create a network from JSON config
24
+ * Wrapper around the global createLoomNetwork function exposed by WASM
25
+ */
26
+ export function createNetwork(config) {
27
+ const jsonConfig = typeof config === 'string' ? config : JSON.stringify(config);
28
+ return createLoomNetwork(jsonConfig);
29
+ }
30
+ /**
31
+ * Default export with all functions
32
+ */
33
+ export default {
34
+ init,
35
+ initBrowser,
36
+ createNetwork
37
+ };
package/dist/index.d.ts CHANGED
@@ -1,33 +1,33 @@
1
- import type { InitOptions, LoomAPI } from "./types.js";
2
1
  /**
3
- * Initialize the LOOM WASM module and return the API
2
+ * @openfluke/welvet - Isomorphic WASM Wrapper
4
3
  *
5
- * @example
6
- * ```typescript
7
- * import { initLoom, ActivationType } from '@openfluke/loom';
8
- *
9
- * const loom = await initLoom();
10
- *
11
- * // Create a network: 784 → 392 → 10
12
- * const network = loom.NewNetwork(784, 1, 1, 2);
13
- *
14
- * // Configure layers
15
- * const layer0 = loom.InitDenseLayer(784, 392, ActivationType.ReLU);
16
- * const layer1 = loom.InitDenseLayer(392, 10, ActivationType.Sigmoid);
17
- *
18
- * network.SetLayer(JSON.stringify([0, 0, 0, JSON.parse(layer0)]));
19
- * network.SetLayer(JSON.stringify([0, 0, 1, JSON.parse(layer1)]));
20
- *
21
- * // Forward pass
22
- * const input = new Array(784).fill(0).map(() => Math.random());
23
- * const resultJSON = network.ForwardCPU(JSON.stringify([input]));
24
- * const [output, duration] = JSON.parse(resultJSON);
25
- *
26
- * console.log('Output:', output);
27
- * ```
4
+ * Direct wrapper around Loom WASM that mirrors main.go exports exactly.
5
+ * Provides the same API in both Node.js and browser environments.
6
+ */
7
+ import { Network } from "./types.js";
8
+ import { loadLoomWASM } from "./loader.js";
9
+ import { loadLoomWASMBrowser } from "./loader.browser.js";
10
+ export * from "./types.js";
11
+ export { loadLoomWASM, loadLoomWASMBrowser };
12
+ /**
13
+ * Initialize WASM for Node.js environment
14
+ */
15
+ export declare function init(): Promise<void>;
16
+ /**
17
+ * Initialize WASM for Browser environment
18
+ */
19
+ export declare function initBrowser(): Promise<void>;
20
+ /**
21
+ * Create a network from JSON config
22
+ * Wrapper around the global createLoomNetwork function exposed by WASM
23
+ */
24
+ export declare function createNetwork(config: object | string): Network;
25
+ /**
26
+ * Default export with all functions
28
27
  */
29
- export declare function initLoom(opts?: InitOptions): Promise<LoomAPI>;
30
- export type { LoomAPI, LoomNetwork, InitOptions, TransformerAPI, } from "./types.js";
31
- export { ActivationType } from "./types.js";
32
- export { createTransformerAPI } from "./transformer.js";
33
- export type { TokenizerLoadResult, TransformerLoadResult, EncodeResult, DecodeResult, GenerateResult, NextTokenResult, } from "./types.js";
28
+ declare const _default: {
29
+ init: typeof init;
30
+ initBrowser: typeof initBrowser;
31
+ createNetwork: typeof createNetwork;
32
+ };
33
+ export default _default;
package/dist/index.js CHANGED
@@ -1,87 +1,38 @@
1
- import { ensureGoRuntime, resolvePackagedWasmURL, instantiateGoWasm, } from "./loader.js";
2
- // tiny helper that waits until WASM has placed symbols on globalThis
3
- async function waitForExports(keys, timeoutMs = 5000) {
4
- const t0 = performance.now();
5
- for (;;) {
6
- const ok = keys.every((k) => globalThis[k]);
7
- if (ok)
8
- return;
9
- if (performance.now() - t0 > timeoutMs) {
10
- throw new Error(`loom: timed out waiting for exports: ${keys.join(", ")}`);
11
- }
12
- await new Promise((r) => setTimeout(r, 10));
13
- }
14
- }
15
1
  /**
16
- * Initialize the LOOM WASM module and return the API
17
- *
18
- * @example
19
- * ```typescript
20
- * import { initLoom, ActivationType } from '@openfluke/loom';
21
- *
22
- * const loom = await initLoom();
23
- *
24
- * // Create a network: 784 → 392 → 10
25
- * const network = loom.NewNetwork(784, 1, 1, 2);
26
- *
27
- * // Configure layers
28
- * const layer0 = loom.InitDenseLayer(784, 392, ActivationType.ReLU);
29
- * const layer1 = loom.InitDenseLayer(392, 10, ActivationType.Sigmoid);
2
+ * @openfluke/welvet - Isomorphic WASM Wrapper
30
3
  *
31
- * network.SetLayer(JSON.stringify([0, 0, 0, JSON.parse(layer0)]));
32
- * network.SetLayer(JSON.stringify([0, 0, 1, JSON.parse(layer1)]));
33
- *
34
- * // Forward pass
35
- * const input = new Array(784).fill(0).map(() => Math.random());
36
- * const resultJSON = network.ForwardCPU(JSON.stringify([input]));
37
- * const [output, duration] = JSON.parse(resultJSON);
38
- *
39
- * console.log('Output:', output);
40
- * ```
4
+ * Direct wrapper around Loom WASM that mirrors main.go exports exactly.
5
+ * Provides the same API in both Node.js and browser environments.
6
+ */
7
+ import { loadLoomWASM } from "./loader.js";
8
+ import { loadLoomWASMBrowser } from "./loader.browser.js";
9
+ export * from "./types.js";
10
+ export { loadLoomWASM, loadLoomWASMBrowser };
11
+ /**
12
+ * Initialize WASM for Node.js environment
41
13
  */
42
- export async function initLoom(opts = {}) {
43
- await ensureGoRuntime(opts.injectGoRuntime !== false);
44
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
- const go = new globalThis.Go();
46
- const wasmUrl = await resolvePackagedWasmURL(opts.wasmUrl);
47
- const instance = await instantiateGoWasm(go, wasmUrl);
48
- // IMPORTANT: don't await this — it resolves when the Go program exits.
49
- // Let it run; then poll for the exported symbols.
50
- // no await:
51
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
52
- Promise.resolve().then(() => go.run(instance));
53
- // wait until your Go code has installed the globals
54
- await waitForExports(["NewNetwork", "LoadModelFromString", "CallLayerInit"]);
55
- const g = globalThis;
56
- // Helper function to call layer init functions from the registry
57
- const callLayerInit = (funcName, ...params) => {
58
- return g.CallLayerInit(funcName, JSON.stringify(params));
59
- };
60
- const api = {
61
- NewNetwork: g.NewNetwork,
62
- LoadModelFromString: g.LoadModelFromString,
63
- CallLayerInit: g.CallLayerInit, // Direct access to registry-based layer init
64
- // Layer initialization functions using CallLayerInit (registry-based)
65
- InitDenseLayer: (inputSize, outputSize, activation) => {
66
- return callLayerInit("InitDenseLayer", inputSize, outputSize, activation);
67
- },
68
- InitConv2DLayer: (inChannels, outChannels, kernelSize, stride, padding, inputH, inputW, activation) => {
69
- return callLayerInit("InitConv2DLayer", inChannels, outChannels, kernelSize, stride, padding, inputH, inputW, activation);
70
- },
71
- InitMultiHeadAttentionLayer: (dModel, numHeads, seqLength, activation) => {
72
- return callLayerInit("InitMultiHeadAttentionLayer", dModel, numHeads, seqLength, activation);
73
- },
74
- InitRNNLayer: (inputSize, hiddenSize, seqLength, outputSize) => {
75
- return callLayerInit("InitRNNLayer", inputSize, hiddenSize, seqLength, outputSize);
76
- },
77
- InitLSTMLayer: (inputSize, hiddenSize, seqLength, outputSize) => {
78
- return callLayerInit("InitLSTMLayer", inputSize, hiddenSize, seqLength, outputSize);
79
- },
80
- };
81
- if (!api.NewNetwork) {
82
- throw new Error("loom: NewNetwork not found after WASM init");
83
- }
84
- return api;
14
+ export async function init() {
15
+ await loadLoomWASM();
85
16
  }
86
- export { ActivationType } from "./types.js";
87
- export { createTransformerAPI } from "./transformer.js";
17
+ /**
18
+ * Initialize WASM for Browser environment
19
+ */
20
+ export async function initBrowser() {
21
+ await loadLoomWASMBrowser();
22
+ }
23
+ /**
24
+ * Create a network from JSON config
25
+ * Wrapper around the global createLoomNetwork function exposed by WASM
26
+ */
27
+ export function createNetwork(config) {
28
+ const jsonConfig = typeof config === 'string' ? config : JSON.stringify(config);
29
+ return createLoomNetwork(jsonConfig);
30
+ }
31
+ /**
32
+ * Default export with all functions
33
+ */
34
+ export default {
35
+ init,
36
+ initBrowser,
37
+ createNetwork
38
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * LOOM WASM Browser Loader
3
+ * Browser-only version without Node.js dependencies
4
+ */
5
+ export declare function loadLoomWASMBrowser(): Promise<void>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * LOOM WASM Browser Loader
3
+ * Browser-only version without Node.js dependencies
4
+ */
5
+ export async function loadLoomWASMBrowser() {
6
+ // For browser environments - load wasm_exec.js first if not already loaded
7
+ if (typeof globalThis.Go === "undefined") {
8
+ // Load wasm_exec.js dynamically from /dist/
9
+ const script = document.createElement("script");
10
+ script.src = "/dist/wasm_exec.js";
11
+ await new Promise((resolve, reject) => {
12
+ script.onload = () => resolve();
13
+ script.onerror = () => reject(new Error("Failed to load wasm_exec.js"));
14
+ document.head.appendChild(script);
15
+ });
16
+ }
17
+ const response = await fetch("/dist/main.wasm");
18
+ const wasmBuffer = await response.arrayBuffer();
19
+ // @ts-ignore - Go is defined by wasm_exec.js
20
+ const go = new Go();
21
+ const { instance } = await WebAssembly.instantiate(wasmBuffer, go.importObject);
22
+ go.run(instance);
23
+ // Wait for initialization
24
+ await new Promise((resolve) => setTimeout(resolve, 100));
25
+ }
package/dist/loader.d.ts CHANGED
@@ -1,3 +1,5 @@
1
- export declare function ensureGoRuntime(inject?: boolean): Promise<void>;
2
- export declare function resolvePackagedWasmURL(override?: string | URL): Promise<string | URL>;
3
- export declare function instantiateGoWasm(go: any, wasmUrl: string | URL): Promise<WebAssembly.Instance>;
1
+ /**
2
+ * LOOM WASM Loader
3
+ * Loads and initializes the LOOM WebAssembly module (Node.js only)
4
+ */
5
+ export declare function loadLoomWASM(): Promise<void>;
package/dist/loader.js CHANGED
@@ -1,90 +1,26 @@
1
- import { isBrowser } from "./env.js";
2
- let goRuntimeInjected = false;
3
- let wasmExecTextBundled;
4
- let wasmUrlBundled;
5
- async function tryLoadBundlerAssets() {
6
- try {
7
- const raw = await import("./wasm_exec.js?raw");
8
- wasmExecTextBundled = raw.default;
9
- }
10
- catch { }
11
- try {
12
- const url = await import("./loom.wasm?url");
13
- wasmUrlBundled = url.default;
14
- }
15
- catch { }
16
- }
17
- export async function ensureGoRuntime(inject = true) {
18
- if (!inject || goRuntimeInjected)
19
- return;
20
- if (isBrowser) {
21
- if (!wasmExecTextBundled)
22
- await tryLoadBundlerAssets();
23
- if (wasmExecTextBundled) {
24
- new Function(wasmExecTextBundled)(); // defines global Go
25
- goRuntimeInjected = true;
26
- return;
27
- }
28
- const url = new URL("./wasm_exec.js", import.meta.url);
29
- const res = await fetch(url);
30
- if (!res.ok)
31
- throw new Error(`Failed to fetch wasm_exec.js (${res.status} ${res.statusText}) from ${url}`);
32
- const jsText = await res.text();
33
- new Function(jsText)();
34
- goRuntimeInjected = true;
35
- return;
36
- }
37
- const { readFile } = await import("node:fs/promises");
38
- const { fileURLToPath } = await import("node:url");
39
- const wasmExecUrl = new URL("./wasm_exec.js", import.meta.url);
40
- const filePath = fileURLToPath(wasmExecUrl);
41
- const jsText = await readFile(filePath, "utf8");
42
- new Function(jsText)();
43
- goRuntimeInjected = true;
44
- }
45
- export async function resolvePackagedWasmURL(override) {
46
- if (override)
47
- return override;
48
- if (isBrowser) {
49
- if (!wasmUrlBundled)
50
- await tryLoadBundlerAssets();
51
- if (wasmUrlBundled)
52
- return wasmUrlBundled;
53
- return new URL("./loom.wasm", import.meta.url);
54
- }
55
- return new URL("./loom.wasm", import.meta.url);
56
- }
57
- export async function instantiateGoWasm(go, wasmUrl) {
58
- const asString = typeof wasmUrl === "string" ? wasmUrl : wasmUrl.toString();
59
- if (isBrowser) {
60
- if (typeof WebAssembly.instantiateStreaming === "function") {
61
- const res = await fetch(asString);
62
- try {
63
- const { instance } = await WebAssembly.instantiateStreaming(res, go.importObject);
64
- return instance;
65
- }
66
- catch {
67
- const buf = await res.arrayBuffer();
68
- const result = (await WebAssembly.instantiate(buf, go.importObject));
69
- const instance = result.instance ?? result;
70
- return instance;
71
- }
72
- }
73
- else {
74
- const res = await fetch(asString);
75
- const buf = await res.arrayBuffer();
76
- const result = (await WebAssembly.instantiate(buf, go.importObject));
77
- const instance = result.instance ?? result;
78
- return instance;
79
- }
80
- }
81
- // Node/Bun
82
- const { readFile } = await import("node:fs/promises");
83
- const { fileURLToPath } = await import("node:url");
84
- const url = typeof wasmUrl === "string" ? new URL(wasmUrl, import.meta.url) : wasmUrl;
85
- const filePath = fileURLToPath(url);
86
- const buf = await readFile(filePath);
87
- const result = (await WebAssembly.instantiate(buf, go.importObject));
88
- const instance = result.instance ?? result;
89
- return instance;
1
+ /**
2
+ * LOOM WASM Loader
3
+ * Loads and initializes the LOOM WebAssembly module (Node.js only)
4
+ */
5
+ import { readFileSync } from "fs";
6
+ import { fileURLToPath } from "url";
7
+ import { dirname, join } from "path";
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ export async function loadLoomWASM() {
11
+ // Load wasm_exec.js
12
+ const wasmExecPath = join(__dirname, "../assets/wasm_exec.js");
13
+ const wasmExecCode = readFileSync(wasmExecPath, "utf-8");
14
+ // Execute wasm_exec.js to get the Go runtime
15
+ eval(wasmExecCode);
16
+ // Load main.wasm
17
+ const wasmPath = join(__dirname, "../assets/main.wasm");
18
+ const wasmBuffer = readFileSync(wasmPath);
19
+ // @ts-ignore - Go is defined by wasm_exec.js
20
+ const go = new Go();
21
+ const { instance } = await WebAssembly.instantiate(wasmBuffer, go.importObject);
22
+ // Run the Go WASM module
23
+ go.run(instance);
24
+ // Wait a bit for initialization
25
+ await new Promise((resolve) => setTimeout(resolve, 100));
90
26
  }
Binary file