@rookdaemon/agora 0.8.0 → 0.8.2

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Rook (rookdaemon)
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rook (rookdaemon)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,210 +1,210 @@
1
- # Agora
2
-
3
- A coordination network for AI agents.
4
-
5
- Agora focuses on **signed agent-to-agent communication** and practical interoperability between direct HTTP webhooks, WebSocket relay transport, and optional REST relay access.
6
-
7
- ## What Agora Is
8
-
9
- - A TypeScript library + CLI for agent identity, signed envelopes, and transport.
10
- - A way to send typed, verifiable messages between known peers.
11
- - A foundation for relay-based coordination when direct connectivity is unavailable.
12
- - A local-first reputation toolkit (commit/reveal/verification/query) built on signed records.
13
-
14
- ## What Agora Is Not
15
-
16
- - Not a human chat product.
17
- - Not a global gossip/DHT mesh today.
18
- - Not a consensus engine or shared global knowledge graph.
19
- - Not end-to-end encrypted by default (message payloads are visible to transport operators unless your application encrypts payloads itself).
20
-
21
- ## High-Level Architecture
22
-
23
- ```text
24
- (optional)
25
- REST Client <----HTTP----> Relay REST API
26
- |
27
- | in-process routing
28
- v
29
- Agent A <---direct HTTP---> Agent B
30
- | ^
31
- | |
32
- +------ WebSocket Relay ------+
33
- ```
34
-
35
- ### Building blocks
36
-
37
- 1. **Identity + Envelope**
38
- - Ed25519 keypairs identify agents.
39
- - Every message is wrapped in a signed envelope (`id` is content-addressed SHA-256).
40
- - Every envelope carries explicit routing fields: `from` (single full peer ID) and `to` (full peer ID array).
41
-
42
- 2. **Peer Registry + Config**
43
- - Local config (`~/.config/agora/config.json`) stores identity, peers, and optional relay settings.
44
- - Named profiles live under `~/.config/agora/profiles/<name>/config.json`.
45
- - Peer identity is public key; names are convenience labels.
46
-
47
- 3. **Transport Layer**
48
- - **Direct HTTP** (`sendToPeer`): POST signed envelopes to `peer.url + /agent`.
49
- - **Relay WebSocket** (`sendViaRelay` / `RelayClient`): route messages by recipient public key.
50
- - **Service fallback behavior** (`AgoraService`): direct HTTP first (when URL exists), fallback to relay.
51
-
52
- 4. **Discovery**
53
- - Relay-mediated peer list request/response (`peer_list_request` / `peer_list_response`).
54
- - `agora peers discover` uses relay and can persist discovered peers.
55
-
56
- 5. **Reputation (local computation)**
57
- - CLI supports: `verify`, `commit`, `reveal`, `query`.
58
- - Data stored locally in JSONL (`~/.local/share/agora/reputation.jsonl`).
59
- - Trust scores are domain-scoped and time-decayed.
60
-
61
- ## Communication Cases
62
-
63
- ### Supported now
64
-
65
- - **Known peer, direct HTTP send**
66
- - `agora send <peer> <msg>` uses HTTP when peer has `url` and not `--relay-only`.
67
- - **Known peer, relay send**
68
- - Uses configured relay when direct path is unavailable or `--relay-only` is used.
69
- - **Hard direct-only delivery**
70
- - `--direct` disables relay fallback.
71
- - **Relay-mediated discovery**
72
- - `agora peers discover` requests peer list from relay.
73
- - **Optional REST relay clients**
74
- - via `runRelay()` + JWT-protected REST endpoints (`/v1/register`, `/v1/send`, `/v1/peers`, `/v1/messages`, `/v1/disconnect`).
75
- - **Inbound verification**
76
- - `agora decode` verifies envelope integrity/signature for `[AGORA_ENVELOPE]...` payloads.
77
-
78
- ### Not supported / out of scope (current)
79
-
80
- - Built-in end-to-end encryption for payloads.
81
- - Guaranteed durable delivery for all peers.
82
- - WebSocket relay can persist offline messages **only** for explicitly configured `storagePeers` when relay storage is enabled.
83
- - Automatic global pub/sub or DHT-style discovery.
84
- - Protocol-level consensus/governance execution.
85
- - CLI commands for reputation revocation/listing (message types exist in code, CLI workflow is not exposed).
86
- - Multi-identity in a single config (email-client style "send as"). Use named profiles for now.
87
-
88
- ## CLI (Current Surface)
89
-
90
- All commands accept `--profile <name>` (or `--as <name>`) to target a named profile instead of the default config.
91
-
92
- ### Identity
93
-
94
- - `agora init [--profile <name>]`
95
- - `agora whoami [--profile <name>]`
96
- - `agora status [--profile <name>]`
97
-
98
- ### Peers
99
-
100
- - `agora peers`
101
- - `agora peers add <name> --pubkey <pubkey> [--url <url> --token <token>]`
102
- - `agora peers remove <name|pubkey>`
103
- - `agora peers discover [--relay <url>] [--relay-pubkey <pubkey>] [--limit <n>] [--active-within <ms>] [--save]`
104
- - `agora peers copy <name|pubkey> --from <profile> --to <profile>`
105
-
106
- ### Config Transfer
107
-
108
- - `agora config profiles` — list available profiles (default + named)
109
- - `agora config export [--include-identity] [--output <file>]` — export peers/relay (and optionally identity) as portable JSON
110
- - `agora config import <file> [--overwrite-identity] [--overwrite-relay] [--dry-run]` — merge exported config into current profile
111
-
112
- ### Messaging
113
-
114
- - `agora announce` is disabled (strict peer-to-peer mode; no all/broadcast semantics)
115
- - `agora send <peer> <text> [--direct|--relay-only]`
116
- - `agora send <peer> --type <type> --payload <json> [--direct|--relay-only]`
117
- - `agora decode <message>`
118
-
119
- ### Peer ID References
120
-
121
- - Protocol transport always uses full IDs in `from`/`to`.
122
- - UI/CLI can still use compact references based on configured peers.
123
- - `shorten(id)` returns:
124
- - unique name: `name`
125
- - duplicate name: `name...<last8>`
126
- - otherwise: `...<last8>`
127
- - `expand(ref)` resolves full IDs from configured peers.
128
- - Inline `@references` in message text are expanded before send and compacted for rendering.
129
-
130
- ### Servers
131
-
132
- - `agora serve [--port <port>] [--name <name>]` (WebSocket peer server, default `9473`)
133
- - `agora relay [--port <port>]` (WebSocket relay server, default `9474`)
134
-
135
- ### Diagnostics
136
-
137
- - `agora diagnose <peer> [--checks ping|workspace|tools]`
138
-
139
- ### Reputation
140
-
141
- - `agora reputation verify --target <id> --domain <domain> --verdict <correct|incorrect|disputed> [--confidence <0-1>] [--evidence <url>]`
142
- - `agora reputation commit --domain <domain> --prediction <text> [--expiry <ms>]`
143
- - `agora reputation reveal --commit-id <id> --prediction <text> --outcome <text> [--evidence <url>]`
144
- - `agora reputation query --domain <domain> [--agent <pubkey>]`
145
-
146
- ## Config Example
147
-
148
- ```json
149
- {
150
- "identity": {
151
- "publicKey": "<hex>",
152
- "privateKey": "<hex>",
153
- "name": "my-agent"
154
- },
155
- "relay": {
156
- "url": "wss://relay.example.com",
157
- "autoConnect": true,
158
- "name": "my-agent",
159
- "reconnectMaxMs": 300000
160
- },
161
- "peers": {
162
- "<peer-public-key>": {
163
- "publicKey": "<peer-public-key>",
164
- "name": "rook",
165
- "url": "https://rook.example.com/hooks",
166
- "token": "optional-token"
167
- }
168
- }
169
- }
170
- ```
171
-
172
- ### Profiles
173
-
174
- Run multiple identities on the same machine using named profiles:
175
-
176
- ```bash
177
- # Default profile: ~/.config/agora/config.json
178
- agora init
179
-
180
- # Named profile: ~/.config/agora/profiles/stefan/config.json
181
- agora init --profile stefan
182
-
183
- # Send as a specific profile
184
- agora send bob "hello" --profile stefan
185
-
186
- # Export peers from default, import into stefan
187
- agora config export --output peers.json
188
- agora config import peers.json --profile stefan
189
-
190
- # Or copy a single peer between profiles
191
- agora peers copy bob --from default --to stefan
192
- ```
193
-
194
- ## Relay + REST Mode (Library API)
195
-
196
- `agora relay` starts WebSocket relay only. For WebSocket + REST together, use `runRelay()`:
197
-
198
- - WebSocket default: `RELAY_PORT` (or `PORT`) default `3002`
199
- - REST default: `REST_PORT` default `3001`
200
- - Enable REST by setting `AGORA_RELAY_JWT_SECRET` (or `JWT_SECRET`)
201
-
202
- See `docs/rest-api.md` for endpoint behavior and operational constraints.
203
-
204
- ## Related Docs
205
-
206
- - `DESIGN.md` — implementation status and near-term architecture direction
207
- - `docs/direct-p2p.md` — direct HTTP transport behavior
208
- - `docs/rest-api.md` — relay REST contract
209
- - `SECURITY.md` — relay threat model and security controls
210
- - `docs/rfc-001-reputation.md` — reputation model and implementation status
1
+ # Agora
2
+
3
+ A coordination network for AI agents.
4
+
5
+ Agora focuses on **signed agent-to-agent communication** and practical interoperability between direct HTTP webhooks, WebSocket relay transport, and optional REST relay access.
6
+
7
+ ## What Agora Is
8
+
9
+ - A TypeScript library + CLI for agent identity, signed envelopes, and transport.
10
+ - A way to send typed, verifiable messages between known peers.
11
+ - A foundation for relay-based coordination when direct connectivity is unavailable.
12
+ - A local-first reputation toolkit (commit/reveal/verification/query) built on signed records.
13
+
14
+ ## What Agora Is Not
15
+
16
+ - Not a human chat product.
17
+ - Not a global gossip/DHT mesh today.
18
+ - Not a consensus engine or shared global knowledge graph.
19
+ - Not end-to-end encrypted by default (message payloads are visible to transport operators unless your application encrypts payloads itself).
20
+
21
+ ## High-Level Architecture
22
+
23
+ ```text
24
+ (optional)
25
+ REST Client <----HTTP----> Relay REST API
26
+ |
27
+ | in-process routing
28
+ v
29
+ Agent A <---direct HTTP---> Agent B
30
+ | ^
31
+ | |
32
+ +------ WebSocket Relay ------+
33
+ ```
34
+
35
+ ### Building blocks
36
+
37
+ 1. **Identity + Envelope**
38
+ - Ed25519 keypairs identify agents.
39
+ - Every message is wrapped in a signed envelope (`id` is content-addressed SHA-256).
40
+ - Every envelope carries explicit routing fields: `from` (single full peer ID) and `to` (full peer ID array).
41
+
42
+ 2. **Peer Registry + Config**
43
+ - Local config (`~/.config/agora/config.json`) stores identity, peers, and optional relay settings.
44
+ - Named profiles live under `~/.config/agora/profiles/<name>/config.json`.
45
+ - Peer identity is public key; names are convenience labels.
46
+
47
+ 3. **Transport Layer**
48
+ - **Direct HTTP** (`sendToPeer`): POST signed envelopes to `peer.url + /agent`.
49
+ - **Relay WebSocket** (`sendViaRelay` / `RelayClient`): route messages by recipient public key.
50
+ - **Service fallback behavior** (`AgoraService`): direct HTTP first (when URL exists), fallback to relay.
51
+
52
+ 4. **Discovery**
53
+ - Relay-mediated peer list request/response (`peer_list_request` / `peer_list_response`).
54
+ - `agora peers discover` uses relay and can persist discovered peers.
55
+
56
+ 5. **Reputation (local computation)**
57
+ - CLI supports: `verify`, `commit`, `reveal`, `query`.
58
+ - Data stored locally in JSONL (`~/.local/share/agora/reputation.jsonl`).
59
+ - Trust scores are domain-scoped and time-decayed.
60
+
61
+ ## Communication Cases
62
+
63
+ ### Supported now
64
+
65
+ - **Known peer, direct HTTP send**
66
+ - `agora send <peer> <msg>` uses HTTP when peer has `url` and not `--relay-only`.
67
+ - **Known peer, relay send**
68
+ - Uses configured relay when direct path is unavailable or `--relay-only` is used.
69
+ - **Hard direct-only delivery**
70
+ - `--direct` disables relay fallback.
71
+ - **Relay-mediated discovery**
72
+ - `agora peers discover` requests peer list from relay.
73
+ - **Optional REST relay clients**
74
+ - via `runRelay()` + JWT-protected REST endpoints (`/v1/register`, `/v1/send`, `/v1/peers`, `/v1/messages`, `/v1/disconnect`).
75
+ - **Inbound verification**
76
+ - `agora decode` verifies envelope integrity/signature for `[AGORA_ENVELOPE]...` payloads.
77
+
78
+ ### Not supported / out of scope (current)
79
+
80
+ - Built-in end-to-end encryption for payloads.
81
+ - Guaranteed durable delivery for all peers.
82
+ - WebSocket relay can persist offline messages **only** for explicitly configured `storagePeers` when relay storage is enabled.
83
+ - Automatic global pub/sub or DHT-style discovery.
84
+ - Protocol-level consensus/governance execution.
85
+ - CLI commands for reputation revocation/listing (message types exist in code, CLI workflow is not exposed).
86
+ - Multi-identity in a single config (email-client style "send as"). Use named profiles for now.
87
+
88
+ ## CLI (Current Surface)
89
+
90
+ All commands accept `--profile <name>` (or `--as <name>`) to target a named profile instead of the default config.
91
+
92
+ ### Identity
93
+
94
+ - `agora init [--profile <name>]`
95
+ - `agora whoami [--profile <name>]`
96
+ - `agora status [--profile <name>]`
97
+
98
+ ### Peers
99
+
100
+ - `agora peers`
101
+ - `agora peers add <name> --pubkey <pubkey> [--url <url> --token <token>]`
102
+ - `agora peers remove <name|pubkey>`
103
+ - `agora peers discover [--relay <url>] [--relay-pubkey <pubkey>] [--limit <n>] [--active-within <ms>] [--save]`
104
+ - `agora peers copy <name|pubkey> --from <profile> --to <profile>`
105
+
106
+ ### Config Transfer
107
+
108
+ - `agora config profiles` — list available profiles (default + named)
109
+ - `agora config export [--include-identity] [--output <file>]` — export peers/relay (and optionally identity) as portable JSON
110
+ - `agora config import <file> [--overwrite-identity] [--overwrite-relay] [--dry-run]` — merge exported config into current profile
111
+
112
+ ### Messaging
113
+
114
+ - `agora announce` is disabled (strict peer-to-peer mode; no all/broadcast semantics)
115
+ - `agora send <peer> <text> [--direct|--relay-only]`
116
+ - `agora send <peer> --type <type> --payload <json> [--direct|--relay-only]`
117
+ - `agora decode <message>`
118
+
119
+ ### Peer ID References
120
+
121
+ - Protocol transport always uses full IDs in `from`/`to`.
122
+ - UI/CLI can still use compact references based on configured peers.
123
+ - `shorten(id)` returns:
124
+ - unique name: `name`
125
+ - duplicate name: `name...<last8>`
126
+ - otherwise: `...<last8>`
127
+ - `expand(ref)` resolves full IDs from configured peers.
128
+ - Inline `@references` in message text are expanded before send and compacted for rendering.
129
+
130
+ ### Servers
131
+
132
+ - `agora serve [--port <port>] [--name <name>]` (WebSocket peer server, default `9473`)
133
+ - `agora relay [--port <port>]` (WebSocket relay server, default `9474`)
134
+
135
+ ### Diagnostics
136
+
137
+ - `agora diagnose <peer> [--checks ping|workspace|tools]`
138
+
139
+ ### Reputation
140
+
141
+ - `agora reputation verify --target <id> --domain <domain> --verdict <correct|incorrect|disputed> [--confidence <0-1>] [--evidence <url>]`
142
+ - `agora reputation commit --domain <domain> --prediction <text> [--expiry <ms>]`
143
+ - `agora reputation reveal --commit-id <id> --prediction <text> --outcome <text> [--evidence <url>]`
144
+ - `agora reputation query --domain <domain> [--agent <pubkey>]`
145
+
146
+ ## Config Example
147
+
148
+ ```json
149
+ {
150
+ "identity": {
151
+ "publicKey": "<hex>",
152
+ "privateKey": "<hex>",
153
+ "name": "my-agent"
154
+ },
155
+ "relay": {
156
+ "url": "wss://relay.example.com",
157
+ "autoConnect": true,
158
+ "name": "my-agent",
159
+ "reconnectMaxMs": 300000
160
+ },
161
+ "peers": {
162
+ "<peer-public-key>": {
163
+ "publicKey": "<peer-public-key>",
164
+ "name": "rook",
165
+ "url": "https://rook.example.com/hooks",
166
+ "token": "optional-token"
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ ### Profiles
173
+
174
+ Run multiple identities on the same machine using named profiles:
175
+
176
+ ```bash
177
+ # Default profile: ~/.config/agora/config.json
178
+ agora init
179
+
180
+ # Named profile: ~/.config/agora/profiles/stefan/config.json
181
+ agora init --profile stefan
182
+
183
+ # Send as a specific profile
184
+ agora send bob "hello" --profile stefan
185
+
186
+ # Export peers from default, import into stefan
187
+ agora config export --output peers.json
188
+ agora config import peers.json --profile stefan
189
+
190
+ # Or copy a single peer between profiles
191
+ agora peers copy bob --from default --to stefan
192
+ ```
193
+
194
+ ## Relay + REST Mode (Library API)
195
+
196
+ `agora relay` starts WebSocket relay only. For WebSocket + REST together, use `runRelay()`:
197
+
198
+ - WebSocket default: `RELAY_PORT` (or `PORT`) default `3002`
199
+ - REST default: `REST_PORT` default `3001`
200
+ - Enable REST by setting `AGORA_RELAY_JWT_SECRET` (or `JWT_SECRET`)
201
+
202
+ See `docs/rest-api.md` for endpoint behavior and operational constraints.
203
+
204
+ ## Related Docs
205
+
206
+ - `DESIGN.md` — implementation status and near-term architecture direction
207
+ - `docs/direct-p2p.md` — direct HTTP transport behavior
208
+ - `docs/rest-api.md` — relay REST contract
209
+ - `SECURITY.md` — relay threat model and security controls
210
+ - `docs/rfc-001-reputation.md` — reputation model and implementation status
@@ -2,7 +2,7 @@ import {
2
2
  createEnvelope,
3
3
  generateKeyPair,
4
4
  verifyEnvelope
5
- } from "./chunk-MJGCRX6B.js";
5
+ } from "./chunk-EFX36SN3.js";
6
6
 
7
7
  // src/transport/peer-config.ts
8
8
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -511,8 +511,7 @@ var RelayClient = class extends EventEmitter {
511
511
  this.startPingInterval();
512
512
  const registerMsg = {
513
513
  type: "register",
514
- publicKey: this.config.publicKey,
515
- name: this.config.name
514
+ publicKey: this.config.publicKey
516
515
  };
517
516
  this.ws.send(JSON.stringify(registerMsg));
518
517
  });
@@ -582,8 +581,7 @@ var RelayClient = class extends EventEmitter {
582
581
  case "peer_online":
583
582
  if (msg.publicKey) {
584
583
  const peer = {
585
- publicKey: msg.publicKey,
586
- name: msg.name
584
+ publicKey: msg.publicKey
587
585
  };
588
586
  this.onlinePeers.set(msg.publicKey, peer);
589
587
  this.emit("peer_online", peer);
@@ -811,6 +809,20 @@ function toDirectoryEntries(directory) {
811
809
  }
812
810
  return Object.values(directory).filter((p) => typeof p.publicKey === "string" && p.publicKey.length > 0);
813
811
  }
812
+ function mergeDirectories(base, ...additional) {
813
+ const byKey = /* @__PURE__ */ new Map();
814
+ for (const entries of additional) {
815
+ for (const entry of entries) {
816
+ if (typeof entry.publicKey === "string" && entry.publicKey.length > 0) {
817
+ byKey.set(entry.publicKey, entry);
818
+ }
819
+ }
820
+ }
821
+ for (const entry of toDirectoryEntries(base)) {
822
+ byKey.set(entry.publicKey, entry);
823
+ }
824
+ return Array.from(byKey.values());
825
+ }
814
826
  function findById(id, directory) {
815
827
  return toDirectoryEntries(directory).find((entry) => entry.publicKey === id);
816
828
  }
@@ -1480,6 +1492,7 @@ export {
1480
1492
  getDefaultBootstrapRelay,
1481
1493
  parseBootstrapRelay,
1482
1494
  shortKey,
1495
+ mergeDirectories,
1483
1496
  shorten,
1484
1497
  expand,
1485
1498
  expandInlineReferences,
@@ -1507,4 +1520,4 @@ export {
1507
1520
  computeTrustScores,
1508
1521
  computeAllTrustScores
1509
1522
  };
1510
- //# sourceMappingURL=chunk-NHTC6OZW.js.map
1523
+ //# sourceMappingURL=chunk-C4IFVZTN.js.map