@rookdaemon/agora 0.2.7 → 0.2.9
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 +33 -0
- package/dist/chunk-JUOGKXFN.js +1645 -0
- package/dist/chunk-JUOGKXFN.js.map +1 -0
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +1163 -1137
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1613 -25
- package/dist/index.js +1135 -24
- package/dist/index.js.map +1 -1
- package/package.json +11 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/config.d.ts +0 -59
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -115
- package/dist/config.js.map +0 -1
- package/dist/discovery/bootstrap.d.ts +0 -32
- package/dist/discovery/bootstrap.d.ts.map +0 -1
- package/dist/discovery/bootstrap.js +0 -36
- package/dist/discovery/bootstrap.js.map +0 -1
- package/dist/discovery/peer-discovery.d.ts +0 -59
- package/dist/discovery/peer-discovery.d.ts.map +0 -1
- package/dist/discovery/peer-discovery.js +0 -108
- package/dist/discovery/peer-discovery.js.map +0 -1
- package/dist/identity/keypair.d.ts +0 -42
- package/dist/identity/keypair.d.ts.map +0 -1
- package/dist/identity/keypair.js +0 -83
- package/dist/identity/keypair.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/message/envelope.d.ts +0 -59
- package/dist/message/envelope.d.ts.map +0 -1
- package/dist/message/envelope.js +0 -83
- package/dist/message/envelope.js.map +0 -1
- package/dist/message/types/paper-discovery.d.ts +0 -28
- package/dist/message/types/paper-discovery.d.ts.map +0 -1
- package/dist/message/types/paper-discovery.js +0 -2
- package/dist/message/types/paper-discovery.js.map +0 -1
- package/dist/message/types/peer-discovery.d.ts +0 -78
- package/dist/message/types/peer-discovery.d.ts.map +0 -1
- package/dist/message/types/peer-discovery.js +0 -90
- package/dist/message/types/peer-discovery.js.map +0 -1
- package/dist/peer/client.d.ts +0 -50
- package/dist/peer/client.d.ts.map +0 -1
- package/dist/peer/client.js +0 -138
- package/dist/peer/client.js.map +0 -1
- package/dist/peer/manager.d.ts +0 -65
- package/dist/peer/manager.d.ts.map +0 -1
- package/dist/peer/manager.js +0 -153
- package/dist/peer/manager.js.map +0 -1
- package/dist/peer/server.d.ts +0 -65
- package/dist/peer/server.d.ts.map +0 -1
- package/dist/peer/server.js +0 -154
- package/dist/peer/server.js.map +0 -1
- package/dist/registry/capability.d.ts +0 -44
- package/dist/registry/capability.d.ts.map +0 -1
- package/dist/registry/capability.js +0 -94
- package/dist/registry/capability.js.map +0 -1
- package/dist/registry/discovery-service.d.ts +0 -64
- package/dist/registry/discovery-service.d.ts.map +0 -1
- package/dist/registry/discovery-service.js +0 -129
- package/dist/registry/discovery-service.js.map +0 -1
- package/dist/registry/messages.d.ts +0 -105
- package/dist/registry/messages.d.ts.map +0 -1
- package/dist/registry/messages.js +0 -2
- package/dist/registry/messages.js.map +0 -1
- package/dist/registry/peer-store.d.ts +0 -57
- package/dist/registry/peer-store.d.ts.map +0 -1
- package/dist/registry/peer-store.js +0 -92
- package/dist/registry/peer-store.js.map +0 -1
- package/dist/registry/peer.d.ts +0 -20
- package/dist/registry/peer.d.ts.map +0 -1
- package/dist/registry/peer.js +0 -2
- package/dist/registry/peer.js.map +0 -1
- package/dist/relay/client.d.ts +0 -112
- package/dist/relay/client.d.ts.map +0 -1
- package/dist/relay/client.js +0 -281
- package/dist/relay/client.js.map +0 -1
- package/dist/relay/server.d.ts +0 -76
- package/dist/relay/server.d.ts.map +0 -1
- package/dist/relay/server.js +0 -338
- package/dist/relay/server.js.map +0 -1
- package/dist/relay/types.d.ts +0 -35
- package/dist/relay/types.d.ts.map +0 -1
- package/dist/relay/types.js +0 -2
- package/dist/relay/types.js.map +0 -1
- package/dist/reputation/commit-reveal.d.ts +0 -45
- package/dist/reputation/commit-reveal.d.ts.map +0 -1
- package/dist/reputation/commit-reveal.js +0 -125
- package/dist/reputation/commit-reveal.js.map +0 -1
- package/dist/reputation/scoring.d.ts +0 -31
- package/dist/reputation/scoring.d.ts.map +0 -1
- package/dist/reputation/scoring.js +0 -105
- package/dist/reputation/scoring.js.map +0 -1
- package/dist/reputation/store.d.ts +0 -83
- package/dist/reputation/store.d.ts.map +0 -1
- package/dist/reputation/store.js +0 -202
- package/dist/reputation/store.js.map +0 -1
- package/dist/reputation/types.d.ts +0 -150
- package/dist/reputation/types.d.ts.map +0 -1
- package/dist/reputation/types.js +0 -113
- package/dist/reputation/types.js.map +0 -1
- package/dist/reputation/verification.d.ts +0 -28
- package/dist/reputation/verification.d.ts.map +0 -1
- package/dist/reputation/verification.js +0 -91
- package/dist/reputation/verification.js.map +0 -1
- package/dist/service.d.ts +0 -90
- package/dist/service.d.ts.map +0 -1
- package/dist/service.js +0 -176
- package/dist/service.js.map +0 -1
- package/dist/transport/http.d.ts +0 -41
- package/dist/transport/http.d.ts.map +0 -1
- package/dist/transport/http.js +0 -103
- package/dist/transport/http.js.map +0 -1
- package/dist/transport/peer-config.d.ts +0 -38
- package/dist/transport/peer-config.d.ts.map +0 -1
- package/dist/transport/peer-config.js +0 -41
- package/dist/transport/peer-config.js.map +0 -1
- package/dist/transport/relay.d.ts +0 -30
- package/dist/transport/relay.d.ts.map +0 -1
- package/dist/transport/relay.js +0 -85
- package/dist/transport/relay.js.map +0 -1
- package/dist/utils.d.ts +0 -40
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -59
- package/dist/utils.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,1613 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { WebSocket } from 'ws';
|
|
3
|
+
import { Request, Response, NextFunction, Router } from 'express';
|
|
4
|
+
import http from 'node:http';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents an ed25519 key pair for agent identity
|
|
8
|
+
*/
|
|
9
|
+
interface KeyPair {
|
|
10
|
+
publicKey: string;
|
|
11
|
+
privateKey: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Generates a new ed25519 key pair
|
|
15
|
+
* @returns KeyPair with hex-encoded public and private keys
|
|
16
|
+
*/
|
|
17
|
+
declare function generateKeyPair(): KeyPair;
|
|
18
|
+
/**
|
|
19
|
+
* Signs a message with the private key
|
|
20
|
+
* @param message - The message to sign (string or Buffer)
|
|
21
|
+
* @param privateKeyHex - The private key in hex format
|
|
22
|
+
* @returns Signature as hex string
|
|
23
|
+
*/
|
|
24
|
+
declare function signMessage(message: string | Buffer, privateKeyHex: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Verifies a signature with the public key
|
|
27
|
+
* @param message - The original message (string or Buffer)
|
|
28
|
+
* @param signatureHex - The signature in hex format
|
|
29
|
+
* @param publicKeyHex - The public key in hex format
|
|
30
|
+
* @returns true if signature is valid, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
declare function verifySignature(message: string | Buffer, signatureHex: string, publicKeyHex: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Exports a key pair to a JSON-serializable format
|
|
35
|
+
* @param keyPair - The key pair to export
|
|
36
|
+
* @returns KeyPair object with hex-encoded keys
|
|
37
|
+
*/
|
|
38
|
+
declare function exportKeyPair(keyPair: KeyPair): KeyPair;
|
|
39
|
+
/**
|
|
40
|
+
* Imports a key pair from hex strings
|
|
41
|
+
* @param publicKeyHex - The public key in hex format
|
|
42
|
+
* @param privateKeyHex - The private key in hex format
|
|
43
|
+
* @returns KeyPair object
|
|
44
|
+
* @throws Error if keys are not valid hex strings
|
|
45
|
+
*/
|
|
46
|
+
declare function importKeyPair(publicKeyHex: string, privateKeyHex: string): KeyPair;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Message types on the Agora network.
|
|
50
|
+
* Every piece of data flowing between agents is wrapped in an envelope.
|
|
51
|
+
*/
|
|
52
|
+
type MessageType = 'announce' | 'discover' | 'request' | 'response' | 'publish' | 'subscribe' | 'verify' | 'ack' | 'error' | 'paper_discovery' | 'peer_list_request' | 'peer_list_response' | 'peer_referral' | 'capability_announce' | 'capability_query' | 'capability_response' | 'commit' | 'reveal' | 'verification' | 'revocation' | 'reputation_query' | 'reputation_response';
|
|
53
|
+
/**
|
|
54
|
+
* The signed envelope that wraps every message on the network.
|
|
55
|
+
* Content-addressed: the ID is the hash of the canonical payload.
|
|
56
|
+
* Signed: every envelope carries a signature from the sender's private key.
|
|
57
|
+
*/
|
|
58
|
+
interface Envelope<T = unknown> {
|
|
59
|
+
/** Content-addressed ID: SHA-256 hash of canonical payload */
|
|
60
|
+
id: string;
|
|
61
|
+
/** Message type */
|
|
62
|
+
type: MessageType;
|
|
63
|
+
/** Sender's public key (hex-encoded ed25519) */
|
|
64
|
+
sender: string;
|
|
65
|
+
/** Unix timestamp (ms) when the message was created */
|
|
66
|
+
timestamp: number;
|
|
67
|
+
/** Optional: ID of the message this is responding to */
|
|
68
|
+
inReplyTo?: string;
|
|
69
|
+
/** The actual payload */
|
|
70
|
+
payload: T;
|
|
71
|
+
/** ed25519 signature over the canonical form (hex-encoded) */
|
|
72
|
+
signature: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Canonical form of an envelope for signing/hashing.
|
|
76
|
+
* Deterministic JSON serialization: recursively sorted keys, no whitespace.
|
|
77
|
+
*/
|
|
78
|
+
declare function canonicalize(type: MessageType, sender: string, timestamp: number, payload: unknown, inReplyTo?: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* Compute the content-addressed ID for a message.
|
|
81
|
+
*/
|
|
82
|
+
declare function computeId(canonical: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Create a signed envelope.
|
|
85
|
+
* @param type - Message type
|
|
86
|
+
* @param sender - Sender's public key (hex)
|
|
87
|
+
* @param privateKey - Sender's private key (hex) for signing
|
|
88
|
+
* @param payload - The message payload
|
|
89
|
+
* @param timestamp - Timestamp for the envelope (ms), defaults to Date.now()
|
|
90
|
+
* @param inReplyTo - Optional ID of the message being replied to
|
|
91
|
+
* @returns A signed Envelope
|
|
92
|
+
*/
|
|
93
|
+
declare function createEnvelope<T>(type: MessageType, sender: string, privateKey: string, payload: T, timestamp?: number, inReplyTo?: string): Envelope<T>;
|
|
94
|
+
/**
|
|
95
|
+
* Verify an envelope's integrity and authenticity.
|
|
96
|
+
* Checks:
|
|
97
|
+
* 1. Canonical form matches the ID (content-addressing)
|
|
98
|
+
* 2. Signature is valid for the sender's public key
|
|
99
|
+
*
|
|
100
|
+
* @returns Object with `valid` boolean and optional `reason` for failure
|
|
101
|
+
*/
|
|
102
|
+
declare function verifyEnvelope(envelope: Envelope): {
|
|
103
|
+
valid: boolean;
|
|
104
|
+
reason?: string;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A capability describes something an agent can do
|
|
109
|
+
*/
|
|
110
|
+
interface Capability {
|
|
111
|
+
/** Unique ID (content-addressed hash of name + version + schema) */
|
|
112
|
+
id: string;
|
|
113
|
+
/** Human-readable name: 'code-review', 'summarization', 'translation' */
|
|
114
|
+
name: string;
|
|
115
|
+
/** Semantic version */
|
|
116
|
+
version: string;
|
|
117
|
+
/** What the capability does */
|
|
118
|
+
description: string;
|
|
119
|
+
/** JSON Schema for expected input */
|
|
120
|
+
inputSchema?: object;
|
|
121
|
+
/** JSON Schema for expected output */
|
|
122
|
+
outputSchema?: object;
|
|
123
|
+
/** Discovery tags: ['code', 'typescript', 'review'] */
|
|
124
|
+
tags: string[];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Creates a capability with a content-addressed ID.
|
|
128
|
+
*
|
|
129
|
+
* @param name - Human-readable capability name
|
|
130
|
+
* @param version - Semantic version string
|
|
131
|
+
* @param description - Description of what the capability does
|
|
132
|
+
* @param options - Optional input/output schemas and tags
|
|
133
|
+
* @returns A Capability object with computed ID
|
|
134
|
+
*/
|
|
135
|
+
declare function createCapability(name: string, version: string, description: string, options?: {
|
|
136
|
+
inputSchema?: object;
|
|
137
|
+
outputSchema?: object;
|
|
138
|
+
tags?: string[];
|
|
139
|
+
}): Capability;
|
|
140
|
+
/**
|
|
141
|
+
* Validates that a capability has all required fields.
|
|
142
|
+
*
|
|
143
|
+
* @param capability - The capability to validate
|
|
144
|
+
* @returns Object with `valid` boolean and optional `errors` array
|
|
145
|
+
*/
|
|
146
|
+
declare function validateCapability(capability: unknown): {
|
|
147
|
+
valid: boolean;
|
|
148
|
+
errors?: string[];
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* A peer is an agent on the network
|
|
153
|
+
*/
|
|
154
|
+
interface Peer {
|
|
155
|
+
/** Identity (hex-encoded ed25519 public key) */
|
|
156
|
+
publicKey: string;
|
|
157
|
+
/** Capabilities this peer offers */
|
|
158
|
+
capabilities: Capability[];
|
|
159
|
+
/** Unix timestamp (ms) when this peer was last seen */
|
|
160
|
+
lastSeen: number;
|
|
161
|
+
/** Optional metadata about the peer */
|
|
162
|
+
metadata?: {
|
|
163
|
+
/** Human-readable alias */
|
|
164
|
+
name?: string;
|
|
165
|
+
/** Agent software version */
|
|
166
|
+
version?: string;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* In-memory store for known peers on the network
|
|
172
|
+
*/
|
|
173
|
+
declare class PeerStore {
|
|
174
|
+
private peers;
|
|
175
|
+
/**
|
|
176
|
+
* Add or update a peer in the store.
|
|
177
|
+
* If a peer with the same publicKey exists, it will be updated.
|
|
178
|
+
*
|
|
179
|
+
* @param peer - The peer to add or update
|
|
180
|
+
*/
|
|
181
|
+
addOrUpdatePeer(peer: Peer): void;
|
|
182
|
+
/**
|
|
183
|
+
* Remove a peer from the store.
|
|
184
|
+
*
|
|
185
|
+
* @param publicKey - The public key of the peer to remove
|
|
186
|
+
* @returns true if the peer was removed, false if it didn't exist
|
|
187
|
+
*/
|
|
188
|
+
removePeer(publicKey: string): boolean;
|
|
189
|
+
/**
|
|
190
|
+
* Get a peer by their public key.
|
|
191
|
+
*
|
|
192
|
+
* @param publicKey - The public key of the peer to retrieve
|
|
193
|
+
* @returns The peer if found, undefined otherwise
|
|
194
|
+
*/
|
|
195
|
+
getPeer(publicKey: string): Peer | undefined;
|
|
196
|
+
/**
|
|
197
|
+
* Find all peers that offer a specific capability by name.
|
|
198
|
+
*
|
|
199
|
+
* @param name - The capability name to search for
|
|
200
|
+
* @returns Array of peers that have a capability with the given name
|
|
201
|
+
*/
|
|
202
|
+
findByCapability(name: string): Peer[];
|
|
203
|
+
/**
|
|
204
|
+
* Find all peers that have capabilities with a specific tag.
|
|
205
|
+
*
|
|
206
|
+
* @param tag - The tag to search for
|
|
207
|
+
* @returns Array of peers that have at least one capability with the given tag
|
|
208
|
+
*/
|
|
209
|
+
findByTag(tag: string): Peer[];
|
|
210
|
+
/**
|
|
211
|
+
* Get all peers in the store.
|
|
212
|
+
*
|
|
213
|
+
* @returns Array of all peers
|
|
214
|
+
*/
|
|
215
|
+
allPeers(): Peer[];
|
|
216
|
+
/**
|
|
217
|
+
* Remove peers that haven't been seen within the specified time window.
|
|
218
|
+
*
|
|
219
|
+
* @param maxAgeMs - Maximum age in milliseconds. Peers older than this will be removed.
|
|
220
|
+
* @param currentTime - Current timestamp (ms), defaults to Date.now()
|
|
221
|
+
* @returns Number of peers removed
|
|
222
|
+
*/
|
|
223
|
+
prune(maxAgeMs: number, currentTime?: number): number;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Payload for 'announce' messages.
|
|
228
|
+
* An agent publishes its capabilities and metadata to the network.
|
|
229
|
+
*/
|
|
230
|
+
interface AnnouncePayload {
|
|
231
|
+
/** Capabilities this agent offers */
|
|
232
|
+
capabilities: Capability[];
|
|
233
|
+
/** Optional metadata about the agent */
|
|
234
|
+
metadata?: {
|
|
235
|
+
/** Human-readable agent name */
|
|
236
|
+
name?: string;
|
|
237
|
+
/** Agent software version */
|
|
238
|
+
version?: string;
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Payload for 'discover' messages.
|
|
243
|
+
* An agent queries the network to find peers with specific capabilities.
|
|
244
|
+
*/
|
|
245
|
+
interface DiscoverPayload {
|
|
246
|
+
/** Query parameters for discovery */
|
|
247
|
+
query: {
|
|
248
|
+
/** Filter by capability name */
|
|
249
|
+
capabilityName?: string;
|
|
250
|
+
/** Filter by capability tag */
|
|
251
|
+
tag?: string;
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Payload for responses to 'discover' messages.
|
|
256
|
+
* Returns a list of peers matching the discovery query.
|
|
257
|
+
*/
|
|
258
|
+
interface DiscoverResponsePayload {
|
|
259
|
+
/** Peers matching the discovery query */
|
|
260
|
+
peers: Array<{
|
|
261
|
+
/** Public key of the peer */
|
|
262
|
+
publicKey: string;
|
|
263
|
+
/** Capabilities the peer offers */
|
|
264
|
+
capabilities: Capability[];
|
|
265
|
+
/** Optional metadata about the peer */
|
|
266
|
+
metadata?: {
|
|
267
|
+
/** Human-readable peer name */
|
|
268
|
+
name?: string;
|
|
269
|
+
/** Peer software version */
|
|
270
|
+
version?: string;
|
|
271
|
+
};
|
|
272
|
+
}>;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Payload for 'capability_announce' messages.
|
|
276
|
+
* An agent publishes its capabilities to the network.
|
|
277
|
+
*/
|
|
278
|
+
interface CapabilityAnnouncePayload {
|
|
279
|
+
/** Agent's Ed25519 public key */
|
|
280
|
+
publicKey: string;
|
|
281
|
+
/** List of capabilities offered */
|
|
282
|
+
capabilities: Capability[];
|
|
283
|
+
/** Optional metadata */
|
|
284
|
+
metadata?: {
|
|
285
|
+
name?: string;
|
|
286
|
+
version?: string;
|
|
287
|
+
lastSeen?: number;
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Payload for 'capability_query' messages.
|
|
292
|
+
* An agent queries the network for peers with specific capabilities.
|
|
293
|
+
*/
|
|
294
|
+
interface CapabilityQueryPayload {
|
|
295
|
+
/** Query type: by name, tag, or schema */
|
|
296
|
+
queryType: 'name' | 'tag' | 'schema';
|
|
297
|
+
/** Query value (capability name, tag, or JSON schema) */
|
|
298
|
+
query: string | object;
|
|
299
|
+
/** Optional filters */
|
|
300
|
+
filters?: {
|
|
301
|
+
/** Minimum trust score (RFC-001 integration) */
|
|
302
|
+
minTrustScore?: number;
|
|
303
|
+
/** Maximum results to return */
|
|
304
|
+
limit?: number;
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Payload for 'capability_response' messages.
|
|
309
|
+
* Response to a capability_query with matching peers.
|
|
310
|
+
*/
|
|
311
|
+
interface CapabilityResponsePayload {
|
|
312
|
+
/** Query ID this is responding to */
|
|
313
|
+
queryId: string;
|
|
314
|
+
/** Matching peers */
|
|
315
|
+
peers: Array<{
|
|
316
|
+
publicKey: string;
|
|
317
|
+
capabilities: Capability[];
|
|
318
|
+
metadata?: {
|
|
319
|
+
name?: string;
|
|
320
|
+
version?: string;
|
|
321
|
+
lastSeen?: number;
|
|
322
|
+
};
|
|
323
|
+
/** Trust score from RFC-001 (Phase 2b) */
|
|
324
|
+
trustScore?: number;
|
|
325
|
+
}>;
|
|
326
|
+
/** Total matching peers (may be > peers.length if limited) */
|
|
327
|
+
totalMatches: number;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* DiscoveryService manages capability-based peer discovery.
|
|
332
|
+
* It maintains a local index of peer capabilities and handles
|
|
333
|
+
* capability announce, query, and response messages.
|
|
334
|
+
*/
|
|
335
|
+
declare class DiscoveryService {
|
|
336
|
+
private peerStore;
|
|
337
|
+
private identity;
|
|
338
|
+
constructor(peerStore: PeerStore, identity: {
|
|
339
|
+
publicKey: string;
|
|
340
|
+
privateKey: string;
|
|
341
|
+
});
|
|
342
|
+
/**
|
|
343
|
+
* Announce own capabilities to the network.
|
|
344
|
+
* Creates a capability_announce envelope that can be broadcast to peers.
|
|
345
|
+
*
|
|
346
|
+
* @param capabilities - List of capabilities this agent offers
|
|
347
|
+
* @param metadata - Optional metadata about this agent
|
|
348
|
+
* @returns A signed capability_announce envelope
|
|
349
|
+
*/
|
|
350
|
+
announce(capabilities: Capability[], metadata?: {
|
|
351
|
+
name?: string;
|
|
352
|
+
version?: string;
|
|
353
|
+
}): Envelope<CapabilityAnnouncePayload>;
|
|
354
|
+
/**
|
|
355
|
+
* Handle an incoming capability_announce message.
|
|
356
|
+
* Updates the peer store with the announced capabilities.
|
|
357
|
+
*
|
|
358
|
+
* @param envelope - The capability_announce envelope to process
|
|
359
|
+
*/
|
|
360
|
+
handleAnnounce(envelope: Envelope<CapabilityAnnouncePayload>): void;
|
|
361
|
+
/**
|
|
362
|
+
* Create a capability query payload.
|
|
363
|
+
*
|
|
364
|
+
* @param queryType - Type of query: 'name', 'tag', or 'schema'
|
|
365
|
+
* @param query - The query value (capability name, tag, or schema)
|
|
366
|
+
* @param filters - Optional filters (limit, minTrustScore)
|
|
367
|
+
* @returns A capability_query payload
|
|
368
|
+
*/
|
|
369
|
+
query(queryType: 'name' | 'tag' | 'schema', query: string | object, filters?: {
|
|
370
|
+
limit?: number;
|
|
371
|
+
minTrustScore?: number;
|
|
372
|
+
}): CapabilityQueryPayload;
|
|
373
|
+
/**
|
|
374
|
+
* Handle an incoming capability_query message.
|
|
375
|
+
* Searches the local peer store and returns matching peers.
|
|
376
|
+
*
|
|
377
|
+
* @param envelope - The capability_query envelope to process
|
|
378
|
+
* @returns A capability_response envelope with matching peers
|
|
379
|
+
*/
|
|
380
|
+
handleQuery(envelope: Envelope<CapabilityQueryPayload>): Envelope<CapabilityResponsePayload>;
|
|
381
|
+
/**
|
|
382
|
+
* Remove peers that haven't been seen within the specified time window.
|
|
383
|
+
*
|
|
384
|
+
* @param maxAgeMs - Maximum age in milliseconds
|
|
385
|
+
* @returns Number of peers removed
|
|
386
|
+
*/
|
|
387
|
+
pruneStale(maxAgeMs: number, currentTime?: number): number;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Payload for 'paper_discovery' messages.
|
|
392
|
+
* An agent publishes a discovered academic paper to the network.
|
|
393
|
+
* Each paper gets its own envelope for easy referencing and threading.
|
|
394
|
+
*/
|
|
395
|
+
interface PaperDiscoveryPayload {
|
|
396
|
+
/** arXiv identifier (e.g. "2501.12345") */
|
|
397
|
+
arxiv_id: string;
|
|
398
|
+
/** Paper title */
|
|
399
|
+
title: string;
|
|
400
|
+
/** List of author names */
|
|
401
|
+
authors: string[];
|
|
402
|
+
/** Key contribution in 1-2 sentences */
|
|
403
|
+
claim: string;
|
|
404
|
+
/** Confidence score (0-1) in the relevance/importance assessment */
|
|
405
|
+
confidence: number;
|
|
406
|
+
/** Tags describing relevance domains */
|
|
407
|
+
relevance_tags: string[];
|
|
408
|
+
/** Agent ID of the discoverer */
|
|
409
|
+
discoverer: string;
|
|
410
|
+
/** ISO 8601 timestamp of discovery */
|
|
411
|
+
timestamp: string;
|
|
412
|
+
/** URL to the abstract page */
|
|
413
|
+
abstract_url: string;
|
|
414
|
+
/** URL to the PDF (optional) */
|
|
415
|
+
pdf_url?: string;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Peer discovery message types for the Agora network.
|
|
420
|
+
*/
|
|
421
|
+
/**
|
|
422
|
+
* Request peer list from relay
|
|
423
|
+
*/
|
|
424
|
+
interface PeerListRequestPayload {
|
|
425
|
+
/** Optional filters */
|
|
426
|
+
filters?: {
|
|
427
|
+
/** Only peers seen in last N ms */
|
|
428
|
+
activeWithin?: number;
|
|
429
|
+
/** Maximum peers to return */
|
|
430
|
+
limit?: number;
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Relay responds with connected peers
|
|
435
|
+
*/
|
|
436
|
+
interface PeerListResponsePayload {
|
|
437
|
+
/** List of known peers */
|
|
438
|
+
peers: Array<{
|
|
439
|
+
/** Peer's Ed25519 public key */
|
|
440
|
+
publicKey: string;
|
|
441
|
+
/** Optional metadata (if peer announced) */
|
|
442
|
+
metadata?: {
|
|
443
|
+
name?: string;
|
|
444
|
+
version?: string;
|
|
445
|
+
capabilities?: string[];
|
|
446
|
+
};
|
|
447
|
+
/** Last seen timestamp (ms) */
|
|
448
|
+
lastSeen: number;
|
|
449
|
+
}>;
|
|
450
|
+
/** Total peer count (may be > peers.length if limited) */
|
|
451
|
+
totalPeers: number;
|
|
452
|
+
/** Relay's public key (for trust verification) */
|
|
453
|
+
relayPublicKey: string;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Agent recommends another agent
|
|
457
|
+
*/
|
|
458
|
+
interface PeerReferralPayload {
|
|
459
|
+
/** Referred peer's public key */
|
|
460
|
+
publicKey: string;
|
|
461
|
+
/** Optional endpoint (if known) */
|
|
462
|
+
endpoint?: string;
|
|
463
|
+
/** Optional metadata */
|
|
464
|
+
metadata?: {
|
|
465
|
+
name?: string;
|
|
466
|
+
version?: string;
|
|
467
|
+
capabilities?: string[];
|
|
468
|
+
};
|
|
469
|
+
/** Referrer's comment */
|
|
470
|
+
comment?: string;
|
|
471
|
+
/** Trust hint (RFC-001 integration) */
|
|
472
|
+
trustScore?: number;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Validate PeerListRequestPayload
|
|
476
|
+
*/
|
|
477
|
+
declare function validatePeerListRequest(payload: unknown): {
|
|
478
|
+
valid: boolean;
|
|
479
|
+
errors: string[];
|
|
480
|
+
};
|
|
481
|
+
/**
|
|
482
|
+
* Validate PeerListResponsePayload
|
|
483
|
+
*/
|
|
484
|
+
declare function validatePeerListResponse(payload: unknown): {
|
|
485
|
+
valid: boolean;
|
|
486
|
+
errors: string[];
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* Validate PeerReferralPayload
|
|
490
|
+
*/
|
|
491
|
+
declare function validatePeerReferral(payload: unknown): {
|
|
492
|
+
valid: boolean;
|
|
493
|
+
errors: string[];
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
interface PeerConfig {
|
|
497
|
+
/** Peer's webhook URL, e.g. http://localhost:18790/hooks (undefined for relay-only peers) */
|
|
498
|
+
url?: string;
|
|
499
|
+
/** Peer's webhook auth token (undefined for relay-only peers) */
|
|
500
|
+
token?: string;
|
|
501
|
+
/** Peer's public key (hex) for verifying responses */
|
|
502
|
+
publicKey: string;
|
|
503
|
+
}
|
|
504
|
+
interface TransportConfig {
|
|
505
|
+
/** This agent's keypair */
|
|
506
|
+
identity: {
|
|
507
|
+
publicKey: string;
|
|
508
|
+
privateKey: string;
|
|
509
|
+
};
|
|
510
|
+
/** Known peers */
|
|
511
|
+
peers: Map<string, PeerConfig>;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Send a signed envelope to a peer via HTTP webhook.
|
|
515
|
+
* Creates the envelope, signs it, and POSTs to the peer's /hooks/agent endpoint.
|
|
516
|
+
* Returns the HTTP status code.
|
|
517
|
+
*/
|
|
518
|
+
declare function sendToPeer(config: TransportConfig, peerPublicKey: string, type: MessageType, payload: unknown, inReplyTo?: string): Promise<{
|
|
519
|
+
ok: boolean;
|
|
520
|
+
status: number;
|
|
521
|
+
error?: string;
|
|
522
|
+
}>;
|
|
523
|
+
/**
|
|
524
|
+
* Decode and verify an inbound Agora envelope from a webhook message.
|
|
525
|
+
* Expects the message to start with [AGORA_ENVELOPE] followed by base64.
|
|
526
|
+
* Returns the verified envelope or an error.
|
|
527
|
+
*/
|
|
528
|
+
declare function decodeInboundEnvelope(message: string, knownPeers: Map<string, PeerConfig>): {
|
|
529
|
+
ok: true;
|
|
530
|
+
envelope: Envelope;
|
|
531
|
+
} | {
|
|
532
|
+
ok: false;
|
|
533
|
+
reason: string;
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
interface PeerConfigFile {
|
|
537
|
+
identity: {
|
|
538
|
+
publicKey: string;
|
|
539
|
+
privateKey: string;
|
|
540
|
+
name?: string;
|
|
541
|
+
};
|
|
542
|
+
relay?: string | {
|
|
543
|
+
url: string;
|
|
544
|
+
name?: string;
|
|
545
|
+
};
|
|
546
|
+
peers: Record<string, {
|
|
547
|
+
url?: string;
|
|
548
|
+
token?: string;
|
|
549
|
+
publicKey: string;
|
|
550
|
+
name?: string;
|
|
551
|
+
}>;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Load peer configuration from a JSON file.
|
|
555
|
+
* @param path - Path to the config file
|
|
556
|
+
* @returns The parsed configuration
|
|
557
|
+
* @throws Error if file doesn't exist or contains invalid JSON
|
|
558
|
+
*/
|
|
559
|
+
declare function loadPeerConfig(path: string): PeerConfigFile;
|
|
560
|
+
/**
|
|
561
|
+
* Save peer configuration to a JSON file.
|
|
562
|
+
* @param path - Path to the config file
|
|
563
|
+
* @param config - The configuration to save
|
|
564
|
+
*/
|
|
565
|
+
declare function savePeerConfig(path: string, config: PeerConfigFile): void;
|
|
566
|
+
/**
|
|
567
|
+
* Initialize peer configuration, generating a new keypair if the file doesn't exist.
|
|
568
|
+
* If the file exists, loads and returns it.
|
|
569
|
+
* @param path - Path to the config file
|
|
570
|
+
* @returns The configuration (loaded or newly created)
|
|
571
|
+
*/
|
|
572
|
+
declare function initPeerConfig(path: string): PeerConfigFile;
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Normalized relay configuration (supports both string and object in config file).
|
|
576
|
+
*/
|
|
577
|
+
interface RelayConfig {
|
|
578
|
+
url: string;
|
|
579
|
+
autoConnect: boolean;
|
|
580
|
+
name?: string;
|
|
581
|
+
reconnectMaxMs?: number;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Peer entry in config (webhook URL, token, public key).
|
|
585
|
+
*/
|
|
586
|
+
interface AgoraPeerConfig {
|
|
587
|
+
publicKey: string;
|
|
588
|
+
/** Webhook URL (undefined for relay-only peers) */
|
|
589
|
+
url?: string;
|
|
590
|
+
/** Webhook auth token (undefined for relay-only peers) */
|
|
591
|
+
token?: string;
|
|
592
|
+
name?: string;
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Identity with optional display name (e.g. for relay registration).
|
|
596
|
+
*/
|
|
597
|
+
interface AgoraIdentity {
|
|
598
|
+
publicKey: string;
|
|
599
|
+
privateKey: string;
|
|
600
|
+
name?: string;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Canonical Agora configuration shape.
|
|
604
|
+
* Use loadAgoraConfig() to load from file with normalized relay.
|
|
605
|
+
*/
|
|
606
|
+
interface AgoraConfig {
|
|
607
|
+
identity: AgoraIdentity;
|
|
608
|
+
peers: Record<string, AgoraPeerConfig>;
|
|
609
|
+
relay?: RelayConfig;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Default config file path: AGORA_CONFIG env or ~/.config/agora/config.json
|
|
613
|
+
*/
|
|
614
|
+
declare function getDefaultConfigPath(): string;
|
|
615
|
+
/**
|
|
616
|
+
* Load and normalize Agora configuration from a JSON file (sync).
|
|
617
|
+
* Supports relay as string (backward compat) or object { url?, autoConnect?, name?, reconnectMaxMs? }.
|
|
618
|
+
*
|
|
619
|
+
* @param path - Config file path; defaults to getDefaultConfigPath()
|
|
620
|
+
* @returns Normalized AgoraConfig
|
|
621
|
+
* @throws Error if file doesn't exist or config is invalid
|
|
622
|
+
*/
|
|
623
|
+
declare function loadAgoraConfig(path?: string): AgoraConfig;
|
|
624
|
+
/**
|
|
625
|
+
* Load and normalize Agora configuration from a JSON file (async).
|
|
626
|
+
*
|
|
627
|
+
* @param path - Config file path; defaults to getDefaultConfigPath()
|
|
628
|
+
* @returns Normalized AgoraConfig
|
|
629
|
+
* @throws Error if file doesn't exist or config is invalid
|
|
630
|
+
*/
|
|
631
|
+
declare function loadAgoraConfigAsync(path?: string): Promise<AgoraConfig>;
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Represents a connected agent in the relay
|
|
635
|
+
*/
|
|
636
|
+
interface ConnectedAgent {
|
|
637
|
+
/** Agent's public key */
|
|
638
|
+
publicKey: string;
|
|
639
|
+
/** Optional agent name */
|
|
640
|
+
name?: string;
|
|
641
|
+
/** WebSocket connection */
|
|
642
|
+
socket: WebSocket;
|
|
643
|
+
/** Last seen timestamp (ms) */
|
|
644
|
+
lastSeen: number;
|
|
645
|
+
/** Optional metadata */
|
|
646
|
+
metadata?: {
|
|
647
|
+
version?: string;
|
|
648
|
+
capabilities?: string[];
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Events emitted by RelayServer
|
|
653
|
+
*/
|
|
654
|
+
interface RelayServerEvents {
|
|
655
|
+
'agent-registered': (publicKey: string) => void;
|
|
656
|
+
'agent-disconnected': (publicKey: string) => void;
|
|
657
|
+
'message-relayed': (from: string, to: string, envelope: Envelope) => void;
|
|
658
|
+
'error': (error: Error) => void;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* WebSocket relay server for routing messages between agents.
|
|
662
|
+
*
|
|
663
|
+
* Agents connect to the relay and register with their public key.
|
|
664
|
+
* Messages are routed to recipients based on the 'to' field.
|
|
665
|
+
* All envelopes are verified before being forwarded.
|
|
666
|
+
*/
|
|
667
|
+
interface RelayServerOptions {
|
|
668
|
+
/** Optional relay identity for peer_list_request handling */
|
|
669
|
+
identity?: {
|
|
670
|
+
publicKey: string;
|
|
671
|
+
privateKey: string;
|
|
672
|
+
};
|
|
673
|
+
/** Public keys that should have messages stored when offline */
|
|
674
|
+
storagePeers?: string[];
|
|
675
|
+
/** Directory for persisting messages for storage peers */
|
|
676
|
+
storageDir?: string;
|
|
677
|
+
}
|
|
678
|
+
declare class RelayServer extends EventEmitter {
|
|
679
|
+
private wss;
|
|
680
|
+
private agents;
|
|
681
|
+
private identity?;
|
|
682
|
+
private storagePeers;
|
|
683
|
+
private store;
|
|
684
|
+
constructor(options?: {
|
|
685
|
+
publicKey: string;
|
|
686
|
+
privateKey: string;
|
|
687
|
+
} | RelayServerOptions);
|
|
688
|
+
/**
|
|
689
|
+
* Start the relay server
|
|
690
|
+
* @param port - Port to listen on
|
|
691
|
+
* @param host - Optional host (default: all interfaces)
|
|
692
|
+
*/
|
|
693
|
+
start(port: number, host?: string): Promise<void>;
|
|
694
|
+
/**
|
|
695
|
+
* Stop the relay server
|
|
696
|
+
*/
|
|
697
|
+
stop(): Promise<void>;
|
|
698
|
+
/**
|
|
699
|
+
* Get all connected agents
|
|
700
|
+
*/
|
|
701
|
+
getAgents(): Map<string, ConnectedAgent>;
|
|
702
|
+
/**
|
|
703
|
+
* Handle incoming connection
|
|
704
|
+
*/
|
|
705
|
+
private handleConnection;
|
|
706
|
+
/**
|
|
707
|
+
* Send an error message to a client
|
|
708
|
+
*/
|
|
709
|
+
private sendError;
|
|
710
|
+
/**
|
|
711
|
+
* Broadcast a peer event to all connected agents
|
|
712
|
+
*/
|
|
713
|
+
private broadcastPeerEvent;
|
|
714
|
+
/**
|
|
715
|
+
* Handle peer list request from an agent
|
|
716
|
+
*/
|
|
717
|
+
private handlePeerListRequest;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Messages sent from client to relay server
|
|
722
|
+
*/
|
|
723
|
+
interface RelayClientMessage {
|
|
724
|
+
type: 'register' | 'message' | 'broadcast' | 'ping';
|
|
725
|
+
publicKey?: string;
|
|
726
|
+
name?: string;
|
|
727
|
+
to?: string;
|
|
728
|
+
envelope?: Envelope;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Messages received from relay server
|
|
732
|
+
*/
|
|
733
|
+
interface RelayServerMessage {
|
|
734
|
+
type: 'registered' | 'message' | 'error' | 'pong' | 'peer_online' | 'peer_offline';
|
|
735
|
+
publicKey?: string;
|
|
736
|
+
name?: string;
|
|
737
|
+
from?: string;
|
|
738
|
+
envelope?: Envelope;
|
|
739
|
+
peers?: Array<{
|
|
740
|
+
publicKey: string;
|
|
741
|
+
name?: string;
|
|
742
|
+
}>;
|
|
743
|
+
code?: string;
|
|
744
|
+
message?: string;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Peer presence information
|
|
748
|
+
*/
|
|
749
|
+
interface RelayPeer {
|
|
750
|
+
publicKey: string;
|
|
751
|
+
name?: string;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Configuration for RelayClient
|
|
756
|
+
*/
|
|
757
|
+
interface RelayClientConfig {
|
|
758
|
+
/** WebSocket URL of the relay server */
|
|
759
|
+
relayUrl: string;
|
|
760
|
+
/** Agent's public key */
|
|
761
|
+
publicKey: string;
|
|
762
|
+
/** Agent's private key (for signing) */
|
|
763
|
+
privateKey: string;
|
|
764
|
+
/** Optional name for this agent */
|
|
765
|
+
name?: string;
|
|
766
|
+
/** Keepalive ping interval in milliseconds (default: 30000) */
|
|
767
|
+
pingInterval?: number;
|
|
768
|
+
/** Maximum reconnection delay in milliseconds (default: 60000) */
|
|
769
|
+
maxReconnectDelay?: number;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Events emitted by RelayClient
|
|
773
|
+
*/
|
|
774
|
+
interface RelayClientEvents {
|
|
775
|
+
/** Emitted when successfully connected and registered */
|
|
776
|
+
'connected': () => void;
|
|
777
|
+
/** Emitted when disconnected from relay */
|
|
778
|
+
'disconnected': () => void;
|
|
779
|
+
/** Emitted when a verified message is received */
|
|
780
|
+
'message': (envelope: Envelope, from: string, fromName?: string) => void;
|
|
781
|
+
/** Emitted when a peer comes online */
|
|
782
|
+
'peer_online': (peer: RelayPeer) => void;
|
|
783
|
+
/** Emitted when a peer goes offline */
|
|
784
|
+
'peer_offline': (peer: RelayPeer) => void;
|
|
785
|
+
/** Emitted on errors */
|
|
786
|
+
'error': (error: Error) => void;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Persistent WebSocket client for the Agora relay server.
|
|
790
|
+
* Maintains a long-lived connection, handles reconnection, and routes messages.
|
|
791
|
+
*/
|
|
792
|
+
declare class RelayClient extends EventEmitter {
|
|
793
|
+
private ws;
|
|
794
|
+
private config;
|
|
795
|
+
private reconnectAttempts;
|
|
796
|
+
private reconnectTimeout;
|
|
797
|
+
private pingInterval;
|
|
798
|
+
private isConnected;
|
|
799
|
+
private isRegistered;
|
|
800
|
+
private shouldReconnect;
|
|
801
|
+
private onlinePeers;
|
|
802
|
+
constructor(config: RelayClientConfig);
|
|
803
|
+
/**
|
|
804
|
+
* Connect to the relay server
|
|
805
|
+
*/
|
|
806
|
+
connect(): Promise<void>;
|
|
807
|
+
/**
|
|
808
|
+
* Disconnect from the relay server
|
|
809
|
+
*/
|
|
810
|
+
disconnect(): void;
|
|
811
|
+
/**
|
|
812
|
+
* Check if currently connected and registered
|
|
813
|
+
*/
|
|
814
|
+
connected(): boolean;
|
|
815
|
+
/**
|
|
816
|
+
* Send a message to a specific peer
|
|
817
|
+
*/
|
|
818
|
+
send(to: string, envelope: Envelope): Promise<{
|
|
819
|
+
ok: boolean;
|
|
820
|
+
error?: string;
|
|
821
|
+
}>;
|
|
822
|
+
/**
|
|
823
|
+
* Broadcast a message to all connected peers
|
|
824
|
+
*/
|
|
825
|
+
broadcast(envelope: Envelope): Promise<{
|
|
826
|
+
ok: boolean;
|
|
827
|
+
error?: string;
|
|
828
|
+
}>;
|
|
829
|
+
/**
|
|
830
|
+
* Get list of currently online peers
|
|
831
|
+
*/
|
|
832
|
+
getOnlinePeers(): RelayPeer[];
|
|
833
|
+
/**
|
|
834
|
+
* Check if a specific peer is online
|
|
835
|
+
*/
|
|
836
|
+
isPeerOnline(publicKey: string): boolean;
|
|
837
|
+
/**
|
|
838
|
+
* Internal: Perform connection
|
|
839
|
+
*/
|
|
840
|
+
private doConnect;
|
|
841
|
+
/**
|
|
842
|
+
* Handle incoming message from relay
|
|
843
|
+
*/
|
|
844
|
+
private handleMessage;
|
|
845
|
+
/**
|
|
846
|
+
* Schedule reconnection with exponential backoff
|
|
847
|
+
*/
|
|
848
|
+
private scheduleReconnect;
|
|
849
|
+
/**
|
|
850
|
+
* Start periodic ping messages
|
|
851
|
+
*/
|
|
852
|
+
private startPingInterval;
|
|
853
|
+
/**
|
|
854
|
+
* Stop ping interval
|
|
855
|
+
*/
|
|
856
|
+
private stopPingInterval;
|
|
857
|
+
/**
|
|
858
|
+
* Cleanup resources
|
|
859
|
+
*/
|
|
860
|
+
private cleanup;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* message-buffer.ts — In-memory bounded message queue per agent.
|
|
865
|
+
*
|
|
866
|
+
* When messages are delivered to an agent via the relay, they are also
|
|
867
|
+
* stored here so that HTTP polling clients can retrieve them via GET /v1/messages.
|
|
868
|
+
*/
|
|
869
|
+
interface BufferedMessage {
|
|
870
|
+
id: string;
|
|
871
|
+
from: string;
|
|
872
|
+
fromName?: string;
|
|
873
|
+
type: string;
|
|
874
|
+
payload: unknown;
|
|
875
|
+
timestamp: number;
|
|
876
|
+
inReplyTo?: string;
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* MessageBuffer stores inbound messages per agent public key.
|
|
880
|
+
* FIFO eviction when the buffer is full (max 100 messages).
|
|
881
|
+
*/
|
|
882
|
+
declare class MessageBuffer {
|
|
883
|
+
private buffers;
|
|
884
|
+
/**
|
|
885
|
+
* Add a message to an agent's buffer.
|
|
886
|
+
* Evicts the oldest message if the buffer is full.
|
|
887
|
+
*/
|
|
888
|
+
add(publicKey: string, message: BufferedMessage): void;
|
|
889
|
+
/**
|
|
890
|
+
* Retrieve messages for an agent, optionally filtering by `since` timestamp.
|
|
891
|
+
* Returns messages with timestamp > since (exclusive).
|
|
892
|
+
*/
|
|
893
|
+
get(publicKey: string, since?: number): BufferedMessage[];
|
|
894
|
+
/**
|
|
895
|
+
* Clear all messages for an agent (after polling without `since`).
|
|
896
|
+
*/
|
|
897
|
+
clear(publicKey: string): void;
|
|
898
|
+
/**
|
|
899
|
+
* Remove all state for a disconnected agent.
|
|
900
|
+
*/
|
|
901
|
+
delete(publicKey: string): void;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* store.ts — File-based message store for offline peers.
|
|
906
|
+
* When the relay has storage enabled for certain public keys, messages
|
|
907
|
+
* for offline recipients are persisted and delivered when they connect.
|
|
908
|
+
*/
|
|
909
|
+
interface StoredMessage {
|
|
910
|
+
from: string;
|
|
911
|
+
name?: string;
|
|
912
|
+
envelope: object;
|
|
913
|
+
}
|
|
914
|
+
declare class MessageStore {
|
|
915
|
+
private storageDir;
|
|
916
|
+
constructor(storageDir: string);
|
|
917
|
+
private recipientDir;
|
|
918
|
+
save(recipientKey: string, message: StoredMessage): void;
|
|
919
|
+
load(recipientKey: string): StoredMessage[];
|
|
920
|
+
clear(recipientKey: string): void;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* jwt-auth.ts — JWT token creation and validation middleware.
|
|
925
|
+
*
|
|
926
|
+
* Tokens are signed with AGORA_RELAY_JWT_SECRET (required env var).
|
|
927
|
+
* Expiry defaults to 3600 seconds (1 hour), configurable via AGORA_JWT_EXPIRY_SECONDS.
|
|
928
|
+
*
|
|
929
|
+
* Token payload: { publicKey, name }
|
|
930
|
+
*/
|
|
931
|
+
|
|
932
|
+
interface JwtPayload {
|
|
933
|
+
publicKey: string;
|
|
934
|
+
name?: string;
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Augment Express Request to carry decoded JWT payload.
|
|
938
|
+
*/
|
|
939
|
+
interface AuthenticatedRequest extends Request {
|
|
940
|
+
agent?: JwtPayload;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Create a signed JWT for a registered agent.
|
|
944
|
+
* Returns the token string and its expiry timestamp (ms since epoch).
|
|
945
|
+
*/
|
|
946
|
+
declare function createToken(payload: JwtPayload): {
|
|
947
|
+
token: string;
|
|
948
|
+
expiresAt: number;
|
|
949
|
+
};
|
|
950
|
+
/**
|
|
951
|
+
* Revoke a token by its jti claim so it cannot be used again.
|
|
952
|
+
* The revocation entry is stored with the token's expiry so it can be
|
|
953
|
+
* pruned automatically once the token would no longer be valid anyway.
|
|
954
|
+
*/
|
|
955
|
+
declare function revokeToken(token: string): void;
|
|
956
|
+
/**
|
|
957
|
+
* Express middleware that validates the Authorization: Bearer <token> header.
|
|
958
|
+
* Attaches decoded payload to `req.agent` on success.
|
|
959
|
+
* Responds with 401 if missing/invalid/expired/revoked.
|
|
960
|
+
*/
|
|
961
|
+
declare function requireAuth(req: AuthenticatedRequest, res: Response, next: NextFunction): void;
|
|
962
|
+
|
|
963
|
+
/**
|
|
964
|
+
* rest-api.ts — Express router implementing the Agora relay REST API.
|
|
965
|
+
*
|
|
966
|
+
* Endpoints:
|
|
967
|
+
* POST /v1/register — Register agent, obtain JWT session token
|
|
968
|
+
* POST /v1/send — Send message to a peer (requires auth)
|
|
969
|
+
* GET /v1/peers — List online peers (requires auth)
|
|
970
|
+
* GET /v1/messages — Poll for new inbound messages (requires auth)
|
|
971
|
+
* DELETE /v1/disconnect — Invalidate token and disconnect (requires auth)
|
|
972
|
+
*/
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* A session for a REST-connected agent.
|
|
976
|
+
* privateKey is held only in memory and never logged or persisted.
|
|
977
|
+
*/
|
|
978
|
+
interface RestSession {
|
|
979
|
+
publicKey: string;
|
|
980
|
+
privateKey: string;
|
|
981
|
+
name?: string;
|
|
982
|
+
metadata?: {
|
|
983
|
+
version?: string;
|
|
984
|
+
capabilities?: string[];
|
|
985
|
+
};
|
|
986
|
+
registeredAt: number;
|
|
987
|
+
expiresAt: number;
|
|
988
|
+
token: string;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Minimal interface for the relay server that the REST API depends on.
|
|
992
|
+
*/
|
|
993
|
+
interface RelayInterface {
|
|
994
|
+
getAgents(): Map<string, {
|
|
995
|
+
publicKey: string;
|
|
996
|
+
name?: string;
|
|
997
|
+
lastSeen: number;
|
|
998
|
+
metadata?: {
|
|
999
|
+
version?: string;
|
|
1000
|
+
capabilities?: string[];
|
|
1001
|
+
};
|
|
1002
|
+
socket: unknown;
|
|
1003
|
+
}>;
|
|
1004
|
+
on(event: 'message-relayed', handler: (from: string, to: string, envelope: unknown) => void): void;
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Envelope creation function interface (matches createEnvelope from message/envelope).
|
|
1008
|
+
*/
|
|
1009
|
+
type CreateEnvelopeFn = (type: string, sender: string, privateKey: string, payload: unknown, timestamp?: number, inReplyTo?: string) => {
|
|
1010
|
+
id: string;
|
|
1011
|
+
type: string;
|
|
1012
|
+
sender: string;
|
|
1013
|
+
timestamp: number;
|
|
1014
|
+
payload: unknown;
|
|
1015
|
+
signature: string;
|
|
1016
|
+
inReplyTo?: string;
|
|
1017
|
+
};
|
|
1018
|
+
/**
|
|
1019
|
+
* Envelope verification function interface.
|
|
1020
|
+
*/
|
|
1021
|
+
type VerifyEnvelopeFn = (envelope: unknown) => {
|
|
1022
|
+
valid: boolean;
|
|
1023
|
+
reason?: string;
|
|
1024
|
+
};
|
|
1025
|
+
/**
|
|
1026
|
+
* Create the REST API router.
|
|
1027
|
+
*/
|
|
1028
|
+
declare function createRestRouter(relay: RelayInterface, buffer: MessageBuffer, sessions: Map<string, RestSession>, createEnv: CreateEnvelopeFn, verifyEnv: VerifyEnvelopeFn): Router;
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* run-relay.ts — Start Agora relay: WebSocket server and optional REST API.
|
|
1032
|
+
*
|
|
1033
|
+
* When REST is enabled, starts:
|
|
1034
|
+
* 1. WebSocket relay (RelayServer) on wsPort
|
|
1035
|
+
* 2. REST API server (Express) on restPort (default wsPort + 1)
|
|
1036
|
+
*
|
|
1037
|
+
* Environment variables (when REST enabled):
|
|
1038
|
+
* AGORA_RELAY_JWT_SECRET — Required for REST (JWT signing)
|
|
1039
|
+
* AGORA_JWT_EXPIRY_SECONDS — JWT expiry in seconds (default: 3600)
|
|
1040
|
+
* PORT — WebSocket port (default: 3001); REST uses PORT+1
|
|
1041
|
+
*/
|
|
1042
|
+
|
|
1043
|
+
interface RunRelayOptions {
|
|
1044
|
+
/** WebSocket port (default from PORT env or 3001) */
|
|
1045
|
+
wsPort?: number;
|
|
1046
|
+
/** REST API port (default: wsPort + 1). Ignored if enableRest is false. */
|
|
1047
|
+
restPort?: number;
|
|
1048
|
+
/** Enable REST API (requires AGORA_RELAY_JWT_SECRET). Default: true if AGORA_RELAY_JWT_SECRET is set. */
|
|
1049
|
+
enableRest?: boolean;
|
|
1050
|
+
/** Relay server options (identity, storagePeers, storageDir) */
|
|
1051
|
+
relayOptions?: RelayServerOptions;
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Start WebSocket relay and optionally REST API.
|
|
1055
|
+
* Returns { relay, httpServer } where httpServer is set only when REST is enabled.
|
|
1056
|
+
*/
|
|
1057
|
+
declare function runRelay(options?: RunRelayOptions): Promise<{
|
|
1058
|
+
relay: RelayServer;
|
|
1059
|
+
httpServer?: http.Server;
|
|
1060
|
+
}>;
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* Get a short display version of a public key using the last 8 characters.
|
|
1064
|
+
* Ed25519 public keys all share the same OID prefix, so the last 8 characters
|
|
1065
|
+
* are more distinguishable than the first 8.
|
|
1066
|
+
*
|
|
1067
|
+
* @param publicKey - The full public key hex string
|
|
1068
|
+
* @returns "..." followed by the last 8 characters of the key
|
|
1069
|
+
*/
|
|
1070
|
+
declare function shortKey(publicKey: string): string;
|
|
1071
|
+
/**
|
|
1072
|
+
* Resolves the name to broadcast when connecting to a relay.
|
|
1073
|
+
* Priority order:
|
|
1074
|
+
* 1. CLI --name flag
|
|
1075
|
+
* 2. config.relay.name (if relay is an object with name property)
|
|
1076
|
+
* 3. config.identity.name
|
|
1077
|
+
* 4. undefined (no name broadcast)
|
|
1078
|
+
*
|
|
1079
|
+
* @param config - The Agora configuration (or compatible config with identity and optional relay)
|
|
1080
|
+
* @param cliName - Optional name from CLI --name flag
|
|
1081
|
+
* @returns The resolved name to broadcast, or undefined if none available
|
|
1082
|
+
*/
|
|
1083
|
+
declare function resolveBroadcastName(config: {
|
|
1084
|
+
identity: {
|
|
1085
|
+
name?: string;
|
|
1086
|
+
};
|
|
1087
|
+
relay?: {
|
|
1088
|
+
name?: string;
|
|
1089
|
+
} | string;
|
|
1090
|
+
}, cliName?: string): string | undefined;
|
|
1091
|
+
/**
|
|
1092
|
+
* Formats a display name with short ID postfix.
|
|
1093
|
+
* If name exists: "name (...3f8c2247)"
|
|
1094
|
+
* If no name: "...3f8c2247" (short ID only)
|
|
1095
|
+
*
|
|
1096
|
+
* @param name - Optional name to display (should not be a short ID)
|
|
1097
|
+
* @param publicKey - The public key to use for short ID
|
|
1098
|
+
* @returns Formatted display string
|
|
1099
|
+
*/
|
|
1100
|
+
declare function formatDisplayName(name: string | undefined, publicKey: string): string;
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Service config: identity, peers keyed by name, optional relay.
|
|
1104
|
+
*/
|
|
1105
|
+
interface AgoraServiceConfig {
|
|
1106
|
+
identity: AgoraIdentity;
|
|
1107
|
+
peers: Map<string, PeerConfig>;
|
|
1108
|
+
relay?: RelayConfig;
|
|
1109
|
+
}
|
|
1110
|
+
interface SendMessageOptions {
|
|
1111
|
+
peerName: string;
|
|
1112
|
+
type: MessageType;
|
|
1113
|
+
payload: unknown;
|
|
1114
|
+
inReplyTo?: string;
|
|
1115
|
+
}
|
|
1116
|
+
interface SendMessageResult {
|
|
1117
|
+
ok: boolean;
|
|
1118
|
+
status: number;
|
|
1119
|
+
error?: string;
|
|
1120
|
+
}
|
|
1121
|
+
interface DecodeInboundResult {
|
|
1122
|
+
ok: boolean;
|
|
1123
|
+
envelope?: Envelope;
|
|
1124
|
+
reason?: string;
|
|
1125
|
+
}
|
|
1126
|
+
type RelayMessageHandler = (envelope: Envelope) => void;
|
|
1127
|
+
type RelayMessageHandlerWithName = (envelope: Envelope, from: string, fromName?: string) => void;
|
|
1128
|
+
interface Logger {
|
|
1129
|
+
debug(message: string): void;
|
|
1130
|
+
}
|
|
1131
|
+
interface RelayClientLike {
|
|
1132
|
+
connect(): Promise<void>;
|
|
1133
|
+
disconnect(): void;
|
|
1134
|
+
connected(): boolean;
|
|
1135
|
+
send(to: string, envelope: Envelope): Promise<{
|
|
1136
|
+
ok: boolean;
|
|
1137
|
+
error?: string;
|
|
1138
|
+
}>;
|
|
1139
|
+
on(event: 'message', handler: (envelope: Envelope, from: string, fromName?: string) => void): void;
|
|
1140
|
+
on(event: 'error', handler: (error: Error) => void): void;
|
|
1141
|
+
}
|
|
1142
|
+
interface RelayClientFactory {
|
|
1143
|
+
(opts: {
|
|
1144
|
+
relayUrl: string;
|
|
1145
|
+
publicKey: string;
|
|
1146
|
+
privateKey: string;
|
|
1147
|
+
name?: string;
|
|
1148
|
+
pingInterval: number;
|
|
1149
|
+
maxReconnectDelay: number;
|
|
1150
|
+
}): RelayClientLike;
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* High-level Agora service: send by peer name, decode inbound, relay lifecycle.
|
|
1154
|
+
*/
|
|
1155
|
+
declare class AgoraService {
|
|
1156
|
+
private config;
|
|
1157
|
+
private relayClient;
|
|
1158
|
+
private relayMessageHandler;
|
|
1159
|
+
private relayMessageHandlerWithName;
|
|
1160
|
+
private logger;
|
|
1161
|
+
private relayClientFactory;
|
|
1162
|
+
constructor(config: AgoraServiceConfig, logger?: Logger, relayClientFactory?: RelayClientFactory);
|
|
1163
|
+
/**
|
|
1164
|
+
* Send a signed message to a named peer.
|
|
1165
|
+
* Tries HTTP webhook first; falls back to relay if HTTP is unavailable.
|
|
1166
|
+
*/
|
|
1167
|
+
sendMessage(options: SendMessageOptions): Promise<SendMessageResult>;
|
|
1168
|
+
/**
|
|
1169
|
+
* Decode and verify an inbound envelope from a webhook message.
|
|
1170
|
+
*/
|
|
1171
|
+
decodeInbound(message: string): Promise<DecodeInboundResult>;
|
|
1172
|
+
getPeers(): string[];
|
|
1173
|
+
getPeerConfig(name: string): PeerConfig | undefined;
|
|
1174
|
+
/**
|
|
1175
|
+
* Connect to the relay server.
|
|
1176
|
+
*/
|
|
1177
|
+
connectRelay(url: string): Promise<void>;
|
|
1178
|
+
setRelayMessageHandler(handler: RelayMessageHandler): void;
|
|
1179
|
+
setRelayMessageHandlerWithName(handler: RelayMessageHandlerWithName): void;
|
|
1180
|
+
disconnectRelay(): Promise<void>;
|
|
1181
|
+
isRelayConnected(): boolean;
|
|
1182
|
+
/**
|
|
1183
|
+
* Load Agora configuration and return service config (peers as Map).
|
|
1184
|
+
*/
|
|
1185
|
+
static loadConfig(path?: string): Promise<AgoraServiceConfig>;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* Configuration for PeerDiscoveryService
|
|
1190
|
+
*/
|
|
1191
|
+
interface PeerDiscoveryConfig {
|
|
1192
|
+
/** Agent's public key */
|
|
1193
|
+
publicKey: string;
|
|
1194
|
+
/** Agent's private key for signing */
|
|
1195
|
+
privateKey: string;
|
|
1196
|
+
/** RelayClient instance for communication */
|
|
1197
|
+
relayClient: RelayClient;
|
|
1198
|
+
/** Public key of the relay server (for sending peer list requests) */
|
|
1199
|
+
relayPublicKey?: string;
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Events emitted by PeerDiscoveryService
|
|
1203
|
+
*/
|
|
1204
|
+
interface PeerDiscoveryEvents {
|
|
1205
|
+
/** Emitted when peers are discovered */
|
|
1206
|
+
'peers-discovered': (peers: PeerListResponsePayload['peers']) => void;
|
|
1207
|
+
/** Emitted when a peer referral is received */
|
|
1208
|
+
'peer-referral': (referral: PeerReferralPayload, from: string) => void;
|
|
1209
|
+
/** Emitted on errors */
|
|
1210
|
+
'error': (error: Error) => void;
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Service for discovering peers on the Agora network
|
|
1214
|
+
*/
|
|
1215
|
+
declare class PeerDiscoveryService extends EventEmitter {
|
|
1216
|
+
private config;
|
|
1217
|
+
constructor(config: PeerDiscoveryConfig);
|
|
1218
|
+
/**
|
|
1219
|
+
* Request peer list from relay
|
|
1220
|
+
*/
|
|
1221
|
+
discoverViaRelay(filters?: PeerListRequestPayload['filters']): Promise<PeerListResponsePayload | null>;
|
|
1222
|
+
/**
|
|
1223
|
+
* Send peer referral to another agent
|
|
1224
|
+
*/
|
|
1225
|
+
referPeer(recipientPublicKey: string, referredPublicKey: string, metadata?: {
|
|
1226
|
+
name?: string;
|
|
1227
|
+
endpoint?: string;
|
|
1228
|
+
comment?: string;
|
|
1229
|
+
trustScore?: number;
|
|
1230
|
+
}): Promise<{
|
|
1231
|
+
ok: boolean;
|
|
1232
|
+
error?: string;
|
|
1233
|
+
}>;
|
|
1234
|
+
/**
|
|
1235
|
+
* Handle incoming peer referral
|
|
1236
|
+
*/
|
|
1237
|
+
private handleReferral;
|
|
1238
|
+
/**
|
|
1239
|
+
* Handle incoming peer list from relay
|
|
1240
|
+
*/
|
|
1241
|
+
private handlePeerList;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* Bootstrap configuration for peer discovery on the Agora network.
|
|
1246
|
+
* Provides default bootstrap relays for initial network entry.
|
|
1247
|
+
*/
|
|
1248
|
+
/**
|
|
1249
|
+
* Default bootstrap relay servers
|
|
1250
|
+
* These are well-known relays that serve as initial entry points to the network
|
|
1251
|
+
*/
|
|
1252
|
+
declare const DEFAULT_BOOTSTRAP_RELAYS: {
|
|
1253
|
+
url: string;
|
|
1254
|
+
name: string;
|
|
1255
|
+
}[];
|
|
1256
|
+
/**
|
|
1257
|
+
* Configuration for bootstrap connection
|
|
1258
|
+
*/
|
|
1259
|
+
interface BootstrapConfig {
|
|
1260
|
+
/** Bootstrap relay URL */
|
|
1261
|
+
relayUrl: string;
|
|
1262
|
+
/** Optional relay public key (for verification) */
|
|
1263
|
+
relayPublicKey?: string;
|
|
1264
|
+
/** Connection timeout in ms (default: 10000) */
|
|
1265
|
+
timeout?: number;
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Get default bootstrap relay configuration
|
|
1269
|
+
*/
|
|
1270
|
+
declare function getDefaultBootstrapRelay(): BootstrapConfig;
|
|
1271
|
+
/**
|
|
1272
|
+
* Parse bootstrap relay URL and optional public key
|
|
1273
|
+
*/
|
|
1274
|
+
declare function parseBootstrapRelay(url: string, publicKey?: string): BootstrapConfig;
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* Core data structures for the Agora reputation layer.
|
|
1278
|
+
* Phase 1: Verification records, commit-reveal patterns, and trust scoring.
|
|
1279
|
+
*/
|
|
1280
|
+
/**
|
|
1281
|
+
* A cryptographically signed verification of another agent's output or claim.
|
|
1282
|
+
* Core primitive for building computational reputation.
|
|
1283
|
+
*/
|
|
1284
|
+
interface VerificationRecord {
|
|
1285
|
+
/** Content-addressed ID (hash of canonical JSON) */
|
|
1286
|
+
id: string;
|
|
1287
|
+
/** Public key of verifying agent */
|
|
1288
|
+
verifier: string;
|
|
1289
|
+
/** ID of message/output being verified */
|
|
1290
|
+
target: string;
|
|
1291
|
+
/** Capability domain (e.g., 'ocr', 'summarization', 'code_review') */
|
|
1292
|
+
domain: string;
|
|
1293
|
+
/** Verification verdict */
|
|
1294
|
+
verdict: 'correct' | 'incorrect' | 'disputed';
|
|
1295
|
+
/** Verifier's confidence in their check (0-1) */
|
|
1296
|
+
confidence: number;
|
|
1297
|
+
/** Optional link to independent verification data */
|
|
1298
|
+
evidence?: string;
|
|
1299
|
+
/** Unix timestamp (ms) */
|
|
1300
|
+
timestamp: number;
|
|
1301
|
+
/** Ed25519 signature over canonical JSON */
|
|
1302
|
+
signature: string;
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* A commitment to a prediction before outcome is known.
|
|
1306
|
+
* Prevents post-hoc editing of predictions.
|
|
1307
|
+
*/
|
|
1308
|
+
interface CommitRecord {
|
|
1309
|
+
/** Content-addressed ID */
|
|
1310
|
+
id: string;
|
|
1311
|
+
/** Public key of committing agent */
|
|
1312
|
+
agent: string;
|
|
1313
|
+
/** Domain of prediction */
|
|
1314
|
+
domain: string;
|
|
1315
|
+
/** SHA-256 hash of prediction string */
|
|
1316
|
+
commitment: string;
|
|
1317
|
+
/** Unix timestamp (ms) */
|
|
1318
|
+
timestamp: number;
|
|
1319
|
+
/** Expiry time (ms) - commitment invalid after this */
|
|
1320
|
+
expiry: number;
|
|
1321
|
+
/** Ed25519 signature */
|
|
1322
|
+
signature: string;
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* Reveals the prediction and outcome after commitment expiry.
|
|
1326
|
+
* Enables verification of prediction accuracy.
|
|
1327
|
+
*/
|
|
1328
|
+
interface RevealRecord {
|
|
1329
|
+
/** Content-addressed ID */
|
|
1330
|
+
id: string;
|
|
1331
|
+
/** Public key of revealing agent */
|
|
1332
|
+
agent: string;
|
|
1333
|
+
/** ID of original commit message */
|
|
1334
|
+
commitmentId: string;
|
|
1335
|
+
/** Original prediction (plaintext) */
|
|
1336
|
+
prediction: string;
|
|
1337
|
+
/** Observed outcome */
|
|
1338
|
+
outcome: string;
|
|
1339
|
+
/** Evidence for outcome (optional) */
|
|
1340
|
+
evidence?: string;
|
|
1341
|
+
/** Unix timestamp (ms) */
|
|
1342
|
+
timestamp: number;
|
|
1343
|
+
/** Ed25519 signature */
|
|
1344
|
+
signature: string;
|
|
1345
|
+
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Computed reputation score for an agent in a specific domain.
|
|
1348
|
+
* Derived from verification history, not stored directly.
|
|
1349
|
+
*/
|
|
1350
|
+
interface TrustScore {
|
|
1351
|
+
/** Public key of agent being scored */
|
|
1352
|
+
agent: string;
|
|
1353
|
+
/** Domain of reputation */
|
|
1354
|
+
domain: string;
|
|
1355
|
+
/** Computed score (0-1, where 1 = highest trust) */
|
|
1356
|
+
score: number;
|
|
1357
|
+
/** Number of verifications considered */
|
|
1358
|
+
verificationCount: number;
|
|
1359
|
+
/** Timestamp of most recent verification (ms) */
|
|
1360
|
+
lastVerified: number;
|
|
1361
|
+
/** Public keys of top verifiers (by weight) */
|
|
1362
|
+
topVerifiers: string[];
|
|
1363
|
+
}
|
|
1364
|
+
/**
|
|
1365
|
+
* Request for reputation data about a specific agent.
|
|
1366
|
+
*/
|
|
1367
|
+
interface ReputationQuery {
|
|
1368
|
+
/** Public key of agent being queried */
|
|
1369
|
+
agent: string;
|
|
1370
|
+
/** Optional: filter by capability domain */
|
|
1371
|
+
domain?: string;
|
|
1372
|
+
/** Optional: only include verifications after this timestamp */
|
|
1373
|
+
after?: number;
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Response containing reputation data for a queried agent.
|
|
1377
|
+
*/
|
|
1378
|
+
interface ReputationResponse {
|
|
1379
|
+
/** Public key of agent being reported on */
|
|
1380
|
+
agent: string;
|
|
1381
|
+
/** Domain filter (if requested) */
|
|
1382
|
+
domain?: string;
|
|
1383
|
+
/** Verification records matching the query */
|
|
1384
|
+
verifications: VerificationRecord[];
|
|
1385
|
+
/** Computed trust scores by domain */
|
|
1386
|
+
scores: Record<string, TrustScore>;
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* Revocation of a previously issued verification.
|
|
1390
|
+
* Used when a verifier discovers their verification was incorrect.
|
|
1391
|
+
*/
|
|
1392
|
+
interface RevocationRecord {
|
|
1393
|
+
/** Content-addressed ID of this revocation */
|
|
1394
|
+
id: string;
|
|
1395
|
+
/** Public key of agent revoking (must match original verifier) */
|
|
1396
|
+
verifier: string;
|
|
1397
|
+
/** ID of verification being revoked */
|
|
1398
|
+
verificationId: string;
|
|
1399
|
+
/** Reason for revocation */
|
|
1400
|
+
reason: string;
|
|
1401
|
+
/** Unix timestamp (ms) */
|
|
1402
|
+
timestamp: number;
|
|
1403
|
+
/** Ed25519 signature */
|
|
1404
|
+
signature: string;
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Validation result structure
|
|
1408
|
+
*/
|
|
1409
|
+
interface ValidationResult {
|
|
1410
|
+
valid: boolean;
|
|
1411
|
+
errors: string[];
|
|
1412
|
+
}
|
|
1413
|
+
/**
|
|
1414
|
+
* Validate a verification record structure
|
|
1415
|
+
*/
|
|
1416
|
+
declare function validateVerificationRecord(record: unknown): ValidationResult;
|
|
1417
|
+
/**
|
|
1418
|
+
* Validate a commit record structure
|
|
1419
|
+
*/
|
|
1420
|
+
declare function validateCommitRecord(record: unknown): ValidationResult;
|
|
1421
|
+
/**
|
|
1422
|
+
* Validate a reveal record structure
|
|
1423
|
+
*/
|
|
1424
|
+
declare function validateRevealRecord(record: unknown): ValidationResult;
|
|
1425
|
+
|
|
1426
|
+
/**
|
|
1427
|
+
* Verification record creation and validation.
|
|
1428
|
+
* Core primitive for computational reputation.
|
|
1429
|
+
*/
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* Create a signed verification record
|
|
1433
|
+
* @param verifier - Public key of the verifying agent
|
|
1434
|
+
* @param privateKey - Private key for signing
|
|
1435
|
+
* @param target - ID of the message/output being verified
|
|
1436
|
+
* @param domain - Capability domain
|
|
1437
|
+
* @param verdict - Verification verdict
|
|
1438
|
+
* @param confidence - Verifier's confidence (0-1)
|
|
1439
|
+
* @param timestamp - Timestamp for the verification (ms)
|
|
1440
|
+
* @param evidence - Optional link to verification evidence
|
|
1441
|
+
* @returns Signed VerificationRecord
|
|
1442
|
+
*/
|
|
1443
|
+
declare function createVerification(verifier: string, privateKey: string, target: string, domain: string, verdict: 'correct' | 'incorrect' | 'disputed', confidence: number, timestamp: number, evidence?: string): VerificationRecord;
|
|
1444
|
+
/**
|
|
1445
|
+
* Verify the cryptographic signature of a verification record
|
|
1446
|
+
* @param record - The verification record to verify
|
|
1447
|
+
* @returns Object with valid flag and optional reason for failure
|
|
1448
|
+
*/
|
|
1449
|
+
declare function verifyVerificationSignature(record: VerificationRecord): {
|
|
1450
|
+
valid: boolean;
|
|
1451
|
+
reason?: string;
|
|
1452
|
+
};
|
|
1453
|
+
|
|
1454
|
+
/**
|
|
1455
|
+
* Commit-reveal pattern implementation for tamper-proof predictions.
|
|
1456
|
+
* Agents commit to predictions before outcomes are known, then reveal after.
|
|
1457
|
+
*/
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* Create a commitment hash for a prediction
|
|
1461
|
+
* @param prediction - The prediction string
|
|
1462
|
+
* @returns SHA-256 hash of the prediction (hex string)
|
|
1463
|
+
*/
|
|
1464
|
+
declare function hashPrediction(prediction: string): string;
|
|
1465
|
+
/**
|
|
1466
|
+
* Create a signed commit record
|
|
1467
|
+
* @param agent - Public key of the committing agent
|
|
1468
|
+
* @param privateKey - Private key for signing
|
|
1469
|
+
* @param domain - Domain of the prediction
|
|
1470
|
+
* @param prediction - The prediction to commit to
|
|
1471
|
+
* @param timestamp - Timestamp for the commit (ms)
|
|
1472
|
+
* @param expiryMs - Expiry time in milliseconds from timestamp
|
|
1473
|
+
* @returns Signed CommitRecord
|
|
1474
|
+
*/
|
|
1475
|
+
declare function createCommit(agent: string, privateKey: string, domain: string, prediction: string, timestamp: number, expiryMs: number): CommitRecord;
|
|
1476
|
+
/**
|
|
1477
|
+
* Create a signed reveal record
|
|
1478
|
+
* @param agent - Public key of the revealing agent
|
|
1479
|
+
* @param privateKey - Private key for signing
|
|
1480
|
+
* @param commitmentId - ID of the original commit record
|
|
1481
|
+
* @param prediction - The original prediction (plaintext)
|
|
1482
|
+
* @param outcome - The observed outcome
|
|
1483
|
+
* @param timestamp - Timestamp for the reveal (ms)
|
|
1484
|
+
* @param evidence - Optional evidence for the outcome
|
|
1485
|
+
* @returns Signed RevealRecord
|
|
1486
|
+
*/
|
|
1487
|
+
declare function createReveal(agent: string, privateKey: string, commitmentId: string, prediction: string, outcome: string, timestamp: number, evidence?: string): RevealRecord;
|
|
1488
|
+
/**
|
|
1489
|
+
* Verify a reveal against its commitment
|
|
1490
|
+
* @param commit - The original commit record
|
|
1491
|
+
* @param reveal - The reveal record
|
|
1492
|
+
* @returns Object with valid flag and optional reason for failure
|
|
1493
|
+
*/
|
|
1494
|
+
declare function verifyReveal(commit: CommitRecord, reveal: RevealRecord): {
|
|
1495
|
+
valid: boolean;
|
|
1496
|
+
reason?: string;
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
/**
|
|
1500
|
+
* Trust score computation with exponential time decay.
|
|
1501
|
+
* Domain-specific reputation scoring from verification history.
|
|
1502
|
+
*/
|
|
1503
|
+
|
|
1504
|
+
/**
|
|
1505
|
+
* Exponential decay function for time-based reputation degradation.
|
|
1506
|
+
* @param deltaTimeMs - Time since verification (milliseconds)
|
|
1507
|
+
* @param lambda - Decay rate (default: ln(2)/70 ≈ 0.0099, giving 70-day half-life)
|
|
1508
|
+
* @returns Weight multiplier (0-1)
|
|
1509
|
+
*/
|
|
1510
|
+
declare function decay(deltaTimeMs: number, lambda?: number): number;
|
|
1511
|
+
/**
|
|
1512
|
+
* Compute trust score for an agent in a specific domain
|
|
1513
|
+
* @param agent - Public key of the agent being scored
|
|
1514
|
+
* @param domain - Capability domain
|
|
1515
|
+
* @param verifications - All verification records (will be filtered by target and domain)
|
|
1516
|
+
* @param currentTime - Current timestamp (ms)
|
|
1517
|
+
* @returns TrustScore object with computed reputation
|
|
1518
|
+
*/
|
|
1519
|
+
declare function computeTrustScore(agent: string, domain: string, verifications: VerificationRecord[], currentTime: number): TrustScore;
|
|
1520
|
+
/**
|
|
1521
|
+
* Compute trust scores for an agent across multiple domains
|
|
1522
|
+
* @param agent - Public key of the agent being scored
|
|
1523
|
+
* @param verifications - All verification records
|
|
1524
|
+
* @param currentTime - Current timestamp (ms)
|
|
1525
|
+
* @returns Map of domain to TrustScore
|
|
1526
|
+
*/
|
|
1527
|
+
declare function computeTrustScores(agent: string, verifications: VerificationRecord[], currentTime: number): Map<string, TrustScore>;
|
|
1528
|
+
declare const computeAllTrustScores: typeof computeTrustScores;
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* Local reputation store using JSONL append-only log.
|
|
1532
|
+
* Stores verification records, commits, and reveals.
|
|
1533
|
+
*/
|
|
1534
|
+
|
|
1535
|
+
/**
|
|
1536
|
+
* Reputation store with JSONL persistence
|
|
1537
|
+
*/
|
|
1538
|
+
declare class ReputationStore {
|
|
1539
|
+
private filePath;
|
|
1540
|
+
private verifications;
|
|
1541
|
+
private commits;
|
|
1542
|
+
private reveals;
|
|
1543
|
+
private loaded;
|
|
1544
|
+
constructor(filePath: string);
|
|
1545
|
+
/**
|
|
1546
|
+
* Load records from JSONL file
|
|
1547
|
+
*/
|
|
1548
|
+
load(): Promise<void>;
|
|
1549
|
+
/**
|
|
1550
|
+
* Ensure the store is loaded
|
|
1551
|
+
*/
|
|
1552
|
+
private ensureLoaded;
|
|
1553
|
+
/**
|
|
1554
|
+
* Append a record to the JSONL file
|
|
1555
|
+
*/
|
|
1556
|
+
private appendToFile;
|
|
1557
|
+
/**
|
|
1558
|
+
* Add a verification record
|
|
1559
|
+
*/
|
|
1560
|
+
addVerification(verification: VerificationRecord): Promise<void>;
|
|
1561
|
+
/**
|
|
1562
|
+
* Add a commit record
|
|
1563
|
+
*/
|
|
1564
|
+
addCommit(commit: CommitRecord): Promise<void>;
|
|
1565
|
+
/**
|
|
1566
|
+
* Add a reveal record
|
|
1567
|
+
*/
|
|
1568
|
+
addReveal(reveal: RevealRecord): Promise<void>;
|
|
1569
|
+
/**
|
|
1570
|
+
* Get all verifications
|
|
1571
|
+
*/
|
|
1572
|
+
getVerifications(): Promise<VerificationRecord[]>;
|
|
1573
|
+
/**
|
|
1574
|
+
* Get verifications for a specific target
|
|
1575
|
+
*/
|
|
1576
|
+
getVerificationsByTarget(target: string): Promise<VerificationRecord[]>;
|
|
1577
|
+
/**
|
|
1578
|
+
* Get verifications by domain
|
|
1579
|
+
*/
|
|
1580
|
+
getVerificationsByDomain(domain: string): Promise<VerificationRecord[]>;
|
|
1581
|
+
/**
|
|
1582
|
+
* Get verifications for an agent (where they are the target of verification)
|
|
1583
|
+
* This requires looking up the target message to find the agent
|
|
1584
|
+
* For now, we'll return all verifications and let the caller filter
|
|
1585
|
+
*/
|
|
1586
|
+
getVerificationsByDomainForAgent(domain: string): Promise<VerificationRecord[]>;
|
|
1587
|
+
/**
|
|
1588
|
+
* Get all commits
|
|
1589
|
+
*/
|
|
1590
|
+
getCommits(): Promise<CommitRecord[]>;
|
|
1591
|
+
/**
|
|
1592
|
+
* Get commit by ID
|
|
1593
|
+
*/
|
|
1594
|
+
getCommit(id: string): Promise<CommitRecord | null>;
|
|
1595
|
+
/**
|
|
1596
|
+
* Get commits by agent
|
|
1597
|
+
*/
|
|
1598
|
+
getCommitsByAgent(agent: string): Promise<CommitRecord[]>;
|
|
1599
|
+
/**
|
|
1600
|
+
* Get all reveals
|
|
1601
|
+
*/
|
|
1602
|
+
getReveals(): Promise<RevealRecord[]>;
|
|
1603
|
+
/**
|
|
1604
|
+
* Get reveal by commitment ID
|
|
1605
|
+
*/
|
|
1606
|
+
getRevealByCommitment(commitmentId: string): Promise<RevealRecord | null>;
|
|
1607
|
+
/**
|
|
1608
|
+
* Get reveals by agent
|
|
1609
|
+
*/
|
|
1610
|
+
getRevealsByAgent(agent: string): Promise<RevealRecord[]>;
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
export { type AgoraConfig, type AgoraIdentity, type AgoraPeerConfig, AgoraService, type AgoraServiceConfig, type AnnouncePayload, type AuthenticatedRequest, type BootstrapConfig, type BufferedMessage, type Capability, type CapabilityAnnouncePayload, type CapabilityQueryPayload, type CapabilityResponsePayload, type CommitRecord, type CreateEnvelopeFn, DEFAULT_BOOTSTRAP_RELAYS, type DecodeInboundResult, type DiscoverPayload, type DiscoverResponsePayload, DiscoveryService, type Envelope, type JwtPayload, type KeyPair, type Logger, MessageBuffer, MessageStore, type MessageType, type PaperDiscoveryPayload, type Peer, type PeerConfig, type PeerConfigFile, type PeerDiscoveryConfig, type PeerDiscoveryEvents, PeerDiscoveryService, type PeerListRequestPayload, type PeerListResponsePayload, type PeerReferralPayload, PeerStore, RelayClient, type RelayClientConfig, type RelayClientEvents, type RelayClientFactory, type RelayClientLike, type RelayClientMessage, type RelayConfig, type RelayInterface, type RelayMessageHandler, type RelayMessageHandlerWithName, type RelayPeer, RelayServer, type RelayServerEvents, type RelayServerMessage, type RelayServerOptions, type ReputationQuery, type ReputationResponse, ReputationStore, type RestSession, type RevealRecord, type RevocationRecord, type RunRelayOptions, type SendMessageOptions, type SendMessageResult, type StoredMessage, type TransportConfig, type TrustScore, type ValidationResult, type VerificationRecord, type VerifyEnvelopeFn, canonicalize, computeAllTrustScores, computeId, computeTrustScore, computeTrustScores, createCapability, createCommit, createEnvelope, createRestRouter, createReveal, createToken, createVerification, decay, decodeInboundEnvelope, exportKeyPair, formatDisplayName, generateKeyPair, getDefaultBootstrapRelay, getDefaultConfigPath, hashPrediction, importKeyPair, initPeerConfig, loadAgoraConfig, loadAgoraConfigAsync, loadPeerConfig, parseBootstrapRelay, requireAuth, resolveBroadcastName, revokeToken, runRelay, savePeerConfig, sendToPeer, shortKey, signMessage, validateCapability, validateCommitRecord, validatePeerListRequest, validatePeerListResponse, validatePeerReferral, validateRevealRecord, validateVerificationRecord, verifyEnvelope, verifyReveal, verifySignature, verifyVerificationSignature };
|