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,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SILO — Agent Router
|
|
3
|
+
*
|
|
4
|
+
* Enables any agent to dynamically spin up sub-agents with:
|
|
5
|
+
* - Inherited shared memory context (via 0G root hashes)
|
|
6
|
+
* - A dedicated parent↔child communication channel
|
|
7
|
+
* - Configurable autonomy levels (supervised vs autonomous)
|
|
8
|
+
* - Result propagation back to the parent
|
|
9
|
+
*
|
|
10
|
+
* The router manages a tree of agent relationships and their communication
|
|
11
|
+
* channels. Each sub-agent gets its own vault instance but shares memory
|
|
12
|
+
* context with its parent through 0G-backed channels.
|
|
13
|
+
*
|
|
14
|
+
* Communication Flow:
|
|
15
|
+
* Parent spawns SubAgent → creates dedicated channel "agent:{parentId}:{childId}"
|
|
16
|
+
* Parent writes context to channel → SubAgent reads on startup
|
|
17
|
+
* SubAgent writes results to channel → Parent receives via subscription
|
|
18
|
+
* SubAgent can itself spawn further sub-agents (recursive)
|
|
19
|
+
*/
|
|
20
|
+
import { AgentVault } from "./vault.js";
|
|
21
|
+
import { SharedMemoryBus, type MemoryEntry } from "./shared-memory.js";
|
|
22
|
+
export type AgentAutonomy = "supervised" | "autonomous";
|
|
23
|
+
export type AgentStatus = "initializing" | "running" | "waiting" | "completed" | "failed" | "terminated";
|
|
24
|
+
export interface SubAgentDescriptor {
|
|
25
|
+
id: string;
|
|
26
|
+
role: string;
|
|
27
|
+
parentId: string;
|
|
28
|
+
channelName: string;
|
|
29
|
+
status: AgentStatus;
|
|
30
|
+
autonomy: AgentAutonomy;
|
|
31
|
+
createdAt: number;
|
|
32
|
+
completedAt: number | null;
|
|
33
|
+
contextRootHashes: string[];
|
|
34
|
+
resultRootHash: string | null;
|
|
35
|
+
metadata?: Record<string, any>;
|
|
36
|
+
}
|
|
37
|
+
export interface SpawnOptions {
|
|
38
|
+
role: string;
|
|
39
|
+
contextRootHashes?: string[];
|
|
40
|
+
contextData?: string;
|
|
41
|
+
autonomy?: AgentAutonomy;
|
|
42
|
+
metadata?: Record<string, any>;
|
|
43
|
+
onMessage?: (entry: MemoryEntry) => void;
|
|
44
|
+
onComplete?: (result: SubAgentResult) => void;
|
|
45
|
+
}
|
|
46
|
+
export interface SubAgentResult {
|
|
47
|
+
agentId: string;
|
|
48
|
+
role: string;
|
|
49
|
+
success: boolean;
|
|
50
|
+
output: string;
|
|
51
|
+
rootHash: string | null;
|
|
52
|
+
duration: number;
|
|
53
|
+
eventsProcessed: number;
|
|
54
|
+
}
|
|
55
|
+
export interface AgentMessage {
|
|
56
|
+
type: "context" | "instruction" | "result" | "status" | "error";
|
|
57
|
+
from: string;
|
|
58
|
+
to: string;
|
|
59
|
+
payload: string;
|
|
60
|
+
timestamp: number;
|
|
61
|
+
}
|
|
62
|
+
export declare class AgentRouter {
|
|
63
|
+
private vault;
|
|
64
|
+
private sharedMemory;
|
|
65
|
+
private agentId;
|
|
66
|
+
private children;
|
|
67
|
+
private parentId;
|
|
68
|
+
private messageHandlers;
|
|
69
|
+
private onSpawn?;
|
|
70
|
+
private onMessage?;
|
|
71
|
+
constructor(vault: AgentVault, sharedMemory: SharedMemoryBus);
|
|
72
|
+
get id(): string;
|
|
73
|
+
/** Register handlers for external notifications (WebSocket, etc.) */
|
|
74
|
+
setEventHandlers(handlers: {
|
|
75
|
+
onSpawn?: (descriptor: SubAgentDescriptor) => void;
|
|
76
|
+
onMessage?: (channel: string, msg: AgentMessage) => void;
|
|
77
|
+
}): void;
|
|
78
|
+
/**
|
|
79
|
+
* Spawn a sub-agent with shared context.
|
|
80
|
+
*
|
|
81
|
+
* Creates a dedicated communication channel and seeds it with context.
|
|
82
|
+
* The sub-agent descriptor is returned immediately — the actual agent
|
|
83
|
+
* execution happens asynchronously (driven by whoever picks up the descriptor).
|
|
84
|
+
*/
|
|
85
|
+
spawn(options: SpawnOptions): Promise<SubAgentDescriptor>;
|
|
86
|
+
/** Send a message to a sub-agent (or parent) via their shared channel */
|
|
87
|
+
sendMessage(channelName: string, message: AgentMessage): Promise<MemoryEntry>;
|
|
88
|
+
/** Send an instruction to a specific sub-agent */
|
|
89
|
+
instruct(childId: string, instruction: string): Promise<MemoryEntry>;
|
|
90
|
+
/** Report a result back to the parent (called by sub-agents) */
|
|
91
|
+
reportResult(result: SubAgentResult): Promise<void>;
|
|
92
|
+
/** Mark a sub-agent as completed */
|
|
93
|
+
completeChild(childId: string, resultRootHash?: string): void;
|
|
94
|
+
/** Terminate a sub-agent */
|
|
95
|
+
terminateChild(childId: string, reason?: string): Promise<void>;
|
|
96
|
+
/** Set this agent as a child of a parent */
|
|
97
|
+
setParent(parentId: string): void;
|
|
98
|
+
/** List all sub-agents */
|
|
99
|
+
listChildren(): SubAgentDescriptor[];
|
|
100
|
+
/** Get a sub-agent's descriptor */
|
|
101
|
+
getChild(childId: string): SubAgentDescriptor | undefined;
|
|
102
|
+
/** Get full agent tree status */
|
|
103
|
+
status(): {
|
|
104
|
+
agentId: string;
|
|
105
|
+
parentId: string | null;
|
|
106
|
+
childCount: number;
|
|
107
|
+
children: SubAgentDescriptor[];
|
|
108
|
+
channels: string[];
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SILO — Agent Router
|
|
3
|
+
*
|
|
4
|
+
* Enables any agent to dynamically spin up sub-agents with:
|
|
5
|
+
* - Inherited shared memory context (via 0G root hashes)
|
|
6
|
+
* - A dedicated parent↔child communication channel
|
|
7
|
+
* - Configurable autonomy levels (supervised vs autonomous)
|
|
8
|
+
* - Result propagation back to the parent
|
|
9
|
+
*
|
|
10
|
+
* The router manages a tree of agent relationships and their communication
|
|
11
|
+
* channels. Each sub-agent gets its own vault instance but shares memory
|
|
12
|
+
* context with its parent through 0G-backed channels.
|
|
13
|
+
*
|
|
14
|
+
* Communication Flow:
|
|
15
|
+
* Parent spawns SubAgent → creates dedicated channel "agent:{parentId}:{childId}"
|
|
16
|
+
* Parent writes context to channel → SubAgent reads on startup
|
|
17
|
+
* SubAgent writes results to channel → Parent receives via subscription
|
|
18
|
+
* SubAgent can itself spawn further sub-agents (recursive)
|
|
19
|
+
*/
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
export class AgentRouter {
|
|
22
|
+
vault;
|
|
23
|
+
sharedMemory;
|
|
24
|
+
agentId;
|
|
25
|
+
children = new Map();
|
|
26
|
+
parentId = null;
|
|
27
|
+
messageHandlers = new Map();
|
|
28
|
+
onSpawn;
|
|
29
|
+
onMessage;
|
|
30
|
+
constructor(vault, sharedMemory) {
|
|
31
|
+
this.vault = vault;
|
|
32
|
+
this.sharedMemory = sharedMemory;
|
|
33
|
+
this.agentId = vault.address;
|
|
34
|
+
}
|
|
35
|
+
get id() { return this.agentId; }
|
|
36
|
+
/** Register handlers for external notifications (WebSocket, etc.) */
|
|
37
|
+
setEventHandlers(handlers) {
|
|
38
|
+
this.onSpawn = handlers.onSpawn;
|
|
39
|
+
this.onMessage = handlers.onMessage;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Spawn a sub-agent with shared context.
|
|
43
|
+
*
|
|
44
|
+
* Creates a dedicated communication channel and seeds it with context.
|
|
45
|
+
* The sub-agent descriptor is returned immediately — the actual agent
|
|
46
|
+
* execution happens asynchronously (driven by whoever picks up the descriptor).
|
|
47
|
+
*/
|
|
48
|
+
async spawn(options) {
|
|
49
|
+
const childId = createHash("sha256")
|
|
50
|
+
.update(`subagent:${this.agentId}:${options.role}:${Date.now()}:${Math.random()}`)
|
|
51
|
+
.digest("hex")
|
|
52
|
+
.slice(0, 16);
|
|
53
|
+
const channelName = `agent:${this.agentId.slice(0, 8)}:${childId}`;
|
|
54
|
+
this.sharedMemory.createChannel(channelName);
|
|
55
|
+
const descriptor = {
|
|
56
|
+
id: childId,
|
|
57
|
+
role: options.role,
|
|
58
|
+
parentId: this.agentId,
|
|
59
|
+
channelName,
|
|
60
|
+
status: "initializing",
|
|
61
|
+
autonomy: options.autonomy ?? "supervised",
|
|
62
|
+
createdAt: Date.now(),
|
|
63
|
+
completedAt: null,
|
|
64
|
+
contextRootHashes: options.contextRootHashes ?? [],
|
|
65
|
+
resultRootHash: null,
|
|
66
|
+
metadata: options.metadata,
|
|
67
|
+
};
|
|
68
|
+
this.children.set(childId, descriptor);
|
|
69
|
+
if (options.contextData) {
|
|
70
|
+
await this.sendMessage(channelName, {
|
|
71
|
+
type: "context",
|
|
72
|
+
from: this.agentId,
|
|
73
|
+
to: childId,
|
|
74
|
+
payload: options.contextData,
|
|
75
|
+
timestamp: Date.now(),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (options.contextRootHashes?.length) {
|
|
79
|
+
await this.sendMessage(channelName, {
|
|
80
|
+
type: "context",
|
|
81
|
+
from: this.agentId,
|
|
82
|
+
to: childId,
|
|
83
|
+
payload: JSON.stringify({
|
|
84
|
+
inheritedMemory: options.contextRootHashes,
|
|
85
|
+
instruction: "Retrieve these root hashes from 0G to load shared context",
|
|
86
|
+
}),
|
|
87
|
+
timestamp: Date.now(),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (options.onMessage) {
|
|
91
|
+
this.sharedMemory.subscribe(channelName, (entry) => {
|
|
92
|
+
try {
|
|
93
|
+
const msg = JSON.parse(entry.data);
|
|
94
|
+
if (msg.from !== this.agentId) {
|
|
95
|
+
options.onMessage(entry);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch { }
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
descriptor.status = "running";
|
|
102
|
+
this.onSpawn?.(descriptor);
|
|
103
|
+
const descriptorData = JSON.stringify(descriptor);
|
|
104
|
+
const stored = await this.vault.store(descriptorData, `spawn:${options.role}`);
|
|
105
|
+
await this.sharedMemory.write("silo:agents", JSON.stringify({
|
|
106
|
+
event: "agent_spawned",
|
|
107
|
+
descriptor: { ...descriptor, storedAt: stored.rootHash },
|
|
108
|
+
}));
|
|
109
|
+
return descriptor;
|
|
110
|
+
}
|
|
111
|
+
/** Send a message to a sub-agent (or parent) via their shared channel */
|
|
112
|
+
async sendMessage(channelName, message) {
|
|
113
|
+
const entry = await this.sharedMemory.write(channelName, JSON.stringify(message), {
|
|
114
|
+
messageType: message.type,
|
|
115
|
+
from: message.from,
|
|
116
|
+
to: message.to,
|
|
117
|
+
});
|
|
118
|
+
this.onMessage?.(channelName, message);
|
|
119
|
+
return entry;
|
|
120
|
+
}
|
|
121
|
+
/** Send an instruction to a specific sub-agent */
|
|
122
|
+
async instruct(childId, instruction) {
|
|
123
|
+
const child = this.children.get(childId);
|
|
124
|
+
if (!child)
|
|
125
|
+
throw new Error(`Sub-agent "${childId}" not found`);
|
|
126
|
+
return this.sendMessage(child.channelName, {
|
|
127
|
+
type: "instruction",
|
|
128
|
+
from: this.agentId,
|
|
129
|
+
to: childId,
|
|
130
|
+
payload: instruction,
|
|
131
|
+
timestamp: Date.now(),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/** Report a result back to the parent (called by sub-agents) */
|
|
135
|
+
async reportResult(result) {
|
|
136
|
+
if (!this.parentId)
|
|
137
|
+
return;
|
|
138
|
+
const channelName = `agent:${this.parentId.slice(0, 8)}:${this.agentId.slice(0, 16)}`;
|
|
139
|
+
const stored = await this.vault.store(JSON.stringify(result), `result:${result.role}`);
|
|
140
|
+
await this.sendMessage(channelName, {
|
|
141
|
+
type: "result",
|
|
142
|
+
from: this.agentId,
|
|
143
|
+
to: this.parentId,
|
|
144
|
+
payload: JSON.stringify({ ...result, rootHash: stored.rootHash }),
|
|
145
|
+
timestamp: Date.now(),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/** Mark a sub-agent as completed */
|
|
149
|
+
completeChild(childId, resultRootHash) {
|
|
150
|
+
const child = this.children.get(childId);
|
|
151
|
+
if (!child)
|
|
152
|
+
return;
|
|
153
|
+
child.status = "completed";
|
|
154
|
+
child.completedAt = Date.now();
|
|
155
|
+
if (resultRootHash)
|
|
156
|
+
child.resultRootHash = resultRootHash;
|
|
157
|
+
}
|
|
158
|
+
/** Terminate a sub-agent */
|
|
159
|
+
async terminateChild(childId, reason) {
|
|
160
|
+
const child = this.children.get(childId);
|
|
161
|
+
if (!child)
|
|
162
|
+
return;
|
|
163
|
+
await this.sendMessage(child.channelName, {
|
|
164
|
+
type: "instruction",
|
|
165
|
+
from: this.agentId,
|
|
166
|
+
to: childId,
|
|
167
|
+
payload: JSON.stringify({ action: "terminate", reason }),
|
|
168
|
+
timestamp: Date.now(),
|
|
169
|
+
});
|
|
170
|
+
child.status = "terminated";
|
|
171
|
+
child.completedAt = Date.now();
|
|
172
|
+
}
|
|
173
|
+
/** Set this agent as a child of a parent */
|
|
174
|
+
setParent(parentId) {
|
|
175
|
+
this.parentId = parentId;
|
|
176
|
+
}
|
|
177
|
+
/** List all sub-agents */
|
|
178
|
+
listChildren() {
|
|
179
|
+
return Array.from(this.children.values());
|
|
180
|
+
}
|
|
181
|
+
/** Get a sub-agent's descriptor */
|
|
182
|
+
getChild(childId) {
|
|
183
|
+
return this.children.get(childId);
|
|
184
|
+
}
|
|
185
|
+
/** Get full agent tree status */
|
|
186
|
+
status() {
|
|
187
|
+
const channels = Array.from(this.children.values()).map(c => c.channelName);
|
|
188
|
+
return {
|
|
189
|
+
agentId: this.agentId,
|
|
190
|
+
parentId: this.parentId,
|
|
191
|
+
childCount: this.children.size,
|
|
192
|
+
children: this.listChildren(),
|
|
193
|
+
channels,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=agent-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-router.js","sourceRoot":"","sources":["../../src/lib/agent-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0G Agent Shield — Attestation Layer
|
|
3
|
+
*
|
|
4
|
+
* Tracks every action an agent takes during a session:
|
|
5
|
+
* - What was stored (hash of plaintext, NOT the plaintext)
|
|
6
|
+
* - What was retrieved
|
|
7
|
+
* - What tools were called
|
|
8
|
+
*
|
|
9
|
+
* At session end, builds a Merkle root from all event hashes.
|
|
10
|
+
* The full encrypted trace goes to 0G Storage.
|
|
11
|
+
* The Merkle root is the public commitment — anyone can verify
|
|
12
|
+
* "this agent did N things in this session" without seeing what.
|
|
13
|
+
*
|
|
14
|
+
* This is what makes 0g-agent-shield more than an encrypted storage wrapper.
|
|
15
|
+
* It's verifiable agent behavior.
|
|
16
|
+
*/
|
|
17
|
+
export interface AttestationEvent {
|
|
18
|
+
type: "store" | "retrieve" | "tool_call" | "policy_check";
|
|
19
|
+
timestamp: number;
|
|
20
|
+
inputHash: string;
|
|
21
|
+
outputHash: string;
|
|
22
|
+
metadata?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface SessionAttestation {
|
|
25
|
+
sessionId: string;
|
|
26
|
+
agentAddress: string;
|
|
27
|
+
startedAt: number;
|
|
28
|
+
endedAt: number;
|
|
29
|
+
eventCount: number;
|
|
30
|
+
merkleRoot: string;
|
|
31
|
+
events: AttestationEvent[];
|
|
32
|
+
}
|
|
33
|
+
export declare class AttestationSession {
|
|
34
|
+
private events;
|
|
35
|
+
private sessionId;
|
|
36
|
+
private agentAddress;
|
|
37
|
+
private startedAt;
|
|
38
|
+
constructor(agentAddress: string);
|
|
39
|
+
get id(): string;
|
|
40
|
+
get count(): number;
|
|
41
|
+
/**
|
|
42
|
+
* Record an agent action. Only hashes are stored in the event —
|
|
43
|
+
* the actual content is never part of the attestation.
|
|
44
|
+
*/
|
|
45
|
+
record(type: AttestationEvent["type"], input: string, output: string, metadata?: string): AttestationEvent;
|
|
46
|
+
/**
|
|
47
|
+
* Build a Merkle root from all recorded events.
|
|
48
|
+
* Uses simple pairwise SHA-256 hashing.
|
|
49
|
+
*
|
|
50
|
+
* This root is the public commitment: it proves exactly how many
|
|
51
|
+
* actions occurred and their order, without revealing content.
|
|
52
|
+
*/
|
|
53
|
+
computeMerkleRoot(): string;
|
|
54
|
+
/**
|
|
55
|
+
* Finalize the session and produce the attestation record.
|
|
56
|
+
* This gets encrypted and stored on 0G.
|
|
57
|
+
* The merkleRoot is the only thing that needs to be public.
|
|
58
|
+
*/
|
|
59
|
+
finalize(): SessionAttestation;
|
|
60
|
+
/**
|
|
61
|
+
* Produce a human-readable summary (for CLI/demo output).
|
|
62
|
+
*/
|
|
63
|
+
summary(): string;
|
|
64
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0G Agent Shield — Attestation Layer
|
|
3
|
+
*
|
|
4
|
+
* Tracks every action an agent takes during a session:
|
|
5
|
+
* - What was stored (hash of plaintext, NOT the plaintext)
|
|
6
|
+
* - What was retrieved
|
|
7
|
+
* - What tools were called
|
|
8
|
+
*
|
|
9
|
+
* At session end, builds a Merkle root from all event hashes.
|
|
10
|
+
* The full encrypted trace goes to 0G Storage.
|
|
11
|
+
* The Merkle root is the public commitment — anyone can verify
|
|
12
|
+
* "this agent did N things in this session" without seeing what.
|
|
13
|
+
*
|
|
14
|
+
* This is what makes 0g-agent-shield more than an encrypted storage wrapper.
|
|
15
|
+
* It's verifiable agent behavior.
|
|
16
|
+
*/
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
export class AttestationSession {
|
|
19
|
+
events = [];
|
|
20
|
+
sessionId;
|
|
21
|
+
agentAddress;
|
|
22
|
+
startedAt;
|
|
23
|
+
constructor(agentAddress) {
|
|
24
|
+
this.agentAddress = agentAddress;
|
|
25
|
+
this.startedAt = Date.now();
|
|
26
|
+
this.sessionId = createHash("sha256")
|
|
27
|
+
.update(`${agentAddress}-${this.startedAt}-${Math.random()}`)
|
|
28
|
+
.digest("hex")
|
|
29
|
+
.slice(0, 16);
|
|
30
|
+
}
|
|
31
|
+
get id() {
|
|
32
|
+
return this.sessionId;
|
|
33
|
+
}
|
|
34
|
+
get count() {
|
|
35
|
+
return this.events.length;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Record an agent action. Only hashes are stored in the event —
|
|
39
|
+
* the actual content is never part of the attestation.
|
|
40
|
+
*/
|
|
41
|
+
record(type, input, output, metadata) {
|
|
42
|
+
const event = {
|
|
43
|
+
type,
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
inputHash: createHash("sha256").update(input).digest("hex"),
|
|
46
|
+
outputHash: createHash("sha256").update(output).digest("hex"),
|
|
47
|
+
metadata,
|
|
48
|
+
};
|
|
49
|
+
this.events.push(event);
|
|
50
|
+
return event;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Build a Merkle root from all recorded events.
|
|
54
|
+
* Uses simple pairwise SHA-256 hashing.
|
|
55
|
+
*
|
|
56
|
+
* This root is the public commitment: it proves exactly how many
|
|
57
|
+
* actions occurred and their order, without revealing content.
|
|
58
|
+
*/
|
|
59
|
+
computeMerkleRoot() {
|
|
60
|
+
if (this.events.length === 0) {
|
|
61
|
+
return createHash("sha256").update("empty-session").digest("hex");
|
|
62
|
+
}
|
|
63
|
+
// Leaf nodes: hash of each event's combined hashes
|
|
64
|
+
let leaves = this.events.map((e) => createHash("sha256")
|
|
65
|
+
.update(`${e.type}:${e.inputHash}:${e.outputHash}:${e.timestamp}`)
|
|
66
|
+
.digest("hex"));
|
|
67
|
+
// Build tree bottom-up
|
|
68
|
+
while (leaves.length > 1) {
|
|
69
|
+
const next = [];
|
|
70
|
+
for (let i = 0; i < leaves.length; i += 2) {
|
|
71
|
+
const left = leaves[i];
|
|
72
|
+
const right = leaves[i + 1] ?? left; // duplicate last if odd
|
|
73
|
+
next.push(createHash("sha256").update(left + right).digest("hex"));
|
|
74
|
+
}
|
|
75
|
+
leaves = next;
|
|
76
|
+
}
|
|
77
|
+
return leaves[0];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Finalize the session and produce the attestation record.
|
|
81
|
+
* This gets encrypted and stored on 0G.
|
|
82
|
+
* The merkleRoot is the only thing that needs to be public.
|
|
83
|
+
*/
|
|
84
|
+
finalize() {
|
|
85
|
+
return {
|
|
86
|
+
sessionId: this.sessionId,
|
|
87
|
+
agentAddress: this.agentAddress,
|
|
88
|
+
startedAt: this.startedAt,
|
|
89
|
+
endedAt: Date.now(),
|
|
90
|
+
eventCount: this.events.length,
|
|
91
|
+
merkleRoot: this.computeMerkleRoot(),
|
|
92
|
+
events: [...this.events], // copy
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Produce a human-readable summary (for CLI/demo output).
|
|
97
|
+
*/
|
|
98
|
+
summary() {
|
|
99
|
+
const root = this.computeMerkleRoot();
|
|
100
|
+
const lines = [
|
|
101
|
+
`Session: ${this.sessionId}`,
|
|
102
|
+
`Agent: ${this.agentAddress.slice(0, 10)}...`,
|
|
103
|
+
`Events: ${this.events.length}`,
|
|
104
|
+
`Root: ${root.slice(0, 16)}...`,
|
|
105
|
+
"",
|
|
106
|
+
"Event Log:",
|
|
107
|
+
...this.events.map((e, i) => ` ${i + 1}. [${e.type}] ${new Date(e.timestamp).toISOString()} — ${e.metadata ?? ""}`),
|
|
108
|
+
];
|
|
109
|
+
return lines.join("\n");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=attestation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.js","sourceRoot":"","sources":["../../src/lib/attestation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAoBzC,MAAM,OAAO,kBAAkB;IACrB,MAAM,GAAuB,EAAE,CAAC;IAChC,SAAS,CAAS;IAClB,YAAY,CAAS;IACrB,SAAS,CAAS;IAE1B,YAAY,YAAoB;QAC9B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC;aAClC,MAAM,CAAC,GAAG,YAAY,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;aAC5D,MAAM,CAAC,KAAK,CAAC;aACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,MAAM,CACJ,IAA8B,EAC9B,KAAa,EACb,MAAc,EACd,QAAiB;QAEjB,MAAM,KAAK,GAAqB;YAC9B,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC3D,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC7D,QAAQ;SACT,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACH,iBAAiB;QACf,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpE,CAAC;QAED,mDAAmD;QACnD,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACjC,UAAU,CAAC,QAAQ,CAAC;aACjB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;aACjE,MAAM,CAAC,KAAK,CAAC,CACjB,CAAC;QAEF,uBAAuB;QACvB,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;gBACvB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,wBAAwB;gBAC7D,IAAI,CAAC,IAAI,CACP,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACxD,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,QAAQ;QACN,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;YACnB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAC9B,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE;YACpC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO;SAClC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,OAAO;QACL,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG;YACZ,YAAY,IAAI,CAAC,SAAS,EAAE;YAC5B,YAAY,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK;YAC/C,YAAY,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAChC,YAAY,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK;YAClC,EAAE;YACF,YAAY;YACZ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAChB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,CACjG;SACF,CAAC;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SILO — Autonomy Engine
|
|
3
|
+
*
|
|
4
|
+
* The orchestrator that ties heartbeat + shared memory + agent routing into
|
|
5
|
+
* a fully autonomous build pipeline.
|
|
6
|
+
*
|
|
7
|
+
* When enabled, the engine:
|
|
8
|
+
* 1. Monitors the system via heartbeat tasks
|
|
9
|
+
* 2. Detects issues through diagnostic handlers
|
|
10
|
+
* 3. Spawns sub-agents to investigate and fix problems
|
|
11
|
+
* 4. Pushes fixes through the attestation pipeline
|
|
12
|
+
* 5. Persists all decisions and outcomes to shared memory on 0G
|
|
13
|
+
*
|
|
14
|
+
* The autonomy loop:
|
|
15
|
+
* DETECT → PLAN → SPAWN → FIX → ATTEST → REPEAT
|
|
16
|
+
*
|
|
17
|
+
* All autonomous actions are fully attested — the Merkle tree captures
|
|
18
|
+
* every decision, fix, and outcome. Nothing happens in the dark.
|
|
19
|
+
*/
|
|
20
|
+
import { AgentVault } from "./vault.js";
|
|
21
|
+
import { SharedMemoryBus } from "./shared-memory.js";
|
|
22
|
+
import { HeartbeatDaemon, type TaskContext } from "./heartbeat.js";
|
|
23
|
+
import { AgentRouter } from "./agent-router.js";
|
|
24
|
+
export type AutonomyLevel = "off" | "monitor" | "suggest" | "autonomous";
|
|
25
|
+
export interface AutonomyConfig {
|
|
26
|
+
level: AutonomyLevel;
|
|
27
|
+
heartbeatIntervalMs: number;
|
|
28
|
+
fixChannel: string;
|
|
29
|
+
decisionChannel: string;
|
|
30
|
+
maxConcurrentAgents: number;
|
|
31
|
+
autoCommitIntervalMs: number;
|
|
32
|
+
diagnosticHandlers: DiagnosticHandler[];
|
|
33
|
+
onDecision?: (decision: AutonomyDecision) => void;
|
|
34
|
+
onFixPushed?: (fix: AutonomyFix) => void;
|
|
35
|
+
}
|
|
36
|
+
export interface DiagnosticHandler {
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
check: (ctx: TaskContext) => Promise<DiagnosticResult>;
|
|
40
|
+
fix?: (ctx: TaskContext, diagnostic: DiagnosticResult) => Promise<FixResult>;
|
|
41
|
+
}
|
|
42
|
+
export interface DiagnosticResult {
|
|
43
|
+
handler: string;
|
|
44
|
+
healthy: boolean;
|
|
45
|
+
severity: "info" | "warning" | "critical";
|
|
46
|
+
message: string;
|
|
47
|
+
details?: Record<string, any>;
|
|
48
|
+
suggestedFix?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface FixResult {
|
|
51
|
+
applied: boolean;
|
|
52
|
+
description: string;
|
|
53
|
+
rootHash?: string;
|
|
54
|
+
rollbackData?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface AutonomyDecision {
|
|
57
|
+
id: string;
|
|
58
|
+
timestamp: number;
|
|
59
|
+
trigger: string;
|
|
60
|
+
diagnostic: DiagnosticResult;
|
|
61
|
+
action: "ignore" | "log" | "suggest" | "auto_fix" | "spawn_agent";
|
|
62
|
+
reasoning: string;
|
|
63
|
+
autonomyLevel: AutonomyLevel;
|
|
64
|
+
}
|
|
65
|
+
export interface AutonomyFix {
|
|
66
|
+
id: string;
|
|
67
|
+
decisionId: string;
|
|
68
|
+
timestamp: number;
|
|
69
|
+
handler: string;
|
|
70
|
+
result: FixResult;
|
|
71
|
+
attestedRootHash: string | null;
|
|
72
|
+
agentId: string | null;
|
|
73
|
+
}
|
|
74
|
+
export declare class AutonomyEngine {
|
|
75
|
+
private vault;
|
|
76
|
+
private sharedMemory;
|
|
77
|
+
private heartbeat;
|
|
78
|
+
private router;
|
|
79
|
+
private config;
|
|
80
|
+
private decisions;
|
|
81
|
+
private fixes;
|
|
82
|
+
private running;
|
|
83
|
+
private diagnosticTimer;
|
|
84
|
+
constructor(vault: AgentVault, sharedMemory: SharedMemoryBus, heartbeat: HeartbeatDaemon, router: AgentRouter, config?: Partial<AutonomyConfig>);
|
|
85
|
+
get level(): AutonomyLevel;
|
|
86
|
+
get isRunning(): boolean;
|
|
87
|
+
/** Set autonomy level at runtime */
|
|
88
|
+
setLevel(level: AutonomyLevel): void;
|
|
89
|
+
/** Register a diagnostic handler */
|
|
90
|
+
registerDiagnostic(handler: DiagnosticHandler): void;
|
|
91
|
+
/**
|
|
92
|
+
* Start the autonomy engine.
|
|
93
|
+
* Initializes shared memory channels, starts heartbeat, and begins diagnostic loop.
|
|
94
|
+
*/
|
|
95
|
+
start(): void;
|
|
96
|
+
/** Stop the autonomy engine and all sub-systems */
|
|
97
|
+
stop(): void;
|
|
98
|
+
/** Run all registered diagnostic handlers and take action based on autonomy level */
|
|
99
|
+
private runDiagnostics;
|
|
100
|
+
/** Decide what to do about an unhealthy diagnostic based on autonomy level */
|
|
101
|
+
private handleDiagnostic;
|
|
102
|
+
/** Apply a fix directly */
|
|
103
|
+
private applyFix;
|
|
104
|
+
/** Spawn a dedicated sub-agent for critical issues */
|
|
105
|
+
private spawnFixAgent;
|
|
106
|
+
/** Get the full autonomy engine status */
|
|
107
|
+
status(): {
|
|
108
|
+
level: AutonomyLevel;
|
|
109
|
+
running: boolean;
|
|
110
|
+
heartbeat: ReturnType<HeartbeatDaemon["status"]>;
|
|
111
|
+
agents: ReturnType<AgentRouter["status"]>;
|
|
112
|
+
recentDecisions: AutonomyDecision[];
|
|
113
|
+
recentFixes: AutonomyFix[];
|
|
114
|
+
diagnosticHandlers: string[];
|
|
115
|
+
};
|
|
116
|
+
}
|