claudemesh-cli 0.6.5 → 0.6.7

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 (2) hide show
  1. package/dist/index.js +805 -493
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -47374,6 +47374,49 @@ var TOOLS = [
47374
47374
  }
47375
47375
  }
47376
47376
  },
47377
+ {
47378
+ name: "schedule_reminder",
47379
+ description: "Schedule a reminder message delivered back to yourself at a future time. The broker fires it as a push when the time arrives. Use to prompt yourself to check on something later.",
47380
+ inputSchema: {
47381
+ type: "object",
47382
+ properties: {
47383
+ message: { type: "string", description: "Reminder text" },
47384
+ deliver_at: { type: "number", description: "Unix timestamp (ms) when to deliver" },
47385
+ in_seconds: { type: "number", description: "Alternative to deliver_at: fire after N seconds" }
47386
+ },
47387
+ required: ["message"]
47388
+ }
47389
+ },
47390
+ {
47391
+ name: "send_later",
47392
+ description: "Send a message to a peer, @group, or broadcast (*) at a future time. The broker holds it and delivers when the time arrives.",
47393
+ inputSchema: {
47394
+ type: "object",
47395
+ properties: {
47396
+ to: { type: "string", description: "Recipient: display name, pubkey hex, @group, or *" },
47397
+ message: { type: "string", description: "Message text" },
47398
+ deliver_at: { type: "number", description: "Unix timestamp (ms) when to deliver" },
47399
+ in_seconds: { type: "number", description: "Alternative to deliver_at: fire after N seconds" }
47400
+ },
47401
+ required: ["to", "message"]
47402
+ }
47403
+ },
47404
+ {
47405
+ name: "list_scheduled",
47406
+ description: "List all your pending scheduled messages: id, recipient, preview, and delivery time.",
47407
+ inputSchema: { type: "object", properties: {} }
47408
+ },
47409
+ {
47410
+ name: "cancel_scheduled",
47411
+ description: "Cancel a pending scheduled message before it fires.",
47412
+ inputSchema: {
47413
+ type: "object",
47414
+ properties: {
47415
+ id: { type: "string", description: "Scheduled message ID" }
47416
+ },
47417
+ required: ["id"]
47418
+ }
47419
+ },
47377
47420
  {
47378
47421
  name: "mesh_info",
47379
47422
  description: "Get a complete overview of the mesh: peers, groups, state, memory, files, tasks, streams, tables. Call on session start for full situational awareness.",
@@ -47468,15 +47511,15 @@ class BrokerClient {
47468
47511
  outbound = [];
47469
47512
  pushHandlers = new Set;
47470
47513
  pushBuffer = [];
47471
- listPeersResolvers = [];
47472
- stateResolvers = [];
47473
- stateListResolvers = [];
47474
- memoryStoreResolvers = [];
47475
- memoryRecallResolvers = [];
47514
+ listPeersResolvers = new Map;
47515
+ stateResolvers = new Map;
47516
+ stateListResolvers = new Map;
47517
+ memoryStoreResolvers = new Map;
47518
+ memoryRecallResolvers = new Map;
47476
47519
  stateChangeHandlers = new Set;
47477
47520
  sessionPubkey = null;
47478
47521
  sessionSecretKey = null;
47479
- grantFileAccessResolvers = [];
47522
+ grantFileAccessResolvers = new Map;
47480
47523
  closed = false;
47481
47524
  reconnectAttempt = 0;
47482
47525
  helloTimer = null;
@@ -47503,6 +47546,9 @@ class BrokerClient {
47503
47546
  getSessionSecretKey() {
47504
47547
  return this.sessionSecretKey;
47505
47548
  }
47549
+ makeReqId() {
47550
+ return Math.random().toString(36).slice(2) + Date.now().toString(36);
47551
+ }
47506
47552
  async connect() {
47507
47553
  if (this.closed)
47508
47554
  throw new Error("client is closed");
@@ -47656,15 +47702,12 @@ class BrokerClient {
47656
47702
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47657
47703
  return [];
47658
47704
  return new Promise((resolve) => {
47659
- this.listPeersResolvers.push(resolve);
47660
- this.ws.send(JSON.stringify({ type: "list_peers" }));
47661
- setTimeout(() => {
47662
- const idx = this.listPeersResolvers.indexOf(resolve);
47663
- if (idx !== -1) {
47664
- this.listPeersResolvers.splice(idx, 1);
47705
+ const reqId = this.makeReqId();
47706
+ this.listPeersResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47707
+ if (this.listPeersResolvers.delete(reqId))
47665
47708
  resolve([]);
47666
- }
47667
- }, 5000);
47709
+ }, 5000) });
47710
+ this.ws.send(JSON.stringify({ type: "list_peers", _reqId: reqId }));
47668
47711
  });
47669
47712
  }
47670
47713
  async setSummary(summary) {
@@ -47691,60 +47734,48 @@ class BrokerClient {
47691
47734
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47692
47735
  return null;
47693
47736
  return new Promise((resolve) => {
47694
- this.stateResolvers.push(resolve);
47695
- this.ws.send(JSON.stringify({ type: "get_state", key }));
47696
- setTimeout(() => {
47697
- const idx = this.stateResolvers.indexOf(resolve);
47698
- if (idx !== -1) {
47699
- this.stateResolvers.splice(idx, 1);
47737
+ const reqId = this.makeReqId();
47738
+ this.stateResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47739
+ if (this.stateResolvers.delete(reqId))
47700
47740
  resolve(null);
47701
- }
47702
- }, 5000);
47741
+ }, 5000) });
47742
+ this.ws.send(JSON.stringify({ type: "get_state", key, _reqId: reqId }));
47703
47743
  });
47704
47744
  }
47705
47745
  async listState() {
47706
47746
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47707
47747
  return [];
47708
47748
  return new Promise((resolve) => {
47709
- this.stateListResolvers.push(resolve);
47710
- this.ws.send(JSON.stringify({ type: "list_state" }));
47711
- setTimeout(() => {
47712
- const idx = this.stateListResolvers.indexOf(resolve);
47713
- if (idx !== -1) {
47714
- this.stateListResolvers.splice(idx, 1);
47749
+ const reqId = this.makeReqId();
47750
+ this.stateListResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47751
+ if (this.stateListResolvers.delete(reqId))
47715
47752
  resolve([]);
47716
- }
47717
- }, 5000);
47753
+ }, 5000) });
47754
+ this.ws.send(JSON.stringify({ type: "list_state", _reqId: reqId }));
47718
47755
  });
47719
47756
  }
47720
47757
  async remember(content, tags) {
47721
47758
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47722
47759
  return null;
47723
47760
  return new Promise((resolve) => {
47724
- this.memoryStoreResolvers.push(resolve);
47725
- this.ws.send(JSON.stringify({ type: "remember", content, tags }));
47726
- setTimeout(() => {
47727
- const idx = this.memoryStoreResolvers.indexOf(resolve);
47728
- if (idx !== -1) {
47729
- this.memoryStoreResolvers.splice(idx, 1);
47761
+ const reqId = this.makeReqId();
47762
+ this.memoryStoreResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47763
+ if (this.memoryStoreResolvers.delete(reqId))
47730
47764
  resolve(null);
47731
- }
47732
- }, 5000);
47765
+ }, 5000) });
47766
+ this.ws.send(JSON.stringify({ type: "remember", content, tags, _reqId: reqId }));
47733
47767
  });
47734
47768
  }
47735
47769
  async recall(query) {
47736
47770
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47737
47771
  return [];
47738
47772
  return new Promise((resolve) => {
47739
- this.memoryRecallResolvers.push(resolve);
47740
- this.ws.send(JSON.stringify({ type: "recall", query }));
47741
- setTimeout(() => {
47742
- const idx = this.memoryRecallResolvers.indexOf(resolve);
47743
- if (idx !== -1) {
47744
- this.memoryRecallResolvers.splice(idx, 1);
47773
+ const reqId = this.makeReqId();
47774
+ this.memoryRecallResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47775
+ if (this.memoryRecallResolvers.delete(reqId))
47745
47776
  resolve([]);
47746
- }
47747
- }, 5000);
47777
+ }, 5000) });
47778
+ this.ws.send(JSON.stringify({ type: "recall", query, _reqId: reqId }));
47748
47779
  });
47749
47780
  }
47750
47781
  async forget(memoryId) {
@@ -47752,81 +47783,108 @@ class BrokerClient {
47752
47783
  return;
47753
47784
  this.ws.send(JSON.stringify({ type: "forget", memoryId }));
47754
47785
  }
47755
- messageStatusResolvers = [];
47756
- fileUrlResolvers = [];
47757
- fileListResolvers = [];
47758
- fileStatusResolvers = [];
47759
- vectorStoredResolvers = [];
47760
- vectorResultsResolvers = [];
47761
- collectionListResolvers = [];
47762
- graphResultResolvers = [];
47763
- contextListResolvers = [];
47764
- contextResultsResolvers = [];
47765
- taskCreatedResolvers = [];
47766
- taskListResolvers = [];
47767
- meshQueryResolvers = [];
47768
- meshSchemaResolvers = [];
47769
- streamCreatedResolvers = [];
47770
- streamListResolvers = [];
47786
+ async scheduleMessage(to, message, deliverAt) {
47787
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47788
+ return null;
47789
+ return new Promise((resolve) => {
47790
+ const reqId = this.makeReqId();
47791
+ this.scheduledAckResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47792
+ if (this.scheduledAckResolvers.delete(reqId))
47793
+ resolve(null);
47794
+ }, 8000) });
47795
+ this.ws.send(JSON.stringify({ type: "schedule", to, message, deliverAt, _reqId: reqId }));
47796
+ });
47797
+ }
47798
+ async listScheduled() {
47799
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47800
+ return [];
47801
+ return new Promise((resolve) => {
47802
+ const reqId = this.makeReqId();
47803
+ this.scheduledListResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47804
+ if (this.scheduledListResolvers.delete(reqId))
47805
+ resolve([]);
47806
+ }, 5000) });
47807
+ this.ws.send(JSON.stringify({ type: "list_scheduled", _reqId: reqId }));
47808
+ });
47809
+ }
47810
+ async cancelScheduled(scheduledId) {
47811
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47812
+ return false;
47813
+ return new Promise((resolve) => {
47814
+ const reqId = this.makeReqId();
47815
+ this.cancelScheduledResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47816
+ if (this.cancelScheduledResolvers.delete(reqId))
47817
+ resolve(false);
47818
+ }, 5000) });
47819
+ this.ws.send(JSON.stringify({ type: "cancel_scheduled", scheduledId, _reqId: reqId }));
47820
+ });
47821
+ }
47822
+ messageStatusResolvers = new Map;
47823
+ fileUrlResolvers = new Map;
47824
+ fileListResolvers = new Map;
47825
+ fileStatusResolvers = new Map;
47826
+ vectorStoredResolvers = new Map;
47827
+ vectorResultsResolvers = new Map;
47828
+ collectionListResolvers = new Map;
47829
+ graphResultResolvers = new Map;
47830
+ contextListResolvers = new Map;
47831
+ contextResultsResolvers = new Map;
47832
+ taskCreatedResolvers = new Map;
47833
+ taskListResolvers = new Map;
47834
+ meshQueryResolvers = new Map;
47835
+ meshSchemaResolvers = new Map;
47836
+ streamCreatedResolvers = new Map;
47837
+ streamListResolvers = new Map;
47771
47838
  streamDataHandlers = new Set;
47839
+ scheduledAckResolvers = new Map;
47840
+ scheduledListResolvers = new Map;
47841
+ cancelScheduledResolvers = new Map;
47772
47842
  async messageStatus(messageId) {
47773
47843
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47774
47844
  return null;
47775
47845
  return new Promise((resolve) => {
47776
- this.messageStatusResolvers.push(resolve);
47777
- this.ws.send(JSON.stringify({ type: "message_status", messageId }));
47778
- setTimeout(() => {
47779
- const idx = this.messageStatusResolvers.indexOf(resolve);
47780
- if (idx !== -1) {
47781
- this.messageStatusResolvers.splice(idx, 1);
47846
+ const reqId = this.makeReqId();
47847
+ this.messageStatusResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47848
+ if (this.messageStatusResolvers.delete(reqId))
47782
47849
  resolve(null);
47783
- }
47784
- }, 5000);
47850
+ }, 5000) });
47851
+ this.ws.send(JSON.stringify({ type: "message_status", messageId, _reqId: reqId }));
47785
47852
  });
47786
47853
  }
47787
47854
  async getFile(fileId) {
47788
47855
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47789
47856
  return null;
47790
47857
  return new Promise((resolve) => {
47791
- this.fileUrlResolvers.push(resolve);
47792
- this.ws.send(JSON.stringify({ type: "get_file", fileId }));
47793
- setTimeout(() => {
47794
- const idx = this.fileUrlResolvers.indexOf(resolve);
47795
- if (idx !== -1) {
47796
- this.fileUrlResolvers.splice(idx, 1);
47858
+ const reqId = this.makeReqId();
47859
+ this.fileUrlResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47860
+ if (this.fileUrlResolvers.delete(reqId))
47797
47861
  resolve(null);
47798
- }
47799
- }, 5000);
47862
+ }, 5000) });
47863
+ this.ws.send(JSON.stringify({ type: "get_file", fileId, _reqId: reqId }));
47800
47864
  });
47801
47865
  }
47802
47866
  async listFiles(query, from) {
47803
47867
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47804
47868
  return [];
47805
47869
  return new Promise((resolve) => {
47806
- this.fileListResolvers.push(resolve);
47807
- this.ws.send(JSON.stringify({ type: "list_files", query, from }));
47808
- setTimeout(() => {
47809
- const idx = this.fileListResolvers.indexOf(resolve);
47810
- if (idx !== -1) {
47811
- this.fileListResolvers.splice(idx, 1);
47870
+ const reqId = this.makeReqId();
47871
+ this.fileListResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47872
+ if (this.fileListResolvers.delete(reqId))
47812
47873
  resolve([]);
47813
- }
47814
- }, 5000);
47874
+ }, 5000) });
47875
+ this.ws.send(JSON.stringify({ type: "list_files", query, from, _reqId: reqId }));
47815
47876
  });
47816
47877
  }
47817
47878
  async fileStatus(fileId) {
47818
47879
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47819
47880
  return [];
47820
47881
  return new Promise((resolve) => {
47821
- this.fileStatusResolvers.push(resolve);
47822
- this.ws.send(JSON.stringify({ type: "file_status", fileId }));
47823
- setTimeout(() => {
47824
- const idx = this.fileStatusResolvers.indexOf(resolve);
47825
- if (idx !== -1) {
47826
- this.fileStatusResolvers.splice(idx, 1);
47882
+ const reqId = this.makeReqId();
47883
+ this.fileStatusResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47884
+ if (this.fileStatusResolvers.delete(reqId))
47827
47885
  resolve([]);
47828
- }
47829
- }, 5000);
47886
+ }, 5000) });
47887
+ this.ws.send(JSON.stringify({ type: "file_status", fileId, _reqId: reqId }));
47830
47888
  });
47831
47889
  }
47832
47890
  async deleteFile(fileId) {
@@ -47867,46 +47925,36 @@ class BrokerClient {
47867
47925
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47868
47926
  return false;
47869
47927
  return new Promise((resolve) => {
47870
- const resolvers = this.grantFileAccessResolvers;
47871
- resolvers.push(resolve);
47872
- this.ws.send(JSON.stringify({ type: "grant_file_access", fileId, peerPubkey, sealedKey }));
47873
- setTimeout(() => {
47874
- const idx = resolvers.indexOf(resolve);
47875
- if (idx !== -1) {
47876
- resolvers.splice(idx, 1);
47928
+ const reqId = this.makeReqId();
47929
+ this.grantFileAccessResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47930
+ if (this.grantFileAccessResolvers.delete(reqId))
47877
47931
  resolve(false);
47878
- }
47879
- }, 5000);
47932
+ }, 5000) });
47933
+ this.ws.send(JSON.stringify({ type: "grant_file_access", fileId, peerPubkey, sealedKey, _reqId: reqId }));
47880
47934
  });
47881
47935
  }
47882
47936
  async vectorStore(collection, text, metadata) {
47883
47937
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47884
47938
  return null;
47885
47939
  return new Promise((resolve) => {
47886
- this.vectorStoredResolvers.push(resolve);
47887
- this.ws.send(JSON.stringify({ type: "vector_store", collection, text, metadata }));
47888
- setTimeout(() => {
47889
- const idx = this.vectorStoredResolvers.indexOf(resolve);
47890
- if (idx !== -1) {
47891
- this.vectorStoredResolvers.splice(idx, 1);
47940
+ const reqId = this.makeReqId();
47941
+ this.vectorStoredResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47942
+ if (this.vectorStoredResolvers.delete(reqId))
47892
47943
  resolve(null);
47893
- }
47894
- }, 5000);
47944
+ }, 5000) });
47945
+ this.ws.send(JSON.stringify({ type: "vector_store", collection, text, metadata, _reqId: reqId }));
47895
47946
  });
47896
47947
  }
47897
47948
  async vectorSearch(collection, query, limit) {
47898
47949
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47899
47950
  return [];
47900
47951
  return new Promise((resolve) => {
47901
- this.vectorResultsResolvers.push(resolve);
47902
- this.ws.send(JSON.stringify({ type: "vector_search", collection, query, limit }));
47903
- setTimeout(() => {
47904
- const idx = this.vectorResultsResolvers.indexOf(resolve);
47905
- if (idx !== -1) {
47906
- this.vectorResultsResolvers.splice(idx, 1);
47952
+ const reqId = this.makeReqId();
47953
+ this.vectorResultsResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47954
+ if (this.vectorResultsResolvers.delete(reqId))
47907
47955
  resolve([]);
47908
- }
47909
- }, 5000);
47956
+ }, 5000) });
47957
+ this.ws.send(JSON.stringify({ type: "vector_search", collection, query, limit, _reqId: reqId }));
47910
47958
  });
47911
47959
  }
47912
47960
  async vectorDelete(collection, id) {
@@ -47918,45 +47966,36 @@ class BrokerClient {
47918
47966
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47919
47967
  return [];
47920
47968
  return new Promise((resolve) => {
47921
- this.collectionListResolvers.push(resolve);
47922
- this.ws.send(JSON.stringify({ type: "list_collections" }));
47923
- setTimeout(() => {
47924
- const idx = this.collectionListResolvers.indexOf(resolve);
47925
- if (idx !== -1) {
47926
- this.collectionListResolvers.splice(idx, 1);
47969
+ const reqId = this.makeReqId();
47970
+ this.collectionListResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47971
+ if (this.collectionListResolvers.delete(reqId))
47927
47972
  resolve([]);
47928
- }
47929
- }, 5000);
47973
+ }, 5000) });
47974
+ this.ws.send(JSON.stringify({ type: "list_collections", _reqId: reqId }));
47930
47975
  });
47931
47976
  }
47932
47977
  async graphQuery(cypher) {
47933
47978
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47934
47979
  return [];
47935
47980
  return new Promise((resolve) => {
47936
- this.graphResultResolvers.push(resolve);
47937
- this.ws.send(JSON.stringify({ type: "graph_query", cypher }));
47938
- setTimeout(() => {
47939
- const idx = this.graphResultResolvers.indexOf(resolve);
47940
- if (idx !== -1) {
47941
- this.graphResultResolvers.splice(idx, 1);
47981
+ const reqId = this.makeReqId();
47982
+ this.graphResultResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47983
+ if (this.graphResultResolvers.delete(reqId))
47942
47984
  resolve([]);
47943
- }
47944
- }, 5000);
47985
+ }, 5000) });
47986
+ this.ws.send(JSON.stringify({ type: "graph_query", cypher, _reqId: reqId }));
47945
47987
  });
47946
47988
  }
47947
47989
  async graphExecute(cypher) {
47948
47990
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47949
47991
  return [];
47950
47992
  return new Promise((resolve) => {
47951
- this.graphResultResolvers.push(resolve);
47952
- this.ws.send(JSON.stringify({ type: "graph_execute", cypher }));
47953
- setTimeout(() => {
47954
- const idx = this.graphResultResolvers.indexOf(resolve);
47955
- if (idx !== -1) {
47956
- this.graphResultResolvers.splice(idx, 1);
47993
+ const reqId = this.makeReqId();
47994
+ this.graphResultResolvers.set(reqId, { resolve, timer: setTimeout(() => {
47995
+ if (this.graphResultResolvers.delete(reqId))
47957
47996
  resolve([]);
47958
- }
47959
- }, 5000);
47997
+ }, 5000) });
47998
+ this.ws.send(JSON.stringify({ type: "graph_execute", cypher, _reqId: reqId }));
47960
47999
  });
47961
48000
  }
47962
48001
  async shareContext(summary, filesRead, keyFindings, tags) {
@@ -47968,45 +48007,36 @@ class BrokerClient {
47968
48007
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47969
48008
  return [];
47970
48009
  return new Promise((resolve) => {
47971
- this.contextResultsResolvers.push(resolve);
47972
- this.ws.send(JSON.stringify({ type: "get_context", query }));
47973
- setTimeout(() => {
47974
- const idx = this.contextResultsResolvers.indexOf(resolve);
47975
- if (idx !== -1) {
47976
- this.contextResultsResolvers.splice(idx, 1);
48010
+ const reqId = this.makeReqId();
48011
+ this.contextResultsResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48012
+ if (this.contextResultsResolvers.delete(reqId))
47977
48013
  resolve([]);
47978
- }
47979
- }, 5000);
48014
+ }, 5000) });
48015
+ this.ws.send(JSON.stringify({ type: "get_context", query, _reqId: reqId }));
47980
48016
  });
47981
48017
  }
47982
48018
  async listContexts() {
47983
48019
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47984
48020
  return [];
47985
48021
  return new Promise((resolve) => {
47986
- this.contextListResolvers.push(resolve);
47987
- this.ws.send(JSON.stringify({ type: "list_contexts" }));
47988
- setTimeout(() => {
47989
- const idx = this.contextListResolvers.indexOf(resolve);
47990
- if (idx !== -1) {
47991
- this.contextListResolvers.splice(idx, 1);
48022
+ const reqId = this.makeReqId();
48023
+ this.contextListResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48024
+ if (this.contextListResolvers.delete(reqId))
47992
48025
  resolve([]);
47993
- }
47994
- }, 5000);
48026
+ }, 5000) });
48027
+ this.ws.send(JSON.stringify({ type: "list_contexts", _reqId: reqId }));
47995
48028
  });
47996
48029
  }
47997
48030
  async createTask(title, assignee, priority, tags) {
47998
48031
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47999
48032
  return null;
48000
48033
  return new Promise((resolve) => {
48001
- this.taskCreatedResolvers.push(resolve);
48002
- this.ws.send(JSON.stringify({ type: "create_task", title, assignee, priority, tags }));
48003
- setTimeout(() => {
48004
- const idx = this.taskCreatedResolvers.indexOf(resolve);
48005
- if (idx !== -1) {
48006
- this.taskCreatedResolvers.splice(idx, 1);
48034
+ const reqId = this.makeReqId();
48035
+ this.taskCreatedResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48036
+ if (this.taskCreatedResolvers.delete(reqId))
48007
48037
  resolve(null);
48008
- }
48009
- }, 5000);
48038
+ }, 5000) });
48039
+ this.ws.send(JSON.stringify({ type: "create_task", title, assignee, priority, tags, _reqId: reqId }));
48010
48040
  });
48011
48041
  }
48012
48042
  async claimTask(id) {
@@ -48023,30 +48053,24 @@ class BrokerClient {
48023
48053
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
48024
48054
  return [];
48025
48055
  return new Promise((resolve) => {
48026
- this.taskListResolvers.push(resolve);
48027
- this.ws.send(JSON.stringify({ type: "list_tasks", status, assignee }));
48028
- setTimeout(() => {
48029
- const idx = this.taskListResolvers.indexOf(resolve);
48030
- if (idx !== -1) {
48031
- this.taskListResolvers.splice(idx, 1);
48056
+ const reqId = this.makeReqId();
48057
+ this.taskListResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48058
+ if (this.taskListResolvers.delete(reqId))
48032
48059
  resolve([]);
48033
- }
48034
- }, 5000);
48060
+ }, 5000) });
48061
+ this.ws.send(JSON.stringify({ type: "list_tasks", status, assignee, _reqId: reqId }));
48035
48062
  });
48036
48063
  }
48037
48064
  async meshQuery(sql) {
48038
48065
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
48039
48066
  return null;
48040
48067
  return new Promise((resolve) => {
48041
- this.meshQueryResolvers.push(resolve);
48042
- this.ws.send(JSON.stringify({ type: "mesh_query", sql }));
48043
- setTimeout(() => {
48044
- const idx = this.meshQueryResolvers.indexOf(resolve);
48045
- if (idx !== -1) {
48046
- this.meshQueryResolvers.splice(idx, 1);
48068
+ const reqId = this.makeReqId();
48069
+ this.meshQueryResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48070
+ if (this.meshQueryResolvers.delete(reqId))
48047
48071
  resolve(null);
48048
- }
48049
- }, 5000);
48072
+ }, 5000) });
48073
+ this.ws.send(JSON.stringify({ type: "mesh_query", sql, _reqId: reqId }));
48050
48074
  });
48051
48075
  }
48052
48076
  async meshExecute(sql) {
@@ -48058,30 +48082,24 @@ class BrokerClient {
48058
48082
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
48059
48083
  return [];
48060
48084
  return new Promise((resolve) => {
48061
- this.meshSchemaResolvers.push(resolve);
48062
- this.ws.send(JSON.stringify({ type: "mesh_schema" }));
48063
- setTimeout(() => {
48064
- const idx = this.meshSchemaResolvers.indexOf(resolve);
48065
- if (idx !== -1) {
48066
- this.meshSchemaResolvers.splice(idx, 1);
48085
+ const reqId = this.makeReqId();
48086
+ this.meshSchemaResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48087
+ if (this.meshSchemaResolvers.delete(reqId))
48067
48088
  resolve([]);
48068
- }
48069
- }, 5000);
48089
+ }, 5000) });
48090
+ this.ws.send(JSON.stringify({ type: "mesh_schema", _reqId: reqId }));
48070
48091
  });
48071
48092
  }
48072
48093
  async createStream(name) {
48073
48094
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
48074
48095
  return null;
48075
48096
  return new Promise((resolve) => {
48076
- this.streamCreatedResolvers.push(resolve);
48077
- this.ws.send(JSON.stringify({ type: "create_stream", name }));
48078
- setTimeout(() => {
48079
- const idx = this.streamCreatedResolvers.indexOf(resolve);
48080
- if (idx !== -1) {
48081
- this.streamCreatedResolvers.splice(idx, 1);
48097
+ const reqId = this.makeReqId();
48098
+ this.streamCreatedResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48099
+ if (this.streamCreatedResolvers.delete(reqId))
48082
48100
  resolve(null);
48083
- }
48084
- }, 5000);
48101
+ }, 5000) });
48102
+ this.ws.send(JSON.stringify({ type: "create_stream", name, _reqId: reqId }));
48085
48103
  });
48086
48104
  }
48087
48105
  async publish(stream, data) {
@@ -48103,15 +48121,12 @@ class BrokerClient {
48103
48121
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
48104
48122
  return [];
48105
48123
  return new Promise((resolve) => {
48106
- this.streamListResolvers.push(resolve);
48107
- this.ws.send(JSON.stringify({ type: "list_streams" }));
48108
- setTimeout(() => {
48109
- const idx = this.streamListResolvers.indexOf(resolve);
48110
- if (idx !== -1) {
48111
- this.streamListResolvers.splice(idx, 1);
48124
+ const reqId = this.makeReqId();
48125
+ this.streamListResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48126
+ if (this.streamListResolvers.delete(reqId))
48112
48127
  resolve([]);
48113
- }
48114
- }, 5000);
48128
+ }, 5000) });
48129
+ this.ws.send(JSON.stringify({ type: "list_streams", _reqId: reqId }));
48115
48130
  });
48116
48131
  }
48117
48132
  onStreamData(handler) {
@@ -48122,20 +48137,17 @@ class BrokerClient {
48122
48137
  this.stateChangeHandlers.add(handler);
48123
48138
  return () => this.stateChangeHandlers.delete(handler);
48124
48139
  }
48125
- meshInfoResolvers = [];
48140
+ meshInfoResolvers = new Map;
48126
48141
  async meshInfo() {
48127
48142
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
48128
48143
  return null;
48129
48144
  return new Promise((resolve) => {
48130
- this.meshInfoResolvers.push(resolve);
48131
- this.ws.send(JSON.stringify({ type: "mesh_info" }));
48132
- setTimeout(() => {
48133
- const idx = this.meshInfoResolvers.indexOf(resolve);
48134
- if (idx !== -1) {
48135
- this.meshInfoResolvers.splice(idx, 1);
48145
+ const reqId = this.makeReqId();
48146
+ this.meshInfoResolvers.set(reqId, { resolve, timer: setTimeout(() => {
48147
+ if (this.meshInfoResolvers.delete(reqId))
48136
48148
  resolve(null);
48137
- }
48138
- }, 5000);
48149
+ }, 5000) });
48150
+ this.ws.send(JSON.stringify({ type: "mesh_info", _reqId: reqId }));
48139
48151
  });
48140
48152
  }
48141
48153
  close() {
@@ -48151,7 +48163,26 @@ class BrokerClient {
48151
48163
  }
48152
48164
  this.setConnStatus("closed");
48153
48165
  }
48166
+ resolveFromMap(map2, reqId, value) {
48167
+ let entry = reqId ? map2.get(reqId) : undefined;
48168
+ if (!entry) {
48169
+ const first = map2.entries().next().value;
48170
+ if (first) {
48171
+ entry = first[1];
48172
+ map2.delete(first[0]);
48173
+ }
48174
+ } else {
48175
+ map2.delete(reqId);
48176
+ }
48177
+ if (entry) {
48178
+ clearTimeout(entry.timer);
48179
+ entry.resolve(value);
48180
+ return true;
48181
+ }
48182
+ return false;
48183
+ }
48154
48184
  handleServerMessage(msg) {
48185
+ const msgReqId = msg._reqId;
48155
48186
  if (msg.type === "ack") {
48156
48187
  const pending = this.pendingSends.get(String(msg.id ?? ""));
48157
48188
  if (pending) {
@@ -48165,9 +48196,7 @@ class BrokerClient {
48165
48196
  }
48166
48197
  if (msg.type === "peers_list") {
48167
48198
  const peers = msg.peers ?? [];
48168
- const resolver = this.listPeersResolvers.shift();
48169
- if (resolver)
48170
- resolver(peers);
48199
+ this.resolveFromMap(this.listPeersResolvers, msgReqId, peers);
48171
48200
  return;
48172
48201
  }
48173
48202
  if (msg.type === "push") {
@@ -48221,26 +48250,21 @@ class BrokerClient {
48221
48250
  return;
48222
48251
  }
48223
48252
  if (msg.type === "state_result") {
48224
- const resolver = this.stateResolvers.shift();
48225
- if (resolver) {
48226
- if (msg.key) {
48227
- resolver({
48228
- key: String(msg.key),
48229
- value: msg.value,
48230
- updatedBy: String(msg.updatedBy ?? ""),
48231
- updatedAt: String(msg.updatedAt ?? "")
48232
- });
48233
- } else {
48234
- resolver(null);
48235
- }
48253
+ if (msg.key) {
48254
+ this.resolveFromMap(this.stateResolvers, msgReqId, {
48255
+ key: String(msg.key),
48256
+ value: msg.value,
48257
+ updatedBy: String(msg.updatedBy ?? ""),
48258
+ updatedAt: String(msg.updatedAt ?? "")
48259
+ });
48260
+ } else {
48261
+ this.resolveFromMap(this.stateResolvers, msgReqId, null);
48236
48262
  }
48237
48263
  return;
48238
48264
  }
48239
48265
  if (msg.type === "state_list") {
48240
48266
  const entries = msg.entries ?? [];
48241
- const resolver = this.stateListResolvers.shift();
48242
- if (resolver)
48243
- resolver(entries);
48267
+ this.resolveFromMap(this.stateListResolvers, msgReqId, entries);
48244
48268
  return;
48245
48269
  }
48246
48270
  if (msg.type === "state_change") {
@@ -48257,147 +48281,107 @@ class BrokerClient {
48257
48281
  return;
48258
48282
  }
48259
48283
  if (msg.type === "memory_stored") {
48260
- const resolver = this.memoryStoreResolvers.shift();
48261
- if (resolver)
48262
- resolver(msg.id ? String(msg.id) : null);
48284
+ this.resolveFromMap(this.memoryStoreResolvers, msgReqId, msg.id ? String(msg.id) : null);
48263
48285
  return;
48264
48286
  }
48265
48287
  if (msg.type === "memory_results") {
48266
48288
  const memories = msg.memories ?? [];
48267
- const resolver = this.memoryRecallResolvers.shift();
48268
- if (resolver)
48269
- resolver(memories);
48289
+ this.resolveFromMap(this.memoryRecallResolvers, msgReqId, memories);
48270
48290
  return;
48271
48291
  }
48272
48292
  if (msg.type === "message_status_result") {
48273
- const resolver = this.messageStatusResolvers.shift();
48274
- if (resolver)
48275
- resolver(msg);
48293
+ this.resolveFromMap(this.messageStatusResolvers, msgReqId, msg);
48276
48294
  return;
48277
48295
  }
48278
48296
  if (msg.type === "file_url") {
48279
- const resolver = this.fileUrlResolvers.shift();
48280
- if (resolver) {
48281
- if (msg.url) {
48282
- resolver({
48283
- url: String(msg.url),
48284
- name: String(msg.name ?? ""),
48285
- encrypted: msg.encrypted ? true : undefined,
48286
- sealedKey: msg.sealedKey ? String(msg.sealedKey) : undefined
48287
- });
48288
- } else {
48289
- resolver(null);
48290
- }
48297
+ if (msg.url) {
48298
+ this.resolveFromMap(this.fileUrlResolvers, msgReqId, {
48299
+ url: String(msg.url),
48300
+ name: String(msg.name ?? ""),
48301
+ encrypted: msg.encrypted ? true : undefined,
48302
+ sealedKey: msg.sealedKey ? String(msg.sealedKey) : undefined
48303
+ });
48304
+ } else {
48305
+ this.resolveFromMap(this.fileUrlResolvers, msgReqId, null);
48291
48306
  }
48292
48307
  return;
48293
48308
  }
48294
48309
  if (msg.type === "file_list") {
48295
48310
  const files = msg.files ?? [];
48296
- const resolver = this.fileListResolvers.shift();
48297
- if (resolver)
48298
- resolver(files);
48311
+ this.resolveFromMap(this.fileListResolvers, msgReqId, files);
48299
48312
  return;
48300
48313
  }
48301
48314
  if (msg.type === "file_status_result") {
48302
48315
  const accesses = msg.accesses ?? [];
48303
- const resolver = this.fileStatusResolvers.shift();
48304
- if (resolver)
48305
- resolver(accesses);
48316
+ this.resolveFromMap(this.fileStatusResolvers, msgReqId, accesses);
48306
48317
  return;
48307
48318
  }
48308
48319
  if (msg.type === "grant_file_access_ok") {
48309
- const resolver = this.grantFileAccessResolvers.shift();
48310
- if (resolver)
48311
- resolver(true);
48320
+ this.resolveFromMap(this.grantFileAccessResolvers, msgReqId, true);
48312
48321
  return;
48313
48322
  }
48314
48323
  if (msg.type === "vector_stored") {
48315
- const resolver = this.vectorStoredResolvers.shift();
48316
- if (resolver)
48317
- resolver(msg.id ? String(msg.id) : null);
48324
+ this.resolveFromMap(this.vectorStoredResolvers, msgReqId, msg.id ? String(msg.id) : null);
48318
48325
  return;
48319
48326
  }
48320
48327
  if (msg.type === "vector_results") {
48321
48328
  const results = msg.results ?? [];
48322
- const resolver = this.vectorResultsResolvers.shift();
48323
- if (resolver)
48324
- resolver(results);
48329
+ this.resolveFromMap(this.vectorResultsResolvers, msgReqId, results);
48325
48330
  return;
48326
48331
  }
48327
48332
  if (msg.type === "collection_list") {
48328
48333
  const collections = msg.collections ?? [];
48329
- const resolver = this.collectionListResolvers.shift();
48330
- if (resolver)
48331
- resolver(collections);
48334
+ this.resolveFromMap(this.collectionListResolvers, msgReqId, collections);
48332
48335
  return;
48333
48336
  }
48334
48337
  if (msg.type === "graph_result") {
48335
48338
  const rows = msg.records ?? [];
48336
- const resolver = this.graphResultResolvers.shift();
48337
- if (resolver)
48338
- resolver(rows);
48339
+ this.resolveFromMap(this.graphResultResolvers, msgReqId, rows);
48339
48340
  return;
48340
48341
  }
48341
48342
  if (msg.type === "context_list") {
48342
48343
  const contexts = msg.contexts ?? [];
48343
- const resolver = this.contextListResolvers.shift();
48344
- if (resolver)
48345
- resolver(contexts);
48344
+ this.resolveFromMap(this.contextListResolvers, msgReqId, contexts);
48346
48345
  return;
48347
48346
  }
48348
48347
  if (msg.type === "context_results") {
48349
48348
  const contexts = msg.contexts ?? [];
48350
- const resolver = this.contextResultsResolvers.shift();
48351
- if (resolver)
48352
- resolver(contexts);
48349
+ this.resolveFromMap(this.contextResultsResolvers, msgReqId, contexts);
48353
48350
  return;
48354
48351
  }
48355
48352
  if (msg.type === "task_created") {
48356
- const resolver = this.taskCreatedResolvers.shift();
48357
- if (resolver)
48358
- resolver(msg.id ? String(msg.id) : null);
48353
+ this.resolveFromMap(this.taskCreatedResolvers, msgReqId, msg.id ? String(msg.id) : null);
48359
48354
  return;
48360
48355
  }
48361
48356
  if (msg.type === "task_list") {
48362
48357
  const tasks = msg.tasks ?? [];
48363
- const resolver = this.taskListResolvers.shift();
48364
- if (resolver)
48365
- resolver(tasks);
48358
+ this.resolveFromMap(this.taskListResolvers, msgReqId, tasks);
48366
48359
  return;
48367
48360
  }
48368
48361
  if (msg.type === "mesh_query_result") {
48369
- const resolver = this.meshQueryResolvers.shift();
48370
- if (resolver) {
48371
- if (msg.columns) {
48372
- resolver({
48373
- columns: msg.columns ?? [],
48374
- rows: msg.rows ?? [],
48375
- rowCount: msg.rowCount ?? 0
48376
- });
48377
- } else {
48378
- resolver(null);
48379
- }
48362
+ if (msg.columns) {
48363
+ this.resolveFromMap(this.meshQueryResolvers, msgReqId, {
48364
+ columns: msg.columns ?? [],
48365
+ rows: msg.rows ?? [],
48366
+ rowCount: msg.rowCount ?? 0
48367
+ });
48368
+ } else {
48369
+ this.resolveFromMap(this.meshQueryResolvers, msgReqId, null);
48380
48370
  }
48381
48371
  return;
48382
48372
  }
48383
48373
  if (msg.type === "mesh_schema_result") {
48384
48374
  const tables = msg.tables ?? [];
48385
- const resolver = this.meshSchemaResolvers.shift();
48386
- if (resolver)
48387
- resolver(tables);
48375
+ this.resolveFromMap(this.meshSchemaResolvers, msgReqId, tables);
48388
48376
  return;
48389
48377
  }
48390
48378
  if (msg.type === "stream_created") {
48391
- const resolver = this.streamCreatedResolvers.shift();
48392
- if (resolver)
48393
- resolver(msg.id ? String(msg.id) : null);
48379
+ this.resolveFromMap(this.streamCreatedResolvers, msgReqId, msg.id ? String(msg.id) : null);
48394
48380
  return;
48395
48381
  }
48396
48382
  if (msg.type === "stream_list") {
48397
48383
  const streams = msg.streams ?? [];
48398
- const resolver = this.streamListResolvers.shift();
48399
- if (resolver)
48400
- resolver(streams);
48384
+ this.resolveFromMap(this.streamListResolvers, msgReqId, streams);
48401
48385
  return;
48402
48386
  }
48403
48387
  if (msg.type === "stream_data") {
@@ -48414,9 +48398,23 @@ class BrokerClient {
48414
48398
  return;
48415
48399
  }
48416
48400
  if (msg.type === "mesh_info_result") {
48417
- const resolver = this.meshInfoResolvers.shift();
48418
- if (resolver)
48419
- resolver(msg);
48401
+ this.resolveFromMap(this.meshInfoResolvers, msgReqId, msg);
48402
+ return;
48403
+ }
48404
+ if (msg.type === "scheduled_ack") {
48405
+ this.resolveFromMap(this.scheduledAckResolvers, msgReqId, {
48406
+ scheduledId: String(msg.scheduledId ?? ""),
48407
+ deliverAt: Number(msg.deliverAt ?? 0)
48408
+ });
48409
+ return;
48410
+ }
48411
+ if (msg.type === "scheduled_list") {
48412
+ const messages = msg.messages ?? [];
48413
+ this.resolveFromMap(this.scheduledListResolvers, msgReqId, messages);
48414
+ return;
48415
+ }
48416
+ if (msg.type === "cancel_scheduled_ack") {
48417
+ this.resolveFromMap(this.cancelScheduledResolvers, msgReqId, Boolean(msg.ok));
48420
48418
  return;
48421
48419
  }
48422
48420
  if (msg.type === "error") {
@@ -48435,36 +48433,42 @@ class BrokerClient {
48435
48433
  }
48436
48434
  }
48437
48435
  if (!handledByPendingSend) {
48438
- if (this.stateResolvers.length > 0) {
48439
- this.stateResolvers.shift()(null);
48440
- } else if (this.stateListResolvers.length > 0) {
48441
- this.stateListResolvers.shift()([]);
48442
- } else if (this.memoryStoreResolvers.length > 0) {
48443
- this.memoryStoreResolvers.shift()(null);
48444
- } else if (this.memoryRecallResolvers.length > 0) {
48445
- this.memoryRecallResolvers.shift()([]);
48446
- } else if (this.fileUrlResolvers.length > 0) {
48447
- this.fileUrlResolvers.shift()(null);
48448
- } else if (this.fileListResolvers.length > 0) {
48449
- this.fileListResolvers.shift()([]);
48450
- } else if (this.fileStatusResolvers.length > 0) {
48451
- this.fileStatusResolvers.shift()([]);
48452
- } else if (this.graphResultResolvers.length > 0) {
48453
- this.graphResultResolvers.shift()([]);
48454
- } else if (this.vectorStoredResolvers.length > 0) {
48455
- this.vectorStoredResolvers.shift()(null);
48456
- } else if (this.vectorResultsResolvers.length > 0) {
48457
- this.vectorResultsResolvers.shift()([]);
48458
- } else if (this.taskListResolvers.length > 0) {
48459
- this.taskListResolvers.shift()([]);
48460
- } else if (this.meshQueryResolvers.length > 0) {
48461
- this.meshQueryResolvers.shift()(null);
48462
- } else if (this.contextResultsResolvers.length > 0) {
48463
- this.contextResultsResolvers.shift()([]);
48464
- } else if (this.contextListResolvers.length > 0) {
48465
- this.contextListResolvers.shift()([]);
48466
- } else if (this.streamListResolvers.length > 0) {
48467
- this.streamListResolvers.shift()([]);
48436
+ const allMaps = [
48437
+ [this.stateResolvers, null],
48438
+ [this.stateListResolvers, []],
48439
+ [this.memoryStoreResolvers, null],
48440
+ [this.memoryRecallResolvers, []],
48441
+ [this.fileUrlResolvers, null],
48442
+ [this.fileListResolvers, []],
48443
+ [this.fileStatusResolvers, []],
48444
+ [this.graphResultResolvers, []],
48445
+ [this.vectorStoredResolvers, null],
48446
+ [this.vectorResultsResolvers, []],
48447
+ [this.taskListResolvers, []],
48448
+ [this.meshQueryResolvers, null],
48449
+ [this.contextResultsResolvers, []],
48450
+ [this.contextListResolvers, []],
48451
+ [this.streamListResolvers, []],
48452
+ [this.scheduledAckResolvers, null],
48453
+ [this.scheduledListResolvers, []],
48454
+ [this.cancelScheduledResolvers, false],
48455
+ [this.messageStatusResolvers, null],
48456
+ [this.grantFileAccessResolvers, false],
48457
+ [this.collectionListResolvers, []],
48458
+ [this.meshSchemaResolvers, []],
48459
+ [this.taskCreatedResolvers, null],
48460
+ [this.streamCreatedResolvers, null],
48461
+ [this.listPeersResolvers, []],
48462
+ [this.meshInfoResolvers, null]
48463
+ ];
48464
+ for (const [map2, defaultVal] of allMaps) {
48465
+ const first = map2.entries().next().value;
48466
+ if (first) {
48467
+ map2.delete(first[0]);
48468
+ clearTimeout(first[1].timer);
48469
+ first[1].resolve(defaultVal);
48470
+ break;
48471
+ }
48468
48472
  }
48469
48473
  }
48470
48474
  }
@@ -48515,17 +48519,17 @@ async function ensureClient(mesh) {
48515
48519
  const existing = clients.get(mesh.meshId);
48516
48520
  if (existing)
48517
48521
  return existing;
48518
- const client = new BrokerClient(mesh, { debug: env.CLAUDEMESH_DEBUG, displayName: configDisplayName });
48519
- clients.set(mesh.meshId, client);
48522
+ const client2 = new BrokerClient(mesh, { debug: env.CLAUDEMESH_DEBUG, displayName: configDisplayName });
48523
+ clients.set(mesh.meshId, client2);
48520
48524
  try {
48521
- await client.connect();
48525
+ await client2.connect();
48522
48526
  for (const g of configGroups ?? []) {
48523
48527
  try {
48524
- await client.joinGroup(g.name, g.role);
48528
+ await client2.joinGroup(g.name, g.role);
48525
48529
  } catch {}
48526
48530
  }
48527
48531
  } catch {}
48528
- return client;
48532
+ return client2;
48529
48533
  }
48530
48534
  async function startClients(config2) {
48531
48535
  configDisplayName = config2.displayName;
@@ -48608,12 +48612,12 @@ async function resolveClient(to) {
48608
48612
  var peerNameCache = new Map;
48609
48613
  var peerNameCacheAge = 0;
48610
48614
  var CACHE_TTL_MS = 30000;
48611
- async function resolvePeerName(client, pubkey) {
48615
+ async function resolvePeerName(client2, pubkey) {
48612
48616
  const now = Date.now();
48613
48617
  if (now - peerNameCacheAge > CACHE_TTL_MS) {
48614
48618
  peerNameCache.clear();
48615
48619
  try {
48616
- const peers = await client.listPeers();
48620
+ const peers = await client2.listPeers();
48617
48621
  for (const p of peers)
48618
48622
  peerNameCache.set(p.pubkey, p.displayName);
48619
48623
  } catch {}
@@ -48763,15 +48767,15 @@ Your message mode is "${messageMode}".
48763
48767
  const results = [];
48764
48768
  const seen = new Set;
48765
48769
  for (const target of targets) {
48766
- const { client, targetSpec, error: error2 } = await resolveClient(target);
48767
- if (!client) {
48770
+ const { client: client2, targetSpec, error: error2 } = await resolveClient(target);
48771
+ if (!client2) {
48768
48772
  results.push(`✗ ${target}: ${error2 ?? "no client resolved"}`);
48769
48773
  continue;
48770
48774
  }
48771
48775
  if (seen.has(targetSpec))
48772
48776
  continue;
48773
48777
  seen.add(targetSpec);
48774
- const result = await client.send(targetSpec, message, priority ?? "next");
48778
+ const result = await client2.send(targetSpec, message, priority ?? "next");
48775
48779
  if (!result.ok) {
48776
48780
  results.push(`✗ ${target}: ${result.error}`);
48777
48781
  } else {
@@ -48892,19 +48896,19 @@ ${drained.join(`
48892
48896
  const { key } = args ?? {};
48893
48897
  if (!key)
48894
48898
  return text("get_state: `key` required", true);
48895
- const client = allClients()[0];
48896
- if (!client)
48899
+ const client2 = allClients()[0];
48900
+ if (!client2)
48897
48901
  return text("get_state: not connected", true);
48898
- const result = await client.getState(key);
48902
+ const result = await client2.getState(key);
48899
48903
  if (!result)
48900
48904
  return text(`State "${key}" not found.`);
48901
48905
  return text(`${key} = ${JSON.stringify(result.value)} (set by ${result.updatedBy} at ${result.updatedAt})`);
48902
48906
  }
48903
48907
  case "list_state": {
48904
- const client = allClients()[0];
48905
- if (!client)
48908
+ const client2 = allClients()[0];
48909
+ if (!client2)
48906
48910
  return text("list_state: not connected", true);
48907
- const entries = await client.listState();
48911
+ const entries = await client2.listState();
48908
48912
  if (entries.length === 0)
48909
48913
  return text("No shared state set.");
48910
48914
  const lines = entries.map((e) => `- **${e.key}** = ${JSON.stringify(e.value)} (by ${e.updatedBy})`);
@@ -48915,20 +48919,20 @@ ${drained.join(`
48915
48919
  const { content, tags } = args ?? {};
48916
48920
  if (!content)
48917
48921
  return text("remember: `content` required", true);
48918
- const client = allClients()[0];
48919
- if (!client)
48922
+ const client2 = allClients()[0];
48923
+ if (!client2)
48920
48924
  return text("remember: not connected", true);
48921
- const id = await client.remember(content, tags);
48925
+ const id = await client2.remember(content, tags);
48922
48926
  return text(`Remembered${id ? ` (${id})` : ""}: "${content.slice(0, 80)}${content.length > 80 ? "..." : ""}"`);
48923
48927
  }
48924
48928
  case "recall": {
48925
48929
  const { query } = args ?? {};
48926
48930
  if (!query)
48927
48931
  return text("recall: `query` required", true);
48928
- const client = allClients()[0];
48929
- if (!client)
48932
+ const client2 = allClients()[0];
48933
+ if (!client2)
48930
48934
  return text("recall: not connected", true);
48931
- const memories = await client.recall(query);
48935
+ const memories = await client2.recall(query);
48932
48936
  if (memories.length === 0)
48933
48937
  return text(`No memories found for "${query}".`);
48934
48938
  const lines = memories.map((m) => `- [${m.id.slice(0, 8)}] ${m.content} (by ${m.rememberedBy}, ${m.rememberedAt})`);
@@ -48940,12 +48944,63 @@ ${lines.join(`
48940
48944
  const { id } = args ?? {};
48941
48945
  if (!id)
48942
48946
  return text("forget: `id` required", true);
48943
- const client = allClients()[0];
48944
- if (!client)
48947
+ const client2 = allClients()[0];
48948
+ if (!client2)
48945
48949
  return text("forget: not connected", true);
48946
- await client.forget(id);
48950
+ await client2.forget(id);
48947
48951
  return text(`Forgotten: ${id}`);
48948
48952
  }
48953
+ case "schedule_reminder":
48954
+ case "send_later": {
48955
+ const sArgs = args ?? {};
48956
+ if (!sArgs.message)
48957
+ return text(`${name}: \`message\` required`, true);
48958
+ const to = name === "schedule_reminder" ? "self" : sArgs.to ?? "";
48959
+ if (name === "send_later" && !to)
48960
+ return text("send_later: `to` required", true);
48961
+ let deliverAt;
48962
+ if (sArgs.deliver_at) {
48963
+ deliverAt = Number(sArgs.deliver_at);
48964
+ } else if (sArgs.in_seconds) {
48965
+ deliverAt = Date.now() + Number(sArgs.in_seconds) * 1000;
48966
+ } else {
48967
+ return text(`${name}: provide \`deliver_at\` (ms timestamp) or \`in_seconds\``, true);
48968
+ }
48969
+ let targetSpec = to;
48970
+ if (name === "send_later" && !to.startsWith("@") && to !== "*" && !/^[0-9a-f]{64}$/i.test(to) && to !== "self") {
48971
+ const peers = await client.listPeers();
48972
+ const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
48973
+ if (!match) {
48974
+ const names = peers.map((p) => p.displayName).join(", ");
48975
+ return text(`send_later: peer "${to}" not found. Online: ${names || "(none)"}`, true);
48976
+ }
48977
+ targetSpec = match.pubkey;
48978
+ }
48979
+ if (name === "schedule_reminder") {
48980
+ targetSpec = client.getSessionPubkey() ?? "*";
48981
+ }
48982
+ const result = await client.scheduleMessage(targetSpec, sArgs.message, deliverAt);
48983
+ if (!result)
48984
+ return text(`${name}: broker did not acknowledge — check connection`, true);
48985
+ const when = new Date(result.deliverAt).toISOString();
48986
+ return text(name === "schedule_reminder" ? `Reminder scheduled (${result.scheduledId.slice(0, 8)}): "${sArgs.message.slice(0, 60)}" at ${when}` : `Message to "${to}" scheduled (${result.scheduledId.slice(0, 8)}) for ${when}`);
48987
+ }
48988
+ case "list_scheduled": {
48989
+ const scheduled = await client.listScheduled();
48990
+ if (scheduled.length === 0)
48991
+ return text("No pending scheduled messages.");
48992
+ const lines = scheduled.map((m) => `- [${m.id.slice(0, 8)}] → ${m.to === client.getSessionPubkey() ? "self (reminder)" : m.to} at ${new Date(m.deliverAt).toISOString()}: "${m.message.slice(0, 60)}${m.message.length > 60 ? "…" : ""}"`);
48993
+ return text(`${scheduled.length} scheduled:
48994
+ ${lines.join(`
48995
+ `)}`);
48996
+ }
48997
+ case "cancel_scheduled": {
48998
+ const { id: schedId } = args ?? {};
48999
+ if (!schedId)
49000
+ return text("cancel_scheduled: `id` required", true);
49001
+ const ok = await client.cancelScheduled(schedId);
49002
+ return text(ok ? `Cancelled: ${schedId}` : `Not found or already fired: ${schedId}`, !ok);
49003
+ }
48949
49004
  case "share_file": {
48950
49005
  const { path: filePath, name: fileName, tags, to: fileTo } = args ?? {};
48951
49006
  if (!filePath)
@@ -48953,15 +49008,15 @@ ${lines.join(`
48953
49008
  const { existsSync: existsSync2 } = await import("node:fs");
48954
49009
  if (!existsSync2(filePath))
48955
49010
  return text(`share_file: file not found: ${filePath}`, true);
48956
- const client = allClients()[0];
48957
- if (!client)
49011
+ const client2 = allClients()[0];
49012
+ if (!client2)
48958
49013
  return text("share_file: not connected", true);
48959
49014
  if (fileTo) {
48960
49015
  const { encryptFile: encryptFile2, sealKeyForPeer: sealKeyForPeer2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
48961
49016
  const { readFileSync: readFileSync2, writeFileSync: writeFileSync2, mkdtempSync, unlinkSync, rmdirSync } = await import("node:fs");
48962
49017
  const { tmpdir } = await import("node:os");
48963
49018
  const { join: join2, basename } = await import("node:path");
48964
- const peers = await client.listPeers();
49019
+ const peers = await client2.listPeers();
48965
49020
  const targetPeer = peers.find((p) => p.pubkey === fileTo || p.displayName === fileTo);
48966
49021
  if (!targetPeer) {
48967
49022
  return text(`share_file: peer not found: ${fileTo}`, true);
@@ -48969,7 +49024,7 @@ ${lines.join(`
48969
49024
  const plaintext = readFileSync2(filePath);
48970
49025
  const { ciphertext, nonce, key } = await encryptFile2(new Uint8Array(plaintext));
48971
49026
  const sealedForTarget = await sealKeyForPeer2(key, targetPeer.pubkey);
48972
- const myPubkey = client.getSessionPubkey();
49027
+ const myPubkey = client2.getSessionPubkey();
48973
49028
  const sealedForSelf = myPubkey ? await sealKeyForPeer2(key, myPubkey) : null;
48974
49029
  const fileKeys = [
48975
49030
  { peerPubkey: targetPeer.pubkey, sealedKey: sealedForTarget },
@@ -48986,7 +49041,7 @@ ${lines.join(`
48986
49041
  const tmpPath = join2(tmpDir, baseName);
48987
49042
  writeFileSync2(tmpPath, combined);
48988
49043
  try {
48989
- const fileId = await client.uploadFile(tmpPath, client.meshId, client.meshSlug, {
49044
+ const fileId = await client2.uploadFile(tmpPath, client2.meshId, client2.meshSlug, {
48990
49045
  name: baseName,
48991
49046
  tags,
48992
49047
  persistent: true,
@@ -49007,7 +49062,7 @@ ${lines.join(`
49007
49062
  }
49008
49063
  }
49009
49064
  try {
49010
- const fileId = await client.uploadFile(filePath, client.meshId, client.meshSlug, {
49065
+ const fileId = await client2.uploadFile(filePath, client2.meshId, client2.meshSlug, {
49011
49066
  name: fileName,
49012
49067
  tags,
49013
49068
  persistent: true
@@ -49021,10 +49076,10 @@ ${lines.join(`
49021
49076
  const { id, save_to } = args ?? {};
49022
49077
  if (!id || !save_to)
49023
49078
  return text("get_file: `id` and `save_to` required", true);
49024
- const client = allClients()[0];
49025
- if (!client)
49079
+ const client2 = allClients()[0];
49080
+ if (!client2)
49026
49081
  return text("get_file: not connected", true);
49027
- const result = await client.getFile(id);
49082
+ const result = await client2.getFile(id);
49028
49083
  if (!result)
49029
49084
  return text(`get_file: file ${id} not found`, true);
49030
49085
  if (result.encrypted) {
@@ -49032,8 +49087,8 @@ ${lines.join(`
49032
49087
  return text("get_file: encrypted file — no decryption key available for your session", true);
49033
49088
  const { openSealedKey: openSealedKey2, decryptFile: decryptFile2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
49034
49089
  const { ensureSodium: ensureSodium2 } = await Promise.resolve().then(() => (init_keypair(), exports_keypair));
49035
- const myPubkey = client.getSessionPubkey();
49036
- const mySecret = client.getSessionSecretKey();
49090
+ const myPubkey = client2.getSessionPubkey();
49091
+ const mySecret = client2.getSessionSecretKey();
49037
49092
  if (!myPubkey || !mySecret) {
49038
49093
  return text("get_file: no session keypair — cannot decrypt", true);
49039
49094
  }
@@ -49068,10 +49123,10 @@ ${lines.join(`
49068
49123
  }
49069
49124
  case "list_files": {
49070
49125
  const { query, from } = args ?? {};
49071
- const client = allClients()[0];
49072
- if (!client)
49126
+ const client2 = allClients()[0];
49127
+ if (!client2)
49073
49128
  return text("list_files: not connected", true);
49074
- const files = await client.listFiles(query, from);
49129
+ const files = await client2.listFiles(query, from);
49075
49130
  if (files.length === 0)
49076
49131
  return text("No files found.");
49077
49132
  const lines = files.map((f) => `- **${f.name}** (${f.id.slice(0, 8)}…, ${f.size} bytes) by ${f.uploadedBy}${f.tags.length ? ` [${f.tags.join(", ")}]` : ""}`);
@@ -49082,10 +49137,10 @@ ${lines.join(`
49082
49137
  const { id } = args ?? {};
49083
49138
  if (!id)
49084
49139
  return text("file_status: `id` required", true);
49085
- const client = allClients()[0];
49086
- if (!client)
49140
+ const client2 = allClients()[0];
49141
+ if (!client2)
49087
49142
  return text("file_status: not connected", true);
49088
- const accesses = await client.fileStatus(id);
49143
+ const accesses = await client2.fileStatus(id);
49089
49144
  if (accesses.length === 0)
49090
49145
  return text("No one has accessed this file yet.");
49091
49146
  const lines = accesses.map((a) => `- ${a.peerName} at ${a.accessedAt}`);
@@ -49097,30 +49152,30 @@ ${lines.join(`
49097
49152
  const { id } = args ?? {};
49098
49153
  if (!id)
49099
49154
  return text("delete_file: `id` required", true);
49100
- const client = allClients()[0];
49101
- if (!client)
49155
+ const client2 = allClients()[0];
49156
+ if (!client2)
49102
49157
  return text("delete_file: not connected", true);
49103
- await client.deleteFile(id);
49158
+ await client2.deleteFile(id);
49104
49159
  return text(`Deleted: ${id}`);
49105
49160
  }
49106
49161
  case "vector_store": {
49107
49162
  const { collection, text: storeText, metadata } = args ?? {};
49108
49163
  if (!collection || !storeText)
49109
49164
  return text("vector_store: `collection` and `text` required", true);
49110
- const client = allClients()[0];
49111
- if (!client)
49165
+ const client2 = allClients()[0];
49166
+ if (!client2)
49112
49167
  return text("vector_store: not connected", true);
49113
- const id = await client.vectorStore(collection, storeText, metadata);
49168
+ const id = await client2.vectorStore(collection, storeText, metadata);
49114
49169
  return text(`Stored in ${collection}${id ? ` (${id})` : ""}`);
49115
49170
  }
49116
49171
  case "vector_search": {
49117
49172
  const { collection, query, limit } = args ?? {};
49118
49173
  if (!collection || !query)
49119
49174
  return text("vector_search: `collection` and `query` required", true);
49120
- const client = allClients()[0];
49121
- if (!client)
49175
+ const client2 = allClients()[0];
49176
+ if (!client2)
49122
49177
  return text("vector_search: not connected", true);
49123
- const results = await client.vectorSearch(collection, query, limit);
49178
+ const results = await client2.vectorSearch(collection, query, limit);
49124
49179
  if (results.length === 0)
49125
49180
  return text(`No results in ${collection} for "${query}".`);
49126
49181
  const lines = results.map((r) => `- [${r.id.slice(0, 8)}…] (score: ${r.score.toFixed(3)}) ${r.text.slice(0, 120)}${r.text.length > 120 ? "…" : ""}`);
@@ -49132,17 +49187,17 @@ ${lines.join(`
49132
49187
  const { collection, id } = args ?? {};
49133
49188
  if (!collection || !id)
49134
49189
  return text("vector_delete: `collection` and `id` required", true);
49135
- const client = allClients()[0];
49136
- if (!client)
49190
+ const client2 = allClients()[0];
49191
+ if (!client2)
49137
49192
  return text("vector_delete: not connected", true);
49138
- await client.vectorDelete(collection, id);
49193
+ await client2.vectorDelete(collection, id);
49139
49194
  return text(`Deleted ${id} from ${collection}`);
49140
49195
  }
49141
49196
  case "list_collections": {
49142
- const client = allClients()[0];
49143
- if (!client)
49197
+ const client2 = allClients()[0];
49198
+ if (!client2)
49144
49199
  return text("list_collections: not connected", true);
49145
- const collections = await client.listCollections();
49200
+ const collections = await client2.listCollections();
49146
49201
  if (collections.length === 0)
49147
49202
  return text("No vector collections.");
49148
49203
  return text(`Collections:
@@ -49153,10 +49208,10 @@ ${collections.map((c) => `- ${c}`).join(`
49153
49208
  const { cypher } = args ?? {};
49154
49209
  if (!cypher)
49155
49210
  return text("graph_query: `cypher` required", true);
49156
- const client = allClients()[0];
49157
- if (!client)
49211
+ const client2 = allClients()[0];
49212
+ if (!client2)
49158
49213
  return text("graph_query: not connected", true);
49159
- const rows = await client.graphQuery(cypher);
49214
+ const rows = await client2.graphQuery(cypher);
49160
49215
  if (rows.length === 0)
49161
49216
  return text("No results.");
49162
49217
  return text(JSON.stringify(rows, null, 2));
@@ -49165,30 +49220,30 @@ ${collections.map((c) => `- ${c}`).join(`
49165
49220
  const { cypher } = args ?? {};
49166
49221
  if (!cypher)
49167
49222
  return text("graph_execute: `cypher` required", true);
49168
- const client = allClients()[0];
49169
- if (!client)
49223
+ const client2 = allClients()[0];
49224
+ if (!client2)
49170
49225
  return text("graph_execute: not connected", true);
49171
- const rows = await client.graphExecute(cypher);
49226
+ const rows = await client2.graphExecute(cypher);
49172
49227
  return text(rows.length > 0 ? JSON.stringify(rows, null, 2) : "Executed successfully.");
49173
49228
  }
49174
49229
  case "share_context": {
49175
49230
  const { summary, files_read, key_findings, tags } = args ?? {};
49176
49231
  if (!summary)
49177
49232
  return text("share_context: `summary` required", true);
49178
- const client = allClients()[0];
49179
- if (!client)
49233
+ const client2 = allClients()[0];
49234
+ if (!client2)
49180
49235
  return text("share_context: not connected", true);
49181
- await client.shareContext(summary, files_read, key_findings, tags);
49236
+ await client2.shareContext(summary, files_read, key_findings, tags);
49182
49237
  return text(`Context shared: "${summary.slice(0, 80)}${summary.length > 80 ? "…" : ""}"`);
49183
49238
  }
49184
49239
  case "get_context": {
49185
49240
  const { query } = args ?? {};
49186
49241
  if (!query)
49187
49242
  return text("get_context: `query` required", true);
49188
- const client = allClients()[0];
49189
- if (!client)
49243
+ const client2 = allClients()[0];
49244
+ if (!client2)
49190
49245
  return text("get_context: not connected", true);
49191
- const contexts = await client.getContext(query);
49246
+ const contexts = await client2.getContext(query);
49192
49247
  if (contexts.length === 0)
49193
49248
  return text(`No context found for "${query}".`);
49194
49249
  const lines = contexts.map((c) => {
@@ -49203,10 +49258,10 @@ ${lines.join(`
49203
49258
  `)}`);
49204
49259
  }
49205
49260
  case "list_contexts": {
49206
- const client = allClients()[0];
49207
- if (!client)
49261
+ const client2 = allClients()[0];
49262
+ if (!client2)
49208
49263
  return text("list_contexts: not connected", true);
49209
- const contexts = await client.listContexts();
49264
+ const contexts = await client2.listContexts();
49210
49265
  if (contexts.length === 0)
49211
49266
  return text("No peer contexts shared yet.");
49212
49267
  const lines = contexts.map((c) => `- **${c.peerName}**: ${c.summary}${c.tags.length ? ` [${c.tags.join(", ")}]` : ""}`);
@@ -49218,38 +49273,38 @@ ${lines.join(`
49218
49273
  const { title, assignee, priority, tags } = args ?? {};
49219
49274
  if (!title)
49220
49275
  return text("create_task: `title` required", true);
49221
- const client = allClients()[0];
49222
- if (!client)
49276
+ const client2 = allClients()[0];
49277
+ if (!client2)
49223
49278
  return text("create_task: not connected", true);
49224
- const id = await client.createTask(title, assignee, priority, tags);
49279
+ const id = await client2.createTask(title, assignee, priority, tags);
49225
49280
  return text(`Task created${id ? ` (${id})` : ""}: "${title}"${assignee ? ` → ${assignee}` : ""}`);
49226
49281
  }
49227
49282
  case "claim_task": {
49228
49283
  const { id } = args ?? {};
49229
49284
  if (!id)
49230
49285
  return text("claim_task: `id` required", true);
49231
- const client = allClients()[0];
49232
- if (!client)
49286
+ const client2 = allClients()[0];
49287
+ if (!client2)
49233
49288
  return text("claim_task: not connected", true);
49234
- await client.claimTask(id);
49289
+ await client2.claimTask(id);
49235
49290
  return text(`Claimed task: ${id}`);
49236
49291
  }
49237
49292
  case "complete_task": {
49238
49293
  const { id, result } = args ?? {};
49239
49294
  if (!id)
49240
49295
  return text("complete_task: `id` required", true);
49241
- const client = allClients()[0];
49242
- if (!client)
49296
+ const client2 = allClients()[0];
49297
+ if (!client2)
49243
49298
  return text("complete_task: not connected", true);
49244
- await client.completeTask(id, result);
49299
+ await client2.completeTask(id, result);
49245
49300
  return text(`Completed task: ${id}${result ? ` — ${result}` : ""}`);
49246
49301
  }
49247
49302
  case "list_tasks": {
49248
49303
  const { status, assignee } = args ?? {};
49249
- const client = allClients()[0];
49250
- if (!client)
49304
+ const client2 = allClients()[0];
49305
+ if (!client2)
49251
49306
  return text("list_tasks: not connected", true);
49252
- const tasks = await client.listTasks(status, assignee);
49307
+ const tasks = await client2.listTasks(status, assignee);
49253
49308
  if (tasks.length === 0)
49254
49309
  return text("No tasks found.");
49255
49310
  const lines = tasks.map((t) => `- [${t.id.slice(0, 8)}…] **${t.title}** (${t.status}, ${t.priority}) ${t.assignee ? `→ ${t.assignee}` : "unassigned"} (by ${t.createdBy})`);
@@ -49261,10 +49316,10 @@ ${lines.join(`
49261
49316
  const { sql: querySql } = args ?? {};
49262
49317
  if (!querySql)
49263
49318
  return text("mesh_query: `sql` required", true);
49264
- const client = allClients()[0];
49265
- if (!client)
49319
+ const client2 = allClients()[0];
49320
+ if (!client2)
49266
49321
  return text("mesh_query: not connected", true);
49267
- const result = await client.meshQuery(querySql);
49322
+ const result = await client2.meshQuery(querySql);
49268
49323
  if (!result)
49269
49324
  return text("mesh_query: query failed or timed out", true);
49270
49325
  if (result.rows.length === 0)
@@ -49282,17 +49337,17 @@ ${rows.join(`
49282
49337
  const { sql: execSql } = args ?? {};
49283
49338
  if (!execSql)
49284
49339
  return text("mesh_execute: `sql` required", true);
49285
- const client = allClients()[0];
49286
- if (!client)
49340
+ const client2 = allClients()[0];
49341
+ if (!client2)
49287
49342
  return text("mesh_execute: not connected", true);
49288
- await client.meshExecute(execSql);
49343
+ await client2.meshExecute(execSql);
49289
49344
  return text(`Executed.`);
49290
49345
  }
49291
49346
  case "mesh_schema": {
49292
- const client = allClients()[0];
49293
- if (!client)
49347
+ const client2 = allClients()[0];
49348
+ if (!client2)
49294
49349
  return text("mesh_schema: not connected", true);
49295
- const tables = await client.meshSchema();
49350
+ const tables = await client2.meshSchema();
49296
49351
  if (!tables || tables.length === 0)
49297
49352
  return text("No tables in mesh database.");
49298
49353
  const lines = tables.map((t) => `**${t.name}**: ${t.columns.map((c) => `${c.name} (${c.type}${c.nullable ? ", nullable" : ""})`).join(", ")}`);
@@ -49303,37 +49358,37 @@ ${rows.join(`
49303
49358
  const { name: streamName } = args ?? {};
49304
49359
  if (!streamName)
49305
49360
  return text("create_stream: `name` required", true);
49306
- const client = allClients()[0];
49307
- if (!client)
49361
+ const client2 = allClients()[0];
49362
+ if (!client2)
49308
49363
  return text("create_stream: not connected", true);
49309
- const streamId = await client.createStream(streamName);
49364
+ const streamId = await client2.createStream(streamName);
49310
49365
  return text(`Stream created: ${streamName}${streamId ? ` (${streamId})` : ""}`);
49311
49366
  }
49312
49367
  case "publish": {
49313
49368
  const { stream: pubStream, data: pubData } = args ?? {};
49314
49369
  if (!pubStream)
49315
49370
  return text("publish: `stream` required", true);
49316
- const client = allClients()[0];
49317
- if (!client)
49371
+ const client2 = allClients()[0];
49372
+ if (!client2)
49318
49373
  return text("publish: not connected", true);
49319
- await client.publish(pubStream, pubData);
49374
+ await client2.publish(pubStream, pubData);
49320
49375
  return text(`Published to ${pubStream}.`);
49321
49376
  }
49322
49377
  case "subscribe": {
49323
49378
  const { stream: subStream } = args ?? {};
49324
49379
  if (!subStream)
49325
49380
  return text("subscribe: `stream` required", true);
49326
- const client = allClients()[0];
49327
- if (!client)
49381
+ const client2 = allClients()[0];
49382
+ if (!client2)
49328
49383
  return text("subscribe: not connected", true);
49329
- await client.subscribe(subStream);
49384
+ await client2.subscribe(subStream);
49330
49385
  return text(`Subscribed to ${subStream}. Data pushes will arrive as channel notifications.`);
49331
49386
  }
49332
49387
  case "list_streams": {
49333
- const client = allClients()[0];
49334
- if (!client)
49388
+ const client2 = allClients()[0];
49389
+ if (!client2)
49335
49390
  return text("list_streams: not connected", true);
49336
- const streams = await client.listStreams();
49391
+ const streams = await client2.listStreams();
49337
49392
  if (streams.length === 0)
49338
49393
  return text("No active streams.");
49339
49394
  const lines = streams.map((s) => `- **${s.name}** (${s.id.slice(0, 8)}…) by ${s.createdBy}, ${s.subscriberCount} subscriber(s)`);
@@ -49341,10 +49396,10 @@ ${rows.join(`
49341
49396
  `));
49342
49397
  }
49343
49398
  case "mesh_info": {
49344
- const client = allClients()[0];
49345
- if (!client)
49399
+ const client2 = allClients()[0];
49400
+ if (!client2)
49346
49401
  return text("mesh_info: not connected", true);
49347
- const info = await client.meshInfo();
49402
+ const info = await client2.meshInfo();
49348
49403
  if (!info)
49349
49404
  return text("mesh_info: timed out", true);
49350
49405
  const lines = [
@@ -49366,21 +49421,21 @@ ${rows.join(`
49366
49421
  case "ping_mesh": {
49367
49422
  const { priorities: pingPriorities } = args ?? {};
49368
49423
  const toTest = pingPriorities ?? ["now", "next"];
49369
- const client = allClients()[0];
49370
- if (!client)
49424
+ const client2 = allClients()[0];
49425
+ if (!client2)
49371
49426
  return text("ping_mesh: not connected", true);
49372
49427
  const results = [];
49373
- results.push(`WS status: ${client.status}`);
49374
- results.push(`Mesh: ${client.meshSlug}`);
49375
- const peers = await client.listPeers();
49428
+ results.push(`WS status: ${client2.status}`);
49429
+ results.push(`Mesh: ${client2.meshSlug}`);
49430
+ const peers = await client2.listPeers();
49376
49431
  const selfPeer = peers.find((p) => p.displayName === myName);
49377
49432
  results.push(`Your status: ${selfPeer?.status ?? "not found in peer list"}`);
49378
49433
  results.push(`Peers online: ${peers.length}`);
49379
- results.push(`Push buffer: ${client.pushHistory.length} buffered`);
49434
+ results.push(`Push buffer: ${client2.pushHistory.length} buffered`);
49380
49435
  for (const prio of toTest) {
49381
49436
  const sendTime = Date.now();
49382
49437
  const target = peers.find((p) => p.displayName !== myName);
49383
- const sendResult = await client.send(target?.pubkey ?? "*", `__ping__ ${prio} from ${myName} at ${new Date().toISOString()}`, prio);
49438
+ const sendResult = await client2.send(target?.pubkey ?? "*", `__ping__ ${prio} from ${myName} at ${new Date().toISOString()}`, prio);
49384
49439
  const ackTime = Date.now();
49385
49440
  if (!sendResult.ok) {
49386
49441
  results.push(`[${prio}] SEND FAILED: ${sendResult.error}`);
@@ -49403,14 +49458,14 @@ ${rows.join(`
49403
49458
  const { fileId, to: grantTo } = args ?? {};
49404
49459
  if (!fileId || !grantTo)
49405
49460
  return text("grant_file_access: `fileId` and `to` required", true);
49406
- const client = allClients()[0];
49407
- if (!client)
49461
+ const client2 = allClients()[0];
49462
+ if (!client2)
49408
49463
  return text("grant_file_access: not connected", true);
49409
- const peers = await client.listPeers();
49464
+ const peers = await client2.listPeers();
49410
49465
  const targetPeer = peers.find((p) => p.pubkey === grantTo || p.displayName === grantTo);
49411
49466
  if (!targetPeer)
49412
49467
  return text(`grant_file_access: peer not found: ${grantTo}`, true);
49413
- const result = await client.getFile(fileId);
49468
+ const result = await client2.getFile(fileId);
49414
49469
  if (!result)
49415
49470
  return text("grant_file_access: file not found", true);
49416
49471
  if (!result.encrypted)
@@ -49418,15 +49473,15 @@ ${rows.join(`
49418
49473
  if (!result.sealedKey)
49419
49474
  return text("grant_file_access: no key available (are you the owner?)", true);
49420
49475
  const { openSealedKey: openSealedKey2, sealKeyForPeer: sealKeyForPeer2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
49421
- const myPubkey = client.getSessionPubkey();
49422
- const mySecret = client.getSessionSecretKey();
49476
+ const myPubkey = client2.getSessionPubkey();
49477
+ const mySecret = client2.getSessionSecretKey();
49423
49478
  if (!myPubkey || !mySecret)
49424
49479
  return text("grant_file_access: no session keypair", true);
49425
49480
  const kf = await openSealedKey2(result.sealedKey, myPubkey, mySecret);
49426
49481
  if (!kf)
49427
49482
  return text("grant_file_access: cannot decrypt your own key", true);
49428
49483
  const sealedForPeer = await sealKeyForPeer2(kf, targetPeer.pubkey);
49429
- const ok = await client.grantFileAccess(fileId, targetPeer.pubkey, sealedForPeer);
49484
+ const ok = await client2.grantFileAccess(fileId, targetPeer.pubkey, sealedForPeer);
49430
49485
  if (!ok)
49431
49486
  return text("grant_file_access: broker did not confirm", true);
49432
49487
  return text(`Access granted: ${targetPeer.displayName} can now download file ${fileId}`);
@@ -49438,12 +49493,12 @@ ${rows.join(`
49438
49493
  await startClients(config2);
49439
49494
  const transport = new StdioServerTransport;
49440
49495
  await server.connect(transport);
49441
- for (const client of allClients()) {
49442
- client.onPush(async (msg) => {
49496
+ for (const client2 of allClients()) {
49497
+ client2.onPush(async (msg) => {
49443
49498
  if (messageMode === "off")
49444
49499
  return;
49445
49500
  const fromPubkey = msg.senderPubkey || "";
49446
- const fromName = fromPubkey ? await resolvePeerName(client, fromPubkey) : "unknown";
49501
+ const fromName = fromPubkey ? await resolvePeerName(client2, fromPubkey) : "unknown";
49447
49502
  if (messageMode === "inbox") {
49448
49503
  try {
49449
49504
  await server.notification({
@@ -49465,8 +49520,8 @@ ${rows.join(`
49465
49520
  meta: {
49466
49521
  from_id: fromPubkey,
49467
49522
  from_name: fromName,
49468
- mesh_slug: client.meshSlug,
49469
- mesh_id: client.meshId,
49523
+ mesh_slug: client2.meshSlug,
49524
+ mesh_id: client2.meshId,
49470
49525
  priority: msg.priority,
49471
49526
  sent_at: msg.createdAt,
49472
49527
  delivered_at: msg.receivedAt,
@@ -49481,7 +49536,7 @@ ${rows.join(`
49481
49536
  `);
49482
49537
  }
49483
49538
  });
49484
- client.onStreamData(async (evt) => {
49539
+ client2.onStreamData(async (evt) => {
49485
49540
  try {
49486
49541
  await server.notification({
49487
49542
  method: "notifications/claude/channel",
@@ -49496,7 +49551,7 @@ ${rows.join(`
49496
49551
  });
49497
49552
  } catch {}
49498
49553
  });
49499
- client.onStateChange(async (change) => {
49554
+ client2.onStateChange(async (change) => {
49500
49555
  try {
49501
49556
  await server.notification({
49502
49557
  method: "notifications/claude/channel",
@@ -49513,17 +49568,17 @@ ${rows.join(`
49513
49568
  });
49514
49569
  }
49515
49570
  setTimeout(async () => {
49516
- const client = allClients()[0];
49517
- if (!client || client.status !== "open")
49571
+ const client2 = allClients()[0];
49572
+ if (!client2 || client2.status !== "open")
49518
49573
  return;
49519
49574
  try {
49520
- const peers = await client.listPeers();
49575
+ const peers = await client2.listPeers();
49521
49576
  const peerNames = peers.filter((p) => p.displayName !== myName).map((p) => p.displayName).join(", ") || "none";
49522
49577
  await server.notification({
49523
49578
  method: "notifications/claude/channel",
49524
49579
  params: {
49525
- content: `[system] Connected as ${myName} to mesh ${client.meshSlug}. ${peers.length} peer(s) online: ${peerNames}. Call mesh_info for full details or set_summary to announce yourself.`,
49526
- meta: { kind: "welcome", mesh_slug: client.meshSlug }
49580
+ content: `[system] Connected as ${myName} to mesh ${client2.meshSlug}. ${peers.length} peer(s) online: ${peerNames}. Call mesh_info for full details or set_summary to announce yourself.`,
49581
+ meta: { kind: "welcome", mesh_slug: client2.meshSlug }
49527
49582
  }
49528
49583
  });
49529
49584
  } catch {}
@@ -50498,7 +50553,7 @@ init_config();
50498
50553
  // package.json
50499
50554
  var package_default = {
50500
50555
  name: "claudemesh-cli",
50501
- version: "0.6.5",
50556
+ version: "0.6.7",
50502
50557
  description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
50503
50558
  keywords: [
50504
50559
  "claude-code",
@@ -50931,13 +50986,13 @@ Joined: ${config2.meshes.map((m) => m.slug).join(", ")}`);
50931
50986
  process.exit(1);
50932
50987
  }
50933
50988
  const displayName = opts.displayName ?? config2.displayName ?? `${hostname3()}-${process.pid}`;
50934
- const client = new BrokerClient(mesh, { displayName });
50989
+ const client2 = new BrokerClient(mesh, { displayName });
50935
50990
  try {
50936
- await client.connect();
50937
- const result = await fn(client, mesh);
50991
+ await client2.connect();
50992
+ const result = await fn(client2, mesh);
50938
50993
  return result;
50939
50994
  } finally {
50940
- client.close();
50995
+ client2.close();
50941
50996
  }
50942
50997
  }
50943
50998
 
@@ -50948,8 +51003,8 @@ async function runPeers(flags) {
50948
51003
  const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
50949
51004
  const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
50950
51005
  const yellow = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
50951
- await withMesh({ meshSlug: flags.mesh ?? null }, async (client, mesh) => {
50952
- const peers = await client.listPeers();
51006
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
51007
+ const peers = await client2.listPeers();
50953
51008
  if (flags.json) {
50954
51009
  console.log(JSON.stringify(peers, null, 2));
50955
51010
  return;
@@ -50974,10 +51029,10 @@ async function runPeers(flags) {
50974
51029
  // src/commands/send.ts
50975
51030
  async function runSend(flags, to, message) {
50976
51031
  const priority = flags.priority === "now" ? "now" : flags.priority === "low" ? "low" : "next";
50977
- await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
51032
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
50978
51033
  let targetSpec = to;
50979
51034
  if (!to.startsWith("@") && to !== "*" && !/^[0-9a-f]{64}$/i.test(to)) {
50980
- const peers = await client.listPeers();
51035
+ const peers = await client2.listPeers();
50981
51036
  const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
50982
51037
  if (!match) {
50983
51038
  const names = peers.map((p) => p.displayName).join(", ");
@@ -50986,7 +51041,7 @@ async function runSend(flags, to, message) {
50986
51041
  }
50987
51042
  targetSpec = match.pubkey;
50988
51043
  }
50989
- const result = await client.send(targetSpec, message, priority);
51044
+ const result = await client2.send(targetSpec, message, priority);
50990
51045
  if (result.ok) {
50991
51046
  console.log(`✓ Sent to ${to}${result.messageId ? ` (${result.messageId.slice(0, 8)})` : ""}`);
50992
51047
  } else {
@@ -51012,9 +51067,9 @@ async function runInbox(flags) {
51012
51067
  const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
51013
51068
  const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
51014
51069
  const waitMs = (flags.wait ?? 1) * 1000;
51015
- await withMesh({ meshSlug: flags.mesh ?? null }, async (client, mesh) => {
51070
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
51016
51071
  await new Promise((resolve2) => setTimeout(resolve2, waitMs));
51017
- const messages = client.drainPushBuffer();
51072
+ const messages = client2.drainPushBuffer();
51018
51073
  if (flags.json) {
51019
51074
  console.log(JSON.stringify(messages, null, 2));
51020
51075
  return;
@@ -51036,8 +51091,8 @@ async function runInbox(flags) {
51036
51091
  async function runStateGet(flags, key) {
51037
51092
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
51038
51093
  const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
51039
- await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
51040
- const entry = await client.getState(key);
51094
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
51095
+ const entry = await client2.getState(key);
51041
51096
  if (!entry) {
51042
51097
  console.log(dim(`(not set)`));
51043
51098
  return;
@@ -51058,8 +51113,8 @@ async function runStateSet(flags, key, value) {
51058
51113
  } catch {
51059
51114
  parsed = value;
51060
51115
  }
51061
- await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
51062
- await client.setState(key, parsed);
51116
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
51117
+ await client2.setState(key, parsed);
51063
51118
  console.log(`✓ ${key} = ${JSON.stringify(parsed)}`);
51064
51119
  });
51065
51120
  }
@@ -51067,8 +51122,8 @@ async function runStateList(flags) {
51067
51122
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
51068
51123
  const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
51069
51124
  const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
51070
- await withMesh({ meshSlug: flags.mesh ?? null }, async (client, mesh) => {
51071
- const entries = await client.listState();
51125
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
51126
+ const entries = await client2.listState();
51072
51127
  if (flags.json) {
51073
51128
  console.log(JSON.stringify(entries, null, 2));
51074
51129
  return;
@@ -51085,6 +51140,214 @@ async function runStateList(flags) {
51085
51140
  });
51086
51141
  }
51087
51142
 
51143
+ // src/commands/memory.ts
51144
+ async function runRemember(flags, content) {
51145
+ const tags = flags.tags ? flags.tags.split(",").map((t) => t.trim()).filter(Boolean) : undefined;
51146
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
51147
+ const id = await client2.remember(content, tags);
51148
+ if (flags.json) {
51149
+ console.log(JSON.stringify({ id, content, tags }));
51150
+ return;
51151
+ }
51152
+ if (id) {
51153
+ console.log(`✓ Remembered (${id.slice(0, 8)})`);
51154
+ } else {
51155
+ console.error("✗ Failed to store memory");
51156
+ process.exit(1);
51157
+ }
51158
+ });
51159
+ }
51160
+ async function runRecall(flags, query) {
51161
+ const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
51162
+ const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
51163
+ const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
51164
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
51165
+ const memories = await client2.recall(query);
51166
+ if (flags.json) {
51167
+ console.log(JSON.stringify(memories, null, 2));
51168
+ return;
51169
+ }
51170
+ if (memories.length === 0) {
51171
+ console.log(dim("No memories found."));
51172
+ return;
51173
+ }
51174
+ for (const m of memories) {
51175
+ const tags = m.tags.length ? dim(` [${m.tags.join(", ")}]`) : "";
51176
+ console.log(`${bold2(m.id.slice(0, 8))}${tags}`);
51177
+ console.log(` ${m.content}`);
51178
+ console.log(dim(` ${m.rememberedBy} · ${new Date(m.rememberedAt).toLocaleString()}`));
51179
+ console.log("");
51180
+ }
51181
+ });
51182
+ }
51183
+
51184
+ // src/commands/info.ts
51185
+ init_config();
51186
+ async function runInfo(flags) {
51187
+ const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
51188
+ const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
51189
+ const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
51190
+ const config2 = loadConfig();
51191
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
51192
+ const [brokerInfo, peers, state] = await Promise.all([
51193
+ client2.meshInfo(),
51194
+ client2.listPeers(),
51195
+ client2.listState()
51196
+ ]);
51197
+ const output = {
51198
+ slug: mesh.slug,
51199
+ meshId: mesh.meshId,
51200
+ memberId: mesh.memberId,
51201
+ brokerUrl: mesh.brokerUrl,
51202
+ displayName: config2.displayName ?? null,
51203
+ peerCount: peers.length,
51204
+ stateCount: state.length,
51205
+ ...brokerInfo ?? {}
51206
+ };
51207
+ if (flags.json) {
51208
+ console.log(JSON.stringify(output, null, 2));
51209
+ return;
51210
+ }
51211
+ console.log(bold2(mesh.slug) + dim(` · ${mesh.brokerUrl}`));
51212
+ console.log(dim(` mesh: ${mesh.meshId}`));
51213
+ console.log(dim(` member: ${mesh.memberId}`));
51214
+ console.log(` peers: ${peers.length} connected`);
51215
+ console.log(` state: ${state.length} keys`);
51216
+ if (brokerInfo && typeof brokerInfo === "object") {
51217
+ for (const [k, v] of Object.entries(brokerInfo)) {
51218
+ if (["slug", "meshId", "brokerUrl"].includes(k))
51219
+ continue;
51220
+ console.log(dim(` ${k}: ${JSON.stringify(v)}`));
51221
+ }
51222
+ }
51223
+ });
51224
+ }
51225
+
51226
+ // src/commands/remind.ts
51227
+ function parseDuration(raw) {
51228
+ const m = raw.trim().match(/^(\d+(?:\.\d+)?)\s*(s|sec|m|min|h|hr|d|day)?$/i);
51229
+ if (!m)
51230
+ return null;
51231
+ const n = parseFloat(m[1]);
51232
+ const unit = (m[2] ?? "s").toLowerCase();
51233
+ if (unit.startsWith("d"))
51234
+ return n * 86400000;
51235
+ if (unit.startsWith("h"))
51236
+ return n * 3600000;
51237
+ if (unit.startsWith("m"))
51238
+ return n * 60000;
51239
+ return n * 1000;
51240
+ }
51241
+ function parseDeliverAt(flags) {
51242
+ if (flags.in) {
51243
+ const ms = parseDuration(flags.in);
51244
+ if (ms === null)
51245
+ return null;
51246
+ return Date.now() + ms;
51247
+ }
51248
+ if (flags.at) {
51249
+ const hm = flags.at.match(/^(\d{1,2}):(\d{2})$/);
51250
+ if (hm) {
51251
+ const now = new Date;
51252
+ const target = new Date(now);
51253
+ target.setHours(parseInt(hm[1], 10), parseInt(hm[2], 10), 0, 0);
51254
+ if (target <= now)
51255
+ target.setDate(target.getDate() + 1);
51256
+ return target.getTime();
51257
+ }
51258
+ const ts = Date.parse(flags.at);
51259
+ return isNaN(ts) ? null : ts;
51260
+ }
51261
+ return null;
51262
+ }
51263
+ async function runRemind(flags, positional) {
51264
+ const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
51265
+ const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
51266
+ const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
51267
+ const action = positional[0];
51268
+ if (action === "list") {
51269
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
51270
+ const scheduled = await client2.listScheduled();
51271
+ if (flags.json) {
51272
+ console.log(JSON.stringify(scheduled, null, 2));
51273
+ return;
51274
+ }
51275
+ if (scheduled.length === 0) {
51276
+ console.log(dim("No pending reminders."));
51277
+ return;
51278
+ }
51279
+ for (const m of scheduled) {
51280
+ const when = new Date(m.deliverAt).toLocaleString();
51281
+ const to = m.to === client2.getSessionPubkey() ? dim("(self)") : m.to;
51282
+ console.log(` ${bold2(m.id.slice(0, 8))} → ${to} at ${when}`);
51283
+ console.log(` ${dim(m.message.slice(0, 80))}`);
51284
+ console.log("");
51285
+ }
51286
+ });
51287
+ return;
51288
+ }
51289
+ if (action === "cancel") {
51290
+ const id = positional[1];
51291
+ if (!id) {
51292
+ console.error("Usage: claudemesh remind cancel <id>");
51293
+ process.exit(1);
51294
+ }
51295
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
51296
+ const ok = await client2.cancelScheduled(id);
51297
+ if (ok)
51298
+ console.log(`✓ Cancelled ${id}`);
51299
+ else {
51300
+ console.error(`✗ Not found or already fired: ${id}`);
51301
+ process.exit(1);
51302
+ }
51303
+ });
51304
+ return;
51305
+ }
51306
+ const message = action ?? positional.join(" ");
51307
+ if (!message) {
51308
+ console.error("Usage: claudemesh remind <message> --in <duration>");
51309
+ console.error(" claudemesh remind <message> --at <time>");
51310
+ console.error(" claudemesh remind list");
51311
+ console.error(" claudemesh remind cancel <id>");
51312
+ process.exit(1);
51313
+ }
51314
+ const deliverAt = parseDeliverAt(flags);
51315
+ if (deliverAt === null) {
51316
+ console.error('Specify when: --in <duration> (e.g. "2h", "30m") or --at <time> (e.g. "15:00")');
51317
+ process.exit(1);
51318
+ }
51319
+ await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
51320
+ let targetSpec;
51321
+ if (flags.to && flags.to !== "self") {
51322
+ if (flags.to.startsWith("@") || flags.to === "*" || /^[0-9a-f]{64}$/i.test(flags.to)) {
51323
+ targetSpec = flags.to;
51324
+ } else {
51325
+ const peers = await client2.listPeers();
51326
+ const match = peers.find((p) => p.displayName.toLowerCase() === flags.to.toLowerCase());
51327
+ if (!match) {
51328
+ console.error(`Peer "${flags.to}" not found. Online: ${peers.map((p) => p.displayName).join(", ") || "(none)"}`);
51329
+ process.exit(1);
51330
+ }
51331
+ targetSpec = match.pubkey;
51332
+ }
51333
+ } else {
51334
+ targetSpec = client2.getSessionPubkey() ?? "*";
51335
+ }
51336
+ const result = await client2.scheduleMessage(targetSpec, message, deliverAt);
51337
+ if (!result) {
51338
+ console.error("✗ Broker did not acknowledge — check connection");
51339
+ process.exit(1);
51340
+ }
51341
+ if (flags.json) {
51342
+ console.log(JSON.stringify(result));
51343
+ return;
51344
+ }
51345
+ const when = new Date(result.deliverAt).toLocaleString();
51346
+ const toLabel = !flags.to || flags.to === "self" ? "yourself" : flags.to;
51347
+ console.log(`✓ Reminder set (${result.scheduledId.slice(0, 8)}): "${message}" → ${toLabel} at ${when}`);
51348
+ });
51349
+ }
51350
+
51088
51351
  // src/index.ts
51089
51352
  var launch = defineCommand({
51090
51353
  meta: {
@@ -51270,6 +51533,55 @@ var main = defineCommand({
51270
51533
  }
51271
51534
  }
51272
51535
  }),
51536
+ info: defineCommand({
51537
+ meta: { name: "info", description: "Show mesh overview: slug, broker, peer count, state keys" },
51538
+ args: {
51539
+ mesh: { type: "string", description: "Mesh slug (auto-selected if only one joined)" },
51540
+ json: { type: "boolean", description: "Output as JSON", default: false }
51541
+ },
51542
+ async run({ args }) {
51543
+ await runInfo(args);
51544
+ }
51545
+ }),
51546
+ remember: defineCommand({
51547
+ meta: { name: "remember", description: "Store a memory in the mesh (accessible to all peers)" },
51548
+ args: {
51549
+ content: { type: "positional", description: "Text to remember", required: true },
51550
+ mesh: { type: "string", description: "Mesh slug (auto-selected if only one joined)" },
51551
+ tags: { type: "string", description: "Comma-separated tags (e.g. task,context)" },
51552
+ json: { type: "boolean", description: "Output as JSON", default: false }
51553
+ },
51554
+ async run({ args }) {
51555
+ await runRemember(args, args.content);
51556
+ }
51557
+ }),
51558
+ recall: defineCommand({
51559
+ meta: { name: "recall", description: "Search mesh memory by keyword or phrase" },
51560
+ args: {
51561
+ query: { type: "positional", description: "Search query", required: true },
51562
+ mesh: { type: "string", description: "Mesh slug (auto-selected if only one joined)" },
51563
+ json: { type: "boolean", description: "Output as JSON", default: false }
51564
+ },
51565
+ async run({ args }) {
51566
+ await runRecall(args, args.query);
51567
+ }
51568
+ }),
51569
+ remind: defineCommand({
51570
+ meta: { name: "remind", description: "Schedule a reminder or delayed message via the broker" },
51571
+ args: {
51572
+ message: { type: "positional", description: "Message text, or: list | cancel <id>", required: false },
51573
+ extra: { type: "positional", description: "Additional positional args", required: false },
51574
+ in: { type: "string", description: 'Deliver after duration: "2h", "30m", "90s"' },
51575
+ at: { type: "string", description: 'Deliver at time: "15:00" or ISO timestamp' },
51576
+ to: { type: "string", description: "Recipient (default: self). Name, @group, pubkey, or *" },
51577
+ mesh: { type: "string", description: "Mesh slug (auto-selected if only one joined)" },
51578
+ json: { type: "boolean", description: "Output as JSON", default: false }
51579
+ },
51580
+ async run({ args, rawArgs }) {
51581
+ const positionals = rawArgs.filter((a) => !a.startsWith("-"));
51582
+ await runRemind(args, positionals);
51583
+ }
51584
+ }),
51273
51585
  status: defineCommand({
51274
51586
  meta: { name: "status", description: "Check broker reachability for each joined mesh" },
51275
51587
  async run() {