space-data-module-sdk 0.5.8 → 0.5.10

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 CHANGED
@@ -1,9 +1,9 @@
1
1
  # Space Data Module SDK
2
2
 
3
- `space-data-module-sdk` defines the canonical module artifact for the Space Data
4
- stack: WebAssembly code, an embedded FlatBuffer manifest, a stable capability
5
- vocabulary, a single-file bundle format, and the signing and transport records
6
- used to move modules between hosts.
3
+ `space-data-module-sdk` defines the canonical Space Data module architecture for
4
+ WebAssembly artifacts: an embedded FlatBuffer manifest, canonical ABI exports,
5
+ a stable capability vocabulary, single-file packaging, and the signing and
6
+ transport records used to move modules between hosts.
7
7
 
8
8
  This repository is the source of truth for module-level concerns:
9
9
 
@@ -11,17 +11,34 @@ This repository is the source of truth for module-level concerns:
11
11
  - embedded manifest exports inside `.wasm` modules
12
12
  - standards-aware compliance and capability validation
13
13
  - module compilation and protection
14
- - the `sds.bundle` single-file custom section
14
+ - the `sds.bundle` single-file container
15
15
  - deployment authorization plus SDS publication records (`REC`, `PNM`, `ENC`)
16
16
  - the first canonical module hostcall/import ABI surface
17
+ - shared module-level testing/runtime harnesses, including the WasmEdge
18
+ process runner used by package-level validation suites
17
19
 
18
20
  <p align="center">
19
21
  <img src="docs/architecture.svg" alt="Module architecture overview" width="820" />
20
22
  </p>
21
23
 
22
- ## Artifact Model
24
+ ## Shared Harness Ownership
23
25
 
24
- A module built with this SDK is a `.wasm` artifact with:
26
+ This repo owns the generic module-side runtime harnesses used across the stack:
27
+
28
+ - `createModuleHarness(...)` for process and WasmEdge-backed module invocation
29
+ - `resolveModuleHarnessLaunchPlan(...)` for portable launch planning
30
+ - `buildWasmEdgeEmscriptenPthreadRunner(...)` plus the shared native runner
31
+ source and runner-level pthread smoke test
32
+
33
+ Flow-specific standalone harnessing lives in `sdn-flow`, which layers flow
34
+ enqueue/drain behavior on top of its compiled standalone runtime host. Package-
35
+ specific validation suites, including conjunction replay/V&V, are expected to
36
+ sit on top of these shared harnesses instead of defining their own runtime
37
+ process model.
38
+
39
+ ## Module Artifact Model
40
+
41
+ A compliant module built with this SDK is always a valid `.wasm` artifact with:
25
42
 
26
43
  - an embedded `PluginManifest.fbs`
27
44
  - exported manifest accessors:
@@ -37,10 +54,15 @@ A module built with this SDK is a `.wasm` artifact with:
37
54
  - resolved deployment plans and input bindings
38
55
  - deployment authorization
39
56
  - auxiliary FlatBuffer or raw payloads
40
- - optional appended SDS `REC` publication trailers carrying:
57
+ - optional appended SDS FlatBuffer publication records in a trailing `REC`
58
+ container carrying:
41
59
  - `PNM` digital-signature/publication metadata
42
60
  - `ENC` encrypted-delivery metadata
43
- - auxiliary FlatBuffer or raw payloads
61
+
62
+ Single-file bundling does not append arbitrary bytes to the end of the wasm
63
+ module. The one-file module container is `sds.bundle`, stored as a standard
64
+ wasm custom section. Appended bytes are reserved for SDS publication records
65
+ such as `PNM` and `ENC`, wrapped in a trailing `REC` FlatBuffer collection.
44
66
 
45
67
  The module contract stays the same whether the artifact is loaded directly,
46
68
  wrapped in a deployment envelope, or shipped as one bundled `.wasm` file.
@@ -65,7 +87,7 @@ same request bytes from guest memory and returns response bytes in guest
65
87
  memory.
66
88
 
67
89
  For simple single-input / single-output methods, command mode also supports a
68
- degenerate raw shortcut:
90
+ raw shortcut:
69
91
 
70
92
  ```bash
71
93
  wasmedge module.wasm --method echo < input.fb > output.fb
@@ -101,8 +123,8 @@ anywhere it can:
101
123
  - read FlatBuffers
102
124
  - honor the module capability and host ABI contract
103
125
 
104
- That target set matches the WebAssembly and FlatBuffers runtime families already
105
- used in the companion `flatbuffers/wasm` work:
126
+ That architecture is intended to stay portable across the common WebAssembly
127
+ and FlatBuffer host environments:
106
128
 
107
129
  - browser
108
130
  - Node.js
@@ -126,26 +148,11 @@ This repo currently includes:
126
148
  - a reference Node host and sync `sdn_host` bridge for the first hostcall
127
149
  surface
128
150
 
129
- ## Testing
130
-
131
- This repo now exposes a manifest-driven harness generator from
132
- `space-data-module-sdk/testing` and two complementary integration suites:
133
-
134
- - `npm run test:runtime-matrix`
135
- - cross-language runtime smoke across the same WASM in Node.js, Go, Python,
136
- Rust, Java, C#, and Swift
137
- - covers method calling, aligned-binary envelope metadata preservation,
138
- stdin/stdout/stderr, args, env, preopened filesystem access, and basic WASI
139
- clock/time smoke
140
- - `npm run test:host-surfaces`
141
- - authoritative Node-host coverage for HTTP, TCP, UDP, TLS, WebSocket, MQTT,
142
- process execution, timers, filesystem, and the sync `sdn_host` ABI
151
+ ## Runtime Targets
143
152
 
144
- The detailed edge cases and the current WASI-vs-host portability boundary are
145
- documented in
146
- [`docs/testing-harness.md`](./docs/testing-harness.md).
153
+ Manifests can declare coarse runtime targets in `manifest.runtimeTargets`.
147
154
 
148
- If a manifest declares `runtimeTargets: ["wasi"]`, this SDK now treats that as
155
+ If a manifest declares `runtimeTargets: ["wasi"]`, this SDK treats that as
149
156
  "standalone WASI, no host wrapper required." In practice that currently means:
150
157
 
151
158
  - the artifact must declare the `command` invoke surface
@@ -153,15 +160,14 @@ If a manifest declares `runtimeTargets: ["wasi"]`, this SDK now treats that as
153
160
  `logging`, `clock`, `random`, `filesystem`, `pipe`
154
161
  - hosted protocols may only use `wasi-pipe` transport
155
162
 
156
- For maximum server-side portability with guest-owned network services, use
157
- `runtimeTargets: ["wasmedge"]`. That target is intended for WasmEdge
158
- environments with socket/TLS extensions, while plain `wasi` remains the strict
159
- no-wrapper baseline. The Node-RED-oriented parity map lives in
160
- [`docs/node-red-default-node-parity.md`](./docs/node-red-default-node-parity.md).
163
+ If a manifest declares `runtimeTargets: ["wasmedge"]`, this SDK treats that as
164
+ the preferred server-side target when the guest needs network-oriented runtime
165
+ features such as sockets or TLS. Plain `wasi` remains the strict portability
166
+ baseline; `wasmedge` is the practical higher-capability target.
161
167
 
162
168
  ## WasmEdge Pthreads
163
169
 
164
- `space-data-module-sdk` is the source of truth for module thread-model
170
+ `space-data-module-sdk` is also the source of truth for module thread-model
165
171
  selection.
166
172
 
167
173
  - `compileModuleFromSource({ threadModel })` accepts an explicit thread model.
@@ -174,10 +180,39 @@ toolchain. They require a real system Emscripten installation on `PATH`, and
174
180
  the compiler result plus guest-link bundle metadata preserve the selected
175
181
  `threadModel`.
176
182
 
177
- This SDK does not treat Cesium `TaskProcessor`, ad hoc JS worker pools, or
178
- host-side fake orchestration as a substitute for guest pthread support. If a
179
- runtime cannot interoperate with the guest contract directly, document that as a
180
- wrapper requirement instead of changing the guest artifact semantics.
183
+ As emitted by current Emscripten, these pthread artifacts still import
184
+ Emscripten `env.*` host functions plus imported shared memory. That means a
185
+ bare `wasmedge` CLI invocation is not yet the direct execution path for them;
186
+ they currently require a WasmEdge-side host shim that satisfies the Emscripten
187
+ pthread contract.
188
+
189
+ If a runtime cannot interoperate with the guest pthread contract directly,
190
+ document that as a wrapper requirement instead of changing the guest artifact
191
+ semantics.
192
+
193
+ ## Testing
194
+
195
+ This repo now exposes a manifest-driven harness generator from
196
+ `space-data-module-sdk/testing` and two complementary integration suites:
197
+
198
+ - shared process-level helpers for command-surface runtimes:
199
+ - `createPluginInvokeProcessClient(...)`
200
+ - `resolveWasmEdgePluginLaunchPlan(...)`
201
+ - `buildWasmEdgeEmscriptenPthreadRunner(...)`
202
+
203
+ - `npm run test:runtime-matrix`
204
+ - cross-language runtime smoke across the same WASM in Node.js, Go, Python,
205
+ Rust, Java, C#, and Swift
206
+ - covers method calling, aligned-binary envelope metadata preservation,
207
+ stdin/stdout/stderr, args, env, preopened filesystem access, and basic WASI
208
+ clock/time smoke
209
+ - `npm run test:host-surfaces`
210
+ - authoritative Node-host coverage for HTTP, TCP, UDP, TLS, WebSocket, MQTT,
211
+ process execution, timers, filesystem, and the sync `sdn_host` ABI
212
+
213
+ The detailed edge cases and the current WASI-vs-host portability boundary are
214
+ documented in
215
+ [`docs/testing-harness.md`](./docs/testing-harness.md).
181
216
 
182
217
  ## Install
183
218
 
@@ -196,6 +231,8 @@ import {
196
231
  validateManifestWithStandards,
197
232
  } from "space-data-module-sdk";
198
233
 
234
+ manifest.runtimeTargets = ["wasmedge"];
235
+
199
236
  const manifestBytes = encodePluginManifest(manifest);
200
237
  const validation = await validateManifestWithStandards(manifest);
201
238
  if (!validation.ok) {
@@ -265,10 +302,11 @@ The full contract split is documented in
265
302
 
266
303
  `sds.bundle` keeps module delivery to one file without changing WebAssembly
267
304
  loadability for the runtime payload itself. The SDK writes the bundle as a
268
- standard custom section inside the wasm module and, when the artifact is
269
- signed or encrypted for publication, appends an SDS `REC` trailer after the
270
- wasm bytes. Loaders must scan and strip that trailer before handing bytes to a
271
- runtime such as WasmEdge.
305
+ standard custom section inside the wasm module. When the artifact is signed or
306
+ encrypted for publication, SDS appends FlatBuffer publication records after the
307
+ wasm bytes in a trailing `REC` container. Loaders must scan from the end,
308
+ resolve `PNM` / `ENC`, strip or decrypt as needed, and only then hand the
309
+ remaining raw wasm bytes to a runtime such as WasmEdge.
272
310
 
273
311
  The reference path lives in
274
312
  [`examples/single-file-bundle`](./examples/single-file-bundle):
@@ -285,7 +323,7 @@ for resolved protocol installations and producer input bindings.
285
323
 
286
324
  ## Module Publication
287
325
 
288
- Packages that publish SDN modules now use the canonical `sdn-module`
326
+ Packages that publish Space Data modules use the canonical `sdn-module`
289
327
  publication descriptor. That descriptor covers:
290
328
 
291
329
  - standalone module packages
@@ -345,7 +383,7 @@ includes:
345
383
 
346
384
  Manifests can also declare coarse runtime targets for planning and compliance:
347
385
 
348
- `node` `browser` `wasi` `server` `desktop` `edge`
386
+ `node` `browser` `wasi` `wasmedge` `server` `desktop` `edge`
349
387
 
350
388
  ## Environment Notes
351
389
 
@@ -401,7 +439,8 @@ npm run check:compliance
401
439
  ```
402
440
 
403
441
  Node.js `>=20` is required. The compiler uses `sdn-emception` and `flatc-wasm`
404
- by default.
442
+ by default for the embedded toolchain path. WasmEdge pthread builds require a
443
+ system Emscripten toolchain on `PATH`.
405
444
 
406
445
  If another repo needs the same compiler runtime, the package also exposes a
407
446
  shared emception session at `space-data-module-sdk/compiler/emception` with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "space-data-module-sdk",
3
- "version": "0.5.8",
3
+ "version": "0.5.10",
4
4
  "description": "Module SDK for building, validating, signing, and deploying WebAssembly modules on the Space Data Network.",
5
5
  "type": "module",
6
6
  "types": "./src/index.d.ts",
package/src/index.d.ts CHANGED
@@ -662,12 +662,25 @@ export type {
662
662
  HarnessInvokeScenario,
663
663
  HarnessRawScenario,
664
664
  ManifestHarnessPlan,
665
+ ModuleHarness,
666
+ ModuleHarnessRuntimeDescriptor,
667
+ PluginInvokeProcessClient,
668
+ PluginInvokeProcessLaunchPlan,
669
+ WasmEdgeRunnerBuildPlan,
665
670
  } from "./testing/index.js";
666
671
 
667
672
  export {
673
+ buildWasmEdgeEmscriptenPthreadRunner,
674
+ buildWasmEdgeSpawnEnv,
675
+ createModuleHarness,
676
+ createPluginInvokeProcessClient,
668
677
  describeCapabilityRuntimeSurface,
669
678
  generateManifestHarnessPlan,
670
679
  materializeHarnessScenario,
680
+ resolveModuleHarnessLaunchPlan,
681
+ resolveWasmEdgeRunnerBuildPlan,
682
+ resolveWasmEdgeRunnerSourcePath,
683
+ resolveWasmEdgePluginLaunchPlan,
671
684
  serializeHarnessPlan,
672
685
  } from "./testing/index.js";
673
686
 
@@ -12,7 +12,7 @@ import { InvokeSurface } from "../generated/orbpro/manifest/invoke-surface.js";
12
12
  import { BufferMutability } from "../generated/orbpro/stream/buffer-mutability.js";
13
13
  import { BufferOwnership } from "../generated/orbpro/stream/buffer-ownership.js";
14
14
  import { FlatBufferTypeRefT } from "../generated/orbpro/stream/flat-buffer-type-ref.js";
15
- import { TypedArenaBuffer, TypedArenaBufferT } from "../generated/orbpro/stream/typed-arena-buffer.js";
15
+ import { TypedArenaBufferT } from "../generated/orbpro/stream/typed-arena-buffer.js";
16
16
  import { toUint8Array } from "../runtime/bufferLike.js";
17
17
 
18
18
  function toByteBuffer(data) {
@@ -149,20 +149,22 @@ function normalizeArenaFrame(frame = {}, offset) {
149
149
 
150
150
  function packArenaFrames(frames = []) {
151
151
  const packedFrames = [];
152
- const arena = [];
152
+ const normalizedFrames = [];
153
153
  let offset = 0;
154
154
  for (const frame of frames) {
155
155
  const normalized = normalizeArenaFrame(frame, offset);
156
- for (let index = 0; index < normalized.padding; index += 1) {
157
- arena.push(0);
158
- }
159
- arena.push(...normalized.payload);
160
156
  offset = normalized.buffer.offset + normalized.buffer.size;
161
157
  packedFrames.push(normalized.buffer);
158
+ normalizedFrames.push(normalized);
159
+ }
160
+
161
+ const arena = new Uint8Array(offset);
162
+ for (const normalized of normalizedFrames) {
163
+ arena.set(normalized.payload, normalized.buffer.offset);
162
164
  }
163
165
  return {
164
166
  frames: packedFrames,
165
- arena: Uint8Array.from(arena),
167
+ arena,
166
168
  };
167
169
  }
168
170
 
@@ -0,0 +1,214 @@
1
+ import { accessSync, existsSync } from "node:fs";
2
+ import { execFile } from "node:child_process";
3
+ import path from "node:path";
4
+ import process from "node:process";
5
+ import { promisify } from "node:util";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const execFileAsync = promisify(execFile);
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+
12
+ function normalizeResolvedPath(value) {
13
+ if (typeof value !== "string" || value.trim().length === 0) {
14
+ return null;
15
+ }
16
+ return path.resolve(value);
17
+ }
18
+
19
+ function ensureReadableSync(targetPath, label) {
20
+ try {
21
+ accessSync(targetPath);
22
+ } catch {
23
+ throw new Error(`${label} not found: ${targetPath}`);
24
+ }
25
+ }
26
+
27
+ function resolveWasmEdgeSharedLibraryFilename() {
28
+ if (process.platform === "darwin") {
29
+ return "libwasmedge.0.dylib";
30
+ }
31
+ if (process.platform === "win32") {
32
+ return "wasmedge.dll";
33
+ }
34
+ return "libwasmedge.so.0";
35
+ }
36
+
37
+ function resolveGeneratedIncludeDir(requestedIncludeDir) {
38
+ const directHeaderPath = path.join(
39
+ requestedIncludeDir,
40
+ "wasmedge",
41
+ "enum_configure.h",
42
+ );
43
+ if (existsSync(directHeaderPath)) {
44
+ return requestedIncludeDir;
45
+ }
46
+
47
+ const repoRoot = path.resolve(requestedIncludeDir, "..", "..");
48
+ const generatedDir = path.join(repoRoot, "build", "include", "api");
49
+ if (existsSync(path.join(generatedDir, "wasmedge", "enum_configure.h"))) {
50
+ return generatedDir;
51
+ }
52
+
53
+ throw new Error(
54
+ `WasmEdge include directory does not contain wasmedge/enum_configure.h: ${requestedIncludeDir}`,
55
+ );
56
+ }
57
+
58
+ export function resolveWasmEdgeRunnerSourcePath() {
59
+ return path.resolve(
60
+ __dirname,
61
+ "native",
62
+ "wasmedge_emscripten_pthread_runner.c",
63
+ );
64
+ }
65
+
66
+ export function resolveWasmEdgeRunnerBuildPlan(options = {}) {
67
+ const requestedIncludeDir = normalizeResolvedPath(
68
+ options.wasmedgeIncludeDir ?? process.env.WASMEDGE_INCLUDE_DIR,
69
+ );
70
+ const wasmedgeLibDir = normalizeResolvedPath(
71
+ options.wasmedgeLibDir ?? process.env.WASMEDGE_LIB_DIR,
72
+ );
73
+ const outputPath = normalizeResolvedPath(
74
+ options.outputPath ?? options.output,
75
+ );
76
+
77
+ if (!requestedIncludeDir) {
78
+ throw new Error(
79
+ "Missing WasmEdge include directory. Set wasmedgeIncludeDir, --wasmedge-include-dir, or WASMEDGE_INCLUDE_DIR.",
80
+ );
81
+ }
82
+ if (!wasmedgeLibDir) {
83
+ throw new Error(
84
+ "Missing WasmEdge library directory. Set wasmedgeLibDir, --wasmedge-lib-dir, or WASMEDGE_LIB_DIR.",
85
+ );
86
+ }
87
+ if (!outputPath) {
88
+ throw new Error("Missing runner outputPath.");
89
+ }
90
+
91
+ const runnerSourcePath = resolveWasmEdgeRunnerSourcePath();
92
+ const wasmedgeSharedLibraryPath = path.join(
93
+ wasmedgeLibDir,
94
+ resolveWasmEdgeSharedLibraryFilename(),
95
+ );
96
+
97
+ return {
98
+ runnerSourcePath,
99
+ requestedIncludeDir,
100
+ wasmedgeIncludeDir: requestedIncludeDir,
101
+ wasmedgeLibDir,
102
+ wasmedgeSharedLibraryPath,
103
+ outputPath,
104
+ compilerCommand:
105
+ process.platform === "darwin" ? "xcrun" : process.env.CC ?? "cc",
106
+ compilerArgs:
107
+ process.platform === "darwin"
108
+ ? [
109
+ "clang",
110
+ runnerSourcePath,
111
+ "-std=c11",
112
+ "-O2",
113
+ "-pthread",
114
+ "-Wall",
115
+ "-Wextra",
116
+ "-Werror",
117
+ "-Wno-unused-parameter",
118
+ "-Wno-error=visibility",
119
+ `-I${requestedIncludeDir}`,
120
+ `-L${wasmedgeLibDir}`,
121
+ "-lwasmedge",
122
+ `-Wl,-rpath,${wasmedgeLibDir}`,
123
+ "-o",
124
+ outputPath,
125
+ ]
126
+ : [
127
+ runnerSourcePath,
128
+ "-std=c11",
129
+ "-O2",
130
+ "-pthread",
131
+ "-Wall",
132
+ "-Wextra",
133
+ "-Werror",
134
+ "-Wno-unused-parameter",
135
+ "-Wno-error=visibility",
136
+ `-I${requestedIncludeDir}`,
137
+ `-L${wasmedgeLibDir}`,
138
+ "-lwasmedge",
139
+ `-Wl,-rpath,${wasmedgeLibDir}`,
140
+ "-o",
141
+ outputPath,
142
+ ],
143
+ };
144
+ }
145
+
146
+ export async function buildWasmEdgeEmscriptenPthreadRunner(options = {}) {
147
+ const basePlan = resolveWasmEdgeRunnerBuildPlan(options);
148
+ const wasmedgeIncludeDir = resolveGeneratedIncludeDir(
149
+ basePlan.requestedIncludeDir,
150
+ );
151
+ const compilerArgs =
152
+ process.platform === "darwin"
153
+ ? [
154
+ "clang",
155
+ basePlan.runnerSourcePath,
156
+ "-std=c11",
157
+ "-O2",
158
+ "-pthread",
159
+ "-Wall",
160
+ "-Wextra",
161
+ "-Werror",
162
+ "-Wno-unused-parameter",
163
+ "-Wno-error=visibility",
164
+ `-I${wasmedgeIncludeDir}`,
165
+ `-L${basePlan.wasmedgeLibDir}`,
166
+ "-lwasmedge",
167
+ `-Wl,-rpath,${basePlan.wasmedgeLibDir}`,
168
+ "-o",
169
+ basePlan.outputPath,
170
+ ]
171
+ : [
172
+ basePlan.runnerSourcePath,
173
+ "-std=c11",
174
+ "-O2",
175
+ "-pthread",
176
+ "-Wall",
177
+ "-Wextra",
178
+ "-Werror",
179
+ "-Wno-unused-parameter",
180
+ "-Wno-error=visibility",
181
+ `-I${wasmedgeIncludeDir}`,
182
+ `-L${basePlan.wasmedgeLibDir}`,
183
+ "-lwasmedge",
184
+ `-Wl,-rpath,${basePlan.wasmedgeLibDir}`,
185
+ "-o",
186
+ basePlan.outputPath,
187
+ ];
188
+ const plan = {
189
+ ...basePlan,
190
+ wasmedgeIncludeDir,
191
+ compilerArgs,
192
+ };
193
+
194
+ ensureReadableSync(plan.runnerSourcePath, "Runner source");
195
+ ensureReadableSync(plan.wasmedgeIncludeDir, "WasmEdge include directory");
196
+ ensureReadableSync(plan.wasmedgeLibDir, "WasmEdge library directory");
197
+ ensureReadableSync(
198
+ plan.wasmedgeSharedLibraryPath,
199
+ "WasmEdge shared library",
200
+ );
201
+
202
+ await execFileAsync(plan.compilerCommand, plan.compilerArgs, {
203
+ cwd: options.cwd ?? process.cwd(),
204
+ });
205
+ if (process.platform === "darwin") {
206
+ await execFileAsync("install_name_tool", [
207
+ "-change",
208
+ "@rpath/libwasmedge.0.dylib",
209
+ plan.wasmedgeSharedLibraryPath,
210
+ plan.outputPath,
211
+ ]);
212
+ }
213
+ return plan.outputPath;
214
+ }
@@ -57,6 +57,69 @@ export interface ManifestHarnessPlan {
57
57
  scenarios: Array<HarnessInvokeScenario | HarnessRawScenario>;
58
58
  }
59
59
 
60
+ export interface PluginInvokeProcessLaunchPlan {
61
+ command: string;
62
+ args: string[];
63
+ env?: Record<string, string | undefined>;
64
+ cwd?: string;
65
+ wasmPath?: string;
66
+ }
67
+
68
+ export interface PluginInvokeProcessClient {
69
+ launchPlan: PluginInvokeProcessLaunchPlan;
70
+ invokeRaw(requestBytes: Uint8Array | ArrayBuffer | ArrayBufferView): Promise<Uint8Array>;
71
+ invoke(request: {
72
+ methodId?: string | null;
73
+ inputs?: HarnessInputFrame[];
74
+ }): Promise<{
75
+ statusCode: number;
76
+ errorCode?: string | null;
77
+ errorMessage?: string | null;
78
+ outputs: HarnessInputFrame[];
79
+ }>;
80
+ destroy(): Promise<void>;
81
+ }
82
+
83
+ export interface ModuleHarnessRuntimeDescriptor {
84
+ kind?: "process" | "wasmedge";
85
+ launchPlan?: PluginInvokeProcessLaunchPlan;
86
+ command?: string;
87
+ args?: string[];
88
+ env?: Record<string, string | undefined>;
89
+ cwd?: string;
90
+ wasmPath?: string;
91
+ wasmEdgeBinary?: string;
92
+ wasmEdgeRunnerBinary?: string;
93
+ enableThreads?: boolean;
94
+ }
95
+
96
+ export interface ModuleHarness {
97
+ runtime: ModuleHarnessRuntimeDescriptor & { kind: "process" | "wasmedge" };
98
+ launchPlan: PluginInvokeProcessLaunchPlan;
99
+ invokeRaw(requestBytes: Uint8Array | ArrayBuffer | ArrayBufferView): Promise<Uint8Array>;
100
+ invoke(request: {
101
+ methodId?: string | null;
102
+ inputs?: HarnessInputFrame[];
103
+ }): Promise<{
104
+ statusCode: number;
105
+ errorCode?: string | null;
106
+ errorMessage?: string | null;
107
+ outputs: HarnessInputFrame[];
108
+ }>;
109
+ destroy(): Promise<void>;
110
+ }
111
+
112
+ export interface WasmEdgeRunnerBuildPlan {
113
+ runnerSourcePath: string;
114
+ requestedIncludeDir: string;
115
+ wasmedgeIncludeDir: string;
116
+ wasmedgeLibDir: string;
117
+ wasmedgeSharedLibraryPath: string;
118
+ outputPath: string;
119
+ compilerCommand: string;
120
+ compilerArgs: string[];
121
+ }
122
+
60
123
  export function describeCapabilityRuntimeSurface(
61
124
  capability: string,
62
125
  ): CapabilityRuntimeSurface;
@@ -84,3 +147,49 @@ export function materializeHarnessScenario(
84
147
  };
85
148
 
86
149
  export function serializeHarnessPlan(plan: ManifestHarnessPlan): unknown;
150
+
151
+ export function buildWasmEdgeSpawnEnv(
152
+ baseEnv?: Record<string, string | undefined>,
153
+ ): Record<string, string | undefined>;
154
+
155
+ export function resolveWasmEdgePluginLaunchPlan(options: {
156
+ wasmPath: string;
157
+ wasmEdgeBinary?: string;
158
+ wasmEdgeRunnerBinary?: string;
159
+ enableThreads?: boolean;
160
+ invokeArgs?: string[];
161
+ env?: Record<string, string | undefined>;
162
+ }): PluginInvokeProcessLaunchPlan;
163
+
164
+ export function createPluginInvokeProcessClient(options: {
165
+ launchPlan?: PluginInvokeProcessLaunchPlan;
166
+ command?: string;
167
+ args?: string[];
168
+ env?: Record<string, string | undefined>;
169
+ cwd?: string;
170
+ }): Promise<PluginInvokeProcessClient>;
171
+
172
+ export function resolveModuleHarnessLaunchPlan(options: {
173
+ runtime?: ModuleHarnessRuntimeDescriptor;
174
+ } | ModuleHarnessRuntimeDescriptor): PluginInvokeProcessLaunchPlan;
175
+
176
+ export function createModuleHarness(options: {
177
+ runtime?: ModuleHarnessRuntimeDescriptor;
178
+ } | ModuleHarnessRuntimeDescriptor): Promise<ModuleHarness>;
179
+
180
+ export function resolveWasmEdgeRunnerSourcePath(): string;
181
+
182
+ export function resolveWasmEdgeRunnerBuildPlan(options: {
183
+ outputPath: string;
184
+ wasmedgeIncludeDir?: string;
185
+ wasmedgeLibDir?: string;
186
+ output?: string;
187
+ }): WasmEdgeRunnerBuildPlan;
188
+
189
+ export function buildWasmEdgeEmscriptenPthreadRunner(options: {
190
+ outputPath: string;
191
+ wasmedgeIncludeDir?: string;
192
+ wasmedgeLibDir?: string;
193
+ output?: string;
194
+ cwd?: string;
195
+ }): Promise<string>;
@@ -1,6 +1,22 @@
1
+ import { Buffer } from "node:buffer";
2
+
1
3
  import { encodePluginInvokeRequest } from "../invoke/codec.js";
2
4
  import { normalizeInvokeSurfaces } from "../invoke/index.js";
3
5
  import { selectPreferredPayloadTypeRef } from "../manifest/typeRefs.js";
6
+ export {
7
+ buildWasmEdgeSpawnEnv,
8
+ createPluginInvokeProcessClient,
9
+ resolveWasmEdgePluginLaunchPlan,
10
+ } from "./processInvoke.js";
11
+ export {
12
+ buildWasmEdgeEmscriptenPthreadRunner,
13
+ resolveWasmEdgeRunnerBuildPlan,
14
+ resolveWasmEdgeRunnerSourcePath,
15
+ } from "./buildWasmEdgeRunner.js";
16
+ export {
17
+ createModuleHarness,
18
+ resolveModuleHarnessLaunchPlan,
19
+ } from "./moduleHarness.js";
4
20
 
5
21
  const CapabilitySurfaceMatrix = Object.freeze({
6
22
  logging: Object.freeze({