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.
Files changed (188) hide show
  1. package/.dfx/local/network-id +4 -0
  2. package/.next/trace +2 -0
  3. package/.vercel/README.txt +11 -0
  4. package/.vercel/project.json +1 -0
  5. package/AGENTS.md +43 -0
  6. package/CHANGELOG.md +196 -0
  7. package/LICENSE +21 -0
  8. package/PLAN_VAULT_INTEGRATION.md +318 -0
  9. package/README.md +253 -0
  10. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +28 -0
  11. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +1 -0
  12. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +28 -0
  13. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +1 -0
  14. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +28 -0
  15. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +1 -0
  16. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +28 -0
  17. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +1 -0
  18. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +1 -0
  19. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +28 -0
  20. package/backups/test-backup.json +28 -0
  21. package/dist/cli/commands/approve.d.ts +4 -0
  22. package/dist/cli/commands/approve.js +232 -0
  23. package/dist/cli/commands/archive.d.ts +4 -0
  24. package/dist/cli/commands/archive.js +192 -0
  25. package/dist/cli/commands/backup.d.ts +4 -0
  26. package/dist/cli/commands/backup.js +164 -0
  27. package/dist/cli/commands/cloud-backup.d.ts +4 -0
  28. package/dist/cli/commands/cloud-backup.js +221 -0
  29. package/dist/cli/commands/cycles.d.ts +8 -0
  30. package/dist/cli/commands/cycles.js +83 -0
  31. package/dist/cli/commands/decrypt.d.ts +16 -0
  32. package/dist/cli/commands/decrypt.js +101 -0
  33. package/dist/cli/commands/deploy.d.ts +32 -0
  34. package/dist/cli/commands/deploy.js +208 -0
  35. package/dist/cli/commands/exec.d.ts +26 -0
  36. package/dist/cli/commands/exec.js +109 -0
  37. package/dist/cli/commands/fetch.d.ts +23 -0
  38. package/dist/cli/commands/fetch.js +164 -0
  39. package/dist/cli/commands/health.d.ts +8 -0
  40. package/dist/cli/commands/health.js +72 -0
  41. package/dist/cli/commands/identity.d.ts +8 -0
  42. package/dist/cli/commands/identity.js +140 -0
  43. package/dist/cli/commands/inference.d.ts +4 -0
  44. package/dist/cli/commands/inference.js +225 -0
  45. package/dist/cli/commands/info.d.ts +8 -0
  46. package/dist/cli/commands/info.js +59 -0
  47. package/dist/cli/commands/init.d.ts +19 -0
  48. package/dist/cli/commands/init.js +135 -0
  49. package/dist/cli/commands/instrument.d.ts +8 -0
  50. package/dist/cli/commands/instrument.js +35 -0
  51. package/dist/cli/commands/list.d.ts +36 -0
  52. package/dist/cli/commands/list.js +173 -0
  53. package/dist/cli/commands/logs.d.ts +8 -0
  54. package/dist/cli/commands/logs.js +96 -0
  55. package/dist/cli/commands/monitor.d.ts +8 -0
  56. package/dist/cli/commands/monitor.js +84 -0
  57. package/dist/cli/commands/network.d.ts +14 -0
  58. package/dist/cli/commands/network.js +258 -0
  59. package/dist/cli/commands/package.d.ts +36 -0
  60. package/dist/cli/commands/package.js +188 -0
  61. package/dist/cli/commands/profile.d.ts +8 -0
  62. package/dist/cli/commands/profile.js +76 -0
  63. package/dist/cli/commands/promote.d.ts +8 -0
  64. package/dist/cli/commands/promote.js +89 -0
  65. package/dist/cli/commands/rebuild.d.ts +21 -0
  66. package/dist/cli/commands/rebuild.js +140 -0
  67. package/dist/cli/commands/rollback.d.ts +8 -0
  68. package/dist/cli/commands/rollback.js +120 -0
  69. package/dist/cli/commands/show.d.ts +36 -0
  70. package/dist/cli/commands/show.js +200 -0
  71. package/dist/cli/commands/stats.d.ts +8 -0
  72. package/dist/cli/commands/stats.js +34 -0
  73. package/dist/cli/commands/status.d.ts +14 -0
  74. package/dist/cli/commands/status.js +83 -0
  75. package/dist/cli/commands/test.d.ts +8 -0
  76. package/dist/cli/commands/test.js +109 -0
  77. package/dist/cli/commands/tokens.d.ts +8 -0
  78. package/dist/cli/commands/tokens.js +62 -0
  79. package/dist/cli/commands/trace.d.ts +8 -0
  80. package/dist/cli/commands/trace.js +68 -0
  81. package/dist/cli/commands/wallet-export.d.ts +13 -0
  82. package/dist/cli/commands/wallet-export.js +140 -0
  83. package/dist/cli/commands/wallet-history.d.ts +10 -0
  84. package/dist/cli/commands/wallet-history.js +127 -0
  85. package/dist/cli/commands/wallet-import.d.ts +10 -0
  86. package/dist/cli/commands/wallet-import.js +209 -0
  87. package/dist/cli/commands/wallet-multi-send.d.ts +17 -0
  88. package/dist/cli/commands/wallet-multi-send.js +195 -0
  89. package/dist/cli/commands/wallet-process-queue.d.ts +19 -0
  90. package/dist/cli/commands/wallet-process-queue.js +209 -0
  91. package/dist/cli/commands/wallet-sign.d.ts +13 -0
  92. package/dist/cli/commands/wallet-sign.js +207 -0
  93. package/dist/cli/commands/wallet.d.ts +12 -0
  94. package/dist/cli/commands/wallet.js +794 -0
  95. package/dist/cli/index.d.ts +10 -0
  96. package/dist/cli/index.js +96 -0
  97. package/dist/vitest.config.d.ts +3 -0
  98. package/dist/vitest.config.js +14 -0
  99. package/fixup_1_0_OSS_release.md +136 -0
  100. package/fixup_REALEASE_PRD.md +136 -0
  101. package/package.json +79 -0
  102. package/pnpm-workspace.yaml +5 -0
  103. package/scripts/dev-dashboard.mjs +84 -0
  104. package/site/README.md +63 -0
  105. package/site/docusaurus.config.ts +148 -0
  106. package/site/package-lock.json +18383 -0
  107. package/site/package.json +47 -0
  108. package/site/sidebars.ts +86 -0
  109. package/site/static/.gitkeep +0 -0
  110. package/site/static/img/logo.svg +28 -0
  111. package/site/static/img/og-image.svg +35 -0
  112. package/src/archival/archive-manager.ts +372 -0
  113. package/src/archival/arweave-client.ts +289 -0
  114. package/src/archival/index.ts +8 -0
  115. package/src/backup/backup.ts +315 -0
  116. package/src/backup/index.ts +7 -0
  117. package/src/cloud-storage/cloud-sync.ts +461 -0
  118. package/src/cloud-storage/index.ts +11 -0
  119. package/src/cloud-storage/provider-detector.ts +198 -0
  120. package/src/cloud-storage/types.ts +104 -0
  121. package/src/debugging/index.ts +6 -0
  122. package/src/debugging/logs.ts +193 -0
  123. package/src/debugging/types.ts +100 -0
  124. package/src/deployment/deployer.ts +274 -0
  125. package/src/deployment/icpClient.ts +620 -0
  126. package/src/deployment/index.ts +46 -0
  127. package/src/deployment/promotion.ts +161 -0
  128. package/src/deployment/types.ts +111 -0
  129. package/src/icp/batch.ts +374 -0
  130. package/src/icp/cycles.ts +50 -0
  131. package/src/icp/environment.ts +215 -0
  132. package/src/icp/icpcli.ts +438 -0
  133. package/src/icp/icwasm.ts +222 -0
  134. package/src/icp/identity.ts +77 -0
  135. package/src/icp/index.ts +94 -0
  136. package/src/icp/optimization.ts +242 -0
  137. package/src/icp/tokens.ts +36 -0
  138. package/src/icp/tool-detector.ts +110 -0
  139. package/src/icp/types.ts +574 -0
  140. package/src/index.ts +25 -0
  141. package/src/inference/bittensor-client.ts +304 -0
  142. package/src/inference/index.ts +8 -0
  143. package/src/inference/inference-manager.ts +327 -0
  144. package/src/metrics/index.ts +7 -0
  145. package/src/metrics/metrics.ts +186 -0
  146. package/src/monitoring/alerting.ts +190 -0
  147. package/src/monitoring/health.ts +197 -0
  148. package/src/monitoring/index.ts +38 -0
  149. package/src/monitoring/info.ts +114 -0
  150. package/src/monitoring/types.ts +99 -0
  151. package/src/network/index.ts +5 -0
  152. package/src/network/network-config.ts +129 -0
  153. package/src/packaging/compiler.ts +647 -0
  154. package/src/packaging/config-persistence.ts +135 -0
  155. package/src/packaging/config-schemas.ts +156 -0
  156. package/src/packaging/detector.ts +220 -0
  157. package/src/packaging/index.ts +90 -0
  158. package/src/packaging/packager.ts +118 -0
  159. package/src/packaging/parsers/clawdbot.ts +278 -0
  160. package/src/packaging/parsers/cline.ts +223 -0
  161. package/src/packaging/parsers/generic.ts +266 -0
  162. package/src/packaging/parsers/goose.ts +214 -0
  163. package/src/packaging/parsers/index.ts +11 -0
  164. package/src/packaging/serializer.ts +260 -0
  165. package/src/packaging/types.ts +144 -0
  166. package/src/packaging/wasmedge-compiler.ts +406 -0
  167. package/src/security/index.ts +17 -0
  168. package/src/security/multisig.ts +415 -0
  169. package/src/security/types.ts +416 -0
  170. package/src/security/vetkeys.ts +655 -0
  171. package/src/testing/index.ts +6 -0
  172. package/src/testing/local-runner.ts +264 -0
  173. package/src/testing/types.ts +104 -0
  174. package/src/wallet/cbor-serializer.ts +323 -0
  175. package/src/wallet/chain-dispatcher.ts +313 -0
  176. package/src/wallet/cross-chain-aggregator.ts +346 -0
  177. package/src/wallet/index.ts +76 -0
  178. package/src/wallet/key-derivation.ts +425 -0
  179. package/src/wallet/providers/base-provider.ts +154 -0
  180. package/src/wallet/providers/cketh-provider.ts +434 -0
  181. package/src/wallet/providers/polkadot-provider.ts +503 -0
  182. package/src/wallet/providers/solana-provider.ts +490 -0
  183. package/src/wallet/transaction-queue.ts +284 -0
  184. package/src/wallet/types.ts +178 -0
  185. package/src/wallet/vetkeys-adapter.ts +431 -0
  186. package/src/wallet/wallet-manager.ts +597 -0
  187. package/src/wallet/wallet-storage.ts +380 -0
  188. 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
+ }