@agentvault/agentvault 0.23.32 → 0.23.33

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
@@ -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.32" : FALLBACK;
63269
+ const v2 = true ? "0.23.33" : FALLBACK;
63270
63270
  return `${PACKAGE}@${v2}`;
63271
63271
  }
63272
63272
  function buildSha() {
63273
- const raw = true ? "9d4a053-dirty" : "";
63273
+ const raw = true ? "7b91f2f-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.32" : "0.0.0-dev";
65484
+ const pluginVersion = true ? "0.23.33" : "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.32" : "0.0.0-dev"
67422
+ pluginVersion: true ? "0.23.33" : "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.32" : "0.0.0-dev"
67746
+ pluginVersion: true ? "0.23.33" : "0.0.0-dev"
67744
67747
  });
67745
67748
  this._telemetryReporter.startAutoFlush(3e4);
67746
67749
  }
@@ -69429,13 +69432,7 @@ ${baseText}`;
69429
69432
  console.warn(`[SecureChannel] MLS epoch recovery for ${groupKey} (${mlsGroupId.slice(0, 8)})`);
69430
69433
  this._mlsGroups.delete(groupKey);
69431
69434
  this._mlsDecryptFailCounts.delete(groupKey);
69432
- try {
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
- }
69435
+ await deleteMlsState(this.config.dataDir, mlsGroupId);
69439
69436
  try {
69440
69437
  const mgr = new MLSGroupManager();
69441
69438
  const identity = new TextEncoder().encode(this._deviceId);
@@ -69510,19 +69507,26 @@ ${baseText}`;
69510
69507
  return 0;
69511
69508
  }
69512
69509
  const snapshot = mlsGroup.exportState();
69513
- const { commit, welcome } = await mlsGroup.addMembers(targets.map((t2) => t2.keyPackage));
69514
- const commitSent = await this._sendFrameConfirmed(
69515
- {
69516
- event: "mls_commit",
69517
- data: {
69518
- group_id: mlsGroupId,
69519
- epoch: Number(mlsGroup.epoch),
69520
- payload: Buffer.from(commit).toString("hex")
69521
- }
69522
- },
69523
- `${label} commit`
69524
- );
69525
- if (!commitSent) {
69510
+ const { commits, welcome } = await mlsGroup.reAdmitMembers(targets.map((t2) => t2.keyPackage));
69511
+ let sentCommits = 0;
69512
+ for (const c2 of commits) {
69513
+ const ok = await this._sendFrameConfirmed(
69514
+ {
69515
+ event: "mls_commit",
69516
+ data: {
69517
+ group_id: mlsGroupId,
69518
+ // The epoch this commit PRODUCED. After two commits the manager
69519
+ // only knows the last one, which is why the result carries them.
69520
+ epoch: Number(c2.epoch),
69521
+ payload: Buffer.from(c2.commit).toString("hex")
69522
+ }
69523
+ },
69524
+ `${label} commit ${sentCommits + 1}/${commits.length}`
69525
+ );
69526
+ if (!ok) break;
69527
+ sentCommits++;
69528
+ }
69529
+ if (sentCommits === 0) {
69526
69530
  mlsGroup.importState(snapshot);
69527
69531
  console.warn(
69528
69532
  `[SecureChannel] ${label}: commit was NOT written \u2014 rolled back to epoch ${Number(mlsGroup.epoch)}, nothing fulfilled, requests stay pending`
@@ -69530,6 +69534,12 @@ ${baseText}`;
69530
69534
  return 0;
69531
69535
  }
69532
69536
  await saveMlsState(this.config.dataDir, mlsGroupId, JSON.stringify(mlsGroup.exportState()));
69537
+ if (sentCommits < commits.length) {
69538
+ console.warn(
69539
+ `[SecureChannel] ${label}: only ${sentCommits}/${commits.length} commits reached the wire \u2014 requests stay PENDING for the next pull`
69540
+ );
69541
+ return 0;
69542
+ }
69533
69543
  if (!welcome) {
69534
69544
  console.warn(
69535
69545
  `[SecureChannel] ${label}: addMembers produced NO Welcome \u2014 ${targets.length} request(s) left pending rather than marked fulfilled`
@@ -70258,38 +70268,63 @@ ${baseText}`;
70258
70268
  { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
70259
70269
  );
70260
70270
  if (!pendingRes.ok) continue;
70261
- const pending = await pendingRes.json();
70271
+ let pending = await pendingRes.json();
70262
70272
  if (pending.length === 0) continue;
70263
70273
  console.log(`[SecureChannel] ${pending.length} pending Welcome requests for room ${roomId.slice(0, 8)}`);
70274
+ const nowMs = Date.now();
70275
+ const fresh = pending.filter((r2) => {
70276
+ const key = `${roomState.mlsGroupId}:${r2.requesting_device_id}`;
70277
+ const last = this._roomFulfilCooldown.get(key) ?? 0;
70278
+ if (nowMs - last < ROOM_FULFIL_COOLDOWN_MS) {
70279
+ console.log(
70280
+ `[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`
70281
+ );
70282
+ return false;
70283
+ }
70284
+ return true;
70285
+ });
70286
+ if (fresh.length === 0) continue;
70287
+ for (const r2 of fresh) {
70288
+ this._roomFulfilCooldown.set(`${roomState.mlsGroupId}:${r2.requesting_device_id}`, nowMs);
70289
+ }
70290
+ pending = fresh;
70291
+ const deviceIds = pending.map((r2) => r2.requesting_device_id);
70292
+ const kpRes = await fetch(
70293
+ `${this.config.apiUrl}/api/v1/mls/key-packages/batch?device_ids=${deviceIds.join(",")}`,
70294
+ { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
70295
+ );
70296
+ if (!kpRes.ok) continue;
70297
+ const kpData = await kpRes.json();
70298
+ const roomTargets = [];
70264
70299
  for (const req of pending) {
70265
- try {
70266
- const kpRes = await fetch(
70267
- `${this.config.apiUrl}/api/v1/mls/key-packages/batch?device_ids=${req.requesting_device_id}`,
70268
- { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
70300
+ const kpHex = kpData[req.requesting_device_id];
70301
+ if (!kpHex) {
70302
+ console.warn(`[SecureChannel] No KeyPackage for ${req.requesting_device_id.slice(0, 8)}, skipping`);
70303
+ continue;
70304
+ }
70305
+ const kpBytes = new Uint8Array(Buffer.from(kpHex, "hex"));
70306
+ roomTargets.push({
70307
+ requestId: req.id,
70308
+ deviceId: req.requesting_device_id,
70309
+ keyPackage: MLSGroupManager.deserializeKeyPackage(kpBytes)
70310
+ });
70311
+ }
70312
+ if (roomTargets.length === 0) continue;
70313
+ try {
70314
+ const done = await this._fulfilWelcomeRequests({
70315
+ mlsGroup,
70316
+ mlsGroupId: roomState.mlsGroupId,
70317
+ label: `room ${roomId.slice(0, 8)}`,
70318
+ welcomeFields: { room_id: roomId },
70319
+ targets: roomTargets
70320
+ });
70321
+ if (done > 0) {
70322
+ console.log(
70323
+ `[SecureChannel] Batched Welcome for ${done}/${roomTargets.length} device(s) in room ${roomId.slice(0, 8)} (epoch=${mlsGroup.epoch})`
70269
70324
  );
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
70325
  }
70326
+ } catch (fulfillErr) {
70327
+ console.warn(`[SecureChannel] Batched Welcome failed for room ${roomId.slice(0, 8)}:`, fulfillErr);
70293
70328
  }
70294
70329
  } catch {
70295
70330
  }
@@ -98550,7 +98585,7 @@ var init_index = __esm({
98550
98585
  await init_skill_telemetry();
98551
98586
  await init_policy_enforcer();
98552
98587
  init_room_protocol();
98553
- VERSION = true ? "0.23.32" : "0.0.0-dev";
98588
+ VERSION = true ? "0.23.33" : "0.0.0-dev";
98554
98589
  }
98555
98590
  });
98556
98591
  await init_index();