@agentvault/agentvault 0.19.58 → 0.19.59

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 (66) hide show
  1. package/dist/_cp.d.ts +10 -0
  2. package/dist/_cp.d.ts.map +1 -0
  3. package/dist/account-config.d.ts +20 -0
  4. package/dist/account-config.d.ts.map +1 -0
  5. package/dist/channel.d.ts +389 -0
  6. package/dist/channel.d.ts.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +42 -415
  10. package/dist/cli.js.map +2 -2
  11. package/dist/create-agent.d.ts +28 -0
  12. package/dist/create-agent.d.ts.map +1 -0
  13. package/dist/credential-store.d.ts +62 -0
  14. package/dist/credential-store.d.ts.map +1 -0
  15. package/dist/crypto-helpers.d.ts +2 -0
  16. package/dist/crypto-helpers.d.ts.map +1 -0
  17. package/dist/doctor.d.ts +41 -0
  18. package/dist/doctor.d.ts.map +1 -0
  19. package/dist/fetch-interceptor.d.ts +32 -0
  20. package/dist/fetch-interceptor.d.ts.map +1 -0
  21. package/dist/gateway-send.d.ts +98 -0
  22. package/dist/gateway-send.d.ts.map +1 -0
  23. package/dist/http-handlers.d.ts +53 -0
  24. package/dist/http-handlers.d.ts.map +1 -0
  25. package/dist/index.d.ts +27 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +42 -415
  28. package/dist/index.js.map +2 -2
  29. package/dist/mcp-handlers.d.ts +26 -0
  30. package/dist/mcp-handlers.d.ts.map +1 -0
  31. package/dist/mcp-proxy-helpers.d.ts +9 -0
  32. package/dist/mcp-proxy-helpers.d.ts.map +1 -0
  33. package/dist/mcp-server.d.ts +91 -0
  34. package/dist/mcp-server.d.ts.map +1 -0
  35. package/dist/mls-state.d.ts +16 -0
  36. package/dist/mls-state.d.ts.map +1 -0
  37. package/dist/openclaw-compat.d.ts +33 -0
  38. package/dist/openclaw-compat.d.ts.map +1 -0
  39. package/dist/openclaw-entry.d.ts +32 -0
  40. package/dist/openclaw-entry.d.ts.map +1 -0
  41. package/dist/openclaw-plugin.d.ts +102 -0
  42. package/dist/openclaw-plugin.d.ts.map +1 -0
  43. package/dist/openclaw-types.d.ts +186 -0
  44. package/dist/openclaw-types.d.ts.map +1 -0
  45. package/dist/policy-enforcer.d.ts +78 -0
  46. package/dist/policy-enforcer.d.ts.map +1 -0
  47. package/dist/setup.d.ts +27 -0
  48. package/dist/setup.d.ts.map +1 -0
  49. package/dist/skill-invoker.d.ts +30 -0
  50. package/dist/skill-invoker.d.ts.map +1 -0
  51. package/dist/skill-manifest.d.ts +30 -0
  52. package/dist/skill-manifest.d.ts.map +1 -0
  53. package/dist/skill-telemetry.d.ts +36 -0
  54. package/dist/skill-telemetry.d.ts.map +1 -0
  55. package/dist/skills-publish.d.ts +8 -0
  56. package/dist/skills-publish.d.ts.map +1 -0
  57. package/dist/state.d.ts +32 -0
  58. package/dist/state.d.ts.map +1 -0
  59. package/dist/transport.d.ts +24 -0
  60. package/dist/transport.d.ts.map +1 -0
  61. package/dist/types.d.ts +421 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/workspace-handlers.d.ts +62 -0
  64. package/dist/workspace-handlers.d.ts.map +1 -0
  65. package/openclaw.plugin.json +1 -1
  66. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -62702,6 +62702,24 @@ var init_channel = __esm({
62702
62702
  if (this._persisted.seenA2AMessageIds) {
62703
62703
  this._a2aSeenMessageIds = new Set(this._persisted.seenA2AMessageIds.slice(-_SecureChannel.A2A_SEEN_MAX));
62704
62704
  }
62705
+ if (this._persisted?.rooms) {
62706
+ const roomConvIds = /* @__PURE__ */ new Set();
62707
+ for (const room of Object.values(this._persisted.rooms)) {
62708
+ for (const cid of room.conversationIds || []) {
62709
+ roomConvIds.add(cid);
62710
+ }
62711
+ }
62712
+ let cleanedCount = 0;
62713
+ for (const cid of roomConvIds) {
62714
+ if (this._persisted.sessions[cid]) {
62715
+ delete this._persisted.sessions[cid];
62716
+ cleanedCount++;
62717
+ }
62718
+ }
62719
+ if (cleanedCount > 0) {
62720
+ console.log(`[SecureChannel] Cleaned ${cleanedCount} stale DR room sessions`);
62721
+ }
62722
+ }
62705
62723
  for (const [convId, sessionData] of Object.entries(
62706
62724
  this._persisted.sessions
62707
62725
  )) {
@@ -63074,89 +63092,21 @@ var init_channel = __esm({
63074
63092
  }
63075
63093
  // --- Multi-agent room methods ---
63076
63094
  /**
63077
- * Join a room by performing X3DH key exchange with each member
63078
- * for the pairwise conversations involving this device.
63095
+ * Join a room by collecting pairwise conversation IDs involving this device.
63096
+ * Encryption is handled by MLS group operations, not per-member DR sessions.
63079
63097
  */
63080
63098
  async joinRoom(roomData) {
63081
63099
  if (!this._persisted) {
63082
63100
  throw new Error("Channel not initialized");
63083
63101
  }
63084
63102
  await libsodium_wrappers_default.ready;
63085
- if (roomData.forceRekey) {
63086
- let cleared = 0;
63087
- const existingRoom = this._persisted.rooms?.[roomData.roomId];
63088
- if (existingRoom) {
63089
- for (const convId of existingRoom.conversationIds) {
63090
- if (this._sessions.has(convId)) {
63091
- this._sessions.delete(convId);
63092
- cleared++;
63093
- }
63094
- delete this._persisted.sessions[convId];
63095
- }
63096
- }
63097
- if (this._persisted) {
63098
- this._persisted.lastMessageTimestamp = (/* @__PURE__ */ new Date()).toISOString();
63099
- }
63100
- console.log(
63101
- `[SecureChannel] Force rekey: cleared ${cleared} sessions for room ${roomData.roomId.slice(0, 8)}...`
63102
- );
63103
- }
63104
- const identity = this._persisted.identityKeypair;
63105
- const ephemeral = this._persisted.ephemeralKeypair;
63106
63103
  const myDeviceId = this._deviceId;
63107
63104
  const conversationIds = [];
63108
63105
  for (const conv of roomData.conversations) {
63109
63106
  if (conv.participantA !== myDeviceId && conv.participantB !== myDeviceId) {
63110
63107
  continue;
63111
63108
  }
63112
- if (this._sessions.has(conv.id)) {
63113
- conversationIds.push(conv.id);
63114
- continue;
63115
- }
63116
- const otherDeviceId = conv.participantA === myDeviceId ? conv.participantB : conv.participantA;
63117
- const otherMember = roomData.members.find((m2) => m2.deviceId === otherDeviceId);
63118
- if (!otherMember?.identityPublicKey) {
63119
- console.warn(
63120
- `[SecureChannel] No public key for member ${otherDeviceId.slice(0, 8)}..., skipping`
63121
- );
63122
- continue;
63123
- }
63124
- const isInitiator = myDeviceId < otherDeviceId;
63125
- const theirEphKey = otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey;
63126
- const sharedSecret = performX3DH({
63127
- myIdentityPrivate: hexToBytes(identity.privateKey),
63128
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
63129
- theirIdentityPublic: hexToBytes(otherMember.identityPublicKey),
63130
- theirEphemeralPublic: hexToBytes(theirEphKey),
63131
- isInitiator
63132
- });
63133
- const peerIdentityPub = hexToBytes(otherMember.identityPublicKey);
63134
- const ratchet = isInitiator ? DoubleRatchet.initSender(sharedSecret, {
63135
- publicKey: hexToBytes(identity.publicKey),
63136
- privateKey: hexToBytes(identity.privateKey),
63137
- keyType: "ed25519"
63138
- }, peerIdentityPub) : DoubleRatchet.initReceiver(sharedSecret, {
63139
- publicKey: hexToBytes(identity.publicKey),
63140
- privateKey: hexToBytes(identity.privateKey),
63141
- keyType: "ed25519"
63142
- }, peerIdentityPub);
63143
- this._sessions.set(conv.id, {
63144
- ownerDeviceId: otherDeviceId,
63145
- ratchet,
63146
- activated: isInitiator,
63147
- // initiator can send immediately
63148
- epoch: 1
63149
- });
63150
- this._persisted.sessions[conv.id] = {
63151
- ownerDeviceId: otherDeviceId,
63152
- ratchetState: ratchet.serialize(),
63153
- activated: isInitiator,
63154
- epoch: 1
63155
- };
63156
63109
  conversationIds.push(conv.id);
63157
- console.log(
63158
- `[SecureChannel] Room session initialized: conv ${conv.id.slice(0, 8)}... with ${otherDeviceId.slice(0, 8)}... (initiator=${isInitiator})`
63159
- );
63160
63110
  }
63161
63111
  if (!this._persisted.rooms) {
63162
63112
  this._persisted.rooms = {};
@@ -63252,68 +63202,15 @@ var init_channel = __esm({
63252
63202
  }
63253
63203
  return;
63254
63204
  } catch (mlsErr) {
63255
- console.warn(`[SecureChannel] MLS encrypt failed for room ${roomId.slice(0, 8)}, falling through to legacy:`, mlsErr);
63256
- }
63257
- }
63258
- }
63259
- const recipients = [];
63260
- for (const convId of room.conversationIds) {
63261
- const session = this._sessions.get(convId);
63262
- if (!session) {
63263
- console.warn(`[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., skipping`);
63264
- continue;
63265
- }
63266
- const encrypted = session.ratchet.encrypt(plaintext);
63267
- const transport = encryptedMessageToTransport(encrypted);
63268
- recipients.push({
63269
- device_id: session.ownerDeviceId,
63270
- header_blob: transport.header_blob,
63271
- ciphertext: transport.ciphertext
63272
- });
63273
- }
63274
- if (recipients.length === 0) {
63275
- throw new Error("No active sessions in room");
63276
- }
63277
- await this._persistState();
63278
- if (this._state === "ready" && this._ws) {
63279
- this._ws.send(
63280
- JSON.stringify({
63281
- event: "room_message",
63282
- data: {
63283
- room_id: roomId,
63284
- recipients,
63285
- message_type: messageType,
63286
- priority: opts?.priority ?? "normal",
63287
- metadata: opts?.metadata
63288
- }
63289
- })
63290
- );
63291
- } else {
63292
- try {
63293
- const res = await fetch(
63294
- `${this.config.apiUrl}/api/v1/rooms/${roomId}/messages`,
63295
- {
63296
- method: "POST",
63297
- headers: {
63298
- "Content-Type": "application/json",
63299
- Authorization: `Bearer ${this._deviceJwt}`
63300
- },
63301
- body: JSON.stringify({
63302
- recipients,
63303
- message_type: messageType,
63304
- priority: opts?.priority ?? "normal",
63305
- metadata: opts?.metadata
63306
- })
63307
- }
63308
- );
63309
- if (!res.ok) {
63310
- const detail = await res.text();
63311
- throw new Error(`Room message failed (${res.status}): ${detail}`);
63205
+ throw new Error(
63206
+ `MLS encrypt failed for room ${roomId.slice(0, 8)}... \u2014 MLS group must be initialized before sending. Error: ${mlsErr}`
63207
+ );
63312
63208
  }
63313
- } catch (err) {
63314
- throw new Error(`Failed to send room message: ${err}`);
63315
63209
  }
63316
63210
  }
63211
+ throw new Error(
63212
+ `Room ${roomId.slice(0, 8)}... has no initialized MLS group. MLS initialization must complete before messages can be sent.`
63213
+ );
63317
63214
  }
63318
63215
  /**
63319
63216
  * Leave a room: remove sessions and persisted room state.
@@ -65473,250 +65370,8 @@ ${messageText}`;
65473
65370
  this.emit("error", err);
65474
65371
  }
65475
65372
  }
65476
- /**
65477
- * Send a resync_request for a room conversation if the cooldown has elapsed.
65478
- * Shared by all room ratchet failure paths to avoid code duplication.
65479
- */
65480
- _sendRoomResyncIfCooled(convId, reason, session) {
65481
- const RESYNC_COOLDOWN_MS = 5 * 60 * 1e3;
65482
- const lastResync = this._lastResyncRequest.get(convId) ?? 0;
65483
- if (Date.now() - lastResync > RESYNC_COOLDOWN_MS && this._ws && this._persisted) {
65484
- this._lastResyncRequest.set(convId, Date.now());
65485
- this._ws.send(
65486
- JSON.stringify({
65487
- event: "resync_request",
65488
- data: {
65489
- conversation_id: convId,
65490
- reason,
65491
- identity_public_key: this._persisted.identityKeypair.publicKey,
65492
- ephemeral_public_key: this._persisted.ephemeralKeypair.publicKey,
65493
- epoch: session?.epoch
65494
- }
65495
- })
65496
- );
65497
- console.log(
65498
- `[SecureChannel] Room resync requested for conv ${convId.slice(0, 8)} (${reason})`
65499
- );
65500
- }
65501
- }
65502
- /**
65503
- * Handle an incoming room message (pairwise path — used by sync replay and pairwise room fallback).
65504
- * Finds the pairwise conversation for the sender, decrypts, and emits a room_message event.
65505
- */
65506
- async _handleRoomMessage(msgData) {
65507
- if (msgData.sender_device_id === this._deviceId) return;
65508
- this._lastInboundRoomId = msgData.room_id;
65509
- const convId = msgData.conversation_id ?? this._findConversationForSender(msgData.sender_device_id, msgData.room_id);
65510
- if (!convId) {
65511
- console.warn(
65512
- `[SecureChannel] No conversation found for sender ${msgData.sender_device_id.slice(0, 8)}... in room ${msgData.room_id}`
65513
- );
65514
- return;
65515
- }
65516
- let session = this._sessions.get(convId);
65517
- if (!session) {
65518
- console.warn(
65519
- `[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., fetching room data`
65520
- );
65521
- try {
65522
- const roomRes = await fetch(
65523
- `${this.config.apiUrl}/api/v1/rooms/${msgData.room_id}`,
65524
- {
65525
- headers: {
65526
- Authorization: `Bearer ${this._persisted.deviceJwt}`
65527
- }
65528
- }
65529
- );
65530
- if (roomRes.ok) {
65531
- const roomData = await roomRes.json();
65532
- await this.joinRoom({
65533
- roomId: roomData.id,
65534
- name: roomData.name,
65535
- members: (roomData.members || []).map((m2) => ({
65536
- deviceId: m2.device_id,
65537
- entityType: m2.entity_type,
65538
- displayName: m2.display_name,
65539
- identityPublicKey: m2.identity_public_key,
65540
- ephemeralPublicKey: m2.ephemeral_public_key
65541
- })),
65542
- conversations: (roomData.conversations || []).map((c2) => ({
65543
- id: c2.id,
65544
- participantA: c2.participant_a,
65545
- participantB: c2.participant_b
65546
- }))
65547
- });
65548
- session = this._sessions.get(convId);
65549
- }
65550
- } catch (fetchErr) {
65551
- console.error(
65552
- `[SecureChannel] Failed to fetch room data for ${msgData.room_id}:`,
65553
- fetchErr
65554
- );
65555
- }
65556
- if (!session) {
65557
- console.warn(
65558
- `[SecureChannel] Still no session for room conv ${convId.slice(0, 8)}... after refresh, skipping`
65559
- );
65560
- return;
65561
- }
65562
- }
65563
- const encrypted = transportToEncryptedMessage({
65564
- header_blob: msgData.header_blob,
65565
- ciphertext: msgData.ciphertext
65566
- });
65567
- let plaintext;
65568
- const ratchetSnapshot = session.ratchet.serialize();
65569
- try {
65570
- plaintext = session.ratchet.decrypt(encrypted);
65571
- } catch (decryptErr) {
65572
- try {
65573
- session.ratchet = DoubleRatchet.deserialize(ratchetSnapshot);
65574
- } catch {
65575
- }
65576
- console.warn(
65577
- `[SecureChannel] Room decrypt failed for conv ${convId.slice(0, 8)}...: ${String(decryptErr)}, re-initializing ratchet`
65578
- );
65579
- try {
65580
- const roomEntry = this._persisted?.rooms ? Object.values(this._persisted.rooms).find(
65581
- (r2) => r2.conversationIds.includes(convId)
65582
- ) : null;
65583
- if (!roomEntry) throw new Error("Room not found for conversation");
65584
- const otherMember = roomEntry.members.find(
65585
- (m2) => m2.deviceId === msgData.sender_device_id
65586
- );
65587
- if (!otherMember?.identityPublicKey) throw new Error("No key for sender");
65588
- const isInitiator = this._deviceId < msgData.sender_device_id;
65589
- const identity = this._persisted.identityKeypair;
65590
- const ephemeral = this._persisted.ephemeralKeypair;
65591
- const sharedSecret = performX3DH({
65592
- myIdentityPrivate: hexToBytes(identity.privateKey),
65593
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
65594
- theirIdentityPublic: hexToBytes(otherMember.identityPublicKey),
65595
- theirEphemeralPublic: hexToBytes(
65596
- otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey
65597
- ),
65598
- isInitiator
65599
- });
65600
- const peerIdPub = hexToBytes(otherMember.identityPublicKey);
65601
- const newRatchet = isInitiator ? DoubleRatchet.initSender(sharedSecret, {
65602
- publicKey: hexToBytes(identity.publicKey),
65603
- privateKey: hexToBytes(identity.privateKey),
65604
- keyType: "ed25519"
65605
- }, peerIdPub) : DoubleRatchet.initReceiver(sharedSecret, {
65606
- publicKey: hexToBytes(identity.publicKey),
65607
- privateKey: hexToBytes(identity.privateKey),
65608
- keyType: "ed25519"
65609
- }, peerIdPub);
65610
- session.ratchet = newRatchet;
65611
- session.activated = false;
65612
- this._persisted.sessions[convId] = {
65613
- ownerDeviceId: session.ownerDeviceId,
65614
- ratchetState: newRatchet.serialize(),
65615
- activated: false
65616
- };
65617
- await this._persistState();
65618
- console.log(
65619
- `[SecureChannel] Room ratchet re-initialized for conv ${convId.slice(0, 8)}...`
65620
- );
65621
- const incomingMsgNum = encrypted.header.messageNumber;
65622
- if (incomingMsgNum <= 5) {
65623
- try {
65624
- plaintext = session.ratchet.decrypt(encrypted);
65625
- session.activated = true;
65626
- if (this._persisted.sessions[convId]) {
65627
- this._persisted.sessions[convId].activated = true;
65628
- }
65629
- await this._persistState();
65630
- console.log(
65631
- `[SecureChannel] Room session ${convId.slice(0, 8)}... re-activated after ratchet re-init`
65632
- );
65633
- } catch (retryErr) {
65634
- console.warn(
65635
- `[SecureChannel] Room re-init retry failed for conv ${convId.slice(0, 8)} (msgNum=${incomingMsgNum}):`,
65636
- retryErr
65637
- );
65638
- this._sendRoomResyncIfCooled(convId, "room_reinit_retry_failed", session);
65639
- return;
65640
- }
65641
- } else {
65642
- console.log(
65643
- `[SecureChannel] Room re-init: skipping message with msgNum=${incomingMsgNum} for conv ${convId.slice(0, 8)} (too far ahead for fresh ratchet)`
65644
- );
65645
- this._sendRoomResyncIfCooled(convId, "room_message_skip");
65646
- return;
65647
- }
65648
- } catch (reinitErr) {
65649
- console.error(
65650
- `[SecureChannel] Room ratchet re-init failed for conv ${convId.slice(0, 8)}...:`,
65651
- reinitErr
65652
- );
65653
- this._sendRoomResyncIfCooled(convId, "room_reinit_failed");
65654
- return;
65655
- }
65656
- }
65657
- let messageText;
65658
- let messageType;
65659
- try {
65660
- const parsed = JSON.parse(plaintext);
65661
- messageType = parsed.type || "message";
65662
- messageText = parsed.text || plaintext;
65663
- } catch {
65664
- messageType = "message";
65665
- messageText = plaintext;
65666
- }
65667
- if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
65668
- this._handleCredentialMessage(msgData.room_id, messageType, messageText, msgData.message_id);
65669
- if (msgData.created_at && this._persisted) {
65670
- this._persisted.lastMessageTimestamp = msgData.created_at;
65671
- }
65672
- await this._persistState();
65673
- return;
65674
- }
65675
- if (!ROOM_AGENT_TYPES.has(messageType)) {
65676
- return;
65677
- }
65678
- if (!session.activated) {
65679
- session.activated = true;
65680
- console.log(
65681
- `[SecureChannel] Room session ${convId.slice(0, 8)}... activated by first message`
65682
- );
65683
- }
65684
- if (msgData.message_id) {
65685
- this._sendAck(msgData.message_id);
65686
- }
65687
- if (msgData.created_at && this._persisted) {
65688
- this._persisted.lastMessageTimestamp = msgData.created_at;
65689
- }
65690
- await this._persistState();
65691
- const legacyRoomMembers = this._persisted?.rooms?.[msgData.room_id]?.members ?? [];
65692
- const legacySenderMember = legacyRoomMembers.find((m2) => m2.deviceId === msgData.sender_device_id);
65693
- const legacySenderIsAgent = legacySenderMember?.entityType === "agent";
65694
- const legacySenderLabel = legacySenderMember?.displayName || "someone";
65695
- const metadata = {
65696
- messageId: msgData.message_id ?? "",
65697
- conversationId: convId,
65698
- timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
65699
- messageType,
65700
- roomId: msgData.room_id,
65701
- senderDeviceId: msgData.sender_device_id,
65702
- senderIsAgent: legacySenderIsAgent,
65703
- senderName: legacySenderLabel,
65704
- roomName: this._persisted?.rooms?.[msgData.room_id]?.name
65705
- };
65706
- this._appendHistory("owner", messageText, `room:${msgData.room_id}`);
65707
- this.emit("room_message", {
65708
- roomId: msgData.room_id,
65709
- senderDeviceId: msgData.sender_device_id,
65710
- senderName: legacySenderLabel,
65711
- plaintext: messageText,
65712
- messageType,
65713
- timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
65714
- });
65715
- const legacyContextualMessage = legacySenderIsAgent ? messageText : `[${legacySenderLabel}]: ${messageText}`;
65716
- Promise.resolve(this.config.onMessage?.(legacyContextualMessage, metadata)).catch((err) => {
65717
- console.error("[SecureChannel] onMessage callback error:", err);
65718
- });
65719
- }
65373
+ // _sendRoomResyncIfCooled removed — rooms are MLS-only now
65374
+ // _handleRoomMessage removed rooms are MLS-only now
65720
65375
  /**
65721
65376
  * Handle credential protocol messages (grant, revoke, request).
65722
65377
  * These are intercepted before reaching the agent's onMessage callback.
@@ -65805,20 +65460,7 @@ ${messageText}`;
65805
65460
  purgeRoomCredentials(roomId) {
65806
65461
  this._credentialStore.purgeForRoom(roomId);
65807
65462
  }
65808
- /**
65809
- * Find the pairwise conversation ID for a given sender in a room.
65810
- */
65811
- _findConversationForSender(senderDeviceId, roomId) {
65812
- const room = this._persisted?.rooms?.[roomId];
65813
- if (!room) return null;
65814
- for (const convId of room.conversationIds) {
65815
- const session = this._sessions.get(convId);
65816
- if (session && session.ownerDeviceId === senderDeviceId) {
65817
- return convId;
65818
- }
65819
- }
65820
- return null;
65821
- }
65463
+ // _findConversationForSender removed — rooms are MLS-only now
65822
65464
  // ---------------------------------------------------------------------------
65823
65465
  // MLS room message handlers
65824
65466
  // ---------------------------------------------------------------------------
@@ -65842,11 +65484,12 @@ ${messageText}`;
65842
65484
  return;
65843
65485
  }
65844
65486
  }
65845
- this._lastInboundRoomId = roomId;
65846
- const mlsGroup = this._mlsGroups.get(roomId);
65847
- console.log(`[SecureChannel] MLS decrypt attempt room=${roomId.slice(0, 8)} group=${groupId?.slice(0, 8)} loaded=${!!mlsGroup} init=${mlsGroup?.isInitialized} mlsGroupsKeys=[${Array.from(this._mlsGroups.keys()).join(",")}]`);
65487
+ const resolvedRoomId = roomId;
65488
+ this._lastInboundRoomId = resolvedRoomId;
65489
+ const mlsGroup = this._mlsGroups.get(resolvedRoomId);
65490
+ console.log(`[SecureChannel] MLS decrypt attempt room=${resolvedRoomId.slice(0, 8)} group=${groupId?.slice(0, 8)} loaded=${!!mlsGroup} init=${mlsGroup?.isInitialized} mlsGroupsKeys=[${Array.from(this._mlsGroups.keys()).join(",")}]`);
65848
65491
  if (!mlsGroup?.isInitialized) {
65849
- console.warn(`[SecureChannel] MLS group not loaded for room ${roomId.slice(0, 8)}`);
65492
+ console.warn(`[SecureChannel] MLS group not loaded for room ${resolvedRoomId.slice(0, 8)}`);
65850
65493
  return;
65851
65494
  }
65852
65495
  try {
@@ -65868,7 +65511,7 @@ ${messageText}`;
65868
65511
  messageText = rawPlaintext;
65869
65512
  }
65870
65513
  if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
65871
- this._handleCredentialMessage(roomId, messageType, messageText, data.message_id);
65514
+ this._handleCredentialMessage(resolvedRoomId, messageType, messageText, data.message_id);
65872
65515
  if (data.created_at && this._persisted) {
65873
65516
  this._persisted.lastMessageTimestamp = data.created_at;
65874
65517
  }
@@ -65883,13 +65526,13 @@ ${messageText}`;
65883
65526
  }
65884
65527
  if (data.created_at && this._persisted) {
65885
65528
  this._persisted.lastMessageTimestamp = data.created_at;
65886
- const roomState = this._persisted.rooms?.[roomId];
65529
+ const roomState = this._persisted.rooms?.[resolvedRoomId];
65887
65530
  if (roomState) {
65888
65531
  roomState.lastMlsMessageTs = data.created_at;
65889
65532
  }
65890
65533
  }
65891
65534
  await this._persistState();
65892
- const roomMembers = this._persisted?.rooms?.[roomId]?.members ?? [];
65535
+ const roomMembers = this._persisted?.rooms?.[resolvedRoomId]?.members ?? [];
65893
65536
  const senderMember = roomMembers.find((m2) => m2.deviceId === senderDeviceId);
65894
65537
  const senderIsAgent = senderMember?.entityType === "agent";
65895
65538
  const metadata = {
@@ -65897,16 +65540,16 @@ ${messageText}`;
65897
65540
  conversationId: "",
65898
65541
  timestamp: data.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
65899
65542
  messageType,
65900
- roomId,
65543
+ roomId: resolvedRoomId,
65901
65544
  senderDeviceId,
65902
65545
  senderIsAgent,
65903
65546
  senderName: senderMember?.displayName || "unknown",
65904
- roomName: this._persisted?.rooms?.[roomId]?.name
65547
+ roomName: this._persisted?.rooms?.[resolvedRoomId]?.name
65905
65548
  };
65906
65549
  const senderLabel = senderMember?.displayName || "someone";
65907
- this._appendHistory("owner", messageText, `room:${roomId}`);
65550
+ this._appendHistory("owner", messageText, `room:${resolvedRoomId}`);
65908
65551
  this.emit("room_message", {
65909
- roomId,
65552
+ roomId: resolvedRoomId,
65910
65553
  senderDeviceId,
65911
65554
  senderName: senderLabel,
65912
65555
  plaintext: messageText,
@@ -65918,7 +65561,7 @@ ${messageText}`;
65918
65561
  console.error("[SecureChannel] onMessage callback error (MLS):", err);
65919
65562
  });
65920
65563
  } catch (err) {
65921
- console.error(`[SecureChannel] MLS room decrypt failed for ${roomId.slice(0, 8)}:`, err);
65564
+ console.error(`[SecureChannel] MLS room decrypt failed for ${resolvedRoomId.slice(0, 8)}:`, err);
65922
65565
  }
65923
65566
  }
65924
65567
  async _handleMlsCommit(data) {
@@ -66245,22 +65888,6 @@ ${messageText}`;
66245
65888
  }
66246
65889
  }
66247
65890
  if (roomId) {
66248
- try {
66249
- await this._handleRoomMessage({
66250
- room_id: roomId,
66251
- sender_device_id: msg.sender_device_id,
66252
- conversation_id: msg.conversation_id,
66253
- header_blob: msg.header_blob,
66254
- ciphertext: msg.ciphertext,
66255
- message_id: msg.id,
66256
- created_at: msg.created_at
66257
- });
66258
- } catch (roomErr) {
66259
- console.warn(
66260
- `[SecureChannel] Sync room message failed for ${msg.conversation_id.slice(0, 8)}...:`,
66261
- roomErr
66262
- );
66263
- }
66264
65891
  this._persisted.lastMessageTimestamp = msg.created_at;
66265
65892
  since = msg.created_at;
66266
65893
  continue;