@contextvm/sdk 0.1.47 → 0.2.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/esm/core/constants.d.ts +3 -0
- package/dist/esm/core/constants.d.ts.map +1 -1
- package/dist/esm/core/constants.js +3 -0
- package/dist/esm/core/constants.js.map +1 -1
- package/dist/esm/core/utils/logger.d.ts +1 -1
- package/dist/esm/core/utils/logger.d.ts.map +1 -1
- package/dist/esm/core/utils/lru-cache.d.ts.map +1 -1
- package/dist/esm/core/utils/lru-cache.js +9 -1
- package/dist/esm/core/utils/lru-cache.js.map +1 -1
- package/dist/esm/core/utils/task-queue.d.ts +5 -0
- package/dist/esm/core/utils/task-queue.d.ts.map +1 -1
- package/dist/esm/core/utils/task-queue.js +11 -0
- package/dist/esm/core/utils/task-queue.js.map +1 -1
- package/dist/esm/core/utils/utils.d.ts +8 -0
- package/dist/esm/core/utils/utils.d.ts.map +1 -1
- package/dist/esm/core/utils/utils.js +23 -0
- package/dist/esm/core/utils/utils.js.map +1 -1
- package/dist/esm/relay/applesauce-relay-pool.d.ts +37 -4
- package/dist/esm/relay/applesauce-relay-pool.d.ts.map +1 -1
- package/dist/esm/relay/applesauce-relay-pool.js +165 -11
- package/dist/esm/relay/applesauce-relay-pool.js.map +1 -1
- package/dist/esm/signer/private-key-signer.d.ts.map +1 -1
- package/dist/esm/signer/private-key-signer.js +1 -1
- package/dist/esm/signer/private-key-signer.js.map +1 -1
- package/dist/esm/transport/base-nostr-transport.d.ts +1 -1
- package/dist/esm/transport/base-nostr-transport.d.ts.map +1 -1
- package/dist/esm/transport/base-nostr-transport.js +8 -6
- package/dist/esm/transport/base-nostr-transport.js.map +1 -1
- package/dist/esm/transport/nostr-client/correlation-store.d.ts +60 -0
- package/dist/esm/transport/nostr-client/correlation-store.d.ts.map +1 -0
- package/dist/esm/transport/nostr-client/correlation-store.js +61 -0
- package/dist/esm/transport/nostr-client/correlation-store.js.map +1 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.d.ts +24 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.d.ts.map +1 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.js +61 -0
- package/dist/esm/transport/nostr-client/stateless-mode-handler.js.map +1 -0
- package/dist/esm/transport/nostr-client-transport.d.ts +48 -24
- package/dist/esm/transport/nostr-client-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client-transport.js +92 -131
- package/dist/esm/transport/nostr-client-transport.js.map +1 -1
- package/dist/esm/transport/nostr-server/announcement-manager.d.ts +116 -0
- package/dist/esm/transport/nostr-server/announcement-manager.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/announcement-manager.js +288 -0
- package/dist/esm/transport/nostr-server/announcement-manager.js.map +1 -0
- package/dist/esm/transport/nostr-server/authorization-policy.d.ts +74 -0
- package/dist/esm/transport/nostr-server/authorization-policy.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/authorization-policy.js +91 -0
- package/dist/esm/transport/nostr-server/authorization-policy.js.map +1 -0
- package/dist/esm/transport/nostr-server/correlation-store.d.ts +102 -0
- package/dist/esm/transport/nostr-server/correlation-store.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/correlation-store.js +167 -0
- package/dist/esm/transport/nostr-server/correlation-store.js.map +1 -0
- package/dist/esm/transport/nostr-server/session-store.d.ts +99 -0
- package/dist/esm/transport/nostr-server/session-store.d.ts.map +1 -0
- package/dist/esm/transport/nostr-server/session-store.js +123 -0
- package/dist/esm/transport/nostr-server/session-store.js.map +1 -0
- package/dist/esm/transport/nostr-server-transport.d.ts +18 -63
- package/dist/esm/transport/nostr-server-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server-transport.js +135 -378
- package/dist/esm/transport/nostr-server-transport.js.map +1 -1
- package/package.json +15 -12
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal correlation store for NostrServerTransport.
|
|
3
|
+
* Provides O(1) routing for responses and progress notifications.
|
|
4
|
+
*
|
|
5
|
+
* This module is not exported from the public API.
|
|
6
|
+
*/
|
|
7
|
+
import { DEFAULT_LRU_SIZE } from '@contextvm/sdk/core/constants.js';
|
|
8
|
+
import { LruCache } from '../../core/utils/lru-cache.js';
|
|
9
|
+
/**
|
|
10
|
+
* Internal store for managing request/response correlation and progress routing.
|
|
11
|
+
*/
|
|
12
|
+
export class CorrelationStore {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
const { maxEventRoutes = DEFAULT_LRU_SIZE, maxProgressTokens = DEFAULT_LRU_SIZE, onEventRouteEvicted, } = options;
|
|
15
|
+
this.eventRoutes = new LruCache(maxEventRoutes, (eventId, route) => {
|
|
16
|
+
// Clean up progress token mapping when event route is evicted
|
|
17
|
+
if (route.progressToken) {
|
|
18
|
+
this.progressTokenToEventId.delete(route.progressToken);
|
|
19
|
+
}
|
|
20
|
+
// Clean up client index when event route is evicted
|
|
21
|
+
const clientSet = this.clientEventIds.get(route.clientPubkey);
|
|
22
|
+
if (clientSet) {
|
|
23
|
+
clientSet.delete(eventId);
|
|
24
|
+
if (clientSet.size === 0) {
|
|
25
|
+
this.clientEventIds.delete(route.clientPubkey);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
onEventRouteEvicted === null || onEventRouteEvicted === void 0 ? void 0 : onEventRouteEvicted(eventId, route);
|
|
29
|
+
});
|
|
30
|
+
this.progressTokenToEventId = new LruCache(maxProgressTokens);
|
|
31
|
+
this.clientEventIds = new Map();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Registers a new event route for an incoming request.
|
|
35
|
+
*
|
|
36
|
+
* @param eventId The Nostr event ID (used as the request ID)
|
|
37
|
+
* @param clientPubkey The client's public key
|
|
38
|
+
* @param originalRequestId The original JSON-RPC request ID
|
|
39
|
+
* @param progressToken Optional progress token for this request
|
|
40
|
+
*/
|
|
41
|
+
registerEventRoute(eventId, clientPubkey, originalRequestId, progressToken) {
|
|
42
|
+
const route = {
|
|
43
|
+
clientPubkey,
|
|
44
|
+
originalRequestId,
|
|
45
|
+
progressToken,
|
|
46
|
+
};
|
|
47
|
+
this.eventRoutes.set(eventId, route);
|
|
48
|
+
// Update client index
|
|
49
|
+
let clientSet = this.clientEventIds.get(clientPubkey);
|
|
50
|
+
if (!clientSet) {
|
|
51
|
+
clientSet = new Set();
|
|
52
|
+
this.clientEventIds.set(clientPubkey, clientSet);
|
|
53
|
+
}
|
|
54
|
+
clientSet.add(eventId);
|
|
55
|
+
if (progressToken) {
|
|
56
|
+
this.progressTokenToEventId.set(progressToken, eventId);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets the route for a given event ID.
|
|
61
|
+
*
|
|
62
|
+
* @param eventId The Nostr event ID
|
|
63
|
+
* @returns The event route, or undefined if not found
|
|
64
|
+
*/
|
|
65
|
+
getEventRoute(eventId) {
|
|
66
|
+
return this.eventRoutes.get(eventId);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Gets the event ID for a given progress token.
|
|
70
|
+
*
|
|
71
|
+
* @param progressToken The progress token
|
|
72
|
+
* @returns The event ID, or undefined if not found
|
|
73
|
+
*/
|
|
74
|
+
getEventIdByProgressToken(progressToken) {
|
|
75
|
+
return this.progressTokenToEventId.get(progressToken);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Removes an event route and its associated progress token mapping.
|
|
79
|
+
*
|
|
80
|
+
* @param eventId The Nostr event ID
|
|
81
|
+
* @returns true if the route was found and removed, false otherwise
|
|
82
|
+
*/
|
|
83
|
+
removeEventRoute(eventId) {
|
|
84
|
+
const route = this.eventRoutes.get(eventId);
|
|
85
|
+
if (!route) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
// Remove progress token mapping if it exists
|
|
89
|
+
if (route.progressToken) {
|
|
90
|
+
this.progressTokenToEventId.delete(route.progressToken);
|
|
91
|
+
}
|
|
92
|
+
// Remove from client index
|
|
93
|
+
const clientSet = this.clientEventIds.get(route.clientPubkey);
|
|
94
|
+
if (clientSet) {
|
|
95
|
+
clientSet.delete(eventId);
|
|
96
|
+
if (clientSet.size === 0) {
|
|
97
|
+
this.clientEventIds.delete(route.clientPubkey);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Remove the event route
|
|
101
|
+
this.eventRoutes.delete(eventId);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Removes all event routes for a specific client.
|
|
106
|
+
* This is called when a session is evicted or closed.
|
|
107
|
+
*
|
|
108
|
+
* @param clientPubkey The client's public key
|
|
109
|
+
* @returns The number of routes removed
|
|
110
|
+
*/
|
|
111
|
+
removeRoutesForClient(clientPubkey) {
|
|
112
|
+
let removed = 0;
|
|
113
|
+
// Get the set of event IDs for this client (O(1) lookup)
|
|
114
|
+
const eventIds = this.clientEventIds.get(clientPubkey);
|
|
115
|
+
if (!eventIds) {
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
// Remove each event route (O(k) where k is the number of active requests for this client)
|
|
119
|
+
const toRemove = Array.from(eventIds);
|
|
120
|
+
for (const eventId of toRemove) {
|
|
121
|
+
if (this.removeEventRoute(eventId)) {
|
|
122
|
+
removed++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// The client index should now be empty, but ensure it's cleaned up
|
|
126
|
+
this.clientEventIds.delete(clientPubkey);
|
|
127
|
+
return removed;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Checks if an event route exists.
|
|
131
|
+
*
|
|
132
|
+
* @param eventId The Nostr event ID
|
|
133
|
+
* @returns true if the route exists, false otherwise
|
|
134
|
+
*/
|
|
135
|
+
hasEventRoute(eventId) {
|
|
136
|
+
return this.eventRoutes.has(eventId);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Checks if a progress token mapping exists.
|
|
140
|
+
*
|
|
141
|
+
* @param progressToken The progress token
|
|
142
|
+
* @returns true if the mapping exists, false otherwise
|
|
143
|
+
*/
|
|
144
|
+
hasProgressToken(progressToken) {
|
|
145
|
+
return this.progressTokenToEventId.has(progressToken);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Gets the current number of event routes.
|
|
149
|
+
*/
|
|
150
|
+
get eventRouteCount() {
|
|
151
|
+
return this.eventRoutes.size;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Gets the current number of progress token mappings.
|
|
155
|
+
*/
|
|
156
|
+
get progressTokenCount() {
|
|
157
|
+
return this.progressTokenToEventId.size;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Clears all event routes and progress token mappings.
|
|
161
|
+
*/
|
|
162
|
+
clear() {
|
|
163
|
+
this.eventRoutes.clear();
|
|
164
|
+
this.progressTokenToEventId.clear();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=correlation-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correlation-store.js","sourceRoot":"","sources":["../../../../src/transport/nostr-server/correlation-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal session store for NostrServerTransport.
|
|
3
|
+
* Manages client sessions with LRU eviction.
|
|
4
|
+
*
|
|
5
|
+
* This module is not exported from the public API.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Represents a connected client session.
|
|
9
|
+
* Simplified from the original design - correlation data is now
|
|
10
|
+
* managed separately by CorrelationStore.
|
|
11
|
+
*/
|
|
12
|
+
export interface ClientSession {
|
|
13
|
+
/** Whether the client has completed the initialize handshake */
|
|
14
|
+
isInitialized: boolean;
|
|
15
|
+
/** Whether this session uses encryption */
|
|
16
|
+
isEncrypted: boolean;
|
|
17
|
+
/** Timestamp of the last activity from this client */
|
|
18
|
+
lastActivity: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for configuring the SessionStore.
|
|
22
|
+
*/
|
|
23
|
+
export interface SessionStoreOptions {
|
|
24
|
+
/** Maximum number of sessions to keep in memory */
|
|
25
|
+
maxSessions?: number;
|
|
26
|
+
/** Callback invoked when a session is evicted */
|
|
27
|
+
onSessionEvicted?: (clientPubkey: string, session: ClientSession) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Internal store for managing client sessions.
|
|
31
|
+
*
|
|
32
|
+
* This class maintains an LRU cache of client sessions, automatically
|
|
33
|
+
* evicting the least recently used sessions when the capacity is reached.
|
|
34
|
+
*
|
|
35
|
+
* Session data is kept minimal - correlation data (request IDs, progress tokens)
|
|
36
|
+
* is managed separately by CorrelationStore for better separation of concerns.
|
|
37
|
+
*/
|
|
38
|
+
export declare class SessionStore {
|
|
39
|
+
private readonly sessions;
|
|
40
|
+
constructor(options?: SessionStoreOptions);
|
|
41
|
+
/**
|
|
42
|
+
* Gets or creates a session for a client.
|
|
43
|
+
*
|
|
44
|
+
* @param clientPubkey The client's public key
|
|
45
|
+
* @param isEncrypted Whether the session uses encryption
|
|
46
|
+
* @returns The client session
|
|
47
|
+
*/
|
|
48
|
+
getOrCreateSession(clientPubkey: string, isEncrypted: boolean): ClientSession;
|
|
49
|
+
/**
|
|
50
|
+
* Gets a session for a client without creating one if it doesn't exist.
|
|
51
|
+
*
|
|
52
|
+
* @param clientPubkey The client's public key
|
|
53
|
+
* @returns The client session, or undefined if not found
|
|
54
|
+
*/
|
|
55
|
+
getSession(clientPubkey: string): ClientSession | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Updates the last activity timestamp for a session.
|
|
58
|
+
*
|
|
59
|
+
* @param clientPubkey The client's public key
|
|
60
|
+
* @returns true if the session was found and updated, false otherwise
|
|
61
|
+
*/
|
|
62
|
+
updateActivity(clientPubkey: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Marks a session as initialized.
|
|
65
|
+
*
|
|
66
|
+
* @param clientPubkey The client's public key
|
|
67
|
+
* @returns true if the session was found and updated, false otherwise
|
|
68
|
+
*/
|
|
69
|
+
markInitialized(clientPubkey: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Checks if a session exists.
|
|
72
|
+
*
|
|
73
|
+
* @param clientPubkey The client's public key
|
|
74
|
+
* @returns true if the session exists, false otherwise
|
|
75
|
+
*/
|
|
76
|
+
hasSession(clientPubkey: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Removes a session.
|
|
79
|
+
*
|
|
80
|
+
* @param clientPubkey The client's public key
|
|
81
|
+
* @returns true if the session was found and removed, false otherwise
|
|
82
|
+
*/
|
|
83
|
+
removeSession(clientPubkey: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Gets all sessions.
|
|
86
|
+
*
|
|
87
|
+
* @returns An iterable of [clientPubkey, session] tuples
|
|
88
|
+
*/
|
|
89
|
+
getAllSessions(): IterableIterator<[string, ClientSession]>;
|
|
90
|
+
/**
|
|
91
|
+
* Gets the number of active sessions.
|
|
92
|
+
*/
|
|
93
|
+
get sessionCount(): number;
|
|
94
|
+
/**
|
|
95
|
+
* Clears all sessions.
|
|
96
|
+
*/
|
|
97
|
+
clear(): void;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=session-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../../../src/transport/nostr-server/session-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,aAAa,EAAE,OAAO,CAAC;IACvB,2CAA2C;IAC3C,WAAW,EAAE,OAAO,CAAC;IACrB,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3E;AAED;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;gBAEvC,OAAO,GAAE,mBAAwB;IAW7C;;;;;;OAMG;IACH,kBAAkB,CAChB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,OAAO,GACnB,aAAa;IAkBhB;;;;;OAKG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI3D;;;;;OAKG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAS7C;;;;;OAKG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAS9C;;;;;OAKG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;OAKG;IACH,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI5C;;;;OAIG;IACH,cAAc,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAI3D;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal session store for NostrServerTransport.
|
|
3
|
+
* Manages client sessions with LRU eviction.
|
|
4
|
+
*
|
|
5
|
+
* This module is not exported from the public API.
|
|
6
|
+
*/
|
|
7
|
+
import { DEFAULT_LRU_SIZE } from '@contextvm/sdk/core/constants.js';
|
|
8
|
+
import { LruCache } from '../../core/utils/lru-cache.js';
|
|
9
|
+
/**
|
|
10
|
+
* Internal store for managing client sessions.
|
|
11
|
+
*
|
|
12
|
+
* This class maintains an LRU cache of client sessions, automatically
|
|
13
|
+
* evicting the least recently used sessions when the capacity is reached.
|
|
14
|
+
*
|
|
15
|
+
* Session data is kept minimal - correlation data (request IDs, progress tokens)
|
|
16
|
+
* is managed separately by CorrelationStore for better separation of concerns.
|
|
17
|
+
*/
|
|
18
|
+
export class SessionStore {
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
const { maxSessions = DEFAULT_LRU_SIZE, onSessionEvicted } = options;
|
|
21
|
+
this.sessions = new LruCache(maxSessions, (clientPubkey, session) => {
|
|
22
|
+
onSessionEvicted === null || onSessionEvicted === void 0 ? void 0 : onSessionEvicted(clientPubkey, session);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Gets or creates a session for a client.
|
|
27
|
+
*
|
|
28
|
+
* @param clientPubkey The client's public key
|
|
29
|
+
* @param isEncrypted Whether the session uses encryption
|
|
30
|
+
* @returns The client session
|
|
31
|
+
*/
|
|
32
|
+
getOrCreateSession(clientPubkey, isEncrypted) {
|
|
33
|
+
const existing = this.sessions.get(clientPubkey);
|
|
34
|
+
if (existing) {
|
|
35
|
+
// Update encryption mode in case it changed
|
|
36
|
+
existing.isEncrypted = isEncrypted;
|
|
37
|
+
return existing;
|
|
38
|
+
}
|
|
39
|
+
const newSession = {
|
|
40
|
+
isInitialized: false,
|
|
41
|
+
isEncrypted,
|
|
42
|
+
lastActivity: Date.now(),
|
|
43
|
+
};
|
|
44
|
+
this.sessions.set(clientPubkey, newSession);
|
|
45
|
+
return newSession;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Gets a session for a client without creating one if it doesn't exist.
|
|
49
|
+
*
|
|
50
|
+
* @param clientPubkey The client's public key
|
|
51
|
+
* @returns The client session, or undefined if not found
|
|
52
|
+
*/
|
|
53
|
+
getSession(clientPubkey) {
|
|
54
|
+
return this.sessions.get(clientPubkey);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Updates the last activity timestamp for a session.
|
|
58
|
+
*
|
|
59
|
+
* @param clientPubkey The client's public key
|
|
60
|
+
* @returns true if the session was found and updated, false otherwise
|
|
61
|
+
*/
|
|
62
|
+
updateActivity(clientPubkey) {
|
|
63
|
+
const session = this.sessions.get(clientPubkey);
|
|
64
|
+
if (session) {
|
|
65
|
+
session.lastActivity = Date.now();
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Marks a session as initialized.
|
|
72
|
+
*
|
|
73
|
+
* @param clientPubkey The client's public key
|
|
74
|
+
* @returns true if the session was found and updated, false otherwise
|
|
75
|
+
*/
|
|
76
|
+
markInitialized(clientPubkey) {
|
|
77
|
+
const session = this.sessions.get(clientPubkey);
|
|
78
|
+
if (session) {
|
|
79
|
+
session.isInitialized = true;
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Checks if a session exists.
|
|
86
|
+
*
|
|
87
|
+
* @param clientPubkey The client's public key
|
|
88
|
+
* @returns true if the session exists, false otherwise
|
|
89
|
+
*/
|
|
90
|
+
hasSession(clientPubkey) {
|
|
91
|
+
return this.sessions.has(clientPubkey);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Removes a session.
|
|
95
|
+
*
|
|
96
|
+
* @param clientPubkey The client's public key
|
|
97
|
+
* @returns true if the session was found and removed, false otherwise
|
|
98
|
+
*/
|
|
99
|
+
removeSession(clientPubkey) {
|
|
100
|
+
return this.sessions.delete(clientPubkey);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Gets all sessions.
|
|
104
|
+
*
|
|
105
|
+
* @returns An iterable of [clientPubkey, session] tuples
|
|
106
|
+
*/
|
|
107
|
+
getAllSessions() {
|
|
108
|
+
return this.sessions.entries();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Gets the number of active sessions.
|
|
112
|
+
*/
|
|
113
|
+
get sessionCount() {
|
|
114
|
+
return this.sessions.size;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Clears all sessions.
|
|
118
|
+
*/
|
|
119
|
+
clear() {
|
|
120
|
+
this.sessions.clear();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../../../src/transport/nostr-server/session-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AA0BzD;;;;;;;;GAQG;AACH,MAAM,OAAO,YAAY;IAGvB,YAAY,UAA+B,EAAE;QAC3C,MAAM,EAAE,WAAW,GAAG,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC;QAErE,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAC1B,WAAW,EACX,CAAC,YAAY,EAAE,OAAO,EAAE,EAAE;YACxB,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAG,YAAY,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC,CACF,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,kBAAkB,CAChB,YAAoB,EACpB,WAAoB;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,QAAQ,EAAE,CAAC;YACb,4CAA4C;YAC5C,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC;YACnC,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,UAAU,GAAkB;YAChC,aAAa,EAAE,KAAK;YACpB,WAAW;YACX,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;SACzB,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAC5C,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,YAAoB;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,YAAoB;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAC,YAAoB;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,YAAoB;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,YAAoB;QAChC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -3,16 +3,10 @@ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
|
3
3
|
import { BaseNostrTransport, BaseNostrTransportOptions } from './base-nostr-transport.js';
|
|
4
4
|
import { NostrEvent } from 'nostr-tools';
|
|
5
5
|
import { LogLevel } from '../core/utils/logger.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export interface CapabilityExclusion {
|
|
11
|
-
/** The JSON-RPC method to exclude from whitelisting (e.g., 'tools/call', 'tools/list') */
|
|
12
|
-
method: string;
|
|
13
|
-
/** Optional capability name to specifically exclude (e.g., 'get_weather') */
|
|
14
|
-
name?: string;
|
|
15
|
-
}
|
|
6
|
+
import { CorrelationStore } from './nostr-server/correlation-store.js';
|
|
7
|
+
import { SessionStore } from './nostr-server/session-store.js';
|
|
8
|
+
import { CapabilityExclusion } from './nostr-server/authorization-policy.js';
|
|
9
|
+
import { ServerInfo } from './nostr-server/announcement-manager.js';
|
|
16
10
|
/**
|
|
17
11
|
* Options for configuring the NostrServerTransport.
|
|
18
12
|
*/
|
|
@@ -30,15 +24,6 @@ export interface NostrServerTransportOptions extends BaseNostrTransportOptions {
|
|
|
30
24
|
*/
|
|
31
25
|
injectClientPubkey?: boolean;
|
|
32
26
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Information about a server.
|
|
35
|
-
*/
|
|
36
|
-
export interface ServerInfo {
|
|
37
|
-
name?: string;
|
|
38
|
-
picture?: string;
|
|
39
|
-
website?: string;
|
|
40
|
-
about?: string;
|
|
41
|
-
}
|
|
42
27
|
/**
|
|
43
28
|
* A server-side transport layer for CTXVM that uses Nostr events for communication.
|
|
44
29
|
* This transport listens for incoming MCP requests via Nostr events and can send
|
|
@@ -49,24 +34,12 @@ export declare class NostrServerTransport extends BaseNostrTransport implements
|
|
|
49
34
|
onmessage?: (message: JSONRPCMessage) => void;
|
|
50
35
|
onclose?: () => void;
|
|
51
36
|
onerror?: (error: Error) => void;
|
|
52
|
-
private readonly
|
|
53
|
-
private readonly
|
|
54
|
-
private readonly
|
|
55
|
-
private readonly
|
|
56
|
-
private readonly allowedPublicKeys?;
|
|
57
|
-
private readonly excludedCapabilities?;
|
|
58
|
-
private readonly serverInfo?;
|
|
37
|
+
private readonly sessionStore;
|
|
38
|
+
private readonly correlationStore;
|
|
39
|
+
private readonly authorizationPolicy;
|
|
40
|
+
private readonly announcementManager;
|
|
59
41
|
private readonly injectClientPubkey;
|
|
60
|
-
private isInitialized;
|
|
61
|
-
private initializationPromise?;
|
|
62
|
-
private initializationResolver?;
|
|
63
|
-
private cachedCommonTags?;
|
|
64
42
|
constructor(options: NostrServerTransportOptions);
|
|
65
|
-
/**
|
|
66
|
-
* Generates common tags from server information for use in Nostr events.
|
|
67
|
-
* @returns Array of tag arrays for Nostr events.
|
|
68
|
-
*/
|
|
69
|
-
private generateCommonTags;
|
|
70
43
|
/**
|
|
71
44
|
* Starts the transport, connecting to the relay and setting up event listeners
|
|
72
45
|
* to receive incoming MCP requests.
|
|
@@ -89,42 +62,23 @@ export declare class NostrServerTransport extends BaseNostrTransport implements
|
|
|
89
62
|
* @returns Promise that resolves to an array of deletion events that were published.
|
|
90
63
|
*/
|
|
91
64
|
deleteAnnouncement(reason?: string): Promise<NostrEvent[]>;
|
|
92
|
-
/**
|
|
93
|
-
* Initiates the process of fetching announcement data from the server's internal logic.
|
|
94
|
-
* This method now properly handles the initialization handshake by first sending
|
|
95
|
-
* the initialize request, waiting for the response, and then proceeding with other announcements.
|
|
96
|
-
*/
|
|
97
|
-
private getAnnouncementData;
|
|
98
|
-
/**
|
|
99
|
-
* Waits for the server to be initialized with a timeout.
|
|
100
|
-
* @returns Promise that resolves when initialized or after 10-second timeout.
|
|
101
|
-
* The method will always resolve, allowing announcements to proceed.
|
|
102
|
-
*/
|
|
103
|
-
private waitForInitialization;
|
|
104
|
-
/**
|
|
105
|
-
* Handles the JSON-RPC responses for public server announcements and publishes
|
|
106
|
-
* them as Nostr events to the configured relays.
|
|
107
|
-
* @param message The JSON-RPC response containing the announcement data.
|
|
108
|
-
*/
|
|
109
|
-
private announcer;
|
|
110
65
|
/**
|
|
111
66
|
* Gets or creates a client session with proper initialization.
|
|
112
67
|
* @param clientPubkey The client's public key.
|
|
113
|
-
* @param now Current timestamp.
|
|
114
68
|
* @param isEncrypted Whether the session uses encryption.
|
|
115
69
|
* @returns The client session.
|
|
116
70
|
*/
|
|
117
71
|
private getOrCreateClientSession;
|
|
118
72
|
/**
|
|
119
73
|
* Handles incoming requests with correlation tracking.
|
|
120
|
-
* @param session The client session.
|
|
121
74
|
* @param eventId The Nostr event ID.
|
|
122
75
|
* @param request The request message.
|
|
76
|
+
* @param clientPubkey The client's public key.
|
|
123
77
|
*/
|
|
124
78
|
private handleIncomingRequest;
|
|
125
79
|
/**
|
|
126
80
|
* Handles incoming notifications.
|
|
127
|
-
* @param
|
|
81
|
+
* @param clientPubkey The client's public key.
|
|
128
82
|
* @param notification The notification message.
|
|
129
83
|
*/
|
|
130
84
|
private handleIncomingNotification;
|
|
@@ -162,13 +116,6 @@ export declare class NostrServerTransport extends BaseNostrTransport implements
|
|
|
162
116
|
* @param event The incoming Nostr event.
|
|
163
117
|
*/
|
|
164
118
|
private handleUnencryptedEvent;
|
|
165
|
-
/**
|
|
166
|
-
* Checks if a capability is excluded from whitelisting requirements.
|
|
167
|
-
* @param method The JSON-RPC method (e.g., 'tools/call', 'tools/list')
|
|
168
|
-
* @param name Optional capability name for method-specific exclusions (e.g., 'get_weather')
|
|
169
|
-
* @returns true if the capability should bypass whitelisting, false otherwise
|
|
170
|
-
*/
|
|
171
|
-
private isCapabilityExcluded;
|
|
172
119
|
/**
|
|
173
120
|
* Authorizes and processes an incoming Nostr event, handling message validation,
|
|
174
121
|
* client authorization, session management, and optional client public key injection.
|
|
@@ -176,5 +123,13 @@ export declare class NostrServerTransport extends BaseNostrTransport implements
|
|
|
176
123
|
* @param isEncrypted Whether the original event was encrypted.
|
|
177
124
|
*/
|
|
178
125
|
private authorizeAndProcessEvent;
|
|
126
|
+
/**
|
|
127
|
+
* Test-only accessor for internal state.
|
|
128
|
+
* @internal
|
|
129
|
+
*/
|
|
130
|
+
getInternalStateForTesting(): {
|
|
131
|
+
sessionStore: SessionStore;
|
|
132
|
+
correlationStore: CorrelationStore;
|
|
133
|
+
};
|
|
179
134
|
}
|
|
180
135
|
//# sourceMappingURL=nostr-server-transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nostr-server-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/nostr-server-transport.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"nostr-server-transport.d.ts","sourceRoot":"","sources":["../../../src/transport/nostr-server-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EAMpB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,2BAA2B,CAAC;AASnC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAiB,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAEL,mBAAmB,EACpB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAEL,UAAU,EACX,MAAM,wCAAwC,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,2BAA4B,SAAQ,yBAAyB;IAC5E,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,uFAAuF;IACvF,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC7C,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;GAKG;AACH,qBAAa,oBACX,SAAQ,kBACR,YAAW,SAAS;IAEb,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAExC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;gBAEjC,OAAO,EAAE,2BAA2B;IAmDhD;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmCnC;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBnC;;;OAGG;IACU,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAazD;;;;;;OAMG;IACU,kBAAkB,CAC7B,MAAM,GAAE,MAA0B,GACjC,OAAO,CAAC,UAAU,EAAE,CAAC;IAIxB;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;IAWhC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAoB7B;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;IAYlC;;;OAGG;YACW,cAAc;IA+D5B;;;OAGG;YACW,kBAAkB;IAiEhC;;;;;OAKG;IACU,gBAAgB,CAC3B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,cAAc,EAC5B,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC;IAqBhB;;;;;OAKG;YACW,oBAAoB;IAkBlC;;;OAGG;YACW,oBAAoB;IA8BlC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;IA4FhC;;;OAGG;IACH,0BAA0B;;;;CAM3B"}
|