@agentvault/agentvault 0.20.27 → 0.20.29

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/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`;
@@ -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) continue;
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();
@@ -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
  }
@@ -65545,28 +65593,32 @@ var init_channel = __esm({
65545
65593
  this._telemetryReporter.startAutoFlush(3e4);
65546
65594
  }
65547
65595
  this.startTrustTokenRefresh();
65548
- try {
65549
- const mlsMgr = new MLSGroupManager();
65550
- const identity = new TextEncoder().encode(this._deviceId);
65551
- const kp = await mlsMgr.generateKeyPackage(identity);
65552
- this._mlsKeyPackage = kp;
65553
- const kpBytes = MLSGroupManager.serializeKeyPackage(kp.publicPackage);
65554
- const kpHex = Buffer.from(kpBytes).toString("hex");
65555
- await fetch(`${this.config.apiUrl}/api/v1/mls/key-packages`, {
65556
- method: "POST",
65557
- headers: {
65558
- Authorization: `Bearer ${this._deviceJwt}`,
65559
- "Content-Type": "application/json"
65560
- },
65561
- body: JSON.stringify({ key_package: kpHex })
65562
- });
65563
- console.log("[SecureChannel] MLS KeyPackage published");
65564
- } catch (kpErr) {
65565
- console.warn("[SecureChannel] Failed to publish MLS KeyPackage:", kpErr);
65566
- }
65567
- this.listA2AChannels().catch((err) => {
65596
+ await this.listA2AChannels().catch((err) => {
65568
65597
  console.warn("[SecureChannel] A2A channel sync on connect failed:", err);
65569
65598
  });
65599
+ if (!this._pendingMlsKpBundle) {
65600
+ try {
65601
+ const mlsMgr = new MLSGroupManager();
65602
+ const identity = new TextEncoder().encode(this._deviceId);
65603
+ const kp = await mlsMgr.generateKeyPackage(identity);
65604
+ this._mlsKeyPackage = kp;
65605
+ const kpBytes = MLSGroupManager.serializeKeyPackage(kp.publicPackage);
65606
+ const kpHex = Buffer.from(kpBytes).toString("hex");
65607
+ await fetch(`${this.config.apiUrl}/api/v1/mls/key-packages`, {
65608
+ method: "POST",
65609
+ headers: {
65610
+ Authorization: `Bearer ${this._deviceJwt}`,
65611
+ "Content-Type": "application/json"
65612
+ },
65613
+ body: JSON.stringify({ key_package: kpHex })
65614
+ });
65615
+ console.log("[SecureChannel] MLS KeyPackage published");
65616
+ } catch (kpErr) {
65617
+ console.warn("[SecureChannel] Failed to publish MLS KeyPackage:", kpErr);
65618
+ }
65619
+ } else {
65620
+ console.log("[SecureChannel] Skipping on-connect KP publish \u2014 A2A sync fallback KP pending");
65621
+ }
65570
65622
  this._pullDeliveryQueue().catch((err) => {
65571
65623
  console.warn("[SecureChannel] Initial delivery pull failed:", err);
65572
65624
  });
@@ -67203,6 +67255,8 @@ ${messageText}`;
67203
67255
  await this._persistState();
67204
67256
  await clearPendingWelcome(this.config.dataDir, groupId).catch(() => {
67205
67257
  });
67258
+ await releaseA2ASyncLock(this.config.dataDir, channelId).catch(() => {
67259
+ });
67206
67260
  this._pendingMlsKpBundle = void 0;
67207
67261
  console.log(`[SecureChannel] Joined MLS group for A2A ${channelId.slice(0, 8)} via Welcome (epoch=${mgr.epoch})`);
67208
67262
  if (this.config.onA2AChannelReady && entry.conversationId) {
@@ -67233,11 +67287,16 @@ ${messageText}`;
67233
67287
  this._mlsGroups.set(`a2a:${a2aChannelId}`, mgr);
67234
67288
  await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
67235
67289
  await this._persistState();
67290
+ await releaseA2ASyncLock(this.config.dataDir, a2aChannelId).catch(() => {
67291
+ });
67236
67292
  console.log(`[SecureChannel] Joined MLS group for A2A ${a2aChannelId.slice(0, 8)} via Welcome (new channel, epoch=${mgr.epoch})`);
67237
67293
  return;
67238
67294
  }
67239
67295
  console.warn(`[SecureChannel] MLS welcome for unmatched group ${groupId?.slice(0, 8)} (no room/A2A/conv match)`);
67240
67296
  } catch (err) {
67297
+ const failedA2aId = data.a2a_channel_id;
67298
+ if (failedA2aId) await releaseA2ASyncLock(this.config.dataDir, failedA2aId).catch(() => {
67299
+ });
67241
67300
  console.error(`[SecureChannel] MLS welcome processing failed (kpSource=${kpSource}):`, err);
67242
67301
  throw err;
67243
67302
  }
@@ -94869,7 +94928,7 @@ var init_index = __esm({
94869
94928
  init_skill_invoker();
94870
94929
  await init_skill_telemetry();
94871
94930
  await init_policy_enforcer();
94872
- VERSION = true ? "0.20.27" : "0.0.0-dev";
94931
+ VERSION = true ? "0.20.29" : "0.0.0-dev";
94873
94932
  }
94874
94933
  });
94875
94934
  await init_index();