@cogitator-ai/wasm-工具
基于WASM的工具,用于Cogitator代理. 使用 Web Assembly 执行安全、沙箱工具.
特征
- 18个预建工具 - 计算器, JSON, 散列器, Base64, 弹簧, 文本框, 单位, 校验, diff, regex, CSV, Markdown, XML, 日期时间, 压缩, Ed25519 签名, 颜色, semver
- 单独处决 - 每一个电话都用工人线条中的Extism sandbox运行,没有文件系统或网络接入
- 快速启动 - 没有要启动的容器;每个文件都会缓存编译的模块
- 自定义工具框架 - 说吧
defineWasmTool()用于您自己的 WASM 模块 - 热重装支持 - 说吧
WasmToolManager当模块文件更改时重新加载
安装
pnpm add @cogitator-ai/wasm-tools
@extism/extism (>= 2.0.0-rc13,现为: latest npm)作为依赖性安装; 预建的插件编译为 extism-js 并且需要它的宿主功能和WASI.
网站文件 : WASM 工具, (中文(简体) ), 沙盒。 。 。 .
如何执行工具
这里创建的每个工具都带有 sandbox: { type: 'wasm', ... } 配置和真实 execute()数字 :
- 内接器: 当
@cogitator-ai/sandbox可用,Cogitator通过它的WASM执行器(插件集合,工人行走超时)运行模块. 不然就归工具了execute()。 。 。 . - 直接数字 :
await tool.execute(params, context)验证params使用工具的Zod schema, 运行模块在 Extism 工人线条中, 执行timeout和荣誉context.signal。编译的模块被每个文件缓存,并在文件更改时被再编译.
const calc = createCalcTool();
await calc.execute({ expression: '(2 + 3) * 4' }, { agentId: 'a', runId: 'r', signal });
// { result: 20, expression: '(2 + 3) * 4' }
插件级别错误作为数据返回( E){ ..., error: '...' }),使代理能够反应;超时,中止和无效参数拒绝承诺.
快速启动
预建工具
使用内置的 WASM 工具 :
import {
createCalcTool,
createJsonTool,
createHashTool,
createBase64Tool,
createSlugTool,
createTextcaseTool,
createUnitsTool,
createValidationTool,
createDiffTool,
createRegexTool,
createCsvTool,
createMarkdownTool,
createXmlTool,
createDatetimeTool,
createCompressionTool,
createSigningTool,
createColorTool,
createSemverTool,
} from '@cogitator-ai/wasm-tools';
import { Cogitator, Agent } from '@cogitator-ai/core';
const agent = new Agent({
name: 'utility-assistant',
model: 'openai/gpt-6.1-sol',
instructions: 'Use your tools for calculations and data transformations.',
tools: [
createCalcTool(),
createJsonTool(),
createHashTool(),
createBase64Tool(),
createSlugTool(),
createTextcaseTool(),
createUnitsTool(),
createValidationTool(),
createDiffTool(),
createRegexTool(),
createCsvTool(),
createMarkdownTool(),
createXmlTool(),
createDatetimeTool(),
createCompressionTool(),
createSigningTool(),
createColorTool(),
createSemverTool(),
],
});
const cog = new Cogitator({
llm: { providers: { openai: { apiKey: process.env.OPENAI_API_KEY! } } },
});
const result = await cog.run(agent, {
input: 'Calculate the SHA-256 hash of "hello world"',
});
自定义 WASM 工具
创建在 WASM 沙盒中运行的自定义工具 :
import { defineWasmTool } from '@cogitator-ai/wasm-tools';
import { Agent } from '@cogitator-ai/core';
import { z } from 'zod';
const hashTool = defineWasmTool({
name: 'hash_text',
description: 'Hash text using various algorithms',
wasmModule: './my-hash.wasm',
wasmFunction: 'hash',
parameters: z.object({
text: z.string().describe('Text to hash'),
algorithm: z.enum(['sha256', 'sha512', 'md5']),
}),
category: 'utility',
tags: ['hash', 'crypto'],
timeout: 5000,
});
const agent = new Agent({
name: 'hasher',
model: 'openai/gpt-6.1-sol',
instructions: 'Hash text on request.',
tools: [hashTool],
});
使用 WasmTool 管理器重装
监视 WASM 文件并在更改时自动重新加载 :
import { WasmToolManager } from '@cogitator-ai/wasm-tools';
import { Cogitator, Agent } from '@cogitator-ai/core';
const manager = new WasmToolManager({ debounceMs: 200 });
// Watch directory for WASM plugins
await manager.watch('./plugins/*.wasm', {
onLoad: (name) => console.log(`✓ Loaded: ${name}`),
onReload: (name) => console.log(`↻ Reloaded: ${name}`),
onUnload: (name) => console.log(`✗ Unloaded: ${name}`),
onError: (name, _, err) => console.error(`Error ${name}: ${err.message}`),
});
// Or load a single module
const calcTool = await manager.load('./plugins/calc.wasm');
// Get all tools for agent
const agent = new Agent({
name: 'wasm-agent',
model: 'openai/gpt-6.1-sol',
instructions: 'Use the loaded tools.',
tools: manager.getTools(),
});
// Tools automatically use the latest plugin version after reload
const cogitator = new Cogitator({
llm: { providers: { openai: { apiKey: process.env.OPENAI_API_KEY! } } },
});
await cogitator.run(agent, { input: 'Calculate 2 + 2' });
// Cleanup when done
await manager.close();
API 参考
定义WasmTool( 配置)
创建自定义的 WASM 工具供代理使用 .
interface WasmToolConfig<TParams> {
name: string;
description: string;
wasmModule: string; // Path to .wasm file
wasmFunction?: string; // Function to call (default: 'run')
parameters: ZodType<TParams>;
category?: ToolCategory;
tags?: string[];
timeout?: number; // Execution timeout in ms (default 5000), also set as tool.timeout
wasi?: boolean; // Enable WASI (required for modules compiled with extism-js)
}
parameters 可能使用 Zod 转换: 解析( 输出) 值是模块得到的, 而 toJSON() 将输入计划暴露在LLM上.
创建 CalcTool( 选项 )
创建数学表达式的计算工具.
const calc = createCalcTool({ timeout: 10000 });
// Supports: +, -, *, /, %, unary +/-, parentheses, decimals (".5", "2.")
// Example: "2 + 2 * 3" → { result: 8, expression: "2 + 2 * 3" }
// Errors (division by zero, malformed numbers, non-finite results) → { result: null, error }
创建 JsonToole( 选项 )
使用 JSONPath 查询支持创建 JSON 处理器工具 .
const json = createJsonTool({ timeout: 10000 });
// { json: '{"a": {"b": 1}}', query: '$.a.b' } → { result: 1, type: 'number', found: true }
// { json, query: '$.items[*].id' } → { result: [1, 2], type: 'array', found: true }
支持的 JSONPath 子集 : $, (中文(简体) ), .key, (中文(简体) ), ['key'], (中文(简体) ), [n] (允许负面指数), [start:end:step], (中文(简体) ), * 编号 : [*],和递归后世 ..key 编号 : ..*. 通关卡、切片和递归回落总是返回一个阵列。 缺少路径返回 { result: null, type: 'undefined', found: false }; 过滤器 ([?()]工会被错误地拒绝.
创建 HashToole( 选项 )
创建支持多算法的密码散列工具.
const hash = createHashTool({ timeout: 10000 });
// Supports: sha256, sha1, md5
// Example: { text: "hello", algorithm: "sha256" } → "2cf24dba5fb0a30e..."
创建Base64 Tool( 选项 )
以 URL-安全变体支持创建 Base64 编码/解码工具.
const base64 = createBase64Tool({ timeout: 10000 });
// Example: { text: "hello", operation: "encode" } → "aGVsbG8="
// Example: { text: "aGVsbG8=", operation: "decode" } → "hello"
// URL-safe: { text: "hello", operation: "encode", urlSafe: true } → "aGVsbG8" (no padding)
解码既接受字母表,可选的编补和白空,以出错拒绝无效字符/长度,并用U+FFFD来替换无效的UTF-8序列.
创建 SlugToole( 选项 )
用 Unicode 转写从文本中生成 URL- safe satters .
const slug = createSlugTool({ timeout: 10000 });
// Example: { text: "Hello World!" } → "hello-world"
// Example: { text: "Привет мир", separator: "_" } → "privet_mir"
// Example: { text: "Crème brûlée, a/b" } → "creme-brulee-a-b"
任意跑出的非平面字符会变成一个分隔符;空心符被丢出;口音被转写后被剥去. maxLength 必须是正整数,并尽可能在分隔符上切入.
创建 Textcase Tool( 选项 )
在骆驼,帕斯卡尔,蛇,克巴布,常数,标题,和句子等案例之间转换文字.
const textcase = createTextcaseTool({ timeout: 5000 });
// Example: { text: "parseHTTPResponse", to: "snake" } → { result: "parse_http_response", words: ["parse", "http", "response"] }
// Example: { text: "version2Beta", to: "kebab" } → { result: "version-2-beta", words: ["version", "2", "beta"] }
- 支助案件数字 :
camel, (中文(简体) ),pascal, (中文(简体) ),snake, (中文(简体) ),kebab, (中文(简体) ),constant, (中文(简体) ),title, (中文(简体) ),sentence。 。 。 . - 拆分规则:分出骆驼 Case,PascalCase,缩写:
parseHTTPResponse→["parse", "http", "response"], (中文(简体) ),XMLHttpRequest→["xml", "http", "request"]),和白空间/_编号 :-编号 :.编号 :/分离器(包括重复和引导/跟踪). - 数字规则: 数字运行是独立的符号,按字母和数字字母的边界进行分割(
version2Beta→["version", "2", "beta"], (中文(简体) ),utf8→["utf", "8"]) (中文(简体) ). - 空输入: 返回
{ result: "", words: [] }没有错误.
创建 UnitsTools( 选项 )
在长度、质量、温度、体积、速度和数据大小的单位之间转换.
const units = createUnitsTool({ timeout: 10000 });
// Example: { value: 100, from: "C", to: "F" } → { value: 212, from: "C", to: "F", category: "temperature" }
// Example: { value: 1, from: "GiB", to: "GB" } → { value: 1.073741824, from: "GiB", to: "GB", category: "data" }
- 长度数字 :
mm, (中文(简体) ),cm, (中文(简体) ),m, (中文(简体) ),km, (中文(简体) ),in, (中文(简体) ),ft, (中文(简体) ),yd, (中文(简体) ),mi - 质量数字 :
mg, (中文(简体) ),g, (中文(简体) ),kg, (中文(简体) ),t, (中文(简体) ),oz, (中文(简体) ),lb - 温度数字 :
C, (中文(简体) ),F, (中文(简体) ),K(单位:千美元) - 音量数字 :
ml, (中文(简体) ),l, (中文(简体) ),tsp, (中文(简体) ),tbsp, (中文(简体) ),cup, (中文(简体) ),US gallon, (中文(简体) ),imperial gallon - 速度数字 :
m/s, (中文(简体) ),km/h, (中文(简体) ),mph, (中文(简体) ),knot - 数据数字 :
B, (中文(简体) ),KB, (中文(简体) ),MB, (中文(简体) ),GB, (中文(简体) ),TB(功率为1000)和KiB, (中文(简体) ),MiB, (中文(简体) ),GiB, (中文(简体) ),TiB(功率为1024)
跨类别转换和未知单位返回 a error 列出所支持的单位.
创建变量工具( 选项 )
验证常用格式:电子邮件,URL,UUID,IPv4,IPv6.
const validation = createValidationTool({ timeout: 10000 });
// Example: { value: "[email protected]", type: "email" } → { valid: true, normalized: "[email protected]" }
// Example: { value: "2001:DB8:0:0:0:0:0:1", type: "ipv6" } → { valid: true, normalized: "2001:db8::1" }
- 电子邮件:dot-atom 本地部分(无引出/拖出/相接点, 64个字符),有效的主机名标签;只有域名被小写.
- url 密码数字 :
http, (中文(简体) ),https, (中文(简体) ),ftp, (中文(简体) ),ftps; 用户info, 端口 \\ 65535 和括号内的 IPv6 主机被支持; 白空间和控制字符被拒绝 。 计划缺省至https://。 。 。 . - ipv4 数据: 点为四面体,而不带正零(
01.2.3.4拒绝, 匹配节点net.isIPv4) (中文(简体) ). - ipv6 数据: 完整的 RFC 4291 语法包括
::并嵌入式IPv4;已与RFC 5952条犬形规范化. 区身份证被拒.
创建 DiffTool( 选项 )
使用 Myers diff 算法比较文本 .
const diff = createDiffTool({ timeout: 10000 });
// { original: "a\nb\n", modified: "a\nc\n" } →
// { diff: "--- original\n+++ modified\n@@ -1,2 +1,2 @@\n a\n-b\n+c", additions: 1, deletions: 1, changes: [...] }
format 实值 unified (默认,标准汉克与 context 线条,默认 3, inline 或者说 json。后行新线不被视为外行.
创建 Regex Tool( 选项 )
安全regex操作与ReDoS保护.
const regex = createRegexTool({ timeout: 10000 });
// Example: { text: "hello world", pattern: "\\w+", operation: "matchAll" }
// Supports: match, matchAll, test, replace, split
具有巢无约束的修饰者(如. (a+)+, (中文(简体) ), (\w+\s?)+)在前面被拒绝。 其他灾难性模式(例如重叠的交替方式,例如: (a|aa)+$停止执行的暂停,终止工人.
创建 CsvTool( 选项 )
RFC 4180 兼容 CSV 解析和生成.
const csv = createCsvTool({ timeout: 10000 });
// Parse: { data: "a,b\n1,2", operation: "parse", headers: true } → headers ["a","b"], result [["1","2"]]
// Stringify: { data: [["a","b"],["1","2"]], operation: "stringify", headers: ["x","y"] }
引用只打开一个字段开头的引用字段;关闭后未终止的引用和字符都是错误. 一个UTF-8 BOM被忽略了. 对于 parse, (中文(简体) ), headers 也可能是列名的数组。 字符串时对象为JSON-encode.
创建 Markdown Tool( 选项 )
将 Markdown 转换为 HTML( GFM 子集) .
const markdown = createMarkdownTool({ timeout: 10000 });
// Example: { markdown: "# Hello\n**bold**" }
// Returns: { html: "<h1>Hello</h1>\n<p><strong>bold</strong></p>" }
// Supports: headings, emphasis, strikethrough, links, images, autolinks, code spans/blocks,
// lists (ordered with start number), blockquotes, rules, GFM tables with alignment, backslash escapes
options.sanitize 默认为 true: 原始 HTML 已逃出, 并将 URL 链接/图像到除此之外的其他方案 http, (中文(简体) ), https, (中文(简体) ), mailto, (中文(简体) ), tel 财务报告和审定财务报表 ftp (例如:. javascript:, (中文(简体) ), data:改为: #。代码内容和生成的属性值总是被逃避。 内字下划线(snake_case)不被视为强调.
创建 XmlToole( 选项 )
用类似 XPath 的查询解析 XML 到 JSON .
const xml = createXmlTool({ timeout: 10000 });
// Example: { xml: "<root><item>1</item></root>", query: "/root/item" }
// Supports: elements, attributes, CDATA, comments
查询语法:从根元素开始的绝对路径(/root/item),从下面开始相对路径(item, (中文(简体) ), //name 寻找后代, * 匹配任意元素, name[2] 选择第2个比对(1个比分), /@attr (或 @*返回属性值和 /text() 返回文本内容。 一个匹配返回一个值, 多个返回一个数组, 没有返回 { result: null, type: 'empty' }。错误的文档(未关闭或不匹配的标签、多根、未终止属性)是错误;DTD实体从未被扩展.
创建 Datetime Tool( 选项 )
UTC支持的日期/时间操作并抵消时区支持.
const datetime = createDatetimeTool({ timeout: 10000 });
// Parse: { date: "2024-01-15", operation: "parse" }
// Format: { date: "2024-01-15T10:30:00Z", operation: "format", format: "YYYY-MM-DD" }
// Add: { date: "2024-01-15", operation: "add", amount: 7, unit: "days" }
// Diff: { date: "2024-01-01", operation: "diff", endDate: "2024-01-15", unit: "days" }
- 接受国际标准化组织的日期( E)
2024-01-15, (中文(简体) ),2024-01-15 10:30分数秒,Z编号 :+04:00编号 :+0400编号 :+04),Unix时间戳(10个数字=秒,11-13=毫秒)等Date.parse明白吗? 可能的日期,例如2023-02-29拒绝. - 月/年计算夹至月底(
2024-01-31+ 1个月=2024-02-29) (中文(简体) ). - 格式符号 :
YYYY MM DD HH mm ss SSS Z中,每次出现都会被替换;括号内为正文([at]) (中文(简体) ). diff返回整个单位,切换为零,负endDate更早的时候.
创建压缩工具( 选项 )
Gzip压缩并解压(RFC 1952),与zlib互通.
const compression = createCompressionTool({ timeout: 30000 });
// Compress: { data: "hello", operation: "compress", level: 6 } → { result: "H4sI...", originalSize, resultSize, ratio }
// Decompress: { data: "H4sIAAAA...", operation: "decompress" } → { result: "hello", ... }
默认 : compress 读取 UTF-8并返回基数64; decompress 读取基数64并返回 UTF-8. 使用 inputEncoding编号 :outputEncoding: 'base64' 二进制数据. level 是整数 0-9。 减压验证了gzip CRC32和大小,并被封为输出的64 MB.
创建签名工具( 选项 )
Ed25519 用于消息认证的数字签名.
const signing = createSigningTool({ timeout: 10000 });
// Generate keypair: { operation: "generateKeypair", algorithm: "ed25519" }
// Sign: { operation: "sign", algorithm: "ed25519", message: "hello", privateKey: "..." }
// Verify: { operation: "verify", algorithm: "ed25519", message: "hello", publicKey: "...", signature: "..." }
WASM没有安全的随机源,因此工具在主机上生成一个32字节种子 node:crypto 何时 generateKeypair 调用没有 seed;种子是私钥. 钥匙和签名的使用 encoding: 'hex' (违约)或 'base64'。签署者为RFC 8032 Ed25519 node:crypto;非卡通或非曲线公用密钥验证失败. 允许空信件 .
创建 ColorToole( 选项 )
转换颜色格式(HEX,RGB,HSL)并计算出WCAG 2.x对比比.
const color = createColorTool({ timeout: 5000 });
// Convert: { operation: "convert", color: "#ff0000" }
// → { hex: "#ff0000", rgb: { r: 255, g: 0, b: 0, a: 1 }, hsl: { h: 0, s: 100, l: 50, a: 1 } }
// Contrast: { operation: "contrast", color: "#000000", color2: "#ffffff" }
// → { ratio: 21, normalText: { aa: true, aaa: true }, largeText: { aa: true, aaa: true } }
支助 #rgb, (中文(简体) ), #rrggbb, (中文(简体) ), #rrggbbaa, (中文(简体) ), rgb(), (中文(简体) ), rgba(), (中文(简体) ), hsl(),以及 hsla() 输入带有alpha保存。 相矛盾的计算遵循了WCAG 2.x 相对亮度,评价AA/AAA符合普通和大文本.
创建SemverToole( 选项 )
剖析版本,比较优先级(SemVer 2.0.0),评价范围满意度,和凸起版本.
const semver = createSemverTool({ timeout: 5000 });
// Parse: { operation: "parse", version: "1.2.3-alpha.1+build" }
// → { major: 1, minor: 2, patch: 3, prerelease: ["alpha", 1], build: ["build"], version: "1.2.3-alpha.1+build" }
// Compare: { operation: "compare", version: "1.0.0-alpha", version2: "1.0.0" }
// → { comparison: -1 }
// Satisfies: { operation: "satisfies", version: "1.2.3", range: "^1.0.0" }
// → { satisfies: true }
// Bump: { operation: "bump", version: "1.2.3", release: "minor" }
// → { version: "1.3.0" }
执行 SemVer 2. 0.0 优先规则( 建立元数据, 比较时忽略), 范围满意度支持 ^, (中文(简体) ), ~,关系运营商(>=, (中文(简体) ), <=, (中文(简体) ), >, (中文(简体) ), <, (中文(简体) ), =),通配符(x, (中文(简体) ), X, (中文(简体) ), *),以及 || 预释隔离的结合, 和决定性的版本相撞.
获取WasmPath( 名称)
获得预建的WASM模块的路径.
import { getWasmPath } from '@cogitator-ai/wasm-tools';
const calcPath = getWasmPath('calc'); // Path to calc.wasm
const jsonPath = getWasmPath('json'); // Path to json.wasm
结果是一种绝对路径,所以它的工作是 wasmModule 到处都是,不管软件包管理器的布局。 与 @cogitator-ai/sandbox 您也可以通过软件包路径 @cogitator-ai/wasm-tools/wasm/calc.wasm: WASM 执行器从您的应用程序中解决它(先是工作目录,再是条目脚本目录).
瓦斯工具管理员
用热重装支持管理 WASM 工具 .
interface WasmToolManagerOptions {
debounceMs?: number; // File change debounce delay (default: 100ms)
useWasi?: boolean; // Enable WASI for all modules
timeout?: number; // Per-call timeout in ms (default: 30000)
}
interface WasmToolCallbacks {
onLoad?: (name: string, path: string) => void;
onReload?: (name: string, path: string) => void;
onUnload?: (name: string, path: string) => void;
onError?: (name: string, path: string, error: Error) => void;
}
declare class WasmToolManager {
constructor(options?: WasmToolManagerOptions);
// Watch a glob pattern for WASM files
watch(pattern: string, callbacks?: WasmToolCallbacks): Promise<void>;
// Load a single WASM module
load(wasmPath: string): Promise<Tool>;
// Get all loaded tools
getTools(): Tool[];
// Get a tool by module name
getTool(name: string): Tool | undefined;
// Get module metadata
getModule(name: string): LoadedModule | undefined;
getModules(): LoadedModule[];
// Close watcher and all plugins
close(): Promise<void>;
}
管理工具调用模块导出 run 函数带有 JSON 编码参数。 插件在 Extism 工人线程中运行: 当调用时间或它的 context.signal 中止, 拒绝调用和插件被替换为新实例, 因此工具继续工作 .
遗产出口
用于直接使用沙盒(预建模块也可达到: @cogitator-ai/wasm-tools/wasm/<name>.wasm:
| 导出 | 说明 |
|---|---|
calcToolConfig | 用于计算器 WASM 模块的沙盒配置 |
calcToolSchema | 计算器输入的 Zod schema |
jsonToolConfig | JSON 处理器的沙盒配置 |
jsonToolSchema | JSON 处理器输入的 Zod 方案 |
hashToolConfig | 散列 WASM 模块的沙盒配置 |
hashToolSchema | 散列输入的 Zod schema |
base64ToolConfig | Base64 WASM 模块的沙盒配置 |
base64ToolSchema | 用于基础64输入的 Zod schema |
构建自定义 WASM 模块
WASM模块使用"极端主义"JS PDK:
// my-tool.ts
export function run(): number {
const input = JSON.parse(Host.inputString());
// Your logic here
const result = { processed: input.data };
Host.outputString(JSON.stringify(result));
return 0; // 0 = success
}
declare const Host: {
inputString(): string;
outputString(s: string): void;
};
用( 接口文件) 构建 my-tool.d.ts 声明 declare module 'main' { export function run(): I32; } 列出出口:
esbuild my-tool.ts --outfile=temp/my-tool.js --bundle --format=cjs --target=es2020
extism-js temp/my-tool.js -i my-tool.d.ts -o dist/my-tool.wasm
模块编译为 extism-js 嵌入快速JS并需要 WASI:通过 wasi: true 改为 defineWasmTool (或 useWasi: true 改为 WasmToolManager) (中文(简体) ).
软件包构建( E)pnpm build)编译 src/plugins/*.ts 与 extism-js 当它安装时,如果任何插件无法编译则失败。 无 extism-js 它会写入空占位符 .wasm 文件; 然后执行一个工具失败, 并有明显的“ 位置持有人构建” 错误 .
警卫
WASM 工具在一个安全的Extism 沙盒中运行 :
- QQ 没有文件系统访问( 没有目录被预开, 即使有 WASI )
- QQ 没有网络访问( 没有允许的主机)
- 超时执行(工人线程终止)
- 终止支持通过
ToolContext.signal - 每个插件实例的孤立线性内存
许可证
麻省理工学院