silo-agent 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/README.md +330 -0
- package/bin/silo.js +55 -0
- package/build/demo.d.ts +13 -0
- package/build/demo.js +91 -0
- package/build/demo.js.map +1 -0
- package/build/doctor.d.ts +13 -0
- package/build/doctor.js +108 -0
- package/build/doctor.js.map +1 -0
- package/build/index.d.ts +16 -0
- package/build/index.js +17 -0
- package/build/index.js.map +1 -0
- package/build/lib/agent-router.d.ts +110 -0
- package/build/lib/agent-router.js +197 -0
- package/build/lib/agent-router.js.map +1 -0
- package/build/lib/attestation.d.ts +64 -0
- package/build/lib/attestation.js +112 -0
- package/build/lib/attestation.js.map +1 -0
- package/build/lib/autonomy.d.ts +116 -0
- package/build/lib/autonomy.js +266 -0
- package/build/lib/autonomy.js.map +1 -0
- package/build/lib/crypto.d.ts +33 -0
- package/build/lib/crypto.js +63 -0
- package/build/lib/crypto.js.map +1 -0
- package/build/lib/heartbeat.d.ts +111 -0
- package/build/lib/heartbeat.js +256 -0
- package/build/lib/heartbeat.js.map +1 -0
- package/build/lib/memory-coordinator.d.ts +150 -0
- package/build/lib/memory-coordinator.js +249 -0
- package/build/lib/memory-coordinator.js.map +1 -0
- package/build/lib/memory-index.d.ts +83 -0
- package/build/lib/memory-index.js +209 -0
- package/build/lib/memory-index.js.map +1 -0
- package/build/lib/shared-memory.d.ts +165 -0
- package/build/lib/shared-memory.js +398 -0
- package/build/lib/shared-memory.js.map +1 -0
- package/build/lib/storage.d.ts +38 -0
- package/build/lib/storage.js +106 -0
- package/build/lib/storage.js.map +1 -0
- package/build/lib/vault.d.ts +71 -0
- package/build/lib/vault.js +119 -0
- package/build/lib/vault.js.map +1 -0
- package/build/mcp.d.ts +32 -0
- package/build/mcp.js +734 -0
- package/build/mcp.js.map +1 -0
- package/build/server.d.ts +1 -0
- package/build/server.js +370 -0
- package/build/server.js.map +1 -0
- package/build/tests/attestation.test.d.ts +1 -0
- package/build/tests/attestation.test.js +175 -0
- package/build/tests/attestation.test.js.map +1 -0
- package/build/tests/crypto.test.d.ts +1 -0
- package/build/tests/crypto.test.js +109 -0
- package/build/tests/crypto.test.js.map +1 -0
- package/build/verify-flow.d.ts +10 -0
- package/build/verify-flow.js +81 -0
- package/build/verify-flow.js.map +1 -0
- package/build/verify.d.ts +14 -0
- package/build/verify.js +77 -0
- package/build/verify.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SILO — Shared Memory Bus
|
|
3
|
+
*
|
|
4
|
+
* Named channels backed by 0G Storage for real-time multi-agent communication.
|
|
5
|
+
*
|
|
6
|
+
* Design:
|
|
7
|
+
* - Each channel is a linked list of entries on 0G (each entry points to the previous via rootHash)
|
|
8
|
+
* - A coordinator layer provides channel locks and optimistic concurrency control
|
|
9
|
+
* - A memory index provides root hash discoverability (search by label, tag, channel, author)
|
|
10
|
+
* - Periodic snapshots persist the full channel state to 0G for crash recovery
|
|
11
|
+
* - Any agent can create, join, write to, or read from a channel
|
|
12
|
+
*
|
|
13
|
+
* Safe Write Protocol (when coordinator is attached):
|
|
14
|
+
* 1. acquireLock(channel) → lockToken
|
|
15
|
+
* 2. Read current head → {headRootHash, version}
|
|
16
|
+
* 3. Upload to 0G with prevRootHash = headRootHash
|
|
17
|
+
* 4. commitWrite(channel, newRootHash, version, lockToken)
|
|
18
|
+
* 5. Coordinator validates → updates head → releases lock → broadcasts
|
|
19
|
+
*
|
|
20
|
+
* Without coordinator, writes are best-effort (backward compatible with v1).
|
|
21
|
+
*/
|
|
22
|
+
import { MemoryIndex } from "./memory-index.js";
|
|
23
|
+
import { createHash } from "node:crypto";
|
|
24
|
+
const DEFAULT_CONFIG = {
|
|
25
|
+
snapshotThreshold: 10,
|
|
26
|
+
useCoordinator: true,
|
|
27
|
+
maxWriteRetries: 3,
|
|
28
|
+
};
|
|
29
|
+
export class SharedMemoryBus {
|
|
30
|
+
vault;
|
|
31
|
+
coordinator = null;
|
|
32
|
+
index;
|
|
33
|
+
channels = new Map();
|
|
34
|
+
entries = new Map();
|
|
35
|
+
subscriptions = new Map();
|
|
36
|
+
config;
|
|
37
|
+
agentId;
|
|
38
|
+
onBroadcast;
|
|
39
|
+
constructor(vault, config = {}) {
|
|
40
|
+
this.vault = vault;
|
|
41
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
42
|
+
this.agentId = vault.address;
|
|
43
|
+
this.index = new MemoryIndex();
|
|
44
|
+
}
|
|
45
|
+
/** Attach a coordinator for multi-agent safety (run on the API server) */
|
|
46
|
+
attachCoordinator(coordinator) {
|
|
47
|
+
this.coordinator = coordinator;
|
|
48
|
+
}
|
|
49
|
+
/** Get the memory index (for search, lookup, stats) */
|
|
50
|
+
getIndex() { return this.index; }
|
|
51
|
+
/** Get the coordinator (if attached) */
|
|
52
|
+
getCoordinator() { return this.coordinator; }
|
|
53
|
+
/** Register a broadcast handler (e.g., Socket.IO emitter) for cross-process notifications */
|
|
54
|
+
setBroadcastHandler(handler) {
|
|
55
|
+
this.onBroadcast = handler;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a new named channel with optional schema.
|
|
59
|
+
* If the channel already exists, returns the existing manifest.
|
|
60
|
+
*/
|
|
61
|
+
createChannel(name, schema) {
|
|
62
|
+
if (this.channels.has(name)) {
|
|
63
|
+
const existing = this.channels.get(name);
|
|
64
|
+
if (schema && !existing.schema)
|
|
65
|
+
existing.schema = schema;
|
|
66
|
+
return existing;
|
|
67
|
+
}
|
|
68
|
+
const manifest = {
|
|
69
|
+
name,
|
|
70
|
+
createdAt: Date.now(),
|
|
71
|
+
createdBy: this.agentId,
|
|
72
|
+
headRootHash: null,
|
|
73
|
+
version: 0,
|
|
74
|
+
entryCount: 0,
|
|
75
|
+
subscribers: [this.agentId],
|
|
76
|
+
snapshotRootHash: null,
|
|
77
|
+
lastSnapshotAt: null,
|
|
78
|
+
schema,
|
|
79
|
+
};
|
|
80
|
+
this.channels.set(name, manifest);
|
|
81
|
+
this.entries.set(name, []);
|
|
82
|
+
this.subscriptions.set(name, []);
|
|
83
|
+
this.coordinator?.ensureChannel(name);
|
|
84
|
+
return manifest;
|
|
85
|
+
}
|
|
86
|
+
/** Subscribe to a channel. Callback fires on every new entry. */
|
|
87
|
+
subscribe(channel, callback) {
|
|
88
|
+
if (!this.channels.has(channel)) {
|
|
89
|
+
this.createChannel(channel);
|
|
90
|
+
}
|
|
91
|
+
const manifest = this.channels.get(channel);
|
|
92
|
+
if (!manifest.subscribers.includes(this.agentId)) {
|
|
93
|
+
manifest.subscribers.push(this.agentId);
|
|
94
|
+
}
|
|
95
|
+
const subscription = {
|
|
96
|
+
channel,
|
|
97
|
+
agentId: this.agentId,
|
|
98
|
+
callback,
|
|
99
|
+
};
|
|
100
|
+
this.subscriptions.get(channel).push(subscription);
|
|
101
|
+
return subscription;
|
|
102
|
+
}
|
|
103
|
+
/** Unsubscribe from a channel */
|
|
104
|
+
unsubscribe(subscription) {
|
|
105
|
+
const subs = this.subscriptions.get(subscription.channel);
|
|
106
|
+
if (!subs)
|
|
107
|
+
return;
|
|
108
|
+
const idx = subs.indexOf(subscription);
|
|
109
|
+
if (idx !== -1)
|
|
110
|
+
subs.splice(idx, 1);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Write data to a channel with coordination.
|
|
114
|
+
*
|
|
115
|
+
* When a coordinator is attached:
|
|
116
|
+
* 1. Acquires channel lock
|
|
117
|
+
* 2. Reads current head + version
|
|
118
|
+
* 3. Uploads to 0G with correct prevRootHash
|
|
119
|
+
* 4. Commits via coordinator (validates version)
|
|
120
|
+
* 5. Retries on conflict up to maxWriteRetries
|
|
121
|
+
*
|
|
122
|
+
* Without coordinator: best-effort write (v1 behavior).
|
|
123
|
+
*/
|
|
124
|
+
async write(channel, data, metadata) {
|
|
125
|
+
if (!this.channels.has(channel)) {
|
|
126
|
+
this.createChannel(channel);
|
|
127
|
+
}
|
|
128
|
+
if (this.coordinator && this.config.useCoordinator) {
|
|
129
|
+
return this.coordinatedWrite(channel, data, metadata);
|
|
130
|
+
}
|
|
131
|
+
return this.uncoordinatedWrite(channel, data, metadata);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Safe write with full coordination — locks, version checks, conflict retry.
|
|
135
|
+
*/
|
|
136
|
+
async coordinatedWrite(channel, data, metadata) {
|
|
137
|
+
const coordinator = this.coordinator;
|
|
138
|
+
let lastError;
|
|
139
|
+
for (let attempt = 0; attempt < this.config.maxWriteRetries; attempt++) {
|
|
140
|
+
const beginResult = coordinator.beginWrite(channel, this.agentId);
|
|
141
|
+
if ("code" in beginResult) {
|
|
142
|
+
if (attempt < this.config.maxWriteRetries - 1) {
|
|
143
|
+
await sleep(100 * Math.pow(2, attempt));
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
throw new Error(`Failed to acquire lock on "${channel}": ${beginResult.message}`);
|
|
147
|
+
}
|
|
148
|
+
const { head, lock } = beginResult;
|
|
149
|
+
try {
|
|
150
|
+
const envelope = JSON.stringify({
|
|
151
|
+
channel,
|
|
152
|
+
data,
|
|
153
|
+
prevRootHash: head.headRootHash,
|
|
154
|
+
version: head.version,
|
|
155
|
+
authorId: this.agentId,
|
|
156
|
+
timestamp: Date.now(),
|
|
157
|
+
metadata,
|
|
158
|
+
});
|
|
159
|
+
const result = await this.vault.store(envelope, `shm:${channel}`);
|
|
160
|
+
const commitResult = coordinator.commitWrite(channel, result.rootHash, head.headRootHash, head.version, this.agentId, lock.token);
|
|
161
|
+
if ("code" in commitResult) {
|
|
162
|
+
lastError = new Error(commitResult.message);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const entry = {
|
|
166
|
+
id: createHash("sha256").update(`${channel}:${result.rootHash}`).digest("hex").slice(0, 16),
|
|
167
|
+
channel,
|
|
168
|
+
authorId: this.agentId,
|
|
169
|
+
timestamp: Date.now(),
|
|
170
|
+
data,
|
|
171
|
+
rootHash: result.rootHash,
|
|
172
|
+
prevRootHash: head.headRootHash,
|
|
173
|
+
contentHash: result.contentHash,
|
|
174
|
+
version: commitResult.version,
|
|
175
|
+
metadata,
|
|
176
|
+
};
|
|
177
|
+
const manifest = this.channels.get(channel);
|
|
178
|
+
manifest.headRootHash = result.rootHash;
|
|
179
|
+
manifest.version = commitResult.version;
|
|
180
|
+
manifest.entryCount++;
|
|
181
|
+
this.entries.get(channel).push(entry);
|
|
182
|
+
this.registerInIndex(entry, result);
|
|
183
|
+
this.notifySubscribers(channel, entry);
|
|
184
|
+
if (manifest.entryCount % this.config.snapshotThreshold === 0) {
|
|
185
|
+
await this.snapshot(channel);
|
|
186
|
+
}
|
|
187
|
+
return entry;
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
coordinator.releaseLock(channel, lock.token);
|
|
191
|
+
lastError = err;
|
|
192
|
+
if (attempt < this.config.maxWriteRetries - 1) {
|
|
193
|
+
await sleep(100 * Math.pow(2, attempt));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
throw lastError ?? new Error(`Coordinated write to "${channel}" failed after ${this.config.maxWriteRetries} attempts`);
|
|
198
|
+
}
|
|
199
|
+
/** Best-effort write without coordination (backward compatible) */
|
|
200
|
+
async uncoordinatedWrite(channel, data, metadata) {
|
|
201
|
+
const manifest = this.channels.get(channel);
|
|
202
|
+
const prevRootHash = manifest.headRootHash;
|
|
203
|
+
const envelope = JSON.stringify({
|
|
204
|
+
channel,
|
|
205
|
+
data,
|
|
206
|
+
prevRootHash,
|
|
207
|
+
version: manifest.version,
|
|
208
|
+
authorId: this.agentId,
|
|
209
|
+
timestamp: Date.now(),
|
|
210
|
+
metadata,
|
|
211
|
+
});
|
|
212
|
+
const result = await this.vault.store(envelope, `shm:${channel}`);
|
|
213
|
+
const entry = {
|
|
214
|
+
id: createHash("sha256").update(`${channel}:${result.rootHash}`).digest("hex").slice(0, 16),
|
|
215
|
+
channel,
|
|
216
|
+
authorId: this.agentId,
|
|
217
|
+
timestamp: Date.now(),
|
|
218
|
+
data,
|
|
219
|
+
rootHash: result.rootHash,
|
|
220
|
+
prevRootHash,
|
|
221
|
+
contentHash: result.contentHash,
|
|
222
|
+
version: ++manifest.version,
|
|
223
|
+
metadata,
|
|
224
|
+
};
|
|
225
|
+
manifest.headRootHash = result.rootHash;
|
|
226
|
+
manifest.entryCount++;
|
|
227
|
+
this.entries.get(channel).push(entry);
|
|
228
|
+
this.registerInIndex(entry, result);
|
|
229
|
+
this.notifySubscribers(channel, entry);
|
|
230
|
+
if (manifest.entryCount % this.config.snapshotThreshold === 0) {
|
|
231
|
+
await this.snapshot(channel);
|
|
232
|
+
}
|
|
233
|
+
return entry;
|
|
234
|
+
}
|
|
235
|
+
registerInIndex(entry, storeResult) {
|
|
236
|
+
const tags = [entry.channel, "shared_memory"];
|
|
237
|
+
if (entry.metadata?.tags)
|
|
238
|
+
tags.push(...entry.metadata.tags);
|
|
239
|
+
this.index.register({
|
|
240
|
+
rootHash: entry.rootHash,
|
|
241
|
+
label: entry.metadata?.label ?? `shm:${entry.channel}`,
|
|
242
|
+
tags,
|
|
243
|
+
channel: entry.channel,
|
|
244
|
+
authorId: entry.authorId,
|
|
245
|
+
contentType: "shared_memory",
|
|
246
|
+
size: storeResult.size,
|
|
247
|
+
createdAt: entry.timestamp,
|
|
248
|
+
contentHash: entry.contentHash,
|
|
249
|
+
metadata: entry.metadata,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
notifySubscribers(channel, entry) {
|
|
253
|
+
const subs = this.subscriptions.get(channel) ?? [];
|
|
254
|
+
for (const sub of subs) {
|
|
255
|
+
try {
|
|
256
|
+
sub.callback(entry);
|
|
257
|
+
}
|
|
258
|
+
catch { }
|
|
259
|
+
}
|
|
260
|
+
this.onBroadcast?.(channel, entry);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Read the latest N entries from a channel (from local cache).
|
|
264
|
+
* For full history recovery from 0G, use `recoverChannel()`.
|
|
265
|
+
*/
|
|
266
|
+
read(channel, limit = 50) {
|
|
267
|
+
const entries = this.entries.get(channel) ?? [];
|
|
268
|
+
return entries.slice(-limit);
|
|
269
|
+
}
|
|
270
|
+
/** Read a specific entry from 0G by its root hash */
|
|
271
|
+
async readFromStorage(rootHash) {
|
|
272
|
+
const raw = await this.vault.retrieve(rootHash, "shm:read");
|
|
273
|
+
const envelope = JSON.parse(raw);
|
|
274
|
+
return {
|
|
275
|
+
data: envelope.data,
|
|
276
|
+
prevRootHash: envelope.prevRootHash,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Search the memory index. Agents use this to discover root hashes
|
|
281
|
+
* without knowing them in advance.
|
|
282
|
+
*/
|
|
283
|
+
search(query) {
|
|
284
|
+
return this.index.search(query);
|
|
285
|
+
}
|
|
286
|
+
/** Look up what a specific root hash contains */
|
|
287
|
+
lookupRootHash(rootHash) {
|
|
288
|
+
return this.index.lookup(rootHash);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Persist the full channel state as a snapshot on 0G.
|
|
292
|
+
*/
|
|
293
|
+
async snapshot(channel) {
|
|
294
|
+
const manifest = this.channels.get(channel);
|
|
295
|
+
if (!manifest)
|
|
296
|
+
throw new Error(`Channel "${channel}" not found`);
|
|
297
|
+
const entries = this.entries.get(channel) ?? [];
|
|
298
|
+
const snapshotData = JSON.stringify({
|
|
299
|
+
manifest,
|
|
300
|
+
entries: entries.map(e => ({
|
|
301
|
+
id: e.id,
|
|
302
|
+
rootHash: e.rootHash,
|
|
303
|
+
prevRootHash: e.prevRootHash,
|
|
304
|
+
authorId: e.authorId,
|
|
305
|
+
timestamp: e.timestamp,
|
|
306
|
+
contentHash: e.contentHash,
|
|
307
|
+
version: e.version,
|
|
308
|
+
metadata: e.metadata,
|
|
309
|
+
})),
|
|
310
|
+
snapshotAt: Date.now(),
|
|
311
|
+
});
|
|
312
|
+
const result = await this.vault.store(snapshotData, `shm:snapshot:${channel}`);
|
|
313
|
+
manifest.snapshotRootHash = result.rootHash;
|
|
314
|
+
manifest.lastSnapshotAt = Date.now();
|
|
315
|
+
this.index.register({
|
|
316
|
+
rootHash: result.rootHash,
|
|
317
|
+
label: `snapshot:${channel}`,
|
|
318
|
+
tags: [channel, "snapshot"],
|
|
319
|
+
channel,
|
|
320
|
+
authorId: this.agentId,
|
|
321
|
+
contentType: "snapshot",
|
|
322
|
+
size: result.size,
|
|
323
|
+
createdAt: Date.now(),
|
|
324
|
+
contentHash: result.contentHash,
|
|
325
|
+
});
|
|
326
|
+
return result.rootHash;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Recover a channel by walking the linked list from a known head root hash.
|
|
330
|
+
*/
|
|
331
|
+
async recoverChannel(channel, headRootHash, maxDepth = 100) {
|
|
332
|
+
const recovered = [];
|
|
333
|
+
let currentHash = headRootHash;
|
|
334
|
+
let depth = 0;
|
|
335
|
+
while (currentHash && depth < maxDepth) {
|
|
336
|
+
const { data, prevRootHash } = await this.readFromStorage(currentHash);
|
|
337
|
+
recovered.unshift({
|
|
338
|
+
id: createHash("sha256").update(`${channel}:${currentHash}`).digest("hex").slice(0, 16),
|
|
339
|
+
channel,
|
|
340
|
+
authorId: "recovered",
|
|
341
|
+
timestamp: Date.now(),
|
|
342
|
+
data,
|
|
343
|
+
rootHash: currentHash,
|
|
344
|
+
prevRootHash,
|
|
345
|
+
contentHash: createHash("sha256").update(data).digest("hex"),
|
|
346
|
+
version: depth,
|
|
347
|
+
});
|
|
348
|
+
currentHash = prevRootHash;
|
|
349
|
+
depth++;
|
|
350
|
+
}
|
|
351
|
+
if (!this.channels.has(channel)) {
|
|
352
|
+
this.createChannel(channel);
|
|
353
|
+
}
|
|
354
|
+
this.entries.set(channel, recovered);
|
|
355
|
+
const manifest = this.channels.get(channel);
|
|
356
|
+
manifest.headRootHash = headRootHash;
|
|
357
|
+
manifest.entryCount = recovered.length;
|
|
358
|
+
manifest.version = recovered.length;
|
|
359
|
+
return recovered;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Ingest an entry from another agent (received via WebSocket broadcast).
|
|
363
|
+
* Keeps the local cache in sync without re-downloading from 0G.
|
|
364
|
+
*/
|
|
365
|
+
ingestRemoteEntry(entry) {
|
|
366
|
+
if (!this.channels.has(entry.channel)) {
|
|
367
|
+
this.createChannel(entry.channel);
|
|
368
|
+
}
|
|
369
|
+
const entries = this.entries.get(entry.channel);
|
|
370
|
+
if (entries.some(e => e.rootHash === entry.rootHash))
|
|
371
|
+
return;
|
|
372
|
+
entries.push(entry);
|
|
373
|
+
const manifest = this.channels.get(entry.channel);
|
|
374
|
+
manifest.headRootHash = entry.rootHash;
|
|
375
|
+
manifest.entryCount = entries.length;
|
|
376
|
+
if (entry.version > manifest.version)
|
|
377
|
+
manifest.version = entry.version;
|
|
378
|
+
const subs = this.subscriptions.get(entry.channel) ?? [];
|
|
379
|
+
for (const sub of subs) {
|
|
380
|
+
try {
|
|
381
|
+
sub.callback(entry);
|
|
382
|
+
}
|
|
383
|
+
catch { }
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/** List all known channels */
|
|
387
|
+
listChannels() {
|
|
388
|
+
return Array.from(this.channels.values());
|
|
389
|
+
}
|
|
390
|
+
/** Get a channel's manifest */
|
|
391
|
+
getChannel(name) {
|
|
392
|
+
return this.channels.get(name);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function sleep(ms) {
|
|
396
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=shared-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-memory.js","sourceRoot":"","sources":["../../src/lib/shared-memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0G Agent Shield — Storage Layer
|
|
3
|
+
*
|
|
4
|
+
* Wraps @0glabs/0g-ts-sdk to provide a simple string-in/string-out interface.
|
|
5
|
+
* The SDK requires file paths, so we handle temp file lifecycle internally.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT API notes (from the actual SDK docs):
|
|
8
|
+
* - indexer.upload(file, evmRpc, signer) ← evmRpc is 2nd arg, NOT signer alone
|
|
9
|
+
* - file.merkleTree() returns [tree, err] ← destructure the tuple
|
|
10
|
+
* - indexer.download(rootHash, outPath, withProof)
|
|
11
|
+
* - file.close() must be called after merkleTree()
|
|
12
|
+
*/
|
|
13
|
+
export interface UploadResult {
|
|
14
|
+
rootHash: string;
|
|
15
|
+
txHash: string;
|
|
16
|
+
size: number;
|
|
17
|
+
timestamp: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class StorageClient {
|
|
20
|
+
private indexer;
|
|
21
|
+
private signer;
|
|
22
|
+
private provider;
|
|
23
|
+
private evmRpc;
|
|
24
|
+
constructor(privateKey: string, evmRpc: string, indexerRpc: string);
|
|
25
|
+
get address(): string;
|
|
26
|
+
getBalance(): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Upload a string to 0G Storage.
|
|
29
|
+
*
|
|
30
|
+
* Flow: write temp file → create ZgFile → get merkle tree for root hash
|
|
31
|
+
* → upload via indexer → cleanup temp file
|
|
32
|
+
*/
|
|
33
|
+
upload(data: string): Promise<UploadResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Download a file from 0G Storage by its root hash.
|
|
36
|
+
*/
|
|
37
|
+
download(rootHash: string): Promise<string>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0G Agent Shield — Storage Layer
|
|
3
|
+
*
|
|
4
|
+
* Wraps @0glabs/0g-ts-sdk to provide a simple string-in/string-out interface.
|
|
5
|
+
* The SDK requires file paths, so we handle temp file lifecycle internally.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT API notes (from the actual SDK docs):
|
|
8
|
+
* - indexer.upload(file, evmRpc, signer) ← evmRpc is 2nd arg, NOT signer alone
|
|
9
|
+
* - file.merkleTree() returns [tree, err] ← destructure the tuple
|
|
10
|
+
* - indexer.download(rootHash, outPath, withProof)
|
|
11
|
+
* - file.close() must be called after merkleTree()
|
|
12
|
+
*/
|
|
13
|
+
import { Indexer, ZgFile } from "@0glabs/0g-ts-sdk";
|
|
14
|
+
import { ethers } from "ethers";
|
|
15
|
+
import * as fs from "node:fs/promises";
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
import * as os from "node:os";
|
|
18
|
+
export class StorageClient {
|
|
19
|
+
indexer;
|
|
20
|
+
signer;
|
|
21
|
+
provider;
|
|
22
|
+
evmRpc;
|
|
23
|
+
constructor(privateKey, evmRpc, indexerRpc) {
|
|
24
|
+
this.evmRpc = evmRpc;
|
|
25
|
+
this.provider = new ethers.JsonRpcProvider(evmRpc);
|
|
26
|
+
this.signer = new ethers.Wallet(privateKey, this.provider);
|
|
27
|
+
this.indexer = new Indexer(indexerRpc);
|
|
28
|
+
}
|
|
29
|
+
get address() {
|
|
30
|
+
return this.signer.address;
|
|
31
|
+
}
|
|
32
|
+
async getBalance() {
|
|
33
|
+
const balance = await this.provider.getBalance(this.signer.address);
|
|
34
|
+
return ethers.formatEther(balance);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Upload a string to 0G Storage.
|
|
38
|
+
*
|
|
39
|
+
* Flow: write temp file → create ZgFile → get merkle tree for root hash
|
|
40
|
+
* → upload via indexer → cleanup temp file
|
|
41
|
+
*/
|
|
42
|
+
async upload(data) {
|
|
43
|
+
const tmpPath = path.join(os.tmpdir(), `0g-shield-${Date.now()}-${Math.random().toString(36).slice(2)}.dat`);
|
|
44
|
+
const dataBytes = Buffer.from(data, "utf-8");
|
|
45
|
+
await fs.writeFile(tmpPath, dataBytes);
|
|
46
|
+
let file = null;
|
|
47
|
+
try {
|
|
48
|
+
file = await ZgFile.fromFilePath(tmpPath);
|
|
49
|
+
// 0G TS SDK uses the old testnet ABI, but Galileo testnet upgraded to require a submitter address.
|
|
50
|
+
// We wrap the signer in a Proxy to intercept and automatically upgrade the transaction payload.
|
|
51
|
+
const newAbi = ['function submit(tuple(tuple(uint256 length, bytes tags, tuple(bytes32 root, uint256 height)[] nodes) data, address submitter) submission) payable'];
|
|
52
|
+
const oldAbi = ['function submit(tuple(uint256 length, bytes tags, tuple(bytes32 root, uint256 height)[] nodes) submission) payable'];
|
|
53
|
+
const newIface = new ethers.Interface(newAbi);
|
|
54
|
+
const oldIface = new ethers.Interface(oldAbi);
|
|
55
|
+
const proxySigner = new Proxy(this.signer, {
|
|
56
|
+
get(target, prop) {
|
|
57
|
+
if (prop === 'sendTransaction' || prop === 'estimateGas') {
|
|
58
|
+
return async function (tx) {
|
|
59
|
+
if (tx.data && tx.data.startsWith('0xef3e12dc')) {
|
|
60
|
+
const decoded = oldIface.decodeFunctionData('submit', tx.data);
|
|
61
|
+
tx.data = newIface.encodeFunctionData('submit', [[decoded[0], target.address]]);
|
|
62
|
+
}
|
|
63
|
+
return target[prop](tx);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (typeof target[prop] === 'function') {
|
|
67
|
+
return target[prop].bind(target);
|
|
68
|
+
}
|
|
69
|
+
return target[prop];
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const [uploadResult, uploadErr] = await this.indexer.upload(file, this.evmRpc, proxySigner);
|
|
73
|
+
if (uploadErr !== null) {
|
|
74
|
+
throw new Error(`0G upload failed: ${uploadErr}`);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
rootHash: uploadResult.rootHash,
|
|
78
|
+
txHash: uploadResult.txHash,
|
|
79
|
+
size: dataBytes.length,
|
|
80
|
+
timestamp: Date.now(),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
if (file)
|
|
85
|
+
await file.close();
|
|
86
|
+
await fs.unlink(tmpPath).catch(() => { });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Download a file from 0G Storage by its root hash.
|
|
91
|
+
*/
|
|
92
|
+
async download(rootHash) {
|
|
93
|
+
const tmpPath = path.join(os.tmpdir(), `0g-down-${Date.now()}-${Math.random().toString(36).slice(2)}.dat`);
|
|
94
|
+
try {
|
|
95
|
+
const err = await this.indexer.download(rootHash, tmpPath, true);
|
|
96
|
+
if (err !== null) {
|
|
97
|
+
throw new Error(`0G download failed: ${err}`);
|
|
98
|
+
}
|
|
99
|
+
return await fs.readFile(tmpPath, "utf-8");
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
await fs.unlink(tmpPath).catch(() => { });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0G Agent Shield — AgentVault
|
|
3
|
+
*
|
|
4
|
+
* This is the single entry point that ties everything together.
|
|
5
|
+
* Developers interact with this class, not the internals.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const vault = new AgentVault({ privateKey, evmRpc, indexerRpc });
|
|
9
|
+
* await vault.init();
|
|
10
|
+
* const { rootHash } = await vault.store("patient has arrhythmia");
|
|
11
|
+
* const data = await vault.retrieve(rootHash);
|
|
12
|
+
* const proof = await vault.commitSession(); // attestation
|
|
13
|
+
*/
|
|
14
|
+
export interface VaultConfig {
|
|
15
|
+
privateKey: string;
|
|
16
|
+
evmRpc: string;
|
|
17
|
+
indexerRpc: string;
|
|
18
|
+
vaultSecret?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface StoreResult {
|
|
21
|
+
rootHash: string;
|
|
22
|
+
txHash: string;
|
|
23
|
+
contentHash: string;
|
|
24
|
+
size: number;
|
|
25
|
+
sessionEvent: number;
|
|
26
|
+
encryptedPayload?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CommitResult {
|
|
29
|
+
merkleRoot: string;
|
|
30
|
+
sessionId: string;
|
|
31
|
+
eventCount: number;
|
|
32
|
+
traceRootHash: string;
|
|
33
|
+
traceTxHash: string;
|
|
34
|
+
}
|
|
35
|
+
export declare class AgentVault {
|
|
36
|
+
private crypto;
|
|
37
|
+
private storage;
|
|
38
|
+
private session;
|
|
39
|
+
private initialized;
|
|
40
|
+
private config;
|
|
41
|
+
constructor(config: VaultConfig);
|
|
42
|
+
/** Initialize encryption. Must be called before store/retrieve. */
|
|
43
|
+
init(): Promise<void>;
|
|
44
|
+
get address(): string;
|
|
45
|
+
get sessionId(): string;
|
|
46
|
+
private ensureInit;
|
|
47
|
+
/**
|
|
48
|
+
* Encrypt data and store it on 0G Storage.
|
|
49
|
+
* Automatically records the action in the attestation session.
|
|
50
|
+
*/
|
|
51
|
+
store(data: string, label?: string): Promise<StoreResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Download and decrypt data from 0G Storage.
|
|
54
|
+
* Automatically records the retrieval in the attestation session.
|
|
55
|
+
*/
|
|
56
|
+
retrieve(rootHash: string, label?: string): Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Finalize the current attestation session:
|
|
59
|
+
* 1. Compute Merkle root of all events
|
|
60
|
+
* 2. Encrypt the full trace
|
|
61
|
+
* 3. Upload encrypted trace to 0G Storage
|
|
62
|
+
* 4. Return the public commitment (merkleRoot) and trace location
|
|
63
|
+
*
|
|
64
|
+
* After this call, a new session begins automatically.
|
|
65
|
+
*/
|
|
66
|
+
commitSession(): Promise<CommitResult>;
|
|
67
|
+
/** Get a human-readable summary of the current session */
|
|
68
|
+
sessionSummary(): string;
|
|
69
|
+
/** Check wallet balance */
|
|
70
|
+
getBalance(): Promise<string>;
|
|
71
|
+
}
|