@agentvault/agentvault 0.20.0 → 0.20.2

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
@@ -65125,6 +65125,19 @@ var init_channel = __esm({
65125
65125
  }
65126
65126
  }
65127
65127
  await this._persistState();
65128
+ for (const [chId, chState] of Object.entries(this._persisted?.a2aChannels ?? {})) {
65129
+ if (chState.role === "creator" && !chState.mlsGroupId && chState.participants.some((p2) => p2.status === "active")) {
65130
+ const activeParticipants = chState.participants.filter((p2) => p2.status === "active");
65131
+ if (activeParticipants.length >= 1) {
65132
+ console.log(`[AgentVault] Sync fallback: founding MLS group for channel ${chId.slice(0, 8)}`);
65133
+ try {
65134
+ await this._foundA2AGroup(chId, chState.conversationId, activeParticipants);
65135
+ } catch (err) {
65136
+ console.warn(`[AgentVault] Sync fallback MLS founding failed for ${chId.slice(0, 8)}:`, err);
65137
+ }
65138
+ }
65139
+ }
65140
+ }
65128
65141
  }
65129
65142
  return channels;
65130
65143
  }
@@ -65739,108 +65752,33 @@ var init_channel = __esm({
65739
65752
  this.emit("a2a_channel_approved", channelData);
65740
65753
  if (this._persisted && convId && channelId && role === "creator") {
65741
65754
  try {
65742
- const mlsInitRes = await fetch(
65743
- `${this.config.apiUrl}/api/v1/mls/a2a/${channelId}/init`,
65744
- {
65745
- method: "POST",
65746
- headers: {
65747
- Authorization: `Bearer ${this._deviceJwt}`,
65748
- "Content-Type": "application/json"
65749
- },
65750
- body: JSON.stringify({ member_device_ids: [] })
65751
- }
65752
- );
65753
- if (mlsInitRes.ok) {
65754
- const mlsData = await mlsInitRes.json();
65755
- const entry = this._persisted.a2aChannels?.[channelId];
65756
- if (entry) {
65757
- entry.mlsGroupId = mlsData.group_id;
65758
- await this._persistState();
65759
- console.log(
65760
- `[SecureChannel] A2A ${channelId.slice(0, 8)} MLS group founded as creator (groupId=${mlsData.group_id.slice(0, 8)})`
65761
- );
65762
- try {
65763
- const mgr = new MLSGroupManager();
65764
- const identity = new TextEncoder().encode(this._persisted.deviceId);
65765
- const creatorKp = await mgr.generateKeyPackage(identity);
65766
- const groupIdBytes = new TextEncoder().encode(mlsData.group_id);
65767
- await mgr.createGroup(groupIdBytes, creatorKp);
65768
- this._mlsGroups.set(`a2a:${channelId}`, mgr);
65769
- await saveMlsState(this.config.dataDir, mlsData.group_id, JSON.stringify(mgr.exportState()));
65770
- for (const p2 of entry.participants ?? []) {
65771
- if (p2.status !== "active" && p2.status !== "invited") continue;
65772
- try {
65773
- const kpRes = await fetch(
65774
- `${this.config.apiUrl}/api/v1/mls/key-packages?hub_id=${encodeURIComponent(p2.hubId)}`,
65775
- { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
65776
- );
65777
- if (kpRes.ok) {
65778
- const kpData = await kpRes.json();
65779
- if (kpData.key_package) {
65780
- const kpBytes = new Uint8Array(Buffer.from(kpData.key_package, "hex"));
65781
- const memberKp = MLSGroupManager.deserializeKeyPackage(kpBytes);
65782
- const { commit, welcome } = await mgr.addMembers([memberKp]);
65783
- if (welcome && this._ws) {
65784
- this._ws.send(JSON.stringify({
65785
- event: "mls_commit",
65786
- data: {
65787
- group_id: mlsData.group_id,
65788
- epoch: Number(mgr.epoch),
65789
- payload: Buffer.from(commit).toString("hex")
65790
- }
65791
- }));
65792
- this._ws.send(JSON.stringify({
65793
- event: "mls_welcome",
65794
- data: {
65795
- group_id: mlsData.group_id,
65796
- welcome: Buffer.from(welcome).toString("hex"),
65797
- target_hub_id: p2.hubId,
65798
- a2a_channel_id: channelId
65799
- }
65800
- }));
65801
- console.log(`[SecureChannel] Sent MLS Welcome to ${p2.hubAddress} for A2A ${channelId.slice(0, 8)}`);
65802
- }
65803
- await saveMlsState(this.config.dataDir, mlsData.group_id, JSON.stringify(mgr.exportState()));
65804
- }
65805
- }
65806
- } catch (kpErr) {
65807
- console.warn(`[SecureChannel] Failed to Welcome participant ${p2.hubAddress}:`, kpErr);
65808
- }
65809
- }
65810
- } catch (mlsErr) {
65811
- console.warn(`[SecureChannel] MLS group creation failed:`, mlsErr);
65812
- }
65813
- }
65814
- }
65755
+ await this._foundA2AGroup(channelId, convId, this._persisted.a2aChannels?.[channelId]?.participants ?? []);
65815
65756
  } catch (err) {
65816
65757
  console.warn(`[SecureChannel] A2A MLS init failed (non-fatal):`, err);
65817
65758
  }
65818
65759
  } else if (this._persisted && convId && channelId && role === "member") {
65819
65760
  try {
65820
- const mlsInitRes = await fetch(
65821
- `${this.config.apiUrl}/api/v1/mls/a2a/${channelId}/init`,
65822
- {
65823
- method: "POST",
65824
- headers: {
65825
- Authorization: `Bearer ${this._deviceJwt}`,
65826
- "Content-Type": "application/json"
65827
- },
65828
- body: JSON.stringify({ member_device_ids: [] })
65829
- }
65761
+ const mgr = new MLSGroupManager();
65762
+ const identity = new TextEncoder().encode(this._persisted.deviceId);
65763
+ const kp = await mgr.generateKeyPackage(identity);
65764
+ this._pendingMlsKpBundle = kp;
65765
+ const kpBytes = MLSGroupManager.serializeKeyPackage(kp.publicPackage);
65766
+ await fetch(`${this.config.apiUrl}/api/v1/mls/key-packages`, {
65767
+ method: "POST",
65768
+ headers: {
65769
+ Authorization: `Bearer ${this._deviceJwt}`,
65770
+ "Content-Type": "application/json"
65771
+ },
65772
+ body: JSON.stringify({
65773
+ key_package: Buffer.from(kpBytes).toString("hex"),
65774
+ device_id: this._persisted.deviceId
65775
+ })
65776
+ });
65777
+ console.log(
65778
+ `[SecureChannel] A2A ${channelId.slice(0, 8)} member published KeyPackage, awaiting Welcome from creator`
65830
65779
  );
65831
- if (mlsInitRes.ok) {
65832
- const mlsData = await mlsInitRes.json();
65833
- const entry = this._persisted.a2aChannels?.[channelId];
65834
- if (entry) {
65835
- entry.mlsGroupId = mlsData.group_id;
65836
- await this._persistState();
65837
- console.log(
65838
- `[SecureChannel] A2A ${channelId.slice(0, 8)} MLS registered as member (groupId=${mlsData.group_id.slice(0, 8)}, awaiting Welcome)`
65839
- );
65840
- }
65841
- }
65842
65780
  } catch (err) {
65843
- console.warn(`[SecureChannel] A2A MLS init failed (non-fatal):`, err);
65781
+ console.warn(`[SecureChannel] A2A member KeyPackage publish failed (non-fatal):`, err);
65844
65782
  }
65845
65783
  }
65846
65784
  }
@@ -67330,6 +67268,90 @@ ${messageText}`;
67330
67268
  console.error(`[SecureChannel] MLS A2A decrypt failed for ${a2aChannelId.slice(0, 8)}:`, err);
67331
67269
  }
67332
67270
  }
67271
+ /**
67272
+ * Found the MLS group for an A2A channel as the creator agent.
67273
+ * Calls /mls/a2a/{channelId}/init, creates the local MLS group, and sends
67274
+ * Welcome messages to all active/invited participants.
67275
+ * Extracted from the a2a_channel_approved WS handler so it can also be called
67276
+ * from the sync fallback in listA2AChannels.
67277
+ */
67278
+ async _foundA2AGroup(channelId, convId, participants) {
67279
+ if (!this._persisted || !this._deviceJwt) return;
67280
+ const mlsInitRes = await fetch(
67281
+ `${this.config.apiUrl}/api/v1/mls/a2a/${channelId}/init`,
67282
+ {
67283
+ method: "POST",
67284
+ headers: {
67285
+ Authorization: `Bearer ${this._deviceJwt}`,
67286
+ "Content-Type": "application/json"
67287
+ },
67288
+ body: JSON.stringify({ member_device_ids: [] })
67289
+ }
67290
+ );
67291
+ if (!mlsInitRes.ok) {
67292
+ const detail = await mlsInitRes.text();
67293
+ throw new Error(`MLS A2A init failed (${mlsInitRes.status}): ${detail}`);
67294
+ }
67295
+ const mlsData = await mlsInitRes.json();
67296
+ const entry = this._persisted.a2aChannels?.[channelId];
67297
+ if (!entry) return;
67298
+ entry.mlsGroupId = mlsData.group_id;
67299
+ await this._persistState();
67300
+ console.log(
67301
+ `[SecureChannel] A2A ${channelId.slice(0, 8)} MLS group founded as creator (groupId=${mlsData.group_id.slice(0, 8)})`
67302
+ );
67303
+ try {
67304
+ const mgr = new MLSGroupManager();
67305
+ const identity = new TextEncoder().encode(this._persisted.deviceId);
67306
+ const creatorKp = await mgr.generateKeyPackage(identity);
67307
+ const groupIdBytes = new TextEncoder().encode(mlsData.group_id);
67308
+ await mgr.createGroup(groupIdBytes, creatorKp);
67309
+ this._mlsGroups.set(`a2a:${channelId}`, mgr);
67310
+ await saveMlsState(this.config.dataDir, mlsData.group_id, JSON.stringify(mgr.exportState()));
67311
+ for (const p2 of participants) {
67312
+ if (p2.status !== "active" && p2.status !== "invited") continue;
67313
+ try {
67314
+ const kpRes = await fetch(
67315
+ `${this.config.apiUrl}/api/v1/mls/key-packages?hub_id=${encodeURIComponent(p2.hubId)}`,
67316
+ { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
67317
+ );
67318
+ if (kpRes.ok) {
67319
+ const kpData = await kpRes.json();
67320
+ if (kpData.key_package) {
67321
+ const kpBytes = new Uint8Array(Buffer.from(kpData.key_package, "hex"));
67322
+ const memberKp = MLSGroupManager.deserializeKeyPackage(kpBytes);
67323
+ const { commit, welcome } = await mgr.addMembers([memberKp]);
67324
+ if (welcome && this._ws) {
67325
+ this._ws.send(JSON.stringify({
67326
+ event: "mls_commit",
67327
+ data: {
67328
+ group_id: mlsData.group_id,
67329
+ epoch: Number(mgr.epoch),
67330
+ payload: Buffer.from(commit).toString("hex")
67331
+ }
67332
+ }));
67333
+ this._ws.send(JSON.stringify({
67334
+ event: "mls_welcome",
67335
+ data: {
67336
+ group_id: mlsData.group_id,
67337
+ welcome: Buffer.from(welcome).toString("hex"),
67338
+ target_hub_id: p2.hubId,
67339
+ a2a_channel_id: channelId
67340
+ }
67341
+ }));
67342
+ console.log(`[SecureChannel] Sent MLS Welcome to ${p2.hubAddress} for A2A ${channelId.slice(0, 8)}`);
67343
+ }
67344
+ await saveMlsState(this.config.dataDir, mlsData.group_id, JSON.stringify(mgr.exportState()));
67345
+ }
67346
+ }
67347
+ } catch (kpErr) {
67348
+ console.warn(`[SecureChannel] Failed to Welcome participant ${p2.hubAddress}:`, kpErr);
67349
+ }
67350
+ }
67351
+ } catch (mlsErr) {
67352
+ console.warn(`[SecureChannel] MLS group creation failed:`, mlsErr);
67353
+ }
67354
+ }
67333
67355
  /**
67334
67356
  * Paginated sync: fetch missed messages in pages of 200, up to 5 pages (1000 messages).
67335
67357
  * Tracks message IDs in _syncMessageIds to prevent duplicate processing from concurrent WS messages.
@@ -94409,7 +94431,7 @@ var init_index = __esm({
94409
94431
  init_skill_invoker();
94410
94432
  await init_skill_telemetry();
94411
94433
  await init_policy_enforcer();
94412
- VERSION = true ? "0.20.0" : "0.0.0-dev";
94434
+ VERSION = true ? "0.20.2" : "0.0.0-dev";
94413
94435
  }
94414
94436
  });
94415
94437
  await init_index();