@agentvault/agentvault 0.20.26 → 0.20.28
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 +5 -0
- package/dist/channel.d.ts.map +1 -1
- package/dist/cli.js +77 -13
- package/dist/cli.js.map +2 -2
- package/dist/index.js +77 -13
- package/dist/index.js.map +2 -2
- package/dist/mls-state.d.ts +38 -0
- package/dist/mls-state.d.ts.map +1 -1
- package/dist/openclaw-entry.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -62722,6 +62722,43 @@ var init_dist = __esm({
|
|
|
62722
62722
|
// src/mls-state.ts
|
|
62723
62723
|
import { mkdir, readFile, writeFile, rm } from "node:fs/promises";
|
|
62724
62724
|
import { join } from "node:path";
|
|
62725
|
+
function syncLockPath(dataDir, channelId) {
|
|
62726
|
+
const safe = channelId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
62727
|
+
return join(dataDir, `mls-a2a-sync-${safe}.lock`);
|
|
62728
|
+
}
|
|
62729
|
+
async function acquireA2ASyncLock(dataDir, channelId) {
|
|
62730
|
+
await mkdir(dataDir, { recursive: true, mode: DIR_MODE });
|
|
62731
|
+
const lockFile = syncLockPath(dataDir, channelId);
|
|
62732
|
+
const content = JSON.stringify({ pid: process.pid, timestamp: Date.now() });
|
|
62733
|
+
try {
|
|
62734
|
+
await writeFile(lockFile, content, { encoding: "utf-8", mode: FILE_MODE, flag: "wx" });
|
|
62735
|
+
return true;
|
|
62736
|
+
} catch (err) {
|
|
62737
|
+
if (err.code !== "EEXIST") throw err;
|
|
62738
|
+
try {
|
|
62739
|
+
const raw = await readFile(lockFile, "utf-8");
|
|
62740
|
+
const parsed = JSON.parse(raw);
|
|
62741
|
+
if (typeof parsed.timestamp === "number" && Date.now() - parsed.timestamp > SYNC_LOCK_STALE_MS) {
|
|
62742
|
+
await rm(lockFile).catch(() => {
|
|
62743
|
+
});
|
|
62744
|
+
try {
|
|
62745
|
+
await writeFile(lockFile, content, { encoding: "utf-8", mode: FILE_MODE, flag: "wx" });
|
|
62746
|
+
return true;
|
|
62747
|
+
} catch {
|
|
62748
|
+
return false;
|
|
62749
|
+
}
|
|
62750
|
+
}
|
|
62751
|
+
} catch {
|
|
62752
|
+
}
|
|
62753
|
+
return false;
|
|
62754
|
+
}
|
|
62755
|
+
}
|
|
62756
|
+
async function releaseA2ASyncLock(dataDir, channelId) {
|
|
62757
|
+
try {
|
|
62758
|
+
await rm(syncLockPath(dataDir, channelId));
|
|
62759
|
+
} catch {
|
|
62760
|
+
}
|
|
62761
|
+
}
|
|
62725
62762
|
function mlsFileName(groupId) {
|
|
62726
62763
|
const safe = groupId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
62727
62764
|
return `mls-${safe}.json`;
|
|
@@ -62734,10 +62771,10 @@ async function hasPendingWelcome(dataDir, groupId) {
|
|
|
62734
62771
|
return false;
|
|
62735
62772
|
}
|
|
62736
62773
|
}
|
|
62737
|
-
async function savePendingKpBundle(dataDir, groupId, kp) {
|
|
62774
|
+
async function savePendingKpBundle(dataDir, groupId, kp, serializePublicFn) {
|
|
62738
62775
|
await mkdir(dataDir, { recursive: true, mode: DIR_MODE });
|
|
62739
62776
|
const serialized = {
|
|
62740
|
-
|
|
62777
|
+
publicPackageBytes: Buffer.from(serializePublicFn(kp.publicPackage)).toString("base64"),
|
|
62741
62778
|
privatePackage: {
|
|
62742
62779
|
initPrivateKey: Buffer.from(kp.privatePackage.initPrivateKey).toString("base64"),
|
|
62743
62780
|
hpkePrivateKey: Buffer.from(kp.privatePackage.hpkePrivateKey).toString("base64"),
|
|
@@ -62751,7 +62788,7 @@ async function loadPendingKpBundle(dataDir, groupId) {
|
|
|
62751
62788
|
const raw = await readFile(pendingKpPath(dataDir, groupId), "utf-8");
|
|
62752
62789
|
const parsed = JSON.parse(raw);
|
|
62753
62790
|
return {
|
|
62754
|
-
|
|
62791
|
+
publicPackageBytes: new Uint8Array(Buffer.from(parsed.publicPackageBytes, "base64")),
|
|
62755
62792
|
privatePackage: {
|
|
62756
62793
|
initPrivateKey: new Uint8Array(Buffer.from(parsed.privatePackage.initPrivateKey, "base64")),
|
|
62757
62794
|
hpkePrivateKey: new Uint8Array(Buffer.from(parsed.privatePackage.hpkePrivateKey, "base64")),
|
|
@@ -62788,12 +62825,13 @@ async function deleteMlsState(dataDir, groupId) {
|
|
|
62788
62825
|
} catch {
|
|
62789
62826
|
}
|
|
62790
62827
|
}
|
|
62791
|
-
var FILE_MODE, DIR_MODE, pendingKpPath;
|
|
62828
|
+
var FILE_MODE, DIR_MODE, SYNC_LOCK_STALE_MS, pendingKpPath;
|
|
62792
62829
|
var init_mls_state = __esm({
|
|
62793
62830
|
"src/mls-state.ts"() {
|
|
62794
62831
|
"use strict";
|
|
62795
62832
|
FILE_MODE = 384;
|
|
62796
62833
|
DIR_MODE = 448;
|
|
62834
|
+
SYNC_LOCK_STALE_MS = 5 * 60 * 1e3;
|
|
62797
62835
|
pendingKpPath = (dataDir, groupId) => join(dataDir, `mls-kp-pending-${groupId.replace(/[^a-zA-Z0-9_-]/g, "_")}.json`);
|
|
62798
62836
|
}
|
|
62799
62837
|
});
|
|
@@ -65243,6 +65281,10 @@ var init_channel = __esm({
|
|
|
65243
65281
|
}
|
|
65244
65282
|
const memberMlsGroup = chState.mlsGroupId ? this._mlsGroups.get(`a2a:${chId}`) : void 0;
|
|
65245
65283
|
if (chState.role === "member" && !memberMlsGroup?.isInitialized) {
|
|
65284
|
+
if (!await acquireA2ASyncLock(this.config.dataDir, chId)) {
|
|
65285
|
+
console.log(`[SecureChannel] A2A ${chId.slice(0, 8)} sync: skipping \u2014 another instance holds the lock`);
|
|
65286
|
+
continue;
|
|
65287
|
+
}
|
|
65246
65288
|
try {
|
|
65247
65289
|
let groupId = chState.mlsGroupId;
|
|
65248
65290
|
let memberIds = [];
|
|
@@ -65252,11 +65294,15 @@ var init_channel = __esm({
|
|
|
65252
65294
|
{ headers: { Authorization: `Bearer ${this._deviceJwt}` } }
|
|
65253
65295
|
);
|
|
65254
65296
|
if (!groupRes.ok) {
|
|
65297
|
+
await releaseA2ASyncLock(this.config.dataDir, chId);
|
|
65255
65298
|
continue;
|
|
65256
65299
|
}
|
|
65257
65300
|
const groupData = await groupRes.json();
|
|
65258
65301
|
groupId = groupData.group_id;
|
|
65259
|
-
if (!groupId)
|
|
65302
|
+
if (!groupId) {
|
|
65303
|
+
await releaseA2ASyncLock(this.config.dataDir, chId);
|
|
65304
|
+
continue;
|
|
65305
|
+
}
|
|
65260
65306
|
memberIds = groupData.member_device_ids || [];
|
|
65261
65307
|
chState.mlsGroupId = groupId;
|
|
65262
65308
|
await this._persistState();
|
|
@@ -65284,7 +65330,7 @@ var init_channel = __esm({
|
|
|
65284
65330
|
const identity = new TextEncoder().encode(this._persisted.deviceId);
|
|
65285
65331
|
const kp = await mgr.generateKeyPackage(identity);
|
|
65286
65332
|
this._pendingMlsKpBundle = kp;
|
|
65287
|
-
await savePendingKpBundle(this.config.dataDir, groupId, kp);
|
|
65333
|
+
await savePendingKpBundle(this.config.dataDir, groupId, kp, MLSGroupManager.serializeKeyPackage);
|
|
65288
65334
|
const kpBytes = MLSGroupManager.serializeKeyPackage(kp.publicPackage);
|
|
65289
65335
|
await fetch(`${this.config.apiUrl}/api/v1/mls/key-packages`, {
|
|
65290
65336
|
method: "POST",
|
|
@@ -65309,6 +65355,8 @@ var init_channel = __esm({
|
|
|
65309
65355
|
`[SecureChannel] A2A ${chId.slice(0, 8)} member sync fallback: published KeyPackage + requested Welcome (group=${groupId.slice(0, 8)})`
|
|
65310
65356
|
);
|
|
65311
65357
|
} catch (err) {
|
|
65358
|
+
await releaseA2ASyncLock(this.config.dataDir, chId).catch(() => {
|
|
65359
|
+
});
|
|
65312
65360
|
console.warn(`[AgentVault] Sync fallback member MLS join failed for ${chId.slice(0, 8)}:`, err);
|
|
65313
65361
|
}
|
|
65314
65362
|
}
|
|
@@ -67148,17 +67196,26 @@ ${messageText}`;
|
|
|
67148
67196
|
async _handleMlsWelcome(data) {
|
|
67149
67197
|
const groupId = data.group_id;
|
|
67150
67198
|
const conversationId = data.conversation_id;
|
|
67151
|
-
const
|
|
67152
|
-
const kpSource = this._pendingMlsKpBundle ? "pending" : persistedKpAvailable ? "persisted" : this._mlsKeyPackage ? "connect" : "generated";
|
|
67199
|
+
const kpSource = this._pendingMlsKpBundle ? "pending" : this._mlsKeyPackage ? "connect" : await hasPendingWelcome(this.config.dataDir, groupId) ? "persisted" : "generated";
|
|
67153
67200
|
console.log(`[SecureChannel] Received MLS welcome for group ${groupId?.slice(0, 8)}${conversationId ? ` conv=${conversationId.slice(0, 8)}` : ""} kpSource=${kpSource}`);
|
|
67154
67201
|
try {
|
|
67155
67202
|
const welcomeBytes = new Uint8Array(Buffer.from(data.payload, "hex"));
|
|
67156
67203
|
const mgr = new MLSGroupManager();
|
|
67157
|
-
|
|
67158
|
-
|
|
67204
|
+
let kp = this._pendingMlsKpBundle ?? this._mlsKeyPackage;
|
|
67205
|
+
if (!kp) {
|
|
67206
|
+
const persisted = await loadPendingKpBundle(this.config.dataDir, groupId);
|
|
67207
|
+
if (persisted) {
|
|
67208
|
+
kp = {
|
|
67209
|
+
publicPackage: MLSGroupManager.deserializeKeyPackage(persisted.publicPackageBytes),
|
|
67210
|
+
privatePackage: persisted.privatePackage
|
|
67211
|
+
};
|
|
67212
|
+
console.log(`[SecureChannel] Loaded persisted KP bundle for group ${groupId?.slice(0, 8)}`);
|
|
67213
|
+
}
|
|
67214
|
+
}
|
|
67215
|
+
if (!kp) {
|
|
67159
67216
|
const identity = new TextEncoder().encode(this._deviceId);
|
|
67160
|
-
|
|
67161
|
-
}
|
|
67217
|
+
kp = await mgr.generateKeyPackage(identity);
|
|
67218
|
+
}
|
|
67162
67219
|
console.log(`[SecureChannel] Welcome joinFromWelcome: group=${groupId?.slice(0, 8)} kpSource=${kpSource} welcomeLen=${welcomeBytes.length}`);
|
|
67163
67220
|
await mgr.joinFromWelcome(welcomeBytes, kp);
|
|
67164
67221
|
if (conversationId) {
|
|
@@ -67194,6 +67251,8 @@ ${messageText}`;
|
|
|
67194
67251
|
await this._persistState();
|
|
67195
67252
|
await clearPendingWelcome(this.config.dataDir, groupId).catch(() => {
|
|
67196
67253
|
});
|
|
67254
|
+
await releaseA2ASyncLock(this.config.dataDir, channelId).catch(() => {
|
|
67255
|
+
});
|
|
67197
67256
|
this._pendingMlsKpBundle = void 0;
|
|
67198
67257
|
console.log(`[SecureChannel] Joined MLS group for A2A ${channelId.slice(0, 8)} via Welcome (epoch=${mgr.epoch})`);
|
|
67199
67258
|
if (this.config.onA2AChannelReady && entry.conversationId) {
|
|
@@ -67224,11 +67283,16 @@ ${messageText}`;
|
|
|
67224
67283
|
this._mlsGroups.set(`a2a:${a2aChannelId}`, mgr);
|
|
67225
67284
|
await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
|
|
67226
67285
|
await this._persistState();
|
|
67286
|
+
await releaseA2ASyncLock(this.config.dataDir, a2aChannelId).catch(() => {
|
|
67287
|
+
});
|
|
67227
67288
|
console.log(`[SecureChannel] Joined MLS group for A2A ${a2aChannelId.slice(0, 8)} via Welcome (new channel, epoch=${mgr.epoch})`);
|
|
67228
67289
|
return;
|
|
67229
67290
|
}
|
|
67230
67291
|
console.warn(`[SecureChannel] MLS welcome for unmatched group ${groupId?.slice(0, 8)} (no room/A2A/conv match)`);
|
|
67231
67292
|
} catch (err) {
|
|
67293
|
+
const failedA2aId = data.a2a_channel_id;
|
|
67294
|
+
if (failedA2aId) await releaseA2ASyncLock(this.config.dataDir, failedA2aId).catch(() => {
|
|
67295
|
+
});
|
|
67232
67296
|
console.error(`[SecureChannel] MLS welcome processing failed (kpSource=${kpSource}):`, err);
|
|
67233
67297
|
throw err;
|
|
67234
67298
|
}
|
|
@@ -94860,7 +94924,7 @@ var init_index = __esm({
|
|
|
94860
94924
|
init_skill_invoker();
|
|
94861
94925
|
await init_skill_telemetry();
|
|
94862
94926
|
await init_policy_enforcer();
|
|
94863
|
-
VERSION = true ? "0.20.
|
|
94927
|
+
VERSION = true ? "0.20.28" : "0.0.0-dev";
|
|
94864
94928
|
}
|
|
94865
94929
|
});
|
|
94866
94930
|
await init_index();
|