@agentvault/agentvault 0.19.57 → 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.
- package/dist/_cp.d.ts +10 -0
- package/dist/_cp.d.ts.map +1 -0
- package/dist/account-config.d.ts +20 -0
- package/dist/account-config.d.ts.map +1 -0
- package/dist/channel.d.ts +389 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +47 -416
- package/dist/cli.js.map +2 -2
- package/dist/create-agent.d.ts +28 -0
- package/dist/create-agent.d.ts.map +1 -0
- package/dist/credential-store.d.ts +62 -0
- package/dist/credential-store.d.ts.map +1 -0
- package/dist/crypto-helpers.d.ts +2 -0
- package/dist/crypto-helpers.d.ts.map +1 -0
- package/dist/doctor.d.ts +41 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/fetch-interceptor.d.ts +32 -0
- package/dist/fetch-interceptor.d.ts.map +1 -0
- package/dist/gateway-send.d.ts +98 -0
- package/dist/gateway-send.d.ts.map +1 -0
- package/dist/http-handlers.d.ts +53 -0
- package/dist/http-handlers.d.ts.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -416
- package/dist/index.js.map +2 -2
- package/dist/mcp-handlers.d.ts +26 -0
- package/dist/mcp-handlers.d.ts.map +1 -0
- package/dist/mcp-proxy-helpers.d.ts +9 -0
- package/dist/mcp-proxy-helpers.d.ts.map +1 -0
- package/dist/mcp-server.d.ts +91 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mls-state.d.ts +16 -0
- package/dist/mls-state.d.ts.map +1 -0
- package/dist/openclaw-compat.d.ts +33 -0
- package/dist/openclaw-compat.d.ts.map +1 -0
- package/dist/openclaw-entry.d.ts +32 -0
- package/dist/openclaw-entry.d.ts.map +1 -0
- package/dist/openclaw-plugin.d.ts +102 -0
- package/dist/openclaw-plugin.d.ts.map +1 -0
- package/dist/openclaw-types.d.ts +186 -0
- package/dist/openclaw-types.d.ts.map +1 -0
- package/dist/policy-enforcer.d.ts +78 -0
- package/dist/policy-enforcer.d.ts.map +1 -0
- package/dist/setup.d.ts +27 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/skill-invoker.d.ts +30 -0
- package/dist/skill-invoker.d.ts.map +1 -0
- package/dist/skill-manifest.d.ts +30 -0
- package/dist/skill-manifest.d.ts.map +1 -0
- package/dist/skill-telemetry.d.ts +36 -0
- package/dist/skill-telemetry.d.ts.map +1 -0
- package/dist/skills-publish.d.ts +8 -0
- package/dist/skills-publish.d.ts.map +1 -0
- package/dist/state.d.ts +32 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/transport.d.ts +24 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/types.d.ts +421 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/workspace-handlers.d.ts +62 -0
- package/dist/workspace-handlers.d.ts.map +1 -0
- package/openclaw.plugin.json +1 -1
- 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,98 +63092,34 @@ var init_channel = __esm({
|
|
|
63074
63092
|
}
|
|
63075
63093
|
// --- Multi-agent room methods ---
|
|
63076
63094
|
/**
|
|
63077
|
-
* Join a room by
|
|
63078
|
-
*
|
|
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 = {};
|
|
63163
63113
|
}
|
|
63114
|
+
const existingMlsGroupId = this._persisted.rooms[roomData.roomId]?.mlsGroupId;
|
|
63115
|
+
const existingMlsTs = this._persisted.rooms[roomData.roomId]?.lastMlsMessageTs;
|
|
63164
63116
|
this._persisted.rooms[roomData.roomId] = {
|
|
63165
63117
|
roomId: roomData.roomId,
|
|
63166
63118
|
name: roomData.name,
|
|
63167
63119
|
conversationIds,
|
|
63168
|
-
members: roomData.members
|
|
63120
|
+
members: roomData.members,
|
|
63121
|
+
...existingMlsGroupId && { mlsGroupId: existingMlsGroupId },
|
|
63122
|
+
...existingMlsTs && { lastMlsMessageTs: existingMlsTs }
|
|
63169
63123
|
};
|
|
63170
63124
|
const mlsRoom = this._persisted.rooms[roomData.roomId];
|
|
63171
63125
|
if (mlsRoom.mlsGroupId && !roomData.forceRekey) {
|
|
@@ -63248,68 +63202,15 @@ var init_channel = __esm({
|
|
|
63248
63202
|
}
|
|
63249
63203
|
return;
|
|
63250
63204
|
} catch (mlsErr) {
|
|
63251
|
-
|
|
63252
|
-
|
|
63253
|
-
|
|
63254
|
-
}
|
|
63255
|
-
const recipients = [];
|
|
63256
|
-
for (const convId of room.conversationIds) {
|
|
63257
|
-
const session = this._sessions.get(convId);
|
|
63258
|
-
if (!session) {
|
|
63259
|
-
console.warn(`[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., skipping`);
|
|
63260
|
-
continue;
|
|
63261
|
-
}
|
|
63262
|
-
const encrypted = session.ratchet.encrypt(plaintext);
|
|
63263
|
-
const transport = encryptedMessageToTransport(encrypted);
|
|
63264
|
-
recipients.push({
|
|
63265
|
-
device_id: session.ownerDeviceId,
|
|
63266
|
-
header_blob: transport.header_blob,
|
|
63267
|
-
ciphertext: transport.ciphertext
|
|
63268
|
-
});
|
|
63269
|
-
}
|
|
63270
|
-
if (recipients.length === 0) {
|
|
63271
|
-
throw new Error("No active sessions in room");
|
|
63272
|
-
}
|
|
63273
|
-
await this._persistState();
|
|
63274
|
-
if (this._state === "ready" && this._ws) {
|
|
63275
|
-
this._ws.send(
|
|
63276
|
-
JSON.stringify({
|
|
63277
|
-
event: "room_message",
|
|
63278
|
-
data: {
|
|
63279
|
-
room_id: roomId,
|
|
63280
|
-
recipients,
|
|
63281
|
-
message_type: messageType,
|
|
63282
|
-
priority: opts?.priority ?? "normal",
|
|
63283
|
-
metadata: opts?.metadata
|
|
63284
|
-
}
|
|
63285
|
-
})
|
|
63286
|
-
);
|
|
63287
|
-
} else {
|
|
63288
|
-
try {
|
|
63289
|
-
const res = await fetch(
|
|
63290
|
-
`${this.config.apiUrl}/api/v1/rooms/${roomId}/messages`,
|
|
63291
|
-
{
|
|
63292
|
-
method: "POST",
|
|
63293
|
-
headers: {
|
|
63294
|
-
"Content-Type": "application/json",
|
|
63295
|
-
Authorization: `Bearer ${this._deviceJwt}`
|
|
63296
|
-
},
|
|
63297
|
-
body: JSON.stringify({
|
|
63298
|
-
recipients,
|
|
63299
|
-
message_type: messageType,
|
|
63300
|
-
priority: opts?.priority ?? "normal",
|
|
63301
|
-
metadata: opts?.metadata
|
|
63302
|
-
})
|
|
63303
|
-
}
|
|
63304
|
-
);
|
|
63305
|
-
if (!res.ok) {
|
|
63306
|
-
const detail = await res.text();
|
|
63307
|
-
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
|
+
);
|
|
63308
63208
|
}
|
|
63309
|
-
} catch (err) {
|
|
63310
|
-
throw new Error(`Failed to send room message: ${err}`);
|
|
63311
63209
|
}
|
|
63312
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
|
+
);
|
|
63313
63214
|
}
|
|
63314
63215
|
/**
|
|
63315
63216
|
* Leave a room: remove sessions and persisted room state.
|
|
@@ -65469,250 +65370,8 @@ ${messageText}`;
|
|
|
65469
65370
|
this.emit("error", err);
|
|
65470
65371
|
}
|
|
65471
65372
|
}
|
|
65472
|
-
|
|
65473
|
-
|
|
65474
|
-
* Shared by all room ratchet failure paths to avoid code duplication.
|
|
65475
|
-
*/
|
|
65476
|
-
_sendRoomResyncIfCooled(convId, reason, session) {
|
|
65477
|
-
const RESYNC_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
65478
|
-
const lastResync = this._lastResyncRequest.get(convId) ?? 0;
|
|
65479
|
-
if (Date.now() - lastResync > RESYNC_COOLDOWN_MS && this._ws && this._persisted) {
|
|
65480
|
-
this._lastResyncRequest.set(convId, Date.now());
|
|
65481
|
-
this._ws.send(
|
|
65482
|
-
JSON.stringify({
|
|
65483
|
-
event: "resync_request",
|
|
65484
|
-
data: {
|
|
65485
|
-
conversation_id: convId,
|
|
65486
|
-
reason,
|
|
65487
|
-
identity_public_key: this._persisted.identityKeypair.publicKey,
|
|
65488
|
-
ephemeral_public_key: this._persisted.ephemeralKeypair.publicKey,
|
|
65489
|
-
epoch: session?.epoch
|
|
65490
|
-
}
|
|
65491
|
-
})
|
|
65492
|
-
);
|
|
65493
|
-
console.log(
|
|
65494
|
-
`[SecureChannel] Room resync requested for conv ${convId.slice(0, 8)} (${reason})`
|
|
65495
|
-
);
|
|
65496
|
-
}
|
|
65497
|
-
}
|
|
65498
|
-
/**
|
|
65499
|
-
* Handle an incoming room message (pairwise path — used by sync replay and pairwise room fallback).
|
|
65500
|
-
* Finds the pairwise conversation for the sender, decrypts, and emits a room_message event.
|
|
65501
|
-
*/
|
|
65502
|
-
async _handleRoomMessage(msgData) {
|
|
65503
|
-
if (msgData.sender_device_id === this._deviceId) return;
|
|
65504
|
-
this._lastInboundRoomId = msgData.room_id;
|
|
65505
|
-
const convId = msgData.conversation_id ?? this._findConversationForSender(msgData.sender_device_id, msgData.room_id);
|
|
65506
|
-
if (!convId) {
|
|
65507
|
-
console.warn(
|
|
65508
|
-
`[SecureChannel] No conversation found for sender ${msgData.sender_device_id.slice(0, 8)}... in room ${msgData.room_id}`
|
|
65509
|
-
);
|
|
65510
|
-
return;
|
|
65511
|
-
}
|
|
65512
|
-
let session = this._sessions.get(convId);
|
|
65513
|
-
if (!session) {
|
|
65514
|
-
console.warn(
|
|
65515
|
-
`[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., fetching room data`
|
|
65516
|
-
);
|
|
65517
|
-
try {
|
|
65518
|
-
const roomRes = await fetch(
|
|
65519
|
-
`${this.config.apiUrl}/api/v1/rooms/${msgData.room_id}`,
|
|
65520
|
-
{
|
|
65521
|
-
headers: {
|
|
65522
|
-
Authorization: `Bearer ${this._persisted.deviceJwt}`
|
|
65523
|
-
}
|
|
65524
|
-
}
|
|
65525
|
-
);
|
|
65526
|
-
if (roomRes.ok) {
|
|
65527
|
-
const roomData = await roomRes.json();
|
|
65528
|
-
await this.joinRoom({
|
|
65529
|
-
roomId: roomData.id,
|
|
65530
|
-
name: roomData.name,
|
|
65531
|
-
members: (roomData.members || []).map((m2) => ({
|
|
65532
|
-
deviceId: m2.device_id,
|
|
65533
|
-
entityType: m2.entity_type,
|
|
65534
|
-
displayName: m2.display_name,
|
|
65535
|
-
identityPublicKey: m2.identity_public_key,
|
|
65536
|
-
ephemeralPublicKey: m2.ephemeral_public_key
|
|
65537
|
-
})),
|
|
65538
|
-
conversations: (roomData.conversations || []).map((c2) => ({
|
|
65539
|
-
id: c2.id,
|
|
65540
|
-
participantA: c2.participant_a,
|
|
65541
|
-
participantB: c2.participant_b
|
|
65542
|
-
}))
|
|
65543
|
-
});
|
|
65544
|
-
session = this._sessions.get(convId);
|
|
65545
|
-
}
|
|
65546
|
-
} catch (fetchErr) {
|
|
65547
|
-
console.error(
|
|
65548
|
-
`[SecureChannel] Failed to fetch room data for ${msgData.room_id}:`,
|
|
65549
|
-
fetchErr
|
|
65550
|
-
);
|
|
65551
|
-
}
|
|
65552
|
-
if (!session) {
|
|
65553
|
-
console.warn(
|
|
65554
|
-
`[SecureChannel] Still no session for room conv ${convId.slice(0, 8)}... after refresh, skipping`
|
|
65555
|
-
);
|
|
65556
|
-
return;
|
|
65557
|
-
}
|
|
65558
|
-
}
|
|
65559
|
-
const encrypted = transportToEncryptedMessage({
|
|
65560
|
-
header_blob: msgData.header_blob,
|
|
65561
|
-
ciphertext: msgData.ciphertext
|
|
65562
|
-
});
|
|
65563
|
-
let plaintext;
|
|
65564
|
-
const ratchetSnapshot = session.ratchet.serialize();
|
|
65565
|
-
try {
|
|
65566
|
-
plaintext = session.ratchet.decrypt(encrypted);
|
|
65567
|
-
} catch (decryptErr) {
|
|
65568
|
-
try {
|
|
65569
|
-
session.ratchet = DoubleRatchet.deserialize(ratchetSnapshot);
|
|
65570
|
-
} catch {
|
|
65571
|
-
}
|
|
65572
|
-
console.warn(
|
|
65573
|
-
`[SecureChannel] Room decrypt failed for conv ${convId.slice(0, 8)}...: ${String(decryptErr)}, re-initializing ratchet`
|
|
65574
|
-
);
|
|
65575
|
-
try {
|
|
65576
|
-
const roomEntry = this._persisted?.rooms ? Object.values(this._persisted.rooms).find(
|
|
65577
|
-
(r2) => r2.conversationIds.includes(convId)
|
|
65578
|
-
) : null;
|
|
65579
|
-
if (!roomEntry) throw new Error("Room not found for conversation");
|
|
65580
|
-
const otherMember = roomEntry.members.find(
|
|
65581
|
-
(m2) => m2.deviceId === msgData.sender_device_id
|
|
65582
|
-
);
|
|
65583
|
-
if (!otherMember?.identityPublicKey) throw new Error("No key for sender");
|
|
65584
|
-
const isInitiator = this._deviceId < msgData.sender_device_id;
|
|
65585
|
-
const identity = this._persisted.identityKeypair;
|
|
65586
|
-
const ephemeral = this._persisted.ephemeralKeypair;
|
|
65587
|
-
const sharedSecret = performX3DH({
|
|
65588
|
-
myIdentityPrivate: hexToBytes(identity.privateKey),
|
|
65589
|
-
myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
|
|
65590
|
-
theirIdentityPublic: hexToBytes(otherMember.identityPublicKey),
|
|
65591
|
-
theirEphemeralPublic: hexToBytes(
|
|
65592
|
-
otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey
|
|
65593
|
-
),
|
|
65594
|
-
isInitiator
|
|
65595
|
-
});
|
|
65596
|
-
const peerIdPub = hexToBytes(otherMember.identityPublicKey);
|
|
65597
|
-
const newRatchet = isInitiator ? DoubleRatchet.initSender(sharedSecret, {
|
|
65598
|
-
publicKey: hexToBytes(identity.publicKey),
|
|
65599
|
-
privateKey: hexToBytes(identity.privateKey),
|
|
65600
|
-
keyType: "ed25519"
|
|
65601
|
-
}, peerIdPub) : DoubleRatchet.initReceiver(sharedSecret, {
|
|
65602
|
-
publicKey: hexToBytes(identity.publicKey),
|
|
65603
|
-
privateKey: hexToBytes(identity.privateKey),
|
|
65604
|
-
keyType: "ed25519"
|
|
65605
|
-
}, peerIdPub);
|
|
65606
|
-
session.ratchet = newRatchet;
|
|
65607
|
-
session.activated = false;
|
|
65608
|
-
this._persisted.sessions[convId] = {
|
|
65609
|
-
ownerDeviceId: session.ownerDeviceId,
|
|
65610
|
-
ratchetState: newRatchet.serialize(),
|
|
65611
|
-
activated: false
|
|
65612
|
-
};
|
|
65613
|
-
await this._persistState();
|
|
65614
|
-
console.log(
|
|
65615
|
-
`[SecureChannel] Room ratchet re-initialized for conv ${convId.slice(0, 8)}...`
|
|
65616
|
-
);
|
|
65617
|
-
const incomingMsgNum = encrypted.header.messageNumber;
|
|
65618
|
-
if (incomingMsgNum <= 5) {
|
|
65619
|
-
try {
|
|
65620
|
-
plaintext = session.ratchet.decrypt(encrypted);
|
|
65621
|
-
session.activated = true;
|
|
65622
|
-
if (this._persisted.sessions[convId]) {
|
|
65623
|
-
this._persisted.sessions[convId].activated = true;
|
|
65624
|
-
}
|
|
65625
|
-
await this._persistState();
|
|
65626
|
-
console.log(
|
|
65627
|
-
`[SecureChannel] Room session ${convId.slice(0, 8)}... re-activated after ratchet re-init`
|
|
65628
|
-
);
|
|
65629
|
-
} catch (retryErr) {
|
|
65630
|
-
console.warn(
|
|
65631
|
-
`[SecureChannel] Room re-init retry failed for conv ${convId.slice(0, 8)} (msgNum=${incomingMsgNum}):`,
|
|
65632
|
-
retryErr
|
|
65633
|
-
);
|
|
65634
|
-
this._sendRoomResyncIfCooled(convId, "room_reinit_retry_failed", session);
|
|
65635
|
-
return;
|
|
65636
|
-
}
|
|
65637
|
-
} else {
|
|
65638
|
-
console.log(
|
|
65639
|
-
`[SecureChannel] Room re-init: skipping message with msgNum=${incomingMsgNum} for conv ${convId.slice(0, 8)} (too far ahead for fresh ratchet)`
|
|
65640
|
-
);
|
|
65641
|
-
this._sendRoomResyncIfCooled(convId, "room_message_skip");
|
|
65642
|
-
return;
|
|
65643
|
-
}
|
|
65644
|
-
} catch (reinitErr) {
|
|
65645
|
-
console.error(
|
|
65646
|
-
`[SecureChannel] Room ratchet re-init failed for conv ${convId.slice(0, 8)}...:`,
|
|
65647
|
-
reinitErr
|
|
65648
|
-
);
|
|
65649
|
-
this._sendRoomResyncIfCooled(convId, "room_reinit_failed");
|
|
65650
|
-
return;
|
|
65651
|
-
}
|
|
65652
|
-
}
|
|
65653
|
-
let messageText;
|
|
65654
|
-
let messageType;
|
|
65655
|
-
try {
|
|
65656
|
-
const parsed = JSON.parse(plaintext);
|
|
65657
|
-
messageType = parsed.type || "message";
|
|
65658
|
-
messageText = parsed.text || plaintext;
|
|
65659
|
-
} catch {
|
|
65660
|
-
messageType = "message";
|
|
65661
|
-
messageText = plaintext;
|
|
65662
|
-
}
|
|
65663
|
-
if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
|
|
65664
|
-
this._handleCredentialMessage(msgData.room_id, messageType, messageText, msgData.message_id);
|
|
65665
|
-
if (msgData.created_at && this._persisted) {
|
|
65666
|
-
this._persisted.lastMessageTimestamp = msgData.created_at;
|
|
65667
|
-
}
|
|
65668
|
-
await this._persistState();
|
|
65669
|
-
return;
|
|
65670
|
-
}
|
|
65671
|
-
if (!ROOM_AGENT_TYPES.has(messageType)) {
|
|
65672
|
-
return;
|
|
65673
|
-
}
|
|
65674
|
-
if (!session.activated) {
|
|
65675
|
-
session.activated = true;
|
|
65676
|
-
console.log(
|
|
65677
|
-
`[SecureChannel] Room session ${convId.slice(0, 8)}... activated by first message`
|
|
65678
|
-
);
|
|
65679
|
-
}
|
|
65680
|
-
if (msgData.message_id) {
|
|
65681
|
-
this._sendAck(msgData.message_id);
|
|
65682
|
-
}
|
|
65683
|
-
if (msgData.created_at && this._persisted) {
|
|
65684
|
-
this._persisted.lastMessageTimestamp = msgData.created_at;
|
|
65685
|
-
}
|
|
65686
|
-
await this._persistState();
|
|
65687
|
-
const legacyRoomMembers = this._persisted?.rooms?.[msgData.room_id]?.members ?? [];
|
|
65688
|
-
const legacySenderMember = legacyRoomMembers.find((m2) => m2.deviceId === msgData.sender_device_id);
|
|
65689
|
-
const legacySenderIsAgent = legacySenderMember?.entityType === "agent";
|
|
65690
|
-
const legacySenderLabel = legacySenderMember?.displayName || "someone";
|
|
65691
|
-
const metadata = {
|
|
65692
|
-
messageId: msgData.message_id ?? "",
|
|
65693
|
-
conversationId: convId,
|
|
65694
|
-
timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
65695
|
-
messageType,
|
|
65696
|
-
roomId: msgData.room_id,
|
|
65697
|
-
senderDeviceId: msgData.sender_device_id,
|
|
65698
|
-
senderIsAgent: legacySenderIsAgent,
|
|
65699
|
-
senderName: legacySenderLabel,
|
|
65700
|
-
roomName: this._persisted?.rooms?.[msgData.room_id]?.name
|
|
65701
|
-
};
|
|
65702
|
-
this._appendHistory("owner", messageText, `room:${msgData.room_id}`);
|
|
65703
|
-
this.emit("room_message", {
|
|
65704
|
-
roomId: msgData.room_id,
|
|
65705
|
-
senderDeviceId: msgData.sender_device_id,
|
|
65706
|
-
senderName: legacySenderLabel,
|
|
65707
|
-
plaintext: messageText,
|
|
65708
|
-
messageType,
|
|
65709
|
-
timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
65710
|
-
});
|
|
65711
|
-
const legacyContextualMessage = legacySenderIsAgent ? messageText : `[${legacySenderLabel}]: ${messageText}`;
|
|
65712
|
-
Promise.resolve(this.config.onMessage?.(legacyContextualMessage, metadata)).catch((err) => {
|
|
65713
|
-
console.error("[SecureChannel] onMessage callback error:", err);
|
|
65714
|
-
});
|
|
65715
|
-
}
|
|
65373
|
+
// _sendRoomResyncIfCooled removed — rooms are MLS-only now
|
|
65374
|
+
// _handleRoomMessage removed — rooms are MLS-only now
|
|
65716
65375
|
/**
|
|
65717
65376
|
* Handle credential protocol messages (grant, revoke, request).
|
|
65718
65377
|
* These are intercepted before reaching the agent's onMessage callback.
|
|
@@ -65801,20 +65460,7 @@ ${messageText}`;
|
|
|
65801
65460
|
purgeRoomCredentials(roomId) {
|
|
65802
65461
|
this._credentialStore.purgeForRoom(roomId);
|
|
65803
65462
|
}
|
|
65804
|
-
|
|
65805
|
-
* Find the pairwise conversation ID for a given sender in a room.
|
|
65806
|
-
*/
|
|
65807
|
-
_findConversationForSender(senderDeviceId, roomId) {
|
|
65808
|
-
const room = this._persisted?.rooms?.[roomId];
|
|
65809
|
-
if (!room) return null;
|
|
65810
|
-
for (const convId of room.conversationIds) {
|
|
65811
|
-
const session = this._sessions.get(convId);
|
|
65812
|
-
if (session && session.ownerDeviceId === senderDeviceId) {
|
|
65813
|
-
return convId;
|
|
65814
|
-
}
|
|
65815
|
-
}
|
|
65816
|
-
return null;
|
|
65817
|
-
}
|
|
65463
|
+
// _findConversationForSender removed — rooms are MLS-only now
|
|
65818
65464
|
// ---------------------------------------------------------------------------
|
|
65819
65465
|
// MLS room message handlers
|
|
65820
65466
|
// ---------------------------------------------------------------------------
|
|
@@ -65838,11 +65484,12 @@ ${messageText}`;
|
|
|
65838
65484
|
return;
|
|
65839
65485
|
}
|
|
65840
65486
|
}
|
|
65841
|
-
|
|
65842
|
-
|
|
65843
|
-
|
|
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(",")}]`);
|
|
65844
65491
|
if (!mlsGroup?.isInitialized) {
|
|
65845
|
-
console.warn(`[SecureChannel] MLS group not loaded for room ${
|
|
65492
|
+
console.warn(`[SecureChannel] MLS group not loaded for room ${resolvedRoomId.slice(0, 8)}`);
|
|
65846
65493
|
return;
|
|
65847
65494
|
}
|
|
65848
65495
|
try {
|
|
@@ -65864,7 +65511,7 @@ ${messageText}`;
|
|
|
65864
65511
|
messageText = rawPlaintext;
|
|
65865
65512
|
}
|
|
65866
65513
|
if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
|
|
65867
|
-
this._handleCredentialMessage(
|
|
65514
|
+
this._handleCredentialMessage(resolvedRoomId, messageType, messageText, data.message_id);
|
|
65868
65515
|
if (data.created_at && this._persisted) {
|
|
65869
65516
|
this._persisted.lastMessageTimestamp = data.created_at;
|
|
65870
65517
|
}
|
|
@@ -65879,13 +65526,13 @@ ${messageText}`;
|
|
|
65879
65526
|
}
|
|
65880
65527
|
if (data.created_at && this._persisted) {
|
|
65881
65528
|
this._persisted.lastMessageTimestamp = data.created_at;
|
|
65882
|
-
const roomState = this._persisted.rooms?.[
|
|
65529
|
+
const roomState = this._persisted.rooms?.[resolvedRoomId];
|
|
65883
65530
|
if (roomState) {
|
|
65884
65531
|
roomState.lastMlsMessageTs = data.created_at;
|
|
65885
65532
|
}
|
|
65886
65533
|
}
|
|
65887
65534
|
await this._persistState();
|
|
65888
|
-
const roomMembers = this._persisted?.rooms?.[
|
|
65535
|
+
const roomMembers = this._persisted?.rooms?.[resolvedRoomId]?.members ?? [];
|
|
65889
65536
|
const senderMember = roomMembers.find((m2) => m2.deviceId === senderDeviceId);
|
|
65890
65537
|
const senderIsAgent = senderMember?.entityType === "agent";
|
|
65891
65538
|
const metadata = {
|
|
@@ -65893,16 +65540,16 @@ ${messageText}`;
|
|
|
65893
65540
|
conversationId: "",
|
|
65894
65541
|
timestamp: data.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
65895
65542
|
messageType,
|
|
65896
|
-
roomId,
|
|
65543
|
+
roomId: resolvedRoomId,
|
|
65897
65544
|
senderDeviceId,
|
|
65898
65545
|
senderIsAgent,
|
|
65899
65546
|
senderName: senderMember?.displayName || "unknown",
|
|
65900
|
-
roomName: this._persisted?.rooms?.[
|
|
65547
|
+
roomName: this._persisted?.rooms?.[resolvedRoomId]?.name
|
|
65901
65548
|
};
|
|
65902
65549
|
const senderLabel = senderMember?.displayName || "someone";
|
|
65903
|
-
this._appendHistory("owner", messageText, `room:${
|
|
65550
|
+
this._appendHistory("owner", messageText, `room:${resolvedRoomId}`);
|
|
65904
65551
|
this.emit("room_message", {
|
|
65905
|
-
roomId,
|
|
65552
|
+
roomId: resolvedRoomId,
|
|
65906
65553
|
senderDeviceId,
|
|
65907
65554
|
senderName: senderLabel,
|
|
65908
65555
|
plaintext: messageText,
|
|
@@ -65914,7 +65561,7 @@ ${messageText}`;
|
|
|
65914
65561
|
console.error("[SecureChannel] onMessage callback error (MLS):", err);
|
|
65915
65562
|
});
|
|
65916
65563
|
} catch (err) {
|
|
65917
|
-
console.error(`[SecureChannel] MLS room decrypt failed for ${
|
|
65564
|
+
console.error(`[SecureChannel] MLS room decrypt failed for ${resolvedRoomId.slice(0, 8)}:`, err);
|
|
65918
65565
|
}
|
|
65919
65566
|
}
|
|
65920
65567
|
async _handleMlsCommit(data) {
|
|
@@ -66241,22 +65888,6 @@ ${messageText}`;
|
|
|
66241
65888
|
}
|
|
66242
65889
|
}
|
|
66243
65890
|
if (roomId) {
|
|
66244
|
-
try {
|
|
66245
|
-
await this._handleRoomMessage({
|
|
66246
|
-
room_id: roomId,
|
|
66247
|
-
sender_device_id: msg.sender_device_id,
|
|
66248
|
-
conversation_id: msg.conversation_id,
|
|
66249
|
-
header_blob: msg.header_blob,
|
|
66250
|
-
ciphertext: msg.ciphertext,
|
|
66251
|
-
message_id: msg.id,
|
|
66252
|
-
created_at: msg.created_at
|
|
66253
|
-
});
|
|
66254
|
-
} catch (roomErr) {
|
|
66255
|
-
console.warn(
|
|
66256
|
-
`[SecureChannel] Sync room message failed for ${msg.conversation_id.slice(0, 8)}...:`,
|
|
66257
|
-
roomErr
|
|
66258
|
-
);
|
|
66259
|
-
}
|
|
66260
65891
|
this._persisted.lastMessageTimestamp = msg.created_at;
|
|
66261
65892
|
since = msg.created_at;
|
|
66262
65893
|
continue;
|