@plurnk/plurnk-execs-wasm 0.1.0
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/LICENSE +21 -0
- package/README.md +32 -0
- package/dist/Wasm.d.ts +9 -0
- package/dist/Wasm.d.ts.map +1 -0
- package/dist/Wasm.js +88 -0
- package/dist/Wasm.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PossumTech Laboratories
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @plurnk/plurnk-execs-wasm
|
|
2
|
+
|
|
3
|
+
WebAssembly runtime executor for [plurnk-service](https://github.com/plurnk/plurnk-service)'s `exec` scheme. Runs model-authored WebAssembly **in-process, sandboxed** — the safe arbitrary-execution tier that `node -e` can't be.
|
|
4
|
+
|
|
5
|
+
A `@plurnk/plurnk-execs-*` sibling built on the [plurnk-execs](https://github.com/plurnk/plurnk-execs) framework.
|
|
6
|
+
|
|
7
|
+
## Runtime tags
|
|
8
|
+
|
|
9
|
+
| Tag | Glyph | Input |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `wat` | 🧩 | WebAssembly **Text** (S-expression module) — the model-facing form |
|
|
12
|
+
| `wasm` | 🧩 | base64-encoded **binary** module (pre-compiled) |
|
|
13
|
+
|
|
14
|
+
`wat` is the primary: a model emits text, not bytes. WAT is assembled to wasm via [wabt](https://github.com/AssemblyScript/wabt.js); `wasm` decodes base64. (`.wast` — the spec test-suite superset with `assert_*` commands — is deliberately *not* supported; this executes a module, not a test script.)
|
|
15
|
+
|
|
16
|
+
## Execution model
|
|
17
|
+
|
|
18
|
+
Both forms instantiate in a sandbox whose only import is `env.log` (capture). The executor then calls the module's entry point — `main`, else `_start`, else the sole exported function — and writes:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{ "returned": <value|null>, "log": [ … ], "exports": [ "main", … ] }
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
to the `results` channel (`application/json`). A module that imports `(import "env" "log" (func $log (param i32)))` can emit intermediate values.
|
|
25
|
+
|
|
26
|
+
- **`effect: pure`** — a module can't touch the host (only the imports it's handed), so it **auto-runs inline**, never proposal-gated.
|
|
27
|
+
- **`probe`** — always available (`WebAssembly` builtin + bundled `wabt`).
|
|
28
|
+
- **Errors** emit a `TelemetryEvent` (`source: "exec:wat"`/`"exec:wasm"`): `wat_parse_error`, `wasm_invalid`, `wasm_trap`, `wabt_init_failed`.
|
|
29
|
+
|
|
30
|
+
## Tests
|
|
31
|
+
|
|
32
|
+
`test:lint`, `test:unit`.
|
package/dist/Wasm.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseExecutor } from "@plurnk/plurnk-execs";
|
|
2
|
+
import type { ChannelDecl, Effect, ExecArgs, ExecResult, RuntimeAvailability } from "@plurnk/plurnk-execs";
|
|
3
|
+
export default class Wasm extends BaseExecutor {
|
|
4
|
+
get channels(): Readonly<Record<string, ChannelDecl>>;
|
|
5
|
+
effect(_target: string | null): Effect;
|
|
6
|
+
probe(): Promise<RuntimeAvailability>;
|
|
7
|
+
run({ runtime, command, write, setState, emit }: ExecArgs): Promise<ExecResult>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=Wasm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Wasm.d.ts","sourceRoot":"","sources":["../src/Wasm.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AA+B3G,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC1C,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAEpD;IAEQ,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;IAIhC,KAAK,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAI9C,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;CAmDxF"}
|
package/dist/Wasm.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import wabtInit from "wabt";
|
|
2
|
+
import { BaseExecutor } from "@plurnk/plurnk-execs";
|
|
3
|
+
let wabtPromise;
|
|
4
|
+
const getWabt = () => (wabtPromise ??= wabtInit());
|
|
5
|
+
// WASM i64 results come back as bigint; stringify so the JSON serializes.
|
|
6
|
+
const jsonReplacer = (_key, value) => (typeof value === "bigint" ? value.toString() : value);
|
|
7
|
+
// Entry-point export names tried in order; falls back to the sole exported
|
|
8
|
+
// function if a module exports exactly one.
|
|
9
|
+
const ENTRY_POINTS = ["main", "_start"];
|
|
10
|
+
// In-process WebAssembly executor (a logical runtime). `wat` assembles the
|
|
11
|
+
// model's WebAssembly Text via wabt; `wasm` decodes a base64 binary module.
|
|
12
|
+
// Both instantiate in a sandbox — the only host interaction is an `env.log`
|
|
13
|
+
// import that captures values — call the entry point, and return its result as
|
|
14
|
+
// application/json. effect `pure`: a module cannot touch the host, only call
|
|
15
|
+
// the imports we hand it, so it auto-runs inline. The safe arbitrary-execution
|
|
16
|
+
// tier `node -e` can't be.
|
|
17
|
+
export default class Wasm extends BaseExecutor {
|
|
18
|
+
get channels() {
|
|
19
|
+
return { results: { mimetype: "application/json" } };
|
|
20
|
+
}
|
|
21
|
+
effect(_target) {
|
|
22
|
+
return "pure";
|
|
23
|
+
}
|
|
24
|
+
async probe() {
|
|
25
|
+
return { available: true, detail: "WebAssembly + wabt" };
|
|
26
|
+
}
|
|
27
|
+
async run({ runtime, command, write, setState, emit }) {
|
|
28
|
+
const fail = (kind, message) => {
|
|
29
|
+
emit({ source: `exec:${runtime}`, kind, message });
|
|
30
|
+
setState("results", "errored");
|
|
31
|
+
return { status: 500 };
|
|
32
|
+
};
|
|
33
|
+
// 1. Obtain the module bytes.
|
|
34
|
+
let bytes;
|
|
35
|
+
if (runtime === "wat") {
|
|
36
|
+
let wabt;
|
|
37
|
+
try {
|
|
38
|
+
wabt = await getWabt();
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return fail("wabt_init_failed", err.message);
|
|
42
|
+
}
|
|
43
|
+
let mod;
|
|
44
|
+
try {
|
|
45
|
+
mod = wabt.parseWat("module.wat", command);
|
|
46
|
+
bytes = mod.toBinary({}).buffer;
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return fail("wat_parse_error", err.message);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
mod?.destroy();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (runtime === "wasm") {
|
|
56
|
+
bytes = Uint8Array.from(Buffer.from(command.trim(), "base64"));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
throw new Error(`plurnk-execs-wasm received unclaimed runtime tag '${runtime}'`);
|
|
60
|
+
}
|
|
61
|
+
// 2. Instantiate in the sandbox (only the log-capture import).
|
|
62
|
+
const log = [];
|
|
63
|
+
let instance;
|
|
64
|
+
try {
|
|
65
|
+
({ instance } = await WebAssembly.instantiate(bytes, { env: { log: (v) => log.push(v) } }));
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
return fail("wasm_invalid", err.message);
|
|
69
|
+
}
|
|
70
|
+
// 3. Call the entry point if present; capture its return.
|
|
71
|
+
const exports = instance.exports;
|
|
72
|
+
const funcs = Object.keys(exports).filter((n) => typeof exports[n] === "function");
|
|
73
|
+
const entry = ENTRY_POINTS.find((n) => funcs.includes(n)) ?? (funcs.length === 1 ? funcs[0] : undefined);
|
|
74
|
+
let returned = null;
|
|
75
|
+
if (entry !== undefined) {
|
|
76
|
+
try {
|
|
77
|
+
returned = exports[entry]();
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
return fail("wasm_trap", `${entry}: ${err.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
write("results", JSON.stringify({ returned, log, exports: funcs }, jsonReplacer));
|
|
84
|
+
setState("results", "closed");
|
|
85
|
+
return { status: 200 };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=Wasm.js.map
|
package/dist/Wasm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Wasm.js","sourceRoot":"","sources":["../src/Wasm.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@plurnk/plurnk-execs-wasm",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "WebAssembly runtime executor for plurnk-service's exec scheme — in-process sandboxed execution of WAT (text) and wasm (binary) modules.",
|
|
5
|
+
"keywords": ["plurnk", "exec", "runtime", "executor", "webassembly", "wasm", "wat", "sandbox"],
|
|
6
|
+
"homepage": "https://github.com/plurnk/plurnk-execs-wasm#readme",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/plurnk/plurnk-execs-wasm/issues"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/plurnk/plurnk-execs-wasm.git"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=25"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "@wikitopian",
|
|
19
|
+
"type": "module",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"plurnk": {
|
|
24
|
+
"kind": "exec",
|
|
25
|
+
"runtimes": [
|
|
26
|
+
{ "name": "wat", "glyph": "🧩" },
|
|
27
|
+
{ "name": "wasm", "glyph": "🧩" }
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist/**/*",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test:lint": "tsc --noEmit",
|
|
43
|
+
"test:unit": "node --test \"src/**/*.test.ts\"",
|
|
44
|
+
"test": "npm run test:lint && npm run test:unit",
|
|
45
|
+
"build:dist": "tsc -p tsconfig.build.json",
|
|
46
|
+
"build": "npm run build:dist",
|
|
47
|
+
"prepare": "npm run build"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@plurnk/plurnk-execs": "0.4.1",
|
|
51
|
+
"wabt": "^1.0.39"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.8.0",
|
|
55
|
+
"typescript": "^6.0.3"
|
|
56
|
+
}
|
|
57
|
+
}
|