@nority/bridge-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +164 -0
  3. package/dist/agent.d.ts +101 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +6 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/auth/jwt.d.ts +38 -0
  8. package/dist/auth/jwt.d.ts.map +1 -0
  9. package/dist/auth/jwt.js +83 -0
  10. package/dist/auth/jwt.js.map +1 -0
  11. package/dist/auth/pairing.d.ts +14 -0
  12. package/dist/auth/pairing.d.ts.map +1 -0
  13. package/dist/auth/pairing.js +34 -0
  14. package/dist/auth/pairing.js.map +1 -0
  15. package/dist/auth/reconnect.d.ts +28 -0
  16. package/dist/auth/reconnect.d.ts.map +1 -0
  17. package/dist/auth/reconnect.js +110 -0
  18. package/dist/auth/reconnect.js.map +1 -0
  19. package/dist/bridge.d.ts +44 -0
  20. package/dist/bridge.d.ts.map +1 -0
  21. package/dist/bridge.js +311 -0
  22. package/dist/bridge.js.map +1 -0
  23. package/dist/config.d.ts +6 -0
  24. package/dist/config.d.ts.map +1 -0
  25. package/dist/config.js +47 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/conversation/replay.d.ts +30 -0
  28. package/dist/conversation/replay.d.ts.map +1 -0
  29. package/dist/conversation/replay.js +85 -0
  30. package/dist/conversation/replay.js.map +1 -0
  31. package/dist/conversation/runtime.d.ts +43 -0
  32. package/dist/conversation/runtime.d.ts.map +1 -0
  33. package/dist/conversation/runtime.js +481 -0
  34. package/dist/conversation/runtime.js.map +1 -0
  35. package/dist/conversation/state.d.ts +25 -0
  36. package/dist/conversation/state.d.ts.map +1 -0
  37. package/dist/conversation/state.js +130 -0
  38. package/dist/conversation/state.js.map +1 -0
  39. package/dist/crypto/conversation.d.ts +20 -0
  40. package/dist/crypto/conversation.d.ts.map +1 -0
  41. package/dist/crypto/conversation.js +134 -0
  42. package/dist/crypto/conversation.js.map +1 -0
  43. package/dist/crypto/hkdf-sha3.d.ts +5 -0
  44. package/dist/crypto/hkdf-sha3.d.ts.map +1 -0
  45. package/dist/crypto/hkdf-sha3.js +8 -0
  46. package/dist/crypto/hkdf-sha3.js.map +1 -0
  47. package/dist/crypto/identity.d.ts +21 -0
  48. package/dist/crypto/identity.d.ts.map +1 -0
  49. package/dist/crypto/identity.js +70 -0
  50. package/dist/crypto/identity.js.map +1 -0
  51. package/dist/crypto/payload.d.ts +10 -0
  52. package/dist/crypto/payload.d.ts.map +1 -0
  53. package/dist/crypto/payload.js +28 -0
  54. package/dist/crypto/payload.js.map +1 -0
  55. package/dist/crypto/x25519.d.ts +16 -0
  56. package/dist/crypto/x25519.d.ts.map +1 -0
  57. package/dist/crypto/x25519.js +44 -0
  58. package/dist/crypto/x25519.js.map +1 -0
  59. package/dist/index.d.ts +27 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +18 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/protocol/frames.d.ts +27 -0
  64. package/dist/protocol/frames.d.ts.map +1 -0
  65. package/dist/protocol/frames.js +43 -0
  66. package/dist/protocol/frames.js.map +1 -0
  67. package/dist/protocol/validation.d.ts +6 -0
  68. package/dist/protocol/validation.d.ts.map +1 -0
  69. package/dist/protocol/validation.js +33 -0
  70. package/dist/protocol/validation.js.map +1 -0
  71. package/dist/runtime/proactive.d.ts +14 -0
  72. package/dist/runtime/proactive.d.ts.map +1 -0
  73. package/dist/runtime/proactive.js +36 -0
  74. package/dist/runtime/proactive.js.map +1 -0
  75. package/dist/storage/conversation-store.d.ts +15 -0
  76. package/dist/storage/conversation-store.d.ts.map +1 -0
  77. package/dist/storage/conversation-store.js +75 -0
  78. package/dist/storage/conversation-store.js.map +1 -0
  79. package/dist/storage/state-store.d.ts +20 -0
  80. package/dist/storage/state-store.d.ts.map +1 -0
  81. package/dist/storage/state-store.js +74 -0
  82. package/dist/storage/state-store.js.map +1 -0
  83. package/dist/transport/outbound-queue.d.ts +18 -0
  84. package/dist/transport/outbound-queue.d.ts.map +1 -0
  85. package/dist/transport/outbound-queue.js +37 -0
  86. package/dist/transport/outbound-queue.js.map +1 -0
  87. package/dist/transport/websocket.d.ts +109 -0
  88. package/dist/transport/websocket.d.ts.map +1 -0
  89. package/dist/transport/websocket.js +346 -0
  90. package/dist/transport/websocket.js.map +1 -0
  91. package/package.json +37 -0
@@ -0,0 +1,44 @@
1
+ import type { BridgeConfig, PairingInfo } from "./agent.js";
2
+ import type { ProactiveTurnRequest } from "./runtime/proactive.js";
3
+ import { type BridgeFrame } from "./protocol/frames.js";
4
+ /**
5
+ * Bridge lifecycle states.
6
+ */
7
+ export type BridgeState = "idle" | "pairing" | "connecting" | "connected" | "reconnecting" | "blocked" | "failed" | "stopped";
8
+ /**
9
+ * NorityBridge is the main entry point for bridge implementations.
10
+ * Manages pairing, auth refresh, reconnection, and durable bridge identity.
11
+ */
12
+ export declare class NorityBridge {
13
+ private readonly config;
14
+ private readonly logger;
15
+ private readonly stateStore;
16
+ private readonly accessTokenManager;
17
+ private readonly conversationRuntime;
18
+ private state;
19
+ private durableState;
20
+ private pairingInfo;
21
+ private pairingTimer;
22
+ private pairingSocket;
23
+ private transport;
24
+ private readonly pendingFrameTasks;
25
+ constructor(config: BridgeConfig);
26
+ getState(): BridgeState;
27
+ getPairingInfo(): PairingInfo | null;
28
+ createProactiveTurnFrame(conversationId: string, request: ProactiveTurnRequest): BridgeFrame<"assistant_turn_start">;
29
+ start(): Promise<void>;
30
+ stop(): Promise<void>;
31
+ regeneratePairingToken(): Promise<PairingInfo>;
32
+ private beginPairingFlow;
33
+ private restartPairingFlow;
34
+ private handlePairingMessage;
35
+ private ensureAuthenticatedTransport;
36
+ private handleTransportStateChange;
37
+ private getDurableState;
38
+ private clearPairingTimer;
39
+ private setState;
40
+ private handleTransportFrame;
41
+ private trackFrameTask;
42
+ private sendTransportFrame;
43
+ }
44
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAgB,WAAW,EAAE,MAAM,YAAY,CAAC;AAW1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAMnE,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGrE;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,SAAS,GACT,YAAY,GACZ,WAAW,GACX,cAAc,GACd,SAAS,GACT,QAAQ,GACR,SAAS,CAAC;AASd;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA2B;IAC9D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,SAAS,CAAgD;IACjE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA4B;gBAElD,MAAM,EAAE,YAAY;IAkBhC,QAAQ,IAAI,WAAW;IAIvB,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC,wBAAwB,CACtB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,oBAAoB,GAC5B,WAAW,CAAC,sBAAsB,CAAC;IAOhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBrB,sBAAsB,IAAI,OAAO,CAAC,WAAW,CAAC;YAatC,gBAAgB;YAKhB,kBAAkB;YAkDlB,oBAAoB;YAuDpB,4BAA4B;IAqC1C,OAAO,CAAC,0BAA0B;IAqClC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,QAAQ;YAIF,oBAAoB;YAYpB,cAAc;IAS5B,OAAO,CAAC,kBAAkB;CAQ3B"}
package/dist/bridge.js ADDED
@@ -0,0 +1,311 @@
1
+ import { validateConfig } from "./config.js";
2
+ import { createPairingExpiry, createPairingToken, createDeeplinkUrl, PAIRING_TOKEN_TTL_SECONDS, } from "./auth/pairing.js";
3
+ import { BridgeAccessTokenManager } from "./auth/reconnect.js";
4
+ import { FileBridgeStateStore } from "./storage/state-store.js";
5
+ import { ConversationRuntime } from "./conversation/runtime.js";
6
+ import { AuthenticatedWebSocketTransport, } from "./transport/websocket.js";
7
+ import { createFrame } from "./protocol/frames.js";
8
+ import { getEd25519PublicKeyBase64 } from "./crypto/identity.js";
9
+ const noopLogger = {
10
+ debug: () => { },
11
+ info: () => { },
12
+ warn: () => { },
13
+ error: () => { },
14
+ };
15
+ /**
16
+ * NorityBridge is the main entry point for bridge implementations.
17
+ * Manages pairing, auth refresh, reconnection, and durable bridge identity.
18
+ */
19
+ export class NorityBridge {
20
+ config;
21
+ logger;
22
+ stateStore;
23
+ accessTokenManager;
24
+ conversationRuntime;
25
+ state = "idle";
26
+ durableState = null;
27
+ pairingInfo = null;
28
+ pairingTimer = null;
29
+ pairingSocket = null;
30
+ transport = null;
31
+ pendingFrameTasks = new Set();
32
+ constructor(config) {
33
+ validateConfig(config);
34
+ this.config = config;
35
+ this.logger = config.logger ?? noopLogger;
36
+ this.stateStore = new FileBridgeStateStore(config.dataDir);
37
+ this.accessTokenManager = new BridgeAccessTokenManager({
38
+ backendUrl: config.backendUrl,
39
+ fetchImplementation: config.fetchImplementation,
40
+ clock: config.clock,
41
+ });
42
+ this.conversationRuntime = new ConversationRuntime({
43
+ dataDir: config.dataDir,
44
+ agent: config.agent,
45
+ logger: this.logger,
46
+ clock: config.clock,
47
+ });
48
+ }
49
+ getState() {
50
+ return this.state;
51
+ }
52
+ getPairingInfo() {
53
+ return this.pairingInfo === null ? null : { ...this.pairingInfo };
54
+ }
55
+ createProactiveTurnFrame(conversationId, request) {
56
+ return this.conversationRuntime.createProactiveTurnFrame(conversationId, request);
57
+ }
58
+ async start() {
59
+ if (this.state !== "idle" && this.state !== "stopped") {
60
+ throw new Error(`NorityBridge.start: cannot start bridge in state ${this.state}`);
61
+ }
62
+ this.durableState = await this.stateStore.loadOrCreateIdentity();
63
+ await this.conversationRuntime.loadPersistedConversations();
64
+ if (!this.durableState.bridgeCredential) {
65
+ this.setState("pairing");
66
+ await this.beginPairingFlow();
67
+ return;
68
+ }
69
+ await this.ensureAuthenticatedTransport(false);
70
+ }
71
+ async stop() {
72
+ this.clearPairingTimer();
73
+ const pairingSocket = this.pairingSocket;
74
+ this.pairingSocket = null;
75
+ if (pairingSocket !== null) {
76
+ pairingSocket.close(1000, "pairing stopped");
77
+ }
78
+ this.conversationRuntime.stop();
79
+ if (this.transport !== null) {
80
+ await this.transport.disconnect();
81
+ this.transport = null;
82
+ }
83
+ await Promise.allSettled(Array.from(this.pendingFrameTasks));
84
+ this.setState("stopped");
85
+ }
86
+ async regeneratePairingToken() {
87
+ if (this.state !== "pairing") {
88
+ throw new Error(`NorityBridge.regeneratePairingToken: bridge must be in pairing state, got ${this.state}`);
89
+ }
90
+ await this.restartPairingFlow();
91
+ if (this.pairingInfo === null) {
92
+ throw new Error("NorityBridge.regeneratePairingToken: pairingInfo must exist");
93
+ }
94
+ return { ...this.pairingInfo };
95
+ }
96
+ async beginPairingFlow() {
97
+ const currentState = this.getDurableState();
98
+ await this.restartPairingFlow(currentState);
99
+ }
100
+ async restartPairingFlow(state = this.getDurableState()) {
101
+ const existingSocket = this.pairingSocket;
102
+ this.pairingSocket = null;
103
+ if (existingSocket !== null) {
104
+ existingSocket.close(1000, "pairing token rotated");
105
+ }
106
+ this.clearPairingTimer();
107
+ const token = this.config.pairingTokenFactory?.() ?? createPairingToken();
108
+ if (!token) {
109
+ throw new Error("NorityBridge.restartPairingFlow: pairing token must not be empty");
110
+ }
111
+ this.pairingInfo = {
112
+ token,
113
+ deeplinkUrl: createDeeplinkUrl(token),
114
+ expiresAt: createPairingExpiry({
115
+ clock: this.config.clock,
116
+ tokenTtlSeconds: PAIRING_TOKEN_TTL_SECONDS,
117
+ }),
118
+ };
119
+ this.config.onPairingToken?.({ ...this.pairingInfo });
120
+ this.pairingTimer = setTimeout(() => {
121
+ void this.restartPairingFlow(state);
122
+ }, PAIRING_TOKEN_TTL_SECONDS * 1000);
123
+ const webSocketFactory = this.config.webSocketFactory;
124
+ if (webSocketFactory === undefined) {
125
+ throw new Error("NorityBridge.restartPairingFlow: webSocketFactory is required for pairing");
126
+ }
127
+ const socket = webSocketFactory.create(this.config.backendUrl, {});
128
+ this.pairingSocket = socket;
129
+ await waitForOpen(socket);
130
+ socket.addEventListener("message", (event) => {
131
+ void this.handlePairingMessage(event.data);
132
+ });
133
+ const pairRequest = createFrame("pair_request", {
134
+ pairing_token: token,
135
+ bridge_public_key: getEd25519PublicKeyBase64(state.publicKeyPem),
136
+ });
137
+ socket.send(JSON.stringify(pairRequest));
138
+ }
139
+ async handlePairingMessage(rawData) {
140
+ let frame;
141
+ try {
142
+ frame = JSON.parse(rawData);
143
+ }
144
+ catch (error) {
145
+ this.logger.warn("NorityBridge.handlePairingMessage: invalid JSON", error);
146
+ return;
147
+ }
148
+ if (frame.type !== "paired") {
149
+ return;
150
+ }
151
+ const payload = frame.payload;
152
+ if (!payload.agent_id ||
153
+ !payload.bridge_credential ||
154
+ !payload.access_jwt ||
155
+ !payload.expires_at) {
156
+ throw new Error("NorityBridge.handlePairingMessage: paired payload missing required fields");
157
+ }
158
+ const currentState = this.getDurableState();
159
+ const nextState = {
160
+ ...currentState,
161
+ agentId: payload.agent_id,
162
+ bridgeCredential: payload.bridge_credential,
163
+ };
164
+ await this.stateStore.save(nextState);
165
+ this.durableState = nextState;
166
+ this.accessTokenManager.seed({
167
+ accessJwt: payload.access_jwt,
168
+ agentId: payload.agent_id,
169
+ expiresAt: payload.expires_at,
170
+ });
171
+ this.clearPairingTimer();
172
+ const pairingSocket = this.pairingSocket;
173
+ this.pairingSocket = null;
174
+ if (pairingSocket !== null) {
175
+ pairingSocket.close(1000, "pairing completed");
176
+ }
177
+ await this.ensureAuthenticatedTransport(false);
178
+ }
179
+ async ensureAuthenticatedTransport(forceRefresh) {
180
+ const currentState = this.getDurableState();
181
+ if (!currentState.bridgeCredential) {
182
+ throw new Error("NorityBridge.ensureAuthenticatedTransport: bridgeCredential is required");
183
+ }
184
+ if (this.transport === null) {
185
+ this.transport = new AuthenticatedWebSocketTransport({
186
+ backendUrl: this.config.backendUrl,
187
+ webSocketFactory: this.config.webSocketFactory,
188
+ heartbeatIntervalMs: this.config.heartbeatIntervalMs,
189
+ idleTimeoutMs: this.config.idleTimeoutMs,
190
+ random: this.config.backoffRandom,
191
+ clock: this.config.clock,
192
+ logger: this.logger,
193
+ onFrame: async (frame) => {
194
+ await this.trackFrameTask(this.handleTransportFrame(frame));
195
+ },
196
+ onStateChange: (transportState) => {
197
+ this.handleTransportStateChange(transportState);
198
+ },
199
+ getAccessToken: async (refreshRequested = false) => {
200
+ const token = await this.accessTokenManager.getAccessToken({
201
+ credential: currentState.bridgeCredential ?? "",
202
+ privateKeyPem: currentState.privateKeyPem,
203
+ forceRefresh: refreshRequested,
204
+ });
205
+ return token.accessJwt;
206
+ },
207
+ });
208
+ }
209
+ await this.transport.connect(forceRefresh);
210
+ }
211
+ handleTransportStateChange(transportState) {
212
+ switch (transportState) {
213
+ case "connecting":
214
+ this.setState("connecting");
215
+ break;
216
+ case "connected":
217
+ this.setState("connected");
218
+ if (this.transport !== null) {
219
+ const replayRequest = this.conversationRuntime.createReplayRequestFrame();
220
+ if (replayRequest !== null) {
221
+ this.transport.send(replayRequest);
222
+ }
223
+ }
224
+ break;
225
+ case "reconnecting":
226
+ this.setState("reconnecting");
227
+ break;
228
+ case "blocked":
229
+ this.setState("blocked");
230
+ break;
231
+ case "failed":
232
+ this.setState("failed");
233
+ break;
234
+ case "stopped":
235
+ if (this.state !== "stopped") {
236
+ this.setState("stopped");
237
+ }
238
+ break;
239
+ case "idle":
240
+ break;
241
+ default:
242
+ throw new Error(`NorityBridge.handleTransportStateChange: unsupported transport state ${transportState}`);
243
+ }
244
+ }
245
+ getDurableState() {
246
+ if (this.durableState === null) {
247
+ throw new Error("NorityBridge: durable bridge state has not been loaded");
248
+ }
249
+ return this.durableState;
250
+ }
251
+ clearPairingTimer() {
252
+ if (this.pairingTimer !== null) {
253
+ clearTimeout(this.pairingTimer);
254
+ this.pairingTimer = null;
255
+ }
256
+ }
257
+ setState(nextState) {
258
+ this.state = nextState;
259
+ }
260
+ async handleTransportFrame(frame) {
261
+ if (this.transport === null) {
262
+ throw new Error("NorityBridge.handleTransportFrame: transport must exist while handling frames");
263
+ }
264
+ await this.conversationRuntime.handleFrame(frame, (outboundFrame) => {
265
+ this.sendTransportFrame(outboundFrame);
266
+ });
267
+ }
268
+ async trackFrameTask(task) {
269
+ this.pendingFrameTasks.add(task);
270
+ try {
271
+ await task;
272
+ }
273
+ finally {
274
+ this.pendingFrameTasks.delete(task);
275
+ }
276
+ }
277
+ sendTransportFrame(outboundFrame) {
278
+ if (this.transport === null) {
279
+ throw new Error("NorityBridge.sendTransportFrame: transport must exist while sending outbound frames");
280
+ }
281
+ this.transport.send(outboundFrame);
282
+ }
283
+ }
284
+ function waitForOpen(socket) {
285
+ if (socket.readyState === 1) {
286
+ return Promise.resolve();
287
+ }
288
+ return new Promise((resolve, reject) => {
289
+ const handleOpen = () => {
290
+ cleanup();
291
+ resolve();
292
+ };
293
+ const handleError = () => {
294
+ cleanup();
295
+ reject(new Error("NorityBridge.waitForOpen: websocket error during pairing"));
296
+ };
297
+ const handleClose = () => {
298
+ cleanup();
299
+ reject(new Error("NorityBridge.waitForOpen: websocket closed before pairing socket opened"));
300
+ };
301
+ const cleanup = () => {
302
+ socket.removeEventListener("open", handleOpen);
303
+ socket.removeEventListener("error", handleError);
304
+ socket.removeEventListener("close", handleClose);
305
+ };
306
+ socket.addEventListener("open", handleOpen);
307
+ socket.addEventListener("error", handleError);
308
+ socket.addEventListener("close", handleClose);
309
+ });
310
+ }
311
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { BridgeConfig } from "./agent.js";
2
+ /**
3
+ * Validate bridge configuration at startup.
4
+ */
5
+ export declare function validateConfig(config: BridgeConfig): void;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAmEzD"}
package/dist/config.js ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Validate bridge configuration at startup.
3
+ */
4
+ export function validateConfig(config) {
5
+ if (!config) {
6
+ throw new Error("validateConfig: config is required");
7
+ }
8
+ if (!config.backendUrl) {
9
+ throw new Error("validateConfig: backendUrl is required");
10
+ }
11
+ if (!config.dataDir) {
12
+ throw new Error("validateConfig: dataDir is required");
13
+ }
14
+ if (!config.agent) {
15
+ throw new Error("validateConfig: agent adapter is required");
16
+ }
17
+ if (typeof config.agent.invokeAgent !== "function") {
18
+ throw new Error("validateConfig: agent must implement invokeAgent()");
19
+ }
20
+ try {
21
+ new URL(config.backendUrl);
22
+ }
23
+ catch {
24
+ throw new Error(`validateConfig: backendUrl is not a valid URL: ${config.backendUrl}`);
25
+ }
26
+ if (config.heartbeatIntervalMs !== undefined &&
27
+ (!Number.isInteger(config.heartbeatIntervalMs) || config.heartbeatIntervalMs <= 0)) {
28
+ throw new Error(`validateConfig: heartbeatIntervalMs must be a positive integer, got ${config.heartbeatIntervalMs}`);
29
+ }
30
+ if (config.idleTimeoutMs !== undefined &&
31
+ (!Number.isInteger(config.idleTimeoutMs) || config.idleTimeoutMs <= 0)) {
32
+ throw new Error(`validateConfig: idleTimeoutMs must be a positive integer, got ${config.idleTimeoutMs}`);
33
+ }
34
+ if (config.heartbeatIntervalMs !== undefined &&
35
+ config.idleTimeoutMs !== undefined &&
36
+ config.idleTimeoutMs <= config.heartbeatIntervalMs) {
37
+ throw new Error("validateConfig: idleTimeoutMs must be greater than heartbeatIntervalMs");
38
+ }
39
+ if (config.pairingTokenFactory !== undefined &&
40
+ typeof config.pairingTokenFactory !== "function") {
41
+ throw new Error("validateConfig: pairingTokenFactory must be a function when provided");
42
+ }
43
+ if (config.webSocketFactory !== undefined && typeof config.webSocketFactory.create !== "function") {
44
+ throw new Error("validateConfig: webSocketFactory.create must be a function when provided");
45
+ }
46
+ }
47
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,kDAAkD,MAAM,CAAC,UAAU,EAAE,CACtE,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,mBAAmB,KAAK,SAAS;QACxC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,mBAAmB,CAAC,IAAI,MAAM,CAAC,mBAAmB,IAAI,CAAC,CAAC,EAClF,CAAC;QACD,MAAM,IAAI,KAAK,CACb,uEAAuE,MAAM,CAAC,mBAAmB,EAAE,CACpG,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,aAAa,KAAK,SAAS;QAClC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC,EACtE,CAAC;QACD,MAAM,IAAI,KAAK,CACb,iEAAiE,MAAM,CAAC,aAAa,EAAE,CACxF,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,mBAAmB,KAAK,SAAS;QACxC,MAAM,CAAC,aAAa,KAAK,SAAS;QAClC,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,mBAAmB,EAClD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,mBAAmB,KAAK,SAAS;QACxC,OAAO,MAAM,CAAC,mBAAmB,KAAK,UAAU,EAChD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,gBAAgB,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAClG,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Replay and history rebuild logic following the bridge protocol specification.
3
+ *
4
+ * Rules (from bridge-protocol/replay/):
5
+ * 1. Skip events at or below last_applied_seq
6
+ * 2. Deduplicate by seq (first occurrence wins)
7
+ * 3. Sort remaining by ascending seq
8
+ * 4. Apply events in order to rebuild history
9
+ *
10
+ * Event format matches what the bridge SDK encrypts and stores:
11
+ * { type: "text_delta", content: "...", message_id: "..." }
12
+ */
13
+ export interface Turn {
14
+ role: "user" | "assistant";
15
+ text: string;
16
+ status: "complete" | "streaming";
17
+ }
18
+ export interface ConversationState {
19
+ last_applied_seq: number;
20
+ turns: Turn[];
21
+ }
22
+ export interface ReplayEvent {
23
+ seq: number;
24
+ type: string;
25
+ text?: string;
26
+ content?: string;
27
+ message_id?: string;
28
+ }
29
+ export declare function rebuildHistory(initialState: ConversationState, replayEvents: ReplayEvent[]): ConversationState;
30
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/conversation/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,WAAW,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,cAAc,CAC5B,YAAY,EAAE,iBAAiB,EAC/B,YAAY,EAAE,WAAW,EAAE,GAC1B,iBAAiB,CAgFnB"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Replay and history rebuild logic following the bridge protocol specification.
3
+ *
4
+ * Rules (from bridge-protocol/replay/):
5
+ * 1. Skip events at or below last_applied_seq
6
+ * 2. Deduplicate by seq (first occurrence wins)
7
+ * 3. Sort remaining by ascending seq
8
+ * 4. Apply events in order to rebuild history
9
+ *
10
+ * Event format matches what the bridge SDK encrypts and stores:
11
+ * { type: "text_delta", content: "...", message_id: "..." }
12
+ */
13
+ export function rebuildHistory(initialState, replayEvents) {
14
+ if (!initialState) {
15
+ throw new Error("rebuildHistory: initialState is required");
16
+ }
17
+ if (!Array.isArray(replayEvents)) {
18
+ throw new Error("rebuildHistory: replayEvents must be an array");
19
+ }
20
+ // 1. Filter out events at or below last_applied_seq
21
+ const filtered = replayEvents.filter((e) => e.seq > initialState.last_applied_seq);
22
+ // 2. Deduplicate by seq (first occurrence wins)
23
+ const seen = new Set();
24
+ const deduped = [];
25
+ for (const event of filtered) {
26
+ if (!seen.has(event.seq)) {
27
+ seen.add(event.seq);
28
+ deduped.push(event);
29
+ }
30
+ }
31
+ // 3. Sort by ascending seq
32
+ deduped.sort((a, b) => a.seq - b.seq);
33
+ // 4. Apply events to rebuild state
34
+ const turns = [...initialState.turns.map((t) => ({ ...t }))];
35
+ let lastSeq = initialState.last_applied_seq;
36
+ // Track in-progress assistant messages
37
+ const pendingAssistant = new Map(); // message_id -> turn index
38
+ for (const event of deduped) {
39
+ lastSeq = event.seq;
40
+ switch (event.type) {
41
+ case "user_message": {
42
+ turns.push({
43
+ role: "user",
44
+ text: event.content ?? event.text ?? "",
45
+ status: "complete",
46
+ });
47
+ break;
48
+ }
49
+ case "text_delta": {
50
+ const msgId = event.message_id ?? "";
51
+ const text = event.content ?? "";
52
+ if (!pendingAssistant.has(msgId)) {
53
+ const idx = turns.length;
54
+ turns.push({
55
+ role: "assistant",
56
+ text,
57
+ status: "streaming",
58
+ });
59
+ pendingAssistant.set(msgId, idx);
60
+ }
61
+ else {
62
+ const idx = pendingAssistant.get(msgId);
63
+ turns[idx].text += text;
64
+ }
65
+ break;
66
+ }
67
+ case "done": {
68
+ const msgId = event.message_id ?? "";
69
+ if (pendingAssistant.has(msgId)) {
70
+ const idx = pendingAssistant.get(msgId);
71
+ turns[idx].status = "complete";
72
+ pendingAssistant.delete(msgId);
73
+ }
74
+ break;
75
+ }
76
+ case "tool_call_start":
77
+ case "tool_result":
78
+ case "run_status":
79
+ // Acknowledged but not rendered in history turns.
80
+ break;
81
+ }
82
+ }
83
+ return { last_applied_seq: lastSeq, turns };
84
+ }
85
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/conversation/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { AgentAdapter, AgentEvent, BridgeLogger } from "../agent.js";
2
+ import { type BridgeFrame } from "../protocol/frames.js";
3
+ import { type ProactiveTurnRequest } from "../runtime/proactive.js";
4
+ export interface ConversationRuntimeOptions {
5
+ dataDir: string;
6
+ agent: AgentAdapter;
7
+ logger?: BridgeLogger;
8
+ clock?: () => Date;
9
+ }
10
+ /**
11
+ * Conversation runtime for key exchange, encrypted message handling, replay, and deletion.
12
+ */
13
+ export declare class ConversationRuntime {
14
+ private readonly agent;
15
+ private readonly logger;
16
+ private readonly clock;
17
+ private readonly store;
18
+ private readonly conversations;
19
+ private readonly activeInvocations;
20
+ constructor(options: ConversationRuntimeOptions);
21
+ loadPersistedConversations(): Promise<void>;
22
+ hasConversation(conversationId: string): boolean;
23
+ createReplayRequestFrame(): BridgeFrame<"replay_request"> | null;
24
+ createProactiveTurnFrame(conversationId: string, request: ProactiveTurnRequest): BridgeFrame<"assistant_turn_start">;
25
+ stop(): void;
26
+ private activeInvocationCount;
27
+ handleFrame(frame: BridgeFrame, sendFrame: (frame: BridgeFrame) => void): Promise<void>;
28
+ private handleKeyExchange;
29
+ private handleMessage;
30
+ private handleReplay;
31
+ private handleConversationDeleted;
32
+ private applyReplayEvents;
33
+ private applyReplayPayload;
34
+ private applyAssistantReplayDelta;
35
+ private completeAssistantReplayTurn;
36
+ private abortInvocation;
37
+ }
38
+ export type SerializedEventType = "text_delta" | "tool_call_start" | "tool_call_update" | "tool_result" | "thinking_start" | "thinking_delta" | "thinking_complete" | "run_status" | "error" | "done";
39
+ export declare function serializeAgentEvent(event: AgentEvent): {
40
+ eventType: SerializedEventType;
41
+ body: Record<string, string>;
42
+ } | null;
43
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/conversation/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAyB,MAAM,aAAa,CAAC;AAajG,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB;AASD;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwC;IACtE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAsC;gBAE5D,OAAO,EAAE,0BAA0B;IAiBzC,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjD,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO;IAOhD,wBAAwB,IAAI,WAAW,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAahE,wBAAwB,CACtB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,oBAAoB,GAC5B,WAAW,CAAC,sBAAsB,CAAC;IAStC,IAAI,IAAI,IAAI;IAMZ,OAAO,CAAC,qBAAqB;IAIvB,WAAW,CACf,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC;YAgCF,iBAAiB;YAmCjB,aAAa;YA0Eb,YAAY;YAgDZ,yBAAyB;IAavC,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,kBAAkB;IAgD1B,OAAO,CAAC,yBAAyB;IA+BjC,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,eAAe;CAIxB;AAoFD,MAAM,MAAM,mBAAmB,GAC3B,YAAY,GACZ,iBAAiB,GACjB,kBAAkB,GAClB,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,mBAAmB,GACnB,YAAY,GACZ,OAAO,GACP,MAAM,CAAC;AAEX,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,GAEf;IACE,SAAS,EAAE,mBAAmB,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,GACD,IAAI,CAwFP"}