@cogitator-ai/wasm-tools 0.5.10 → 0.6.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/README.md +84 -25
- package/dist/index.d.ts +22 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +81 -14
- package/dist/index.js.map +1 -1
- package/dist/manager/file-watcher.d.ts.map +1 -1
- package/dist/manager/file-watcher.js +6 -0
- package/dist/manager/file-watcher.js.map +1 -1
- package/dist/manager/types.d.ts +11 -3
- package/dist/manager/types.d.ts.map +1 -1
- package/dist/manager/wasm-loader.d.ts +1 -0
- package/dist/manager/wasm-loader.d.ts.map +1 -1
- package/dist/manager/wasm-loader.js +26 -5
- package/dist/manager/wasm-loader.js.map +1 -1
- package/dist/manager/wasm-tool-manager.d.ts +6 -0
- package/dist/manager/wasm-tool-manager.d.ts.map +1 -1
- package/dist/manager/wasm-tool-manager.js +115 -30
- package/dist/manager/wasm-tool-manager.js.map +1 -1
- package/dist/runtime.d.ts +11 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +104 -0
- package/dist/runtime.js.map +1 -0
- package/dist/wasm/base64.wasm +0 -0
- package/dist/wasm/calc.wasm +0 -0
- package/dist/wasm/compression.wasm +0 -0
- package/dist/wasm/csv.wasm +0 -0
- package/dist/wasm/datetime.wasm +0 -0
- package/dist/wasm/diff.wasm +0 -0
- package/dist/wasm/hash.wasm +0 -0
- package/dist/wasm/json.wasm +0 -0
- package/dist/wasm/markdown.wasm +0 -0
- package/dist/wasm/regex.wasm +0 -0
- package/dist/wasm/signing.wasm +0 -0
- package/dist/wasm/slug.wasm +0 -0
- package/dist/wasm/validation.wasm +0 -0
- package/dist/wasm/xml.wasm +0 -0
- package/package.json +5 -6
- package/dist/__tests__/file-watcher.test.d.ts +0 -2
- package/dist/__tests__/file-watcher.test.d.ts.map +0 -1
- package/dist/__tests__/file-watcher.test.js +0 -99
- package/dist/__tests__/file-watcher.test.js.map +0 -1
- package/dist/__tests__/index.test.d.ts +0 -2
- package/dist/__tests__/index.test.d.ts.map +0 -1
- package/dist/__tests__/index.test.js +0 -226
- package/dist/__tests__/index.test.js.map +0 -1
- package/dist/__tests__/wasm-loader.test.d.ts +0 -2
- package/dist/__tests__/wasm-loader.test.d.ts.map +0 -1
- package/dist/__tests__/wasm-loader.test.js +0 -68
- package/dist/__tests__/wasm-loader.test.js.map +0 -1
- package/dist/__tests__/wasm-tool-manager.test.d.ts +0 -2
- package/dist/__tests__/wasm-tool-manager.test.d.ts.map +0 -1
- package/dist/__tests__/wasm-tool-manager.test.js +0 -166
- package/dist/__tests__/wasm-tool-manager.test.js.map +0 -1
- package/dist/plugins/base64.d.ts +0 -12
- package/dist/plugins/base64.d.ts.map +0 -1
- package/dist/plugins/base64.js +0 -95
- package/dist/plugins/base64.js.map +0 -1
- package/dist/plugins/calc.d.ts +0 -12
- package/dist/plugins/calc.d.ts.map +0 -1
- package/dist/plugins/calc.js +0 -95
- package/dist/plugins/calc.js.map +0 -1
- package/dist/plugins/compression.d.ts +0 -2
- package/dist/plugins/compression.d.ts.map +0 -1
- package/dist/plugins/compression.js +0 -545
- package/dist/plugins/compression.js.map +0 -1
- package/dist/plugins/csv.d.ts +0 -2
- package/dist/plugins/csv.d.ts.map +0 -1
- package/dist/plugins/csv.js +0 -136
- package/dist/plugins/csv.js.map +0 -1
- package/dist/plugins/datetime.d.ts +0 -2
- package/dist/plugins/datetime.d.ts.map +0 -1
- package/dist/plugins/datetime.js +0 -186
- package/dist/plugins/datetime.js.map +0 -1
- package/dist/plugins/diff.d.ts +0 -2
- package/dist/plugins/diff.d.ts.map +0 -1
- package/dist/plugins/diff.js +0 -187
- package/dist/plugins/diff.js.map +0 -1
- package/dist/plugins/hash.d.ts +0 -12
- package/dist/plugins/hash.d.ts.map +0 -1
- package/dist/plugins/hash.js +0 -309
- package/dist/plugins/hash.js.map +0 -1
- package/dist/plugins/json.d.ts +0 -12
- package/dist/plugins/json.d.ts.map +0 -1
- package/dist/plugins/json.js +0 -70
- package/dist/plugins/json.js.map +0 -1
- package/dist/plugins/markdown.d.ts +0 -2
- package/dist/plugins/markdown.d.ts.map +0 -1
- package/dist/plugins/markdown.js +0 -213
- package/dist/plugins/markdown.js.map +0 -1
- package/dist/plugins/regex.d.ts +0 -2
- package/dist/plugins/regex.d.ts.map +0 -1
- package/dist/plugins/regex.js +0 -120
- package/dist/plugins/regex.js.map +0 -1
- package/dist/plugins/signing.d.ts +0 -2
- package/dist/plugins/signing.d.ts.map +0 -1
- package/dist/plugins/signing.js +0 -576
- package/dist/plugins/signing.js.map +0 -1
- package/dist/plugins/slug.d.ts +0 -2
- package/dist/plugins/slug.d.ts.map +0 -1
- package/dist/plugins/slug.js +0 -180
- package/dist/plugins/slug.js.map +0 -1
- package/dist/plugins/validation.d.ts +0 -2
- package/dist/plugins/validation.d.ts.map +0 -1
- package/dist/plugins/validation.js +0 -105
- package/dist/plugins/validation.js.map +0 -1
- package/dist/plugins/xml.d.ts +0 -2
- package/dist/plugins/xml.d.ts.map +0 -1
- package/dist/plugins/xml.js +0 -297
- package/dist/plugins/xml.js.map +0 -1
- package/dist/temp/base64.js +0 -102
- package/dist/temp/calc.js +0 -102
- package/dist/temp/compression.js +0 -738
- package/dist/temp/csv.js +0 -155
- package/dist/temp/datetime.js +0 -201
- package/dist/temp/diff.js +0 -198
- package/dist/temp/hash.js +0 -423
- package/dist/temp/json.js +0 -80
- package/dist/temp/markdown.js +0 -224
- package/dist/temp/regex.js +0 -141
- package/dist/temp/signing.js +0 -584
- package/dist/temp/slug.js +0 -198
- package/dist/temp/validation.js +0 -125
- package/dist/temp/xml.js +0 -295
package/README.md
CHANGED
|
@@ -16,6 +16,23 @@ WASM-based tools for Cogitator agents. Secure, sandboxed tool execution using We
|
|
|
16
16
|
pnpm add @cogitator-ai/wasm-tools
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
`@extism/extism` (>= 2.0.0-rc13, the current `latest` on npm) is installed as a dependency; the pre-built plugins are compiled with `extism-js` and need its host functions and WASI.
|
|
20
|
+
|
|
21
|
+
## How Tools Execute
|
|
22
|
+
|
|
23
|
+
Every tool created here carries a `sandbox: { type: 'wasm', ... }` config and a real `execute()`:
|
|
24
|
+
|
|
25
|
+
- **Inside Cogitator**: when `@cogitator-ai/sandbox` is available, Cogitator runs the module through its WASM executor (plugin pooling, worker-thread timeouts). Otherwise it falls back to the tool's own `execute()`.
|
|
26
|
+
- **Directly**: `await tool.execute(params, context)` validates `params` with the tool's Zod schema, runs the module in an Extism worker thread, enforces `timeout` (the worker is terminated) and honours `context.signal`. Compiled modules are cached per file and recompiled when the file changes.
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
const calc = createCalcTool();
|
|
30
|
+
await calc.execute({ expression: '(2 + 3) * 4' }, { agentId: 'a', runId: 'r', signal });
|
|
31
|
+
// { result: 20, expression: '(2 + 3) * 4' }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Plugin-level errors are returned as data (`{ ..., error: '...' }`) so the agent can react; timeouts, aborts and invalid parameters reject the promise.
|
|
35
|
+
|
|
19
36
|
## Quick Start
|
|
20
37
|
|
|
21
38
|
### Pre-built Tools
|
|
@@ -146,11 +163,13 @@ interface WasmToolConfig<TParams> {
|
|
|
146
163
|
parameters: ZodType<TParams>;
|
|
147
164
|
category?: ToolCategory;
|
|
148
165
|
tags?: string[];
|
|
149
|
-
timeout?: number; // Execution timeout in ms
|
|
150
|
-
wasi?: boolean; // Enable WASI
|
|
166
|
+
timeout?: number; // Execution timeout in ms (default 5000), also set as tool.timeout
|
|
167
|
+
wasi?: boolean; // Enable WASI (required for modules compiled with extism-js)
|
|
151
168
|
}
|
|
152
169
|
```
|
|
153
170
|
|
|
171
|
+
`parameters` may use Zod transforms: the parsed (output) value is what the module receives, while `toJSON()` exposes the input schema to the LLM.
|
|
172
|
+
|
|
154
173
|
### createCalcTool(options?)
|
|
155
174
|
|
|
156
175
|
Create a calculator tool for mathematical expressions.
|
|
@@ -158,8 +177,9 @@ Create a calculator tool for mathematical expressions.
|
|
|
158
177
|
```typescript
|
|
159
178
|
const calc = createCalcTool({ timeout: 10000 });
|
|
160
179
|
|
|
161
|
-
// Supports: +, -, *, /, %, parentheses
|
|
162
|
-
// Example: "2 + 2 * 3" → 8
|
|
180
|
+
// Supports: +, -, *, /, %, unary +/-, parentheses, decimals (".5", "2.")
|
|
181
|
+
// Example: "2 + 2 * 3" → { result: 8, expression: "2 + 2 * 3" }
|
|
182
|
+
// Errors (division by zero, malformed numbers, non-finite results) → { result: null, error }
|
|
163
183
|
```
|
|
164
184
|
|
|
165
185
|
### createJsonTool(options?)
|
|
@@ -169,9 +189,12 @@ Create a JSON processor tool with JSONPath query support.
|
|
|
169
189
|
```typescript
|
|
170
190
|
const json = createJsonTool({ timeout: 10000 });
|
|
171
191
|
|
|
172
|
-
//
|
|
192
|
+
// { json: '{"a": {"b": 1}}', query: '$.a.b' } → { result: 1, type: 'number', found: true }
|
|
193
|
+
// { json, query: '$.items[*].id' } → { result: [1, 2], type: 'array', found: true }
|
|
173
194
|
```
|
|
174
195
|
|
|
196
|
+
Supported JSONPath subset: `$`, `.key`, `['key']`, `[n]` (negative indexes allowed), `[start:end:step]`, `*` / `[*]`, and recursive descent `..key` / `..*`. Wildcards, slices and recursive descent always return an array. Missing paths return `{ result: null, type: 'undefined', found: false }`; filters (`[?()]`) and unions are rejected with an error.
|
|
197
|
+
|
|
175
198
|
### createHashTool(options?)
|
|
176
199
|
|
|
177
200
|
Create a cryptographic hash tool supporting multiple algorithms.
|
|
@@ -192,9 +215,11 @@ const base64 = createBase64Tool({ timeout: 10000 });
|
|
|
192
215
|
|
|
193
216
|
// Example: { text: "hello", operation: "encode" } → "aGVsbG8="
|
|
194
217
|
// Example: { text: "aGVsbG8=", operation: "decode" } → "hello"
|
|
195
|
-
// URL-safe: { text: "hello", operation: "encode", urlSafe: true }
|
|
218
|
+
// URL-safe: { text: "hello", operation: "encode", urlSafe: true } → "aGVsbG8" (no padding)
|
|
196
219
|
```
|
|
197
220
|
|
|
221
|
+
Decoding accepts both alphabets, optional padding and whitespace, rejects invalid characters/lengths with an error, and replaces invalid UTF-8 sequences with U+FFFD.
|
|
222
|
+
|
|
198
223
|
### createSlugTool(options?)
|
|
199
224
|
|
|
200
225
|
Generate URL-safe slugs from text with Unicode transliteration.
|
|
@@ -204,8 +229,11 @@ const slug = createSlugTool({ timeout: 10000 });
|
|
|
204
229
|
|
|
205
230
|
// Example: { text: "Hello World!" } → "hello-world"
|
|
206
231
|
// Example: { text: "Привет мир", separator: "_" } → "privet_mir"
|
|
232
|
+
// Example: { text: "Crème brûlée, a/b" } → "creme-brulee-a-b"
|
|
207
233
|
```
|
|
208
234
|
|
|
235
|
+
Any run of non-alphanumeric characters becomes one separator; apostrophes are dropped; accents are stripped after transliteration. `maxLength` must be a positive integer and cuts at a separator when possible.
|
|
236
|
+
|
|
209
237
|
### createValidationTool(options?)
|
|
210
238
|
|
|
211
239
|
Validate common formats: email, URL, UUID, IPv4, IPv6.
|
|
@@ -213,10 +241,15 @@ Validate common formats: email, URL, UUID, IPv4, IPv6.
|
|
|
213
241
|
```typescript
|
|
214
242
|
const validation = createValidationTool({ timeout: 10000 });
|
|
215
243
|
|
|
216
|
-
// Example: { value: "test@example.com", type: "email" } → { valid: true }
|
|
217
|
-
// Example: { value: "
|
|
244
|
+
// Example: { value: "test@example.com", type: "email" } → { valid: true, normalized: "test@example.com" }
|
|
245
|
+
// Example: { value: "2001:DB8:0:0:0:0:0:1", type: "ipv6" } → { valid: true, normalized: "2001:db8::1" }
|
|
218
246
|
```
|
|
219
247
|
|
|
248
|
+
- **email**: dot-atom local part (no leading/trailing/consecutive dots, ≤ 64 chars), valid hostname labels; only the domain is lower-cased.
|
|
249
|
+
- **url**: `http`, `https`, `ftp`, `ftps`; userinfo, ports ≤ 65535 and bracketed IPv6 hosts are supported; whitespace and control characters are rejected. Missing schemes default to `https://`.
|
|
250
|
+
- **ipv4**: dotted quad without leading zeros (`01.2.3.4` is rejected, matching Node's `net.isIPv4`).
|
|
251
|
+
- **ipv6**: full RFC 4291 syntax including `::` and embedded IPv4; normalized to the RFC 5952 canonical form. Zone IDs are rejected.
|
|
252
|
+
|
|
220
253
|
### createDiffTool(options?)
|
|
221
254
|
|
|
222
255
|
Compare texts using Myers diff algorithm.
|
|
@@ -224,10 +257,12 @@ Compare texts using Myers diff algorithm.
|
|
|
224
257
|
```typescript
|
|
225
258
|
const diff = createDiffTool({ timeout: 10000 });
|
|
226
259
|
|
|
227
|
-
//
|
|
228
|
-
//
|
|
260
|
+
// { original: "a\nb\n", modified: "a\nc\n" } →
|
|
261
|
+
// { diff: "--- original\n+++ modified\n@@ -1,2 +1,2 @@\n a\n-b\n+c", additions: 1, deletions: 1, changes: [...] }
|
|
229
262
|
```
|
|
230
263
|
|
|
264
|
+
`format` is `unified` (default, standard hunks with `context` lines, default 3), `inline` or `json`. A trailing newline is not treated as an extra line.
|
|
265
|
+
|
|
231
266
|
### createRegexTool(options?)
|
|
232
267
|
|
|
233
268
|
Safe regex operations with ReDoS protection.
|
|
@@ -239,6 +274,8 @@ const regex = createRegexTool({ timeout: 10000 });
|
|
|
239
274
|
// Supports: match, matchAll, test, replace, split
|
|
240
275
|
```
|
|
241
276
|
|
|
277
|
+
Patterns with nested unbounded quantifiers (e.g. `(a+)+`, `(\w+\s?)+`) are rejected up front. Other catastrophic patterns (e.g. overlapping alternations like `(a|aa)+$`) are stopped by the execution timeout, which terminates the worker.
|
|
278
|
+
|
|
242
279
|
### createCsvTool(options?)
|
|
243
280
|
|
|
244
281
|
RFC 4180 compliant CSV parsing and generation.
|
|
@@ -246,10 +283,12 @@ RFC 4180 compliant CSV parsing and generation.
|
|
|
246
283
|
```typescript
|
|
247
284
|
const csv = createCsvTool({ timeout: 10000 });
|
|
248
285
|
|
|
249
|
-
// Parse: { data: "a,b\n1,2", operation: "parse" }
|
|
250
|
-
// Stringify: { data: [["a","b"],["1","2"]], operation: "stringify" }
|
|
286
|
+
// Parse: { data: "a,b\n1,2", operation: "parse", headers: true } → headers ["a","b"], result [["1","2"]]
|
|
287
|
+
// Stringify: { data: [["a","b"],["1","2"]], operation: "stringify", headers: ["x","y"] }
|
|
251
288
|
```
|
|
252
289
|
|
|
290
|
+
Quotes only open a quoted field at the start of a field; unterminated quotes and characters after a closing quote are errors. A UTF-8 BOM is ignored. For `parse`, `headers` may also be an array of column names. Objects are JSON-encoded when stringifying.
|
|
291
|
+
|
|
253
292
|
### createMarkdownTool(options?)
|
|
254
293
|
|
|
255
294
|
Convert Markdown to HTML (GFM subset).
|
|
@@ -259,9 +298,12 @@ const markdown = createMarkdownTool({ timeout: 10000 });
|
|
|
259
298
|
|
|
260
299
|
// Example: { markdown: "# Hello\n**bold**" }
|
|
261
300
|
// Returns: { html: "<h1>Hello</h1>\n<p><strong>bold</strong></p>" }
|
|
262
|
-
// Supports:
|
|
301
|
+
// Supports: headings, emphasis, strikethrough, links, images, autolinks, code spans/blocks,
|
|
302
|
+
// lists (ordered with start number), blockquotes, rules, GFM tables with alignment, backslash escapes
|
|
263
303
|
```
|
|
264
304
|
|
|
305
|
+
`options.sanitize` defaults to `true`: raw HTML is escaped and link/image URLs with schemes other than `http`, `https`, `mailto`, `tel` and `ftp` (e.g. `javascript:`, `data:`) are replaced with `#`. Code content and generated attribute values are always escaped. Intraword underscores (`snake_case`) are not treated as emphasis.
|
|
306
|
+
|
|
265
307
|
### createXmlTool(options?)
|
|
266
308
|
|
|
267
309
|
Parse XML to JSON with XPath-like queries.
|
|
@@ -273,6 +315,8 @@ const xml = createXmlTool({ timeout: 10000 });
|
|
|
273
315
|
// Supports: elements, attributes, CDATA, comments
|
|
274
316
|
```
|
|
275
317
|
|
|
318
|
+
Query syntax: absolute paths start at the root element (`/root/item`), relative paths start below it (`item`), `//name` searches descendants, `*` matches any element, `name[2]` selects the 2nd match (1-based), `/@attr` (or `@*`) returns attribute values and `/text()` returns text content. One match returns a value, several return an array, none returns `{ result: null, type: 'empty' }`. Malformed documents (unclosed or mismatched tags, multiple roots, unterminated attributes) are errors; DTD entities are never expanded.
|
|
319
|
+
|
|
276
320
|
### createDatetimeTool(options?)
|
|
277
321
|
|
|
278
322
|
Date/time operations with UTC and offset timezone support.
|
|
@@ -286,18 +330,24 @@ const datetime = createDatetimeTool({ timeout: 10000 });
|
|
|
286
330
|
// Diff: { date: "2024-01-01", operation: "diff", endDate: "2024-01-15", unit: "days" }
|
|
287
331
|
```
|
|
288
332
|
|
|
333
|
+
- Accepts ISO dates (`2024-01-15`, `2024-01-15 10:30`, fractional seconds, `Z`/`+04:00`/`+0400`/`+04`), Unix timestamps (10 digits = seconds, 11-13 = ms) and anything `Date.parse` understands. Impossible dates such as `2023-02-29` are rejected.
|
|
334
|
+
- Month/year arithmetic clamps to the end of the month (`2024-01-31` + 1 month = `2024-02-29`).
|
|
335
|
+
- Format tokens: `YYYY MM DD HH mm ss SSS Z`, every occurrence is replaced; wrap literal text in brackets (`[at]`).
|
|
336
|
+
- `diff` returns whole units, truncated toward zero, negative when `endDate` is earlier.
|
|
337
|
+
|
|
289
338
|
### createCompressionTool(options?)
|
|
290
339
|
|
|
291
|
-
Gzip
|
|
340
|
+
Gzip compression and decompression (RFC 1952), interoperable with zlib.
|
|
292
341
|
|
|
293
342
|
```typescript
|
|
294
343
|
const compression = createCompressionTool({ timeout: 30000 });
|
|
295
344
|
|
|
296
|
-
// Compress: { data: "hello",
|
|
297
|
-
// Decompress: { data: "H4sIAAAA...",
|
|
298
|
-
// Returns base64-encoded compressed data with size info
|
|
345
|
+
// Compress: { data: "hello", operation: "compress", level: 6 } → { result: "H4sI...", originalSize, resultSize, ratio }
|
|
346
|
+
// Decompress: { data: "H4sIAAAA...", operation: "decompress" } → { result: "hello", ... }
|
|
299
347
|
```
|
|
300
348
|
|
|
349
|
+
Defaults: `compress` reads UTF-8 and returns base64; `decompress` reads base64 and returns UTF-8. Use `inputEncoding`/`outputEncoding: 'base64'` for binary data. `level` is an integer 0-9. Decompression verifies the gzip CRC32 and size and is capped at 64 MB of output.
|
|
350
|
+
|
|
301
351
|
### createSigningTool(options?)
|
|
302
352
|
|
|
303
353
|
Ed25519 digital signatures for message authentication.
|
|
@@ -310,6 +360,8 @@ const signing = createSigningTool({ timeout: 10000 });
|
|
|
310
360
|
// Verify: { operation: "verify", algorithm: "ed25519", message: "hello", publicKey: "...", signature: "..." }
|
|
311
361
|
```
|
|
312
362
|
|
|
363
|
+
WASM has no secure random source, so `signingToolSchema` generates a 32-byte seed on the host with `node:crypto` when `generateKeypair` is called without `seed`; the seed is the private key. Keys and signatures use `encoding: 'hex'` (default) or `'base64'`. Signatures are RFC 8032 Ed25519 and interoperate with `node:crypto`; non-canonical or off-curve public keys fail verification. Empty messages are allowed.
|
|
364
|
+
|
|
313
365
|
### getWasmPath(name)
|
|
314
366
|
|
|
315
367
|
Get the path to a pre-built WASM module.
|
|
@@ -329,6 +381,7 @@ Manage WASM tools with hot-reload support.
|
|
|
329
381
|
interface WasmToolManagerOptions {
|
|
330
382
|
debounceMs?: number; // File change debounce delay (default: 100ms)
|
|
331
383
|
useWasi?: boolean; // Enable WASI for all modules
|
|
384
|
+
timeout?: number; // Per-call timeout in ms (default: 30000)
|
|
332
385
|
}
|
|
333
386
|
|
|
334
387
|
interface WasmToolCallbacks {
|
|
@@ -362,6 +415,8 @@ class WasmToolManager {
|
|
|
362
415
|
}
|
|
363
416
|
```
|
|
364
417
|
|
|
418
|
+
Manager tools call the module's exported `run` function with the JSON-encoded parameters. Plugins run in Extism worker threads: when a call times out or its `context.signal` aborts, the call rejects and the plugin is replaced with a fresh instance so the tool keeps working.
|
|
419
|
+
|
|
365
420
|
### Legacy Exports
|
|
366
421
|
|
|
367
422
|
For direct sandbox usage:
|
|
@@ -399,22 +454,26 @@ declare const Host: {
|
|
|
399
454
|
};
|
|
400
455
|
```
|
|
401
456
|
|
|
402
|
-
Build with:
|
|
457
|
+
Build with (an interface file `my-tool.d.ts` declaring `declare module 'main' { export function run(): I32; }` lists the exports):
|
|
403
458
|
|
|
404
459
|
```bash
|
|
405
|
-
esbuild my-tool.ts
|
|
406
|
-
extism-js temp/my-tool.js -o dist/my-tool.wasm
|
|
460
|
+
esbuild my-tool.ts --outfile=temp/my-tool.js --bundle --format=cjs --target=es2020
|
|
461
|
+
extism-js temp/my-tool.js -i my-tool.d.ts -o dist/my-tool.wasm
|
|
407
462
|
```
|
|
408
463
|
|
|
464
|
+
Modules compiled with `extism-js` embed QuickJS and require WASI: pass `wasi: true` to `defineWasmTool` (or `useWasi: true` to `WasmToolManager`).
|
|
465
|
+
|
|
466
|
+
The package build (`pnpm build`) compiles `src/plugins/*.ts` with `extism-js` when it is installed and fails if any plugin fails to compile. Without `extism-js` it writes empty placeholder `.wasm` files; executing a tool then fails with a clear "placeholder build" error.
|
|
467
|
+
|
|
409
468
|
## Security
|
|
410
469
|
|
|
411
470
|
WASM tools run in a secure Extism sandbox:
|
|
412
471
|
|
|
413
|
-
- ❌ No filesystem access (
|
|
414
|
-
- ❌ No network access
|
|
415
|
-
- ✅
|
|
416
|
-
- ✅
|
|
417
|
-
- ✅ Isolated
|
|
472
|
+
- ❌ No filesystem access (no directories are pre-opened, even with WASI)
|
|
473
|
+
- ❌ No network access (no allowed hosts)
|
|
474
|
+
- ✅ Timeout enforcement (the worker thread is terminated)
|
|
475
|
+
- ✅ Abort support via `ToolContext.signal`
|
|
476
|
+
- ✅ Isolated linear memory per plugin instance
|
|
418
477
|
|
|
419
478
|
## License
|
|
420
479
|
|
package/dist/index.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export interface WasmToolConfig<TParams = unknown> {
|
|
|
39
39
|
description: string;
|
|
40
40
|
wasmModule: string;
|
|
41
41
|
wasmFunction?: string;
|
|
42
|
-
parameters: ZodType<TParams>;
|
|
42
|
+
parameters: ZodType<TParams, unknown>;
|
|
43
43
|
category?: ToolCategory;
|
|
44
44
|
tags?: string[];
|
|
45
45
|
timeout?: number;
|
|
@@ -292,7 +292,7 @@ export declare const compressionToolSchema: z.ZodObject<{
|
|
|
292
292
|
}>>;
|
|
293
293
|
level: z.ZodOptional<z.ZodNumber>;
|
|
294
294
|
}, z.core.$strip>;
|
|
295
|
-
export declare const signingToolSchema: z.ZodObject<{
|
|
295
|
+
export declare const signingToolSchema: z.ZodPipe<z.ZodObject<{
|
|
296
296
|
operation: z.ZodEnum<{
|
|
297
297
|
generateKeypair: "generateKeypair";
|
|
298
298
|
sign: "sign";
|
|
@@ -309,7 +309,26 @@ export declare const signingToolSchema: z.ZodObject<{
|
|
|
309
309
|
base64: "base64";
|
|
310
310
|
hex: "hex";
|
|
311
311
|
}>>;
|
|
312
|
-
|
|
312
|
+
seed: z.ZodOptional<z.ZodString>;
|
|
313
|
+
}, z.core.$strip>, z.ZodTransform<{
|
|
314
|
+
operation: "generateKeypair" | "sign" | "verify";
|
|
315
|
+
algorithm: "ed25519";
|
|
316
|
+
message?: string | undefined;
|
|
317
|
+
privateKey?: string | undefined;
|
|
318
|
+
publicKey?: string | undefined;
|
|
319
|
+
signature?: string | undefined;
|
|
320
|
+
encoding?: "base64" | "hex" | undefined;
|
|
321
|
+
seed?: string | undefined;
|
|
322
|
+
}, {
|
|
323
|
+
operation: "generateKeypair" | "sign" | "verify";
|
|
324
|
+
algorithm: "ed25519";
|
|
325
|
+
message?: string | undefined;
|
|
326
|
+
privateKey?: string | undefined;
|
|
327
|
+
publicKey?: string | undefined;
|
|
328
|
+
signature?: string | undefined;
|
|
329
|
+
encoding?: "base64" | "hex" | undefined;
|
|
330
|
+
seed?: string | undefined;
|
|
331
|
+
}>>;
|
|
313
332
|
export declare function createSlugTool(options?: {
|
|
314
333
|
timeout?: number;
|
|
315
334
|
}): Tool<SlugToolInput, unknown>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,CAAC,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAe,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -30,8 +30,10 @@
|
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
32
|
import { z } from 'zod';
|
|
33
|
+
import { randomBytes } from 'node:crypto';
|
|
33
34
|
import { fileURLToPath } from 'node:url';
|
|
34
35
|
import { dirname, join } from 'node:path';
|
|
36
|
+
import { invokeWasm } from './runtime.js';
|
|
35
37
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
36
38
|
/**
|
|
37
39
|
* Create a custom WASM tool for agent use.
|
|
@@ -64,11 +66,13 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
64
66
|
* ```
|
|
65
67
|
*/
|
|
66
68
|
export function defineWasmTool(config) {
|
|
69
|
+
const wasmFunction = config.wasmFunction ?? 'run';
|
|
70
|
+
const timeout = config.timeout ?? 5000;
|
|
67
71
|
const sandboxConfig = {
|
|
68
72
|
type: 'wasm',
|
|
69
73
|
wasmModule: config.wasmModule,
|
|
70
|
-
wasmFunction
|
|
71
|
-
timeout
|
|
74
|
+
wasmFunction,
|
|
75
|
+
timeout,
|
|
72
76
|
wasi: config.wasi,
|
|
73
77
|
};
|
|
74
78
|
const tool = {
|
|
@@ -77,9 +81,19 @@ export function defineWasmTool(config) {
|
|
|
77
81
|
category: config.category,
|
|
78
82
|
tags: config.tags,
|
|
79
83
|
parameters: config.parameters,
|
|
84
|
+
timeout,
|
|
80
85
|
sandbox: sandboxConfig,
|
|
81
|
-
execute: async (params,
|
|
82
|
-
|
|
86
|
+
execute: async (params, context) => {
|
|
87
|
+
const validated = config.parameters.parse(params);
|
|
88
|
+
return invokeWasm({
|
|
89
|
+
toolName: config.name,
|
|
90
|
+
wasmModule: config.wasmModule,
|
|
91
|
+
wasmFunction,
|
|
92
|
+
wasi: config.wasi ?? false,
|
|
93
|
+
timeout,
|
|
94
|
+
input: JSON.stringify(validated),
|
|
95
|
+
signal: context?.signal,
|
|
96
|
+
});
|
|
83
97
|
},
|
|
84
98
|
toJSON: () => wasmToolToSchema(tool),
|
|
85
99
|
};
|
|
@@ -89,6 +103,7 @@ function wasmToolToSchema(t) {
|
|
|
89
103
|
const jsonSchema = z.toJSONSchema(t.parameters, {
|
|
90
104
|
target: 'openapi-3.0',
|
|
91
105
|
unrepresentable: 'any',
|
|
106
|
+
io: 'input',
|
|
92
107
|
});
|
|
93
108
|
const schema = jsonSchema;
|
|
94
109
|
const properties = (schema.properties ?? {});
|
|
@@ -114,7 +129,10 @@ export const calcToolSchema = z.object({
|
|
|
114
129
|
});
|
|
115
130
|
export const jsonToolSchema = z.object({
|
|
116
131
|
json: z.string().describe('JSON string to parse and process'),
|
|
117
|
-
query: z
|
|
132
|
+
query: z
|
|
133
|
+
.string()
|
|
134
|
+
.optional()
|
|
135
|
+
.describe('Optional JSONPath query, e.g. "$.items[*].id", "$..price", "$.a[0:2]"'),
|
|
118
136
|
});
|
|
119
137
|
export const hashToolSchema = z.object({
|
|
120
138
|
text: z.string().describe('Text to hash'),
|
|
@@ -147,6 +165,7 @@ export function createCalcTool(options) {
|
|
|
147
165
|
name: 'calculate',
|
|
148
166
|
description: 'Evaluate a mathematical expression safely. Supports +, -, *, /, %, and parentheses.',
|
|
149
167
|
wasmModule: getWasmPath('calc'),
|
|
168
|
+
wasi: true,
|
|
150
169
|
wasmFunction: 'calculate',
|
|
151
170
|
parameters: calcToolSchema,
|
|
152
171
|
category: 'math',
|
|
@@ -176,6 +195,7 @@ export function createJsonTool(options) {
|
|
|
176
195
|
name: 'process_json',
|
|
177
196
|
description: 'Parse and query JSON data. Supports JSONPath queries for extracting nested values.',
|
|
178
197
|
wasmModule: getWasmPath('json'),
|
|
198
|
+
wasi: true,
|
|
179
199
|
wasmFunction: 'process',
|
|
180
200
|
parameters: jsonToolSchema,
|
|
181
201
|
category: 'utility',
|
|
@@ -205,6 +225,7 @@ export function createHashTool(options) {
|
|
|
205
225
|
name: 'hash_text',
|
|
206
226
|
description: 'Compute cryptographic hash of text. Supports SHA-256, SHA-1, and MD5 algorithms.',
|
|
207
227
|
wasmModule: getWasmPath('hash'),
|
|
228
|
+
wasi: true,
|
|
208
229
|
wasmFunction: 'hash',
|
|
209
230
|
parameters: hashToolSchema,
|
|
210
231
|
category: 'utility',
|
|
@@ -234,6 +255,7 @@ export function createBase64Tool(options) {
|
|
|
234
255
|
name: 'base64',
|
|
235
256
|
description: 'Encode or decode Base64 text. Supports standard and URL-safe variants.',
|
|
236
257
|
wasmModule: getWasmPath('base64'),
|
|
258
|
+
wasi: true,
|
|
237
259
|
wasmFunction: 'base64',
|
|
238
260
|
parameters: base64ToolSchema,
|
|
239
261
|
category: 'utility',
|
|
@@ -244,24 +266,28 @@ export function createBase64Tool(options) {
|
|
|
244
266
|
export const calcToolConfig = {
|
|
245
267
|
type: 'wasm',
|
|
246
268
|
wasmModule: getWasmPath('calc'),
|
|
269
|
+
wasi: true,
|
|
247
270
|
wasmFunction: 'calculate',
|
|
248
271
|
timeout: 5000,
|
|
249
272
|
};
|
|
250
273
|
export const jsonToolConfig = {
|
|
251
274
|
type: 'wasm',
|
|
252
275
|
wasmModule: getWasmPath('json'),
|
|
276
|
+
wasi: true,
|
|
253
277
|
wasmFunction: 'process',
|
|
254
278
|
timeout: 5000,
|
|
255
279
|
};
|
|
256
280
|
export const hashToolConfig = {
|
|
257
281
|
type: 'wasm',
|
|
258
282
|
wasmModule: getWasmPath('hash'),
|
|
283
|
+
wasi: true,
|
|
259
284
|
wasmFunction: 'hash',
|
|
260
285
|
timeout: 5000,
|
|
261
286
|
};
|
|
262
287
|
export const base64ToolConfig = {
|
|
263
288
|
type: 'wasm',
|
|
264
289
|
wasmModule: getWasmPath('base64'),
|
|
290
|
+
wasi: true,
|
|
265
291
|
wasmFunction: 'base64',
|
|
266
292
|
timeout: 5000,
|
|
267
293
|
};
|
|
@@ -269,7 +295,7 @@ export const slugToolSchema = z.object({
|
|
|
269
295
|
text: z.string().describe('Text to convert to URL-safe slug'),
|
|
270
296
|
separator: z.string().optional().describe('Separator character (default: "-")'),
|
|
271
297
|
lowercase: z.boolean().optional().describe('Convert to lowercase (default: true)'),
|
|
272
|
-
maxLength: z.number().optional().describe('Maximum length of the slug'),
|
|
298
|
+
maxLength: z.number().int().min(1).optional().describe('Maximum length of the slug'),
|
|
273
299
|
});
|
|
274
300
|
export const validationToolSchema = z.object({
|
|
275
301
|
value: z.string().describe('Value to validate'),
|
|
@@ -279,7 +305,12 @@ export const diffToolSchema = z.object({
|
|
|
279
305
|
original: z.string().describe('Original text'),
|
|
280
306
|
modified: z.string().describe('Modified text'),
|
|
281
307
|
format: z.enum(['unified', 'inline', 'json']).optional().describe('Output format'),
|
|
282
|
-
context: z
|
|
308
|
+
context: z
|
|
309
|
+
.number()
|
|
310
|
+
.int()
|
|
311
|
+
.min(0)
|
|
312
|
+
.optional()
|
|
313
|
+
.describe('Context lines for unified diff (default 3)'),
|
|
283
314
|
});
|
|
284
315
|
export const regexToolSchema = z.object({
|
|
285
316
|
text: z.string().describe('Text to search/replace'),
|
|
@@ -287,7 +318,7 @@ export const regexToolSchema = z.object({
|
|
|
287
318
|
flags: z.string().optional().describe('Regex flags (g, i, m, etc.)'),
|
|
288
319
|
operation: z.enum(['match', 'matchAll', 'test', 'replace', 'split']).describe('Operation'),
|
|
289
320
|
replacement: z.string().optional().describe('Replacement text for replace operation'),
|
|
290
|
-
limit: z.number().optional().describe('Limit number of matches/splits'),
|
|
321
|
+
limit: z.number().int().min(0).optional().describe('Limit number of matches/splits'),
|
|
291
322
|
});
|
|
292
323
|
export const csvToolSchema = z.object({
|
|
293
324
|
data: z.union([z.string(), z.array(z.array(z.unknown()))]).describe('CSV string or array data'),
|
|
@@ -310,12 +341,18 @@ export const markdownToolSchema = z.object({
|
|
|
310
341
|
});
|
|
311
342
|
export const xmlToolSchema = z.object({
|
|
312
343
|
xml: z.string().describe('XML string to parse'),
|
|
313
|
-
query: z
|
|
344
|
+
query: z
|
|
345
|
+
.string()
|
|
346
|
+
.optional()
|
|
347
|
+
.describe('XPath-like query, e.g. "/root/child", "//item[2]", "//item/@id", "//item/text()"'),
|
|
314
348
|
});
|
|
315
349
|
export const datetimeToolSchema = z.object({
|
|
316
350
|
date: z.string().optional().describe('Date string to process'),
|
|
317
351
|
operation: z.enum(['parse', 'format', 'add', 'subtract', 'diff', 'now']).describe('Operation'),
|
|
318
|
-
format: z
|
|
352
|
+
format: z
|
|
353
|
+
.string()
|
|
354
|
+
.optional()
|
|
355
|
+
.describe('Date format tokens: YYYY MM DD HH mm ss SSS Z; wrap literal text in [brackets]'),
|
|
319
356
|
timezone: z.string().optional().describe('Timezone offset (e.g., "+04:00", "UTC")'),
|
|
320
357
|
amount: z.number().optional().describe('Amount for add/subtract'),
|
|
321
358
|
unit: z
|
|
@@ -326,11 +363,18 @@ export const datetimeToolSchema = z.object({
|
|
|
326
363
|
export const compressionToolSchema = z.object({
|
|
327
364
|
data: z.string().describe('Data to compress/decompress'),
|
|
328
365
|
operation: z.enum(['compress', 'decompress']).describe('Operation'),
|
|
329
|
-
inputEncoding: z
|
|
330
|
-
|
|
331
|
-
|
|
366
|
+
inputEncoding: z
|
|
367
|
+
.enum(['base64', 'utf8'])
|
|
368
|
+
.optional()
|
|
369
|
+
.describe('Input encoding (default: utf8 for compress, base64 for decompress)'),
|
|
370
|
+
outputEncoding: z
|
|
371
|
+
.enum(['base64', 'utf8'])
|
|
372
|
+
.optional()
|
|
373
|
+
.describe('Output encoding (default: base64 for compress, utf8 for decompress)'),
|
|
374
|
+
level: z.number().int().min(0).max(9).optional().describe('Compression level (0-9, default 6)'),
|
|
332
375
|
});
|
|
333
|
-
export const signingToolSchema = z
|
|
376
|
+
export const signingToolSchema = z
|
|
377
|
+
.object({
|
|
334
378
|
operation: z.enum(['generateKeypair', 'sign', 'verify']).describe('Operation'),
|
|
335
379
|
algorithm: z.enum(['ed25519']).describe('Signing algorithm'),
|
|
336
380
|
message: z.string().optional().describe('Message to sign/verify'),
|
|
@@ -338,12 +382,26 @@ export const signingToolSchema = z.object({
|
|
|
338
382
|
publicKey: z.string().optional().describe('Public key (hex or base64)'),
|
|
339
383
|
signature: z.string().optional().describe('Signature to verify'),
|
|
340
384
|
encoding: z.enum(['hex', 'base64']).optional().describe('Key/signature encoding'),
|
|
385
|
+
seed: z
|
|
386
|
+
.string()
|
|
387
|
+
.optional()
|
|
388
|
+
.describe('Optional 32-byte seed for generateKeypair (hex or base64). A cryptographically secure seed is generated on the host when omitted.'),
|
|
389
|
+
})
|
|
390
|
+
.transform((input) => {
|
|
391
|
+
if (input.operation !== 'generateKeypair' || input.seed !== undefined)
|
|
392
|
+
return input;
|
|
393
|
+
const seed = randomBytes(32);
|
|
394
|
+
return {
|
|
395
|
+
...input,
|
|
396
|
+
seed: input.encoding === 'base64' ? seed.toString('base64') : seed.toString('hex'),
|
|
397
|
+
};
|
|
341
398
|
});
|
|
342
399
|
export function createSlugTool(options) {
|
|
343
400
|
return defineWasmTool({
|
|
344
401
|
name: 'slug',
|
|
345
402
|
description: 'Convert text to URL-safe slug with transliteration support',
|
|
346
403
|
wasmModule: getWasmPath('slug'),
|
|
404
|
+
wasi: true,
|
|
347
405
|
wasmFunction: 'slug',
|
|
348
406
|
parameters: slugToolSchema,
|
|
349
407
|
category: 'utility',
|
|
@@ -356,6 +414,7 @@ export function createValidationTool(options) {
|
|
|
356
414
|
name: 'validate',
|
|
357
415
|
description: 'Validate email, URL, UUID, IPv4, or IPv6 addresses',
|
|
358
416
|
wasmModule: getWasmPath('validation'),
|
|
417
|
+
wasi: true,
|
|
359
418
|
wasmFunction: 'validate',
|
|
360
419
|
parameters: validationToolSchema,
|
|
361
420
|
category: 'utility',
|
|
@@ -368,6 +427,7 @@ export function createDiffTool(options) {
|
|
|
368
427
|
name: 'diff',
|
|
369
428
|
description: 'Generate diff between two texts using Myers algorithm',
|
|
370
429
|
wasmModule: getWasmPath('diff'),
|
|
430
|
+
wasi: true,
|
|
371
431
|
wasmFunction: 'diff',
|
|
372
432
|
parameters: diffToolSchema,
|
|
373
433
|
category: 'utility',
|
|
@@ -380,6 +440,7 @@ export function createRegexTool(options) {
|
|
|
380
440
|
name: 'regex',
|
|
381
441
|
description: 'Execute regex operations with ReDoS protection',
|
|
382
442
|
wasmModule: getWasmPath('regex'),
|
|
443
|
+
wasi: true,
|
|
383
444
|
wasmFunction: 'regex',
|
|
384
445
|
parameters: regexToolSchema,
|
|
385
446
|
category: 'utility',
|
|
@@ -392,6 +453,7 @@ export function createCsvTool(options) {
|
|
|
392
453
|
name: 'csv',
|
|
393
454
|
description: 'Parse and generate CSV data (RFC 4180 compliant)',
|
|
394
455
|
wasmModule: getWasmPath('csv'),
|
|
456
|
+
wasi: true,
|
|
395
457
|
wasmFunction: 'csv',
|
|
396
458
|
parameters: csvToolSchema,
|
|
397
459
|
category: 'utility',
|
|
@@ -404,6 +466,7 @@ export function createMarkdownTool(options) {
|
|
|
404
466
|
name: 'markdown',
|
|
405
467
|
description: 'Convert Markdown to HTML (GFM subset)',
|
|
406
468
|
wasmModule: getWasmPath('markdown'),
|
|
469
|
+
wasi: true,
|
|
407
470
|
wasmFunction: 'markdown',
|
|
408
471
|
parameters: markdownToolSchema,
|
|
409
472
|
category: 'utility',
|
|
@@ -416,6 +479,7 @@ export function createXmlTool(options) {
|
|
|
416
479
|
name: 'xml',
|
|
417
480
|
description: 'Parse XML to JSON with XPath-like query support',
|
|
418
481
|
wasmModule: getWasmPath('xml'),
|
|
482
|
+
wasi: true,
|
|
419
483
|
wasmFunction: 'xml',
|
|
420
484
|
parameters: xmlToolSchema,
|
|
421
485
|
category: 'utility',
|
|
@@ -428,6 +492,7 @@ export function createDatetimeTool(options) {
|
|
|
428
492
|
name: 'datetime',
|
|
429
493
|
description: 'Parse, format, and manipulate dates (UTC + offset timezones)',
|
|
430
494
|
wasmModule: getWasmPath('datetime'),
|
|
495
|
+
wasi: true,
|
|
431
496
|
wasmFunction: 'datetime',
|
|
432
497
|
parameters: datetimeToolSchema,
|
|
433
498
|
category: 'utility',
|
|
@@ -440,6 +505,7 @@ export function createCompressionTool(options) {
|
|
|
440
505
|
name: 'compression',
|
|
441
506
|
description: 'Compress and decompress data using gzip',
|
|
442
507
|
wasmModule: getWasmPath('compression'),
|
|
508
|
+
wasi: true,
|
|
443
509
|
wasmFunction: 'compression',
|
|
444
510
|
parameters: compressionToolSchema,
|
|
445
511
|
category: 'utility',
|
|
@@ -452,6 +518,7 @@ export function createSigningTool(options) {
|
|
|
452
518
|
name: 'signing',
|
|
453
519
|
description: 'Digital signatures with Ed25519 (keypair generation, sign, verify)',
|
|
454
520
|
wasmModule: getWasmPath('signing'),
|
|
521
|
+
wasi: true,
|
|
455
522
|
wasmFunction: 'signing',
|
|
456
523
|
parameters: signingToolSchema,
|
|
457
524
|
category: 'utility',
|