@agentvault/agentvault 0.20.31 → 0.20.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.
Files changed (66) hide show
  1. package/dist/cli.js +227 -3
  2. package/dist/cli.js.map +2 -2
  3. package/dist/index.js +227 -3
  4. package/dist/index.js.map +2 -2
  5. package/openclaw.plugin.json +1 -1
  6. package/package.json +1 -1
  7. package/dist/_cp.d.ts +0 -10
  8. package/dist/_cp.d.ts.map +0 -1
  9. package/dist/account-config.d.ts +0 -20
  10. package/dist/account-config.d.ts.map +0 -1
  11. package/dist/channel.d.ts +0 -418
  12. package/dist/channel.d.ts.map +0 -1
  13. package/dist/cli.d.ts +0 -2
  14. package/dist/cli.d.ts.map +0 -1
  15. package/dist/create-agent.d.ts +0 -28
  16. package/dist/create-agent.d.ts.map +0 -1
  17. package/dist/credential-store.d.ts +0 -62
  18. package/dist/credential-store.d.ts.map +0 -1
  19. package/dist/crypto-helpers.d.ts +0 -2
  20. package/dist/crypto-helpers.d.ts.map +0 -1
  21. package/dist/doctor.d.ts +0 -41
  22. package/dist/doctor.d.ts.map +0 -1
  23. package/dist/fetch-interceptor.d.ts +0 -32
  24. package/dist/fetch-interceptor.d.ts.map +0 -1
  25. package/dist/gateway-send.d.ts +0 -98
  26. package/dist/gateway-send.d.ts.map +0 -1
  27. package/dist/http-handlers.d.ts +0 -53
  28. package/dist/http-handlers.d.ts.map +0 -1
  29. package/dist/index.d.ts +0 -27
  30. package/dist/index.d.ts.map +0 -1
  31. package/dist/mcp-handlers.d.ts +0 -26
  32. package/dist/mcp-handlers.d.ts.map +0 -1
  33. package/dist/mcp-proxy-helpers.d.ts +0 -9
  34. package/dist/mcp-proxy-helpers.d.ts.map +0 -1
  35. package/dist/mcp-server.d.ts +0 -91
  36. package/dist/mcp-server.d.ts.map +0 -1
  37. package/dist/mls-state.d.ts +0 -54
  38. package/dist/mls-state.d.ts.map +0 -1
  39. package/dist/openclaw-compat.d.ts +0 -33
  40. package/dist/openclaw-compat.d.ts.map +0 -1
  41. package/dist/openclaw-entry.d.ts +0 -32
  42. package/dist/openclaw-entry.d.ts.map +0 -1
  43. package/dist/openclaw-plugin.d.ts +0 -102
  44. package/dist/openclaw-plugin.d.ts.map +0 -1
  45. package/dist/openclaw-types.d.ts +0 -186
  46. package/dist/openclaw-types.d.ts.map +0 -1
  47. package/dist/policy-enforcer.d.ts +0 -78
  48. package/dist/policy-enforcer.d.ts.map +0 -1
  49. package/dist/setup.d.ts +0 -27
  50. package/dist/setup.d.ts.map +0 -1
  51. package/dist/skill-invoker.d.ts +0 -30
  52. package/dist/skill-invoker.d.ts.map +0 -1
  53. package/dist/skill-manifest.d.ts +0 -30
  54. package/dist/skill-manifest.d.ts.map +0 -1
  55. package/dist/skill-telemetry.d.ts +0 -36
  56. package/dist/skill-telemetry.d.ts.map +0 -1
  57. package/dist/skills-publish.d.ts +0 -8
  58. package/dist/skills-publish.d.ts.map +0 -1
  59. package/dist/state.d.ts +0 -32
  60. package/dist/state.d.ts.map +0 -1
  61. package/dist/transport.d.ts +0 -24
  62. package/dist/transport.d.ts.map +0 -1
  63. package/dist/types.d.ts +0 -454
  64. package/dist/types.d.ts.map +0 -1
  65. package/dist/workspace-handlers.d.ts +0 -62
  66. package/dist/workspace-handlers.d.ts.map +0 -1
package/dist/cli.js CHANGED
@@ -63715,12 +63715,15 @@ var init_channel = __esm({
63715
63715
  _syncMessageIds = null;
63716
63716
  _deliveryHeartbeat = null;
63717
63717
  _deliveryPulling = false;
63718
+ _drDeliveryPulling = false;
63718
63719
  /** MLS group managers per room/conversation (roomId or conv:conversationId -> MLSGroupManager) */
63719
63720
  _mlsGroups = /* @__PURE__ */ new Map();
63720
63721
  /** Cached MLS KeyPackage bundle for this device (regenerated on each connect). */
63721
63722
  _mlsKeyPackage = null;
63722
63723
  /** Pending KeyPackage bundle from request-Welcome flow (used by _handleMlsWelcome). */
63723
63724
  _pendingMlsKpBundle;
63725
+ /** Buffer for MLS commits received before Welcome (keyed by groupId, sorted by epoch). */
63726
+ _pendingMlsCommits = /* @__PURE__ */ new Map();
63724
63727
  /** In-memory credential store for renter-provided credentials (never persisted). */
63725
63728
  _credentialStore = new CredentialStore();
63726
63729
  /** Dedup buffer for A2A message IDs (prevents double-delivery via direct + Redis) */
@@ -65596,6 +65599,7 @@ var init_channel = __esm({
65596
65599
  this._startWakeDetector();
65597
65600
  this._startPendingPoll();
65598
65601
  await this._syncMissedMessages();
65602
+ await this._pullDrDeliveryQueue();
65599
65603
  await this._flushOutboundQueue();
65600
65604
  this._setState("ready");
65601
65605
  if (this.config.enableScanning) {
@@ -65825,6 +65829,11 @@ var init_channel = __esm({
65825
65829
  console.warn("[SecureChannel] Delivery pull on ping failed:", err);
65826
65830
  });
65827
65831
  }
65832
+ if (data.event === "dr_delivery") {
65833
+ this._pullDrDeliveryQueue().catch((err) => {
65834
+ console.warn("[SecureChannel] DR delivery pull on ping failed:", err);
65835
+ });
65836
+ }
65828
65837
  if (data.event === "mls_welcome_requested") {
65829
65838
  console.log(`[SecureChannel] mls_welcome_requested for group ${(data.data?.group_id || "").slice(0, 8)} \u2014 pulling deliveries`);
65830
65839
  this._pullDeliveryQueue().catch((err) => {
@@ -67030,6 +67039,11 @@ ${messageText}`;
67030
67039
  console.log(`[SecureChannel] MLS decrypt attempt room=${resolvedRoomId.slice(0, 8)} group=${groupId?.slice(0, 8)} loaded=${!!mlsGroup} init=${mlsGroup?.isInitialized} mlsGroupsKeys=[${Array.from(this._mlsGroups.keys()).join(",")}]`);
67031
67040
  if (!mlsGroup?.isInitialized) {
67032
67041
  console.warn(`[SecureChannel] MLS group not loaded for room ${resolvedRoomId.slice(0, 8)}, requesting Welcome`);
67042
+ const roomLockId = `room-kp-${groupId}`;
67043
+ if (!await acquireA2ASyncLock(this.config.dataDir, roomLockId)) {
67044
+ console.log(`[SecureChannel] Room KP publish locked for group ${groupId?.slice(0, 8)}, skipping`);
67045
+ return;
67046
+ }
67033
67047
  try {
67034
67048
  const { MLSGroupManager: MLS } = await init_dist().then(() => dist_exports);
67035
67049
  const mgr = new MLS();
@@ -67042,6 +67056,7 @@ ${messageText}`;
67042
67056
  body: JSON.stringify({ key_package: kpHex, device_id: this._deviceId })
67043
67057
  });
67044
67058
  this._pendingMlsKpBundle = kp;
67059
+ await savePendingKpBundle(this.config.dataDir, groupId, kp);
67045
67060
  await fetch(`${this.config.apiUrl}/api/v1/mls/groups/${groupId}/request-welcome`, {
67046
67061
  method: "POST",
67047
67062
  headers: { Authorization: `Bearer ${this._deviceJwt}`, "Content-Type": "application/json" },
@@ -67050,6 +67065,8 @@ ${messageText}`;
67050
67065
  console.log(`[SecureChannel] Welcome requested for room ${resolvedRoomId.slice(0, 8)} group ${groupId?.slice(0, 8)}`);
67051
67066
  } catch (reqErr) {
67052
67067
  console.warn(`[SecureChannel] Welcome request failed for room ${resolvedRoomId.slice(0, 8)}:`, reqErr);
67068
+ await releaseA2ASyncLock(this.config.dataDir, roomLockId).catch(() => {
67069
+ });
67053
67070
  }
67054
67071
  return;
67055
67072
  }
@@ -67182,6 +67199,7 @@ ${messageText}`;
67182
67199
  }
67183
67200
  async _handleMlsCommit(data) {
67184
67201
  const groupId = data.group_id;
67202
+ const epoch = typeof data.epoch === "number" ? data.epoch : 0;
67185
67203
  for (const [roomId, room] of Object.entries(this._persisted?.rooms ?? {})) {
67186
67204
  if (room.mlsGroupId === groupId) {
67187
67205
  const mlsGroup = this._mlsGroups.get(roomId);
@@ -67200,6 +67218,9 @@ ${messageText}`;
67200
67218
  throw err;
67201
67219
  }
67202
67220
  }
67221
+ } else {
67222
+ this._bufferMlsCommit(groupId, epoch, data);
67223
+ console.log(`[SecureChannel] Buffered MLS commit for room ${roomId.slice(0, 8)} (epoch=${epoch}, group not initialized)`);
67203
67224
  }
67204
67225
  return;
67205
67226
  }
@@ -67222,11 +67243,50 @@ ${messageText}`;
67222
67243
  throw err;
67223
67244
  }
67224
67245
  }
67246
+ } else {
67247
+ this._bufferMlsCommit(groupId, epoch, data);
67248
+ console.log(`[SecureChannel] Buffered MLS commit for A2A ${chId.slice(0, 8)} (epoch=${epoch}, group not initialized)`);
67225
67249
  }
67226
67250
  return;
67227
67251
  }
67228
67252
  }
67229
67253
  }
67254
+ /** Buffer an MLS commit for replay after Welcome join. Max 50 per group. */
67255
+ _bufferMlsCommit(groupId, epoch, data) {
67256
+ let buf = this._pendingMlsCommits.get(groupId);
67257
+ if (!buf) {
67258
+ buf = [];
67259
+ this._pendingMlsCommits.set(groupId, buf);
67260
+ }
67261
+ if (!buf.some((c2) => c2.epoch === epoch)) {
67262
+ buf.push({ epoch, data });
67263
+ buf.sort((a2, b2) => a2.epoch - b2.epoch);
67264
+ if (buf.length > 50) buf.splice(0, buf.length - 50);
67265
+ }
67266
+ }
67267
+ /** Apply buffered MLS commits after Welcome join. */
67268
+ async _applyBufferedMlsCommits(groupId, mgr) {
67269
+ const buf = this._pendingMlsCommits.get(groupId);
67270
+ if (!buf || buf.length === 0) return;
67271
+ console.log(`[SecureChannel] Applying ${buf.length} buffered MLS commits for group ${groupId.slice(0, 8)}`);
67272
+ let applied = 0;
67273
+ for (const entry of buf) {
67274
+ if (entry.epoch <= mgr.epoch) continue;
67275
+ try {
67276
+ const commitBytes = new Uint8Array(Buffer.from(entry.data.payload, "hex"));
67277
+ await mgr.processCommit(commitBytes);
67278
+ applied++;
67279
+ } catch (err) {
67280
+ console.warn(`[SecureChannel] Buffered commit epoch=${entry.epoch} failed: ${err?.message}`);
67281
+ break;
67282
+ }
67283
+ }
67284
+ this._pendingMlsCommits.delete(groupId);
67285
+ if (applied > 0) {
67286
+ await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
67287
+ console.log(`[SecureChannel] Applied ${applied} buffered commits, now epoch=${mgr.epoch}`);
67288
+ }
67289
+ }
67230
67290
  async _handleMlsWelcome(data) {
67231
67291
  const groupId = data.group_id;
67232
67292
  const conversationId = data.conversation_id;
@@ -67247,8 +67307,8 @@ ${messageText}`;
67247
67307
  }
67248
67308
  }
67249
67309
  if (!kp) {
67250
- const identity = new TextEncoder().encode(this._deviceId);
67251
- kp = await mgr.generateKeyPackage(identity);
67310
+ console.error(`[SecureChannel] No matching KeyPackage found for Welcome \u2014 cannot join group ${groupId?.slice(0, 8)}. A fresh KP would fail because the Welcome is encrypted to the published KP's public key. The existing Welcome recovery mechanism will re-request.`);
67311
+ return;
67252
67312
  }
67253
67313
  console.log(`[SecureChannel] Welcome joinFromWelcome: group=${groupId?.slice(0, 8)} kpSource=${kpSource} welcomeLen=${welcomeBytes.length}`);
67254
67314
  await mgr.joinFromWelcome(welcomeBytes, kp);
@@ -67256,6 +67316,7 @@ ${messageText}`;
67256
67316
  const key = `conv:${conversationId}`;
67257
67317
  this._mlsGroups.set(key, mgr);
67258
67318
  await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
67319
+ await this._applyBufferedMlsCommits(groupId, mgr);
67259
67320
  if (this._persisted) {
67260
67321
  if (!this._persisted.mlsConversations) this._persisted.mlsConversations = {};
67261
67322
  this._persisted.mlsConversations[conversationId] = { mlsGroupId: groupId };
@@ -67271,8 +67332,11 @@ ${messageText}`;
67271
67332
  this._mlsGroups.set(roomId, mgr);
67272
67333
  await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
67273
67334
  await this._persistState();
67335
+ await this._applyBufferedMlsCommits(groupId, mgr);
67274
67336
  console.log(`[SecureChannel] Joined MLS group for room ${roomId.slice(0, 8)} via Welcome (epoch=${mgr.epoch})`);
67275
67337
  this._pendingMlsKpBundle = void 0;
67338
+ await releaseA2ASyncLock(this.config.dataDir, `room-kp-${groupId}`).catch(() => {
67339
+ });
67276
67340
  return;
67277
67341
  }
67278
67342
  }
@@ -67283,6 +67347,7 @@ ${messageText}`;
67283
67347
  this._mlsGroups.set(`a2a:${channelId}`, mgr);
67284
67348
  await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
67285
67349
  await this._persistState();
67350
+ await this._applyBufferedMlsCommits(groupId, mgr);
67286
67351
  await clearPendingWelcome(this.config.dataDir, groupId).catch(() => {
67287
67352
  });
67288
67353
  await releaseA2ASyncLock(this.config.dataDir, channelId).catch(() => {
@@ -67706,6 +67771,165 @@ ${messageText}`;
67706
67771
  this._deliveryPulling = false;
67707
67772
  }
67708
67773
  }
67774
+ /**
67775
+ * Pull pending DR (Double Ratchet) messages from the delivery queue.
67776
+ * Signal-model queue-first: called on WS connect and on dr_delivery ping.
67777
+ */
67778
+ async _pullDrDeliveryQueue() {
67779
+ if (!this._deviceId || !this._deviceJwt || this._drDeliveryPulling) return;
67780
+ this._drDeliveryPulling = true;
67781
+ try {
67782
+ const res = await fetch(
67783
+ `${this.config.apiUrl}/api/v1/dr/delivery?device_id=${this._deviceId}`,
67784
+ { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
67785
+ );
67786
+ if (!res.ok) {
67787
+ console.warn(`[SecureChannel] DR delivery pull failed: ${res.status}`);
67788
+ return;
67789
+ }
67790
+ const { messages } = await res.json();
67791
+ if (!messages || messages.length === 0) return;
67792
+ const ackedIds = [];
67793
+ const nackedIds = [];
67794
+ for (const msg of messages) {
67795
+ try {
67796
+ if (msg.sender_device_id === this._deviceId) {
67797
+ ackedIds.push(msg.queue_id);
67798
+ continue;
67799
+ }
67800
+ if (msg.message_id && this._seenMessageIds.has(msg.message_id)) {
67801
+ ackedIds.push(msg.queue_id);
67802
+ continue;
67803
+ }
67804
+ let isRoom = false;
67805
+ if (this._persisted?.rooms) {
67806
+ for (const room of Object.values(this._persisted.rooms)) {
67807
+ if (room.conversationIds?.includes(msg.conversation_id)) {
67808
+ isRoom = true;
67809
+ break;
67810
+ }
67811
+ }
67812
+ }
67813
+ if (isRoom) {
67814
+ ackedIds.push(msg.queue_id);
67815
+ continue;
67816
+ }
67817
+ if (!msg.header_blob || !msg.ciphertext) {
67818
+ ackedIds.push(msg.queue_id);
67819
+ continue;
67820
+ }
67821
+ const session = this._sessions.get(msg.conversation_id);
67822
+ if (!session) {
67823
+ console.warn(`[SecureChannel] DR delivery: no session for conv ${msg.conversation_id.slice(0, 8)}, skipping`);
67824
+ continue;
67825
+ }
67826
+ const encrypted = transportToEncryptedMessage({
67827
+ header_blob: msg.header_blob,
67828
+ ciphertext: msg.ciphertext
67829
+ });
67830
+ const ratchetSnapshot = session.ratchet.serialize();
67831
+ let plaintext;
67832
+ try {
67833
+ plaintext = session.ratchet.decrypt(encrypted);
67834
+ } catch (decryptErr) {
67835
+ console.error(`[SecureChannel] DR delivery decrypt failed for conv ${msg.conversation_id.slice(0, 8)} \u2014 restoring ratchet:`, decryptErr);
67836
+ try {
67837
+ session.ratchet = DoubleRatchet.deserialize(ratchetSnapshot);
67838
+ } catch {
67839
+ }
67840
+ nackedIds.push(msg.queue_id);
67841
+ continue;
67842
+ }
67843
+ if (msg.message_id) {
67844
+ this._seenMessageIds.add(msg.message_id);
67845
+ if (this._seenMessageIds.size > _SecureChannel.SEEN_MSG_MAX) {
67846
+ const first = this._seenMessageIds.values().next().value;
67847
+ if (first) this._seenMessageIds.delete(first);
67848
+ }
67849
+ }
67850
+ this._sendAck(msg.message_id);
67851
+ if (!session.activated) {
67852
+ session.activated = true;
67853
+ console.log(`[SecureChannel] Session ${msg.conversation_id.slice(0, 8)}... activated via DR delivery`);
67854
+ if (this._persisted?.sessions[msg.conversation_id]) {
67855
+ this._persisted.sessions[msg.conversation_id].activated = true;
67856
+ }
67857
+ this._activateSiblings(msg.conversation_id);
67858
+ await this._persistState();
67859
+ }
67860
+ let messageText;
67861
+ let messageType;
67862
+ try {
67863
+ const parsed = JSON.parse(plaintext);
67864
+ messageType = parsed.type || "message";
67865
+ messageText = parsed.text || plaintext;
67866
+ } catch {
67867
+ messageType = "message";
67868
+ messageText = plaintext;
67869
+ }
67870
+ if (messageType === "session_init") {
67871
+ console.log(`[SecureChannel] session_init received via DR delivery for ${msg.conversation_id.slice(0, 8)}...`);
67872
+ await this._replayHistoryToSession(msg.conversation_id);
67873
+ await this._persistState();
67874
+ ackedIds.push(msg.queue_id);
67875
+ continue;
67876
+ }
67877
+ if (messageType === "message") {
67878
+ const topicId = msg.topic_id;
67879
+ this._appendHistory("owner", messageText, topicId);
67880
+ const metadata = {
67881
+ messageId: msg.message_id,
67882
+ conversationId: msg.conversation_id,
67883
+ timestamp: msg.created_at,
67884
+ topicId
67885
+ };
67886
+ this.emit("message", messageText, metadata);
67887
+ Promise.resolve(this.config.onMessage?.(messageText, metadata)).catch((err) => {
67888
+ console.error("[SecureChannel] onMessage callback error:", err);
67889
+ });
67890
+ }
67891
+ this._persisted.lastMessageTimestamp = msg.created_at;
67892
+ ackedIds.push(msg.queue_id);
67893
+ } catch (err) {
67894
+ console.warn(`[SecureChannel] DR delivery processing failed for ${msg.message_id?.slice(0, 8)}:`, err);
67895
+ nackedIds.push(msg.queue_id);
67896
+ }
67897
+ }
67898
+ await this._persistState();
67899
+ if (nackedIds.length > 0) {
67900
+ try {
67901
+ await fetch(`${this.config.apiUrl}/api/v1/dr/delivery/nack`, {
67902
+ method: "POST",
67903
+ headers: {
67904
+ Authorization: `Bearer ${this._deviceJwt}`,
67905
+ "Content-Type": "application/json"
67906
+ },
67907
+ body: JSON.stringify({ queue_ids: nackedIds })
67908
+ });
67909
+ } catch {
67910
+ }
67911
+ }
67912
+ if (ackedIds.length > 0) {
67913
+ try {
67914
+ await fetch(`${this.config.apiUrl}/api/v1/dr/delivery/ack`, {
67915
+ method: "POST",
67916
+ headers: {
67917
+ Authorization: `Bearer ${this._deviceJwt}`,
67918
+ "Content-Type": "application/json"
67919
+ },
67920
+ body: JSON.stringify({ queue_ids: ackedIds, device_id: this._deviceId })
67921
+ });
67922
+ console.log(`[SecureChannel] DR delivery acked ${ackedIds.length}/${messages.length}`);
67923
+ } catch (ackErr) {
67924
+ console.warn("[SecureChannel] DR delivery ack failed:", ackErr);
67925
+ }
67926
+ }
67927
+ } catch (err) {
67928
+ console.warn("[SecureChannel] DR delivery pull error:", err);
67929
+ } finally {
67930
+ this._drDeliveryPulling = false;
67931
+ }
67932
+ }
67709
67933
  async _handleMlsSyncResponse(data) {
67710
67934
  const action = data.action;
67711
67935
  const groupId = data.group_id;
@@ -89065,7 +89289,7 @@ var init_index = __esm({
89065
89289
  init_skill_invoker();
89066
89290
  await init_skill_telemetry();
89067
89291
  await init_policy_enforcer();
89068
- VERSION = true ? "0.20.31" : "0.0.0-dev";
89292
+ VERSION = true ? "0.20.33" : "0.0.0-dev";
89069
89293
  }
89070
89294
  });
89071
89295