@agentvault/agentvault 0.9.0 → 0.9.1
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.map +1 -1
- package/dist/cli.js +178 -12
- package/dist/cli.js.map +3 -3
- package/dist/index.js +178 -12
- package/dist/index.js.map +3 -3
- package/dist/openclaw-entry.d.ts.map +1 -1
- package/dist/openclaw-entry.js +13 -8
- package/dist/openclaw-entry.js.map +2 -2
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45421,9 +45421,18 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
|
|
|
45421
45421
|
scanStatus = scanResult.status;
|
|
45422
45422
|
}
|
|
45423
45423
|
this._appendHistory("agent", plaintext, topicId);
|
|
45424
|
+
const roomConvIds = /* @__PURE__ */ new Set();
|
|
45425
|
+
if (this._persisted?.rooms) {
|
|
45426
|
+
for (const room of Object.values(this._persisted.rooms)) {
|
|
45427
|
+
for (const cid of room.conversationIds) {
|
|
45428
|
+
roomConvIds.add(cid);
|
|
45429
|
+
}
|
|
45430
|
+
}
|
|
45431
|
+
}
|
|
45424
45432
|
const messageGroupId = randomUUID();
|
|
45425
45433
|
for (const [convId, session] of this._sessions) {
|
|
45426
45434
|
if (!session.activated) continue;
|
|
45435
|
+
if (roomConvIds.has(convId)) continue;
|
|
45427
45436
|
const encrypted = session.ratchet.encrypt(plaintext);
|
|
45428
45437
|
const transport = encryptedMessageToTransport(encrypted);
|
|
45429
45438
|
const msg = {
|
|
@@ -45569,6 +45578,10 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
|
|
|
45569
45578
|
if (conv.participantA !== myDeviceId && conv.participantB !== myDeviceId) {
|
|
45570
45579
|
continue;
|
|
45571
45580
|
}
|
|
45581
|
+
if (this._sessions.has(conv.id)) {
|
|
45582
|
+
conversationIds.push(conv.id);
|
|
45583
|
+
continue;
|
|
45584
|
+
}
|
|
45572
45585
|
const otherDeviceId = conv.participantA === myDeviceId ? conv.participantB : conv.participantA;
|
|
45573
45586
|
const otherMember = roomData.members.find((m2) => m2.deviceId === otherDeviceId);
|
|
45574
45587
|
if (!otherMember?.identityPublicKey) {
|
|
@@ -45578,13 +45591,12 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
|
|
|
45578
45591
|
continue;
|
|
45579
45592
|
}
|
|
45580
45593
|
const isInitiator = myDeviceId < otherDeviceId;
|
|
45594
|
+
const theirEphKey = otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey;
|
|
45581
45595
|
const sharedSecret = performX3DH({
|
|
45582
45596
|
myIdentityPrivate: hexToBytes(identity.privateKey),
|
|
45583
45597
|
myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
|
|
45584
45598
|
theirIdentityPublic: hexToBytes(otherMember.identityPublicKey),
|
|
45585
|
-
theirEphemeralPublic: hexToBytes(
|
|
45586
|
-
otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey
|
|
45587
|
-
),
|
|
45599
|
+
theirEphemeralPublic: hexToBytes(theirEphKey),
|
|
45588
45600
|
isInitiator
|
|
45589
45601
|
});
|
|
45590
45602
|
const ratchet = isInitiator ? DoubleRatchet.initSender(sharedSecret, {
|
|
@@ -45656,9 +45668,11 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
|
|
|
45656
45668
|
this._ws.send(
|
|
45657
45669
|
JSON.stringify({
|
|
45658
45670
|
event: "room_message",
|
|
45659
|
-
|
|
45660
|
-
|
|
45661
|
-
|
|
45671
|
+
data: {
|
|
45672
|
+
room_id: roomId,
|
|
45673
|
+
recipients,
|
|
45674
|
+
message_type: messageType
|
|
45675
|
+
}
|
|
45662
45676
|
})
|
|
45663
45677
|
);
|
|
45664
45678
|
} else {
|
|
@@ -46084,6 +46098,23 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
|
|
|
46084
46098
|
if (this._persisted.hubAddress) {
|
|
46085
46099
|
payload2.hub_address = this._persisted.hubAddress;
|
|
46086
46100
|
}
|
|
46101
|
+
if (channelEntry.observerSession?.ratchetState) {
|
|
46102
|
+
try {
|
|
46103
|
+
const obsRatchet = DoubleRatchet.deserialize(channelEntry.observerSession.ratchetState);
|
|
46104
|
+
const obsEncrypted = obsRatchet.encrypt(text);
|
|
46105
|
+
const obsHeaderObj = {
|
|
46106
|
+
dhPublicKey: bytesToHex(obsEncrypted.header.dhPublicKey),
|
|
46107
|
+
previousChainLength: obsEncrypted.header.previousChainLength,
|
|
46108
|
+
messageNumber: obsEncrypted.header.messageNumber
|
|
46109
|
+
};
|
|
46110
|
+
payload2.observer_header_blob = Buffer.from(JSON.stringify(obsHeaderObj)).toString("hex");
|
|
46111
|
+
payload2.observer_ciphertext = bytesToHex(obsEncrypted.ciphertext);
|
|
46112
|
+
payload2.observer_nonce = bytesToHex(obsEncrypted.nonce);
|
|
46113
|
+
channelEntry.observerSession.ratchetState = obsRatchet.serialize();
|
|
46114
|
+
} catch (obsErr) {
|
|
46115
|
+
console.error("[SecureChannel] Observer encryption failed (sending without observer copy):", obsErr);
|
|
46116
|
+
}
|
|
46117
|
+
}
|
|
46087
46118
|
channelEntry.session.ratchetState = ratchet.serialize();
|
|
46088
46119
|
await this._persistState();
|
|
46089
46120
|
this._ws.send(
|
|
@@ -46386,7 +46417,7 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
|
|
|
46386
46417
|
const d2 = data.data;
|
|
46387
46418
|
this.joinRoom({
|
|
46388
46419
|
roomId: d2.room_id,
|
|
46389
|
-
name: d2.name,
|
|
46420
|
+
name: d2.room_name ?? d2.name ?? "Room",
|
|
46390
46421
|
members: (d2.members || []).map((m2) => ({
|
|
46391
46422
|
deviceId: m2.device_id,
|
|
46392
46423
|
entityType: m2.entity_type,
|
|
@@ -46539,6 +46570,74 @@ var SecureChannel = class _SecureChannel extends EventEmitter {
|
|
|
46539
46570
|
}
|
|
46540
46571
|
this.emit("a2a_channel_activated", actData);
|
|
46541
46572
|
}
|
|
46573
|
+
if (data.event === "a2a_observer_enabled") {
|
|
46574
|
+
const obsData = data.data || data;
|
|
46575
|
+
const obsChannelId = obsData.channel_id;
|
|
46576
|
+
const obsChannelEntry = this._persisted?.a2aChannels?.[obsChannelId];
|
|
46577
|
+
if (obsChannelEntry && this._persisted && this._ws) {
|
|
46578
|
+
try {
|
|
46579
|
+
const obsEphemeral = await generateEphemeralKeypair();
|
|
46580
|
+
const obsEphPubHex = bytesToHex(obsEphemeral.publicKey);
|
|
46581
|
+
const obsEphPrivHex = bytesToHex(obsEphemeral.privateKey);
|
|
46582
|
+
obsChannelEntry.pendingObserverEphemeralPrivateKey = obsEphPrivHex;
|
|
46583
|
+
await this._persistState();
|
|
46584
|
+
this._ws.send(
|
|
46585
|
+
JSON.stringify({
|
|
46586
|
+
event: "a2a_observer_key_submit",
|
|
46587
|
+
data: {
|
|
46588
|
+
channel_id: obsChannelId,
|
|
46589
|
+
ephemeral_key: obsEphPubHex,
|
|
46590
|
+
side: obsChannelEntry.role || "initiator"
|
|
46591
|
+
}
|
|
46592
|
+
})
|
|
46593
|
+
);
|
|
46594
|
+
console.log(
|
|
46595
|
+
`[SecureChannel] Observer key submitted for channel ${obsChannelId.slice(0, 8)}... (side=${obsChannelEntry.role})`
|
|
46596
|
+
);
|
|
46597
|
+
} catch (err) {
|
|
46598
|
+
console.error("[SecureChannel] Observer key submission failed:", err);
|
|
46599
|
+
}
|
|
46600
|
+
}
|
|
46601
|
+
}
|
|
46602
|
+
if (data.event === "a2a_observer_key_accepted") {
|
|
46603
|
+
const obsAccData = data.data || data;
|
|
46604
|
+
const obsAccChannelId = obsAccData.channel_id;
|
|
46605
|
+
const observerIdentityHex = obsAccData.observer_identity_key;
|
|
46606
|
+
const obsAccSide = obsAccData.side;
|
|
46607
|
+
const obsAccEntry = this._persisted?.a2aChannels?.[obsAccChannelId];
|
|
46608
|
+
if (obsAccEntry && obsAccEntry.pendingObserverEphemeralPrivateKey && this._persisted) {
|
|
46609
|
+
try {
|
|
46610
|
+
const myIdentityPrivate = hexToBytes(this._persisted.identityKeypair.privateKey);
|
|
46611
|
+
const myIdentityPublic = hexToBytes(this._persisted.identityKeypair.publicKey);
|
|
46612
|
+
const myObsEphemeralPrivate = hexToBytes(obsAccEntry.pendingObserverEphemeralPrivateKey);
|
|
46613
|
+
const ownerIdentityPublic = hexToBytes(observerIdentityHex);
|
|
46614
|
+
const obsSharedSecret = performX3DH({
|
|
46615
|
+
myIdentityPrivate,
|
|
46616
|
+
myEphemeralPrivate: myObsEphemeralPrivate,
|
|
46617
|
+
theirIdentityPublic: ownerIdentityPublic,
|
|
46618
|
+
theirEphemeralPublic: ownerIdentityPublic,
|
|
46619
|
+
// owner uses identity as ephemeral
|
|
46620
|
+
isInitiator: true
|
|
46621
|
+
});
|
|
46622
|
+
const identityKp = {
|
|
46623
|
+
publicKey: myIdentityPublic,
|
|
46624
|
+
privateKey: myIdentityPrivate,
|
|
46625
|
+
keyType: "ed25519"
|
|
46626
|
+
};
|
|
46627
|
+
const obsRatchet = DoubleRatchet.initSender(obsSharedSecret, identityKp);
|
|
46628
|
+
obsAccEntry.observerSession = {
|
|
46629
|
+
ratchetState: obsRatchet.serialize()
|
|
46630
|
+
};
|
|
46631
|
+
delete obsAccEntry.pendingObserverEphemeralPrivateKey;
|
|
46632
|
+
await this._persistState();
|
|
46633
|
+
console.log(
|
|
46634
|
+
`[SecureChannel] Observer ratchet initialized for channel ${obsAccChannelId.slice(0, 8)}... (side=${obsAccSide})`
|
|
46635
|
+
);
|
|
46636
|
+
} catch (err) {
|
|
46637
|
+
console.error("[SecureChannel] Observer ratchet init failed:", err);
|
|
46638
|
+
}
|
|
46639
|
+
}
|
|
46640
|
+
}
|
|
46542
46641
|
if (data.event === "a2a_channel_rejected") {
|
|
46543
46642
|
this.emit("a2a_channel_rejected", data.data || data);
|
|
46544
46643
|
}
|
|
@@ -47009,7 +47108,73 @@ ${messageText}`;
|
|
|
47009
47108
|
header_blob: msgData.header_blob,
|
|
47010
47109
|
ciphertext: msgData.ciphertext
|
|
47011
47110
|
});
|
|
47012
|
-
|
|
47111
|
+
let plaintext;
|
|
47112
|
+
try {
|
|
47113
|
+
plaintext = session.ratchet.decrypt(encrypted);
|
|
47114
|
+
} catch (decryptErr) {
|
|
47115
|
+
console.warn(
|
|
47116
|
+
`[SecureChannel] Room decrypt failed for conv ${convId.slice(0, 8)}...: ${String(decryptErr)}, re-initializing ratchet`
|
|
47117
|
+
);
|
|
47118
|
+
try {
|
|
47119
|
+
const roomEntry = this._persisted?.rooms ? Object.values(this._persisted.rooms).find(
|
|
47120
|
+
(r2) => r2.conversationIds.includes(convId)
|
|
47121
|
+
) : null;
|
|
47122
|
+
if (!roomEntry) throw new Error("Room not found for conversation");
|
|
47123
|
+
const otherMember = roomEntry.members.find(
|
|
47124
|
+
(m2) => m2.deviceId === msgData.sender_device_id
|
|
47125
|
+
);
|
|
47126
|
+
if (!otherMember?.identityPublicKey) throw new Error("No key for sender");
|
|
47127
|
+
const isInitiator = this._deviceId < msgData.sender_device_id;
|
|
47128
|
+
const identity = this._persisted.identityKeypair;
|
|
47129
|
+
const ephemeral = this._persisted.ephemeralKeypair;
|
|
47130
|
+
const sharedSecret = performX3DH({
|
|
47131
|
+
myIdentityPrivate: hexToBytes(identity.privateKey),
|
|
47132
|
+
myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
|
|
47133
|
+
theirIdentityPublic: hexToBytes(otherMember.identityPublicKey),
|
|
47134
|
+
theirEphemeralPublic: hexToBytes(
|
|
47135
|
+
otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey
|
|
47136
|
+
),
|
|
47137
|
+
isInitiator
|
|
47138
|
+
});
|
|
47139
|
+
const newRatchet = isInitiator ? DoubleRatchet.initSender(sharedSecret, {
|
|
47140
|
+
publicKey: hexToBytes(identity.publicKey),
|
|
47141
|
+
privateKey: hexToBytes(identity.privateKey),
|
|
47142
|
+
keyType: "ed25519"
|
|
47143
|
+
}) : DoubleRatchet.initReceiver(sharedSecret, {
|
|
47144
|
+
publicKey: hexToBytes(identity.publicKey),
|
|
47145
|
+
privateKey: hexToBytes(identity.privateKey),
|
|
47146
|
+
keyType: "ed25519"
|
|
47147
|
+
});
|
|
47148
|
+
session.ratchet = newRatchet;
|
|
47149
|
+
session.activated = false;
|
|
47150
|
+
this._persisted.sessions[convId] = {
|
|
47151
|
+
ownerDeviceId: session.ownerDeviceId,
|
|
47152
|
+
ratchetState: newRatchet.serialize(),
|
|
47153
|
+
activated: false
|
|
47154
|
+
};
|
|
47155
|
+
await this._persistState();
|
|
47156
|
+
console.log(
|
|
47157
|
+
`[SecureChannel] Room ratchet re-initialized for conv ${convId.slice(0, 8)}...`
|
|
47158
|
+
);
|
|
47159
|
+
plaintext = session.ratchet.decrypt(encrypted);
|
|
47160
|
+
} catch (reinitErr) {
|
|
47161
|
+
console.error(
|
|
47162
|
+
`[SecureChannel] Room ratchet re-init failed for conv ${convId.slice(0, 8)}...:`,
|
|
47163
|
+
reinitErr
|
|
47164
|
+
);
|
|
47165
|
+
return;
|
|
47166
|
+
}
|
|
47167
|
+
}
|
|
47168
|
+
let messageText;
|
|
47169
|
+
let messageType;
|
|
47170
|
+
try {
|
|
47171
|
+
const parsed = JSON.parse(plaintext);
|
|
47172
|
+
messageType = parsed.type || "message";
|
|
47173
|
+
messageText = parsed.text || plaintext;
|
|
47174
|
+
} catch {
|
|
47175
|
+
messageType = "message";
|
|
47176
|
+
messageText = plaintext;
|
|
47177
|
+
}
|
|
47013
47178
|
if (!session.activated) {
|
|
47014
47179
|
session.activated = true;
|
|
47015
47180
|
console.log(
|
|
@@ -47024,16 +47189,17 @@ ${messageText}`;
|
|
|
47024
47189
|
messageId: msgData.message_id ?? "",
|
|
47025
47190
|
conversationId: convId,
|
|
47026
47191
|
timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
47027
|
-
messageType
|
|
47192
|
+
messageType,
|
|
47193
|
+
roomId: msgData.room_id
|
|
47028
47194
|
};
|
|
47029
47195
|
this.emit("room_message", {
|
|
47030
47196
|
roomId: msgData.room_id,
|
|
47031
47197
|
senderDeviceId: msgData.sender_device_id,
|
|
47032
|
-
plaintext,
|
|
47033
|
-
messageType
|
|
47198
|
+
plaintext: messageText,
|
|
47199
|
+
messageType,
|
|
47034
47200
|
timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
47035
47201
|
});
|
|
47036
|
-
this.config.onMessage?.(
|
|
47202
|
+
this.config.onMessage?.(messageText, metadata);
|
|
47037
47203
|
}
|
|
47038
47204
|
/**
|
|
47039
47205
|
* Find the pairwise conversation ID for a given sender in a room.
|