@agentvault/agentvault 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -45292,6 +45292,8 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
45292
45292
  _lastWakeTick = Date.now();
45293
45293
  _pendingPollTimer = null;
45294
45294
  _syncMessageIds = null;
45295
+ /** Recently handled message IDs via WS — survives reconnects so sync skips them. Max 500. */
45296
+ _recentlyHandledIds = /* @__PURE__ */ new Set();
45295
45297
  /** Queued A2A messages for responder channels not yet activated (no first initiator message received). */
45296
45298
  _a2aPendingQueue = {};
45297
45299
  _scanEngine = null;
@@ -46397,6 +46399,20 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46397
46399
  this.emit("error", openErr);
46398
46400
  }
46399
46401
  });
46402
+ const _onUnhandledRejection = (reason) => {
46403
+ console.error("[SecureChannel] UNHANDLED REJECTION (would crash process):", reason);
46404
+ };
46405
+ const _onUncaughtException = (err) => {
46406
+ console.error("[SecureChannel] UNCAUGHT EXCEPTION (would crash process):", err);
46407
+ };
46408
+ process.on("unhandledRejection", _onUnhandledRejection);
46409
+ process.on("uncaughtException", _onUncaughtException);
46410
+ ws.on("close", (code, reason) => {
46411
+ const reasonStr = reason?.toString() || "";
46412
+ console.log(`[SecureChannel] WS CLOSED: code=${code} reason=${JSON.stringify(reasonStr)}`);
46413
+ process.removeListener("unhandledRejection", _onUnhandledRejection);
46414
+ process.removeListener("uncaughtException", _onUncaughtException);
46415
+ });
46400
46416
  ws.on("message", async (raw) => {
46401
46417
  this._lastServerMessage = Date.now();
46402
46418
  this._lastWakeTick = Date.now();
@@ -46416,8 +46432,10 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46416
46432
  return;
46417
46433
  }
46418
46434
  if (data.event === "message") {
46435
+ console.log(`[SecureChannel] \u2190 Direct message received: msg=${data.data?.message_id?.slice(0, 8) ?? "?"} conv=${data.data?.conversation_id?.slice(0, 8) ?? "?"}`);
46419
46436
  try {
46420
46437
  await this._handleIncomingMessage(data.data);
46438
+ console.log(`[SecureChannel] \u2190 Direct message processed OK: msg=${data.data?.message_id?.slice(0, 8) ?? "?"}`);
46421
46439
  } catch (msgErr) {
46422
46440
  console.error(
46423
46441
  `[SecureChannel] Message handler failed for conv ${data.data?.conversation_id?.slice(0, 8) ?? "?"}...:`,
@@ -46749,7 +46767,9 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46749
46767
  this.emit("error", err);
46750
46768
  }
46751
46769
  });
46752
- ws.on("close", () => {
46770
+ ws.on("close", (code, reason) => {
46771
+ const reasonStr = reason?.toString() || "";
46772
+ console.log(`[SecureChannel] WS close handler: code=${code} reason=${JSON.stringify(reasonStr)}`);
46753
46773
  this._stopPing();
46754
46774
  this._stopWakeDetector();
46755
46775
  this._stopPendingPoll();
@@ -46771,6 +46791,11 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46771
46791
  if (this._syncMessageIds?.has(msgData.message_id)) {
46772
46792
  return;
46773
46793
  }
46794
+ this._recentlyHandledIds.add(msgData.message_id);
46795
+ if (this._recentlyHandledIds.size > 500) {
46796
+ const all = [...this._recentlyHandledIds];
46797
+ this._recentlyHandledIds = new Set(all.slice(all.length - 400));
46798
+ }
46774
46799
  const convId = msgData.conversation_id;
46775
46800
  const session = this._sessions.get(convId);
46776
46801
  if (!session) {
@@ -46783,7 +46808,14 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46783
46808
  header_blob: msgData.header_blob,
46784
46809
  ciphertext: msgData.ciphertext
46785
46810
  });
46786
- const plaintext = session.ratchet.decrypt(encrypted);
46811
+ let plaintext;
46812
+ try {
46813
+ plaintext = session.ratchet.decrypt(encrypted);
46814
+ } catch (decryptErr) {
46815
+ console.error(`[SecureChannel] Direct message decrypt FAILED for conv ${convId.slice(0, 8)}...: ${String(decryptErr)}`);
46816
+ throw decryptErr;
46817
+ }
46818
+ console.log(`[SecureChannel] Direct message decrypted OK for conv ${convId.slice(0, 8)}...`);
46787
46819
  this._sendAck(msgData.message_id);
46788
46820
  if (!session.activated) {
46789
46821
  session.activated = true;
@@ -46876,7 +46908,13 @@ ${messageText}`;
46876
46908
  Promise.resolve(this.config.onMessage?.(emitText, metadata)).catch((err) => {
46877
46909
  console.error("[SecureChannel] onMessage callback error:", err);
46878
46910
  });
46879
- await this._relaySyncToSiblings(convId, session.ownerDeviceId, messageText, topicId);
46911
+ console.log(`[SecureChannel] Relaying sync to ${this._sessions.size - 1} siblings for conv ${convId.slice(0, 8)}...`);
46912
+ try {
46913
+ await this._relaySyncToSiblings(convId, session.ownerDeviceId, messageText, topicId);
46914
+ console.log(`[SecureChannel] Sync relay complete for conv ${convId.slice(0, 8)}...`);
46915
+ } catch (relayErr) {
46916
+ console.error(`[SecureChannel] Sync relay FAILED: ${String(relayErr)}`);
46917
+ }
46880
46918
  }
46881
46919
  if (this._persisted) {
46882
46920
  this._persisted.lastMessageTimestamp = msgData.created_at;
@@ -47001,22 +47039,29 @@ ${messageText}`;
47001
47039
  ts: (/* @__PURE__ */ new Date()).toISOString(),
47002
47040
  topicId
47003
47041
  });
47042
+ let relayed = 0;
47004
47043
  for (const [siblingConvId, siblingSession] of this._sessions) {
47005
47044
  if (siblingConvId === sourceConvId) continue;
47006
47045
  if (!siblingSession.activated) continue;
47007
- const syncEncrypted = siblingSession.ratchet.encrypt(syncPayload);
47008
- const syncTransport = encryptedMessageToTransport(syncEncrypted);
47009
- this._ws.send(
47010
- JSON.stringify({
47011
- event: "message",
47012
- data: {
47013
- conversation_id: siblingConvId,
47014
- header_blob: syncTransport.header_blob,
47015
- ciphertext: syncTransport.ciphertext
47016
- }
47017
- })
47018
- );
47046
+ try {
47047
+ const syncEncrypted = siblingSession.ratchet.encrypt(syncPayload);
47048
+ const syncTransport = encryptedMessageToTransport(syncEncrypted);
47049
+ this._ws.send(
47050
+ JSON.stringify({
47051
+ event: "message",
47052
+ data: {
47053
+ conversation_id: siblingConvId,
47054
+ header_blob: syncTransport.header_blob,
47055
+ ciphertext: syncTransport.ciphertext
47056
+ }
47057
+ })
47058
+ );
47059
+ relayed++;
47060
+ } catch (err) {
47061
+ console.error(`[SecureChannel] Sync send failed for sibling ${siblingConvId.slice(0, 8)}...: ${String(err)}`);
47062
+ }
47019
47063
  }
47064
+ console.log(`[SecureChannel] _relaySyncToSiblings: relayed to ${relayed}/${this._sessions.size - 1} siblings`);
47020
47065
  }
47021
47066
  /**
47022
47067
  * Send stored message history to a newly-activated session.
@@ -47253,6 +47298,7 @@ ${messageText}`;
47253
47298
  const PAGE_SIZE = 200;
47254
47299
  let since = this._persisted.lastMessageTimestamp;
47255
47300
  let totalProcessed = 0;
47301
+ let totalSkipped = 0;
47256
47302
  try {
47257
47303
  for (let page = 0; page < MAX_PAGES; page++) {
47258
47304
  const url = `${this.config.apiUrl}/api/v1/devices/${this._deviceId}/messages?since=${encodeURIComponent(since)}&limit=${PAGE_SIZE}`;
@@ -47262,15 +47308,24 @@ ${messageText}`;
47262
47308
  if (!res.ok) break;
47263
47309
  const messages = await res.json();
47264
47310
  if (messages.length === 0) break;
47311
+ console.log(`[SecureChannel] Sync page ${page}: ${messages.length} messages since ${since}`);
47265
47312
  for (const msg of messages) {
47266
47313
  if (msg.sender_device_id === this._deviceId) continue;
47267
47314
  if (this._syncMessageIds.has(msg.id)) continue;
47268
47315
  this._syncMessageIds.add(msg.id);
47316
+ if (this._recentlyHandledIds.has(msg.id)) {
47317
+ this._persisted.lastMessageTimestamp = msg.created_at;
47318
+ since = msg.created_at;
47319
+ totalSkipped++;
47320
+ continue;
47321
+ }
47269
47322
  const session = this._sessions.get(msg.conversation_id);
47270
47323
  if (!session) {
47271
47324
  console.warn(
47272
47325
  `[SecureChannel] No session for conversation ${msg.conversation_id} during sync, skipping`
47273
47326
  );
47327
+ this._persisted.lastMessageTimestamp = msg.created_at;
47328
+ since = msg.created_at;
47274
47329
  continue;
47275
47330
  }
47276
47331
  try {
@@ -47304,9 +47359,6 @@ ${messageText}`;
47304
47359
  topicId
47305
47360
  };
47306
47361
  this.emit("message", messageText, metadata);
47307
- Promise.resolve(this.config.onMessage?.(messageText, metadata)).catch((err) => {
47308
- console.error("[SecureChannel] onMessage callback error:", err);
47309
- });
47310
47362
  }
47311
47363
  this._persisted.lastMessageTimestamp = msg.created_at;
47312
47364
  since = msg.created_at;
@@ -47323,10 +47375,15 @@ ${messageText}`;
47323
47375
  await this._persistState();
47324
47376
  if (messages.length < PAGE_SIZE) break;
47325
47377
  }
47326
- if (totalProcessed > 0) {
47327
- console.log(`[SecureChannel] Synced ${totalProcessed} missed messages`);
47378
+ if (totalProcessed > 0 || totalSkipped > 0) {
47379
+ console.log(`[SecureChannel] Sync complete: ${totalProcessed} processed, ${totalSkipped} skipped (already handled via WS)`);
47380
+ }
47381
+ } catch (outerErr) {
47382
+ console.warn(`[SecureChannel] Sync interrupted: ${String(outerErr)}`);
47383
+ try {
47384
+ await this._persistState();
47385
+ } catch {
47328
47386
  }
47329
- } catch {
47330
47387
  }
47331
47388
  this._syncMessageIds = null;
47332
47389
  }