@agentvault/agentvault 0.23.32 → 0.23.34
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 +2 -0
- package/dist/channel.d.ts.map +1 -1
- package/dist/cli.js +111 -56
- package/dist/cli.js.map +3 -3
- package/dist/index.js +109 -54
- package/dist/index.js.map +3 -3
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -63266,11 +63266,11 @@ var init_mls_kp_pool = __esm({
|
|
|
63266
63266
|
|
|
63267
63267
|
// src/client-version.ts
|
|
63268
63268
|
function ownIdentity() {
|
|
63269
|
-
const v2 = true ? "0.23.
|
|
63269
|
+
const v2 = true ? "0.23.34" : FALLBACK;
|
|
63270
63270
|
return `${PACKAGE}@${v2}`;
|
|
63271
63271
|
}
|
|
63272
63272
|
function buildSha() {
|
|
63273
|
-
const raw = true ? "
|
|
63273
|
+
const raw = true ? "6b305ca-dirty" : "";
|
|
63274
63274
|
const cleaned = (raw ?? "").trim();
|
|
63275
63275
|
return !cleaned || cleaned === "unknown" ? null : cleaned;
|
|
63276
63276
|
}
|
|
@@ -64199,7 +64199,7 @@ function _isSelfHubAddress(ownHubAddress, target) {
|
|
|
64199
64199
|
const tgt = (target ?? "").trim().toLowerCase();
|
|
64200
64200
|
return own.length > 0 && own === tgt;
|
|
64201
64201
|
}
|
|
64202
|
-
var ROOM_AGENT_TYPES, CREDENTIAL_MESSAGE_TYPES, CATCHUP_MESSAGE_TYPES, POLL_INTERVAL_MS, RECONNECT_BASE_MS, RECONNECT_MAX_MS, PENDING_POLL_INTERVAL_MS, OUTBOUND_DEDUPE_WINDOW_MS, OUTBOUND_DEDUPE_MAX_SUPPRESS_MS, OUTBOUND_DEDUPE_MAX, OUTBOUND_DEDUPE_TYPES, RETRY_CANDIDATE_TTL_MS, RETRY_CANDIDATE_MAX, SecureChannel;
|
|
64202
|
+
var ROOM_AGENT_TYPES, CREDENTIAL_MESSAGE_TYPES, CATCHUP_MESSAGE_TYPES, POLL_INTERVAL_MS, RECONNECT_BASE_MS, RECONNECT_MAX_MS, PENDING_POLL_INTERVAL_MS, OUTBOUND_DEDUPE_WINDOW_MS, OUTBOUND_DEDUPE_MAX_SUPPRESS_MS, OUTBOUND_DEDUPE_MAX, OUTBOUND_DEDUPE_TYPES, RETRY_CANDIDATE_TTL_MS, RETRY_CANDIDATE_MAX, ROOM_FULFIL_COOLDOWN_MS, SecureChannel;
|
|
64203
64203
|
var init_channel = __esm({
|
|
64204
64204
|
async "src/channel.ts"() {
|
|
64205
64205
|
"use strict";
|
|
@@ -64244,6 +64244,7 @@ var init_channel = __esm({
|
|
|
64244
64244
|
OUTBOUND_DEDUPE_TYPES = /* @__PURE__ */ new Set(["text", "status_alert", "artifact", "attachment"]);
|
|
64245
64245
|
RETRY_CANDIDATE_TTL_MS = 6e4;
|
|
64246
64246
|
RETRY_CANDIDATE_MAX = 32;
|
|
64247
|
+
ROOM_FULFIL_COOLDOWN_MS = 6e4;
|
|
64247
64248
|
SecureChannel = class _SecureChannel extends EventEmitter {
|
|
64248
64249
|
constructor(config2) {
|
|
64249
64250
|
super();
|
|
@@ -64313,6 +64314,8 @@ var init_channel = __esm({
|
|
|
64313
64314
|
_drDeliveryPulling = false;
|
|
64314
64315
|
/** MLS group managers per room/conversation (roomId or conv:conversationId or 1to1-group:groupId -> MLSGroupManager) */
|
|
64315
64316
|
_mlsGroups = /* @__PURE__ */ new Map();
|
|
64317
|
+
/** `${mlsGroupId}:${deviceId}` -> last re-admit ms (#1171). */
|
|
64318
|
+
_roomFulfilCooldown = /* @__PURE__ */ new Map();
|
|
64316
64319
|
/** Maps conversationId -> conversation_group_id for shared 1:1 MLS groups */
|
|
64317
64320
|
_sessionGroupIds = /* @__PURE__ */ new Map();
|
|
64318
64321
|
/** Consecutive MLS decrypt failure count per group key for epoch recovery. */
|
|
@@ -65478,7 +65481,7 @@ var init_channel = __esm({
|
|
|
65478
65481
|
*/
|
|
65479
65482
|
sendActivitySpan(spanData) {
|
|
65480
65483
|
if (!this._ws || this._ws.readyState !== WebSocket.OPEN) return;
|
|
65481
|
-
const pluginVersion = true ? "0.23.
|
|
65484
|
+
const pluginVersion = true ? "0.23.34" : "0.0.0-dev";
|
|
65482
65485
|
const agentName = this.config.agentName ?? "Agent";
|
|
65483
65486
|
const resource = {
|
|
65484
65487
|
"service.name": "agentvault-agent",
|
|
@@ -67416,7 +67419,7 @@ var init_channel = __esm({
|
|
|
67416
67419
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
67417
67420
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
67418
67421
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
67419
|
-
pluginVersion: true ? "0.23.
|
|
67422
|
+
pluginVersion: true ? "0.23.34" : "0.0.0-dev"
|
|
67420
67423
|
});
|
|
67421
67424
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
67422
67425
|
}
|
|
@@ -67740,7 +67743,7 @@ var init_channel = __esm({
|
|
|
67740
67743
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
67741
67744
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
67742
67745
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
67743
|
-
pluginVersion: true ? "0.23.
|
|
67746
|
+
pluginVersion: true ? "0.23.34" : "0.0.0-dev"
|
|
67744
67747
|
});
|
|
67745
67748
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
67746
67749
|
}
|
|
@@ -68144,6 +68147,7 @@ var init_channel = __esm({
|
|
|
68144
68147
|
try {
|
|
68145
68148
|
const cipherBytes = new Uint8Array(Buffer.from(data.payload, "hex"));
|
|
68146
68149
|
const result = await mgr.decrypt(cipherBytes);
|
|
68150
|
+
if (mgrKey) this._mlsDecryptFailCounts.delete(mgrKey);
|
|
68147
68151
|
const mlsGroupId = (convGroupId ? this._persisted?.mlsGroups?.[convGroupId]?.mlsGroupId : null) ?? this._persisted?.mlsConversations?.[convId]?.mlsGroupId ?? groupId;
|
|
68148
68152
|
if (mlsGroupId) {
|
|
68149
68153
|
await saveMlsState(this.config.dataDir, mlsGroupId, JSON.stringify(mgr.exportState()));
|
|
@@ -68248,6 +68252,10 @@ var init_channel = __esm({
|
|
|
68248
68252
|
this.config.onMessage(text, metadata);
|
|
68249
68253
|
}
|
|
68250
68254
|
} catch (decryptErr) {
|
|
68255
|
+
if (classifyCommitFailure(data.epoch, mgr?.epoch) === "already-applied") {
|
|
68256
|
+
console.debug(`[SecureChannel] MLS 1:1 message at epoch ${String(data.epoch)} predates our epoch ${String(mgr?.epoch)} \u2014 cannot decrypt, ignoring`);
|
|
68257
|
+
return;
|
|
68258
|
+
}
|
|
68251
68259
|
const failKey = mgrKey || `unknown:${groupId}`;
|
|
68252
68260
|
const count = (this._mlsDecryptFailCounts.get(failKey) ?? 0) + 1;
|
|
68253
68261
|
this._mlsDecryptFailCounts.set(failKey, count);
|
|
@@ -69089,6 +69097,7 @@ ${baseText}`;
|
|
|
69089
69097
|
try {
|
|
69090
69098
|
const ciphertext = Buffer.from(data.payload, "hex");
|
|
69091
69099
|
const result = await mlsGroup.decrypt(new Uint8Array(ciphertext));
|
|
69100
|
+
this._mlsDecryptFailCounts.delete(resolvedRoomId);
|
|
69092
69101
|
await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mlsGroup.exportState()));
|
|
69093
69102
|
if (result.isHandshake || !result.plaintext) {
|
|
69094
69103
|
return;
|
|
@@ -69178,6 +69187,10 @@ ${baseText}`;
|
|
|
69178
69187
|
console.error("[SecureChannel] onMessage callback error (MLS):", err);
|
|
69179
69188
|
});
|
|
69180
69189
|
} catch (err) {
|
|
69190
|
+
if (classifyCommitFailure(data.epoch, mlsGroup.epoch) === "already-applied") {
|
|
69191
|
+
console.debug(`[SecureChannel] MLS room message at epoch ${String(data.epoch)} predates our epoch ${String(mlsGroup.epoch)} for ${resolvedRoomId.slice(0, 8)} \u2014 cannot decrypt, ignoring`);
|
|
69192
|
+
return;
|
|
69193
|
+
}
|
|
69181
69194
|
const failKey = resolvedRoomId;
|
|
69182
69195
|
const count = (this._mlsDecryptFailCounts.get(failKey) ?? 0) + 1;
|
|
69183
69196
|
this._mlsDecryptFailCounts.set(failKey, count);
|
|
@@ -69429,13 +69442,7 @@ ${baseText}`;
|
|
|
69429
69442
|
console.warn(`[SecureChannel] MLS epoch recovery for ${groupKey} (${mlsGroupId.slice(0, 8)})`);
|
|
69430
69443
|
this._mlsGroups.delete(groupKey);
|
|
69431
69444
|
this._mlsDecryptFailCounts.delete(groupKey);
|
|
69432
|
-
|
|
69433
|
-
const { unlink: unlink2 } = await import("fs/promises");
|
|
69434
|
-
const path = `${this.config.dataDir}/.mls-state/${mlsGroupId}.json`;
|
|
69435
|
-
await unlink2(path).catch(() => {
|
|
69436
|
-
});
|
|
69437
|
-
} catch {
|
|
69438
|
-
}
|
|
69445
|
+
await deleteMlsState(this.config.dataDir, mlsGroupId);
|
|
69439
69446
|
try {
|
|
69440
69447
|
const mgr = new MLSGroupManager();
|
|
69441
69448
|
const identity = new TextEncoder().encode(this._deviceId);
|
|
@@ -69510,19 +69517,26 @@ ${baseText}`;
|
|
|
69510
69517
|
return 0;
|
|
69511
69518
|
}
|
|
69512
69519
|
const snapshot = mlsGroup.exportState();
|
|
69513
|
-
const {
|
|
69514
|
-
|
|
69515
|
-
|
|
69516
|
-
|
|
69517
|
-
|
|
69518
|
-
|
|
69519
|
-
|
|
69520
|
-
|
|
69521
|
-
|
|
69522
|
-
|
|
69523
|
-
|
|
69524
|
-
|
|
69525
|
-
|
|
69520
|
+
const { commits, welcome } = await mlsGroup.reAdmitMembers(targets.map((t2) => t2.keyPackage));
|
|
69521
|
+
let sentCommits = 0;
|
|
69522
|
+
for (const c2 of commits) {
|
|
69523
|
+
const ok = await this._sendFrameConfirmed(
|
|
69524
|
+
{
|
|
69525
|
+
event: "mls_commit",
|
|
69526
|
+
data: {
|
|
69527
|
+
group_id: mlsGroupId,
|
|
69528
|
+
// The epoch this commit PRODUCED. After two commits the manager
|
|
69529
|
+
// only knows the last one, which is why the result carries them.
|
|
69530
|
+
epoch: Number(c2.epoch),
|
|
69531
|
+
payload: Buffer.from(c2.commit).toString("hex")
|
|
69532
|
+
}
|
|
69533
|
+
},
|
|
69534
|
+
`${label} commit ${sentCommits + 1}/${commits.length}`
|
|
69535
|
+
);
|
|
69536
|
+
if (!ok) break;
|
|
69537
|
+
sentCommits++;
|
|
69538
|
+
}
|
|
69539
|
+
if (sentCommits === 0) {
|
|
69526
69540
|
mlsGroup.importState(snapshot);
|
|
69527
69541
|
console.warn(
|
|
69528
69542
|
`[SecureChannel] ${label}: commit was NOT written \u2014 rolled back to epoch ${Number(mlsGroup.epoch)}, nothing fulfilled, requests stay pending`
|
|
@@ -69530,6 +69544,12 @@ ${baseText}`;
|
|
|
69530
69544
|
return 0;
|
|
69531
69545
|
}
|
|
69532
69546
|
await saveMlsState(this.config.dataDir, mlsGroupId, JSON.stringify(mlsGroup.exportState()));
|
|
69547
|
+
if (sentCommits < commits.length) {
|
|
69548
|
+
console.warn(
|
|
69549
|
+
`[SecureChannel] ${label}: only ${sentCommits}/${commits.length} commits reached the wire \u2014 requests stay PENDING for the next pull`
|
|
69550
|
+
);
|
|
69551
|
+
return 0;
|
|
69552
|
+
}
|
|
69533
69553
|
if (!welcome) {
|
|
69534
69554
|
console.warn(
|
|
69535
69555
|
`[SecureChannel] ${label}: addMembers produced NO Welcome \u2014 ${targets.length} request(s) left pending rather than marked fulfilled`
|
|
@@ -70210,6 +70230,11 @@ ${baseText}`;
|
|
|
70210
70230
|
nackedIds.push(msg.queue_id);
|
|
70211
70231
|
if (msg.group_id && (msg.message_type === "commit" || msg.message_type === "application")) {
|
|
70212
70232
|
const failKey = msg.conversation_group_id ? `1to1-group:${msg.conversation_group_id}` : `group:${msg.group_id}`;
|
|
70233
|
+
const localMgr = msg.room_id && this._mlsGroups.get(msg.room_id) || this._mlsGroups.get(failKey);
|
|
70234
|
+
if (classifyCommitFailure(msg.epoch, localMgr?.epoch) === "already-applied") {
|
|
70235
|
+
console.debug(`[SecureChannel] Delivery ${msg.message_type} at epoch ${String(msg.epoch)} predates our epoch ${String(localMgr?.epoch)} \u2014 not counting toward recovery`);
|
|
70236
|
+
continue;
|
|
70237
|
+
}
|
|
70213
70238
|
const count = (this._mlsDecryptFailCounts.get(failKey) ?? 0) + 1;
|
|
70214
70239
|
this._mlsDecryptFailCounts.set(failKey, count);
|
|
70215
70240
|
if (count >= _SecureChannel.MAX_MLS_DECRYPT_FAILS) {
|
|
@@ -70258,38 +70283,63 @@ ${baseText}`;
|
|
|
70258
70283
|
{ headers: { Authorization: `Bearer ${this._deviceJwt}` } }
|
|
70259
70284
|
);
|
|
70260
70285
|
if (!pendingRes.ok) continue;
|
|
70261
|
-
|
|
70286
|
+
let pending = await pendingRes.json();
|
|
70262
70287
|
if (pending.length === 0) continue;
|
|
70263
70288
|
console.log(`[SecureChannel] ${pending.length} pending Welcome requests for room ${roomId.slice(0, 8)}`);
|
|
70289
|
+
const nowMs = Date.now();
|
|
70290
|
+
const fresh = pending.filter((r2) => {
|
|
70291
|
+
const key = `${roomState.mlsGroupId}:${r2.requesting_device_id}`;
|
|
70292
|
+
const last = this._roomFulfilCooldown.get(key) ?? 0;
|
|
70293
|
+
if (nowMs - last < ROOM_FULFIL_COOLDOWN_MS) {
|
|
70294
|
+
console.log(
|
|
70295
|
+
`[SecureChannel] skipping ${r2.requesting_device_id.slice(0, 8)} in room ${roomId.slice(0, 8)} \u2014 re-admitted ${Math.round((nowMs - last) / 1e3)}s ago`
|
|
70296
|
+
);
|
|
70297
|
+
return false;
|
|
70298
|
+
}
|
|
70299
|
+
return true;
|
|
70300
|
+
});
|
|
70301
|
+
if (fresh.length === 0) continue;
|
|
70302
|
+
for (const r2 of fresh) {
|
|
70303
|
+
this._roomFulfilCooldown.set(`${roomState.mlsGroupId}:${r2.requesting_device_id}`, nowMs);
|
|
70304
|
+
}
|
|
70305
|
+
pending = fresh;
|
|
70306
|
+
const deviceIds = pending.map((r2) => r2.requesting_device_id);
|
|
70307
|
+
const kpRes = await fetch(
|
|
70308
|
+
`${this.config.apiUrl}/api/v1/mls/key-packages/batch?device_ids=${deviceIds.join(",")}`,
|
|
70309
|
+
{ headers: { Authorization: `Bearer ${this._deviceJwt}` } }
|
|
70310
|
+
);
|
|
70311
|
+
if (!kpRes.ok) continue;
|
|
70312
|
+
const kpData = await kpRes.json();
|
|
70313
|
+
const roomTargets = [];
|
|
70264
70314
|
for (const req of pending) {
|
|
70265
|
-
|
|
70266
|
-
|
|
70267
|
-
|
|
70268
|
-
|
|
70315
|
+
const kpHex = kpData[req.requesting_device_id];
|
|
70316
|
+
if (!kpHex) {
|
|
70317
|
+
console.warn(`[SecureChannel] No KeyPackage for ${req.requesting_device_id.slice(0, 8)}, skipping`);
|
|
70318
|
+
continue;
|
|
70319
|
+
}
|
|
70320
|
+
const kpBytes = new Uint8Array(Buffer.from(kpHex, "hex"));
|
|
70321
|
+
roomTargets.push({
|
|
70322
|
+
requestId: req.id,
|
|
70323
|
+
deviceId: req.requesting_device_id,
|
|
70324
|
+
keyPackage: MLSGroupManager.deserializeKeyPackage(kpBytes)
|
|
70325
|
+
});
|
|
70326
|
+
}
|
|
70327
|
+
if (roomTargets.length === 0) continue;
|
|
70328
|
+
try {
|
|
70329
|
+
const done = await this._fulfilWelcomeRequests({
|
|
70330
|
+
mlsGroup,
|
|
70331
|
+
mlsGroupId: roomState.mlsGroupId,
|
|
70332
|
+
label: `room ${roomId.slice(0, 8)}`,
|
|
70333
|
+
welcomeFields: { room_id: roomId },
|
|
70334
|
+
targets: roomTargets
|
|
70335
|
+
});
|
|
70336
|
+
if (done > 0) {
|
|
70337
|
+
console.log(
|
|
70338
|
+
`[SecureChannel] Batched Welcome for ${done}/${roomTargets.length} device(s) in room ${roomId.slice(0, 8)} (epoch=${mlsGroup.epoch})`
|
|
70269
70339
|
);
|
|
70270
|
-
if (!kpRes.ok) continue;
|
|
70271
|
-
const kpData = await kpRes.json();
|
|
70272
|
-
const kpHex = kpData[req.requesting_device_id];
|
|
70273
|
-
if (!kpHex) continue;
|
|
70274
|
-
const kpBytes = new Uint8Array(Buffer.from(kpHex, "hex"));
|
|
70275
|
-
const memberKp = MLSGroupManager.deserializeKeyPackage(kpBytes);
|
|
70276
|
-
const done = await this._fulfilWelcomeRequests({
|
|
70277
|
-
mlsGroup,
|
|
70278
|
-
mlsGroupId: roomState.mlsGroupId,
|
|
70279
|
-
label: `room ${roomId.slice(0, 8)}`,
|
|
70280
|
-
welcomeFields: { room_id: roomId },
|
|
70281
|
-
targets: [{
|
|
70282
|
-
requestId: req.id,
|
|
70283
|
-
deviceId: req.requesting_device_id,
|
|
70284
|
-
keyPackage: memberKp
|
|
70285
|
-
}]
|
|
70286
|
-
});
|
|
70287
|
-
if (done > 0) {
|
|
70288
|
-
console.log(`[SecureChannel] Fulfilled Welcome for ${req.requesting_device_id.slice(0, 8)} in room ${roomId.slice(0, 8)}`);
|
|
70289
|
-
}
|
|
70290
|
-
} catch (fulfillErr) {
|
|
70291
|
-
console.warn(`[SecureChannel] Welcome fulfill failed for ${req.requesting_device_id.slice(0, 8)}:`, fulfillErr);
|
|
70292
70340
|
}
|
|
70341
|
+
} catch (fulfillErr) {
|
|
70342
|
+
console.warn(`[SecureChannel] Batched Welcome failed for room ${roomId.slice(0, 8)}:`, fulfillErr);
|
|
70293
70343
|
}
|
|
70294
70344
|
} catch {
|
|
70295
70345
|
}
|
|
@@ -70862,6 +70912,7 @@ ${baseText}`;
|
|
|
70862
70912
|
try {
|
|
70863
70913
|
const ciphertext = new Uint8Array(Buffer.from(data.payload, "hex"));
|
|
70864
70914
|
const result = await mlsGroup.decrypt(ciphertext);
|
|
70915
|
+
this._mlsDecryptFailCounts.delete(`a2a:${a2aChannelId}`);
|
|
70865
70916
|
await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mlsGroup.exportState()));
|
|
70866
70917
|
if (result.isHandshake || !result.plaintext) {
|
|
70867
70918
|
return;
|
|
@@ -70882,6 +70933,10 @@ ${baseText}`;
|
|
|
70882
70933
|
this.config.onA2AMessage(a2aMsg);
|
|
70883
70934
|
}
|
|
70884
70935
|
} catch (err) {
|
|
70936
|
+
if (classifyCommitFailure(data.epoch, mlsGroup?.epoch) === "already-applied") {
|
|
70937
|
+
console.debug(`[SecureChannel] MLS A2A message at epoch ${String(data.epoch)} predates our epoch ${String(mlsGroup?.epoch)} for ${a2aChannelId.slice(0, 8)} \u2014 cannot decrypt, ignoring`);
|
|
70938
|
+
return;
|
|
70939
|
+
}
|
|
70885
70940
|
const failKey = `a2a:${a2aChannelId}`;
|
|
70886
70941
|
const count = (this._mlsDecryptFailCounts.get(failKey) ?? 0) + 1;
|
|
70887
70942
|
this._mlsDecryptFailCounts.set(failKey, count);
|
|
@@ -98550,7 +98605,7 @@ var init_index = __esm({
|
|
|
98550
98605
|
await init_skill_telemetry();
|
|
98551
98606
|
await init_policy_enforcer();
|
|
98552
98607
|
init_room_protocol();
|
|
98553
|
-
VERSION = true ? "0.23.
|
|
98608
|
+
VERSION = true ? "0.23.34" : "0.0.0-dev";
|
|
98554
98609
|
}
|
|
98555
98610
|
});
|
|
98556
98611
|
await init_index();
|