@contextvm/sdk 0.11.7 → 0.11.9

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 (89) hide show
  1. package/dist/esm/core/utils/base64.d.ts +3 -0
  2. package/dist/esm/core/utils/base64.d.ts.map +1 -0
  3. package/dist/esm/core/utils/base64.js +24 -0
  4. package/dist/esm/core/utils/base64.js.map +1 -0
  5. package/dist/esm/payments/handlers/ln-bolt11-lnbits-payment-handler.d.ts.map +1 -1
  6. package/dist/esm/payments/handlers/ln-bolt11-lnbits-payment-handler.js +2 -1
  7. package/dist/esm/payments/handlers/ln-bolt11-lnbits-payment-handler.js.map +1 -1
  8. package/dist/esm/payments/processors/ln-bolt11-lnbits-payment-processor.d.ts.map +1 -1
  9. package/dist/esm/payments/processors/ln-bolt11-lnbits-payment-processor.js +2 -1
  10. package/dist/esm/payments/processors/ln-bolt11-lnbits-payment-processor.js.map +1 -1
  11. package/dist/esm/transport/capability-negotiator.d.ts +141 -0
  12. package/dist/esm/transport/capability-negotiator.d.ts.map +1 -0
  13. package/dist/esm/transport/capability-negotiator.js +198 -0
  14. package/dist/esm/transport/capability-negotiator.js.map +1 -0
  15. package/dist/esm/transport/middleware.d.ts +9 -0
  16. package/dist/esm/transport/middleware.d.ts.map +1 -0
  17. package/dist/esm/transport/middleware.js +2 -0
  18. package/dist/esm/transport/middleware.js.map +1 -0
  19. package/dist/esm/transport/nostr-client/event-pipeline.d.ts +29 -0
  20. package/dist/esm/transport/nostr-client/event-pipeline.d.ts.map +1 -0
  21. package/dist/esm/transport/nostr-client/event-pipeline.js +109 -0
  22. package/dist/esm/transport/nostr-client/event-pipeline.js.map +1 -0
  23. package/dist/esm/transport/nostr-client/inbound-coordinator.d.ts +37 -0
  24. package/dist/esm/transport/nostr-client/inbound-coordinator.d.ts.map +1 -0
  25. package/dist/esm/transport/nostr-client/inbound-coordinator.js +159 -0
  26. package/dist/esm/transport/nostr-client/inbound-coordinator.js.map +1 -0
  27. package/dist/esm/transport/nostr-client/inbound-notification-dispatcher.d.ts +28 -0
  28. package/dist/esm/transport/nostr-client/inbound-notification-dispatcher.d.ts.map +1 -0
  29. package/dist/esm/transport/nostr-client/inbound-notification-dispatcher.js +65 -0
  30. package/dist/esm/transport/nostr-client/inbound-notification-dispatcher.js.map +1 -0
  31. package/dist/esm/transport/nostr-client/open-stream-factory.d.ts +36 -0
  32. package/dist/esm/transport/nostr-client/open-stream-factory.d.ts.map +1 -0
  33. package/dist/esm/transport/nostr-client/open-stream-factory.js +126 -0
  34. package/dist/esm/transport/nostr-client/open-stream-factory.js.map +1 -0
  35. package/dist/esm/transport/nostr-client/outbound-sender.d.ts +45 -0
  36. package/dist/esm/transport/nostr-client/outbound-sender.d.ts.map +1 -0
  37. package/dist/esm/transport/nostr-client/outbound-sender.js +105 -0
  38. package/dist/esm/transport/nostr-client/outbound-sender.js.map +1 -0
  39. package/dist/esm/transport/nostr-client/server-metadata-store.d.ts +35 -0
  40. package/dist/esm/transport/nostr-client/server-metadata-store.d.ts.map +1 -0
  41. package/dist/esm/transport/nostr-client/server-metadata-store.js +107 -0
  42. package/dist/esm/transport/nostr-client/server-metadata-store.js.map +1 -0
  43. package/dist/esm/transport/nostr-client-transport.d.ts +18 -41
  44. package/dist/esm/transport/nostr-client-transport.d.ts.map +1 -1
  45. package/dist/esm/transport/nostr-client-transport.js +117 -553
  46. package/dist/esm/transport/nostr-client-transport.js.map +1 -1
  47. package/dist/esm/transport/nostr-server/correlation-store.d.ts +2 -2
  48. package/dist/esm/transport/nostr-server/correlation-store.d.ts.map +1 -1
  49. package/dist/esm/transport/nostr-server/correlation-store.js +12 -3
  50. package/dist/esm/transport/nostr-server/correlation-store.js.map +1 -1
  51. package/dist/esm/transport/nostr-server/event-pipeline.d.ts +32 -0
  52. package/dist/esm/transport/nostr-server/event-pipeline.d.ts.map +1 -0
  53. package/dist/esm/transport/nostr-server/event-pipeline.js +118 -0
  54. package/dist/esm/transport/nostr-server/event-pipeline.js.map +1 -0
  55. package/dist/esm/transport/nostr-server/inbound-coordinator.d.ts +56 -0
  56. package/dist/esm/transport/nostr-server/inbound-coordinator.d.ts.map +1 -0
  57. package/dist/esm/transport/nostr-server/inbound-coordinator.js +168 -0
  58. package/dist/esm/transport/nostr-server/inbound-coordinator.js.map +1 -0
  59. package/dist/esm/transport/nostr-server/inbound-notification-dispatcher.d.ts +44 -0
  60. package/dist/esm/transport/nostr-server/inbound-notification-dispatcher.d.ts.map +1 -0
  61. package/dist/esm/transport/nostr-server/inbound-notification-dispatcher.js +153 -0
  62. package/dist/esm/transport/nostr-server/inbound-notification-dispatcher.js.map +1 -0
  63. package/dist/esm/transport/nostr-server/open-stream-factory.d.ts +81 -0
  64. package/dist/esm/transport/nostr-server/open-stream-factory.d.ts.map +1 -0
  65. package/dist/esm/transport/nostr-server/open-stream-factory.js +224 -0
  66. package/dist/esm/transport/nostr-server/open-stream-factory.js.map +1 -0
  67. package/dist/esm/transport/nostr-server/outbound-notification-broadcaster.d.ts +24 -0
  68. package/dist/esm/transport/nostr-server/outbound-notification-broadcaster.d.ts.map +1 -0
  69. package/dist/esm/transport/nostr-server/outbound-notification-broadcaster.js +64 -0
  70. package/dist/esm/transport/nostr-server/outbound-notification-broadcaster.js.map +1 -0
  71. package/dist/esm/transport/nostr-server/outbound-response-router.d.ts +62 -0
  72. package/dist/esm/transport/nostr-server/outbound-response-router.d.ts.map +1 -0
  73. package/dist/esm/transport/nostr-server/outbound-response-router.js +125 -0
  74. package/dist/esm/transport/nostr-server/outbound-response-router.js.map +1 -0
  75. package/dist/esm/transport/nostr-server-transport.d.ts +15 -62
  76. package/dist/esm/transport/nostr-server-transport.d.ts.map +1 -1
  77. package/dist/esm/transport/nostr-server-transport.js +121 -741
  78. package/dist/esm/transport/nostr-server-transport.js.map +1 -1
  79. package/dist/esm/transport/open-stream/registry.d.ts.map +1 -1
  80. package/dist/esm/transport/open-stream/registry.js +7 -1
  81. package/dist/esm/transport/open-stream/registry.js.map +1 -1
  82. package/dist/esm/transport/open-stream/session.d.ts +1 -0
  83. package/dist/esm/transport/open-stream/session.d.ts.map +1 -1
  84. package/dist/esm/transport/open-stream/session.js +14 -4
  85. package/dist/esm/transport/open-stream/session.js.map +1 -1
  86. package/dist/esm/transport/open-stream/writer.d.ts.map +1 -1
  87. package/dist/esm/transport/open-stream/writer.js +6 -12
  88. package/dist/esm/transport/open-stream/writer.js.map +1 -1
  89. package/package.json +1 -1
@@ -0,0 +1,44 @@
1
+ import { type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest } from '@modelcontextprotocol/sdk/types.js';
2
+ import { type NostrEvent } from 'nostr-tools';
3
+ import { type Logger } from '../../core/utils/logger.js';
4
+ import { OpenStreamReceiver, OpenStreamWriter } from '../open-stream/index.js';
5
+ import { OversizedTransferReceiver } from '../oversized-transfer/index.js';
6
+ import { type CorrelationStore } from './correlation-store.js';
7
+ import { type ClientSession } from './session-store.js';
8
+ /**
9
+ * Dependencies for the Server InboundNotificationDispatcher.
10
+ */
11
+ export interface InboundNotificationDispatcherDeps {
12
+ openStreamReceiver: OpenStreamReceiver;
13
+ oversizedReceiver: OversizedTransferReceiver;
14
+ openStreamFactory: {
15
+ getWriter: (eventId: string) => OpenStreamWriter | undefined;
16
+ };
17
+ correlationStore: CorrelationStore;
18
+ sendNotification: (clientPubkey: string, notification: JSONRPCMessage) => Promise<void>;
19
+ handleIncomingRequest: (event: NostrEvent, eventId: string, request: JSONRPCRequest, clientPubkey: string, wrapKind?: number) => void;
20
+ handleIncomingNotification: (clientPubkey: string, notification: JSONRPCMessage) => void;
21
+ cleanupDroppedRequest: (message: JSONRPCMessage) => void;
22
+ shouldInjectRequestEventId: boolean;
23
+ injectClientPubkey: boolean;
24
+ logger: Logger;
25
+ onerror?: (error: Error) => void;
26
+ }
27
+ /**
28
+ * Intercepts incoming transport-level notifications (CEP-22, CEP-41) for the server.
29
+ */
30
+ export declare class InboundNotificationDispatcher {
31
+ private deps;
32
+ constructor(deps: InboundNotificationDispatcherDeps);
33
+ /**
34
+ * Returns true if the notification was intercepted (CEP-22 or CEP-41).
35
+ * Returns false if it should fall through to normal middleware dispatch.
36
+ */
37
+ tryIntercept(inboundMessage: JSONRPCNotification, ctx: {
38
+ event: NostrEvent;
39
+ session: ClientSession;
40
+ shouldSendAccept: boolean;
41
+ wrapKind?: number;
42
+ }, dispatch: (msg: JSONRPCMessage) => Promise<boolean>): boolean;
43
+ }
44
+ //# sourceMappingURL=inbound-notification-dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-notification-dispatcher.d.ts","sourceRoot":"","sources":["../../../../src/transport/nostr-server/inbound-notification-dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EAGpB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAEjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOxD;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,iBAAiB,EAAE,yBAAyB,CAAC;IAC7C,iBAAiB,EAAE;QACjB,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG,SAAS,CAAC;KAC9D,CAAC;IACF,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gBAAgB,EAAE,CAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,cAAc,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,qBAAqB,EAAE,CACrB,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,KACd,IAAI,CAAC;IACV,0BAA0B,EAAE,CAC1B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,cAAc,KACzB,IAAI,CAAC;IACV,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,0BAA0B,EAAE,OAAO,CAAC;IACpC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,qBAAa,6BAA6B;IAC5B,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,iCAAiC;IAE3D;;;OAGG;IACI,YAAY,CACjB,cAAc,EAAE,mBAAmB,EACnC,GAAG,EAAE;QACH,KAAK,EAAE,UAAU,CAAC;QAClB,OAAO,EAAE,aAAa,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,EACD,QAAQ,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,GAClD,OAAO;CAiMX"}
@@ -0,0 +1,153 @@
1
+ import { isJSONRPCRequest, isJSONRPCNotification, } from '@modelcontextprotocol/sdk/types.js';
2
+ import { OpenStreamReceiver, buildOpenStreamAcceptFrame, } from '../open-stream/index.js';
3
+ import { OversizedTransferReceiver } from '../oversized-transfer/index.js';
4
+ import { sendAcceptFrame } from './oversized-server-handler.js';
5
+ import { injectClientPubkey, injectRequestEventId, } from '../../core/utils/utils.js';
6
+ /**
7
+ * Intercepts incoming transport-level notifications (CEP-22, CEP-41) for the server.
8
+ */
9
+ export class InboundNotificationDispatcher {
10
+ constructor(deps) {
11
+ this.deps = deps;
12
+ }
13
+ /**
14
+ * Returns true if the notification was intercepted (CEP-22 or CEP-41).
15
+ * Returns false if it should fall through to normal middleware dispatch.
16
+ */
17
+ tryIntercept(inboundMessage, ctx, dispatch) {
18
+ var _a, _b, _c, _d, _e;
19
+ const { event, session, shouldSendAccept, wrapKind } = ctx;
20
+ if (inboundMessage.method === 'notifications/progress' &&
21
+ OpenStreamReceiver.isOpenStreamFrame(inboundMessage)) {
22
+ const frame = (_a = inboundMessage.params) === null || _a === void 0 ? void 0 : _a.cvm;
23
+ if ((frame === null || frame === void 0 ? void 0 : frame.frameType) === 'abort') {
24
+ const progressToken = String((_c = (_b = inboundMessage.params) === null || _b === void 0 ? void 0 : _b.progressToken) !== null && _c !== void 0 ? _c : '');
25
+ const eventId = this.deps.correlationStore.getEventIdByProgressToken(progressToken, event.pubkey);
26
+ const writer = eventId
27
+ ? this.deps.openStreamFactory.getWriter(eventId)
28
+ : undefined;
29
+ if (writer) {
30
+ void writer.abort(frame.reason).catch((err) => {
31
+ var _a, _b;
32
+ this.deps.logger.error('Open stream abort propagation failed (server)', {
33
+ error: err instanceof Error ? err.message : String(err),
34
+ pubkey: event.pubkey,
35
+ progressToken,
36
+ });
37
+ (_b = (_a = this.deps).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, err instanceof Error ? err : new Error(String(err)));
38
+ });
39
+ }
40
+ return true;
41
+ }
42
+ if ((frame === null || frame === void 0 ? void 0 : frame.frameType) === 'ping') {
43
+ const progressToken = String((_e = (_d = inboundMessage.params) === null || _d === void 0 ? void 0 : _d.progressToken) !== null && _e !== void 0 ? _e : '');
44
+ const nonce = 'nonce' in frame && typeof frame.nonce === 'string'
45
+ ? frame.nonce
46
+ : '';
47
+ const eventId = this.deps.correlationStore.getEventIdByProgressToken(progressToken, event.pubkey);
48
+ const writer = eventId
49
+ ? this.deps.openStreamFactory.getWriter(eventId)
50
+ : undefined;
51
+ if (writer) {
52
+ void writer.pong(nonce).catch((err) => {
53
+ var _a, _b;
54
+ this.deps.logger.error('Open stream ping handling failed (server)', {
55
+ error: err instanceof Error ? err.message : String(err),
56
+ pubkey: event.pubkey,
57
+ progressToken,
58
+ });
59
+ (_b = (_a = this.deps).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, err instanceof Error ? err : new Error(String(err)));
60
+ });
61
+ return true;
62
+ }
63
+ }
64
+ this.deps.openStreamReceiver
65
+ .processFrame(inboundMessage)
66
+ .then(async () => {
67
+ var _a, _b, _c, _d;
68
+ const frameType = frame === null || frame === void 0 ? void 0 : frame.frameType;
69
+ if (frameType === 'start' && session.supportsOpenStream) {
70
+ await this.deps.sendNotification(event.pubkey, {
71
+ jsonrpc: '2.0',
72
+ method: 'notifications/progress',
73
+ params: buildOpenStreamAcceptFrame({
74
+ progressToken: String((_b = (_a = inboundMessage.params) === null || _a === void 0 ? void 0 : _a.progressToken) !== null && _b !== void 0 ? _b : ''),
75
+ progress: Number((_d = (_c = inboundMessage.params) === null || _c === void 0 ? void 0 : _c.progress) !== null && _d !== void 0 ? _d : 0) + 1,
76
+ }),
77
+ });
78
+ }
79
+ })
80
+ .catch((err) => {
81
+ var _a, _b;
82
+ this.deps.logger.error('Open stream error (server)', {
83
+ error: err instanceof Error ? err.message : String(err),
84
+ pubkey: event.pubkey,
85
+ });
86
+ (_b = (_a = this.deps).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, err instanceof Error ? err : new Error(String(err)));
87
+ });
88
+ return true;
89
+ }
90
+ if (inboundMessage.method === 'notifications/progress' &&
91
+ OversizedTransferReceiver.isOversizedFrame(inboundMessage)) {
92
+ this.deps.oversizedReceiver
93
+ .processFrame(inboundMessage)
94
+ .then(async (synthetic) => {
95
+ var _a, _b, _c, _d;
96
+ if (synthetic === null) {
97
+ if (((_b = (_a = inboundMessage.params) === null || _a === void 0 ? void 0 : _a.cvm) === null || _b === void 0 ? void 0 : _b.frameType) === 'start' &&
98
+ shouldSendAccept) {
99
+ await sendAcceptFrame({
100
+ clientPubkey: event.pubkey,
101
+ progressToken: String((_d = (_c = inboundMessage.params) === null || _c === void 0 ? void 0 : _c.progressToken) !== null && _d !== void 0 ? _d : ''),
102
+ }, {
103
+ sendNotification: this.deps.sendNotification,
104
+ }).catch((err) => {
105
+ this.deps.logger.error('Failed to send oversized accept', {
106
+ error: err instanceof Error ? err.message : String(err),
107
+ });
108
+ });
109
+ }
110
+ return;
111
+ }
112
+ if (isJSONRPCRequest(synthetic)) {
113
+ this.deps.handleIncomingRequest(event, event.id, synthetic, event.pubkey, wrapKind);
114
+ if (this.deps.shouldInjectRequestEventId) {
115
+ injectRequestEventId(synthetic, event.id);
116
+ }
117
+ if (this.deps.injectClientPubkey) {
118
+ injectClientPubkey(synthetic, event.pubkey);
119
+ }
120
+ }
121
+ else if (isJSONRPCNotification(synthetic)) {
122
+ this.deps.handleIncomingNotification(event.pubkey, synthetic);
123
+ }
124
+ void dispatch(synthetic)
125
+ .then((forwarded) => {
126
+ if (!forwarded) {
127
+ this.deps.cleanupDroppedRequest(synthetic);
128
+ }
129
+ })
130
+ .catch((err) => {
131
+ var _a, _b;
132
+ this.deps.logger.error('Error dispatching reassembled oversized message', {
133
+ error: err instanceof Error ? err.message : String(err),
134
+ pubkey: event.pubkey,
135
+ });
136
+ (_b = (_a = this.deps).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, err instanceof Error
137
+ ? err
138
+ : new Error('oversized dispatch failed'));
139
+ });
140
+ })
141
+ .catch((err) => {
142
+ var _a, _b;
143
+ this.deps.logger.error('Oversized transfer error (server)', {
144
+ error: err instanceof Error ? err.message : String(err),
145
+ });
146
+ (_b = (_a = this.deps).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, err instanceof Error ? err : new Error(String(err)));
147
+ });
148
+ return true;
149
+ }
150
+ return false;
151
+ }
152
+ }
153
+ //# sourceMappingURL=inbound-notification-dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-notification-dispatcher.js","sourceRoot":"","sources":["../../../../src/transport/nostr-server/inbound-notification-dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EACL,kBAAkB,EAElB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAG3E,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,2BAA2B,CAAC;AAkCnC;;GAEG;AACH,MAAM,OAAO,6BAA6B;IACxC,YAAoB,IAAuC;QAAvC,SAAI,GAAJ,IAAI,CAAmC;IAAG,CAAC;IAE/D;;;OAGG;IACI,YAAY,CACjB,cAAmC,EACnC,GAKC,EACD,QAAmD;;QAEnD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;QAE3D,IACE,cAAc,CAAC,MAAM,KAAK,wBAAwB;YAClD,kBAAkB,CAAC,iBAAiB,CAAC,cAAc,CAAC,EACpD,CAAC;YACD,MAAM,KAAK,GAAG,MAAA,cAAc,CAAC,MAAM,0CAAE,GAExB,CAAC;YAEd,IAAI,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,SAAS,MAAK,OAAO,EAAE,CAAC;gBACjC,MAAM,aAAa,GAAG,MAAM,CAC1B,MAAA,MAAA,cAAc,CAAC,MAAM,0CAAE,aAAa,mCAAI,EAAE,CAC3C,CAAC;gBACF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,yBAAyB,CAClE,aAAa,EACb,KAAK,CAAC,MAAM,CACb,CAAC;gBACF,MAAM,MAAM,GAAG,OAAO;oBACpB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC;oBAChD,CAAC,CAAC,SAAS,CAAC;gBAEd,IAAI,MAAM,EAAE,CAAC;oBACX,KAAK,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;;wBACrD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CACpB,+CAA+C,EAC/C;4BACE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;4BACvD,MAAM,EAAE,KAAK,CAAC,MAAM;4BACpB,aAAa;yBACd,CACF,CAAC;wBACF,MAAA,MAAA,IAAI,CAAC,IAAI,EAAC,OAAO,mDACf,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CACpD,CAAC;oBACJ,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,SAAS,MAAK,MAAM,EAAE,CAAC;gBAChC,MAAM,aAAa,GAAG,MAAM,CAC1B,MAAA,MAAA,cAAc,CAAC,MAAM,0CAAE,aAAa,mCAAI,EAAE,CAC3C,CAAC;gBACF,MAAM,KAAK,GACT,OAAO,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;oBACjD,CAAC,CAAC,KAAK,CAAC,KAAK;oBACb,CAAC,CAAC,EAAE,CAAC;gBACT,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,yBAAyB,CAClE,aAAa,EACb,KAAK,CAAC,MAAM,CACb,CAAC;gBACF,MAAM,MAAM,GAAG,OAAO;oBACpB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC;oBAChD,CAAC,CAAC,SAAS,CAAC;gBAEd,IAAI,MAAM,EAAE,CAAC;oBACX,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;;wBAC7C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CACpB,2CAA2C,EAC3C;4BACE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;4BACvD,MAAM,EAAE,KAAK,CAAC,MAAM;4BACpB,aAAa;yBACd,CACF,CAAC;wBACF,MAAA,MAAA,IAAI,CAAC,IAAI,EAAC,OAAO,mDACf,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CACpD,CAAC;oBACJ,CAAC,CAAC,CAAC;oBAEH,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,kBAAkB;iBACzB,YAAY,CAAC,cAAc,CAAC;iBAC5B,IAAI,CAAC,KAAK,IAAI,EAAE;;gBACf,MAAM,SAAS,GAAG,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,SAAS,CAAC;gBAEnC,IAAI,SAAS,KAAK,OAAO,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;oBACxD,MAAM,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE;wBAC7C,OAAO,EAAE,KAAK;wBACd,MAAM,EAAE,wBAAwB;wBAChC,MAAM,EAAE,0BAA0B,CAAC;4BACjC,aAAa,EAAE,MAAM,CACnB,MAAA,MAAA,cAAc,CAAC,MAAM,0CAAE,aAAa,mCAAI,EAAE,CAC3C;4BACD,QAAQ,EAAE,MAAM,CAAC,MAAA,MAAA,cAAc,CAAC,MAAM,0CAAE,QAAQ,mCAAI,CAAC,CAAC,GAAG,CAAC;yBAC3D,CAAC;qBACH,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;;gBACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE;oBACnD,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;oBACvD,MAAM,EAAE,KAAK,CAAC,MAAM;iBACrB,CAAC,CAAC;gBACH,MAAA,MAAA,IAAI,CAAC,IAAI,EAAC,OAAO,mDACf,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CACpD,CAAC;YACJ,CAAC,CAAC,CAAC;YACL,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IACE,cAAc,CAAC,MAAM,KAAK,wBAAwB;YAClD,yBAAyB,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAC1D,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,iBAAiB;iBACxB,YAAY,CAAC,cAAc,CAAC;iBAC5B,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;;gBACxB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;oBACvB,IACE,CAAA,MAAC,MAAA,cAAc,CAAC,MAAM,0CAAE,GAA0C,0CAC9D,SAAS,MAAK,OAAO;wBACzB,gBAAgB,EAChB,CAAC;wBACD,MAAM,eAAe,CACnB;4BACE,YAAY,EAAE,KAAK,CAAC,MAAM;4BAC1B,aAAa,EAAE,MAAM,CACnB,MAAA,MAAA,cAAc,CAAC,MAAM,0CAAE,aAAa,mCAAI,EAAE,CAC3C;yBACF,EACD;4BACE,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB;yBAC7C,CACF,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;4BACvB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE;gCACxD,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;6BACxD,CAAC,CAAC;wBACL,CAAC,CAAC,CAAC;oBACL,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,IAAI,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;oBAChC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAC7B,KAAK,EACL,KAAK,CAAC,EAAE,EACR,SAAS,EACT,KAAK,CAAC,MAAM,EACZ,QAAQ,CACT,CAAC;oBAEF,IAAI,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC;wBACzC,oBAAoB,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC5C,CAAC;oBAED,IAAI,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;wBACjC,kBAAkB,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC9C,CAAC;gBACH,CAAC;qBAAM,IAAI,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC5C,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;gBAChE,CAAC;gBAED,KAAK,QAAQ,CAAC,SAAS,CAAC;qBACrB,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;oBAClB,IAAI,CAAC,SAAS,EAAE,CAAC;wBACf,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;oBAC7C,CAAC;gBACH,CAAC,CAAC;qBACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;;oBACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CACpB,iDAAiD,EACjD;wBACE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;wBACvD,MAAM,EAAE,KAAK,CAAC,MAAM;qBACrB,CACF,CAAC;oBACF,MAAA,MAAA,IAAI,CAAC,IAAI,EAAC,OAAO,mDACf,GAAG,YAAY,KAAK;wBAClB,CAAC,CAAC,GAAG;wBACL,CAAC,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAC3C,CAAC;gBACJ,CAAC,CAAC,CAAC;YACP,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;;gBACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE;oBAC1D,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD,CAAC,CAAC;gBACH,MAAA,MAAA,IAAI,CAAC,IAAI,EAAC,OAAO,mDACf,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CACpD,CAAC;YACJ,CAAC,CAAC,CAAC;YACL,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,81 @@
1
+ import { OpenStreamWriter, OpenStreamReceiver } from '../open-stream/index.js';
2
+ import { type OpenStreamRegistryOptions } from '../open-stream/registry.js';
3
+ import { type Logger } from '../../core/utils/logger.js';
4
+ import { type CorrelationStore } from './correlation-store.js';
5
+ import { type ClientSession, type SessionStore } from './session-store.js';
6
+ import { type JSONRPCMessage, type JSONRPCResponse } from '@modelcontextprotocol/sdk/types.js';
7
+ /**
8
+ * Dependencies for the ServerOpenStreamFactory.
9
+ */
10
+ export interface ServerOpenStreamFactoryDeps {
11
+ openStreamEnabled: boolean;
12
+ sendNotification: (clientPubkey: string, notification: JSONRPCMessage) => Promise<void>;
13
+ handleResponse: (response: JSONRPCResponse) => Promise<void>;
14
+ sessionStore: SessionStore;
15
+ onClientSessionEvicted?: (ctx: {
16
+ clientPubkey: string;
17
+ session: ClientSession;
18
+ }) => void | Promise<void>;
19
+ onAbort?: (clientPubkey: string, eventId: string, reason?: string) => Promise<void>;
20
+ correlationStore: CorrelationStore;
21
+ policy?: Partial<OpenStreamRegistryOptions>;
22
+ logger: Logger;
23
+ }
24
+ /**
25
+ * Manages the lifecycle of CEP-41 OpenStream instances for the server transport.
26
+ */
27
+ export declare class ServerOpenStreamFactory {
28
+ private deps;
29
+ private readonly writers;
30
+ private readonly pendingResponses;
31
+ private readonly receiver;
32
+ private readonly pendingSessionEvictions;
33
+ private readonly evictedClientPubkeys;
34
+ constructor(deps: ServerOpenStreamFactoryDeps);
35
+ /**
36
+ * Gets the inbound OpenStreamReceiver instance used for CEP-41.
37
+ */
38
+ getReceiver(): OpenStreamReceiver;
39
+ /**
40
+ * Gets an active OpenStreamWriter for a specific event ID.
41
+ */
42
+ getWriter(eventId: string): OpenStreamWriter | undefined;
43
+ /**
44
+ * Clears all active writers and pending responses.
45
+ */
46
+ clear(): void;
47
+ /** Returns true if the client is currently marked as evicted. */
48
+ isClientEvicted(clientPubkey: string): boolean;
49
+ /**
50
+ * Takes and clears a pending eviction entry keyed by the request event id.
51
+ */
52
+ takePendingEviction(eventId: string): {
53
+ clientPubkey: string;
54
+ session: ClientSession;
55
+ } | undefined;
56
+ /**
57
+ * Checks if an event has an active stream and defers the response if so.
58
+ * Returns true if deferred.
59
+ */
60
+ deferIfStreamActive(eventId: string, response: JSONRPCResponse): boolean;
61
+ /**
62
+ * Conditionally creates a new OpenStreamWriter if the client supports it.
63
+ */
64
+ createWriterIfEnabled(eventId: string, clientPubkey: string, progressToken?: string): void;
65
+ /**
66
+ * Flushes a deferred response for a stream once it has closed or aborted.
67
+ */
68
+ flushPendingResponse(eventId: string): Promise<void>;
69
+ private handleProbeTimeout;
70
+ /**
71
+ * Test-only accessor for writers map.
72
+ * @internal
73
+ */
74
+ getWritersMap(): Map<string, OpenStreamWriter>;
75
+ /**
76
+ * Test-only accessor for pending responses map.
77
+ * @internal
78
+ */
79
+ getPendingResponsesMap(): Map<string, JSONRPCResponse>;
80
+ }
81
+ //# sourceMappingURL=open-stream-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-stream-factory.d.ts","sourceRoot":"","sources":["../../../../src/transport/nostr-server/open-stream-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAInB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,oCAAoC,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,CAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,cAAc,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,YAAY,EAAE,YAAY,CAAC;IAC3B,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,aAAa,CAAC;KACxB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,CACR,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,KACZ,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,uBAAuB;IAUtB,OAAO,CAAC,IAAI;IATxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsC;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAGpC;IACJ,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;gBAEtC,IAAI,EAAE,2BAA2B;IAoErD;;OAEG;IACI,WAAW,IAAI,kBAAkB;IAIxC;;OAEG;IACI,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAI/D;;OAEG;IACI,KAAK,IAAI,IAAI;IAOpB,iEAAiE;IAC1D,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAIrD;;OAEG;IACI,mBAAmB,CACxB,OAAO,EAAE,MAAM,GACd;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,aAAa,CAAA;KAAE,GAAG,SAAS;IAW/D;;;OAGG;IACI,mBAAmB,CACxB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,eAAe,GACxB,OAAO;IASV;;OAEG;IACI,qBAAqB,CAC1B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI;IA8BP;;OAEG;IACU,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAYnD,kBAAkB;IA8ChC;;;OAGG;IACI,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAIrD;;;OAGG;IACI,sBAAsB,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;CAG9D"}
@@ -0,0 +1,224 @@
1
+ import { OpenStreamWriter, OpenStreamReceiver, buildOpenStreamPingFrame, buildOpenStreamPongFrame, buildOpenStreamAbortFrame, } from '../open-stream/index.js';
2
+ /**
3
+ * Manages the lifecycle of CEP-41 OpenStream instances for the server transport.
4
+ */
5
+ export class ServerOpenStreamFactory {
6
+ constructor(deps) {
7
+ var _a, _b, _c, _d, _e, _f;
8
+ this.deps = deps;
9
+ this.writers = new Map();
10
+ this.pendingResponses = new Map();
11
+ this.pendingSessionEvictions = new Map();
12
+ this.evictedClientPubkeys = new Set();
13
+ this.receiver = new OpenStreamReceiver({
14
+ maxConcurrentStreams: (_a = deps.policy) === null || _a === void 0 ? void 0 : _a.maxConcurrentStreams,
15
+ maxBufferedChunksPerStream: (_b = deps.policy) === null || _b === void 0 ? void 0 : _b.maxBufferedChunksPerStream,
16
+ maxBufferedBytesPerStream: (_c = deps.policy) === null || _c === void 0 ? void 0 : _c.maxBufferedBytesPerStream,
17
+ idleTimeoutMs: (_d = deps.policy) === null || _d === void 0 ? void 0 : _d.idleTimeoutMs,
18
+ probeTimeoutMs: (_e = deps.policy) === null || _e === void 0 ? void 0 : _e.probeTimeoutMs,
19
+ closeGracePeriodMs: (_f = deps.policy) === null || _f === void 0 ? void 0 : _f.closeGracePeriodMs,
20
+ getSessionOptions: (progressToken) => {
21
+ let progress = 0;
22
+ const getClientPubkey = () => {
23
+ const eventId = this.deps.correlationStore.getEventIdByProgressToken(progressToken);
24
+ if (!eventId)
25
+ return undefined;
26
+ const route = this.deps.correlationStore.getEventRoute(eventId);
27
+ return route === null || route === void 0 ? void 0 : route.clientPubkey;
28
+ };
29
+ return {
30
+ sendPing: async (nonce) => {
31
+ progress += 1;
32
+ const clientPubkey = getClientPubkey();
33
+ if (!clientPubkey)
34
+ return;
35
+ await this.deps.sendNotification(clientPubkey, {
36
+ jsonrpc: '2.0',
37
+ method: 'notifications/progress',
38
+ params: buildOpenStreamPingFrame({
39
+ progressToken,
40
+ progress,
41
+ nonce,
42
+ }),
43
+ });
44
+ },
45
+ sendPong: async (nonce) => {
46
+ progress += 1;
47
+ const clientPubkey = getClientPubkey();
48
+ if (!clientPubkey)
49
+ return;
50
+ await this.deps.sendNotification(clientPubkey, {
51
+ jsonrpc: '2.0',
52
+ method: 'notifications/progress',
53
+ params: buildOpenStreamPongFrame({
54
+ progressToken,
55
+ progress,
56
+ nonce,
57
+ }),
58
+ });
59
+ },
60
+ sendAbort: async (reason) => {
61
+ progress += 1;
62
+ const clientPubkey = getClientPubkey();
63
+ if (!clientPubkey)
64
+ return;
65
+ await this.deps.sendNotification(clientPubkey, {
66
+ jsonrpc: '2.0',
67
+ method: 'notifications/progress',
68
+ params: buildOpenStreamAbortFrame({
69
+ progressToken,
70
+ progress,
71
+ reason,
72
+ }),
73
+ });
74
+ },
75
+ };
76
+ },
77
+ logger: deps.logger,
78
+ });
79
+ }
80
+ /**
81
+ * Gets the inbound OpenStreamReceiver instance used for CEP-41.
82
+ */
83
+ getReceiver() {
84
+ return this.receiver;
85
+ }
86
+ /**
87
+ * Gets an active OpenStreamWriter for a specific event ID.
88
+ */
89
+ getWriter(eventId) {
90
+ return this.writers.get(eventId);
91
+ }
92
+ /**
93
+ * Clears all active writers and pending responses.
94
+ */
95
+ clear() {
96
+ this.writers.clear();
97
+ this.pendingResponses.clear();
98
+ this.pendingSessionEvictions.clear();
99
+ this.evictedClientPubkeys.clear();
100
+ }
101
+ /** Returns true if the client is currently marked as evicted. */
102
+ isClientEvicted(clientPubkey) {
103
+ return this.evictedClientPubkeys.has(clientPubkey);
104
+ }
105
+ /**
106
+ * Takes and clears a pending eviction entry keyed by the request event id.
107
+ */
108
+ takePendingEviction(eventId) {
109
+ const pendingEviction = this.pendingSessionEvictions.get(eventId);
110
+ if (!pendingEviction) {
111
+ return undefined;
112
+ }
113
+ this.pendingSessionEvictions.delete(eventId);
114
+ this.evictedClientPubkeys.delete(pendingEviction.clientPubkey);
115
+ return pendingEviction;
116
+ }
117
+ /**
118
+ * Checks if an event has an active stream and defers the response if so.
119
+ * Returns true if deferred.
120
+ */
121
+ deferIfStreamActive(eventId, response) {
122
+ const existingWriter = this.writers.get(eventId);
123
+ if (existingWriter && existingWriter.isActive) {
124
+ this.pendingResponses.set(eventId, response);
125
+ return true;
126
+ }
127
+ return false;
128
+ }
129
+ /**
130
+ * Conditionally creates a new OpenStreamWriter if the client supports it.
131
+ */
132
+ createWriterIfEnabled(eventId, clientPubkey, progressToken) {
133
+ if (!this.deps.openStreamEnabled || !progressToken) {
134
+ return;
135
+ }
136
+ const writer = new OpenStreamWriter({
137
+ progressToken,
138
+ publishFrame: async (frame) => {
139
+ await this.deps.sendNotification(clientPubkey, {
140
+ jsonrpc: '2.0',
141
+ method: 'notifications/progress',
142
+ params: frame,
143
+ });
144
+ return undefined;
145
+ },
146
+ onClose: async () => {
147
+ await this.flushPendingResponse(eventId);
148
+ },
149
+ onAbort: async (reason) => {
150
+ var _a, _b;
151
+ if (reason === 'Probe timeout') {
152
+ await this.handleProbeTimeout(clientPubkey, eventId);
153
+ }
154
+ await ((_b = (_a = this.deps).onAbort) === null || _b === void 0 ? void 0 : _b.call(_a, clientPubkey, eventId, reason));
155
+ await this.flushPendingResponse(eventId);
156
+ },
157
+ });
158
+ this.writers.set(eventId, writer);
159
+ }
160
+ /**
161
+ * Flushes a deferred response for a stream once it has closed or aborted.
162
+ */
163
+ async flushPendingResponse(eventId) {
164
+ const pendingResponse = this.pendingResponses.get(eventId);
165
+ this.pendingResponses.delete(eventId);
166
+ this.writers.delete(eventId);
167
+ if (!pendingResponse) {
168
+ return;
169
+ }
170
+ await this.deps.handleResponse(pendingResponse);
171
+ }
172
+ async handleProbeTimeout(clientPubkey, eventId) {
173
+ var _a, _b;
174
+ const session = this.deps.sessionStore.getSession(clientPubkey);
175
+ if (session) {
176
+ this.pendingSessionEvictions.set(eventId, {
177
+ clientPubkey,
178
+ session: { ...session },
179
+ });
180
+ this.evictedClientPubkeys.add(clientPubkey);
181
+ }
182
+ const removed = this.deps.sessionStore.removeSession(clientPubkey);
183
+ if (!removed && !session) {
184
+ return;
185
+ }
186
+ this.deps.logger.info('Removed session after open-stream probe timeout', {
187
+ clientPubkey,
188
+ eventId,
189
+ });
190
+ const evictionSession = session !== null && session !== void 0 ? session : {
191
+ isInitialized: false,
192
+ isEncrypted: false,
193
+ hasSentCommonTags: false,
194
+ supportsEncryption: false,
195
+ supportsEphemeralEncryption: false,
196
+ supportsOversizedTransfer: false,
197
+ supportsOpenStream: false,
198
+ };
199
+ await Promise.resolve((_b = (_a = this.deps).onClientSessionEvicted) === null || _b === void 0 ? void 0 : _b.call(_a, {
200
+ clientPubkey,
201
+ session: evictionSession,
202
+ })).catch((error) => {
203
+ this.deps.logger.error('Error in onClientSessionEvicted callback', {
204
+ clientPubkey,
205
+ error,
206
+ });
207
+ });
208
+ }
209
+ /**
210
+ * Test-only accessor for writers map.
211
+ * @internal
212
+ */
213
+ getWritersMap() {
214
+ return this.writers;
215
+ }
216
+ /**
217
+ * Test-only accessor for pending responses map.
218
+ * @internal
219
+ */
220
+ getPendingResponsesMap() {
221
+ return this.pendingResponses;
222
+ }
223
+ }
224
+ //# sourceMappingURL=open-stream-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-stream-factory.js","sourceRoot":"","sources":["../../../../src/transport/nostr-server/open-stream-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { type JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
2
+ import { type Logger } from '../../core/utils/logger.js';
3
+ import { type CorrelationStore } from './correlation-store.js';
4
+ import { type SessionStore } from './session-store.js';
5
+ export interface OutboundNotificationBroadcasterDeps {
6
+ correlationStore: CorrelationStore;
7
+ sessionStore: SessionStore;
8
+ sendNotification: (clientPubkey: string, notification: JSONRPCMessage, correlatedEventId?: string) => Promise<void>;
9
+ enqueueTask: (task: () => Promise<void>) => void;
10
+ logger: Logger;
11
+ onerror?: (error: Error) => void;
12
+ }
13
+ /**
14
+ * Routes server outbound notifications to a specific client or broadcasts to all.
15
+ */
16
+ export declare class OutboundNotificationBroadcaster {
17
+ private deps;
18
+ constructor(deps: OutboundNotificationBroadcasterDeps);
19
+ /**
20
+ * Broadcasts a notification or routes it based on correlation metadata.
21
+ */
22
+ broadcast(notification: JSONRPCMessage): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=outbound-notification-broadcaster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-notification-broadcaster.d.ts","sourceRoot":"","sources":["../../../../src/transport/nostr-server/outbound-notification-broadcaster.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,mCAAmC;IAClD,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,CAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,cAAc,EAC5B,iBAAiB,CAAC,EAAE,MAAM,KACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,qBAAa,+BAA+B;IAC9B,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,mCAAmC;IAE7D;;OAEG;IACU,SAAS,CAAC,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAgEpE"}
@@ -0,0 +1,64 @@
1
+ import { isJSONRPCNotification, } from '@modelcontextprotocol/sdk/types.js';
2
+ /**
3
+ * Routes server outbound notifications to a specific client or broadcasts to all.
4
+ */
5
+ export class OutboundNotificationBroadcaster {
6
+ constructor(deps) {
7
+ this.deps = deps;
8
+ }
9
+ /**
10
+ * Broadcasts a notification or routes it based on correlation metadata.
11
+ */
12
+ async broadcast(notification) {
13
+ var _a, _b, _c, _d, _e;
14
+ try {
15
+ // Special handling for progress notifications
16
+ // TODO: Add handling for `notifications/resources/updated`, as they need to be associated with an id
17
+ if (isJSONRPCNotification(notification) &&
18
+ notification.method === 'notifications/progress' &&
19
+ ((_a = notification.params) === null || _a === void 0 ? void 0 : _a.progressToken)) {
20
+ const token = String(notification.params.progressToken);
21
+ // Use O(1) lookup for progress token routing
22
+ const nostrEventId = this.deps.correlationStore.getEventIdByProgressToken(token);
23
+ if (nostrEventId) {
24
+ const route = this.deps.correlationStore.getEventRoute(nostrEventId);
25
+ if (route) {
26
+ await this.deps.sendNotification(route.clientPubkey, notification, nostrEventId);
27
+ return;
28
+ }
29
+ }
30
+ const error = new Error(`No client found for progress token: ${token}`);
31
+ this.deps.logger.error('Progress token not found', { token });
32
+ (_c = (_b = this.deps).onerror) === null || _c === void 0 ? void 0 : _c.call(_b, error);
33
+ return;
34
+ }
35
+ // Use TaskQueue for outbound notification broadcasting to prevent event loop blocking
36
+ for (const [clientPubkey, session,] of this.deps.sessionStore.getAllSessions()) {
37
+ if (session.isInitialized) {
38
+ this.deps.enqueueTask(async () => {
39
+ try {
40
+ await this.deps.sendNotification(clientPubkey, notification);
41
+ }
42
+ catch (error) {
43
+ this.deps.logger.error('Error sending notification', {
44
+ error: error instanceof Error ? error.message : String(error),
45
+ clientPubkey,
46
+ method: isJSONRPCNotification(notification)
47
+ ? notification.method
48
+ : 'unknown',
49
+ });
50
+ }
51
+ });
52
+ }
53
+ }
54
+ }
55
+ catch (error) {
56
+ this.deps.logger.error('Error in notification broadcaster', {
57
+ error: error instanceof Error ? error.message : String(error),
58
+ stack: error instanceof Error ? error.stack : undefined,
59
+ });
60
+ (_e = (_d = this.deps).onerror) === null || _e === void 0 ? void 0 : _e.call(_d, error instanceof Error ? error : new Error(String(error)));
61
+ }
62
+ }
63
+ }
64
+ //# sourceMappingURL=outbound-notification-broadcaster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-notification-broadcaster.js","sourceRoot":"","sources":["../../../../src/transport/nostr-server/outbound-notification-broadcaster.ts"],"names":[],"mappings":"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"}