@agentvault/agentvault 0.9.5 → 0.9.6

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
@@ -6,7 +6,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "node:fs/promises";
6
6
  import { join as join2 } from "node:path";
7
7
  import { readFile as readFile2 } from "node:fs/promises";
8
8
 
9
- // ../../node_modules/libsodium-sumo/dist/modules-sumo-esm/libsodium-sumo.mjs
9
+ // ../../../../../node_modules/libsodium-sumo/dist/modules-sumo-esm/libsodium-sumo.mjs
10
10
  var __filename;
11
11
  var __dirname;
12
12
  try {
@@ -214,7 +214,7 @@ Module.ready = new Promise(function(resolve2, reject) {
214
214
  }, Module: function(binary) {
215
215
  }, Instance: function(module2, info) {
216
216
  this.exports = // EMSCRIPTEN_START_ASM
217
- (function instantiate(ea2) {
217
+ function instantiate(ea2) {
218
218
  var a2;
219
219
  var b2 = new Uint8Array(123);
220
220
  for (var c2 = 25; c2 >= 0; --c2) {
@@ -40009,7 +40009,7 @@ Module.ready = new Promise(function(resolve2, reject) {
40009
40009
  } } }), f: yi, g: ma2, h: Ba2, i: ma2, j: ka2, k: Le2, l: Je2, m: zg, n: yg, o: xg, p: wg, q: ka2, r: Ba2, s: ka2, t: ka2, u: Le2, v: ra2, w: vg, x: ug, y: tg, z: sg, A: Ba2, B: rg, C: qg, D: pg, E: ng, F: mg, G: lg, H: kg, I: jg, J: ka2, K: Ce2, L: Ba2, M: ma2, N: Ta2, O: ra2, P: ka2, Q: Oa2, R: Ba2, S: ma2, T: Ta2, U: ra2, V: ig, W: hg, X: gg, Y: fg, Z: ka2, _: Ma2, $: Ba2, aa: ma2, ba: Ta2, ca: ra2, da: ka2, ea: ka2, fa: Kg, ga: wd, ha: vd, ia: ra2, ja: ka2, ka: ka2, la: Cb, ma: ra2, na: Xa2, oa: eg, pa: qb, qa: dg, ra: cg, sa: ua2, ta: ka2, ua: Dc, va: ra2, wa: Va2, xa: ud, ya: Ya2, za: bg, Aa: ag, Ba: ka2, Ca: ka2, Da: Dc, Ea: ra2, Fa: ze2, Ga: ud, Ha: Ng, Ia: wd, Ja: vd, Ka: ka2, La: ka2, Ma: ka2, Na: ka2, Oa: Ma2, Pa: ka2, Qa: ma2, Ra: ma2, Sa: Ta2, Ta: dh2, Ua: ch, Va: bh, Wa: ah, Xa: Lb, Ya: Kb, Za: td, _a: sd, $a: rd, ab: $f, bb: _f, cb: Zf, db: qd, eb: Yf, fb: pd, gb: Xf, hb: Wf, ib: Uf, jb: Md, kb: tc, lb: nb, mb, nb: Lb, ob: Kb, pb: td, qb: sd, rb: ka2, sb: ka2, tb: ka2, ub: ka2, vb: Ma2, wb: ka2, xb: ma2, yb: ma2, zb: Ta2, Ab: Aa2, Bb: ka2, Cb: ma2, Db: ka2, Eb: ma2, Fb: Sa2, Gb: ka2, Hb: ma2, Ib: ka2, Jb: ma2, Kb: vb, Lb: ua2, Mb: ma2, Nb: ka2, Ob: ma2, Pb: ub, Qb: ua2, Rb: ma2, Sb: ka2, Tb: ma2, Ub: tb, Vb: ua2, Wb: ma2, Xb: ka2, Yb: ma2, Zb: ma2, _b: ua2, $b: ka2, ac: ma2, bc: ua2, cc: ka2, dc: Nd, ec: pe2, fc: od, gc: fh, hc: nd, ic: eh, jc: ra2, kc: ma2, lc: ua2, mc: ka2, nc: ma2, oc: ua2, pc: ka2, qc: ma2, rc: ma2, sc: pe2, tc: ra2, uc: od, vc: Tf, wc: Ja2, xc: xh, yc: nd, zc: Ia2, Ac: ua2, Bc: md, Cc: Lg, Dc: ka2, Ec: Ag, Fc: Ub, Gc: Sf, Hc: Ua2, Ic: Rf, Jc: ua2, Kc: Cb, Lc: Za2, Mc: ic, Nc: Ca2, Oc: md, Pc: ma2, Qc: ua2, Rc: Oa2, Sc: ka2, Tc: ld, Uc: Nd, Vc: ma2, Wc: ua2, Xc: Oa2, Yc: ka2, Zc: ld, _c: ra2, $c: Gh, ad: Fh, bd: Eh, cd: Dh, dd: ra2, ed: Ch, fd: ka2, gd: Ba2, hd: Bh, id: Cb, jd: ze2, kd: hi, ld: gi, md: fi, nd: ei, od: di, pd: ua2, qd: Ba2, rd: ci, sd: Dc, td: Gg, ud: nb, vd: Fg, wd: Eg, xd: ka2, yd: ka2, zd: ka2, Ad: ka2, Bd: Dg, Cd: Rc, Dd: ma2, Ed: ka2, Fd: kd, Gd: jd, Hd: Sg, Id: id, Jd: Rg, Kd: Qg, Ld: ra2, Md: kd, Nd: jd, Od: Ga2, Pd: id, Qd: Fa2, Rd: ma2, Sd: ka2, Td: Rc, Ud: ra2, Vd: Db, Wd: ma2, Xd: wa2, Yd: Ba2, Zd: wa2, _d: ma2, $d: yc, ae: wh, be: Vb, ce: wa2, de: xc, ee: wc, fe: vc, ge: me2, he: vh, ie: uh, je: Oa2, ke: th, le: Pf, me: Of, ne: Nf, oe: Mf, pe: Lf, qe: fb, re: ma2, se: wa2, te: Ba2, ue: wa2, ve: ma2, we: yc, xe: fe2, ye: Db, ze: wa2, Ae: xc, Be: wc, Ce: fb, De: ee2, Ee: Vb, Fe: de2, Ge: vc, He: uc, Ie: Kf, Je: hd, Ke: Jf, Le: Db, Me: fb, Ne: fb, Oe: ma2, Pe: wa2, Qe: Ba2, Re: wa2, Se: ma2, Te: yc, Ue: fe2, Ve: Db, We: wa2, Xe: xc, Ye: wc, Ze: fb, _e: ee2, $e: Vb, af: de2, bf: vc, cf: uc, df: Hf, ef: hd, ff: Gf, gf: Ff, hf: Ef, jf: sh, kf: Jg, lf: Ig, mf: Hg, nf: ka2, of: ka2, pf: Ea2, qf: wb, rf: ka2, sf: ka2, tf: ka2, uf: Ma2, vf: ka2, wf: ma2, xf: ma2, yf: Ta2, zf: Mg, Af: Lb, Bf: Kb, Cf: ra2, Df: rd, Ef: Df, Ff: qd, Gf: pd, Hf: Lb, If: Kb, Jf: ka2, Kf: Ma2, Lf: ka2, Mf: ma2, Nf: ma2, Of: Ta2, Pf: ra2, Qf: ra2, Rf: Mh, Sf: Lh, Tf: Kh, Uf: Cf, Vf: Bf, Wf: Jh, Xf: Ih, Yf: Ma2, Zf: ka2, _f: Hh, $f: Ba2, ag: Db, bg: fb, cg: Vb, dg: Oa2, eg: ma2, fg: Tg, gg: gd, hg: Je2, ig: Oa2, jg: ma2, kg: gd, lg: Cb, mg: ua2, ng: ka2, og: ka2, pg: ua2, qg: Wd, rg: lh, sg: kh, tg: jh, ug: fd, vg: ed, wg: dd, xg: cd, yg: ih, zg: ic, Ag: hh, Bg: gh, Cg: Cb, Dg: ua2, Eg: ka2, Fg: ka2, Gg: ua2, Hg: Wd, Ig: nh, Jg: mh, Kg: Vd, Lg: ic, Mg: Ud, Ng: Td, Og: Yd, Pg: Xd, Qg: ph, Rg: oh, Sg: cd, Tg: ed, Ug: dd, Vg: fd, Wg: ka2, Xg: Oa2, Yg: wa2, Zg: ka2, _g: Ce2, $g: wa2, ah: zf, bh: yf, ch: xf, dh: wf, eh: vf, fh: uf, gh: ra2, hh: ra2, ih: ka2, jh: Ma2, kh: wa2, lh: qh, mh: bd, nh: ad, oh: ra2, ph: ka2, qh: Oa2, rh: wa2, sh: tf, th: sf, uh: rf, vh: ra2, wh: bd, xh: qf, yh: ad, zh: ka2, Ah: Ma2, Bh: wa2, Ch: ra2, Dh: ma2, Eh: ka2, Fh: ua2, Gh: db, Hh: kb, Ih: xd, Jh: oi, Kh: ni, Lh: Ae2, Mh: mi, Nh: za2, Oh: li, Ph: ka2, Qh: ki, Rh: pf, Sh: Ah, Th: zh, Uh: yh, Vh: Bc, Wh: Ac, Xh: ti, Yh: ji, Zh: ii, _h: Cg, $h: Bg, ai: fb, bi: Ba2, ci: tc, di: nb, ei: rh, fi: $c, gi: of, hi: nf, ii: mf, ji: _c, ki: lf, li: Yc, mi: kf, ni: ka2, oi: ka2, pi: ka2, qi: ka2, ri: Ma2, si: ma2, ti: Ta2, ui: jf, vi: hf, wi: Md, xi: bi, yi: ai, zi: $h, Ai: _h, Bi: Zh, Ci: ye2, Di: xe2, Ei: we2, Fi: ve2, Gi: ue2, Hi: te2, Ii: se2, Ji: re2, Ki: ka2, Li: ua2, Mi: ka2, Ni: ua2, Oi: ka2, Pi: Yh, Qi: Xh, Ri: Wh, Si: Vh, Ti: Uh, Ui: Th, Vi: Sh, Wi: Rh, Xi: Qh, Yi: Ph, Zi: Oh, _i: re2, $i: Nh, aj: ka2, bj: ua2, cj: ua2, dj: ka2, ej: gf, fj: ma2, gj: wa2, hj: Ba2, ij: wa2, jj: ka2, kj: $g, lj: _g, mj: Zg, nj: wa2, oj: Ed, pj: wa2, qj: Yg, rj: Ed, sj: me2, tj: uc, uj: ff, vj: ef, wj: df, xj: cf, yj: Xg, zj: Wg, Aj: Vg, Bj: Ug, Cj: ka2, Dj: ka2, Ej: Pg, Fj: Og, Gj: ka2, Hj: ka2, Ij: $c, Jj: bf, Kj: _c, Lj: Yc, Mj: ka2, Nj: Ma2, Oj: ma2, Pj: Ta2, Qj: ma2, Rj: ma2, Sj: af, Tj: $e2, Uj: _e2, Vj: ka2, Wj: Oa2, Xj: wa2, Yj: ra2, Zj: Ze2, _j: Ye2, $j: ka2, ak: Oa2, bk: wa2, ck: ra2, dk: ka2, ek: Ma2, fk: wa2, gk: Xe2, hk: We2, ik: Ve2, jk: ra2, kk: Da2, lk: ta2 };
40010
40010
  }
40011
40011
  return da2(ea2);
40012
- })(info);
40012
+ }(info);
40013
40013
  }, instantiate: function(binary, info) {
40014
40014
  return { then: function(ok) {
40015
40015
  var module2 = new WebAssembly2.Module(binary);
@@ -42011,7 +42011,7 @@ Module.ready = new Promise(function(resolve2, reject) {
42011
42011
  });
42012
42012
  var libsodium_sumo_default = Module;
42013
42013
 
42014
- // ../../node_modules/libsodium-wrappers-sumo/dist/modules-sumo-esm/libsodium-wrappers.mjs
42014
+ // ../../../../../node_modules/libsodium-wrappers-sumo/dist/modules-sumo-esm/libsodium-wrappers.mjs
42015
42015
  var a;
42016
42016
  var r = {};
42017
42017
  var t = libsodium_sumo_default.ready.then(function() {
@@ -44611,7 +44611,7 @@ var libsodium_wrappers_default = r;
44611
44611
  // src/channel.ts
44612
44612
  import WebSocket from "ws";
44613
44613
 
44614
- // ../crypto/dist/keys.js
44614
+ // ../../../../../packages/crypto/dist/keys.js
44615
44615
  async function generateIdentityKeypair() {
44616
44616
  await libsodium_wrappers_default.ready;
44617
44617
  const kp = libsodium_wrappers_default.crypto_sign_keypair();
@@ -44638,7 +44638,7 @@ function createProofOfPossession(privateKey, publicKey) {
44638
44638
  return libsodium_wrappers_default.crypto_sign_detached(publicKey, privateKey);
44639
44639
  }
44640
44640
 
44641
- // ../crypto/dist/x3dh.js
44641
+ // ../../../../../packages/crypto/dist/x3dh.js
44642
44642
  function ed25519PrivateToX25519(edPrivate) {
44643
44643
  return libsodium_wrappers_default.crypto_sign_ed25519_sk_to_curve25519(edPrivate);
44644
44644
  }
@@ -44660,7 +44660,7 @@ function performX3DH(params) {
44660
44660
  return libsodium_wrappers_default.crypto_generichash(32, combined);
44661
44661
  }
44662
44662
 
44663
- // ../crypto/dist/ratchet.js
44663
+ // ../../../../../packages/crypto/dist/ratchet.js
44664
44664
  var MAX_SKIP = 100;
44665
44665
  var CHAIN_KEY_SEED = new Uint8Array([1]);
44666
44666
  var MSG_KEY_SEED = new Uint8Array([2]);
@@ -44921,7 +44921,7 @@ var DoubleRatchet = class _DoubleRatchet {
44921
44921
  }
44922
44922
  };
44923
44923
 
44924
- // ../crypto/dist/file-crypto.js
44924
+ // ../../../../../packages/crypto/dist/file-crypto.js
44925
44925
  function encryptFile(plainData) {
44926
44926
  const fileKey = libsodium_wrappers_default.randombytes_buf(libsodium_wrappers_default.crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
44927
44927
  const fileNonce = libsodium_wrappers_default.randombytes_buf(libsodium_wrappers_default.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
@@ -44954,7 +44954,7 @@ function computeFileDigest(data) {
44954
44954
  return libsodium_wrappers_default.to_hex(digestBytes);
44955
44955
  }
44956
44956
 
44957
- // ../crypto/dist/scan-engine.js
44957
+ // ../../../../../packages/crypto/dist/scan-engine.js
44958
44958
  var BUILTIN_PATTERNS = {
44959
44959
  pii_ssn: [/\b\d{3}-\d{2}-\d{4}\b/g, /\b\d{9}\b/g],
44960
44960
  pii_credit_card: [
@@ -45106,7 +45106,7 @@ var ScanEngine = class {
45106
45106
  }
45107
45107
  };
45108
45108
 
45109
- // ../crypto/dist/transport.js
45109
+ // ../../../../../packages/crypto/dist/transport.js
45110
45110
  function hexToBytes(hex) {
45111
45111
  return libsodium_wrappers_default.from_hex(hex);
45112
45112
  }
@@ -45292,12 +45292,12 @@ 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();
45297
45295
  /** Queued A2A messages for responder channels not yet activated (no first initiator message received). */
45298
45296
  _a2aPendingQueue = {};
45299
45297
  _scanEngine = null;
45300
45298
  _scanRuleSetVersion = 0;
45299
+ /** Topic ID from the most recent inbound message — used as fallback for replies. */
45300
+ _lastIncomingTopicId;
45301
45301
  // Liveness detection: server sends app-level {"event":"ping"} every 30s.
45302
45302
  // We check every 30s; if no data received in 90s (3 missed pings), connection is dead.
45303
45303
  static PING_INTERVAL_MS = 3e4;
@@ -45408,7 +45408,7 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
45408
45408
  if (this._sessions.size === 0) {
45409
45409
  throw new Error("No active sessions");
45410
45410
  }
45411
- const topicId = options?.topicId ?? this._persisted?.defaultTopicId;
45411
+ const topicId = options?.topicId ?? this._lastIncomingTopicId ?? this._persisted?.defaultTopicId;
45412
45412
  const messageType = options?.messageType ?? "text";
45413
45413
  const priority = options?.priority ?? "normal";
45414
45414
  const parentSpanId = options?.parentSpanId;
@@ -46399,20 +46399,6 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46399
46399
  this.emit("error", openErr);
46400
46400
  }
46401
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
- });
46416
46402
  ws.on("message", async (raw) => {
46417
46403
  this._lastServerMessage = Date.now();
46418
46404
  this._lastWakeTick = Date.now();
@@ -46432,10 +46418,8 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46432
46418
  return;
46433
46419
  }
46434
46420
  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) ?? "?"}`);
46436
46421
  try {
46437
46422
  await this._handleIncomingMessage(data.data);
46438
- console.log(`[SecureChannel] \u2190 Direct message processed OK: msg=${data.data?.message_id?.slice(0, 8) ?? "?"}`);
46439
46423
  } catch (msgErr) {
46440
46424
  console.error(
46441
46425
  `[SecureChannel] Message handler failed for conv ${data.data?.conversation_id?.slice(0, 8) ?? "?"}...:`,
@@ -46767,9 +46751,7 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46767
46751
  this.emit("error", err);
46768
46752
  }
46769
46753
  });
46770
- ws.on("close", (code, reason) => {
46771
- const reasonStr = reason?.toString() || "";
46772
- console.log(`[SecureChannel] WS close handler: code=${code} reason=${JSON.stringify(reasonStr)}`);
46754
+ ws.on("close", () => {
46773
46755
  this._stopPing();
46774
46756
  this._stopWakeDetector();
46775
46757
  this._stopPendingPoll();
@@ -46791,11 +46773,6 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46791
46773
  if (this._syncMessageIds?.has(msgData.message_id)) {
46792
46774
  return;
46793
46775
  }
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
- }
46799
46776
  const convId = msgData.conversation_id;
46800
46777
  const session = this._sessions.get(convId);
46801
46778
  if (!session) {
@@ -46808,14 +46785,7 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46808
46785
  header_blob: msgData.header_blob,
46809
46786
  ciphertext: msgData.ciphertext
46810
46787
  });
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)}...`);
46788
+ const plaintext = session.ratchet.decrypt(encrypted);
46819
46789
  this._sendAck(msgData.message_id);
46820
46790
  if (!session.activated) {
46821
46791
  session.activated = true;
@@ -46850,6 +46820,7 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
46850
46820
  }
46851
46821
  if (messageType === "message") {
46852
46822
  const topicId = msgData.topic_id;
46823
+ this._lastIncomingTopicId = topicId;
46853
46824
  let attachData;
46854
46825
  if (attachmentInfo) {
46855
46826
  try {
@@ -46908,13 +46879,7 @@ ${messageText}`;
46908
46879
  Promise.resolve(this.config.onMessage?.(emitText, metadata)).catch((err) => {
46909
46880
  console.error("[SecureChannel] onMessage callback error:", err);
46910
46881
  });
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
- }
46882
+ await this._relaySyncToSiblings(convId, session.ownerDeviceId, messageText, topicId);
46918
46883
  }
46919
46884
  if (this._persisted) {
46920
46885
  this._persisted.lastMessageTimestamp = msgData.created_at;
@@ -47039,29 +47004,22 @@ ${messageText}`;
47039
47004
  ts: (/* @__PURE__ */ new Date()).toISOString(),
47040
47005
  topicId
47041
47006
  });
47042
- let relayed = 0;
47043
47007
  for (const [siblingConvId, siblingSession] of this._sessions) {
47044
47008
  if (siblingConvId === sourceConvId) continue;
47045
47009
  if (!siblingSession.activated) continue;
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
- }
47010
+ const syncEncrypted = siblingSession.ratchet.encrypt(syncPayload);
47011
+ const syncTransport = encryptedMessageToTransport(syncEncrypted);
47012
+ this._ws.send(
47013
+ JSON.stringify({
47014
+ event: "message",
47015
+ data: {
47016
+ conversation_id: siblingConvId,
47017
+ header_blob: syncTransport.header_blob,
47018
+ ciphertext: syncTransport.ciphertext
47019
+ }
47020
+ })
47021
+ );
47063
47022
  }
47064
- console.log(`[SecureChannel] _relaySyncToSiblings: relayed to ${relayed}/${this._sessions.size - 1} siblings`);
47065
47023
  }
47066
47024
  /**
47067
47025
  * Send stored message history to a newly-activated session.
@@ -47163,12 +47121,52 @@ ${messageText}`;
47163
47121
  );
47164
47122
  return;
47165
47123
  }
47166
- const session = this._sessions.get(convId);
47124
+ let session = this._sessions.get(convId);
47167
47125
  if (!session) {
47168
47126
  console.warn(
47169
- `[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., skipping`
47127
+ `[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., fetching room data`
47170
47128
  );
47171
- return;
47129
+ try {
47130
+ const roomRes = await fetch(
47131
+ `${this.config.apiUrl}/api/v1/rooms/${msgData.room_id}`,
47132
+ {
47133
+ headers: {
47134
+ Authorization: `Bearer ${this._persisted.deviceJwt}`
47135
+ }
47136
+ }
47137
+ );
47138
+ if (roomRes.ok) {
47139
+ const roomData = await roomRes.json();
47140
+ await this.joinRoom({
47141
+ roomId: roomData.id,
47142
+ name: roomData.name,
47143
+ members: (roomData.members || []).map((m2) => ({
47144
+ deviceId: m2.device_id,
47145
+ entityType: m2.entity_type,
47146
+ displayName: m2.display_name,
47147
+ identityPublicKey: m2.identity_public_key,
47148
+ ephemeralPublicKey: m2.ephemeral_public_key
47149
+ })),
47150
+ conversations: (roomData.conversations || []).map((c2) => ({
47151
+ id: c2.id,
47152
+ participantA: c2.participant_a,
47153
+ participantB: c2.participant_b
47154
+ }))
47155
+ });
47156
+ session = this._sessions.get(convId);
47157
+ }
47158
+ } catch (fetchErr) {
47159
+ console.error(
47160
+ `[SecureChannel] Failed to fetch room data for ${msgData.room_id}:`,
47161
+ fetchErr
47162
+ );
47163
+ }
47164
+ if (!session) {
47165
+ console.warn(
47166
+ `[SecureChannel] Still no session for room conv ${convId.slice(0, 8)}... after refresh, skipping`
47167
+ );
47168
+ return;
47169
+ }
47172
47170
  }
47173
47171
  const encrypted = transportToEncryptedMessage({
47174
47172
  header_blob: msgData.header_blob,
@@ -47298,7 +47296,6 @@ ${messageText}`;
47298
47296
  const PAGE_SIZE = 200;
47299
47297
  let since = this._persisted.lastMessageTimestamp;
47300
47298
  let totalProcessed = 0;
47301
- let totalSkipped = 0;
47302
47299
  try {
47303
47300
  for (let page = 0; page < MAX_PAGES; page++) {
47304
47301
  const url = `${this.config.apiUrl}/api/v1/devices/${this._deviceId}/messages?since=${encodeURIComponent(since)}&limit=${PAGE_SIZE}`;
@@ -47308,24 +47305,15 @@ ${messageText}`;
47308
47305
  if (!res.ok) break;
47309
47306
  const messages = await res.json();
47310
47307
  if (messages.length === 0) break;
47311
- console.log(`[SecureChannel] Sync page ${page}: ${messages.length} messages since ${since}`);
47312
47308
  for (const msg of messages) {
47313
47309
  if (msg.sender_device_id === this._deviceId) continue;
47314
47310
  if (this._syncMessageIds.has(msg.id)) continue;
47315
47311
  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
- }
47322
47312
  const session = this._sessions.get(msg.conversation_id);
47323
47313
  if (!session) {
47324
47314
  console.warn(
47325
47315
  `[SecureChannel] No session for conversation ${msg.conversation_id} during sync, skipping`
47326
47316
  );
47327
- this._persisted.lastMessageTimestamp = msg.created_at;
47328
- since = msg.created_at;
47329
47317
  continue;
47330
47318
  }
47331
47319
  try {
@@ -47359,6 +47347,9 @@ ${messageText}`;
47359
47347
  topicId
47360
47348
  };
47361
47349
  this.emit("message", messageText, metadata);
47350
+ Promise.resolve(this.config.onMessage?.(messageText, metadata)).catch((err) => {
47351
+ console.error("[SecureChannel] onMessage callback error:", err);
47352
+ });
47362
47353
  }
47363
47354
  this._persisted.lastMessageTimestamp = msg.created_at;
47364
47355
  since = msg.created_at;
@@ -47375,15 +47366,10 @@ ${messageText}`;
47375
47366
  await this._persistState();
47376
47367
  if (messages.length < PAGE_SIZE) break;
47377
47368
  }
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 {
47369
+ if (totalProcessed > 0) {
47370
+ console.log(`[SecureChannel] Synced ${totalProcessed} missed messages`);
47386
47371
  }
47372
+ } catch {
47387
47373
  }
47388
47374
  this._syncMessageIds = null;
47389
47375
  }