claudemesh-cli 0.3.0 → 0.5.0

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 +1272 -44
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -46250,8 +46250,11 @@ var TOOLS = [
46250
46250
  type: "object",
46251
46251
  properties: {
46252
46252
  to: {
46253
- type: "string",
46254
- description: "Peer name, pubkey, @group, or #channel"
46253
+ oneOf: [
46254
+ { type: "string", description: "Peer name, pubkey, @group" },
46255
+ { type: "array", items: { type: "string" }, description: "Multiple targets" }
46256
+ ],
46257
+ description: "Single target or array of targets"
46255
46258
  },
46256
46259
  message: { type: "string", description: "Message text" },
46257
46260
  priority: {
@@ -46415,6 +46418,333 @@ var TOOLS = [
46415
46418
  },
46416
46419
  required: ["id"]
46417
46420
  }
46421
+ },
46422
+ {
46423
+ name: "share_file",
46424
+ description: "Share a persistent file with the mesh. All current and future peers can access it.",
46425
+ inputSchema: {
46426
+ type: "object",
46427
+ properties: {
46428
+ path: { type: "string", description: "Local file path to share" },
46429
+ name: {
46430
+ type: "string",
46431
+ description: "Display name (defaults to filename)"
46432
+ },
46433
+ tags: {
46434
+ type: "array",
46435
+ items: { type: "string" },
46436
+ description: "Tags for categorization"
46437
+ }
46438
+ },
46439
+ required: ["path"]
46440
+ }
46441
+ },
46442
+ {
46443
+ name: "get_file",
46444
+ description: "Download a shared file to a local path.",
46445
+ inputSchema: {
46446
+ type: "object",
46447
+ properties: {
46448
+ id: { type: "string", description: "File ID" },
46449
+ save_to: {
46450
+ type: "string",
46451
+ description: "Local path to save the file"
46452
+ }
46453
+ },
46454
+ required: ["id", "save_to"]
46455
+ }
46456
+ },
46457
+ {
46458
+ name: "list_files",
46459
+ description: "List files shared in the mesh.",
46460
+ inputSchema: {
46461
+ type: "object",
46462
+ properties: {
46463
+ query: { type: "string", description: "Search by name or tags" },
46464
+ from: { type: "string", description: "Filter by uploader name" }
46465
+ }
46466
+ }
46467
+ },
46468
+ {
46469
+ name: "file_status",
46470
+ description: "Check who has accessed a shared file.",
46471
+ inputSchema: {
46472
+ type: "object",
46473
+ properties: {
46474
+ id: { type: "string", description: "File ID" }
46475
+ },
46476
+ required: ["id"]
46477
+ }
46478
+ },
46479
+ {
46480
+ name: "delete_file",
46481
+ description: "Remove a shared file from the mesh.",
46482
+ inputSchema: {
46483
+ type: "object",
46484
+ properties: {
46485
+ id: { type: "string", description: "File ID" }
46486
+ },
46487
+ required: ["id"]
46488
+ }
46489
+ },
46490
+ {
46491
+ name: "vector_store",
46492
+ description: "Store an embedding in a per-mesh Qdrant collection. Auto-creates the collection on first use.",
46493
+ inputSchema: {
46494
+ type: "object",
46495
+ properties: {
46496
+ collection: { type: "string", description: "Collection name" },
46497
+ text: { type: "string", description: "Text to embed and store" },
46498
+ metadata: {
46499
+ type: "object",
46500
+ description: "Optional metadata to attach"
46501
+ }
46502
+ },
46503
+ required: ["collection", "text"]
46504
+ }
46505
+ },
46506
+ {
46507
+ name: "vector_search",
46508
+ description: "Semantic search over stored embeddings in a collection.",
46509
+ inputSchema: {
46510
+ type: "object",
46511
+ properties: {
46512
+ collection: { type: "string", description: "Collection name" },
46513
+ query: { type: "string", description: "Search query text" },
46514
+ limit: {
46515
+ type: "number",
46516
+ description: "Max results (default: 10)"
46517
+ }
46518
+ },
46519
+ required: ["collection", "query"]
46520
+ }
46521
+ },
46522
+ {
46523
+ name: "vector_delete",
46524
+ description: "Remove an embedding from a collection.",
46525
+ inputSchema: {
46526
+ type: "object",
46527
+ properties: {
46528
+ collection: { type: "string", description: "Collection name" },
46529
+ id: { type: "string", description: "Embedding ID to delete" }
46530
+ },
46531
+ required: ["collection", "id"]
46532
+ }
46533
+ },
46534
+ {
46535
+ name: "list_collections",
46536
+ description: "List vector collections in this mesh.",
46537
+ inputSchema: { type: "object", properties: {} }
46538
+ },
46539
+ {
46540
+ name: "graph_query",
46541
+ description: "Run a read-only Cypher query on the per-mesh Neo4j database.",
46542
+ inputSchema: {
46543
+ type: "object",
46544
+ properties: {
46545
+ cypher: { type: "string", description: "Cypher MATCH query" }
46546
+ },
46547
+ required: ["cypher"]
46548
+ }
46549
+ },
46550
+ {
46551
+ name: "graph_execute",
46552
+ description: "Run a write Cypher query (CREATE, MERGE, DELETE) on the per-mesh Neo4j database.",
46553
+ inputSchema: {
46554
+ type: "object",
46555
+ properties: {
46556
+ cypher: { type: "string", description: "Cypher write query" }
46557
+ },
46558
+ required: ["cypher"]
46559
+ }
46560
+ },
46561
+ {
46562
+ name: "mesh_query",
46563
+ description: "Run a SELECT query on the per-mesh shared database.",
46564
+ inputSchema: {
46565
+ type: "object",
46566
+ properties: {
46567
+ sql: { type: "string", description: "SQL SELECT query" }
46568
+ },
46569
+ required: ["sql"]
46570
+ }
46571
+ },
46572
+ {
46573
+ name: "mesh_execute",
46574
+ description: "Run DDL/DML on the per-mesh database (CREATE TABLE, INSERT, UPDATE, DELETE).",
46575
+ inputSchema: {
46576
+ type: "object",
46577
+ properties: {
46578
+ sql: { type: "string", description: "SQL statement" }
46579
+ },
46580
+ required: ["sql"]
46581
+ }
46582
+ },
46583
+ {
46584
+ name: "mesh_schema",
46585
+ description: "List tables and columns in the per-mesh shared database.",
46586
+ inputSchema: { type: "object", properties: {} }
46587
+ },
46588
+ {
46589
+ name: "create_stream",
46590
+ description: "Create a real-time data stream in the mesh.",
46591
+ inputSchema: {
46592
+ type: "object",
46593
+ properties: {
46594
+ name: { type: "string", description: "Stream name" }
46595
+ },
46596
+ required: ["name"]
46597
+ }
46598
+ },
46599
+ {
46600
+ name: "publish",
46601
+ description: "Push data to a stream. Subscribers receive it in real-time.",
46602
+ inputSchema: {
46603
+ type: "object",
46604
+ properties: {
46605
+ stream: { type: "string", description: "Stream name" },
46606
+ data: { description: "Any JSON data to publish" }
46607
+ },
46608
+ required: ["stream", "data"]
46609
+ }
46610
+ },
46611
+ {
46612
+ name: "subscribe",
46613
+ description: "Subscribe to a stream. Data pushes arrive as channel notifications.",
46614
+ inputSchema: {
46615
+ type: "object",
46616
+ properties: {
46617
+ stream: { type: "string", description: "Stream name" }
46618
+ },
46619
+ required: ["stream"]
46620
+ }
46621
+ },
46622
+ {
46623
+ name: "list_streams",
46624
+ description: "List active streams in the mesh.",
46625
+ inputSchema: { type: "object", properties: {} }
46626
+ },
46627
+ {
46628
+ name: "share_context",
46629
+ description: "Share your session understanding with the mesh. Call after exploring a codebase area.",
46630
+ inputSchema: {
46631
+ type: "object",
46632
+ properties: {
46633
+ summary: {
46634
+ type: "string",
46635
+ description: "Summary of what you explored/learned"
46636
+ },
46637
+ files_read: {
46638
+ type: "array",
46639
+ items: { type: "string" },
46640
+ description: "File paths you read"
46641
+ },
46642
+ key_findings: {
46643
+ type: "array",
46644
+ items: { type: "string" },
46645
+ description: "Key findings or insights"
46646
+ },
46647
+ tags: {
46648
+ type: "array",
46649
+ items: { type: "string" },
46650
+ description: "Tags for categorization"
46651
+ }
46652
+ },
46653
+ required: ["summary"]
46654
+ }
46655
+ },
46656
+ {
46657
+ name: "get_context",
46658
+ description: "Find context from peers who explored an area. Check before re-reading files another peer already analyzed.",
46659
+ inputSchema: {
46660
+ type: "object",
46661
+ properties: {
46662
+ query: {
46663
+ type: "string",
46664
+ description: "Search query (file path, topic, etc.)"
46665
+ }
46666
+ },
46667
+ required: ["query"]
46668
+ }
46669
+ },
46670
+ {
46671
+ name: "list_contexts",
46672
+ description: "See what all peers currently know about the codebase.",
46673
+ inputSchema: { type: "object", properties: {} }
46674
+ },
46675
+ {
46676
+ name: "create_task",
46677
+ description: "Create a work item for the mesh.",
46678
+ inputSchema: {
46679
+ type: "object",
46680
+ properties: {
46681
+ title: { type: "string", description: "Task title" },
46682
+ assignee: {
46683
+ type: "string",
46684
+ description: "Peer name to assign (optional)"
46685
+ },
46686
+ priority: {
46687
+ type: "string",
46688
+ enum: ["low", "normal", "high", "urgent"],
46689
+ description: "Priority level (default: normal)"
46690
+ },
46691
+ tags: {
46692
+ type: "array",
46693
+ items: { type: "string" },
46694
+ description: "Tags for categorization"
46695
+ }
46696
+ },
46697
+ required: ["title"]
46698
+ }
46699
+ },
46700
+ {
46701
+ name: "claim_task",
46702
+ description: "Claim an unclaimed task to take ownership.",
46703
+ inputSchema: {
46704
+ type: "object",
46705
+ properties: {
46706
+ id: { type: "string", description: "Task ID" }
46707
+ },
46708
+ required: ["id"]
46709
+ }
46710
+ },
46711
+ {
46712
+ name: "complete_task",
46713
+ description: "Mark a task as done with an optional result summary.",
46714
+ inputSchema: {
46715
+ type: "object",
46716
+ properties: {
46717
+ id: { type: "string", description: "Task ID" },
46718
+ result: {
46719
+ type: "string",
46720
+ description: "Summary of what was done"
46721
+ }
46722
+ },
46723
+ required: ["id"]
46724
+ }
46725
+ },
46726
+ {
46727
+ name: "list_tasks",
46728
+ description: "List tasks filtered by status and/or assignee.",
46729
+ inputSchema: {
46730
+ type: "object",
46731
+ properties: {
46732
+ status: {
46733
+ type: "string",
46734
+ enum: ["open", "claimed", "completed"],
46735
+ description: "Filter by status"
46736
+ },
46737
+ assignee: {
46738
+ type: "string",
46739
+ description: "Filter by assignee name"
46740
+ }
46741
+ }
46742
+ }
46743
+ },
46744
+ {
46745
+ name: "mesh_info",
46746
+ description: "Get a complete overview of the mesh: peers, groups, state, memory, files, tasks, streams, tables. Call on session start for full situational awareness.",
46747
+ inputSchema: { type: "object", properties: {} }
46418
46748
  }
46419
46749
  ];
46420
46750
 
@@ -46719,91 +47049,435 @@ class BrokerClient {
46719
47049
  return;
46720
47050
  this.ws.send(JSON.stringify({ type: "set_state", key, value }));
46721
47051
  }
46722
- async getState(key) {
47052
+ async getState(key) {
47053
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47054
+ return null;
47055
+ return new Promise((resolve) => {
47056
+ this.stateResolvers.push(resolve);
47057
+ this.ws.send(JSON.stringify({ type: "get_state", key }));
47058
+ setTimeout(() => {
47059
+ const idx = this.stateResolvers.indexOf(resolve);
47060
+ if (idx !== -1) {
47061
+ this.stateResolvers.splice(idx, 1);
47062
+ resolve(null);
47063
+ }
47064
+ }, 5000);
47065
+ });
47066
+ }
47067
+ async listState() {
47068
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47069
+ return [];
47070
+ return new Promise((resolve) => {
47071
+ this.stateListResolvers.push(resolve);
47072
+ this.ws.send(JSON.stringify({ type: "list_state" }));
47073
+ setTimeout(() => {
47074
+ const idx = this.stateListResolvers.indexOf(resolve);
47075
+ if (idx !== -1) {
47076
+ this.stateListResolvers.splice(idx, 1);
47077
+ resolve([]);
47078
+ }
47079
+ }, 5000);
47080
+ });
47081
+ }
47082
+ async remember(content, tags) {
47083
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47084
+ return null;
47085
+ return new Promise((resolve) => {
47086
+ this.memoryStoreResolvers.push(resolve);
47087
+ this.ws.send(JSON.stringify({ type: "remember", content, tags }));
47088
+ setTimeout(() => {
47089
+ const idx = this.memoryStoreResolvers.indexOf(resolve);
47090
+ if (idx !== -1) {
47091
+ this.memoryStoreResolvers.splice(idx, 1);
47092
+ resolve(null);
47093
+ }
47094
+ }, 5000);
47095
+ });
47096
+ }
47097
+ async recall(query) {
47098
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47099
+ return [];
47100
+ return new Promise((resolve) => {
47101
+ this.memoryRecallResolvers.push(resolve);
47102
+ this.ws.send(JSON.stringify({ type: "recall", query }));
47103
+ setTimeout(() => {
47104
+ const idx = this.memoryRecallResolvers.indexOf(resolve);
47105
+ if (idx !== -1) {
47106
+ this.memoryRecallResolvers.splice(idx, 1);
47107
+ resolve([]);
47108
+ }
47109
+ }, 5000);
47110
+ });
47111
+ }
47112
+ async forget(memoryId) {
47113
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47114
+ return;
47115
+ this.ws.send(JSON.stringify({ type: "forget", memoryId }));
47116
+ }
47117
+ messageStatusResolvers = [];
47118
+ fileUrlResolvers = [];
47119
+ fileListResolvers = [];
47120
+ fileStatusResolvers = [];
47121
+ vectorStoredResolvers = [];
47122
+ vectorResultsResolvers = [];
47123
+ collectionListResolvers = [];
47124
+ graphResultResolvers = [];
47125
+ contextListResolvers = [];
47126
+ contextResultsResolvers = [];
47127
+ taskCreatedResolvers = [];
47128
+ taskListResolvers = [];
47129
+ meshQueryResolvers = [];
47130
+ meshSchemaResolvers = [];
47131
+ streamCreatedResolvers = [];
47132
+ streamListResolvers = [];
47133
+ streamDataHandlers = new Set;
47134
+ async messageStatus(messageId) {
47135
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47136
+ return null;
47137
+ return new Promise((resolve) => {
47138
+ this.messageStatusResolvers.push(resolve);
47139
+ this.ws.send(JSON.stringify({ type: "message_status", messageId }));
47140
+ setTimeout(() => {
47141
+ const idx = this.messageStatusResolvers.indexOf(resolve);
47142
+ if (idx !== -1) {
47143
+ this.messageStatusResolvers.splice(idx, 1);
47144
+ resolve(null);
47145
+ }
47146
+ }, 5000);
47147
+ });
47148
+ }
47149
+ async getFile(fileId) {
47150
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47151
+ return null;
47152
+ return new Promise((resolve) => {
47153
+ this.fileUrlResolvers.push(resolve);
47154
+ this.ws.send(JSON.stringify({ type: "get_file", fileId }));
47155
+ setTimeout(() => {
47156
+ const idx = this.fileUrlResolvers.indexOf(resolve);
47157
+ if (idx !== -1) {
47158
+ this.fileUrlResolvers.splice(idx, 1);
47159
+ resolve(null);
47160
+ }
47161
+ }, 5000);
47162
+ });
47163
+ }
47164
+ async listFiles(query, from) {
47165
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47166
+ return [];
47167
+ return new Promise((resolve) => {
47168
+ this.fileListResolvers.push(resolve);
47169
+ this.ws.send(JSON.stringify({ type: "list_files", query, from }));
47170
+ setTimeout(() => {
47171
+ const idx = this.fileListResolvers.indexOf(resolve);
47172
+ if (idx !== -1) {
47173
+ this.fileListResolvers.splice(idx, 1);
47174
+ resolve([]);
47175
+ }
47176
+ }, 5000);
47177
+ });
47178
+ }
47179
+ async fileStatus(fileId) {
47180
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47181
+ return [];
47182
+ return new Promise((resolve) => {
47183
+ this.fileStatusResolvers.push(resolve);
47184
+ this.ws.send(JSON.stringify({ type: "file_status", fileId }));
47185
+ setTimeout(() => {
47186
+ const idx = this.fileStatusResolvers.indexOf(resolve);
47187
+ if (idx !== -1) {
47188
+ this.fileStatusResolvers.splice(idx, 1);
47189
+ resolve([]);
47190
+ }
47191
+ }, 5000);
47192
+ });
47193
+ }
47194
+ async deleteFile(fileId) {
47195
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47196
+ return;
47197
+ this.ws.send(JSON.stringify({ type: "delete_file", fileId }));
47198
+ }
47199
+ async uploadFile(filePath, meshId, memberId, opts) {
47200
+ const { readFileSync: readFileSync2 } = await import("node:fs");
47201
+ const { basename } = await import("node:path");
47202
+ const data = readFileSync2(filePath);
47203
+ const fileName = opts.name ?? basename(filePath);
47204
+ const brokerHttp = this.mesh.brokerUrl.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
47205
+ const res = await fetch(`${brokerHttp}/upload`, {
47206
+ method: "POST",
47207
+ headers: {
47208
+ "Content-Type": "application/octet-stream",
47209
+ "X-Mesh-Id": meshId,
47210
+ "X-Member-Id": memberId,
47211
+ "X-File-Name": fileName,
47212
+ "X-Tags": JSON.stringify(opts.tags ?? []),
47213
+ "X-Persistent": String(opts.persistent ?? true),
47214
+ "X-Target-Spec": opts.targetSpec ?? ""
47215
+ },
47216
+ body: data,
47217
+ signal: AbortSignal.timeout(30000)
47218
+ });
47219
+ const body = await res.json();
47220
+ return body.fileId ?? null;
47221
+ }
47222
+ async vectorStore(collection, text, metadata) {
47223
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47224
+ return null;
47225
+ return new Promise((resolve) => {
47226
+ this.vectorStoredResolvers.push(resolve);
47227
+ this.ws.send(JSON.stringify({ type: "vector_store", collection, text, metadata }));
47228
+ setTimeout(() => {
47229
+ const idx = this.vectorStoredResolvers.indexOf(resolve);
47230
+ if (idx !== -1) {
47231
+ this.vectorStoredResolvers.splice(idx, 1);
47232
+ resolve(null);
47233
+ }
47234
+ }, 5000);
47235
+ });
47236
+ }
47237
+ async vectorSearch(collection, query, limit) {
47238
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47239
+ return [];
47240
+ return new Promise((resolve) => {
47241
+ this.vectorResultsResolvers.push(resolve);
47242
+ this.ws.send(JSON.stringify({ type: "vector_search", collection, query, limit }));
47243
+ setTimeout(() => {
47244
+ const idx = this.vectorResultsResolvers.indexOf(resolve);
47245
+ if (idx !== -1) {
47246
+ this.vectorResultsResolvers.splice(idx, 1);
47247
+ resolve([]);
47248
+ }
47249
+ }, 5000);
47250
+ });
47251
+ }
47252
+ async vectorDelete(collection, id) {
47253
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47254
+ return;
47255
+ this.ws.send(JSON.stringify({ type: "vector_delete", collection, id }));
47256
+ }
47257
+ async listCollections() {
47258
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47259
+ return [];
47260
+ return new Promise((resolve) => {
47261
+ this.collectionListResolvers.push(resolve);
47262
+ this.ws.send(JSON.stringify({ type: "list_collections" }));
47263
+ setTimeout(() => {
47264
+ const idx = this.collectionListResolvers.indexOf(resolve);
47265
+ if (idx !== -1) {
47266
+ this.collectionListResolvers.splice(idx, 1);
47267
+ resolve([]);
47268
+ }
47269
+ }, 5000);
47270
+ });
47271
+ }
47272
+ async graphQuery(cypher) {
47273
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47274
+ return [];
47275
+ return new Promise((resolve) => {
47276
+ this.graphResultResolvers.push(resolve);
47277
+ this.ws.send(JSON.stringify({ type: "graph_query", cypher }));
47278
+ setTimeout(() => {
47279
+ const idx = this.graphResultResolvers.indexOf(resolve);
47280
+ if (idx !== -1) {
47281
+ this.graphResultResolvers.splice(idx, 1);
47282
+ resolve([]);
47283
+ }
47284
+ }, 5000);
47285
+ });
47286
+ }
47287
+ async graphExecute(cypher) {
47288
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47289
+ return [];
47290
+ return new Promise((resolve) => {
47291
+ this.graphResultResolvers.push(resolve);
47292
+ this.ws.send(JSON.stringify({ type: "graph_execute", cypher }));
47293
+ setTimeout(() => {
47294
+ const idx = this.graphResultResolvers.indexOf(resolve);
47295
+ if (idx !== -1) {
47296
+ this.graphResultResolvers.splice(idx, 1);
47297
+ resolve([]);
47298
+ }
47299
+ }, 5000);
47300
+ });
47301
+ }
47302
+ async shareContext(summary, filesRead, keyFindings, tags) {
47303
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47304
+ return;
47305
+ this.ws.send(JSON.stringify({ type: "share_context", summary, filesRead, keyFindings, tags }));
47306
+ }
47307
+ async getContext(query) {
47308
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47309
+ return [];
47310
+ return new Promise((resolve) => {
47311
+ this.contextResultsResolvers.push(resolve);
47312
+ this.ws.send(JSON.stringify({ type: "get_context", query }));
47313
+ setTimeout(() => {
47314
+ const idx = this.contextResultsResolvers.indexOf(resolve);
47315
+ if (idx !== -1) {
47316
+ this.contextResultsResolvers.splice(idx, 1);
47317
+ resolve([]);
47318
+ }
47319
+ }, 5000);
47320
+ });
47321
+ }
47322
+ async listContexts() {
47323
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47324
+ return [];
47325
+ return new Promise((resolve) => {
47326
+ this.contextListResolvers.push(resolve);
47327
+ this.ws.send(JSON.stringify({ type: "list_contexts" }));
47328
+ setTimeout(() => {
47329
+ const idx = this.contextListResolvers.indexOf(resolve);
47330
+ if (idx !== -1) {
47331
+ this.contextListResolvers.splice(idx, 1);
47332
+ resolve([]);
47333
+ }
47334
+ }, 5000);
47335
+ });
47336
+ }
47337
+ async createTask(title, assignee, priority, tags) {
47338
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47339
+ return null;
47340
+ return new Promise((resolve) => {
47341
+ this.taskCreatedResolvers.push(resolve);
47342
+ this.ws.send(JSON.stringify({ type: "create_task", title, assignee, priority, tags }));
47343
+ setTimeout(() => {
47344
+ const idx = this.taskCreatedResolvers.indexOf(resolve);
47345
+ if (idx !== -1) {
47346
+ this.taskCreatedResolvers.splice(idx, 1);
47347
+ resolve(null);
47348
+ }
47349
+ }, 5000);
47350
+ });
47351
+ }
47352
+ async claimTask(id) {
47353
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47354
+ return;
47355
+ this.ws.send(JSON.stringify({ type: "claim_task", id }));
47356
+ }
47357
+ async completeTask(id, result) {
47358
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47359
+ return;
47360
+ this.ws.send(JSON.stringify({ type: "complete_task", id, result }));
47361
+ }
47362
+ async listTasks(status, assignee) {
47363
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47364
+ return [];
47365
+ return new Promise((resolve) => {
47366
+ this.taskListResolvers.push(resolve);
47367
+ this.ws.send(JSON.stringify({ type: "list_tasks", status, assignee }));
47368
+ setTimeout(() => {
47369
+ const idx = this.taskListResolvers.indexOf(resolve);
47370
+ if (idx !== -1) {
47371
+ this.taskListResolvers.splice(idx, 1);
47372
+ resolve([]);
47373
+ }
47374
+ }, 5000);
47375
+ });
47376
+ }
47377
+ async meshQuery(sql) {
46723
47378
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
46724
47379
  return null;
46725
47380
  return new Promise((resolve) => {
46726
- this.stateResolvers.push(resolve);
46727
- this.ws.send(JSON.stringify({ type: "get_state", key }));
47381
+ this.meshQueryResolvers.push(resolve);
47382
+ this.ws.send(JSON.stringify({ type: "mesh_query", sql }));
46728
47383
  setTimeout(() => {
46729
- const idx = this.stateResolvers.indexOf(resolve);
47384
+ const idx = this.meshQueryResolvers.indexOf(resolve);
46730
47385
  if (idx !== -1) {
46731
- this.stateResolvers.splice(idx, 1);
47386
+ this.meshQueryResolvers.splice(idx, 1);
46732
47387
  resolve(null);
46733
47388
  }
46734
47389
  }, 5000);
46735
47390
  });
46736
47391
  }
46737
- async listState() {
47392
+ async meshExecute(sql) {
47393
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47394
+ return;
47395
+ this.ws.send(JSON.stringify({ type: "mesh_execute", sql }));
47396
+ }
47397
+ async meshSchema() {
46738
47398
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
46739
47399
  return [];
46740
47400
  return new Promise((resolve) => {
46741
- this.stateListResolvers.push(resolve);
46742
- this.ws.send(JSON.stringify({ type: "list_state" }));
47401
+ this.meshSchemaResolvers.push(resolve);
47402
+ this.ws.send(JSON.stringify({ type: "mesh_schema" }));
46743
47403
  setTimeout(() => {
46744
- const idx = this.stateListResolvers.indexOf(resolve);
47404
+ const idx = this.meshSchemaResolvers.indexOf(resolve);
46745
47405
  if (idx !== -1) {
46746
- this.stateListResolvers.splice(idx, 1);
47406
+ this.meshSchemaResolvers.splice(idx, 1);
46747
47407
  resolve([]);
46748
47408
  }
46749
47409
  }, 5000);
46750
47410
  });
46751
47411
  }
46752
- async remember(content, tags) {
47412
+ async createStream(name) {
46753
47413
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
46754
47414
  return null;
46755
47415
  return new Promise((resolve) => {
46756
- this.memoryStoreResolvers.push(resolve);
46757
- this.ws.send(JSON.stringify({ type: "remember", content, tags }));
47416
+ this.streamCreatedResolvers.push(resolve);
47417
+ this.ws.send(JSON.stringify({ type: "create_stream", name }));
46758
47418
  setTimeout(() => {
46759
- const idx = this.memoryStoreResolvers.indexOf(resolve);
47419
+ const idx = this.streamCreatedResolvers.indexOf(resolve);
46760
47420
  if (idx !== -1) {
46761
- this.memoryStoreResolvers.splice(idx, 1);
47421
+ this.streamCreatedResolvers.splice(idx, 1);
46762
47422
  resolve(null);
46763
47423
  }
46764
47424
  }, 5000);
46765
47425
  });
46766
47426
  }
46767
- async recall(query) {
47427
+ async publish(stream, data) {
47428
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47429
+ return;
47430
+ this.ws.send(JSON.stringify({ type: "publish", stream, data }));
47431
+ }
47432
+ async subscribe(stream) {
47433
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47434
+ return;
47435
+ this.ws.send(JSON.stringify({ type: "subscribe", stream }));
47436
+ }
47437
+ async unsubscribe(stream) {
47438
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47439
+ return;
47440
+ this.ws.send(JSON.stringify({ type: "unsubscribe", stream }));
47441
+ }
47442
+ async listStreams() {
46768
47443
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
46769
47444
  return [];
46770
47445
  return new Promise((resolve) => {
46771
- this.memoryRecallResolvers.push(resolve);
46772
- this.ws.send(JSON.stringify({ type: "recall", query }));
47446
+ this.streamListResolvers.push(resolve);
47447
+ this.ws.send(JSON.stringify({ type: "list_streams" }));
46773
47448
  setTimeout(() => {
46774
- const idx = this.memoryRecallResolvers.indexOf(resolve);
47449
+ const idx = this.streamListResolvers.indexOf(resolve);
46775
47450
  if (idx !== -1) {
46776
- this.memoryRecallResolvers.splice(idx, 1);
47451
+ this.streamListResolvers.splice(idx, 1);
46777
47452
  resolve([]);
46778
47453
  }
46779
47454
  }, 5000);
46780
47455
  });
46781
47456
  }
46782
- async forget(memoryId) {
46783
- if (!this.ws || this.ws.readyState !== this.ws.OPEN)
46784
- return;
46785
- this.ws.send(JSON.stringify({ type: "forget", memoryId }));
47457
+ onStreamData(handler) {
47458
+ this.streamDataHandlers.add(handler);
47459
+ return () => this.streamDataHandlers.delete(handler);
46786
47460
  }
46787
- messageStatusResolvers = [];
46788
- async messageStatus(messageId) {
47461
+ onStateChange(handler) {
47462
+ this.stateChangeHandlers.add(handler);
47463
+ return () => this.stateChangeHandlers.delete(handler);
47464
+ }
47465
+ meshInfoResolvers = [];
47466
+ async meshInfo() {
46789
47467
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
46790
47468
  return null;
46791
47469
  return new Promise((resolve) => {
46792
- this.messageStatusResolvers.push(resolve);
46793
- this.ws.send(JSON.stringify({ type: "message_status", messageId }));
47470
+ this.meshInfoResolvers.push(resolve);
47471
+ this.ws.send(JSON.stringify({ type: "mesh_info" }));
46794
47472
  setTimeout(() => {
46795
- const idx = this.messageStatusResolvers.indexOf(resolve);
47473
+ const idx = this.meshInfoResolvers.indexOf(resolve);
46796
47474
  if (idx !== -1) {
46797
- this.messageStatusResolvers.splice(idx, 1);
47475
+ this.meshInfoResolvers.splice(idx, 1);
46798
47476
  resolve(null);
46799
47477
  }
46800
47478
  }, 5000);
46801
47479
  });
46802
47480
  }
46803
- onStateChange(handler) {
46804
- this.stateChangeHandlers.add(handler);
46805
- return () => this.stateChangeHandlers.delete(handler);
46806
- }
46807
47481
  close() {
46808
47482
  this.closed = true;
46809
47483
  if (this.helloTimer)
@@ -46941,6 +47615,139 @@ class BrokerClient {
46941
47615
  resolver(msg);
46942
47616
  return;
46943
47617
  }
47618
+ if (msg.type === "file_url") {
47619
+ const resolver = this.fileUrlResolvers.shift();
47620
+ if (resolver) {
47621
+ if (msg.url) {
47622
+ resolver({ url: String(msg.url), name: String(msg.name ?? "") });
47623
+ } else {
47624
+ resolver(null);
47625
+ }
47626
+ }
47627
+ return;
47628
+ }
47629
+ if (msg.type === "file_list") {
47630
+ const files = msg.files ?? [];
47631
+ const resolver = this.fileListResolvers.shift();
47632
+ if (resolver)
47633
+ resolver(files);
47634
+ return;
47635
+ }
47636
+ if (msg.type === "file_status_result") {
47637
+ const accesses = msg.accesses ?? [];
47638
+ const resolver = this.fileStatusResolvers.shift();
47639
+ if (resolver)
47640
+ resolver(accesses);
47641
+ return;
47642
+ }
47643
+ if (msg.type === "vector_stored") {
47644
+ const resolver = this.vectorStoredResolvers.shift();
47645
+ if (resolver)
47646
+ resolver(msg.id ? String(msg.id) : null);
47647
+ return;
47648
+ }
47649
+ if (msg.type === "vector_results") {
47650
+ const results = msg.results ?? [];
47651
+ const resolver = this.vectorResultsResolvers.shift();
47652
+ if (resolver)
47653
+ resolver(results);
47654
+ return;
47655
+ }
47656
+ if (msg.type === "collection_list") {
47657
+ const collections = msg.collections ?? [];
47658
+ const resolver = this.collectionListResolvers.shift();
47659
+ if (resolver)
47660
+ resolver(collections);
47661
+ return;
47662
+ }
47663
+ if (msg.type === "graph_result") {
47664
+ const rows = msg.rows ?? [];
47665
+ const resolver = this.graphResultResolvers.shift();
47666
+ if (resolver)
47667
+ resolver(rows);
47668
+ return;
47669
+ }
47670
+ if (msg.type === "context_list") {
47671
+ const contexts = msg.contexts ?? [];
47672
+ const resolver = this.contextListResolvers.shift();
47673
+ if (resolver)
47674
+ resolver(contexts);
47675
+ return;
47676
+ }
47677
+ if (msg.type === "context_results") {
47678
+ const contexts = msg.contexts ?? [];
47679
+ const resolver = this.contextResultsResolvers.shift();
47680
+ if (resolver)
47681
+ resolver(contexts);
47682
+ return;
47683
+ }
47684
+ if (msg.type === "task_created") {
47685
+ const resolver = this.taskCreatedResolvers.shift();
47686
+ if (resolver)
47687
+ resolver(msg.id ? String(msg.id) : null);
47688
+ return;
47689
+ }
47690
+ if (msg.type === "task_list") {
47691
+ const tasks = msg.tasks ?? [];
47692
+ const resolver = this.taskListResolvers.shift();
47693
+ if (resolver)
47694
+ resolver(tasks);
47695
+ return;
47696
+ }
47697
+ if (msg.type === "mesh_query_result") {
47698
+ const resolver = this.meshQueryResolvers.shift();
47699
+ if (resolver) {
47700
+ if (msg.columns) {
47701
+ resolver({
47702
+ columns: msg.columns ?? [],
47703
+ rows: msg.rows ?? [],
47704
+ rowCount: msg.rowCount ?? 0
47705
+ });
47706
+ } else {
47707
+ resolver(null);
47708
+ }
47709
+ }
47710
+ return;
47711
+ }
47712
+ if (msg.type === "mesh_schema_result") {
47713
+ const tables = msg.tables ?? [];
47714
+ const resolver = this.meshSchemaResolvers.shift();
47715
+ if (resolver)
47716
+ resolver(tables);
47717
+ return;
47718
+ }
47719
+ if (msg.type === "stream_created") {
47720
+ const resolver = this.streamCreatedResolvers.shift();
47721
+ if (resolver)
47722
+ resolver(msg.id ? String(msg.id) : null);
47723
+ return;
47724
+ }
47725
+ if (msg.type === "stream_list") {
47726
+ const streams = msg.streams ?? [];
47727
+ const resolver = this.streamListResolvers.shift();
47728
+ if (resolver)
47729
+ resolver(streams);
47730
+ return;
47731
+ }
47732
+ if (msg.type === "stream_data") {
47733
+ const evt = {
47734
+ stream: String(msg.stream ?? ""),
47735
+ data: msg.data,
47736
+ publishedBy: String(msg.publishedBy ?? "")
47737
+ };
47738
+ for (const h of this.streamDataHandlers) {
47739
+ try {
47740
+ h(evt);
47741
+ } catch {}
47742
+ }
47743
+ return;
47744
+ }
47745
+ if (msg.type === "mesh_info_result") {
47746
+ const resolver = this.meshInfoResolvers.shift();
47747
+ if (resolver)
47748
+ resolver(msg);
47749
+ return;
47750
+ }
46944
47751
  if (msg.type === "error") {
46945
47752
  this.debug(`broker error: ${msg.code} ${msg.message}`);
46946
47753
  const id = msg.id ? String(msg.id) : null;
@@ -47141,9 +47948,44 @@ When you receive a <channel source="claudemesh" ...> message, RESPOND IMMEDIATEL
47141
47948
  | remember(content, tags?) | Store persistent knowledge with optional tags. |
47142
47949
  | recall(query) | Full-text search over mesh memory. |
47143
47950
  | forget(id) | Soft-delete a memory entry. |
47951
+ | share_file(path, name?, tags?) | Share a persistent file with the mesh. |
47952
+ | get_file(id, save_to) | Download a shared file to a local path. |
47953
+ | list_files(query?, from?) | Find files shared in the mesh. |
47954
+ | file_status(id) | Check who has accessed a file. |
47955
+ | delete_file(id) | Remove a shared file from the mesh. |
47956
+ | vector_store(collection, text, metadata?) | Store embedding in per-mesh Qdrant collection. |
47957
+ | vector_search(collection, query, limit?) | Semantic search over stored embeddings. |
47958
+ | vector_delete(collection, id) | Remove an embedding. |
47959
+ | list_collections() | List vector collections in this mesh. |
47960
+ | graph_query(cypher) | Read-only Cypher query on per-mesh Neo4j. |
47961
+ | graph_execute(cypher) | Write Cypher query (CREATE, MERGE, DELETE). |
47962
+ | mesh_query(sql) | Run a SELECT query on the per-mesh shared database. |
47963
+ | mesh_execute(sql) | Run DDL/DML on the per-mesh database (CREATE TABLE, INSERT, UPDATE, DELETE). |
47964
+ | mesh_schema() | List tables and columns in the per-mesh shared database. |
47965
+ | create_stream(name) | Create a real-time data stream in the mesh. |
47966
+ | publish(stream, data) | Push data to a stream. Subscribers receive it in real-time. |
47967
+ | subscribe(stream) | Subscribe to a stream. Data pushes arrive as channel notifications. |
47968
+ | list_streams() | List active streams in the mesh. |
47969
+ | share_context(summary, files_read?, key_findings?, tags?) | Share session understanding with peers. |
47970
+ | get_context(query) | Find context from peers who explored an area. |
47971
+ | list_contexts() | See what all peers currently know. |
47972
+ | create_task(title, assignee?, priority?, tags?) | Create a work item. |
47973
+ | claim_task(id) | Claim an unclaimed task. |
47974
+ | complete_task(id, result?) | Mark task done with optional result. |
47975
+ | list_tasks(status?, assignee?) | List tasks filtered by status/assignee. |
47144
47976
 
47145
47977
  If multiple meshes are joined, prefix \`to\` with \`<mesh-slug>:\` to disambiguate (e.g. \`dev-team:Alice\`).
47146
47978
 
47979
+ Multi-target: send_message accepts an array of targets for the 'to' field.
47980
+ send_message(to: ["Alice", "@backend"], message: "sprint starts")
47981
+ Targets are deduplicated — each peer receives the message once.
47982
+
47983
+ Targeted views: when different audiences need different details about the same event,
47984
+ send tailored messages instead of one generic broadcast:
47985
+ send_message(to: "@frontend", message: "Auth v2: useAuth hook changed, see src/auth/")
47986
+ send_message(to: "@backend", message: "Auth v2: new /api/auth/v2 endpoints, v1 deprecated")
47987
+ send_message(to: "@pm", message: "Auth v2 done. 3 points, no blockers.")
47988
+
47147
47989
  ## Groups
47148
47990
  Groups are routing labels. Send to @groupname to multicast to all members. Roles are metadata that peers interpret: a "lead" gathers input before synthesizing a response, a "member" contributes when asked, an "observer" watches silently. Join and leave groups dynamically with join_group/leave_group. Check list_peers to see who belongs to which groups and their roles.
47149
47991
 
@@ -47153,6 +47995,28 @@ Shared key-value store scoped to the mesh. Use get_state/set_state for live coor
47153
47995
  ## Memory
47154
47996
  Persistent knowledge that survives across sessions. Use remember(content, tags?) to store lessons, decisions, and incidents. Use recall(query) to search before asking peers. New peers should recall at session start to load institutional knowledge.
47155
47997
 
47998
+ ## Files
47999
+ share_file for persistent references, send_message(file:) for ephemeral attachments.
48000
+ Tags on shared files make them searchable. Use list_files to find what peers shared.
48001
+
48002
+ ## Vectors
48003
+ Store and search semantic embeddings. Use vector_store to index content, vector_search to find similar content.
48004
+
48005
+ ## Graph
48006
+ Build and query entity relationship graphs. Use graph_execute for writes (CREATE, MERGE), graph_query for reads (MATCH).
48007
+
48008
+ ## Mesh Database
48009
+ Per-mesh PostgreSQL database. Use mesh_execute for DDL/DML (CREATE TABLE, INSERT), mesh_query for SELECT, mesh_schema to inspect tables. Schema auto-created on first use.
48010
+
48011
+ ## Streams
48012
+ Real-time data channels. create_stream to start one, publish to push data, subscribe to receive pushes. Use for build logs, deploy status, live metrics.
48013
+
48014
+ ## Context
48015
+ Share your session understanding with peers. Use share_context after exploring a codebase area. Check get_context before re-reading files another peer already analyzed.
48016
+
48017
+ ## Tasks
48018
+ Create and claim work items. create_task to propose work, claim_task to take ownership, complete_task when done. Prevents duplicate effort.
48019
+
47156
48020
  ## Priority
47157
48021
  - "now": interrupt immediately, even if recipient is in DND (use for urgent: broken deploy, blocking issue)
47158
48022
  - "next" (default): deliver when recipient goes idle (normal coordination)
@@ -47174,13 +48038,27 @@ Call list_peers at session start to understand who is online, their roles, and w
47174
48038
  const { to, message, priority } = args ?? {};
47175
48039
  if (!to || !message)
47176
48040
  return text("send_message: `to` and `message` required", true);
47177
- const { client, targetSpec, error: error2 } = await resolveClient(to);
47178
- if (!client)
47179
- return text(`send_message: ${error2 ?? "no client resolved"}`, true);
47180
- const result = await client.send(targetSpec, message, priority ?? "next");
47181
- if (!result.ok)
47182
- return text(`send_message failed (${client.meshSlug}): ${result.error}`, true);
47183
- return text(`Sent to ${targetSpec} via ${client.meshSlug} [${priority ?? "next"}] ${result.messageId}`);
48041
+ const targets = Array.isArray(to) ? to : [to];
48042
+ const results = [];
48043
+ const seen = new Set;
48044
+ for (const target of targets) {
48045
+ const { client, targetSpec, error: error2 } = await resolveClient(target);
48046
+ if (!client) {
48047
+ results.push(`✗ ${target}: ${error2 ?? "no client resolved"}`);
48048
+ continue;
48049
+ }
48050
+ if (seen.has(targetSpec))
48051
+ continue;
48052
+ seen.add(targetSpec);
48053
+ const result = await client.send(targetSpec, message, priority ?? "next");
48054
+ if (!result.ok) {
48055
+ results.push(`✗ ${target}: ${result.error}`);
48056
+ } else {
48057
+ results.push(`✓ ${target} → ${result.messageId}`);
48058
+ }
48059
+ }
48060
+ return text(results.join(`
48061
+ `));
47184
48062
  }
47185
48063
  case "list_peers": {
47186
48064
  const { mesh_slug } = args ?? {};
@@ -47342,6 +48220,341 @@ ${lines.join(`
47342
48220
  await client.forget(id);
47343
48221
  return text(`Forgotten: ${id}`);
47344
48222
  }
48223
+ case "share_file": {
48224
+ const { path: filePath, name: fileName, tags } = args ?? {};
48225
+ if (!filePath)
48226
+ return text("share_file: `path` required", true);
48227
+ const { existsSync: existsSync2 } = await import("node:fs");
48228
+ if (!existsSync2(filePath))
48229
+ return text(`share_file: file not found: ${filePath}`, true);
48230
+ const client = allClients()[0];
48231
+ if (!client)
48232
+ return text("share_file: not connected", true);
48233
+ const fileId = await client.uploadFile(filePath, client.meshId, client.meshSlug, {
48234
+ name: fileName,
48235
+ tags,
48236
+ persistent: true
48237
+ });
48238
+ if (!fileId)
48239
+ return text("share_file: upload failed", true);
48240
+ return text(`Shared: ${fileName ?? filePath} (${fileId})`);
48241
+ }
48242
+ case "get_file": {
48243
+ const { id, save_to } = args ?? {};
48244
+ if (!id || !save_to)
48245
+ return text("get_file: `id` and `save_to` required", true);
48246
+ const client = allClients()[0];
48247
+ if (!client)
48248
+ return text("get_file: not connected", true);
48249
+ const result = await client.getFile(id);
48250
+ if (!result)
48251
+ return text(`get_file: file ${id} not found`, true);
48252
+ const res = await fetch(result.url, { signal: AbortSignal.timeout(30000) });
48253
+ if (!res.ok)
48254
+ return text(`get_file: download failed (${res.status})`, true);
48255
+ const { writeFileSync: writeFileSync2, mkdirSync: mkdirSync2 } = await import("node:fs");
48256
+ const { dirname: dirname2 } = await import("node:path");
48257
+ mkdirSync2(dirname2(save_to), { recursive: true });
48258
+ writeFileSync2(save_to, Buffer.from(await res.arrayBuffer()));
48259
+ return text(`Downloaded: ${result.name} → ${save_to}`);
48260
+ }
48261
+ case "list_files": {
48262
+ const { query, from } = args ?? {};
48263
+ const client = allClients()[0];
48264
+ if (!client)
48265
+ return text("list_files: not connected", true);
48266
+ const files = await client.listFiles(query, from);
48267
+ if (files.length === 0)
48268
+ return text("No files found.");
48269
+ const lines = files.map((f) => `- **${f.name}** (${f.id.slice(0, 8)}…, ${f.size} bytes) by ${f.uploadedBy}${f.tags.length ? ` [${f.tags.join(", ")}]` : ""}`);
48270
+ return text(lines.join(`
48271
+ `));
48272
+ }
48273
+ case "file_status": {
48274
+ const { id } = args ?? {};
48275
+ if (!id)
48276
+ return text("file_status: `id` required", true);
48277
+ const client = allClients()[0];
48278
+ if (!client)
48279
+ return text("file_status: not connected", true);
48280
+ const accesses = await client.fileStatus(id);
48281
+ if (accesses.length === 0)
48282
+ return text("No one has accessed this file yet.");
48283
+ const lines = accesses.map((a) => `- ${a.peerName} at ${a.accessedAt}`);
48284
+ return text(`Accessed by:
48285
+ ${lines.join(`
48286
+ `)}`);
48287
+ }
48288
+ case "delete_file": {
48289
+ const { id } = args ?? {};
48290
+ if (!id)
48291
+ return text("delete_file: `id` required", true);
48292
+ const client = allClients()[0];
48293
+ if (!client)
48294
+ return text("delete_file: not connected", true);
48295
+ await client.deleteFile(id);
48296
+ return text(`Deleted: ${id}`);
48297
+ }
48298
+ case "vector_store": {
48299
+ const { collection, text: storeText, metadata } = args ?? {};
48300
+ if (!collection || !storeText)
48301
+ return text("vector_store: `collection` and `text` required", true);
48302
+ const client = allClients()[0];
48303
+ if (!client)
48304
+ return text("vector_store: not connected", true);
48305
+ const id = await client.vectorStore(collection, storeText, metadata);
48306
+ return text(`Stored in ${collection}${id ? ` (${id})` : ""}`);
48307
+ }
48308
+ case "vector_search": {
48309
+ const { collection, query, limit } = args ?? {};
48310
+ if (!collection || !query)
48311
+ return text("vector_search: `collection` and `query` required", true);
48312
+ const client = allClients()[0];
48313
+ if (!client)
48314
+ return text("vector_search: not connected", true);
48315
+ const results = await client.vectorSearch(collection, query, limit);
48316
+ if (results.length === 0)
48317
+ return text(`No results in ${collection} for "${query}".`);
48318
+ const lines = results.map((r) => `- [${r.id.slice(0, 8)}…] (score: ${r.score.toFixed(3)}) ${r.text.slice(0, 120)}${r.text.length > 120 ? "…" : ""}`);
48319
+ return text(`${results.length} result(s) in ${collection}:
48320
+ ${lines.join(`
48321
+ `)}`);
48322
+ }
48323
+ case "vector_delete": {
48324
+ const { collection, id } = args ?? {};
48325
+ if (!collection || !id)
48326
+ return text("vector_delete: `collection` and `id` required", true);
48327
+ const client = allClients()[0];
48328
+ if (!client)
48329
+ return text("vector_delete: not connected", true);
48330
+ await client.vectorDelete(collection, id);
48331
+ return text(`Deleted ${id} from ${collection}`);
48332
+ }
48333
+ case "list_collections": {
48334
+ const client = allClients()[0];
48335
+ if (!client)
48336
+ return text("list_collections: not connected", true);
48337
+ const collections = await client.listCollections();
48338
+ if (collections.length === 0)
48339
+ return text("No vector collections.");
48340
+ return text(`Collections:
48341
+ ${collections.map((c) => `- ${c}`).join(`
48342
+ `)}`);
48343
+ }
48344
+ case "graph_query": {
48345
+ const { cypher } = args ?? {};
48346
+ if (!cypher)
48347
+ return text("graph_query: `cypher` required", true);
48348
+ const client = allClients()[0];
48349
+ if (!client)
48350
+ return text("graph_query: not connected", true);
48351
+ const rows = await client.graphQuery(cypher);
48352
+ if (rows.length === 0)
48353
+ return text("No results.");
48354
+ return text(JSON.stringify(rows, null, 2));
48355
+ }
48356
+ case "graph_execute": {
48357
+ const { cypher } = args ?? {};
48358
+ if (!cypher)
48359
+ return text("graph_execute: `cypher` required", true);
48360
+ const client = allClients()[0];
48361
+ if (!client)
48362
+ return text("graph_execute: not connected", true);
48363
+ const rows = await client.graphExecute(cypher);
48364
+ return text(rows.length > 0 ? JSON.stringify(rows, null, 2) : "Executed successfully.");
48365
+ }
48366
+ case "share_context": {
48367
+ const { summary, files_read, key_findings, tags } = args ?? {};
48368
+ if (!summary)
48369
+ return text("share_context: `summary` required", true);
48370
+ const client = allClients()[0];
48371
+ if (!client)
48372
+ return text("share_context: not connected", true);
48373
+ await client.shareContext(summary, files_read, key_findings, tags);
48374
+ return text(`Context shared: "${summary.slice(0, 80)}${summary.length > 80 ? "…" : ""}"`);
48375
+ }
48376
+ case "get_context": {
48377
+ const { query } = args ?? {};
48378
+ if (!query)
48379
+ return text("get_context: `query` required", true);
48380
+ const client = allClients()[0];
48381
+ if (!client)
48382
+ return text("get_context: not connected", true);
48383
+ const contexts = await client.getContext(query);
48384
+ if (contexts.length === 0)
48385
+ return text(`No context found for "${query}".`);
48386
+ const lines = contexts.map((c) => {
48387
+ const files = c.filesRead.length ? `
48388
+ Files: ${c.filesRead.join(", ")}` : "";
48389
+ const findings = c.keyFindings.length ? `
48390
+ Findings: ${c.keyFindings.join("; ")}` : "";
48391
+ return `- **${c.peerName}** (${c.updatedAt}): ${c.summary}${files}${findings}`;
48392
+ });
48393
+ return text(`${contexts.length} context(s):
48394
+ ${lines.join(`
48395
+ `)}`);
48396
+ }
48397
+ case "list_contexts": {
48398
+ const client = allClients()[0];
48399
+ if (!client)
48400
+ return text("list_contexts: not connected", true);
48401
+ const contexts = await client.listContexts();
48402
+ if (contexts.length === 0)
48403
+ return text("No peer contexts shared yet.");
48404
+ const lines = contexts.map((c) => `- **${c.peerName}**: ${c.summary}${c.tags.length ? ` [${c.tags.join(", ")}]` : ""}`);
48405
+ return text(`Peer contexts:
48406
+ ${lines.join(`
48407
+ `)}`);
48408
+ }
48409
+ case "create_task": {
48410
+ const { title, assignee, priority, tags } = args ?? {};
48411
+ if (!title)
48412
+ return text("create_task: `title` required", true);
48413
+ const client = allClients()[0];
48414
+ if (!client)
48415
+ return text("create_task: not connected", true);
48416
+ const id = await client.createTask(title, assignee, priority, tags);
48417
+ return text(`Task created${id ? ` (${id})` : ""}: "${title}"${assignee ? ` → ${assignee}` : ""}`);
48418
+ }
48419
+ case "claim_task": {
48420
+ const { id } = args ?? {};
48421
+ if (!id)
48422
+ return text("claim_task: `id` required", true);
48423
+ const client = allClients()[0];
48424
+ if (!client)
48425
+ return text("claim_task: not connected", true);
48426
+ await client.claimTask(id);
48427
+ return text(`Claimed task: ${id}`);
48428
+ }
48429
+ case "complete_task": {
48430
+ const { id, result } = args ?? {};
48431
+ if (!id)
48432
+ return text("complete_task: `id` required", true);
48433
+ const client = allClients()[0];
48434
+ if (!client)
48435
+ return text("complete_task: not connected", true);
48436
+ await client.completeTask(id, result);
48437
+ return text(`Completed task: ${id}${result ? ` — ${result}` : ""}`);
48438
+ }
48439
+ case "list_tasks": {
48440
+ const { status, assignee } = args ?? {};
48441
+ const client = allClients()[0];
48442
+ if (!client)
48443
+ return text("list_tasks: not connected", true);
48444
+ const tasks = await client.listTasks(status, assignee);
48445
+ if (tasks.length === 0)
48446
+ return text("No tasks found.");
48447
+ const lines = tasks.map((t) => `- [${t.id.slice(0, 8)}…] **${t.title}** (${t.status}, ${t.priority}) ${t.assignee ? `→ ${t.assignee}` : "unassigned"} (by ${t.createdBy})`);
48448
+ return text(`${tasks.length} task(s):
48449
+ ${lines.join(`
48450
+ `)}`);
48451
+ }
48452
+ case "mesh_query": {
48453
+ const { sql: querySql } = args ?? {};
48454
+ if (!querySql)
48455
+ return text("mesh_query: `sql` required", true);
48456
+ const client = allClients()[0];
48457
+ if (!client)
48458
+ return text("mesh_query: not connected", true);
48459
+ const result = await client.meshQuery(querySql);
48460
+ if (!result)
48461
+ return text("mesh_query: query failed or timed out", true);
48462
+ if (result.rows.length === 0)
48463
+ return text(`Query returned 0 rows.`);
48464
+ const header = `| ${result.columns.join(" | ")} |`;
48465
+ const sep = `| ${result.columns.map(() => "---").join(" | ")} |`;
48466
+ const rows = result.rows.map((r) => `| ${result.columns.map((c) => String(r[c] ?? "")).join(" | ")} |`);
48467
+ return text(`${result.rowCount} row(s):
48468
+ ${header}
48469
+ ${sep}
48470
+ ${rows.join(`
48471
+ `)}`);
48472
+ }
48473
+ case "mesh_execute": {
48474
+ const { sql: execSql } = args ?? {};
48475
+ if (!execSql)
48476
+ return text("mesh_execute: `sql` required", true);
48477
+ const client = allClients()[0];
48478
+ if (!client)
48479
+ return text("mesh_execute: not connected", true);
48480
+ await client.meshExecute(execSql);
48481
+ return text(`Executed.`);
48482
+ }
48483
+ case "mesh_schema": {
48484
+ const client = allClients()[0];
48485
+ if (!client)
48486
+ return text("mesh_schema: not connected", true);
48487
+ const tables = await client.meshSchema();
48488
+ if (!tables || tables.length === 0)
48489
+ return text("No tables in mesh database.");
48490
+ const lines = tables.map((t) => `**${t.name}**: ${t.columns.map((c) => `${c.name} (${c.type}${c.nullable ? ", nullable" : ""})`).join(", ")}`);
48491
+ return text(lines.join(`
48492
+ `));
48493
+ }
48494
+ case "create_stream": {
48495
+ const { name: streamName } = args ?? {};
48496
+ if (!streamName)
48497
+ return text("create_stream: `name` required", true);
48498
+ const client = allClients()[0];
48499
+ if (!client)
48500
+ return text("create_stream: not connected", true);
48501
+ const streamId = await client.createStream(streamName);
48502
+ return text(`Stream created: ${streamName}${streamId ? ` (${streamId})` : ""}`);
48503
+ }
48504
+ case "publish": {
48505
+ const { stream: pubStream, data: pubData } = args ?? {};
48506
+ if (!pubStream)
48507
+ return text("publish: `stream` required", true);
48508
+ const client = allClients()[0];
48509
+ if (!client)
48510
+ return text("publish: not connected", true);
48511
+ await client.publish(pubStream, pubData);
48512
+ return text(`Published to ${pubStream}.`);
48513
+ }
48514
+ case "subscribe": {
48515
+ const { stream: subStream } = args ?? {};
48516
+ if (!subStream)
48517
+ return text("subscribe: `stream` required", true);
48518
+ const client = allClients()[0];
48519
+ if (!client)
48520
+ return text("subscribe: not connected", true);
48521
+ await client.subscribe(subStream);
48522
+ return text(`Subscribed to ${subStream}. Data pushes will arrive as channel notifications.`);
48523
+ }
48524
+ case "list_streams": {
48525
+ const client = allClients()[0];
48526
+ if (!client)
48527
+ return text("list_streams: not connected", true);
48528
+ const streams = await client.listStreams();
48529
+ if (streams.length === 0)
48530
+ return text("No active streams.");
48531
+ const lines = streams.map((s) => `- **${s.name}** (${s.id.slice(0, 8)}…) by ${s.createdBy}, ${s.subscriberCount} subscriber(s)`);
48532
+ return text(lines.join(`
48533
+ `));
48534
+ }
48535
+ case "mesh_info": {
48536
+ const client = allClients()[0];
48537
+ if (!client)
48538
+ return text("mesh_info: not connected", true);
48539
+ const info = await client.meshInfo();
48540
+ if (!info)
48541
+ return text("mesh_info: timed out", true);
48542
+ const lines = [
48543
+ `**Mesh**: ${info.mesh}`,
48544
+ `**Peers**: ${info.peers}`,
48545
+ `**Groups**: ${info.groups?.join(", ") || "none"}`,
48546
+ `**State keys**: ${info.stateKeys?.join(", ") || "none"}`,
48547
+ `**Memories**: ${info.memoryCount}`,
48548
+ `**Files**: ${info.fileCount}`,
48549
+ `**Tasks**: open=${info.tasks?.open ?? 0}, claimed=${info.tasks?.claimed ?? 0}, done=${info.tasks?.done ?? 0}`,
48550
+ `**Streams**: ${info.streams?.join(", ") || "none"}`,
48551
+ `**Tables**: ${info.tables?.join(", ") || "none"}`,
48552
+ `**Your name**: ${info.yourName}`,
48553
+ `**Your groups**: ${info.yourGroups?.map((g) => `@${g.name}${g.role ? ":" + g.role : ""}`).join(", ") || "none"}`
48554
+ ];
48555
+ return text(lines.join(`
48556
+ `));
48557
+ }
47345
48558
  default:
47346
48559
  return text(`Unknown tool: ${name}`, true);
47347
48560
  }
@@ -47373,6 +48586,21 @@ ${lines.join(`
47373
48586
  });
47374
48587
  } catch {}
47375
48588
  });
48589
+ client.onStreamData(async (evt) => {
48590
+ try {
48591
+ await server.notification({
48592
+ method: "notifications/claude/channel",
48593
+ params: {
48594
+ content: `[stream:${evt.stream}] from ${evt.publishedBy}: ${JSON.stringify(evt.data)}`,
48595
+ meta: {
48596
+ kind: "stream_data",
48597
+ stream: evt.stream,
48598
+ published_by: evt.publishedBy
48599
+ }
48600
+ }
48601
+ });
48602
+ } catch {}
48603
+ });
47376
48604
  client.onStateChange(async (change) => {
47377
48605
  try {
47378
48606
  await server.notification({
@@ -48273,7 +49501,7 @@ init_config();
48273
49501
  // package.json
48274
49502
  var package_default = {
48275
49503
  name: "claudemesh-cli",
48276
- version: "0.3.0",
49504
+ version: "0.5.0",
48277
49505
  description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
48278
49506
  keywords: [
48279
49507
  "claude-code",