society-protocol 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/benchmark/collector.d.ts +17 -0
- package/dist/benchmark/collector.d.ts.map +1 -0
- package/dist/benchmark/collector.js +36 -0
- package/dist/benchmark/collector.js.map +1 -0
- package/dist/benchmark/reporter.d.ts +17 -0
- package/dist/benchmark/reporter.d.ts.map +1 -0
- package/dist/benchmark/reporter.js +140 -0
- package/dist/benchmark/reporter.js.map +1 -0
- package/dist/benchmark/types.d.ts +63 -0
- package/dist/benchmark/types.d.ts.map +1 -0
- package/dist/benchmark/types.js +6 -0
- package/dist/benchmark/types.js.map +1 -0
- package/dist/bootstrap.d.ts +8 -3
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +52 -9
- package/dist/bootstrap.js.map +1 -1
- package/dist/content-store.d.ts +77 -0
- package/dist/content-store.d.ts.map +1 -0
- package/dist/content-store.js +178 -0
- package/dist/content-store.js.map +1 -0
- package/dist/identity-proof.d.ts +43 -0
- package/dist/identity-proof.d.ts.map +1 -0
- package/dist/identity-proof.js +98 -0
- package/dist/identity-proof.js.map +1 -0
- package/dist/index.js +174 -39
- package/dist/index.js.map +1 -1
- package/dist/knowledge.d.ts +100 -1
- package/dist/knowledge.d.ts.map +1 -1
- package/dist/knowledge.js +437 -2
- package/dist/knowledge.js.map +1 -1
- package/dist/lib.d.ts +8 -2
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +6 -1
- package/dist/lib.js.map +1 -1
- package/dist/p2p.d.ts +25 -0
- package/dist/p2p.d.ts.map +1 -1
- package/dist/p2p.js +159 -69
- package/dist/p2p.js.map +1 -1
- package/dist/persona/types.d.ts +1 -1
- package/dist/persona/types.d.ts.map +1 -1
- package/dist/persona/zkp/engine.d.ts.map +1 -1
- package/dist/persona/zkp/engine.js +8 -0
- package/dist/persona/zkp/engine.js.map +1 -1
- package/dist/planner.d.ts +1 -0
- package/dist/planner.d.ts.map +1 -1
- package/dist/planner.js +26 -4
- package/dist/planner.js.map +1 -1
- package/dist/proactive/watcher.d.ts +76 -0
- package/dist/proactive/watcher.d.ts.map +1 -0
- package/dist/proactive/watcher.js +246 -0
- package/dist/proactive/watcher.js.map +1 -0
- package/dist/registry.d.ts +4 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +21 -0
- package/dist/registry.js.map +1 -1
- package/dist/reputation.d.ts +10 -0
- package/dist/reputation.d.ts.map +1 -1
- package/dist/reputation.js +23 -4
- package/dist/reputation.js.map +1 -1
- package/dist/rooms.d.ts +35 -0
- package/dist/rooms.d.ts.map +1 -1
- package/dist/rooms.js +128 -0
- package/dist/rooms.js.map +1 -1
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +1 -1
- package/dist/swp.d.ts +1 -1
- package/dist/swp.d.ts.map +1 -1
- package/dist/swp.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-Addressed Block Store
|
|
3
|
+
*
|
|
4
|
+
* IPFS-inspired content-addressed storage for Society Protocol.
|
|
5
|
+
* Uses blake3 hashing for CIDs and SQLite for block persistence.
|
|
6
|
+
* Supports chunked file storage with Merkle-like manifests.
|
|
7
|
+
*
|
|
8
|
+
* Based on: IPFS (arXiv:1407.3561) — content-addressed blocks with CID-based retrieval
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
11
|
+
import { basename } from 'path';
|
|
12
|
+
// ─── Constants ──────────────────────────────────────────────────
|
|
13
|
+
const BLOCK_SIZE = 256 * 1024; // 256KB per block
|
|
14
|
+
// ─── ContentStore ───────────────────────────────────────────────
|
|
15
|
+
export class ContentStore {
|
|
16
|
+
storage;
|
|
17
|
+
manifests = new Map(); // rootCid → manifest
|
|
18
|
+
constructor(storage) {
|
|
19
|
+
this.storage = storage;
|
|
20
|
+
this.ensureTable();
|
|
21
|
+
}
|
|
22
|
+
ensureTable() {
|
|
23
|
+
this.storage.db.exec(`
|
|
24
|
+
CREATE TABLE IF NOT EXISTS content_blocks (
|
|
25
|
+
cid TEXT PRIMARY KEY,
|
|
26
|
+
data BLOB NOT NULL,
|
|
27
|
+
size INTEGER NOT NULL,
|
|
28
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
29
|
+
);
|
|
30
|
+
CREATE TABLE IF NOT EXISTS file_manifests (
|
|
31
|
+
root_cid TEXT PRIMARY KEY,
|
|
32
|
+
manifest TEXT NOT NULL,
|
|
33
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
34
|
+
);
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Store a data block, returning its CID (blake3 hash).
|
|
39
|
+
*/
|
|
40
|
+
async put(data) {
|
|
41
|
+
const { blake3 } = await import('@noble/hashes/blake3');
|
|
42
|
+
const hash = blake3(data);
|
|
43
|
+
const cid = Buffer.from(hash).toString('hex');
|
|
44
|
+
// Idempotent: skip if already stored
|
|
45
|
+
const existing = this.storage.db
|
|
46
|
+
.prepare('SELECT cid FROM content_blocks WHERE cid = ?')
|
|
47
|
+
.get(cid);
|
|
48
|
+
if (!existing) {
|
|
49
|
+
this.storage.db
|
|
50
|
+
.prepare('INSERT INTO content_blocks (cid, data, size) VALUES (?, ?, ?)')
|
|
51
|
+
.run(cid, Buffer.from(data), data.byteLength);
|
|
52
|
+
}
|
|
53
|
+
return cid;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Retrieve a block by CID.
|
|
57
|
+
*/
|
|
58
|
+
async get(cid) {
|
|
59
|
+
const row = this.storage.db
|
|
60
|
+
.prepare('SELECT data FROM content_blocks WHERE cid = ?')
|
|
61
|
+
.get(cid);
|
|
62
|
+
return row ? new Uint8Array(row.data) : null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if a block exists locally.
|
|
66
|
+
*/
|
|
67
|
+
has(cid) {
|
|
68
|
+
const row = this.storage.db
|
|
69
|
+
.prepare('SELECT 1 FROM content_blocks WHERE cid = ?')
|
|
70
|
+
.get(cid);
|
|
71
|
+
return !!row;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Store a file from disk, chunking into blocks.
|
|
75
|
+
* Returns a manifest describing all blocks.
|
|
76
|
+
*/
|
|
77
|
+
async storeFile(filePath, author) {
|
|
78
|
+
const fileData = readFileSync(filePath);
|
|
79
|
+
return this.storeBuffer(fileData, basename(filePath), author);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Store raw buffer data, chunking into blocks.
|
|
83
|
+
*/
|
|
84
|
+
async storeBuffer(data, fileName, author) {
|
|
85
|
+
const buf = Buffer.from(data);
|
|
86
|
+
const blocks = [];
|
|
87
|
+
for (let offset = 0; offset < buf.byteLength; offset += BLOCK_SIZE) {
|
|
88
|
+
const chunk = new Uint8Array(buf.subarray(offset, Math.min(offset + BLOCK_SIZE, buf.byteLength)));
|
|
89
|
+
const cid = await this.put(chunk);
|
|
90
|
+
blocks.push({ cid, offset, size: chunk.byteLength });
|
|
91
|
+
}
|
|
92
|
+
// Root CID = hash of all block CIDs concatenated
|
|
93
|
+
const { blake3 } = await import('@noble/hashes/blake3');
|
|
94
|
+
const rootData = new TextEncoder().encode(blocks.map(b => b.cid).join(':'));
|
|
95
|
+
const rootCid = Buffer.from(blake3(rootData)).toString('hex');
|
|
96
|
+
const manifest = {
|
|
97
|
+
rootCid,
|
|
98
|
+
fileName,
|
|
99
|
+
totalSize: buf.byteLength,
|
|
100
|
+
blockSize: BLOCK_SIZE,
|
|
101
|
+
blocks,
|
|
102
|
+
createdAt: Date.now(),
|
|
103
|
+
author,
|
|
104
|
+
};
|
|
105
|
+
// Persist manifest
|
|
106
|
+
this.manifests.set(rootCid, manifest);
|
|
107
|
+
this.storage.db
|
|
108
|
+
.prepare('INSERT OR REPLACE INTO file_manifests (root_cid, manifest) VALUES (?, ?)')
|
|
109
|
+
.run(rootCid, JSON.stringify(manifest));
|
|
110
|
+
return manifest;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Reassemble a file from its manifest.
|
|
114
|
+
* All blocks must be locally available.
|
|
115
|
+
*/
|
|
116
|
+
async retrieveFile(manifest) {
|
|
117
|
+
const result = Buffer.alloc(manifest.totalSize);
|
|
118
|
+
for (const block of manifest.blocks) {
|
|
119
|
+
const data = await this.get(block.cid);
|
|
120
|
+
if (!data) {
|
|
121
|
+
throw new Error(`Missing block ${block.cid} for file ${manifest.fileName}`);
|
|
122
|
+
}
|
|
123
|
+
Buffer.from(data).copy(result, block.offset);
|
|
124
|
+
}
|
|
125
|
+
return new Uint8Array(result);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Save reassembled file to disk.
|
|
129
|
+
*/
|
|
130
|
+
async saveFile(manifest, outputPath) {
|
|
131
|
+
const data = await this.retrieveFile(manifest);
|
|
132
|
+
writeFileSync(outputPath, data);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get a manifest by root CID.
|
|
136
|
+
*/
|
|
137
|
+
getManifest(rootCid) {
|
|
138
|
+
if (this.manifests.has(rootCid)) {
|
|
139
|
+
return this.manifests.get(rootCid);
|
|
140
|
+
}
|
|
141
|
+
const row = this.storage.db
|
|
142
|
+
.prepare('SELECT manifest FROM file_manifests WHERE root_cid = ?')
|
|
143
|
+
.get(rootCid);
|
|
144
|
+
if (row) {
|
|
145
|
+
const manifest = JSON.parse(row.manifest);
|
|
146
|
+
this.manifests.set(rootCid, manifest);
|
|
147
|
+
return manifest;
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* List all stored file manifests.
|
|
153
|
+
*/
|
|
154
|
+
listFiles() {
|
|
155
|
+
const rows = this.storage.db
|
|
156
|
+
.prepare('SELECT manifest FROM file_manifests ORDER BY created_at DESC')
|
|
157
|
+
.all();
|
|
158
|
+
return rows.map(r => JSON.parse(r.manifest));
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* List missing blocks for a manifest (for fetching from peers).
|
|
162
|
+
*/
|
|
163
|
+
getMissingBlocks(manifest) {
|
|
164
|
+
return manifest.blocks
|
|
165
|
+
.filter(b => !this.has(b.cid))
|
|
166
|
+
.map(b => b.cid);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Store a manifest received from a peer (without blocks).
|
|
170
|
+
*/
|
|
171
|
+
addRemoteManifest(manifest) {
|
|
172
|
+
this.manifests.set(manifest.rootCid, manifest);
|
|
173
|
+
this.storage.db
|
|
174
|
+
.prepare('INSERT OR REPLACE INTO file_manifests (root_cid, manifest) VALUES (?, ?)')
|
|
175
|
+
.run(manifest.rootCid, JSON.stringify(manifest));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=content-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-store.js","sourceRoot":"","sources":["../src/content-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Society Protocol — ZKP Identity Proofs (Schnorr PoK)
|
|
3
|
+
*
|
|
4
|
+
* Non-interactive Schnorr proof of DID/key ownership via Fiat-Shamir.
|
|
5
|
+
* Ed25519 signatures ARE Schnorr signatures — we use ed.sign(challenge, key)
|
|
6
|
+
* as a zero-knowledge proof of private key ownership.
|
|
7
|
+
*
|
|
8
|
+
* Based on: Agent-OSI Layer 3 (arxiv 2602.13795)
|
|
9
|
+
*/
|
|
10
|
+
import { type Identity } from './identity.js';
|
|
11
|
+
export interface IdentityProof {
|
|
12
|
+
did: string;
|
|
13
|
+
challenge: string;
|
|
14
|
+
proof: string;
|
|
15
|
+
roomId: string;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
nonce: string;
|
|
18
|
+
expiresAt: number;
|
|
19
|
+
}
|
|
20
|
+
export interface IdentityProofVerifyResult {
|
|
21
|
+
valid: boolean;
|
|
22
|
+
did: string;
|
|
23
|
+
reason?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a non-interactive Schnorr proof of DID ownership.
|
|
27
|
+
*
|
|
28
|
+
* The challenge is SHA-512(did || roomId || timestamp || nonce),
|
|
29
|
+
* and the proof is ed.sign(challenge, privateKey).
|
|
30
|
+
*/
|
|
31
|
+
export declare function createIdentityProof(identity: Identity, roomId: string, ttlMs?: number): IdentityProof;
|
|
32
|
+
/**
|
|
33
|
+
* Verify a non-interactive Schnorr proof of DID ownership.
|
|
34
|
+
*
|
|
35
|
+
* 1. Recompute the challenge from the proof fields
|
|
36
|
+
* 2. Extract public key from the DID
|
|
37
|
+
* 3. Verify the Ed25519 signature
|
|
38
|
+
* 4. Check TTL expiration
|
|
39
|
+
*/
|
|
40
|
+
export declare function verifyIdentityProof(proof: IdentityProof): IdentityProofVerifyResult;
|
|
41
|
+
export declare function serializeIdentityProof(proof: IdentityProof): Uint8Array;
|
|
42
|
+
export declare function deserializeIdentityProof(data: Uint8Array): IdentityProof;
|
|
43
|
+
//# sourceMappingURL=identity-proof.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-proof.d.ts","sourceRoot":"","sources":["../src/identity-proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIhE,MAAM,WAAW,aAAa;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAuB,GAC/B,aAAa,CAuBf;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,yBAAyB,CAoCnF;AAID,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,CAEvE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,CAExE"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Society Protocol — ZKP Identity Proofs (Schnorr PoK)
|
|
3
|
+
*
|
|
4
|
+
* Non-interactive Schnorr proof of DID/key ownership via Fiat-Shamir.
|
|
5
|
+
* Ed25519 signatures ARE Schnorr signatures — we use ed.sign(challenge, key)
|
|
6
|
+
* as a zero-knowledge proof of private key ownership.
|
|
7
|
+
*
|
|
8
|
+
* Based on: Agent-OSI Layer 3 (arxiv 2602.13795)
|
|
9
|
+
*/
|
|
10
|
+
import * as ed from '@noble/ed25519';
|
|
11
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
12
|
+
import { toString as uint8ToString, fromString as uint8FromString } from 'uint8arrays';
|
|
13
|
+
import { randomBytes as cryptoRandomBytes } from 'crypto';
|
|
14
|
+
import { publicKeyFromDid } from './identity.js';
|
|
15
|
+
// ─── Proof Generation ───────────────────────────────────────────
|
|
16
|
+
const DEFAULT_TTL_MS = 300_000; // 5 minutes
|
|
17
|
+
/**
|
|
18
|
+
* Create a non-interactive Schnorr proof of DID ownership.
|
|
19
|
+
*
|
|
20
|
+
* The challenge is SHA-512(did || roomId || timestamp || nonce),
|
|
21
|
+
* and the proof is ed.sign(challenge, privateKey).
|
|
22
|
+
*/
|
|
23
|
+
export function createIdentityProof(identity, roomId, ttlMs = DEFAULT_TTL_MS) {
|
|
24
|
+
const timestamp = Date.now();
|
|
25
|
+
const nonce = uint8ToString(randomBytes(16), 'base16');
|
|
26
|
+
const expiresAt = timestamp + ttlMs;
|
|
27
|
+
// Build challenge: SHA-512(did || roomId || timestamp || nonce)
|
|
28
|
+
const challengeInput = `${identity.did}|${roomId}|${timestamp}|${nonce}`;
|
|
29
|
+
const challengeBytes = sha512(new TextEncoder().encode(challengeInput));
|
|
30
|
+
const challenge = uint8ToString(challengeBytes, 'base16');
|
|
31
|
+
// Sign the challenge as Schnorr PoK
|
|
32
|
+
const sig = ed.sign(challengeBytes, identity.privateKey);
|
|
33
|
+
const proof = uint8ToString(sig, 'base64');
|
|
34
|
+
return {
|
|
35
|
+
did: identity.did,
|
|
36
|
+
challenge,
|
|
37
|
+
proof,
|
|
38
|
+
roomId,
|
|
39
|
+
timestamp,
|
|
40
|
+
nonce,
|
|
41
|
+
expiresAt,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// ─── Proof Verification ────────────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* Verify a non-interactive Schnorr proof of DID ownership.
|
|
47
|
+
*
|
|
48
|
+
* 1. Recompute the challenge from the proof fields
|
|
49
|
+
* 2. Extract public key from the DID
|
|
50
|
+
* 3. Verify the Ed25519 signature
|
|
51
|
+
* 4. Check TTL expiration
|
|
52
|
+
*/
|
|
53
|
+
export function verifyIdentityProof(proof) {
|
|
54
|
+
// Check expiration
|
|
55
|
+
if (Date.now() > proof.expiresAt) {
|
|
56
|
+
return { valid: false, did: proof.did, reason: 'proof expired' };
|
|
57
|
+
}
|
|
58
|
+
// Recompute challenge
|
|
59
|
+
const challengeInput = `${proof.did}|${proof.roomId}|${proof.timestamp}|${proof.nonce}`;
|
|
60
|
+
const expectedChallengeBytes = sha512(new TextEncoder().encode(challengeInput));
|
|
61
|
+
const expectedChallenge = uint8ToString(expectedChallengeBytes, 'base16');
|
|
62
|
+
// Verify challenge matches
|
|
63
|
+
if (proof.challenge !== expectedChallenge) {
|
|
64
|
+
return { valid: false, did: proof.did, reason: 'challenge mismatch' };
|
|
65
|
+
}
|
|
66
|
+
// Extract public key from DID
|
|
67
|
+
let publicKey;
|
|
68
|
+
try {
|
|
69
|
+
publicKey = publicKeyFromDid(proof.did);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return { valid: false, did: proof.did, reason: 'invalid DID format' };
|
|
73
|
+
}
|
|
74
|
+
// Verify Ed25519 signature (Schnorr PoK)
|
|
75
|
+
try {
|
|
76
|
+
const sigBytes = uint8FromString(proof.proof, 'base64');
|
|
77
|
+
const valid = ed.verify(sigBytes, expectedChallengeBytes, publicKey);
|
|
78
|
+
if (!valid) {
|
|
79
|
+
return { valid: false, did: proof.did, reason: 'signature verification failed' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return { valid: false, did: proof.did, reason: 'signature verification error' };
|
|
84
|
+
}
|
|
85
|
+
return { valid: true, did: proof.did };
|
|
86
|
+
}
|
|
87
|
+
// ─── Serialization ──────────────────────────────────────────────
|
|
88
|
+
export function serializeIdentityProof(proof) {
|
|
89
|
+
return new TextEncoder().encode(JSON.stringify(proof));
|
|
90
|
+
}
|
|
91
|
+
export function deserializeIdentityProof(data) {
|
|
92
|
+
return JSON.parse(new TextDecoder().decode(data));
|
|
93
|
+
}
|
|
94
|
+
// ─── Utility ────────────────────────────────────────────────────
|
|
95
|
+
function randomBytes(n) {
|
|
96
|
+
return new Uint8Array(cryptoRandomBytes(n));
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=identity-proof.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-proof.js","sourceRoot":"","sources":["../src/identity-proof.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -52,12 +52,13 @@ import { SecurityManager } from './security.js';
|
|
|
52
52
|
import { IntegrationEngine } from './integration.js';
|
|
53
53
|
import { PersonaVaultEngine } from './persona/index.js';
|
|
54
54
|
import { ProactiveMissionEngine } from './proactive/engine.js';
|
|
55
|
+
import { ProactiveWatcher } from './proactive/watcher.js';
|
|
55
56
|
import { spawn, execSync } from 'child_process';
|
|
56
57
|
import { fileURLToPath } from 'url';
|
|
57
58
|
import { resolve } from 'path';
|
|
58
59
|
import { realpathSync } from 'fs';
|
|
59
60
|
import { createClient } from './sdk/client.js';
|
|
60
|
-
import { registerNode, resolveNode, stopHeartbeat } from './registry.js';
|
|
61
|
+
import { registerNode, resolveNode, stopHeartbeat, generateFriendlyName } from './registry.js';
|
|
61
62
|
// ─── Invite Code Helpers ─────────────────────────────────────────
|
|
62
63
|
// Encode a multiaddr + room into a short invite code: base64url
|
|
63
64
|
function encodeInvite(multiaddr, room) {
|
|
@@ -193,27 +194,23 @@ program
|
|
|
193
194
|
// Local invite (LAN)
|
|
194
195
|
const localMultiaddr = `/ip4/127.0.0.1/tcp/${port}/p2p/${peerId}`;
|
|
195
196
|
const localCode = encodeInvite(localMultiaddr, options.room);
|
|
197
|
+
// Auto-register with friendly name
|
|
198
|
+
const agentName = options.name || generateFriendlyName();
|
|
199
|
+
const registered = await registerNode(agentName, {
|
|
200
|
+
multiaddr: localMultiaddr,
|
|
201
|
+
room: options.room,
|
|
202
|
+
peerId,
|
|
203
|
+
name: agentName,
|
|
204
|
+
});
|
|
196
205
|
console.log(` ${green('Node running!')} Room: ${cyan(options.room)}`);
|
|
206
|
+
if (registered) {
|
|
207
|
+
console.log(` ${bold('Your address:')} ${cyan(`${agentName}@society.computer`)}`);
|
|
208
|
+
}
|
|
197
209
|
console.log('');
|
|
198
|
-
console.log(` ${bold('Share with friends
|
|
210
|
+
console.log(` ${bold('Share with friends:')}`);
|
|
199
211
|
console.log('');
|
|
200
|
-
console.log(` ${bold(cyan(`npx society join ${localCode}`))}`);
|
|
212
|
+
console.log(` ${bold(cyan(`npx society join ${registered ? agentName : localCode}`))}`);
|
|
201
213
|
console.log('');
|
|
202
|
-
// Register friendly name if provided
|
|
203
|
-
if (options.name) {
|
|
204
|
-
const registered = await registerNode(options.name, {
|
|
205
|
-
multiaddr: localMultiaddr,
|
|
206
|
-
room: options.room,
|
|
207
|
-
peerId,
|
|
208
|
-
name: options.name,
|
|
209
|
-
});
|
|
210
|
-
if (registered) {
|
|
211
|
-
console.log(` ${green('Registered!')} Friends can also join with:`);
|
|
212
|
-
console.log('');
|
|
213
|
-
console.log(` ${bold(cyan(`npx society join ${options.name}`))}`);
|
|
214
|
-
console.log('');
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
214
|
// If --relay, spawn cloudflared for a public URL
|
|
218
215
|
if (options.relay) {
|
|
219
216
|
const wsPort = port + 1;
|
|
@@ -237,22 +234,17 @@ program
|
|
|
237
234
|
console.log('');
|
|
238
235
|
console.log(` ${bold(cyan(`npx society join ${publicCode}`))}`);
|
|
239
236
|
// Update registry with public multiaddr
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
console.log('');
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
237
|
+
registerNode(agentName, {
|
|
238
|
+
multiaddr: publicMultiaddr,
|
|
239
|
+
room: options.room,
|
|
240
|
+
peerId,
|
|
241
|
+
name: agentName,
|
|
242
|
+
}).then(ok => {
|
|
243
|
+
if (ok) {
|
|
244
|
+
console.log(` ${bold(cyan(`npx society join ${agentName}`))}`);
|
|
245
|
+
}
|
|
254
246
|
console.log('');
|
|
255
|
-
}
|
|
247
|
+
});
|
|
256
248
|
}
|
|
257
249
|
});
|
|
258
250
|
process.on('SIGINT', () => { cfProc.kill(); });
|
|
@@ -335,6 +327,8 @@ program
|
|
|
335
327
|
.option('--relay', 'spawn cloudflared to create a public WebSocket relay')
|
|
336
328
|
.option('--gossipsub', 'enable GossipSub for scalable pub/sub', true)
|
|
337
329
|
.option('--dht', 'enable DHT for peer discovery', true)
|
|
330
|
+
.option('--encrypted', 'enable E2E encryption for all room messages')
|
|
331
|
+
.option('--proactive', 'enable proactive agent behavior (watches room, intervenes when relevant)')
|
|
338
332
|
.option('--mission-leader', 'enable proactive mission leadership with auto-restore', false)
|
|
339
333
|
.option('--provider <provider>', 'AI planner provider (openai|anthropic|ollama)', 'openai')
|
|
340
334
|
.option('--debug', 'enable debug logging')
|
|
@@ -773,10 +767,9 @@ async function startNode(options) {
|
|
|
773
767
|
// Banner
|
|
774
768
|
console.log('');
|
|
775
769
|
console.log(' ╔══════════════════════════════════════════════════════════╗');
|
|
776
|
-
console.log(' ║
|
|
777
|
-
console.log(' ║ P2P Multi-Agent Collaboration Network Node ║');
|
|
770
|
+
console.log(' ║ 🌐 Society Protocol v1.0 ║');
|
|
778
771
|
console.log(' ╠══════════════════════════════════════════════════════════╣');
|
|
779
|
-
console.log(' ║
|
|
772
|
+
console.log(' ║ GossipSub · Kad-DHT · did:key · CRDT · Reputation ║');
|
|
780
773
|
console.log(' ╚══════════════════════════════════════════════════════════╝');
|
|
781
774
|
console.log('');
|
|
782
775
|
// 1. Initialize storage
|
|
@@ -825,12 +818,22 @@ async function startNode(options) {
|
|
|
825
818
|
enableDht: options.dht,
|
|
826
819
|
enableGossipsub: options.gossipsub,
|
|
827
820
|
});
|
|
828
|
-
// 6. Initialize room manager
|
|
821
|
+
// 6. Initialize room manager + encryption
|
|
829
822
|
const rooms = new RoomManager(identity, p2p, storage);
|
|
823
|
+
if (options.encrypted) {
|
|
824
|
+
const { SecurityManager } = await import('./security.js');
|
|
825
|
+
const security = new SecurityManager(identity);
|
|
826
|
+
p2p.setSecurityManager(security);
|
|
827
|
+
await security.generateKeyPair();
|
|
828
|
+
console.log(`[init] E2E encryption enabled (AES-256-GCM + X25519)`);
|
|
829
|
+
}
|
|
830
830
|
// 7. Join room
|
|
831
831
|
const roomId = options.room;
|
|
832
832
|
await rooms.joinRoom(roomId, roomId);
|
|
833
|
-
|
|
833
|
+
if (options.encrypted) {
|
|
834
|
+
rooms.enableEncryption(roomId);
|
|
835
|
+
}
|
|
836
|
+
console.log(`[init] Joined room: ${roomId}${options.encrypted ? ' (encrypted)' : ''}`);
|
|
834
837
|
// 8. Initialize CoC Engine with reputation
|
|
835
838
|
const coc = new CocEngine(identity, rooms, storage, reputation);
|
|
836
839
|
// 9. Initialize Planner with multi-provider support
|
|
@@ -864,6 +867,7 @@ async function startNode(options) {
|
|
|
864
867
|
// 12. Initialize federation/integration stack (Federation Mesh)
|
|
865
868
|
const federation = new FederationEngine(storage, identity);
|
|
866
869
|
const knowledge = new KnowledgePool(storage, identity);
|
|
870
|
+
rooms.setKnowledgePool(knowledge); // Enable conversational knowledge exchange
|
|
867
871
|
const skills = new SkillsEngine(storage, identity);
|
|
868
872
|
const security = new SecurityManager(identity);
|
|
869
873
|
const persona = new PersonaVaultEngine(storage, identity.did, {
|
|
@@ -880,6 +884,16 @@ async function startNode(options) {
|
|
|
880
884
|
if (proactiveLeader) {
|
|
881
885
|
console.log('[init] Mission leader mode enabled (auto-restore active).');
|
|
882
886
|
}
|
|
887
|
+
// Initialize ProactiveWatcher if --proactive flag
|
|
888
|
+
let proactiveWatcher;
|
|
889
|
+
if (options.proactive) {
|
|
890
|
+
proactiveWatcher = new ProactiveWatcher(identity, {
|
|
891
|
+
level: 1,
|
|
892
|
+
specialties: [],
|
|
893
|
+
});
|
|
894
|
+
proactiveWatcher.watch(rooms, knowledge);
|
|
895
|
+
console.log(`[init] Proactive watcher enabled (level ${proactiveWatcher.getLevel()})`);
|
|
896
|
+
}
|
|
883
897
|
console.log('');
|
|
884
898
|
console.log(' Type a message and press Enter to send.');
|
|
885
899
|
console.log(' Commands: /peers /rooms /presence /reputation /info /history');
|
|
@@ -898,6 +912,8 @@ async function startNode(options) {
|
|
|
898
912
|
rl.prompt(true);
|
|
899
913
|
});
|
|
900
914
|
rooms.on('presence:update', (_roomId, envelope) => {
|
|
915
|
+
if (envelope.from.did === identity.did)
|
|
916
|
+
return; // Skip own presence
|
|
901
917
|
const body = envelope.body;
|
|
902
918
|
if (body.status === 'online') {
|
|
903
919
|
process.stdout.write('\r\x1b[K');
|
|
@@ -957,6 +973,18 @@ async function startNode(options) {
|
|
|
957
973
|
process.stdout.write('\r\x1b[K');
|
|
958
974
|
console.log(`\n ${bold(green('✅ Chain Completed'))}: ${chainId}\n`);
|
|
959
975
|
rl.prompt(true);
|
|
976
|
+
// Post-chain knowledge distillation
|
|
977
|
+
const chain = coc.getChain(chainId);
|
|
978
|
+
if (chain && knowledge) {
|
|
979
|
+
const participants = [...new Set(chain.steps.map(s => s.assignee_did).filter(Boolean))];
|
|
980
|
+
knowledge.distillChainExperience(chainId, chain.final_report || chain.goal, chain.goal, chain.room_id, participants.length > 0 ? participants : [identity.did]).then(cards => {
|
|
981
|
+
if (cards.length > 0) {
|
|
982
|
+
process.stdout.write('\r\x1b[K');
|
|
983
|
+
console.log(` ${dim(`📚 Distilled ${cards.length} knowledge card(s) from chain`)}`);
|
|
984
|
+
rl.prompt(true);
|
|
985
|
+
}
|
|
986
|
+
}).catch(() => { });
|
|
987
|
+
}
|
|
960
988
|
});
|
|
961
989
|
// ─── Interactive REPL ───────────────────────────────────────
|
|
962
990
|
const rl = readline.createInterface({
|
|
@@ -1033,6 +1061,8 @@ async function startNode(options) {
|
|
|
1033
1061
|
exporter,
|
|
1034
1062
|
federation,
|
|
1035
1063
|
integration,
|
|
1064
|
+
knowledge,
|
|
1065
|
+
proactiveWatcher,
|
|
1036
1066
|
roomId,
|
|
1037
1067
|
DEBUG,
|
|
1038
1068
|
});
|
|
@@ -1488,6 +1518,111 @@ async function handleCommand(input, ctx) {
|
|
|
1488
1518
|
}
|
|
1489
1519
|
break;
|
|
1490
1520
|
}
|
|
1521
|
+
case '/share': {
|
|
1522
|
+
const filePath = args.join(' ').trim();
|
|
1523
|
+
if (!filePath) {
|
|
1524
|
+
console.log(` Usage: /share <filepath>`);
|
|
1525
|
+
break;
|
|
1526
|
+
}
|
|
1527
|
+
try {
|
|
1528
|
+
const { ContentStore } = await import('./content-store.js');
|
|
1529
|
+
const contentStore = new ContentStore(ctx.storage);
|
|
1530
|
+
const manifest = await contentStore.storeFile(filePath, ctx.identity.did);
|
|
1531
|
+
const sizeKB = (manifest.totalSize / 1024).toFixed(1);
|
|
1532
|
+
console.log(` ${green('Shared!')} ${manifest.fileName} (${sizeKB}KB, ${manifest.blocks.length} blocks)`);
|
|
1533
|
+
console.log(` CID: ${dim(manifest.rootCid.slice(0, 16))}...`);
|
|
1534
|
+
// Broadcast manifest to room
|
|
1535
|
+
const body = { type: 'artifact.offer', manifest };
|
|
1536
|
+
const swp = await import('./swp.js');
|
|
1537
|
+
const envelope = swp.createEnvelope(ctx.identity, 'artifact.offer', ctx.roomId, body);
|
|
1538
|
+
const data = new TextEncoder().encode(JSON.stringify(envelope));
|
|
1539
|
+
await ctx.p2p.publish(`${ctx.roomId}/artifacts`, data);
|
|
1540
|
+
}
|
|
1541
|
+
catch (err) {
|
|
1542
|
+
console.log(` Error: ${err.message}`);
|
|
1543
|
+
}
|
|
1544
|
+
break;
|
|
1545
|
+
}
|
|
1546
|
+
case '/files': {
|
|
1547
|
+
try {
|
|
1548
|
+
const { ContentStore } = await import('./content-store.js');
|
|
1549
|
+
const contentStore = new ContentStore(ctx.storage);
|
|
1550
|
+
const files = contentStore.listFiles();
|
|
1551
|
+
if (files.length === 0) {
|
|
1552
|
+
console.log(` No files shared yet. Use /share <filepath>`);
|
|
1553
|
+
}
|
|
1554
|
+
else {
|
|
1555
|
+
console.log(` ${bold('Shared files:')}`);
|
|
1556
|
+
for (const f of files) {
|
|
1557
|
+
const sizeKB = (f.totalSize / 1024).toFixed(1);
|
|
1558
|
+
const date = new Date(f.createdAt).toLocaleTimeString();
|
|
1559
|
+
console.log(` ${f.fileName} (${sizeKB}KB) — ${dim(date)} — CID: ${dim(f.rootCid.slice(0, 12))}...`);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
catch (err) {
|
|
1564
|
+
console.log(` Error: ${err.message}`);
|
|
1565
|
+
}
|
|
1566
|
+
break;
|
|
1567
|
+
}
|
|
1568
|
+
case '/encrypt': {
|
|
1569
|
+
const subCmd = args[0]?.toLowerCase();
|
|
1570
|
+
if (subCmd === 'on') {
|
|
1571
|
+
ctx.rooms.enableEncryption(ctx.roomId);
|
|
1572
|
+
console.log(` ${green('E2E encryption enabled')} for this room`);
|
|
1573
|
+
}
|
|
1574
|
+
else if (subCmd === 'off') {
|
|
1575
|
+
ctx.rooms.disableEncryption(ctx.roomId);
|
|
1576
|
+
console.log(` Encryption disabled for this room`);
|
|
1577
|
+
}
|
|
1578
|
+
else {
|
|
1579
|
+
const status = ctx.rooms.isEncrypted(ctx.roomId) ? green('ON') : 'OFF';
|
|
1580
|
+
console.log(` Encryption: ${status}`);
|
|
1581
|
+
console.log(` Usage: /encrypt on | /encrypt off`);
|
|
1582
|
+
}
|
|
1583
|
+
break;
|
|
1584
|
+
}
|
|
1585
|
+
case '/context': {
|
|
1586
|
+
const knowledge = ctx.knowledge;
|
|
1587
|
+
if (!knowledge) {
|
|
1588
|
+
console.log(` Knowledge system not available`);
|
|
1589
|
+
break;
|
|
1590
|
+
}
|
|
1591
|
+
const sharedCtx = knowledge.getSharedContext(ctx.roomId);
|
|
1592
|
+
if (sharedCtx) {
|
|
1593
|
+
console.log(sharedCtx);
|
|
1594
|
+
}
|
|
1595
|
+
else {
|
|
1596
|
+
console.log(` No shared context yet. Chat to build collaborative knowledge.`);
|
|
1597
|
+
}
|
|
1598
|
+
break;
|
|
1599
|
+
}
|
|
1600
|
+
case '/proactive': {
|
|
1601
|
+
const subCmd = args[0];
|
|
1602
|
+
if (!ctx.proactiveWatcher) {
|
|
1603
|
+
console.log(` Proactive watcher not initialized. Start with --proactive flag.`);
|
|
1604
|
+
break;
|
|
1605
|
+
}
|
|
1606
|
+
if (subCmd === 'on') {
|
|
1607
|
+
ctx.proactiveWatcher.setLevel(1);
|
|
1608
|
+
console.log(` Proactive watcher: ${green('ON')} (level 1 - moderate)`);
|
|
1609
|
+
}
|
|
1610
|
+
else if (subCmd === 'off') {
|
|
1611
|
+
ctx.proactiveWatcher.setLevel(0);
|
|
1612
|
+
console.log(` Proactive watcher: OFF`);
|
|
1613
|
+
}
|
|
1614
|
+
else if (subCmd === '2' || subCmd === 'aggressive') {
|
|
1615
|
+
ctx.proactiveWatcher.setLevel(2);
|
|
1616
|
+
console.log(` Proactive watcher: ${green('ON')} (level 2 - aggressive)`);
|
|
1617
|
+
}
|
|
1618
|
+
else {
|
|
1619
|
+
const level = ctx.proactiveWatcher.getLevel();
|
|
1620
|
+
const labels = ['OFF', 'moderate', 'aggressive'];
|
|
1621
|
+
console.log(` Proactive watcher: level ${level} (${labels[level]})`);
|
|
1622
|
+
console.log(` Usage: /proactive on | off | 2`);
|
|
1623
|
+
}
|
|
1624
|
+
break;
|
|
1625
|
+
}
|
|
1491
1626
|
case '/debug': {
|
|
1492
1627
|
console.log(` Debug mode: ${ctx.DEBUG ? 'ON' : 'OFF'}`);
|
|
1493
1628
|
break;
|
|
@@ -1499,7 +1634,7 @@ async function handleCommand(input, ctx) {
|
|
|
1499
1634
|
console.log(` Unknown command: ${cmd}`);
|
|
1500
1635
|
console.log(' Available: /peers /rooms /presence /reputation /info /history');
|
|
1501
1636
|
console.log(' /summon /template /chains /chain /step /assign /review');
|
|
1502
|
-
console.log(' /cancel /export /cache /debug /quit');
|
|
1637
|
+
console.log(' /cancel /export /cache /encrypt /context /proactive /debug /quit');
|
|
1503
1638
|
console.log(' /mesh-request /mesh-accept /mesh-reject /mesh-revoke /mesh-peerings');
|
|
1504
1639
|
console.log(' /mesh-open /mesh-close /mesh-bridges /mesh-stats');
|
|
1505
1640
|
}
|