agentvault 1.0.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/.dfx/local/network-id +4 -0
- package/.next/trace +2 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/AGENTS.md +43 -0
- package/CHANGELOG.md +196 -0
- package/LICENSE +21 -0
- package/PLAN_VAULT_INTEGRATION.md +318 -0
- package/README.md +253 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +28 -0
- package/backups/test-backup.json +28 -0
- package/dist/cli/commands/approve.d.ts +4 -0
- package/dist/cli/commands/approve.js +232 -0
- package/dist/cli/commands/archive.d.ts +4 -0
- package/dist/cli/commands/archive.js +192 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.js +164 -0
- package/dist/cli/commands/cloud-backup.d.ts +4 -0
- package/dist/cli/commands/cloud-backup.js +221 -0
- package/dist/cli/commands/cycles.d.ts +8 -0
- package/dist/cli/commands/cycles.js +83 -0
- package/dist/cli/commands/decrypt.d.ts +16 -0
- package/dist/cli/commands/decrypt.js +101 -0
- package/dist/cli/commands/deploy.d.ts +32 -0
- package/dist/cli/commands/deploy.js +208 -0
- package/dist/cli/commands/exec.d.ts +26 -0
- package/dist/cli/commands/exec.js +109 -0
- package/dist/cli/commands/fetch.d.ts +23 -0
- package/dist/cli/commands/fetch.js +164 -0
- package/dist/cli/commands/health.d.ts +8 -0
- package/dist/cli/commands/health.js +72 -0
- package/dist/cli/commands/identity.d.ts +8 -0
- package/dist/cli/commands/identity.js +140 -0
- package/dist/cli/commands/inference.d.ts +4 -0
- package/dist/cli/commands/inference.js +225 -0
- package/dist/cli/commands/info.d.ts +8 -0
- package/dist/cli/commands/info.js +59 -0
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.js +135 -0
- package/dist/cli/commands/instrument.d.ts +8 -0
- package/dist/cli/commands/instrument.js +35 -0
- package/dist/cli/commands/list.d.ts +36 -0
- package/dist/cli/commands/list.js +173 -0
- package/dist/cli/commands/logs.d.ts +8 -0
- package/dist/cli/commands/logs.js +96 -0
- package/dist/cli/commands/monitor.d.ts +8 -0
- package/dist/cli/commands/monitor.js +84 -0
- package/dist/cli/commands/network.d.ts +14 -0
- package/dist/cli/commands/network.js +258 -0
- package/dist/cli/commands/package.d.ts +36 -0
- package/dist/cli/commands/package.js +188 -0
- package/dist/cli/commands/profile.d.ts +8 -0
- package/dist/cli/commands/profile.js +76 -0
- package/dist/cli/commands/promote.d.ts +8 -0
- package/dist/cli/commands/promote.js +89 -0
- package/dist/cli/commands/rebuild.d.ts +21 -0
- package/dist/cli/commands/rebuild.js +140 -0
- package/dist/cli/commands/rollback.d.ts +8 -0
- package/dist/cli/commands/rollback.js +120 -0
- package/dist/cli/commands/show.d.ts +36 -0
- package/dist/cli/commands/show.js +200 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.js +34 -0
- package/dist/cli/commands/status.d.ts +14 -0
- package/dist/cli/commands/status.js +83 -0
- package/dist/cli/commands/test.d.ts +8 -0
- package/dist/cli/commands/test.js +109 -0
- package/dist/cli/commands/tokens.d.ts +8 -0
- package/dist/cli/commands/tokens.js +62 -0
- package/dist/cli/commands/trace.d.ts +8 -0
- package/dist/cli/commands/trace.js +68 -0
- package/dist/cli/commands/wallet-export.d.ts +13 -0
- package/dist/cli/commands/wallet-export.js +140 -0
- package/dist/cli/commands/wallet-history.d.ts +10 -0
- package/dist/cli/commands/wallet-history.js +127 -0
- package/dist/cli/commands/wallet-import.d.ts +10 -0
- package/dist/cli/commands/wallet-import.js +209 -0
- package/dist/cli/commands/wallet-multi-send.d.ts +17 -0
- package/dist/cli/commands/wallet-multi-send.js +195 -0
- package/dist/cli/commands/wallet-process-queue.d.ts +19 -0
- package/dist/cli/commands/wallet-process-queue.js +209 -0
- package/dist/cli/commands/wallet-sign.d.ts +13 -0
- package/dist/cli/commands/wallet-sign.js +207 -0
- package/dist/cli/commands/wallet.d.ts +12 -0
- package/dist/cli/commands/wallet.js +794 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +96 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.js +14 -0
- package/fixup_1_0_OSS_release.md +136 -0
- package/fixup_REALEASE_PRD.md +136 -0
- package/package.json +79 -0
- package/pnpm-workspace.yaml +5 -0
- package/scripts/dev-dashboard.mjs +84 -0
- package/site/README.md +63 -0
- package/site/docusaurus.config.ts +148 -0
- package/site/package-lock.json +18383 -0
- package/site/package.json +47 -0
- package/site/sidebars.ts +86 -0
- package/site/static/.gitkeep +0 -0
- package/site/static/img/logo.svg +28 -0
- package/site/static/img/og-image.svg +35 -0
- package/src/archival/archive-manager.ts +372 -0
- package/src/archival/arweave-client.ts +289 -0
- package/src/archival/index.ts +8 -0
- package/src/backup/backup.ts +315 -0
- package/src/backup/index.ts +7 -0
- package/src/cloud-storage/cloud-sync.ts +461 -0
- package/src/cloud-storage/index.ts +11 -0
- package/src/cloud-storage/provider-detector.ts +198 -0
- package/src/cloud-storage/types.ts +104 -0
- package/src/debugging/index.ts +6 -0
- package/src/debugging/logs.ts +193 -0
- package/src/debugging/types.ts +100 -0
- package/src/deployment/deployer.ts +274 -0
- package/src/deployment/icpClient.ts +620 -0
- package/src/deployment/index.ts +46 -0
- package/src/deployment/promotion.ts +161 -0
- package/src/deployment/types.ts +111 -0
- package/src/icp/batch.ts +374 -0
- package/src/icp/cycles.ts +50 -0
- package/src/icp/environment.ts +215 -0
- package/src/icp/icpcli.ts +438 -0
- package/src/icp/icwasm.ts +222 -0
- package/src/icp/identity.ts +77 -0
- package/src/icp/index.ts +94 -0
- package/src/icp/optimization.ts +242 -0
- package/src/icp/tokens.ts +36 -0
- package/src/icp/tool-detector.ts +110 -0
- package/src/icp/types.ts +574 -0
- package/src/index.ts +25 -0
- package/src/inference/bittensor-client.ts +304 -0
- package/src/inference/index.ts +8 -0
- package/src/inference/inference-manager.ts +327 -0
- package/src/metrics/index.ts +7 -0
- package/src/metrics/metrics.ts +186 -0
- package/src/monitoring/alerting.ts +190 -0
- package/src/monitoring/health.ts +197 -0
- package/src/monitoring/index.ts +38 -0
- package/src/monitoring/info.ts +114 -0
- package/src/monitoring/types.ts +99 -0
- package/src/network/index.ts +5 -0
- package/src/network/network-config.ts +129 -0
- package/src/packaging/compiler.ts +647 -0
- package/src/packaging/config-persistence.ts +135 -0
- package/src/packaging/config-schemas.ts +156 -0
- package/src/packaging/detector.ts +220 -0
- package/src/packaging/index.ts +90 -0
- package/src/packaging/packager.ts +118 -0
- package/src/packaging/parsers/clawdbot.ts +278 -0
- package/src/packaging/parsers/cline.ts +223 -0
- package/src/packaging/parsers/generic.ts +266 -0
- package/src/packaging/parsers/goose.ts +214 -0
- package/src/packaging/parsers/index.ts +11 -0
- package/src/packaging/serializer.ts +260 -0
- package/src/packaging/types.ts +144 -0
- package/src/packaging/wasmedge-compiler.ts +406 -0
- package/src/security/index.ts +17 -0
- package/src/security/multisig.ts +415 -0
- package/src/security/types.ts +416 -0
- package/src/security/vetkeys.ts +655 -0
- package/src/testing/index.ts +6 -0
- package/src/testing/local-runner.ts +264 -0
- package/src/testing/types.ts +104 -0
- package/src/wallet/cbor-serializer.ts +323 -0
- package/src/wallet/chain-dispatcher.ts +313 -0
- package/src/wallet/cross-chain-aggregator.ts +346 -0
- package/src/wallet/index.ts +76 -0
- package/src/wallet/key-derivation.ts +425 -0
- package/src/wallet/providers/base-provider.ts +154 -0
- package/src/wallet/providers/cketh-provider.ts +434 -0
- package/src/wallet/providers/polkadot-provider.ts +503 -0
- package/src/wallet/providers/solana-provider.ts +490 -0
- package/src/wallet/transaction-queue.ts +284 -0
- package/src/wallet/types.ts +178 -0
- package/src/wallet/vetkeys-adapter.ts +431 -0
- package/src/wallet/wallet-manager.ts +597 -0
- package/src/wallet/wallet-storage.ts +380 -0
- package/vercel.json +8 -0
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WASM Compilation
|
|
3
|
+
*
|
|
4
|
+
* This module provides real WASM compilation for agent code.
|
|
5
|
+
* It bundles agent source code and creates WebAssembly modules
|
|
6
|
+
* with embedded JavaScript for execution.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as fs from 'node:fs';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import * as esbuild from 'esbuild';
|
|
12
|
+
import type { AgentConfig, PackageResult, PackageOptions } from './types.js';
|
|
13
|
+
import {
|
|
14
|
+
generateWasmEdgeWrapper,
|
|
15
|
+
validateWasmEdgeModule,
|
|
16
|
+
generateWasmEdgeConfig,
|
|
17
|
+
generateWasmEdgeManifest,
|
|
18
|
+
type WasmEdgeOptions,
|
|
19
|
+
DEFAULT_WASMEDGE_OPTIONS,
|
|
20
|
+
} from './wasmedge-compiler.js';
|
|
21
|
+
import { runOptimizationPipeline } from '../icp/optimization.js';
|
|
22
|
+
import type { IcWasmOptLevel } from '../icp/types.js';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* WASM magic bytes (first 4 bytes of any valid .wasm file)
|
|
26
|
+
*/
|
|
27
|
+
const WASM_MAGIC = Buffer.from([0x00, 0x61, 0x73, 0x6d]);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* WASM version bytes (version 1)
|
|
31
|
+
*/
|
|
32
|
+
const WASM_VERSION = Buffer.from([0x01, 0x00, 0x00, 0x00]);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Bundle agent code to JavaScript
|
|
36
|
+
*
|
|
37
|
+
* Uses esbuild to bundle the agent's source code into a single JavaScript file.
|
|
38
|
+
*/
|
|
39
|
+
export async function bundleAgentCode(config: AgentConfig): Promise<string> {
|
|
40
|
+
if (!config.entryPoint) {
|
|
41
|
+
if (config.type === 'goose') {
|
|
42
|
+
const pythonCandidates = ['goose.py', 'main.py'];
|
|
43
|
+
const hasPythonEntrypoint = pythonCandidates.some((candidate) =>
|
|
44
|
+
fs.existsSync(path.resolve(config.sourcePath, candidate))
|
|
45
|
+
);
|
|
46
|
+
if (hasPythonEntrypoint) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
'Goose Python entrypoints are not supported in the bundler. Use a JS/TS entrypoint instead.'
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`No entry point found for agent ${config.name}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const entryPath = path.resolve(config.sourcePath, config.entryPoint);
|
|
56
|
+
|
|
57
|
+
if (!fs.existsSync(entryPath)) {
|
|
58
|
+
throw new Error(`Entry point not found: ${entryPath}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (path.extname(config.entryPoint) === '.py') {
|
|
62
|
+
throw new Error(
|
|
63
|
+
'Goose Python entrypoints are not supported in the bundler. Use a JS/TS entrypoint instead.'
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const result = await esbuild.build({
|
|
69
|
+
entryPoints: [entryPath],
|
|
70
|
+
bundle: true,
|
|
71
|
+
platform: 'browser',
|
|
72
|
+
target: 'es2020',
|
|
73
|
+
format: 'iife',
|
|
74
|
+
minify: false,
|
|
75
|
+
sourcemap: false,
|
|
76
|
+
write: false,
|
|
77
|
+
treeShaking: false,
|
|
78
|
+
logLevel: 'silent',
|
|
79
|
+
external: [],
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (result.errors.length > 0) {
|
|
83
|
+
const errorMessages = result.errors
|
|
84
|
+
.map((e) => e.text)
|
|
85
|
+
.join('; ');
|
|
86
|
+
throw new Error(`Bundle failed: ${errorMessages}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!result.outputFiles[0]) {
|
|
90
|
+
throw new Error('Bundle produced no output files');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return result.outputFiles[0].text;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
96
|
+
throw new Error(`Failed to bundle agent code: ${message}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Helper to concatenate buffers and Uint8Arrays
|
|
102
|
+
*/
|
|
103
|
+
function concatBuffers(parts: (Buffer | Uint8Array | number[])[]): Buffer {
|
|
104
|
+
const buffers = parts.map(p => {
|
|
105
|
+
if (Array.isArray(p)) {
|
|
106
|
+
return Buffer.from(p);
|
|
107
|
+
}
|
|
108
|
+
if (p instanceof Uint8Array) {
|
|
109
|
+
return Buffer.from(p.buffer, p.byteOffset, p.byteLength);
|
|
110
|
+
}
|
|
111
|
+
return p;
|
|
112
|
+
});
|
|
113
|
+
return Buffer.concat(buffers);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Write LEB128 encoded unsigned integer directly to bytes
|
|
118
|
+
*/
|
|
119
|
+
function writeUleb128Bytes(value: number): number[] {
|
|
120
|
+
const bytes: number[] = [];
|
|
121
|
+
let remaining = value >>> 0;
|
|
122
|
+
|
|
123
|
+
do {
|
|
124
|
+
let byte = remaining & 0x7f;
|
|
125
|
+
remaining >>>= 7;
|
|
126
|
+
if (remaining !== 0) {
|
|
127
|
+
byte |= 0x80;
|
|
128
|
+
}
|
|
129
|
+
bytes.push(byte);
|
|
130
|
+
} while (remaining !== 0);
|
|
131
|
+
|
|
132
|
+
return bytes;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Generate a real WASM binary with embedded JavaScript bundle
|
|
137
|
+
*
|
|
138
|
+
* Creates a WASM module that contains:
|
|
139
|
+
* - Magic bytes and version
|
|
140
|
+
* - Custom section with agent metadata
|
|
141
|
+
* - Data section with embedded JavaScript bundle
|
|
142
|
+
* - Exported functions for agent lifecycle
|
|
143
|
+
*/
|
|
144
|
+
export function generateWasm(config: AgentConfig, javascriptBundle: string): Buffer {
|
|
145
|
+
const agentNameBytes = Buffer.from(config.name, 'utf-8');
|
|
146
|
+
const jsBytes = Buffer.from(javascriptBundle, 'utf-8');
|
|
147
|
+
|
|
148
|
+
// Build sections
|
|
149
|
+
const sections: Buffer[] = [];
|
|
150
|
+
|
|
151
|
+
// 1. Custom section with metadata
|
|
152
|
+
const version = config.version ?? '1.0.0';
|
|
153
|
+
const metadataContent = Buffer.concat([
|
|
154
|
+
Buffer.from('agentvault', 'utf-8'),
|
|
155
|
+
Buffer.from([0]),
|
|
156
|
+
agentNameBytes,
|
|
157
|
+
Buffer.from([0]),
|
|
158
|
+
Buffer.from(config.type, 'utf-8'),
|
|
159
|
+
Buffer.from([0]),
|
|
160
|
+
Buffer.from(version, 'utf-8'),
|
|
161
|
+
]);
|
|
162
|
+
|
|
163
|
+
const customSectionName = Buffer.from('agent.metadata', 'utf-8');
|
|
164
|
+
const customSection = concatBuffers([
|
|
165
|
+
Buffer.from([0x00]), // section id: custom
|
|
166
|
+
concatBuffers([writeUleb128Bytes(customSectionName.length + 1 + metadataContent.length)]),
|
|
167
|
+
customSectionName,
|
|
168
|
+
Buffer.from([0]), // null terminator
|
|
169
|
+
metadataContent,
|
|
170
|
+
]);
|
|
171
|
+
sections.push(customSection);
|
|
172
|
+
|
|
173
|
+
// 2. Type section
|
|
174
|
+
const typeSectionContent = Buffer.concat([
|
|
175
|
+
// Function type 0: () -> i32
|
|
176
|
+
Buffer.from([0x60]), // func type
|
|
177
|
+
Buffer.from([0x00]), // 0 params
|
|
178
|
+
Buffer.from([0x7f]), // 1 result i32
|
|
179
|
+
// Function type 1: (i32) -> i32
|
|
180
|
+
Buffer.from([0x60]), // func type
|
|
181
|
+
Buffer.from([0x01]), // 1 param i32
|
|
182
|
+
Buffer.from([0x7f]), // 1 result i32
|
|
183
|
+
]);
|
|
184
|
+
|
|
185
|
+
const typeSection = concatBuffers([
|
|
186
|
+
Buffer.from([0x01]), // section id: type
|
|
187
|
+
concatBuffers([writeUleb128Bytes(typeSectionContent.length)]),
|
|
188
|
+
concatBuffers([writeUleb128Bytes(2)]), // 2 types
|
|
189
|
+
typeSectionContent,
|
|
190
|
+
]);
|
|
191
|
+
sections.push(typeSection);
|
|
192
|
+
|
|
193
|
+
// 3. Function section
|
|
194
|
+
const funcSectionContent = Buffer.concat([
|
|
195
|
+
// Function 0: uses type 0
|
|
196
|
+
Buffer.from([0x00]),
|
|
197
|
+
// Function 1: uses type 1
|
|
198
|
+
Buffer.from([0x01]),
|
|
199
|
+
]);
|
|
200
|
+
|
|
201
|
+
const funcSection = concatBuffers([
|
|
202
|
+
Buffer.from([0x03]), // section id: function
|
|
203
|
+
concatBuffers([writeUleb128Bytes(funcSectionContent.length)]),
|
|
204
|
+
concatBuffers([writeUleb128Bytes(2)]), // 2 functions
|
|
205
|
+
funcSectionContent,
|
|
206
|
+
]);
|
|
207
|
+
sections.push(funcSection);
|
|
208
|
+
|
|
209
|
+
// 4. Memory section
|
|
210
|
+
const memorySection = Buffer.concat([
|
|
211
|
+
Buffer.from([0x05]), // section id: memory
|
|
212
|
+
Buffer.from([0x01, 0x01]), // 1 memory, min 1 page (64KB)
|
|
213
|
+
]);
|
|
214
|
+
sections.push(memorySection);
|
|
215
|
+
|
|
216
|
+
// 5. Export section
|
|
217
|
+
const exportSectionNames = ['init', 'step', 'get_state_ptr', 'get_state_size'];
|
|
218
|
+
const exportSectionContent = Buffer.concat([
|
|
219
|
+
// Export 0: init
|
|
220
|
+
concatBuffers([writeUleb128Bytes((exportSectionNames[0] as string).length)]),
|
|
221
|
+
Buffer.from(exportSectionNames[0] as string, 'utf-8'),
|
|
222
|
+
Buffer.from([0x00]), // export kind: function
|
|
223
|
+
Buffer.from([0x00]), // func index
|
|
224
|
+
// Export 1: step
|
|
225
|
+
concatBuffers([writeUleb128Bytes((exportSectionNames[1] as string).length)]),
|
|
226
|
+
Buffer.from(exportSectionNames[1] as string, 'utf-8'),
|
|
227
|
+
Buffer.from([0x00]),
|
|
228
|
+
Buffer.from([0x01]),
|
|
229
|
+
// Export 2: get_state_ptr
|
|
230
|
+
concatBuffers([writeUleb128Bytes((exportSectionNames[2] as string).length)]),
|
|
231
|
+
Buffer.from(exportSectionNames[2] as string, 'utf-8'),
|
|
232
|
+
Buffer.from([0x00]),
|
|
233
|
+
Buffer.from([0x02]),
|
|
234
|
+
// Export 3: get_state_size
|
|
235
|
+
concatBuffers([writeUleb128Bytes((exportSectionNames[3] as string).length)]),
|
|
236
|
+
Buffer.from(exportSectionNames[3] as string, 'utf-8'),
|
|
237
|
+
Buffer.from([0x00]),
|
|
238
|
+
Buffer.from([0x03]),
|
|
239
|
+
]);
|
|
240
|
+
|
|
241
|
+
const exportSection = concatBuffers([
|
|
242
|
+
Buffer.from([0x07]), // section id: export
|
|
243
|
+
concatBuffers([writeUleb128Bytes(exportSectionContent.length)]),
|
|
244
|
+
concatBuffers([writeUleb128Bytes(4)]), // 4 exports
|
|
245
|
+
exportSectionContent,
|
|
246
|
+
]);
|
|
247
|
+
sections.push(exportSection);
|
|
248
|
+
|
|
249
|
+
// 6. Code section with function bodies
|
|
250
|
+
// Function 0: init - returns success (0)
|
|
251
|
+
const funcBody0 = Buffer.concat([
|
|
252
|
+
Buffer.from([0x0b, 0x01]), // func body size
|
|
253
|
+
Buffer.from([0x00, 0x41, 0x00, 0x0b]), // i32.const 0; return
|
|
254
|
+
]);
|
|
255
|
+
|
|
256
|
+
// Function 1: step - returns input
|
|
257
|
+
const funcBody1 = Buffer.concat([
|
|
258
|
+
Buffer.from([0x0b, 0x02]), // func body size
|
|
259
|
+
Buffer.from([0x20, 0x00, 0x0b]), // local.get 0; return
|
|
260
|
+
]);
|
|
261
|
+
|
|
262
|
+
// Function 2: get_state_ptr - returns 0 (memory offset)
|
|
263
|
+
const funcBody2 = Buffer.concat([
|
|
264
|
+
Buffer.from([0x0b, 0x01]), // func body size
|
|
265
|
+
Buffer.from([0x41, 0x00, 0x0b]), // i32.const 0; return
|
|
266
|
+
]);
|
|
267
|
+
|
|
268
|
+
// Function 3: get_state_size - returns js bundle size
|
|
269
|
+
const funcBody3 = Buffer.concat([
|
|
270
|
+
Buffer.from([0x0b, 0x06]), // func body size
|
|
271
|
+
Buffer.from([0x41]), // i32.const
|
|
272
|
+
concatBuffers([writeUleb128Bytes(jsBytes.length)]),
|
|
273
|
+
Buffer.from([0x0b]), // return
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
const codeSectionContent = Buffer.concat([
|
|
277
|
+
concatBuffers([writeUleb128Bytes(funcBody0.length)]),
|
|
278
|
+
funcBody0,
|
|
279
|
+
concatBuffers([writeUleb128Bytes(funcBody1.length)]),
|
|
280
|
+
funcBody1,
|
|
281
|
+
concatBuffers([writeUleb128Bytes(funcBody2.length)]),
|
|
282
|
+
funcBody2,
|
|
283
|
+
concatBuffers([writeUleb128Bytes(funcBody3.length)]),
|
|
284
|
+
funcBody3,
|
|
285
|
+
]);
|
|
286
|
+
|
|
287
|
+
const codeSection = concatBuffers([
|
|
288
|
+
Buffer.from([0x0a]), // section id: code
|
|
289
|
+
concatBuffers([writeUleb128Bytes(codeSectionContent.length)]),
|
|
290
|
+
concatBuffers([writeUleb128Bytes(4)]), // 4 function bodies
|
|
291
|
+
codeSectionContent,
|
|
292
|
+
]);
|
|
293
|
+
sections.push(codeSection);
|
|
294
|
+
|
|
295
|
+
// 7. Data section with embedded JavaScript
|
|
296
|
+
const dataSectionContent = Buffer.concat([
|
|
297
|
+
Buffer.from([0x00, 0x41, 0x00, 0x0b]), // memory 0, i32.const 0
|
|
298
|
+
concatBuffers([writeUleb128Bytes(jsBytes.length)]),
|
|
299
|
+
jsBytes,
|
|
300
|
+
]);
|
|
301
|
+
|
|
302
|
+
const dataSection = concatBuffers([
|
|
303
|
+
Buffer.from([0x0b]), // section id: data
|
|
304
|
+
concatBuffers([writeUleb128Bytes(dataSectionContent.length)]),
|
|
305
|
+
Buffer.from([0x01]), // 1 data segment
|
|
306
|
+
dataSectionContent,
|
|
307
|
+
]);
|
|
308
|
+
sections.push(dataSection);
|
|
309
|
+
|
|
310
|
+
// Combine all sections into final WASM
|
|
311
|
+
const wasmBuffer = Buffer.concat([WASM_MAGIC, WASM_VERSION, ...sections]);
|
|
312
|
+
|
|
313
|
+
return wasmBuffer;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Generate WAT (WebAssembly Text Format) representation
|
|
318
|
+
*
|
|
319
|
+
* Creates a human-readable text representation of the WASM module.
|
|
320
|
+
*/
|
|
321
|
+
export function generateStubWat(config: AgentConfig): string {
|
|
322
|
+
return `;;
|
|
323
|
+
;; AgentVault WASM Module (Stub)
|
|
324
|
+
;; Agent: ${config.name}
|
|
325
|
+
;; Type: ${config.type}
|
|
326
|
+
;; Generated: ${new Date().toISOString()}
|
|
327
|
+
;;
|
|
328
|
+
;; This is a placeholder WAT file. In production, this would contain
|
|
329
|
+
;; the actual compiled WebAssembly code for the agent.
|
|
330
|
+
;;
|
|
331
|
+
|
|
332
|
+
(module
|
|
333
|
+
;; Custom section for agent metadata
|
|
334
|
+
(@custom "agentvault" "${config.name}")
|
|
335
|
+
|
|
336
|
+
;; Memory for agent state (1 page = 64KB)
|
|
337
|
+
(memory (export "memory") 1)
|
|
338
|
+
|
|
339
|
+
;; Agent initialization function (stub)
|
|
340
|
+
(func (export "init") (result i32)
|
|
341
|
+
;; Return success code
|
|
342
|
+
i32.const 0
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
;; Agent step function (stub)
|
|
346
|
+
(func (export "step") (param $input i32) (result i32)
|
|
347
|
+
;; Return input unchanged
|
|
348
|
+
local.get $input
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
;; Get agent state pointer (stub)
|
|
352
|
+
(func (export "get_state_ptr") (result i32)
|
|
353
|
+
;; Return memory offset 0
|
|
354
|
+
i32.const 0
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
;; Get agent state size (stub)
|
|
358
|
+
(func (export "get_state_size") (result i32)
|
|
359
|
+
;; Return 0 bytes (empty state)
|
|
360
|
+
i32.const 0
|
|
361
|
+
)
|
|
362
|
+
)
|
|
363
|
+
`;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Generate serialized state JSON
|
|
368
|
+
*
|
|
369
|
+
* Creates the initial state representation for the agent.
|
|
370
|
+
*/
|
|
371
|
+
export function generateStateJson(config: AgentConfig): string {
|
|
372
|
+
const state = {
|
|
373
|
+
$schema: 'https://agentvault.dev/schemas/agent-state-v1.json',
|
|
374
|
+
agent: {
|
|
375
|
+
name: config.name,
|
|
376
|
+
type: config.type,
|
|
377
|
+
version: config.version ?? '1.0.0',
|
|
378
|
+
},
|
|
379
|
+
metadata: {
|
|
380
|
+
createdAt: new Date().toISOString(),
|
|
381
|
+
sourcePath: config.sourcePath,
|
|
382
|
+
entryPoint: config.entryPoint,
|
|
383
|
+
},
|
|
384
|
+
state: {
|
|
385
|
+
// Initial empty state
|
|
386
|
+
initialized: false,
|
|
387
|
+
data: {},
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
return JSON.stringify(state, null, 2);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Generate WAT (WebAssembly Text Format) representation
|
|
396
|
+
*
|
|
397
|
+
* Creates a human-readable text representation of the compiled WASM module.
|
|
398
|
+
*/
|
|
399
|
+
export function generateWat(config: AgentConfig, javascriptBundle: string): string {
|
|
400
|
+
const jsSize = Buffer.from(javascriptBundle, 'utf-8').length;
|
|
401
|
+
|
|
402
|
+
return `;;
|
|
403
|
+
;; AgentVault WASM Module
|
|
404
|
+
;; Agent: ${config.name}
|
|
405
|
+
;; Type: ${config.type}
|
|
406
|
+
;; Version: ${config.version ?? '1.0.0'}
|
|
407
|
+
;; Generated: ${new Date().toISOString()}
|
|
408
|
+
;;
|
|
409
|
+
;; This module contains the agent's compiled WebAssembly code
|
|
410
|
+
;; with embedded JavaScript bundle in the data section.
|
|
411
|
+
;;
|
|
412
|
+
|
|
413
|
+
(module
|
|
414
|
+
;; Metadata custom section
|
|
415
|
+
(@custom "agent.metadata" "${config.name}")
|
|
416
|
+
|
|
417
|
+
;; Memory for agent state and JavaScript bundle (1 page = 64KB)
|
|
418
|
+
(memory (export "memory") 1)
|
|
419
|
+
|
|
420
|
+
;; Agent initialization function
|
|
421
|
+
;; Returns 0 on success
|
|
422
|
+
(func (export "init") (result i32)
|
|
423
|
+
i32.const 0
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
;; Agent step function
|
|
427
|
+
;; Executes agent logic with input
|
|
428
|
+
(func (export "step") (param $input i32) (result i32)
|
|
429
|
+
local.get $input
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
;; Get agent state pointer
|
|
433
|
+
;; Returns memory offset where state is stored
|
|
434
|
+
(func (export "get_state_ptr") (result i32)
|
|
435
|
+
i32.const 0
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
;; Get agent state size
|
|
439
|
+
;; Returns size of embedded JavaScript bundle
|
|
440
|
+
(func (export "get_state_size") (result i32)
|
|
441
|
+
i32.const ${jsSize}
|
|
442
|
+
)
|
|
443
|
+
)
|
|
444
|
+
`;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Compile an agent to WASM using WasmEdge
|
|
449
|
+
*
|
|
450
|
+
* This is the main compilation function that orchestrates the packaging process.
|
|
451
|
+
* It bundles agent code and creates a WASM module with embedded JavaScript.
|
|
452
|
+
*
|
|
453
|
+
* @param config - Agent configuration from detection
|
|
454
|
+
* @param options - Packaging options including compilation target
|
|
455
|
+
* @param outputDir - Directory to write output files
|
|
456
|
+
* @returns Package result with paths to generated files
|
|
457
|
+
*/
|
|
458
|
+
export async function compileToWasm(
|
|
459
|
+
config: AgentConfig,
|
|
460
|
+
options: PackageOptions,
|
|
461
|
+
outputDir: string
|
|
462
|
+
): Promise<PackageResult> {
|
|
463
|
+
const startTime = Date.now();
|
|
464
|
+
const target = options.target ?? 'wasmedge';
|
|
465
|
+
|
|
466
|
+
// Ensure output directory exists
|
|
467
|
+
if (!fs.existsSync(outputDir)) {
|
|
468
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Generate file paths
|
|
472
|
+
const wasmPath = path.join(outputDir, `${config.name}.wasm`);
|
|
473
|
+
const watPath = path.join(outputDir, `${config.name}.wat`);
|
|
474
|
+
const statePath = path.join(outputDir, `${config.name}.state.json`);
|
|
475
|
+
const jsBundlePath = path.join(outputDir, `${config.name}.bundle.js`);
|
|
476
|
+
const manifestPath = path.join(outputDir, `${config.name}.manifest.json`);
|
|
477
|
+
const sourceMapPath = path.join(outputDir, `${config.name}.wasm.map`);
|
|
478
|
+
|
|
479
|
+
// Bundle agent code
|
|
480
|
+
const agentCode = await bundleAgentCode(config);
|
|
481
|
+
|
|
482
|
+
let wasmBuffer: Buffer;
|
|
483
|
+
let watContent: string;
|
|
484
|
+
|
|
485
|
+
// Compile based on target
|
|
486
|
+
if (target === 'wasmedge') {
|
|
487
|
+
// Use WasmEdge wrapper for full JS support
|
|
488
|
+
const wasmedgeWrapper = generateWasmEdgeWrapper(agentCode, config);
|
|
489
|
+
const wasmedgeOptions: WasmEdgeOptions = {
|
|
490
|
+
debug: options.debug ?? DEFAULT_WASMEDGE_OPTIONS.debug,
|
|
491
|
+
sourcemap: options.debug ?? DEFAULT_WASMEDGE_OPTIONS.sourcemap,
|
|
492
|
+
optimize: options.optimize ?? DEFAULT_WASMEDGE_OPTIONS.optimize,
|
|
493
|
+
wasi: DEFAULT_WASMEDGE_OPTIONS.wasi,
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
// Generate WAT for WasmEdge
|
|
497
|
+
watContent = generateWat(config, wasmedgeWrapper);
|
|
498
|
+
|
|
499
|
+
// Generate WASM (using existing WASM structure as base)
|
|
500
|
+
wasmBuffer = generateWasm(config, wasmedgeWrapper);
|
|
501
|
+
|
|
502
|
+
// Write WasmEdge wrapper
|
|
503
|
+
fs.writeFileSync(jsBundlePath, wasmedgeWrapper, 'utf-8');
|
|
504
|
+
|
|
505
|
+
// Write WasmEdge config
|
|
506
|
+
const wasmedgeConfig = generateWasmEdgeConfig(config, wasmedgeOptions);
|
|
507
|
+
const wasmedgeConfigPath = path.join(outputDir, `${config.name}.wasmedge.json`);
|
|
508
|
+
fs.writeFileSync(wasmedgeConfigPath, wasmedgeConfig, 'utf-8');
|
|
509
|
+
|
|
510
|
+
// Write manifest
|
|
511
|
+
const manifest = generateWasmEdgeManifest(config, wasmPath, outputDir);
|
|
512
|
+
fs.writeFileSync(manifestPath, manifest, 'utf-8');
|
|
513
|
+
|
|
514
|
+
} else if (target === 'motoko') {
|
|
515
|
+
// For Motoko target, generate basic WASM structure
|
|
516
|
+
// The actual compilation happens in dfx with Motoko compiler
|
|
517
|
+
watContent = generateWat(config, agentCode);
|
|
518
|
+
wasmBuffer = generateWasm(config, agentCode);
|
|
519
|
+
} else {
|
|
520
|
+
// Pure WASM target - minimal structure
|
|
521
|
+
watContent = generateWat(config, agentCode);
|
|
522
|
+
wasmBuffer = generateWasm(config, agentCode);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Generate state JSON
|
|
526
|
+
const stateContent = generateStateJson(config);
|
|
527
|
+
|
|
528
|
+
// Write files
|
|
529
|
+
fs.writeFileSync(wasmPath, wasmBuffer);
|
|
530
|
+
fs.writeFileSync(watPath, watContent, 'utf-8');
|
|
531
|
+
fs.writeFileSync(statePath, stateContent, 'utf-8');
|
|
532
|
+
|
|
533
|
+
// ── ic-wasm optimization pipeline ──────────────────────────────────────
|
|
534
|
+
const shouldOptimize = options.icWasmOptimize || options.icWasmShrink ||
|
|
535
|
+
options.candidInterface || options.memoryLimit || options.computeQuota;
|
|
536
|
+
|
|
537
|
+
let finalWasmSize = wasmBuffer.length;
|
|
538
|
+
let originalWasmSize: number | undefined;
|
|
539
|
+
let optimizationReductionPercent: number | undefined;
|
|
540
|
+
let candidValidationPassed: boolean | undefined;
|
|
541
|
+
let optimizationWarnings: string[] | undefined;
|
|
542
|
+
|
|
543
|
+
if (shouldOptimize) {
|
|
544
|
+
originalWasmSize = wasmBuffer.length;
|
|
545
|
+
|
|
546
|
+
// Map numeric optimize level (0-3) to IcWasmOptLevel
|
|
547
|
+
const levelMap: Record<number, IcWasmOptLevel> = {
|
|
548
|
+
0: 'O0', 1: 'O1', 2: 'O2', 3: 'O3',
|
|
549
|
+
};
|
|
550
|
+
const optimizeLevel = levelMap[options.optimize ?? 3] ?? 'O3';
|
|
551
|
+
|
|
552
|
+
// Build resource limits map
|
|
553
|
+
const resourceLimits: Record<string, string> = {};
|
|
554
|
+
if (options.memoryLimit) {
|
|
555
|
+
resourceLimits['memory'] = options.memoryLimit;
|
|
556
|
+
}
|
|
557
|
+
if (options.computeQuota) {
|
|
558
|
+
resourceLimits['compute'] = options.computeQuota;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const optimizedPath = path.join(outputDir, `${config.name}.optimized.wasm`);
|
|
562
|
+
|
|
563
|
+
const pipelineResult = await runOptimizationPipeline({
|
|
564
|
+
input: wasmPath,
|
|
565
|
+
output: optimizedPath,
|
|
566
|
+
optimize: options.icWasmOptimize,
|
|
567
|
+
optimizeLevel,
|
|
568
|
+
shrink: options.icWasmShrink,
|
|
569
|
+
resourceLimits: Object.keys(resourceLimits).length > 0 ? resourceLimits : undefined,
|
|
570
|
+
candidInterface: options.candidInterface,
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
optimizationWarnings = pipelineResult.warnings;
|
|
574
|
+
candidValidationPassed = pipelineResult.validationPassed;
|
|
575
|
+
|
|
576
|
+
if (pipelineResult.success && fs.existsSync(optimizedPath)) {
|
|
577
|
+
// Replace the original WASM with the optimized version
|
|
578
|
+
fs.copyFileSync(optimizedPath, wasmPath);
|
|
579
|
+
fs.unlinkSync(optimizedPath);
|
|
580
|
+
finalWasmSize = pipelineResult.finalSize;
|
|
581
|
+
optimizationReductionPercent = pipelineResult.reductionPercent;
|
|
582
|
+
} else {
|
|
583
|
+
// Optimization failed but original WASM is still valid
|
|
584
|
+
optimizationWarnings = [
|
|
585
|
+
...(optimizationWarnings ?? []),
|
|
586
|
+
'Optimization pipeline did not fully succeed; using unoptimized WASM',
|
|
587
|
+
];
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const result: PackageResult = {
|
|
592
|
+
config,
|
|
593
|
+
wasmPath,
|
|
594
|
+
watPath,
|
|
595
|
+
statePath,
|
|
596
|
+
jsBundlePath,
|
|
597
|
+
sourceMapPath: options.debug ? sourceMapPath : undefined,
|
|
598
|
+
manifestPath,
|
|
599
|
+
wasmSize: finalWasmSize,
|
|
600
|
+
target,
|
|
601
|
+
timestamp: new Date(),
|
|
602
|
+
duration: Date.now() - startTime,
|
|
603
|
+
functionCount: 14, // Standard agent interface exports
|
|
604
|
+
originalWasmSize,
|
|
605
|
+
optimizationReductionPercent,
|
|
606
|
+
candidValidationPassed,
|
|
607
|
+
optimizationWarnings,
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// Validate generated WASM
|
|
611
|
+
const validation = validateWasmEdgeModule(wasmBuffer);
|
|
612
|
+
if (!validation.valid) {
|
|
613
|
+
console.warn(`WASM validation warnings: ${validation.errors.join(', ')}`);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
return result;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Validate WASM file integrity
|
|
621
|
+
*
|
|
622
|
+
* Checks that a file has valid WASM magic bytes.
|
|
623
|
+
*/
|
|
624
|
+
export function validateWasmFile(filePath: string): boolean {
|
|
625
|
+
try {
|
|
626
|
+
const buffer = fs.readFileSync(filePath);
|
|
627
|
+
|
|
628
|
+
// Check minimum size
|
|
629
|
+
if (buffer.length < 8) {
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Check magic bytes
|
|
634
|
+
if (!buffer.subarray(0, 4).equals(WASM_MAGIC)) {
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Check version
|
|
639
|
+
if (!buffer.subarray(4, 8).equals(WASM_VERSION)) {
|
|
640
|
+
return false;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
return true;
|
|
644
|
+
} catch {
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
}
|