space-data-module-sdk 0.5.15 → 0.5.19

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 (45) hide show
  1. package/README.md +51 -0
  2. package/package.json +13 -4
  3. package/schemas/HostStorageAbi.fbs +53 -0
  4. package/src/browser.js +6 -0
  5. package/src/bundle/codec.js +1 -1
  6. package/src/compiler/compileModule.js +3 -0
  7. package/src/compliance/pluginCompliance.js +1 -2
  8. package/src/generated/orbpro/invoke/plugin-invoke-request.js +1 -1
  9. package/src/generated/orbpro/invoke/plugin-invoke-response.js +1 -1
  10. package/src/generated/orbpro/manifest/accepted-type-set.js +1 -1
  11. package/src/generated/orbpro/manifest/build-artifact.js +1 -1
  12. package/src/generated/orbpro/manifest/host-capability.js +1 -1
  13. package/src/generated/orbpro/manifest/method-manifest.js +1 -1
  14. package/src/generated/orbpro/manifest/plugin-manifest.js +1 -1
  15. package/src/generated/orbpro/manifest/port-manifest.js +1 -1
  16. package/src/generated/orbpro/manifest/protocol-spec.js +1 -1
  17. package/src/generated/orbpro/manifest/timer-spec.js +1 -1
  18. package/src/generated/orbpro/module/canonicalization-rule.js +1 -1
  19. package/src/generated/orbpro/module/module-bundle-entry.js +1 -1
  20. package/src/generated/orbpro/module/module-bundle.js +1 -1
  21. package/src/generated/orbpro/stream/flat-buffer-type-ref.js +1 -1
  22. package/src/generated/orbpro/stream/typed-arena-buffer.js +1 -1
  23. package/src/host/browserEdgeShims.js +355 -0
  24. package/src/host/browserHost.js +399 -0
  25. package/src/host/index.js +4 -0
  26. package/src/host/isomorphicLoader.js +101 -0
  27. package/src/host/wasiShim.js +275 -0
  28. package/src/index.d.ts +364 -0
  29. package/src/index.js +1 -0
  30. package/src/invoke/codec.js +1 -1
  31. package/src/manifest/codec.js +1 -1
  32. package/src/manifest/typeRefs.js +49 -12
  33. package/src/runtime-host/flatsqlRuntimeStore.js +217 -0
  34. package/src/runtime-host/index.js +21 -0
  35. package/src/runtime-host/moduleRegistry.js +92 -0
  36. package/src/runtime-host/runtimeRegionStore.js +245 -0
  37. package/src/testing/browserModuleHarness.js +275 -0
  38. package/src/testing/buildWasmEdgeRunner.js +41 -2
  39. package/src/testing/index.d.ts +173 -2
  40. package/src/testing/index.js +5 -0
  41. package/src/testing/moduleHarness.js +102 -1
  42. package/src/testing/native/wasmedge_emscripten_pthread_runner.c +2319 -209
  43. package/src/testing/processInvoke.js +250 -9
  44. package/src/testing/streamInvokeCodec.js +175 -0
  45. package/src/transport/records.js +19 -6
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Browser-side module harness.
3
+ *
4
+ * Loads the same standalone WASI .wasm artifact that WasmEdge runs,
5
+ * instantiating it in the browser with the WASI shim + optional sdn_host
6
+ * bridge. Matches the createModuleHarness() API surface.
7
+ *
8
+ * Supports two invoke paths:
9
+ * 1. "direct" — call plugin_invoke_stream(ptr, len, &outLen) and read
10
+ * the FlatBuffer response from WASM memory.
11
+ * 2. "command" — call _start() with stdin piped via WASI shim, read
12
+ * stdout for the response bytes.
13
+ */
14
+
15
+ import { createBrowserWasiShim, WasiExitError } from "../host/wasiShim.js";
16
+ import { createBrowserHost } from "../host/browserHost.js";
17
+ import {
18
+ createJsonHostcallBridge,
19
+ createNodeHostSyncDispatcher,
20
+ DEFAULT_HOSTCALL_IMPORT_MODULE,
21
+ } from "../host/abi.js";
22
+ import {
23
+ DefaultInvokeExports,
24
+ DefaultManifestExports,
25
+ } from "../runtime/constants.js";
26
+ import {
27
+ encodePluginInvokeRequest,
28
+ decodePluginInvokeResponse,
29
+ } from "../invoke/codec.js";
30
+
31
+ /**
32
+ * Detect artifact profile from WebAssembly.Module imports.
33
+ * Returns "standalone" (WASI-only), "sdn-abi" (WASI + sdn_host),
34
+ * or "emscripten" (env.* with invoke trampolines).
35
+ */
36
+ export function detectArtifactProfile(wasmModule) {
37
+ const imports = WebAssembly.Module.imports(wasmModule);
38
+ const moduleNames = new Set(imports.map((i) => i.module));
39
+
40
+ if (moduleNames.has("env")) {
41
+ const envImports = imports.filter((i) => i.module === "env");
42
+ const hasInvokeTrampolines = envImports.some((i) => i.name.startsWith("invoke_"));
43
+ const hasPthreads = envImports.some(
44
+ (i) => i.name.includes("pthread") || i.name.includes("thread"),
45
+ );
46
+ if (hasInvokeTrampolines || hasPthreads) {
47
+ return "emscripten";
48
+ }
49
+ }
50
+
51
+ if (moduleNames.has(DEFAULT_HOSTCALL_IMPORT_MODULE)) {
52
+ return "sdn-abi";
53
+ }
54
+
55
+ if (moduleNames.has("wasi_snapshot_preview1") || moduleNames.has("wasi_unstable")) {
56
+ return "standalone";
57
+ }
58
+
59
+ return "unknown";
60
+ }
61
+
62
+ async function compileWasmModule(source) {
63
+ if (source instanceof WebAssembly.Module) {
64
+ return source;
65
+ }
66
+ if (source instanceof Response) {
67
+ return WebAssembly.compileStreaming(source);
68
+ }
69
+ if (typeof source === "string") {
70
+ return WebAssembly.compileStreaming(fetch(source));
71
+ }
72
+ const bytes = source instanceof ArrayBuffer ? new Uint8Array(source) : source;
73
+ return WebAssembly.compile(bytes);
74
+ }
75
+
76
+ async function instantiateBrowserModule(options = {}) {
77
+ const wasi = createBrowserWasiShim({
78
+ args: options.args ?? [],
79
+ env: options.env ?? {},
80
+ stdinBytes: options.stdinBytes ?? new Uint8Array(),
81
+ logOutput: options.logOutput === true,
82
+ performance: options.performance,
83
+ });
84
+ const importObject = { ...wasi.imports };
85
+ const moduleImports = WebAssembly.Module.imports(options.wasmModule);
86
+ const needsHostBridge = moduleImports.some(
87
+ (entry) => entry.module === DEFAULT_HOSTCALL_IMPORT_MODULE,
88
+ );
89
+
90
+ let instance = null;
91
+ let bridge = null;
92
+ if (needsHostBridge) {
93
+ const dispatch = createNodeHostSyncDispatcher(options.host);
94
+ bridge = createJsonHostcallBridge({
95
+ dispatch,
96
+ getMemory: () => instance.exports.memory,
97
+ });
98
+ Object.assign(importObject, bridge.imports);
99
+ }
100
+
101
+ instance = await WebAssembly.instantiate(options.wasmModule, importObject);
102
+ if (instance.exports.memory) {
103
+ wasi.setMemory(instance.exports.memory);
104
+ }
105
+ if (instance.exports._initialize) {
106
+ instance.exports._initialize();
107
+ }
108
+
109
+ return {
110
+ instance,
111
+ bridge,
112
+ wasi,
113
+ };
114
+ }
115
+
116
+ /**
117
+ * Create a browser-side module harness for a standalone WASI artifact.
118
+ *
119
+ * @param {Object} options
120
+ * @param {Uint8Array|ArrayBuffer|Response|string} options.wasmSource
121
+ * WASM bytes, ArrayBuffer, fetch Response, or URL string.
122
+ * @param {Object} [options.host] - BrowserHost instance (created if omitted).
123
+ * @param {string[]} [options.args] - WASI args passed to the module.
124
+ * @param {Object} [options.env] - WASI environment variables.
125
+ * @param {string} [options.surface] - "direct" or "command" (default: auto-detect).
126
+ */
127
+ export async function createBrowserModuleHarness(options = {}) {
128
+ const host = options.host ?? createBrowserHost(options.hostOptions);
129
+ const wasmModule = await compileWasmModule(options.wasmSource);
130
+
131
+ const profile = detectArtifactProfile(wasmModule);
132
+ const moduleExports = WebAssembly.Module.exports(wasmModule);
133
+ const exportNames = new Set(moduleExports.map((e) => e.name));
134
+
135
+ const hasDirectInvoke = exportNames.has(DefaultInvokeExports.invokeSymbol);
136
+ const hasCommand = exportNames.has(DefaultInvokeExports.commandSymbol);
137
+ const surface =
138
+ options.surface ?? (hasDirectInvoke ? "direct" : hasCommand ? "command" : "direct");
139
+ if (profile === "emscripten") {
140
+ throw new Error(
141
+ "Browser harness only supports standalone WASI or sdn_host artifacts. " +
142
+ 'Compile shared browser/WasmEdge modules with runtimeTargets: ["browser", "wasmedge"] ' +
143
+ 'or override threadModel to "single-thread".',
144
+ );
145
+ }
146
+
147
+ const activeContext = await instantiateBrowserModule({
148
+ wasmModule,
149
+ host,
150
+ args: options.args,
151
+ env: options.env,
152
+ performance: options.performance ?? host?.performance,
153
+ logOutput: options.logOutput === true,
154
+ });
155
+ const { instance, bridge, wasi } = activeContext;
156
+
157
+ // --- Invoke helpers ---
158
+ function invokeDirectRaw(requestBytes) {
159
+ const alloc = instance.exports[DefaultInvokeExports.allocSymbol];
160
+ const free = instance.exports[DefaultInvokeExports.freeSymbol];
161
+ const invokeStream = instance.exports[DefaultInvokeExports.invokeSymbol];
162
+ const memory = instance.exports.memory;
163
+ if (
164
+ typeof alloc !== "function" ||
165
+ typeof free !== "function" ||
166
+ typeof invokeStream !== "function" ||
167
+ !memory
168
+ ) {
169
+ throw new Error(
170
+ "Direct browser invoke requires plugin_alloc, plugin_free, plugin_invoke_stream, and memory exports.",
171
+ );
172
+ }
173
+ const reqLen = requestBytes.length;
174
+ const reqPtr = alloc(reqLen);
175
+ if (!reqPtr) throw new Error("plugin_alloc returned null for request.");
176
+
177
+ new Uint8Array(memory.buffer, reqPtr, reqLen).set(requestBytes);
178
+
179
+ // Allocate space for the response length output
180
+ const outLenPtr = alloc(4);
181
+ if (!outLenPtr) throw new Error("plugin_alloc returned null for response length.");
182
+
183
+ new DataView(memory.buffer).setUint32(outLenPtr, 0, true);
184
+
185
+ const resPtr = invokeStream(reqPtr, reqLen, outLenPtr);
186
+ const resLen = new DataView(memory.buffer).getUint32(outLenPtr, true);
187
+
188
+ free(reqPtr, reqLen);
189
+ free(outLenPtr, 4);
190
+
191
+ if (!resPtr || !resLen) {
192
+ throw new Error("plugin_invoke_stream returned null response.");
193
+ }
194
+
195
+ const responseBytes = new Uint8Array(memory.buffer, resPtr, resLen).slice();
196
+ free(resPtr, resLen);
197
+ return responseBytes;
198
+ }
199
+
200
+ async function invokeCommandRaw(stdinBytes) {
201
+ const commandContext = await instantiateBrowserModule({
202
+ wasmModule,
203
+ host,
204
+ args: options.args,
205
+ env: options.env,
206
+ stdinBytes,
207
+ performance: options.performance ?? host?.performance,
208
+ logOutput: false,
209
+ });
210
+ try {
211
+ const commandExport = commandContext.instance.exports[DefaultInvokeExports.commandSymbol];
212
+ if (typeof commandExport !== "function") {
213
+ throw new Error(
214
+ `Command-surface browser invoke requires the ${DefaultInvokeExports.commandSymbol} export.`,
215
+ );
216
+ }
217
+ commandExport();
218
+ } catch (error) {
219
+ if (!(error instanceof WasiExitError) || error.code !== 0) {
220
+ throw error;
221
+ }
222
+ }
223
+ return commandContext.wasi.stdout;
224
+ }
225
+
226
+ // --- Public API ---
227
+
228
+ async function invokeRaw(requestBytes) {
229
+ if (surface === "command") {
230
+ return invokeCommandRaw(requestBytes);
231
+ }
232
+ return invokeDirectRaw(requestBytes);
233
+ }
234
+
235
+ async function invoke(request) {
236
+ const requestBytes = encodePluginInvokeRequest(request);
237
+ const responseBytes = await invokeRaw(requestBytes);
238
+ return decodePluginInvokeResponse(responseBytes);
239
+ }
240
+
241
+ function readManifest() {
242
+ const getBytesExport =
243
+ instance.exports[DefaultManifestExports.pluginBytesSymbol];
244
+ const getSizeExport =
245
+ instance.exports[DefaultManifestExports.pluginSizeSymbol];
246
+ if (!getBytesExport || !getSizeExport) return null;
247
+
248
+ const ptr = getBytesExport();
249
+ const size = getSizeExport();
250
+ if (!ptr || !size) return null;
251
+
252
+ return new Uint8Array(instance.exports.memory.buffer, ptr, size).slice();
253
+ }
254
+
255
+ function destroy() {
256
+ wasi.flushOutput();
257
+ }
258
+
259
+ return {
260
+ runtime: {
261
+ kind: "browser",
262
+ profile,
263
+ surface,
264
+ },
265
+ instance,
266
+ module: wasmModule,
267
+ host,
268
+ bridge,
269
+ wasi,
270
+ invoke,
271
+ invokeRaw,
272
+ readManifest,
273
+ destroy,
274
+ };
275
+ }
@@ -1,5 +1,6 @@
1
1
  import { accessSync, existsSync } from "node:fs";
2
2
  import { execFile } from "node:child_process";
3
+ import os from "node:os";
3
4
  import path from "node:path";
4
5
  import process from "node:process";
5
6
  import { promisify } from "node:util";
@@ -63,12 +64,50 @@ export function resolveWasmEdgeRunnerSourcePath() {
63
64
  );
64
65
  }
65
66
 
67
+ function resolveDefaultWasmEdgeInstall() {
68
+ const home = os.homedir();
69
+ const candidates = [
70
+ {
71
+ includeDir: path.join(home, ".wasmedge", "include"),
72
+ libDir: path.join(home, ".wasmedge", "lib"),
73
+ },
74
+ {
75
+ includeDir: "/opt/homebrew/include",
76
+ libDir: "/opt/homebrew/opt/wasmedge/lib",
77
+ },
78
+ {
79
+ includeDir: "/usr/local/include",
80
+ libDir: "/usr/local/lib",
81
+ },
82
+ ];
83
+ for (const candidate of candidates) {
84
+ const header = path.join(
85
+ candidate.includeDir,
86
+ "wasmedge",
87
+ "enum_configure.h",
88
+ );
89
+ const library = path.join(
90
+ candidate.libDir,
91
+ resolveWasmEdgeSharedLibraryFilename(),
92
+ );
93
+ if (existsSync(header) && existsSync(library)) {
94
+ return candidate;
95
+ }
96
+ }
97
+ return null;
98
+ }
99
+
66
100
  export function resolveWasmEdgeRunnerBuildPlan(options = {}) {
101
+ const detectedInstall = resolveDefaultWasmEdgeInstall();
67
102
  const requestedIncludeDir = normalizeResolvedPath(
68
- options.wasmedgeIncludeDir ?? process.env.WASMEDGE_INCLUDE_DIR,
103
+ options.wasmedgeIncludeDir ??
104
+ process.env.WASMEDGE_INCLUDE_DIR ??
105
+ detectedInstall?.includeDir,
69
106
  );
70
107
  const wasmedgeLibDir = normalizeResolvedPath(
71
- options.wasmedgeLibDir ?? process.env.WASMEDGE_LIB_DIR,
108
+ options.wasmedgeLibDir ??
109
+ process.env.WASMEDGE_LIB_DIR ??
110
+ detectedInstall?.libDir,
72
111
  );
73
112
  const outputPath = normalizeResolvedPath(
74
113
  options.outputPath ?? options.output,
@@ -131,7 +131,55 @@ export interface PluginInvokeProcessLaunchPlan {
131
131
  args: string[];
132
132
  env?: Record<string, string | undefined>;
133
133
  cwd?: string;
134
- wasmPath?: string;
134
+ wasmPath?: string | null;
135
+ hostProfile?: "runtime-host";
136
+ }
137
+
138
+ export interface RuntimeHostTestModuleDefinition {
139
+ moduleId: string;
140
+ wasmPath?: string | null;
141
+ metadata?: unknown;
142
+ [key: string]: unknown;
143
+ }
144
+
145
+ export interface RuntimeHostInstalledModule {
146
+ moduleId: string;
147
+ metadata: unknown;
148
+ methodIds: string[];
149
+ }
150
+
151
+ export interface RuntimeHostRowHandle {
152
+ schemaFileId: string;
153
+ rowId: number;
154
+ }
155
+
156
+ export interface RuntimeHostRowView {
157
+ handle: RuntimeHostRowHandle;
158
+ payload: unknown;
159
+ }
160
+
161
+ export interface RuntimeHostRowQueryResult {
162
+ columns: string[];
163
+ rows: unknown[][];
164
+ rowCount: number;
165
+ }
166
+
167
+ export interface RuntimeHostRegionDescriptor {
168
+ regionId: number;
169
+ layoutId: string;
170
+ recordByteLength: number;
171
+ alignment: number;
172
+ recordCount: number;
173
+ }
174
+
175
+ export interface RuntimeHostRegionRecord {
176
+ regionId: number;
177
+ recordIndex: number;
178
+ layoutId: string;
179
+ recordByteLength: number;
180
+ alignment: number;
181
+ byteLength: number;
182
+ bytes: Uint8Array;
135
183
  }
136
184
 
137
185
  export interface PluginInvokeProcessClient {
@@ -140,12 +188,42 @@ export interface PluginInvokeProcessClient {
140
188
  invoke(request: {
141
189
  methodId?: string | null;
142
190
  inputs?: HarnessInputFrame[];
191
+ }): Promise<{
192
+ statusCode: number;
193
+ errorCode?: string | null;
194
+ errorMessage?: string | null;
195
+ outputs: HarnessInputFrame[];
196
+ }>;
197
+ installModule(definition: RuntimeHostTestModuleDefinition): Promise<RuntimeHostInstalledModule>;
198
+ listModules(): Promise<RuntimeHostInstalledModule[]>;
199
+ unloadModule(moduleId: string): Promise<boolean>;
200
+ invokeModule(requestModuleId: string, request: {
201
+ methodId?: string | null;
202
+ inputs?: HarnessInputFrame[];
143
203
  }): Promise<{
144
204
  statusCode: number;
145
205
  errorCode?: string | null;
146
206
  errorMessage?: string | null;
147
207
  outputs: HarnessInputFrame[];
148
208
  }>;
209
+ appendRow(options: {
210
+ schemaFileId: string;
211
+ payload?: unknown;
212
+ }): Promise<RuntimeHostRowHandle>;
213
+ listRows(schemaFileId?: string | null): Promise<RuntimeHostRowView[]>;
214
+ resolveRow(handle: RuntimeHostRowHandle): Promise<RuntimeHostRowView | null>;
215
+ queryRows(sql: string): Promise<RuntimeHostRowQueryResult>;
216
+ allocateRegion(options: {
217
+ layoutId: string;
218
+ recordByteLength: number;
219
+ alignment?: number;
220
+ initialRecords?: Array<Uint8Array | ArrayBuffer | ArrayBufferView | null | undefined>;
221
+ }): Promise<RuntimeHostRegionDescriptor>;
222
+ describeRegion(regionId: number): Promise<RuntimeHostRegionDescriptor | null>;
223
+ resolveRecord(query: {
224
+ regionId: number;
225
+ recordIndex: number;
226
+ }): Promise<RuntimeHostRegionRecord | null>;
149
227
  destroy(): Promise<void>;
150
228
  }
151
229
 
@@ -160,6 +238,10 @@ export interface ModuleHarnessRuntimeDescriptor {
160
238
  wasmEdgeBinary?: string;
161
239
  wasmEdgeRunnerBinary?: string;
162
240
  enableThreads?: boolean;
241
+ hostProfile?: "runtime-host";
242
+ modules?: RuntimeHostTestModuleDefinition[];
243
+ defaultModuleId?: string;
244
+ metadata?: unknown;
163
245
  }
164
246
 
165
247
  export interface ModuleHarness {
@@ -169,12 +251,42 @@ export interface ModuleHarness {
169
251
  invoke(request: {
170
252
  methodId?: string | null;
171
253
  inputs?: HarnessInputFrame[];
254
+ }): Promise<{
255
+ statusCode: number;
256
+ errorCode?: string | null;
257
+ errorMessage?: string | null;
258
+ outputs: HarnessInputFrame[];
259
+ }>;
260
+ installModule(definition: RuntimeHostTestModuleDefinition): Promise<RuntimeHostInstalledModule>;
261
+ listModules(): Promise<RuntimeHostInstalledModule[]>;
262
+ unloadModule(moduleId: string): Promise<boolean>;
263
+ invokeModule(moduleId: string, request: {
264
+ methodId?: string | null;
265
+ inputs?: HarnessInputFrame[];
172
266
  }): Promise<{
173
267
  statusCode: number;
174
268
  errorCode?: string | null;
175
269
  errorMessage?: string | null;
176
270
  outputs: HarnessInputFrame[];
177
271
  }>;
272
+ appendRow(options: {
273
+ schemaFileId: string;
274
+ payload?: unknown;
275
+ }): Promise<RuntimeHostRowHandle>;
276
+ listRows(schemaFileId?: string | null): Promise<RuntimeHostRowView[]>;
277
+ resolveRow(handle: RuntimeHostRowHandle): Promise<RuntimeHostRowView | null>;
278
+ queryRows(sql: string): Promise<RuntimeHostRowQueryResult>;
279
+ allocateRegion(options: {
280
+ layoutId: string;
281
+ recordByteLength: number;
282
+ alignment?: number;
283
+ initialRecords?: Array<Uint8Array | ArrayBuffer | ArrayBufferView | null | undefined>;
284
+ }): Promise<RuntimeHostRegionDescriptor>;
285
+ describeRegion(regionId: number): Promise<RuntimeHostRegionDescriptor | null>;
286
+ resolveRecord(query: {
287
+ regionId: number;
288
+ recordIndex: number;
289
+ }): Promise<RuntimeHostRegionRecord | null>;
178
290
  destroy(): Promise<void>;
179
291
  }
180
292
 
@@ -205,6 +317,40 @@ export function createPublicationProtectionDemoSummary(options?: {
205
317
  };
206
318
  }): Promise<PublicationProtectionDemoSummary>;
207
319
 
320
+ export interface BrowserModuleHarness {
321
+ runtime: {
322
+ kind: "browser";
323
+ profile: string;
324
+ surface: string;
325
+ };
326
+ instance: WebAssembly.Instance;
327
+ module: WebAssembly.Module;
328
+ host: unknown;
329
+ bridge: unknown;
330
+ wasi: {
331
+ imports: Record<string, Record<string, (...args: number[]) => number>>;
332
+ setMemory(mem: { buffer: ArrayBuffer | SharedArrayBuffer }): void;
333
+ getMemory(): { buffer: ArrayBuffer | SharedArrayBuffer } | null;
334
+ flushOutput(): void;
335
+ stdout: Uint8Array;
336
+ stderr: Uint8Array;
337
+ };
338
+ invokeRaw(
339
+ requestBytes: Uint8Array | ArrayBuffer | ArrayBufferView,
340
+ ): Promise<Uint8Array>;
341
+ invoke(request: {
342
+ methodId?: string | null;
343
+ inputs?: HarnessInputFrame[];
344
+ }): Promise<{
345
+ statusCode: number;
346
+ errorCode?: string | null;
347
+ errorMessage?: string | null;
348
+ outputs: HarnessInputFrame[];
349
+ }>;
350
+ readManifest(): Uint8Array | null;
351
+ destroy(): void;
352
+ }
353
+
208
354
  export function generateManifestHarnessPlan(options: {
209
355
  manifest: PluginManifest;
210
356
  includeOptionalInputs?: boolean;
@@ -234,12 +380,13 @@ export function buildWasmEdgeSpawnEnv(
234
380
  ): Record<string, string | undefined>;
235
381
 
236
382
  export function resolveWasmEdgePluginLaunchPlan(options: {
237
- wasmPath: string;
383
+ wasmPath?: string;
238
384
  wasmEdgeBinary?: string;
239
385
  wasmEdgeRunnerBinary?: string;
240
386
  enableThreads?: boolean;
241
387
  invokeArgs?: string[];
242
388
  env?: Record<string, string | undefined>;
389
+ hostProfile?: "runtime-host";
243
390
  }): PluginInvokeProcessLaunchPlan;
244
391
 
245
392
  export function createPluginInvokeProcessClient(options: {
@@ -250,10 +397,34 @@ export function createPluginInvokeProcessClient(options: {
250
397
  cwd?: string;
251
398
  }): Promise<PluginInvokeProcessClient>;
252
399
 
400
+ export function createWasmEdgeStreamProcessClient(options: {
401
+ launchPlan?: PluginInvokeProcessLaunchPlan;
402
+ command?: string;
403
+ args?: string[];
404
+ env?: Record<string, string | undefined>;
405
+ cwd?: string;
406
+ }): Promise<PluginInvokeProcessClient>;
407
+
253
408
  export function resolveModuleHarnessLaunchPlan(options: {
254
409
  runtime?: ModuleHarnessRuntimeDescriptor;
255
410
  } | ModuleHarnessRuntimeDescriptor): PluginInvokeProcessLaunchPlan;
256
411
 
412
+ export function detectArtifactProfile(wasmModule: WebAssembly.Module): string;
413
+
414
+ export function createBrowserModuleHarness(options?: {
415
+ wasmSource: Uint8Array | ArrayBuffer | string | WebAssembly.Module | unknown;
416
+ host?: unknown;
417
+ hostOptions?: unknown;
418
+ args?: string[];
419
+ env?: Record<string, string>;
420
+ surface?: "direct" | "command";
421
+ performance?: {
422
+ now(): number;
423
+ timeOrigin: number;
424
+ };
425
+ logOutput?: boolean;
426
+ }): Promise<BrowserModuleHarness>;
427
+
257
428
  export function createModuleHarness(options: {
258
429
  runtime?: ModuleHarnessRuntimeDescriptor;
259
430
  } | ModuleHarnessRuntimeDescriptor): Promise<ModuleHarness>;
@@ -7,9 +7,14 @@ export {
7
7
  createPublicationProtectionDemoManifest,
8
8
  createPublicationProtectionDemoSummary,
9
9
  } from "./publicationProtectionDemo.js";
10
+ export {
11
+ createBrowserModuleHarness,
12
+ detectArtifactProfile,
13
+ } from "./browserModuleHarness.js";
10
14
  export {
11
15
  buildWasmEdgeSpawnEnv,
12
16
  createPluginInvokeProcessClient,
17
+ createWasmEdgeStreamProcessClient,
13
18
  resolveWasmEdgePluginLaunchPlan,
14
19
  } from "./processInvoke.js";
15
20
  export {