@rookdaemon/agora 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +347 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/identity/keypair.d.ts +42 -0
  8. package/dist/identity/keypair.d.ts.map +1 -0
  9. package/dist/identity/keypair.js +83 -0
  10. package/dist/identity/keypair.js.map +1 -0
  11. package/dist/index.d.ts +9 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +9 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/message/envelope.d.ts +58 -0
  16. package/dist/message/envelope.d.ts.map +1 -0
  17. package/dist/message/envelope.js +83 -0
  18. package/dist/message/envelope.js.map +1 -0
  19. package/dist/registry/capability.d.ts +44 -0
  20. package/dist/registry/capability.d.ts.map +1 -0
  21. package/dist/registry/capability.js +94 -0
  22. package/dist/registry/capability.js.map +1 -0
  23. package/dist/registry/messages.d.ts +50 -0
  24. package/dist/registry/messages.d.ts.map +1 -0
  25. package/dist/registry/messages.js +2 -0
  26. package/dist/registry/messages.js.map +1 -0
  27. package/dist/registry/peer-store.d.ts +56 -0
  28. package/dist/registry/peer-store.d.ts.map +1 -0
  29. package/dist/registry/peer-store.js +92 -0
  30. package/dist/registry/peer-store.js.map +1 -0
  31. package/dist/registry/peer.d.ts +20 -0
  32. package/dist/registry/peer.d.ts.map +1 -0
  33. package/dist/registry/peer.js +2 -0
  34. package/dist/registry/peer.js.map +1 -0
  35. package/dist/transport/http.d.ts +41 -0
  36. package/dist/transport/http.d.ts.map +1 -0
  37. package/dist/transport/http.js +99 -0
  38. package/dist/transport/http.js.map +1 -0
  39. package/dist/transport/peer-config.d.ts +33 -0
  40. package/dist/transport/peer-config.d.ts.map +1 -0
  41. package/dist/transport/peer-config.js +41 -0
  42. package/dist/transport/peer-config.js.map +1 -0
  43. package/package.json +38 -0
@@ -0,0 +1,99 @@
1
+ import { createEnvelope, verifyEnvelope } from '../message/envelope.js';
2
+ /**
3
+ * Send a signed envelope to a peer via HTTP webhook.
4
+ * Creates the envelope, signs it, and POSTs to the peer's /hooks/agent endpoint.
5
+ * Returns the HTTP status code.
6
+ */
7
+ export async function sendToPeer(config, peerPublicKey, type, payload, inReplyTo) {
8
+ // Look up peer config
9
+ const peer = config.peers.get(peerPublicKey);
10
+ if (!peer) {
11
+ return { ok: false, status: 0, error: 'Unknown peer' };
12
+ }
13
+ // Create and sign the envelope
14
+ const envelope = createEnvelope(type, config.identity.publicKey, config.identity.privateKey, payload, inReplyTo);
15
+ // Encode envelope as base64url
16
+ const envelopeJson = JSON.stringify(envelope);
17
+ const envelopeBase64 = Buffer.from(envelopeJson).toString('base64url');
18
+ // Construct webhook payload
19
+ const webhookPayload = {
20
+ message: `[AGORA_ENVELOPE]${envelopeBase64}`,
21
+ name: 'Agora',
22
+ sessionKey: `agora:${envelope.sender.substring(0, 16)}`,
23
+ deliver: false,
24
+ };
25
+ // Send HTTP POST
26
+ try {
27
+ const response = await fetch(`${peer.url}/agent`, {
28
+ method: 'POST',
29
+ headers: {
30
+ 'Authorization': `Bearer ${peer.token}`,
31
+ 'Content-Type': 'application/json',
32
+ },
33
+ body: JSON.stringify(webhookPayload),
34
+ });
35
+ return {
36
+ ok: response.ok,
37
+ status: response.status,
38
+ error: response.ok ? undefined : await response.text(),
39
+ };
40
+ }
41
+ catch (err) {
42
+ return {
43
+ ok: false,
44
+ status: 0,
45
+ error: err instanceof Error ? err.message : String(err),
46
+ };
47
+ }
48
+ }
49
+ /**
50
+ * Decode and verify an inbound Agora envelope from a webhook message.
51
+ * Expects the message to start with [AGORA_ENVELOPE] followed by base64.
52
+ * Returns the verified envelope or an error.
53
+ */
54
+ export function decodeInboundEnvelope(message, knownPeers) {
55
+ // Check for AGORA_ENVELOPE prefix
56
+ const prefix = '[AGORA_ENVELOPE]';
57
+ if (!message.startsWith(prefix)) {
58
+ return { ok: false, reason: 'not_agora_message' };
59
+ }
60
+ // Extract base64 payload
61
+ const base64Payload = message.substring(prefix.length);
62
+ // Check for empty payload
63
+ if (!base64Payload) {
64
+ return { ok: false, reason: 'invalid_base64' };
65
+ }
66
+ // Decode base64
67
+ let envelopeJson;
68
+ try {
69
+ const decoded = Buffer.from(base64Payload, 'base64url');
70
+ // Check if decoded buffer is empty or contains invalid data
71
+ if (decoded.length === 0) {
72
+ return { ok: false, reason: 'invalid_base64' };
73
+ }
74
+ envelopeJson = decoded.toString('utf-8');
75
+ }
76
+ catch {
77
+ return { ok: false, reason: 'invalid_base64' };
78
+ }
79
+ // Parse JSON
80
+ let envelope;
81
+ try {
82
+ envelope = JSON.parse(envelopeJson);
83
+ }
84
+ catch {
85
+ return { ok: false, reason: 'invalid_json' };
86
+ }
87
+ // Verify envelope integrity
88
+ const verification = verifyEnvelope(envelope);
89
+ if (!verification.valid) {
90
+ return { ok: false, reason: verification.reason || 'verification_failed' };
91
+ }
92
+ // Check if sender is a known peer
93
+ const senderKnown = knownPeers.has(envelope.sender);
94
+ if (!senderKnown) {
95
+ return { ok: false, reason: 'unknown_sender' };
96
+ }
97
+ return { ok: true, envelope };
98
+ }
99
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAmC,MAAM,wBAAwB,CAAC;AAkBzG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAuB,EACvB,aAAqB,EACrB,IAAiB,EACjB,OAAgB,EAChB,SAAkB;IAElB,sBAAsB;IACtB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IACzD,CAAC;IAED,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,cAAc,CAC7B,IAAI,EACJ,MAAM,CAAC,QAAQ,CAAC,SAAS,EACzB,MAAM,CAAC,QAAQ,CAAC,UAAU,EAC1B,OAAO,EACP,SAAS,CACV,CAAC;IAEF,+BAA+B;IAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEvE,4BAA4B;IAC5B,MAAM,cAAc,GAAG;QACrB,OAAO,EAAE,mBAAmB,cAAc,EAAE;QAC5C,IAAI,EAAE,OAAO;QACb,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;QACvD,OAAO,EAAE,KAAK;KACf,CAAC;IAEF,iBAAiB;IACjB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,QAAQ,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;gBACvC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;SACrC,CAAC,CAAC;QAEH,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE;SACvD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,UAAmC;IAEnC,kCAAkC;IAClC,MAAM,MAAM,GAAG,kBAAkB,CAAC;IAClC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACpD,CAAC;IAED,yBAAyB;IACzB,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEvD,0BAA0B;IAC1B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,gBAAgB;IAChB,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACxD,4DAA4D;QAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACjD,CAAC;QACD,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,aAAa;IACb,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAC/C,CAAC;IAED,4BAA4B;IAC5B,MAAM,YAAY,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,IAAI,qBAAqB,EAAE,CAAC;IAC7E,CAAC;IAED,kCAAkC;IAClC,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,33 @@
1
+ export interface PeerConfigFile {
2
+ identity: {
3
+ publicKey: string;
4
+ privateKey: string;
5
+ };
6
+ peers: Record<string, {
7
+ url: string;
8
+ token: string;
9
+ publicKey: string;
10
+ name?: string;
11
+ }>;
12
+ }
13
+ /**
14
+ * Load peer configuration from a JSON file.
15
+ * @param path - Path to the config file
16
+ * @returns The parsed configuration
17
+ * @throws Error if file doesn't exist or contains invalid JSON
18
+ */
19
+ export declare function loadPeerConfig(path: string): PeerConfigFile;
20
+ /**
21
+ * Save peer configuration to a JSON file.
22
+ * @param path - Path to the config file
23
+ * @param config - The configuration to save
24
+ */
25
+ export declare function savePeerConfig(path: string, config: PeerConfigFile): void;
26
+ /**
27
+ * Initialize peer configuration, generating a new keypair if the file doesn't exist.
28
+ * If the file exists, loads and returns it.
29
+ * @param path - Path to the config file
30
+ * @returns The configuration (loaded or newly created)
31
+ */
32
+ export declare function initPeerConfig(path: string): PeerConfigFile;
33
+ //# sourceMappingURL=peer-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-config.d.ts","sourceRoot":"","sources":["../../src/transport/peer-config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAG3D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAGzE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAc3D"}
@@ -0,0 +1,41 @@
1
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
2
+ import { generateKeyPair } from '../identity/keypair.js';
3
+ /**
4
+ * Load peer configuration from a JSON file.
5
+ * @param path - Path to the config file
6
+ * @returns The parsed configuration
7
+ * @throws Error if file doesn't exist or contains invalid JSON
8
+ */
9
+ export function loadPeerConfig(path) {
10
+ const content = readFileSync(path, 'utf-8');
11
+ return JSON.parse(content);
12
+ }
13
+ /**
14
+ * Save peer configuration to a JSON file.
15
+ * @param path - Path to the config file
16
+ * @param config - The configuration to save
17
+ */
18
+ export function savePeerConfig(path, config) {
19
+ const content = JSON.stringify(config, null, 2);
20
+ writeFileSync(path, content, 'utf-8');
21
+ }
22
+ /**
23
+ * Initialize peer configuration, generating a new keypair if the file doesn't exist.
24
+ * If the file exists, loads and returns it.
25
+ * @param path - Path to the config file
26
+ * @returns The configuration (loaded or newly created)
27
+ */
28
+ export function initPeerConfig(path) {
29
+ if (existsSync(path)) {
30
+ return loadPeerConfig(path);
31
+ }
32
+ // Generate new keypair and create initial config
33
+ const identity = generateKeyPair();
34
+ const config = {
35
+ identity,
36
+ peers: {},
37
+ };
38
+ savePeerConfig(path, config);
39
+ return config;
40
+ }
41
+ //# sourceMappingURL=peer-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-config.js","sourceRoot":"","sources":["../../src/transport/peer-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAezD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,MAAsB;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,iDAAiD;IACjD,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,MAAM,MAAM,GAAmB;QAC7B,QAAQ;QACR,KAAK,EAAE,EAAE;KACV,CAAC;IAEF,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@rookdaemon/agora",
3
+ "version": "0.1.0",
4
+ "description": "A coordination network for AI agents",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "agora": "./dist/cli.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "node --import tsx --test test/*.test.ts",
14
+ "lint": "eslint src test --ext .ts",
15
+ "prepublishOnly": "npm run lint && npm run build && npm test"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "keywords": [
23
+ "agent",
24
+ "coordination",
25
+ "distributed",
26
+ "p2p"
27
+ ],
28
+ "author": "",
29
+ "license": "MIT",
30
+ "devDependencies": {
31
+ "@types/node": "^25.1.0",
32
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
33
+ "@typescript-eslint/parser": "^8.54.0",
34
+ "eslint": "^9.39.2",
35
+ "tsx": "^4.21.0",
36
+ "typescript": "^5.9.3"
37
+ }
38
+ }