@agentvault/secure-channel 0.6.8 → 0.6.10

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/channel.d.ts CHANGED
@@ -12,8 +12,14 @@ export declare class SecureChannel extends EventEmitter {
12
12
  private _pollTimer;
13
13
  private _reconnectAttempt;
14
14
  private _reconnectTimer;
15
+ private _pingTimer;
16
+ private _pingTimeout;
17
+ private _pendingAcks;
18
+ private _ackTimer;
15
19
  private _stopped;
16
20
  private _persisted;
21
+ private static readonly PING_INTERVAL_MS;
22
+ private static readonly PING_TIMEOUT_MS;
17
23
  constructor(config: SecureChannelConfig);
18
24
  get state(): ChannelState;
19
25
  get deviceId(): string | null;
@@ -86,6 +92,10 @@ export declare class SecureChannel extends EventEmitter {
86
92
  * For each conversation, fetches messages since last sync and decrypts.
87
93
  */
88
94
  private _syncMissedMessages;
95
+ private _sendAck;
96
+ private _flushAcks;
97
+ private _startPing;
98
+ private _stopPing;
89
99
  private _scheduleReconnect;
90
100
  private _setState;
91
101
  private _handleError;
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAa3C,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EAKb,MAAM,YAAY,CAAC;AAiDpB,qBAAa,aAAc,SAAQ,YAAY;IAiBjC,OAAO,CAAC,MAAM;IAhB1B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,sBAAsB,CAAc;IAC5C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,SAAS,CAGH;IACd,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,eAAe,CAA8C;IACrE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAA+B;gBAE7B,MAAM,EAAE,mBAAmB;IAI/C,IAAI,KAAK,IAAI,YAAY,CAExB;IAED,IAAI,QAAQ,IAAI,MAAM,GAAG,IAAI,CAE5B;IAED,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED,iEAAiE;IACjE,IAAI,cAAc,IAAI,MAAM,GAAG,IAAI,CAElC;IAED,2CAA2C;IAC3C,IAAI,eAAe,IAAI,MAAM,EAAE,CAE9B;IAED,6CAA6C;IAC7C,IAAI,YAAY,IAAI,MAAM,CAEzB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;OAGG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCtE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAsC1F;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;YAiCtE,OAAO;IAgDrB,OAAO,CAAC,KAAK;YAsCC,SAAS;IAyIvB,OAAO,CAAC,QAAQ;IAsEhB;;;;OAIG;YACW,sBAAsB;IAwFpC;;;OAGG;YACW,oBAAoB;IAqClC;;;OAGG;YACW,uBAAuB;IAkCrC;;;;OAIG;YACW,mBAAmB;IAkEjC;;;OAGG;YACW,mBAAmB;IA4FjC,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,YAAY;IAKpB;;;OAGG;YACW,aAAa;CAc5B"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAa3C,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EAKb,MAAM,YAAY,CAAC;AAiDpB,qBAAa,aAAc,SAAQ,YAAY;IAwBjC,OAAO,CAAC,MAAM;IAvB1B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,sBAAsB,CAAc;IAC5C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,SAAS,CAGH;IACd,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,eAAe,CAA8C;IACrE,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAA+B;IAEjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAW;gBAE9B,MAAM,EAAE,mBAAmB;IAI/C,IAAI,KAAK,IAAI,YAAY,CAExB;IAED,IAAI,QAAQ,IAAI,MAAM,GAAG,IAAI,CAE5B;IAED,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED,iEAAiE;IACjE,IAAI,cAAc,IAAI,MAAM,GAAG,IAAI,CAElC;IAED,2CAA2C;IAC3C,IAAI,eAAe,IAAI,MAAM,EAAE,CAE9B;IAED,6CAA6C;IAC7C,IAAI,YAAY,IAAI,MAAM,CAEzB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;OAGG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCtE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B3B;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAsC1F;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;YAiCtE,OAAO;IAgDrB,OAAO,CAAC,KAAK;YAsCC,SAAS;IAyIvB,OAAO,CAAC,QAAQ;IAwEhB;;;;OAIG;YACW,sBAAsB;IA2FpC;;;OAGG;YACW,oBAAoB;IAqClC;;;OAGG;YACW,uBAAuB;IAkCrC;;;;OAIG;YACW,mBAAmB;IAkEjC;;;OAGG;YACW,mBAAmB;IA+FjC,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,YAAY;IAKpB;;;OAGG;YACW,aAAa;CAc5B"}
package/dist/cli.js CHANGED
@@ -45061,7 +45061,8 @@ function migratePersistedState(raw) {
45061
45061
  messageHistory: []
45062
45062
  };
45063
45063
  }
45064
- var SecureChannel = class extends EventEmitter {
45064
+ var SecureChannel = class _SecureChannel extends EventEmitter {
45065
+ // Treat as dead if no pong within 10s
45065
45066
  constructor(config) {
45066
45067
  super();
45067
45068
  this.config = config;
@@ -45076,8 +45077,15 @@ var SecureChannel = class extends EventEmitter {
45076
45077
  _pollTimer = null;
45077
45078
  _reconnectAttempt = 0;
45078
45079
  _reconnectTimer = null;
45080
+ _pingTimer = null;
45081
+ _pingTimeout = null;
45082
+ _pendingAcks = [];
45083
+ _ackTimer = null;
45079
45084
  _stopped = false;
45080
45085
  _persisted = null;
45086
+ static PING_INTERVAL_MS = 3e4;
45087
+ // Send ping every 30s
45088
+ static PING_TIMEOUT_MS = 1e4;
45081
45089
  get state() {
45082
45090
  return this._state;
45083
45091
  }
@@ -45185,6 +45193,12 @@ var SecureChannel = class extends EventEmitter {
45185
45193
  }
45186
45194
  async stop() {
45187
45195
  this._stopped = true;
45196
+ this._flushAcks();
45197
+ this._stopPing();
45198
+ if (this._ackTimer) {
45199
+ clearTimeout(this._ackTimer);
45200
+ this._ackTimer = null;
45201
+ }
45188
45202
  if (this._pollTimer) {
45189
45203
  clearTimeout(this._pollTimer);
45190
45204
  this._pollTimer = null;
@@ -45457,6 +45471,7 @@ var SecureChannel = class extends EventEmitter {
45457
45471
  this._ws = ws;
45458
45472
  ws.on("open", async () => {
45459
45473
  this._reconnectAttempt = 0;
45474
+ this._startPing(ws);
45460
45475
  await this._syncMissedMessages();
45461
45476
  this._setState("ready");
45462
45477
  this.emit("ready");
@@ -45485,6 +45500,7 @@ var SecureChannel = class extends EventEmitter {
45485
45500
  }
45486
45501
  });
45487
45502
  ws.on("close", () => {
45503
+ this._stopPing();
45488
45504
  if (this._stopped) return;
45489
45505
  this._setState("disconnected");
45490
45506
  this._scheduleReconnect();
@@ -45513,6 +45529,7 @@ var SecureChannel = class extends EventEmitter {
45513
45529
  ciphertext: msgData.ciphertext
45514
45530
  });
45515
45531
  const plaintext = session.ratchet.decrypt(encrypted);
45532
+ this._sendAck(msgData.message_id);
45516
45533
  if (!session.activated) {
45517
45534
  session.activated = true;
45518
45535
  console.log(`[SecureChannel] Session ${convId.slice(0, 8)}... activated by first owner message`);
@@ -45697,6 +45714,7 @@ var SecureChannel = class extends EventEmitter {
45697
45714
  ciphertext: msg.ciphertext
45698
45715
  });
45699
45716
  const plaintext = session.ratchet.decrypt(encrypted);
45717
+ this._sendAck(msg.id);
45700
45718
  if (!session.activated) {
45701
45719
  session.activated = true;
45702
45720
  console.log(`[SecureChannel] Session ${msg.conversation_id.slice(0, 8)}... activated during sync`);
@@ -45733,6 +45751,43 @@ var SecureChannel = class extends EventEmitter {
45733
45751
  } catch {
45734
45752
  }
45735
45753
  }
45754
+ _sendAck(messageId) {
45755
+ this._pendingAcks.push(messageId);
45756
+ if (this._ackTimer) clearTimeout(this._ackTimer);
45757
+ this._ackTimer = setTimeout(() => this._flushAcks(), 500);
45758
+ }
45759
+ _flushAcks() {
45760
+ if (this._pendingAcks.length === 0 || !this._ws) return;
45761
+ const batch = this._pendingAcks.splice(0, 50);
45762
+ this._ws.send(JSON.stringify({ event: "ack", data: { message_ids: batch } }));
45763
+ }
45764
+ _startPing(ws) {
45765
+ this._stopPing();
45766
+ this._pingTimer = setInterval(() => {
45767
+ if (ws.readyState !== WebSocket.OPEN) return;
45768
+ this._pingTimeout = setTimeout(() => {
45769
+ console.log("[SecureChannel] Ping timeout \u2014 reconnecting stale WebSocket");
45770
+ ws.terminate();
45771
+ }, _SecureChannel.PING_TIMEOUT_MS);
45772
+ ws.ping();
45773
+ }, _SecureChannel.PING_INTERVAL_MS);
45774
+ ws.on("pong", () => {
45775
+ if (this._pingTimeout) {
45776
+ clearTimeout(this._pingTimeout);
45777
+ this._pingTimeout = null;
45778
+ }
45779
+ });
45780
+ }
45781
+ _stopPing() {
45782
+ if (this._pingTimer) {
45783
+ clearInterval(this._pingTimer);
45784
+ this._pingTimer = null;
45785
+ }
45786
+ if (this._pingTimeout) {
45787
+ clearTimeout(this._pingTimeout);
45788
+ this._pingTimeout = null;
45789
+ }
45790
+ }
45736
45791
  _scheduleReconnect() {
45737
45792
  if (this._stopped) return;
45738
45793
  if (this._reconnectTimer) return;