claudemesh-cli 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1006 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6514,7 +6514,7 @@ function loadConfig() {
|
|
|
6514
6514
|
if (!parsed || !Array.isArray(parsed.meshes)) {
|
|
6515
6515
|
return { version: 1, meshes: [] };
|
|
6516
6516
|
}
|
|
6517
|
-
return { version: 1, meshes: parsed.meshes, displayName: parsed.displayName, groups: parsed.groups };
|
|
6517
|
+
return { version: 1, meshes: parsed.meshes, displayName: parsed.displayName, groups: parsed.groups, messageMode: parsed.messageMode };
|
|
6518
6518
|
} catch (e) {
|
|
6519
6519
|
throw new Error(`Failed to load ${CONFIG_PATH}: ${e instanceof Error ? e.message : String(e)}`);
|
|
6520
6520
|
}
|
|
@@ -46486,6 +46486,265 @@ var TOOLS = [
|
|
|
46486
46486
|
},
|
|
46487
46487
|
required: ["id"]
|
|
46488
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: {} }
|
|
46489
46748
|
}
|
|
46490
46749
|
];
|
|
46491
46750
|
|
|
@@ -46859,6 +47118,19 @@ class BrokerClient {
|
|
|
46859
47118
|
fileUrlResolvers = [];
|
|
46860
47119
|
fileListResolvers = [];
|
|
46861
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;
|
|
46862
47134
|
async messageStatus(messageId) {
|
|
46863
47135
|
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
46864
47136
|
return null;
|
|
@@ -46947,10 +47219,265 @@ class BrokerClient {
|
|
|
46947
47219
|
const body = await res.json();
|
|
46948
47220
|
return body.fileId ?? null;
|
|
46949
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) {
|
|
47378
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
47379
|
+
return null;
|
|
47380
|
+
return new Promise((resolve) => {
|
|
47381
|
+
this.meshQueryResolvers.push(resolve);
|
|
47382
|
+
this.ws.send(JSON.stringify({ type: "mesh_query", sql }));
|
|
47383
|
+
setTimeout(() => {
|
|
47384
|
+
const idx = this.meshQueryResolvers.indexOf(resolve);
|
|
47385
|
+
if (idx !== -1) {
|
|
47386
|
+
this.meshQueryResolvers.splice(idx, 1);
|
|
47387
|
+
resolve(null);
|
|
47388
|
+
}
|
|
47389
|
+
}, 5000);
|
|
47390
|
+
});
|
|
47391
|
+
}
|
|
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() {
|
|
47398
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
47399
|
+
return [];
|
|
47400
|
+
return new Promise((resolve) => {
|
|
47401
|
+
this.meshSchemaResolvers.push(resolve);
|
|
47402
|
+
this.ws.send(JSON.stringify({ type: "mesh_schema" }));
|
|
47403
|
+
setTimeout(() => {
|
|
47404
|
+
const idx = this.meshSchemaResolvers.indexOf(resolve);
|
|
47405
|
+
if (idx !== -1) {
|
|
47406
|
+
this.meshSchemaResolvers.splice(idx, 1);
|
|
47407
|
+
resolve([]);
|
|
47408
|
+
}
|
|
47409
|
+
}, 5000);
|
|
47410
|
+
});
|
|
47411
|
+
}
|
|
47412
|
+
async createStream(name) {
|
|
47413
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
47414
|
+
return null;
|
|
47415
|
+
return new Promise((resolve) => {
|
|
47416
|
+
this.streamCreatedResolvers.push(resolve);
|
|
47417
|
+
this.ws.send(JSON.stringify({ type: "create_stream", name }));
|
|
47418
|
+
setTimeout(() => {
|
|
47419
|
+
const idx = this.streamCreatedResolvers.indexOf(resolve);
|
|
47420
|
+
if (idx !== -1) {
|
|
47421
|
+
this.streamCreatedResolvers.splice(idx, 1);
|
|
47422
|
+
resolve(null);
|
|
47423
|
+
}
|
|
47424
|
+
}, 5000);
|
|
47425
|
+
});
|
|
47426
|
+
}
|
|
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() {
|
|
47443
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
47444
|
+
return [];
|
|
47445
|
+
return new Promise((resolve) => {
|
|
47446
|
+
this.streamListResolvers.push(resolve);
|
|
47447
|
+
this.ws.send(JSON.stringify({ type: "list_streams" }));
|
|
47448
|
+
setTimeout(() => {
|
|
47449
|
+
const idx = this.streamListResolvers.indexOf(resolve);
|
|
47450
|
+
if (idx !== -1) {
|
|
47451
|
+
this.streamListResolvers.splice(idx, 1);
|
|
47452
|
+
resolve([]);
|
|
47453
|
+
}
|
|
47454
|
+
}, 5000);
|
|
47455
|
+
});
|
|
47456
|
+
}
|
|
47457
|
+
onStreamData(handler) {
|
|
47458
|
+
this.streamDataHandlers.add(handler);
|
|
47459
|
+
return () => this.streamDataHandlers.delete(handler);
|
|
47460
|
+
}
|
|
46950
47461
|
onStateChange(handler) {
|
|
46951
47462
|
this.stateChangeHandlers.add(handler);
|
|
46952
47463
|
return () => this.stateChangeHandlers.delete(handler);
|
|
46953
47464
|
}
|
|
47465
|
+
meshInfoResolvers = [];
|
|
47466
|
+
async meshInfo() {
|
|
47467
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
47468
|
+
return null;
|
|
47469
|
+
return new Promise((resolve) => {
|
|
47470
|
+
this.meshInfoResolvers.push(resolve);
|
|
47471
|
+
this.ws.send(JSON.stringify({ type: "mesh_info" }));
|
|
47472
|
+
setTimeout(() => {
|
|
47473
|
+
const idx = this.meshInfoResolvers.indexOf(resolve);
|
|
47474
|
+
if (idx !== -1) {
|
|
47475
|
+
this.meshInfoResolvers.splice(idx, 1);
|
|
47476
|
+
resolve(null);
|
|
47477
|
+
}
|
|
47478
|
+
}, 5000);
|
|
47479
|
+
});
|
|
47480
|
+
}
|
|
46954
47481
|
close() {
|
|
46955
47482
|
this.closed = true;
|
|
46956
47483
|
if (this.helloTimer)
|
|
@@ -47113,6 +47640,114 @@ class BrokerClient {
|
|
|
47113
47640
|
resolver(accesses);
|
|
47114
47641
|
return;
|
|
47115
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
|
+
}
|
|
47116
47751
|
if (msg.type === "error") {
|
|
47117
47752
|
this.debug(`broker error: ${msg.code} ${msg.message}`);
|
|
47118
47753
|
const id = msg.id ? String(msg.id) : null;
|
|
@@ -47286,6 +47921,7 @@ async function startMcpServer() {
|
|
|
47286
47921
|
const config2 = loadConfig();
|
|
47287
47922
|
const myName = config2.displayName ?? "unnamed";
|
|
47288
47923
|
const myGroups = (config2.groups ?? []).map((g) => `@${g.name}${g.role ? ":" + g.role : ""}`).join(", ") || "none";
|
|
47924
|
+
const messageMode = config2.messageMode ?? "push";
|
|
47289
47925
|
const server = new Server({ name: "claudemesh", version: "0.3.0" }, {
|
|
47290
47926
|
capabilities: {
|
|
47291
47927
|
experimental: { "claude/channel": {} },
|
|
@@ -47318,6 +47954,26 @@ When you receive a <channel source="claudemesh" ...> message, RESPOND IMMEDIATEL
|
|
|
47318
47954
|
| list_files(query?, from?) | Find files shared in the mesh. |
|
|
47319
47955
|
| file_status(id) | Check who has accessed a file. |
|
|
47320
47956
|
| delete_file(id) | Remove a shared file from the mesh. |
|
|
47957
|
+
| vector_store(collection, text, metadata?) | Store embedding in per-mesh Qdrant collection. |
|
|
47958
|
+
| vector_search(collection, query, limit?) | Semantic search over stored embeddings. |
|
|
47959
|
+
| vector_delete(collection, id) | Remove an embedding. |
|
|
47960
|
+
| list_collections() | List vector collections in this mesh. |
|
|
47961
|
+
| graph_query(cypher) | Read-only Cypher query on per-mesh Neo4j. |
|
|
47962
|
+
| graph_execute(cypher) | Write Cypher query (CREATE, MERGE, DELETE). |
|
|
47963
|
+
| mesh_query(sql) | Run a SELECT query on the per-mesh shared database. |
|
|
47964
|
+
| mesh_execute(sql) | Run DDL/DML on the per-mesh database (CREATE TABLE, INSERT, UPDATE, DELETE). |
|
|
47965
|
+
| mesh_schema() | List tables and columns in the per-mesh shared database. |
|
|
47966
|
+
| create_stream(name) | Create a real-time data stream in the mesh. |
|
|
47967
|
+
| publish(stream, data) | Push data to a stream. Subscribers receive it in real-time. |
|
|
47968
|
+
| subscribe(stream) | Subscribe to a stream. Data pushes arrive as channel notifications. |
|
|
47969
|
+
| list_streams() | List active streams in the mesh. |
|
|
47970
|
+
| share_context(summary, files_read?, key_findings?, tags?) | Share session understanding with peers. |
|
|
47971
|
+
| get_context(query) | Find context from peers who explored an area. |
|
|
47972
|
+
| list_contexts() | See what all peers currently know. |
|
|
47973
|
+
| create_task(title, assignee?, priority?, tags?) | Create a work item. |
|
|
47974
|
+
| claim_task(id) | Claim an unclaimed task. |
|
|
47975
|
+
| complete_task(id, result?) | Mark task done with optional result. |
|
|
47976
|
+
| list_tasks(status?, assignee?) | List tasks filtered by status/assignee. |
|
|
47321
47977
|
|
|
47322
47978
|
If multiple meshes are joined, prefix \`to\` with \`<mesh-slug>:\` to disambiguate (e.g. \`dev-team:Alice\`).
|
|
47323
47979
|
|
|
@@ -47344,13 +48000,37 @@ Persistent knowledge that survives across sessions. Use remember(content, tags?)
|
|
|
47344
48000
|
share_file for persistent references, send_message(file:) for ephemeral attachments.
|
|
47345
48001
|
Tags on shared files make them searchable. Use list_files to find what peers shared.
|
|
47346
48002
|
|
|
48003
|
+
## Vectors
|
|
48004
|
+
Store and search semantic embeddings. Use vector_store to index content, vector_search to find similar content.
|
|
48005
|
+
|
|
48006
|
+
## Graph
|
|
48007
|
+
Build and query entity relationship graphs. Use graph_execute for writes (CREATE, MERGE), graph_query for reads (MATCH).
|
|
48008
|
+
|
|
48009
|
+
## Mesh Database
|
|
48010
|
+
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.
|
|
48011
|
+
|
|
48012
|
+
## Streams
|
|
48013
|
+
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.
|
|
48014
|
+
|
|
48015
|
+
## Context
|
|
48016
|
+
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.
|
|
48017
|
+
|
|
48018
|
+
## Tasks
|
|
48019
|
+
Create and claim work items. create_task to propose work, claim_task to take ownership, complete_task when done. Prevents duplicate effort.
|
|
48020
|
+
|
|
47347
48021
|
## Priority
|
|
47348
48022
|
- "now": interrupt immediately, even if recipient is in DND (use for urgent: broken deploy, blocking issue)
|
|
47349
48023
|
- "next" (default): deliver when recipient goes idle (normal coordination)
|
|
47350
48024
|
- "low": pull-only via check_messages (FYI, non-blocking context)
|
|
47351
48025
|
|
|
47352
48026
|
## Coordination
|
|
47353
|
-
Call list_peers at session start to understand who is online, their roles, and what they are working on. If you are a group lead, gather input from members before responding to external requests — do not answer alone. If you are a member, contribute to your lead when asked. Use @group messages for team-wide questions, direct messages for 1:1 coordination. Set a meaningful summary so peers know your current focus
|
|
48027
|
+
Call list_peers at session start to understand who is online, their roles, and what they are working on. If you are a group lead, gather input from members before responding to external requests — do not answer alone. If you are a member, contribute to your lead when asked. Use @group messages for team-wide questions, direct messages for 1:1 coordination. Set a meaningful summary so peers know your current focus.
|
|
48028
|
+
|
|
48029
|
+
## Message Mode
|
|
48030
|
+
Your message mode is "${messageMode}".
|
|
48031
|
+
- push: messages arrive in real-time as channel notifications. Respond immediately.
|
|
48032
|
+
- inbox: messages are held. You'll see "[inbox] New message from X" notifications. Call check_messages to read them.
|
|
48033
|
+
- off: no message notifications. Use check_messages manually to poll.`
|
|
47354
48034
|
});
|
|
47355
48035
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
47356
48036
|
tools: TOOLS
|
|
@@ -47622,6 +48302,266 @@ ${lines.join(`
|
|
|
47622
48302
|
await client.deleteFile(id);
|
|
47623
48303
|
return text(`Deleted: ${id}`);
|
|
47624
48304
|
}
|
|
48305
|
+
case "vector_store": {
|
|
48306
|
+
const { collection, text: storeText, metadata } = args ?? {};
|
|
48307
|
+
if (!collection || !storeText)
|
|
48308
|
+
return text("vector_store: `collection` and `text` required", true);
|
|
48309
|
+
const client = allClients()[0];
|
|
48310
|
+
if (!client)
|
|
48311
|
+
return text("vector_store: not connected", true);
|
|
48312
|
+
const id = await client.vectorStore(collection, storeText, metadata);
|
|
48313
|
+
return text(`Stored in ${collection}${id ? ` (${id})` : ""}`);
|
|
48314
|
+
}
|
|
48315
|
+
case "vector_search": {
|
|
48316
|
+
const { collection, query, limit } = args ?? {};
|
|
48317
|
+
if (!collection || !query)
|
|
48318
|
+
return text("vector_search: `collection` and `query` required", true);
|
|
48319
|
+
const client = allClients()[0];
|
|
48320
|
+
if (!client)
|
|
48321
|
+
return text("vector_search: not connected", true);
|
|
48322
|
+
const results = await client.vectorSearch(collection, query, limit);
|
|
48323
|
+
if (results.length === 0)
|
|
48324
|
+
return text(`No results in ${collection} for "${query}".`);
|
|
48325
|
+
const lines = results.map((r) => `- [${r.id.slice(0, 8)}…] (score: ${r.score.toFixed(3)}) ${r.text.slice(0, 120)}${r.text.length > 120 ? "…" : ""}`);
|
|
48326
|
+
return text(`${results.length} result(s) in ${collection}:
|
|
48327
|
+
${lines.join(`
|
|
48328
|
+
`)}`);
|
|
48329
|
+
}
|
|
48330
|
+
case "vector_delete": {
|
|
48331
|
+
const { collection, id } = args ?? {};
|
|
48332
|
+
if (!collection || !id)
|
|
48333
|
+
return text("vector_delete: `collection` and `id` required", true);
|
|
48334
|
+
const client = allClients()[0];
|
|
48335
|
+
if (!client)
|
|
48336
|
+
return text("vector_delete: not connected", true);
|
|
48337
|
+
await client.vectorDelete(collection, id);
|
|
48338
|
+
return text(`Deleted ${id} from ${collection}`);
|
|
48339
|
+
}
|
|
48340
|
+
case "list_collections": {
|
|
48341
|
+
const client = allClients()[0];
|
|
48342
|
+
if (!client)
|
|
48343
|
+
return text("list_collections: not connected", true);
|
|
48344
|
+
const collections = await client.listCollections();
|
|
48345
|
+
if (collections.length === 0)
|
|
48346
|
+
return text("No vector collections.");
|
|
48347
|
+
return text(`Collections:
|
|
48348
|
+
${collections.map((c) => `- ${c}`).join(`
|
|
48349
|
+
`)}`);
|
|
48350
|
+
}
|
|
48351
|
+
case "graph_query": {
|
|
48352
|
+
const { cypher } = args ?? {};
|
|
48353
|
+
if (!cypher)
|
|
48354
|
+
return text("graph_query: `cypher` required", true);
|
|
48355
|
+
const client = allClients()[0];
|
|
48356
|
+
if (!client)
|
|
48357
|
+
return text("graph_query: not connected", true);
|
|
48358
|
+
const rows = await client.graphQuery(cypher);
|
|
48359
|
+
if (rows.length === 0)
|
|
48360
|
+
return text("No results.");
|
|
48361
|
+
return text(JSON.stringify(rows, null, 2));
|
|
48362
|
+
}
|
|
48363
|
+
case "graph_execute": {
|
|
48364
|
+
const { cypher } = args ?? {};
|
|
48365
|
+
if (!cypher)
|
|
48366
|
+
return text("graph_execute: `cypher` required", true);
|
|
48367
|
+
const client = allClients()[0];
|
|
48368
|
+
if (!client)
|
|
48369
|
+
return text("graph_execute: not connected", true);
|
|
48370
|
+
const rows = await client.graphExecute(cypher);
|
|
48371
|
+
return text(rows.length > 0 ? JSON.stringify(rows, null, 2) : "Executed successfully.");
|
|
48372
|
+
}
|
|
48373
|
+
case "share_context": {
|
|
48374
|
+
const { summary, files_read, key_findings, tags } = args ?? {};
|
|
48375
|
+
if (!summary)
|
|
48376
|
+
return text("share_context: `summary` required", true);
|
|
48377
|
+
const client = allClients()[0];
|
|
48378
|
+
if (!client)
|
|
48379
|
+
return text("share_context: not connected", true);
|
|
48380
|
+
await client.shareContext(summary, files_read, key_findings, tags);
|
|
48381
|
+
return text(`Context shared: "${summary.slice(0, 80)}${summary.length > 80 ? "…" : ""}"`);
|
|
48382
|
+
}
|
|
48383
|
+
case "get_context": {
|
|
48384
|
+
const { query } = args ?? {};
|
|
48385
|
+
if (!query)
|
|
48386
|
+
return text("get_context: `query` required", true);
|
|
48387
|
+
const client = allClients()[0];
|
|
48388
|
+
if (!client)
|
|
48389
|
+
return text("get_context: not connected", true);
|
|
48390
|
+
const contexts = await client.getContext(query);
|
|
48391
|
+
if (contexts.length === 0)
|
|
48392
|
+
return text(`No context found for "${query}".`);
|
|
48393
|
+
const lines = contexts.map((c) => {
|
|
48394
|
+
const files = c.filesRead.length ? `
|
|
48395
|
+
Files: ${c.filesRead.join(", ")}` : "";
|
|
48396
|
+
const findings = c.keyFindings.length ? `
|
|
48397
|
+
Findings: ${c.keyFindings.join("; ")}` : "";
|
|
48398
|
+
return `- **${c.peerName}** (${c.updatedAt}): ${c.summary}${files}${findings}`;
|
|
48399
|
+
});
|
|
48400
|
+
return text(`${contexts.length} context(s):
|
|
48401
|
+
${lines.join(`
|
|
48402
|
+
`)}`);
|
|
48403
|
+
}
|
|
48404
|
+
case "list_contexts": {
|
|
48405
|
+
const client = allClients()[0];
|
|
48406
|
+
if (!client)
|
|
48407
|
+
return text("list_contexts: not connected", true);
|
|
48408
|
+
const contexts = await client.listContexts();
|
|
48409
|
+
if (contexts.length === 0)
|
|
48410
|
+
return text("No peer contexts shared yet.");
|
|
48411
|
+
const lines = contexts.map((c) => `- **${c.peerName}**: ${c.summary}${c.tags.length ? ` [${c.tags.join(", ")}]` : ""}`);
|
|
48412
|
+
return text(`Peer contexts:
|
|
48413
|
+
${lines.join(`
|
|
48414
|
+
`)}`);
|
|
48415
|
+
}
|
|
48416
|
+
case "create_task": {
|
|
48417
|
+
const { title, assignee, priority, tags } = args ?? {};
|
|
48418
|
+
if (!title)
|
|
48419
|
+
return text("create_task: `title` required", true);
|
|
48420
|
+
const client = allClients()[0];
|
|
48421
|
+
if (!client)
|
|
48422
|
+
return text("create_task: not connected", true);
|
|
48423
|
+
const id = await client.createTask(title, assignee, priority, tags);
|
|
48424
|
+
return text(`Task created${id ? ` (${id})` : ""}: "${title}"${assignee ? ` → ${assignee}` : ""}`);
|
|
48425
|
+
}
|
|
48426
|
+
case "claim_task": {
|
|
48427
|
+
const { id } = args ?? {};
|
|
48428
|
+
if (!id)
|
|
48429
|
+
return text("claim_task: `id` required", true);
|
|
48430
|
+
const client = allClients()[0];
|
|
48431
|
+
if (!client)
|
|
48432
|
+
return text("claim_task: not connected", true);
|
|
48433
|
+
await client.claimTask(id);
|
|
48434
|
+
return text(`Claimed task: ${id}`);
|
|
48435
|
+
}
|
|
48436
|
+
case "complete_task": {
|
|
48437
|
+
const { id, result } = args ?? {};
|
|
48438
|
+
if (!id)
|
|
48439
|
+
return text("complete_task: `id` required", true);
|
|
48440
|
+
const client = allClients()[0];
|
|
48441
|
+
if (!client)
|
|
48442
|
+
return text("complete_task: not connected", true);
|
|
48443
|
+
await client.completeTask(id, result);
|
|
48444
|
+
return text(`Completed task: ${id}${result ? ` — ${result}` : ""}`);
|
|
48445
|
+
}
|
|
48446
|
+
case "list_tasks": {
|
|
48447
|
+
const { status, assignee } = args ?? {};
|
|
48448
|
+
const client = allClients()[0];
|
|
48449
|
+
if (!client)
|
|
48450
|
+
return text("list_tasks: not connected", true);
|
|
48451
|
+
const tasks = await client.listTasks(status, assignee);
|
|
48452
|
+
if (tasks.length === 0)
|
|
48453
|
+
return text("No tasks found.");
|
|
48454
|
+
const lines = tasks.map((t) => `- [${t.id.slice(0, 8)}…] **${t.title}** (${t.status}, ${t.priority}) ${t.assignee ? `→ ${t.assignee}` : "unassigned"} (by ${t.createdBy})`);
|
|
48455
|
+
return text(`${tasks.length} task(s):
|
|
48456
|
+
${lines.join(`
|
|
48457
|
+
`)}`);
|
|
48458
|
+
}
|
|
48459
|
+
case "mesh_query": {
|
|
48460
|
+
const { sql: querySql } = args ?? {};
|
|
48461
|
+
if (!querySql)
|
|
48462
|
+
return text("mesh_query: `sql` required", true);
|
|
48463
|
+
const client = allClients()[0];
|
|
48464
|
+
if (!client)
|
|
48465
|
+
return text("mesh_query: not connected", true);
|
|
48466
|
+
const result = await client.meshQuery(querySql);
|
|
48467
|
+
if (!result)
|
|
48468
|
+
return text("mesh_query: query failed or timed out", true);
|
|
48469
|
+
if (result.rows.length === 0)
|
|
48470
|
+
return text(`Query returned 0 rows.`);
|
|
48471
|
+
const header = `| ${result.columns.join(" | ")} |`;
|
|
48472
|
+
const sep = `| ${result.columns.map(() => "---").join(" | ")} |`;
|
|
48473
|
+
const rows = result.rows.map((r) => `| ${result.columns.map((c) => String(r[c] ?? "")).join(" | ")} |`);
|
|
48474
|
+
return text(`${result.rowCount} row(s):
|
|
48475
|
+
${header}
|
|
48476
|
+
${sep}
|
|
48477
|
+
${rows.join(`
|
|
48478
|
+
`)}`);
|
|
48479
|
+
}
|
|
48480
|
+
case "mesh_execute": {
|
|
48481
|
+
const { sql: execSql } = args ?? {};
|
|
48482
|
+
if (!execSql)
|
|
48483
|
+
return text("mesh_execute: `sql` required", true);
|
|
48484
|
+
const client = allClients()[0];
|
|
48485
|
+
if (!client)
|
|
48486
|
+
return text("mesh_execute: not connected", true);
|
|
48487
|
+
await client.meshExecute(execSql);
|
|
48488
|
+
return text(`Executed.`);
|
|
48489
|
+
}
|
|
48490
|
+
case "mesh_schema": {
|
|
48491
|
+
const client = allClients()[0];
|
|
48492
|
+
if (!client)
|
|
48493
|
+
return text("mesh_schema: not connected", true);
|
|
48494
|
+
const tables = await client.meshSchema();
|
|
48495
|
+
if (!tables || tables.length === 0)
|
|
48496
|
+
return text("No tables in mesh database.");
|
|
48497
|
+
const lines = tables.map((t) => `**${t.name}**: ${t.columns.map((c) => `${c.name} (${c.type}${c.nullable ? ", nullable" : ""})`).join(", ")}`);
|
|
48498
|
+
return text(lines.join(`
|
|
48499
|
+
`));
|
|
48500
|
+
}
|
|
48501
|
+
case "create_stream": {
|
|
48502
|
+
const { name: streamName } = args ?? {};
|
|
48503
|
+
if (!streamName)
|
|
48504
|
+
return text("create_stream: `name` required", true);
|
|
48505
|
+
const client = allClients()[0];
|
|
48506
|
+
if (!client)
|
|
48507
|
+
return text("create_stream: not connected", true);
|
|
48508
|
+
const streamId = await client.createStream(streamName);
|
|
48509
|
+
return text(`Stream created: ${streamName}${streamId ? ` (${streamId})` : ""}`);
|
|
48510
|
+
}
|
|
48511
|
+
case "publish": {
|
|
48512
|
+
const { stream: pubStream, data: pubData } = args ?? {};
|
|
48513
|
+
if (!pubStream)
|
|
48514
|
+
return text("publish: `stream` required", true);
|
|
48515
|
+
const client = allClients()[0];
|
|
48516
|
+
if (!client)
|
|
48517
|
+
return text("publish: not connected", true);
|
|
48518
|
+
await client.publish(pubStream, pubData);
|
|
48519
|
+
return text(`Published to ${pubStream}.`);
|
|
48520
|
+
}
|
|
48521
|
+
case "subscribe": {
|
|
48522
|
+
const { stream: subStream } = args ?? {};
|
|
48523
|
+
if (!subStream)
|
|
48524
|
+
return text("subscribe: `stream` required", true);
|
|
48525
|
+
const client = allClients()[0];
|
|
48526
|
+
if (!client)
|
|
48527
|
+
return text("subscribe: not connected", true);
|
|
48528
|
+
await client.subscribe(subStream);
|
|
48529
|
+
return text(`Subscribed to ${subStream}. Data pushes will arrive as channel notifications.`);
|
|
48530
|
+
}
|
|
48531
|
+
case "list_streams": {
|
|
48532
|
+
const client = allClients()[0];
|
|
48533
|
+
if (!client)
|
|
48534
|
+
return text("list_streams: not connected", true);
|
|
48535
|
+
const streams = await client.listStreams();
|
|
48536
|
+
if (streams.length === 0)
|
|
48537
|
+
return text("No active streams.");
|
|
48538
|
+
const lines = streams.map((s) => `- **${s.name}** (${s.id.slice(0, 8)}…) by ${s.createdBy}, ${s.subscriberCount} subscriber(s)`);
|
|
48539
|
+
return text(lines.join(`
|
|
48540
|
+
`));
|
|
48541
|
+
}
|
|
48542
|
+
case "mesh_info": {
|
|
48543
|
+
const client = allClients()[0];
|
|
48544
|
+
if (!client)
|
|
48545
|
+
return text("mesh_info: not connected", true);
|
|
48546
|
+
const info = await client.meshInfo();
|
|
48547
|
+
if (!info)
|
|
48548
|
+
return text("mesh_info: timed out", true);
|
|
48549
|
+
const lines = [
|
|
48550
|
+
`**Mesh**: ${info.mesh}`,
|
|
48551
|
+
`**Peers**: ${info.peers}`,
|
|
48552
|
+
`**Groups**: ${info.groups?.join(", ") || "none"}`,
|
|
48553
|
+
`**State keys**: ${info.stateKeys?.join(", ") || "none"}`,
|
|
48554
|
+
`**Memories**: ${info.memoryCount}`,
|
|
48555
|
+
`**Files**: ${info.fileCount}`,
|
|
48556
|
+
`**Tasks**: open=${info.tasks?.open ?? 0}, claimed=${info.tasks?.claimed ?? 0}, done=${info.tasks?.done ?? 0}`,
|
|
48557
|
+
`**Streams**: ${info.streams?.join(", ") || "none"}`,
|
|
48558
|
+
`**Tables**: ${info.tables?.join(", ") || "none"}`,
|
|
48559
|
+
`**Your name**: ${info.yourName}`,
|
|
48560
|
+
`**Your groups**: ${info.yourGroups?.map((g) => `@${g.name}${g.role ? ":" + g.role : ""}`).join(", ") || "none"}`
|
|
48561
|
+
];
|
|
48562
|
+
return text(lines.join(`
|
|
48563
|
+
`));
|
|
48564
|
+
}
|
|
47625
48565
|
default:
|
|
47626
48566
|
return text(`Unknown tool: ${name}`, true);
|
|
47627
48567
|
}
|
|
@@ -47631,8 +48571,22 @@ ${lines.join(`
|
|
|
47631
48571
|
await server.connect(transport);
|
|
47632
48572
|
for (const client of allClients()) {
|
|
47633
48573
|
client.onPush(async (msg) => {
|
|
48574
|
+
if (messageMode === "off")
|
|
48575
|
+
return;
|
|
47634
48576
|
const fromPubkey = msg.senderPubkey || "";
|
|
47635
48577
|
const fromName = fromPubkey ? await resolvePeerName(client, fromPubkey) : "unknown";
|
|
48578
|
+
if (messageMode === "inbox") {
|
|
48579
|
+
try {
|
|
48580
|
+
await server.notification({
|
|
48581
|
+
method: "notifications/claude/channel",
|
|
48582
|
+
params: {
|
|
48583
|
+
content: `[inbox] New message from ${fromName}. Use check_messages to read.`,
|
|
48584
|
+
meta: { kind: "inbox_notification", from_name: fromName }
|
|
48585
|
+
}
|
|
48586
|
+
});
|
|
48587
|
+
} catch {}
|
|
48588
|
+
return;
|
|
48589
|
+
}
|
|
47636
48590
|
const content = msg.plaintext ?? decryptFailedWarning(fromPubkey);
|
|
47637
48591
|
try {
|
|
47638
48592
|
await server.notification({
|
|
@@ -47653,6 +48607,21 @@ ${lines.join(`
|
|
|
47653
48607
|
});
|
|
47654
48608
|
} catch {}
|
|
47655
48609
|
});
|
|
48610
|
+
client.onStreamData(async (evt) => {
|
|
48611
|
+
try {
|
|
48612
|
+
await server.notification({
|
|
48613
|
+
method: "notifications/claude/channel",
|
|
48614
|
+
params: {
|
|
48615
|
+
content: `[stream:${evt.stream}] from ${evt.publishedBy}: ${JSON.stringify(evt.data)}`,
|
|
48616
|
+
meta: {
|
|
48617
|
+
kind: "stream_data",
|
|
48618
|
+
stream: evt.stream,
|
|
48619
|
+
published_by: evt.publishedBy
|
|
48620
|
+
}
|
|
48621
|
+
}
|
|
48622
|
+
});
|
|
48623
|
+
} catch {}
|
|
48624
|
+
});
|
|
47656
48625
|
client.onStateChange(async (change) => {
|
|
47657
48626
|
try {
|
|
47658
48627
|
await server.notification({
|
|
@@ -48274,6 +49243,7 @@ function parseArgs(argv) {
|
|
|
48274
49243
|
groups: null,
|
|
48275
49244
|
joinLink: null,
|
|
48276
49245
|
meshSlug: null,
|
|
49246
|
+
messageMode: null,
|
|
48277
49247
|
quiet: false,
|
|
48278
49248
|
skipPermConfirm: false,
|
|
48279
49249
|
claudeArgs: []
|
|
@@ -48301,6 +49271,10 @@ function parseArgs(argv) {
|
|
|
48301
49271
|
result.meshSlug = argv[++i];
|
|
48302
49272
|
} else if (arg.startsWith("--mesh=")) {
|
|
48303
49273
|
result.meshSlug = arg.slice("--mesh=".length);
|
|
49274
|
+
} else if (arg === "--inbox") {
|
|
49275
|
+
result.messageMode = "inbox";
|
|
49276
|
+
} else if (arg === "--no-messages") {
|
|
49277
|
+
result.messageMode = "off";
|
|
48304
49278
|
} else if (arg === "--quiet") {
|
|
48305
49279
|
result.quiet = true;
|
|
48306
49280
|
} else if (arg === "-y" || arg === "--yes") {
|
|
@@ -48386,16 +49360,22 @@ async function confirmPermissions() {
|
|
|
48386
49360
|
});
|
|
48387
49361
|
});
|
|
48388
49362
|
}
|
|
48389
|
-
function printBanner(name, meshSlug, role, groups) {
|
|
49363
|
+
function printBanner(name, meshSlug, role, groups, messageMode) {
|
|
48390
49364
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
48391
49365
|
const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
48392
49366
|
const bold = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
48393
49367
|
const roleSuffix = role ? ` (${role})` : "";
|
|
48394
49368
|
const groupTags = groups.length ? " [" + groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
|
|
48395
49369
|
const rule = "─".repeat(60);
|
|
48396
|
-
console.log(bold(`claudemesh launch`) + dim(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags}`));
|
|
49370
|
+
console.log(bold(`claudemesh launch`) + dim(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags} [${messageMode}]`));
|
|
48397
49371
|
console.log(rule);
|
|
48398
|
-
|
|
49372
|
+
if (messageMode === "push") {
|
|
49373
|
+
console.log("Peer messages arrive as <channel> reminders in real-time.");
|
|
49374
|
+
} else if (messageMode === "inbox") {
|
|
49375
|
+
console.log("Peer messages held in inbox. Use check_messages to read.");
|
|
49376
|
+
} else {
|
|
49377
|
+
console.log("Messages off. Use check_messages to poll manually.");
|
|
49378
|
+
}
|
|
48399
49379
|
console.log("Peers send text only — they cannot call tools or read files.");
|
|
48400
49380
|
console.log(dim(`Config: ${getConfigPath()}`));
|
|
48401
49381
|
console.log(rule);
|
|
@@ -48450,6 +49430,7 @@ async function runLaunch(extraArgs) {
|
|
|
48450
49430
|
const displayName = args.name ?? `${hostname2()}-${process.pid}`;
|
|
48451
49431
|
let role = args.role;
|
|
48452
49432
|
let parsedGroups = args.groups ? parseGroupsString(args.groups) : [];
|
|
49433
|
+
let messageMode = args.messageMode ?? "push";
|
|
48453
49434
|
if (!args.quiet) {
|
|
48454
49435
|
if (role === null) {
|
|
48455
49436
|
const answer = await askLine(" Role (optional): ");
|
|
@@ -48461,6 +49442,22 @@ async function runLaunch(extraArgs) {
|
|
|
48461
49442
|
if (answer)
|
|
48462
49443
|
parsedGroups = parseGroupsString(answer);
|
|
48463
49444
|
}
|
|
49445
|
+
if (args.messageMode === null) {
|
|
49446
|
+
console.log(`
|
|
49447
|
+
Message mode:`);
|
|
49448
|
+
console.log(" 1) Push (real-time, peers can interrupt your work)");
|
|
49449
|
+
console.log(" 2) Inbox (held until you check, notification only)");
|
|
49450
|
+
console.log(" 3) Off (tools only, no messages)");
|
|
49451
|
+
console.log("");
|
|
49452
|
+
const answer = await askLine(" Choice [1]: ");
|
|
49453
|
+
const choice = parseInt(answer || "1", 10);
|
|
49454
|
+
if (choice === 2)
|
|
49455
|
+
messageMode = "inbox";
|
|
49456
|
+
else if (choice === 3)
|
|
49457
|
+
messageMode = "off";
|
|
49458
|
+
else
|
|
49459
|
+
messageMode = "push";
|
|
49460
|
+
}
|
|
48464
49461
|
if (role || parsedGroups.length)
|
|
48465
49462
|
console.log("");
|
|
48466
49463
|
}
|
|
@@ -48480,12 +49477,13 @@ async function runLaunch(extraArgs) {
|
|
|
48480
49477
|
version: 1,
|
|
48481
49478
|
meshes: [mesh],
|
|
48482
49479
|
displayName,
|
|
48483
|
-
...parsedGroups.length > 0 ? { groups: parsedGroups } : {}
|
|
49480
|
+
...parsedGroups.length > 0 ? { groups: parsedGroups } : {},
|
|
49481
|
+
messageMode
|
|
48484
49482
|
};
|
|
48485
49483
|
writeFileSync4(join4(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
|
|
48486
49484
|
`, "utf-8");
|
|
48487
49485
|
if (!args.quiet) {
|
|
48488
|
-
printBanner(displayName, mesh.slug, role, parsedGroups);
|
|
49486
|
+
printBanner(displayName, mesh.slug, role, parsedGroups, messageMode);
|
|
48489
49487
|
if (!args.skipPermConfirm) {
|
|
48490
49488
|
await confirmPermissions();
|
|
48491
49489
|
}
|
|
@@ -48553,7 +49551,7 @@ init_config();
|
|
|
48553
49551
|
// package.json
|
|
48554
49552
|
var package_default = {
|
|
48555
49553
|
name: "claudemesh-cli",
|
|
48556
|
-
version: "0.
|
|
49554
|
+
version: "0.5.1",
|
|
48557
49555
|
description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
48558
49556
|
keywords: [
|
|
48559
49557
|
"claude-code",
|