@openvole/volenet 1.0.0 → 1.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.
- package/dist/index.d.ts +127 -4
- package/dist/index.js +361 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -76,7 +76,7 @@ declare class RelayNotices {
|
|
|
76
76
|
* The local node's post-quantum (ML-DSA) signing key, set once at VoleNet start.
|
|
77
77
|
* Module-level because there is exactly one signing identity per process — this lets
|
|
78
78
|
*/
|
|
79
|
-
type VoleNetMessageType = 'ping' | 'pong' | 'discover' | 'discover:response' | 'auth:challenge' | 'auth:response' | 'auth:result' | 'task:delegate' | 'task:result' | 'task:status' | 'memory:sync' | 'memory:search' | 'memory:results' | 'session:sync' | 'tool:list' | 'tool:list:response' | 'tool:call' | 'tool:result' | 'leader:heartbeat' | 'leader:claim' | 'leader:ack' | 'chat:message' | 'sealed' | 'sealed:direct' | 'relay:deliver' | 'relay:error' | 'relay:ack' | 'relay:pending' | 'roster' | 'relay:connect-request' | 'relay:connect-accept' | 'relay:connect-deny' | 'file:offer' | 'file:accept' | 'file:reject' | 'file:relay-ready' | 'file:done' | 'file:error' | 'file:cancel' | 'relay:blob:create' | 'relay:blob:grant' | 'relay:blob:deny' | 'relay:blob:fetch' | 'relay:blob:done';
|
|
79
|
+
type VoleNetMessageType = 'ping' | 'pong' | 'discover' | 'discover:response' | 'auth:challenge' | 'auth:response' | 'auth:result' | 'task:delegate' | 'task:result' | 'task:status' | 'memory:sync' | 'memory:search' | 'memory:results' | 'session:sync' | 'tool:list' | 'tool:list:response' | 'tool:call' | 'tool:result' | 'leader:heartbeat' | 'leader:claim' | 'leader:ack' | 'chat:message' | 'sealed' | 'sealed:direct' | 'relay:deliver' | 'room:create' | 'room:join' | 'room:leave' | 'room:invite' | 'room:list' | 'room:list:response' | 'room:info' | 'room:members' | 'room:error' | 'relay:error' | 'relay:ack' | 'relay:pending' | 'roster' | 'relay:connect-request' | 'relay:connect-accept' | 'relay:connect-deny' | 'file:offer' | 'file:accept' | 'file:reject' | 'file:relay-ready' | 'file:done' | 'file:error' | 'file:cancel' | 'relay:blob:create' | 'relay:blob:grant' | 'relay:blob:deny' | 'relay:blob:fetch' | 'relay:blob:done';
|
|
80
80
|
interface VoleNetMessage {
|
|
81
81
|
version: number;
|
|
82
82
|
id: string;
|
|
@@ -249,6 +249,11 @@ declare class VoleNetTransport {
|
|
|
249
249
|
*/
|
|
250
250
|
start(): Promise<void>;
|
|
251
251
|
/** Bind the listening port, retrying briefly on EADDRINUSE (covers restart races). */
|
|
252
|
+
/**
|
|
253
|
+
* The port actually bound, which is not always the one configured — a host may pass 0 and let
|
|
254
|
+
* the OS choose. Null before the server is listening.
|
|
255
|
+
*/
|
|
256
|
+
getPort(): number | null;
|
|
252
257
|
private listen;
|
|
253
258
|
/**
|
|
254
259
|
* Stop the transport.
|
|
@@ -703,6 +708,55 @@ declare class RemoteTaskManager {
|
|
|
703
708
|
dispose(): void;
|
|
704
709
|
}
|
|
705
710
|
|
|
711
|
+
/** The size past which sealing per member stops being sensible. Enforced by the hub at join. */
|
|
712
|
+
declare const MAX_ROOM_MEMBERS = 64;
|
|
713
|
+
/** How long a room with nobody in it is kept before the hub forgets it. */
|
|
714
|
+
declare const EMPTY_ROOM_TTL_MS: number;
|
|
715
|
+
interface RoomRecord {
|
|
716
|
+
id: string;
|
|
717
|
+
name: string;
|
|
718
|
+
topic?: string;
|
|
719
|
+
/** Instance ids. Keys are looked up from the hub's own directory when a room is described. */
|
|
720
|
+
members: string[];
|
|
721
|
+
createdAt: number;
|
|
722
|
+
/** When the room last had a member, so an abandoned one can be forgotten. */
|
|
723
|
+
lastOccupied: number;
|
|
724
|
+
}
|
|
725
|
+
/** A room as a member sees it: enough to fan out a post without asking anything further. */
|
|
726
|
+
interface RoomMember {
|
|
727
|
+
instanceId: string;
|
|
728
|
+
name: string;
|
|
729
|
+
publicKey: string;
|
|
730
|
+
xPublicKey?: string;
|
|
731
|
+
mlkemPublicKey?: string;
|
|
732
|
+
}
|
|
733
|
+
interface RoomInfo {
|
|
734
|
+
room: string;
|
|
735
|
+
name: string;
|
|
736
|
+
topic?: string;
|
|
737
|
+
members: RoomMember[];
|
|
738
|
+
}
|
|
739
|
+
type RoomError = 'full' | 'not-a-member' | 'no-such-room' | 'refused';
|
|
740
|
+
/** The hub's side: who is in what. Persisted, so a restart does not dissolve every room. */
|
|
741
|
+
declare class RoomStore {
|
|
742
|
+
private readonly file;
|
|
743
|
+
private rooms;
|
|
744
|
+
private writing;
|
|
745
|
+
constructor(file: string);
|
|
746
|
+
load(now?: number): Promise<void>;
|
|
747
|
+
get(id: string): RoomRecord | undefined;
|
|
748
|
+
list(): RoomRecord[];
|
|
749
|
+
/** Rooms this member belongs to. */
|
|
750
|
+
forMember(instanceId: string): RoomRecord[];
|
|
751
|
+
create(name: string, creator: string, topic?: string): Promise<RoomRecord>;
|
|
752
|
+
/** Add a member. The ceiling is the design's edge, so it is refused rather than stretched. */
|
|
753
|
+
join(id: string, instanceId: string): Promise<RoomRecord | RoomError>;
|
|
754
|
+
leave(id: string, instanceId: string): Promise<RoomRecord | RoomError>;
|
|
755
|
+
/** Drop rooms nobody has been in for the TTL. */
|
|
756
|
+
sweep(now?: number): Promise<RoomRecord[]>;
|
|
757
|
+
private persist;
|
|
758
|
+
}
|
|
759
|
+
|
|
706
760
|
/**
|
|
707
761
|
* VoleNet Sync — memory and session synchronization across peers.
|
|
708
762
|
*
|
|
@@ -1048,6 +1102,17 @@ interface VoleNetConfig {
|
|
|
1048
1102
|
* live-only, which is the right default for a library.
|
|
1049
1103
|
*/
|
|
1050
1104
|
persistPeer?: (url: string) => Promise<void>;
|
|
1105
|
+
/**
|
|
1106
|
+
* Remember a peer entry that has no url — one named by identity, as an address-less peer must
|
|
1107
|
+
* be. Separate from `persistPeer` rather than widening it, so a host written against the
|
|
1108
|
+
* earlier callback keeps working.
|
|
1109
|
+
*/
|
|
1110
|
+
persistPeerEntry?: (entry: {
|
|
1111
|
+
id?: string;
|
|
1112
|
+
name?: string;
|
|
1113
|
+
trust?: string;
|
|
1114
|
+
allowBrain?: boolean;
|
|
1115
|
+
}) => Promise<void>;
|
|
1051
1116
|
peers?: Array<{
|
|
1052
1117
|
/**
|
|
1053
1118
|
* Where to reach this peer. Also how the entry is matched to a connected peer, by
|
|
@@ -1202,6 +1267,20 @@ interface VoleNetConfig {
|
|
|
1202
1267
|
*/
|
|
1203
1268
|
files?: VoleNetFilesConfig;
|
|
1204
1269
|
}
|
|
1270
|
+
/**
|
|
1271
|
+
* What a peer asks for when it introduces itself, beyond being trusted at all.
|
|
1272
|
+
*
|
|
1273
|
+
* Trust and permission are separate — the keystore says who may connect, `net.peers` says what
|
|
1274
|
+
* they may then do — and that split used to mean the operator accepted a pair request and then,
|
|
1275
|
+
* separately, hand-edited a config file to make the peer useful. A requester can now say what it
|
|
1276
|
+
* is for, so accepting is one decision made with the reason in front of you.
|
|
1277
|
+
*/
|
|
1278
|
+
type PairWant = 'brain';
|
|
1279
|
+
/** What the operator grants when accepting. Absent means trust only, as before. */
|
|
1280
|
+
interface PairGrant {
|
|
1281
|
+
trust?: 'full' | 'tool' | 'read';
|
|
1282
|
+
allowBrain?: boolean;
|
|
1283
|
+
}
|
|
1205
1284
|
/** A hub-vouched mesh member, learned from a relay hub's roster broadcast. */
|
|
1206
1285
|
interface RosterMember {
|
|
1207
1286
|
instanceId: string;
|
|
@@ -1260,6 +1339,10 @@ declare class VoleNetManager {
|
|
|
1260
1339
|
private relayNotices;
|
|
1261
1340
|
/** Brain answers whose asker had gone by the time they were ready — see result-outbox.ts. */
|
|
1262
1341
|
private resultOutbox;
|
|
1342
|
+
/** Hub side: who is in which room (§7c). Only a relay hub keeps these. */
|
|
1343
|
+
private roomStore;
|
|
1344
|
+
/** Member side: rooms this node is in, as the hub last described them. */
|
|
1345
|
+
private rooms;
|
|
1263
1346
|
/** Peers a flush is already running for, so a burst of pings does not send an answer twice. */
|
|
1264
1347
|
private flushingResults;
|
|
1265
1348
|
/** The polling timers waiting on delegated tasks, so stopping cancels them. */
|
|
@@ -1448,6 +1531,36 @@ declare class VoleNetManager {
|
|
|
1448
1531
|
private rosterName;
|
|
1449
1532
|
private findRosterMember;
|
|
1450
1533
|
/** Hub: push the current member directory to every connected member. */
|
|
1534
|
+
/** Rooms this node is in, as its hub last described them. */
|
|
1535
|
+
getRooms(): RoomInfo[];
|
|
1536
|
+
/** Ask a hub to make a room, join one, leave one, invite to one, or list what it has. */
|
|
1537
|
+
roomCommand(hubRef: string, type: 'room:create' | 'room:join' | 'room:leave' | 'room:invite' | 'room:list', payload: Record<string, unknown>): Promise<{
|
|
1538
|
+
ok: boolean;
|
|
1539
|
+
error?: string;
|
|
1540
|
+
}>;
|
|
1541
|
+
/**
|
|
1542
|
+
* Post to a room: one sealed copy per member.
|
|
1543
|
+
*
|
|
1544
|
+
* There is no room key, so this is the fan-out itself — the same `chat:message` sealed to each
|
|
1545
|
+
* member in turn (§7c). Everything §7 gives a private message therefore applies to each copy:
|
|
1546
|
+
* a member who is away has theirs held in this node's outbox and delivered when they return,
|
|
1547
|
+
* and consent still gates whether they accept anything from us at all.
|
|
1548
|
+
*/
|
|
1549
|
+
postToRoom(roomId: string, text: string): Promise<{
|
|
1550
|
+
ok: boolean;
|
|
1551
|
+
sent: number;
|
|
1552
|
+
held: number;
|
|
1553
|
+
skipped: number;
|
|
1554
|
+
error?: string;
|
|
1555
|
+
}>;
|
|
1556
|
+
/** Act on a member's room command and answer it. */
|
|
1557
|
+
private handleRoomCommand;
|
|
1558
|
+
/** A room as its members need to see it: ids *and keys*, since a sender fans out itself. */
|
|
1559
|
+
private describeRoom;
|
|
1560
|
+
/** Tell everyone in a room who is in it now. */
|
|
1561
|
+
private pushRoomMembers;
|
|
1562
|
+
/** Signed, unsealed, straight to one member. Room control is hub business, not private. */
|
|
1563
|
+
private sendToMember;
|
|
1451
1564
|
private broadcastRoster;
|
|
1452
1565
|
/** Hand a member that just reconnected everything the hub noted for it while it was away. */
|
|
1453
1566
|
private sendRelayNotices;
|
|
@@ -1537,12 +1650,22 @@ declare class VoleNetManager {
|
|
|
1537
1650
|
name: string;
|
|
1538
1651
|
endpoint?: string;
|
|
1539
1652
|
note?: string;
|
|
1653
|
+
wants?: PairWant[];
|
|
1540
1654
|
ts: number;
|
|
1541
1655
|
}>;
|
|
1542
1656
|
/** Operator consent: trust the requester's pinned key, live-reload, dial back if possible. */
|
|
1543
|
-
|
|
1657
|
+
/**
|
|
1658
|
+
* Accept a pair request, and optionally grant what it asked for in the same act.
|
|
1659
|
+
*
|
|
1660
|
+
* Trusting a key and saying what that key may do were two steps in two places — the second a
|
|
1661
|
+
* hand-edited config file and a restart — which is why a paired peer so often sat there unable
|
|
1662
|
+
* to do the thing it was paired for. A grant writes a `net.peers` entry naming the peer's
|
|
1663
|
+
* identity, live, so it applies without a restart, and asks the host to remember it.
|
|
1664
|
+
*/
|
|
1665
|
+
acceptPair(ref: string, grant?: PairGrant): Promise<{
|
|
1544
1666
|
ok: boolean;
|
|
1545
1667
|
name?: string;
|
|
1668
|
+
granted?: PairGrant;
|
|
1546
1669
|
error?: string;
|
|
1547
1670
|
}>;
|
|
1548
1671
|
denyPair(ref: string): Promise<{
|
|
@@ -1574,7 +1697,7 @@ declare class VoleNetManager {
|
|
|
1574
1697
|
* fingerprint client-side), persist + dial the peer, and file the pair request for
|
|
1575
1698
|
* the other operator. Fully live — no restart needed on this side.
|
|
1576
1699
|
*/
|
|
1577
|
-
initiatePair(url: string, publicKey: string, note?: string): Promise<{
|
|
1700
|
+
initiatePair(url: string, publicKey: string, note?: string, wants?: PairWant[]): Promise<{
|
|
1578
1701
|
ok: boolean;
|
|
1579
1702
|
pending?: boolean;
|
|
1580
1703
|
alreadyTrusted?: boolean;
|
|
@@ -1670,4 +1793,4 @@ declare function upsertPeerUrl(peers: PeerEntry[], url: string): {
|
|
|
1670
1793
|
replaced?: string;
|
|
1671
1794
|
};
|
|
1672
1795
|
|
|
1673
|
-
export { CONTROL_PLANE_PAWS, type ChatEntry, ChatOutbox, DEFAULT_NOTICE_TTL_MS, DEFAULT_OUTBOX_TTL_MS, DEFAULT_RESULT_TTL_MS, type EventBus, type EventSink, type LeaderState, type Logger, type LoggerFactory, MAX_RESULTS_PER_PEER, type MemorySearchRequest, type MemorySearchResult, type MemorySyncEntry, type OutboxEntry, type OutboxKind, type PendingResult, type RelayNotice, RelayNotices, RemoteTaskManager, type RemoteTaskRequest, type RemoteTaskResult, type RemoteToolCallRequest, type RemoteToolCallResult, type RemoteToolInfo, ResultOutbox, type RosterMember, type SealedBox, type SessionSyncEntry, type SharedToolDefinition, type SharedToolEntry, type ToolProvider, type VoleKeyPair, type VoleNetConfig, VoleNetDiscovery, type VoleNetInstance, VoleNetLeader, VoleNetManager, type VoleNetMessage, type VoleNetMessageType, VoleNetSync, VoleNetTransport, addRelayAccept, buildAdvertisedEndpoint, closeLogger, createEventBus, createLogger, createMessage, findEndpointDrift, generateKeyPair, isControlPlanePaw, isSharedTool, loadAuthorizedVoles, loadKeyPair, loadRelayAccepts, parsePublicKey, peerPrefix, removeRelayAccept, revokePeer, seal, setLoggerFactory, trustPeer, unseal, upsertPeerUrl, verifyMessage, withVerifiedCaller };
|
|
1796
|
+
export { CONTROL_PLANE_PAWS, type ChatEntry, ChatOutbox, DEFAULT_NOTICE_TTL_MS, DEFAULT_OUTBOX_TTL_MS, DEFAULT_RESULT_TTL_MS, EMPTY_ROOM_TTL_MS, type EventBus, type EventSink, type LeaderState, type Logger, type LoggerFactory, MAX_RESULTS_PER_PEER, MAX_ROOM_MEMBERS, type MemorySearchRequest, type MemorySearchResult, type MemorySyncEntry, type OutboxEntry, type OutboxKind, type PairGrant, type PairWant, type PendingResult, type RelayNotice, RelayNotices, RemoteTaskManager, type RemoteTaskRequest, type RemoteTaskResult, type RemoteToolCallRequest, type RemoteToolCallResult, type RemoteToolInfo, ResultOutbox, type RoomError, type RoomInfo, type RoomMember, type RoomRecord, RoomStore, type RosterMember, type SealedBox, type SessionSyncEntry, type SharedToolDefinition, type SharedToolEntry, type ToolProvider, type VoleKeyPair, type VoleNetConfig, VoleNetDiscovery, type VoleNetInstance, VoleNetLeader, VoleNetManager, type VoleNetMessage, type VoleNetMessageType, VoleNetSync, VoleNetTransport, addRelayAccept, buildAdvertisedEndpoint, closeLogger, createEventBus, createLogger, createMessage, findEndpointDrift, generateKeyPair, isControlPlanePaw, isSharedTool, loadAuthorizedVoles, loadKeyPair, loadRelayAccepts, parsePublicKey, peerPrefix, removeRelayAccept, revokePeer, seal, setLoggerFactory, trustPeer, unseal, upsertPeerUrl, verifyMessage, withVerifiedCaller };
|