opencode-swarm-plugin 0.47.0 → 0.48.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.
- package/bin/swarm.ts +328 -0
- package/dist/bin/swarm.js +256 -0
- package/dist/examples/plugin-wrapper-template.ts +74 -0
- package/examples/plugin-wrapper-template.ts +74 -0
- package/package.json +1 -1
package/bin/swarm.ts
CHANGED
|
@@ -3216,6 +3216,7 @@ ${cyan("Commands:")}
|
|
|
3216
3216
|
swarm viz Alias for 'swarm serve' (deprecated, use serve)
|
|
3217
3217
|
--port <n> Port to listen on (default: 4483)
|
|
3218
3218
|
swarm cells List or get cells from database (replaces 'swarm tool hive_query')
|
|
3219
|
+
swarm memory Manage unified memory system (learnings + sessions)
|
|
3219
3220
|
swarm log View swarm logs with filtering
|
|
3220
3221
|
swarm stats Show swarm health metrics powered by swarm-insights (strategy success rates, patterns)
|
|
3221
3222
|
swarm o11y Show observability health - hook coverage, event capture, session quality
|
|
@@ -3243,6 +3244,17 @@ ${cyan("Cell Management:")}
|
|
|
3243
3244
|
swarm cells --ready Show next ready (unblocked) cell
|
|
3244
3245
|
swarm cells --json Raw JSON output (array, no wrapper)
|
|
3245
3246
|
|
|
3247
|
+
${cyan("Memory Management (Hivemind):")}
|
|
3248
|
+
swarm memory store <info> [--tags <tags>] Store a learning/memory
|
|
3249
|
+
swarm memory find <query> [--limit <n>] Search all memories (semantic + FTS)
|
|
3250
|
+
swarm memory get <id> Get specific memory by ID
|
|
3251
|
+
swarm memory remove <id> Delete outdated/incorrect memory
|
|
3252
|
+
swarm memory validate <id> Confirm accuracy (resets 90-day decay)
|
|
3253
|
+
swarm memory stats Show database statistics
|
|
3254
|
+
swarm memory index Index AI sessions (use hivemind_index tool)
|
|
3255
|
+
swarm memory sync Sync to .hive/memories.jsonl (use hivemind_sync tool)
|
|
3256
|
+
swarm memory <command> --json Output JSON for all commands
|
|
3257
|
+
|
|
3246
3258
|
${cyan("Log Viewing:")}
|
|
3247
3259
|
swarm log Tail recent logs (last 50 lines)
|
|
3248
3260
|
swarm log <module> Filter by module (e.g., compaction)
|
|
@@ -5503,6 +5515,319 @@ async function capture() {
|
|
|
5503
5515
|
}
|
|
5504
5516
|
}
|
|
5505
5517
|
|
|
5518
|
+
// ============================================================================
|
|
5519
|
+
// Memory Commands
|
|
5520
|
+
// ============================================================================
|
|
5521
|
+
|
|
5522
|
+
/**
|
|
5523
|
+
* Parse args for memory commands
|
|
5524
|
+
*/
|
|
5525
|
+
function parseMemoryArgs(subcommand: string, args: string[]): {
|
|
5526
|
+
json: boolean;
|
|
5527
|
+
info?: string;
|
|
5528
|
+
query?: string;
|
|
5529
|
+
id?: string;
|
|
5530
|
+
tags?: string;
|
|
5531
|
+
limit?: number;
|
|
5532
|
+
collection?: string;
|
|
5533
|
+
} {
|
|
5534
|
+
let json = false;
|
|
5535
|
+
let info: string | undefined;
|
|
5536
|
+
let query: string | undefined;
|
|
5537
|
+
let id: string | undefined;
|
|
5538
|
+
let tags: string | undefined;
|
|
5539
|
+
let limit: number | undefined;
|
|
5540
|
+
let collection: string | undefined;
|
|
5541
|
+
|
|
5542
|
+
// First positional arg for store/find/get/remove/validate
|
|
5543
|
+
if (args.length > 0 && !args[0].startsWith("--")) {
|
|
5544
|
+
if (subcommand === "store") {
|
|
5545
|
+
info = args[0];
|
|
5546
|
+
} else if (subcommand === "find") {
|
|
5547
|
+
query = args[0];
|
|
5548
|
+
} else if (subcommand === "get" || subcommand === "remove" || subcommand === "validate") {
|
|
5549
|
+
id = args[0];
|
|
5550
|
+
}
|
|
5551
|
+
}
|
|
5552
|
+
|
|
5553
|
+
for (let i = 0; i < args.length; i++) {
|
|
5554
|
+
const arg = args[i];
|
|
5555
|
+
if (arg === "--json") {
|
|
5556
|
+
json = true;
|
|
5557
|
+
} else if (arg === "--tags" && i + 1 < args.length) {
|
|
5558
|
+
tags = args[++i];
|
|
5559
|
+
} else if (arg === "--limit" && i + 1 < args.length) {
|
|
5560
|
+
const val = parseInt(args[++i], 10);
|
|
5561
|
+
if (!isNaN(val)) limit = val;
|
|
5562
|
+
} else if (arg === "--collection" && i + 1 < args.length) {
|
|
5563
|
+
collection = args[++i];
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
|
|
5567
|
+
return { json, info, query, id, tags, limit, collection };
|
|
5568
|
+
}
|
|
5569
|
+
|
|
5570
|
+
/**
|
|
5571
|
+
* Memory command - unified interface to memory operations
|
|
5572
|
+
*
|
|
5573
|
+
* Commands:
|
|
5574
|
+
* swarm memory store <info> [--tags <tags>]
|
|
5575
|
+
* swarm memory find <query> [--limit <n>] [--collection <name>]
|
|
5576
|
+
* swarm memory get <id>
|
|
5577
|
+
* swarm memory remove <id>
|
|
5578
|
+
* swarm memory validate <id>
|
|
5579
|
+
* swarm memory stats
|
|
5580
|
+
* swarm memory index
|
|
5581
|
+
* swarm memory sync
|
|
5582
|
+
*/
|
|
5583
|
+
async function memory() {
|
|
5584
|
+
const subcommand = process.argv[3];
|
|
5585
|
+
const args = process.argv.slice(4);
|
|
5586
|
+
const parsed = parseMemoryArgs(subcommand, args);
|
|
5587
|
+
|
|
5588
|
+
// Get project path for libSQL database
|
|
5589
|
+
const projectPath = process.cwd();
|
|
5590
|
+
|
|
5591
|
+
try {
|
|
5592
|
+
// Get database instance using getDb from swarm-mail
|
|
5593
|
+
// This returns a drizzle instance (SwarmDb) that memory adapter expects
|
|
5594
|
+
const { getDb } = await import("swarm-mail");
|
|
5595
|
+
|
|
5596
|
+
// Calculate DB path (same logic as libsql.convenience.ts)
|
|
5597
|
+
const tempDirName = getLibSQLProjectTempDirName(projectPath);
|
|
5598
|
+
const tempDir = join(tmpdir(), tempDirName);
|
|
5599
|
+
|
|
5600
|
+
// Ensure temp directory exists
|
|
5601
|
+
if (!existsSync(tempDir)) {
|
|
5602
|
+
mkdirSync(tempDir, { recursive: true });
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5605
|
+
const dbPath = join(tempDir, "streams.db");
|
|
5606
|
+
|
|
5607
|
+
// Convert to file:// URL (required by libSQL)
|
|
5608
|
+
const dbUrl = `file://${dbPath}`;
|
|
5609
|
+
|
|
5610
|
+
const db = await getDb(dbUrl);
|
|
5611
|
+
|
|
5612
|
+
// Create memory adapter with default Ollama config
|
|
5613
|
+
const { createMemoryAdapter } = await import("swarm-mail");
|
|
5614
|
+
const adapter = createMemoryAdapter(db, {
|
|
5615
|
+
ollamaHost: process.env.OLLAMA_HOST || "http://localhost:11434",
|
|
5616
|
+
ollamaModel: process.env.OLLAMA_MODEL || "mxbai-embed-large",
|
|
5617
|
+
});
|
|
5618
|
+
|
|
5619
|
+
switch (subcommand) {
|
|
5620
|
+
case "store": {
|
|
5621
|
+
if (!parsed.info) {
|
|
5622
|
+
console.error("Usage: swarm memory store <information> [--tags <tags>]");
|
|
5623
|
+
process.exit(1);
|
|
5624
|
+
}
|
|
5625
|
+
|
|
5626
|
+
const result = await adapter.store(parsed.info, {
|
|
5627
|
+
tags: parsed.tags,
|
|
5628
|
+
collection: parsed.collection || "default",
|
|
5629
|
+
});
|
|
5630
|
+
|
|
5631
|
+
if (parsed.json) {
|
|
5632
|
+
console.log(JSON.stringify({ success: true, id: result.id }));
|
|
5633
|
+
} else {
|
|
5634
|
+
p.intro("swarm memory store");
|
|
5635
|
+
p.log.success(`Stored memory: ${result.id}`);
|
|
5636
|
+
if (result.autoTags) {
|
|
5637
|
+
p.log.message(`Auto-tags: ${result.autoTags.tags.join(", ")}`);
|
|
5638
|
+
}
|
|
5639
|
+
p.outro("Done");
|
|
5640
|
+
}
|
|
5641
|
+
break;
|
|
5642
|
+
}
|
|
5643
|
+
|
|
5644
|
+
case "find": {
|
|
5645
|
+
if (!parsed.query) {
|
|
5646
|
+
console.error("Usage: swarm memory find <query> [--limit <n>] [--collection <name>]");
|
|
5647
|
+
process.exit(1);
|
|
5648
|
+
}
|
|
5649
|
+
|
|
5650
|
+
const results = await adapter.find(parsed.query, {
|
|
5651
|
+
limit: parsed.limit || 10,
|
|
5652
|
+
collection: parsed.collection,
|
|
5653
|
+
});
|
|
5654
|
+
|
|
5655
|
+
if (parsed.json) {
|
|
5656
|
+
console.log(JSON.stringify({ success: true, results }));
|
|
5657
|
+
} else {
|
|
5658
|
+
p.intro(`swarm memory find: "${parsed.query}"`);
|
|
5659
|
+
if (results.length === 0) {
|
|
5660
|
+
p.log.warn("No memories found");
|
|
5661
|
+
} else {
|
|
5662
|
+
for (const result of results) {
|
|
5663
|
+
console.log();
|
|
5664
|
+
console.log(cyan(`[${result.memory.id}] Score: ${result.score.toFixed(3)}`));
|
|
5665
|
+
console.log(dim(` Created: ${new Date(result.memory.createdAt).toLocaleDateString()}`));
|
|
5666
|
+
console.log(` ${result.memory.content.slice(0, 200)}${result.memory.content.length > 200 ? "..." : ""}`);
|
|
5667
|
+
if (result.memory.metadata.tags) {
|
|
5668
|
+
console.log(dim(` Tags: ${(result.memory.metadata.tags as string[]).join(", ")}`));
|
|
5669
|
+
}
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
p.outro(`Found ${results.length} result(s)`);
|
|
5673
|
+
}
|
|
5674
|
+
break;
|
|
5675
|
+
}
|
|
5676
|
+
|
|
5677
|
+
case "get": {
|
|
5678
|
+
if (!parsed.id) {
|
|
5679
|
+
console.error("Usage: swarm memory get <id>");
|
|
5680
|
+
process.exit(1);
|
|
5681
|
+
}
|
|
5682
|
+
|
|
5683
|
+
const memory = await adapter.get(parsed.id);
|
|
5684
|
+
|
|
5685
|
+
if (parsed.json) {
|
|
5686
|
+
if (memory) {
|
|
5687
|
+
console.log(JSON.stringify({ success: true, memory }));
|
|
5688
|
+
} else {
|
|
5689
|
+
console.log(JSON.stringify({ success: false, error: "Memory not found" }));
|
|
5690
|
+
process.exit(1);
|
|
5691
|
+
}
|
|
5692
|
+
} else {
|
|
5693
|
+
p.intro(`swarm memory get: ${parsed.id}`);
|
|
5694
|
+
if (!memory) {
|
|
5695
|
+
p.log.error("Memory not found");
|
|
5696
|
+
p.outro("Aborted");
|
|
5697
|
+
process.exit(1);
|
|
5698
|
+
} else {
|
|
5699
|
+
console.log();
|
|
5700
|
+
console.log(cyan("Content:"));
|
|
5701
|
+
console.log(memory.content);
|
|
5702
|
+
console.log();
|
|
5703
|
+
console.log(dim(`Created: ${new Date(memory.createdAt).toLocaleDateString()}`));
|
|
5704
|
+
console.log(dim(`Collection: ${memory.collection}`));
|
|
5705
|
+
console.log(dim(`Confidence: ${memory.confidence ?? 0.7}`));
|
|
5706
|
+
if (memory.metadata.tags) {
|
|
5707
|
+
console.log(dim(`Tags: ${(memory.metadata.tags as string[]).join(", ")}`));
|
|
5708
|
+
}
|
|
5709
|
+
p.outro("Done");
|
|
5710
|
+
}
|
|
5711
|
+
}
|
|
5712
|
+
break;
|
|
5713
|
+
}
|
|
5714
|
+
|
|
5715
|
+
case "remove": {
|
|
5716
|
+
if (!parsed.id) {
|
|
5717
|
+
console.error("Usage: swarm memory remove <id>");
|
|
5718
|
+
process.exit(1);
|
|
5719
|
+
}
|
|
5720
|
+
|
|
5721
|
+
await adapter.remove(parsed.id);
|
|
5722
|
+
|
|
5723
|
+
if (parsed.json) {
|
|
5724
|
+
console.log(JSON.stringify({ success: true }));
|
|
5725
|
+
} else {
|
|
5726
|
+
p.intro("swarm memory remove");
|
|
5727
|
+
p.log.success(`Removed memory: ${parsed.id}`);
|
|
5728
|
+
p.outro("Done");
|
|
5729
|
+
}
|
|
5730
|
+
break;
|
|
5731
|
+
}
|
|
5732
|
+
|
|
5733
|
+
case "validate": {
|
|
5734
|
+
if (!parsed.id) {
|
|
5735
|
+
console.error("Usage: swarm memory validate <id>");
|
|
5736
|
+
process.exit(1);
|
|
5737
|
+
}
|
|
5738
|
+
|
|
5739
|
+
await adapter.validate(parsed.id);
|
|
5740
|
+
|
|
5741
|
+
if (parsed.json) {
|
|
5742
|
+
console.log(JSON.stringify({ success: true }));
|
|
5743
|
+
} else {
|
|
5744
|
+
p.intro("swarm memory validate");
|
|
5745
|
+
p.log.success(`Validated memory: ${parsed.id} (decay timer reset)`);
|
|
5746
|
+
p.outro("Done");
|
|
5747
|
+
}
|
|
5748
|
+
break;
|
|
5749
|
+
}
|
|
5750
|
+
|
|
5751
|
+
case "stats": {
|
|
5752
|
+
const stats = await adapter.stats();
|
|
5753
|
+
|
|
5754
|
+
if (parsed.json) {
|
|
5755
|
+
console.log(JSON.stringify({ success: true, stats }));
|
|
5756
|
+
} else {
|
|
5757
|
+
p.intro("swarm memory stats");
|
|
5758
|
+
console.log();
|
|
5759
|
+
console.log(cyan("Database Statistics:"));
|
|
5760
|
+
console.log(` Memories: ${stats.memories}`);
|
|
5761
|
+
console.log(` Embeddings: ${stats.embeddings}`);
|
|
5762
|
+
p.outro("Done");
|
|
5763
|
+
}
|
|
5764
|
+
break;
|
|
5765
|
+
}
|
|
5766
|
+
|
|
5767
|
+
case "index": {
|
|
5768
|
+
// Index is a stub - actual indexing happens via session indexing
|
|
5769
|
+
// which is handled by hivemind_index tool
|
|
5770
|
+
if (parsed.json) {
|
|
5771
|
+
console.log(JSON.stringify({ success: true, message: "Use hivemind_index tool for session indexing" }));
|
|
5772
|
+
} else {
|
|
5773
|
+
p.intro("swarm memory index");
|
|
5774
|
+
p.log.message("Session indexing is handled by the hivemind_index tool");
|
|
5775
|
+
p.log.message("Use: swarm tool hivemind_index");
|
|
5776
|
+
p.outro("Done");
|
|
5777
|
+
}
|
|
5778
|
+
break;
|
|
5779
|
+
}
|
|
5780
|
+
|
|
5781
|
+
case "sync": {
|
|
5782
|
+
// Sync is a stub - actual sync happens via .hive/memories.jsonl
|
|
5783
|
+
// which is handled by hivemind_sync tool
|
|
5784
|
+
if (parsed.json) {
|
|
5785
|
+
console.log(JSON.stringify({ success: true, message: "Use hivemind_sync tool for git sync" }));
|
|
5786
|
+
} else {
|
|
5787
|
+
p.intro("swarm memory sync");
|
|
5788
|
+
p.log.message("Memory sync to .hive/memories.jsonl is handled by the hivemind_sync tool");
|
|
5789
|
+
p.log.message("Use: swarm tool hivemind_sync");
|
|
5790
|
+
p.outro("Done");
|
|
5791
|
+
}
|
|
5792
|
+
break;
|
|
5793
|
+
}
|
|
5794
|
+
|
|
5795
|
+
default: {
|
|
5796
|
+
console.error(`Unknown subcommand: ${subcommand}`);
|
|
5797
|
+
console.error("");
|
|
5798
|
+
console.error("Usage: swarm memory <subcommand> [options]");
|
|
5799
|
+
console.error("");
|
|
5800
|
+
console.error("Subcommands:");
|
|
5801
|
+
console.error(" store <info> [--tags <tags>] Store a memory");
|
|
5802
|
+
console.error(" find <query> [--limit <n>] Search memories");
|
|
5803
|
+
console.error(" get <id> Get memory by ID");
|
|
5804
|
+
console.error(" remove <id> Delete memory");
|
|
5805
|
+
console.error(" validate <id> Reset decay timer");
|
|
5806
|
+
console.error(" stats Show database stats");
|
|
5807
|
+
console.error(" index Index sessions (use hivemind_index)");
|
|
5808
|
+
console.error(" sync Sync to git (use hivemind_sync)");
|
|
5809
|
+
console.error("");
|
|
5810
|
+
console.error("Global options:");
|
|
5811
|
+
console.error(" --json Output JSON");
|
|
5812
|
+
process.exit(1);
|
|
5813
|
+
}
|
|
5814
|
+
}
|
|
5815
|
+
} catch (error) {
|
|
5816
|
+
if (parsed.json) {
|
|
5817
|
+
console.log(JSON.stringify({
|
|
5818
|
+
success: false,
|
|
5819
|
+
error: error instanceof Error ? error.message : String(error),
|
|
5820
|
+
}));
|
|
5821
|
+
process.exit(1);
|
|
5822
|
+
} else {
|
|
5823
|
+
p.log.error("Memory operation failed");
|
|
5824
|
+
p.log.message(error instanceof Error ? error.message : String(error));
|
|
5825
|
+
p.outro("Aborted");
|
|
5826
|
+
process.exit(1);
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
}
|
|
5830
|
+
|
|
5506
5831
|
// ============================================================================
|
|
5507
5832
|
// Main
|
|
5508
5833
|
// ============================================================================
|
|
@@ -5582,6 +5907,9 @@ switch (command) {
|
|
|
5582
5907
|
case "capture":
|
|
5583
5908
|
await capture();
|
|
5584
5909
|
break;
|
|
5910
|
+
case "memory":
|
|
5911
|
+
await memory();
|
|
5912
|
+
break;
|
|
5585
5913
|
case "query":
|
|
5586
5914
|
await query();
|
|
5587
5915
|
break;
|
package/dist/bin/swarm.js
CHANGED
|
@@ -124211,6 +124211,7 @@ ${cyan("Commands:")}
|
|
|
124211
124211
|
swarm viz Alias for 'swarm serve' (deprecated, use serve)
|
|
124212
124212
|
--port <n> Port to listen on (default: 4483)
|
|
124213
124213
|
swarm cells List or get cells from database (replaces 'swarm tool hive_query')
|
|
124214
|
+
swarm memory Manage unified memory system (learnings + sessions)
|
|
124214
124215
|
swarm log View swarm logs with filtering
|
|
124215
124216
|
swarm stats Show swarm health metrics powered by swarm-insights (strategy success rates, patterns)
|
|
124216
124217
|
swarm o11y Show observability health - hook coverage, event capture, session quality
|
|
@@ -124238,6 +124239,17 @@ ${cyan("Cell Management:")}
|
|
|
124238
124239
|
swarm cells --ready Show next ready (unblocked) cell
|
|
124239
124240
|
swarm cells --json Raw JSON output (array, no wrapper)
|
|
124240
124241
|
|
|
124242
|
+
${cyan("Memory Management (Hivemind):")}
|
|
124243
|
+
swarm memory store <info> [--tags <tags>] Store a learning/memory
|
|
124244
|
+
swarm memory find <query> [--limit <n>] Search all memories (semantic + FTS)
|
|
124245
|
+
swarm memory get <id> Get specific memory by ID
|
|
124246
|
+
swarm memory remove <id> Delete outdated/incorrect memory
|
|
124247
|
+
swarm memory validate <id> Confirm accuracy (resets 90-day decay)
|
|
124248
|
+
swarm memory stats Show database statistics
|
|
124249
|
+
swarm memory index Index AI sessions (use hivemind_index tool)
|
|
124250
|
+
swarm memory sync Sync to .hive/memories.jsonl (use hivemind_sync tool)
|
|
124251
|
+
swarm memory <command> --json Output JSON for all commands
|
|
124252
|
+
|
|
124241
124253
|
${cyan("Log Viewing:")}
|
|
124242
124254
|
swarm log Tail recent logs (last 50 lines)
|
|
124243
124255
|
swarm log <module> Filter by module (e.g., compaction)
|
|
@@ -125808,6 +125820,247 @@ async function capture3() {
|
|
|
125808
125820
|
process.exit(1);
|
|
125809
125821
|
}
|
|
125810
125822
|
}
|
|
125823
|
+
function parseMemoryArgs(subcommand, args3) {
|
|
125824
|
+
let json4 = false;
|
|
125825
|
+
let info;
|
|
125826
|
+
let query2;
|
|
125827
|
+
let id;
|
|
125828
|
+
let tags;
|
|
125829
|
+
let limit;
|
|
125830
|
+
let collection;
|
|
125831
|
+
if (args3.length > 0 && !args3[0].startsWith("--")) {
|
|
125832
|
+
if (subcommand === "store") {
|
|
125833
|
+
info = args3[0];
|
|
125834
|
+
} else if (subcommand === "find") {
|
|
125835
|
+
query2 = args3[0];
|
|
125836
|
+
} else if (subcommand === "get" || subcommand === "remove" || subcommand === "validate") {
|
|
125837
|
+
id = args3[0];
|
|
125838
|
+
}
|
|
125839
|
+
}
|
|
125840
|
+
for (let i = 0;i < args3.length; i++) {
|
|
125841
|
+
const arg = args3[i];
|
|
125842
|
+
if (arg === "--json") {
|
|
125843
|
+
json4 = true;
|
|
125844
|
+
} else if (arg === "--tags" && i + 1 < args3.length) {
|
|
125845
|
+
tags = args3[++i];
|
|
125846
|
+
} else if (arg === "--limit" && i + 1 < args3.length) {
|
|
125847
|
+
const val = parseInt(args3[++i], 10);
|
|
125848
|
+
if (!isNaN(val))
|
|
125849
|
+
limit = val;
|
|
125850
|
+
} else if (arg === "--collection" && i + 1 < args3.length) {
|
|
125851
|
+
collection = args3[++i];
|
|
125852
|
+
}
|
|
125853
|
+
}
|
|
125854
|
+
return { json: json4, info, query: query2, id, tags, limit, collection };
|
|
125855
|
+
}
|
|
125856
|
+
async function memory() {
|
|
125857
|
+
const subcommand = process.argv[3];
|
|
125858
|
+
const args3 = process.argv.slice(4);
|
|
125859
|
+
const parsed = parseMemoryArgs(subcommand, args3);
|
|
125860
|
+
const projectPath = process.cwd();
|
|
125861
|
+
try {
|
|
125862
|
+
const { getDb: getDb2 } = await import("swarm-mail");
|
|
125863
|
+
const tempDirName = getLibSQLProjectTempDirName(projectPath);
|
|
125864
|
+
const tempDir = join29(tmpdir3(), tempDirName);
|
|
125865
|
+
if (!existsSync20(tempDir)) {
|
|
125866
|
+
mkdirSync11(tempDir, { recursive: true });
|
|
125867
|
+
}
|
|
125868
|
+
const dbPath = join29(tempDir, "streams.db");
|
|
125869
|
+
const dbUrl = `file://${dbPath}`;
|
|
125870
|
+
const db2 = await getDb2(dbUrl);
|
|
125871
|
+
const { createMemoryAdapter: createMemoryAdapter3 } = await import("swarm-mail");
|
|
125872
|
+
const adapter = createMemoryAdapter3(db2, {
|
|
125873
|
+
ollamaHost: process.env.OLLAMA_HOST || "http://localhost:11434",
|
|
125874
|
+
ollamaModel: process.env.OLLAMA_MODEL || "mxbai-embed-large"
|
|
125875
|
+
});
|
|
125876
|
+
switch (subcommand) {
|
|
125877
|
+
case "store": {
|
|
125878
|
+
if (!parsed.info) {
|
|
125879
|
+
console.error("Usage: swarm memory store <information> [--tags <tags>]");
|
|
125880
|
+
process.exit(1);
|
|
125881
|
+
}
|
|
125882
|
+
const result = await adapter.store(parsed.info, {
|
|
125883
|
+
tags: parsed.tags,
|
|
125884
|
+
collection: parsed.collection || "default"
|
|
125885
|
+
});
|
|
125886
|
+
if (parsed.json) {
|
|
125887
|
+
console.log(JSON.stringify({ success: true, id: result.id }));
|
|
125888
|
+
} else {
|
|
125889
|
+
p.intro("swarm memory store");
|
|
125890
|
+
p.log.success(`Stored memory: ${result.id}`);
|
|
125891
|
+
if (result.autoTags) {
|
|
125892
|
+
p.log.message(`Auto-tags: ${result.autoTags.tags.join(", ")}`);
|
|
125893
|
+
}
|
|
125894
|
+
p.outro("Done");
|
|
125895
|
+
}
|
|
125896
|
+
break;
|
|
125897
|
+
}
|
|
125898
|
+
case "find": {
|
|
125899
|
+
if (!parsed.query) {
|
|
125900
|
+
console.error("Usage: swarm memory find <query> [--limit <n>] [--collection <name>]");
|
|
125901
|
+
process.exit(1);
|
|
125902
|
+
}
|
|
125903
|
+
const results = await adapter.find(parsed.query, {
|
|
125904
|
+
limit: parsed.limit || 10,
|
|
125905
|
+
collection: parsed.collection
|
|
125906
|
+
});
|
|
125907
|
+
if (parsed.json) {
|
|
125908
|
+
console.log(JSON.stringify({ success: true, results }));
|
|
125909
|
+
} else {
|
|
125910
|
+
p.intro(`swarm memory find: "${parsed.query}"`);
|
|
125911
|
+
if (results.length === 0) {
|
|
125912
|
+
p.log.warn("No memories found");
|
|
125913
|
+
} else {
|
|
125914
|
+
for (const result of results) {
|
|
125915
|
+
console.log();
|
|
125916
|
+
console.log(cyan(`[${result.memory.id}] Score: ${result.score.toFixed(3)}`));
|
|
125917
|
+
console.log(dim(` Created: ${new Date(result.memory.createdAt).toLocaleDateString()}`));
|
|
125918
|
+
console.log(` ${result.memory.content.slice(0, 200)}${result.memory.content.length > 200 ? "..." : ""}`);
|
|
125919
|
+
if (result.memory.metadata.tags) {
|
|
125920
|
+
console.log(dim(` Tags: ${result.memory.metadata.tags.join(", ")}`));
|
|
125921
|
+
}
|
|
125922
|
+
}
|
|
125923
|
+
}
|
|
125924
|
+
p.outro(`Found ${results.length} result(s)`);
|
|
125925
|
+
}
|
|
125926
|
+
break;
|
|
125927
|
+
}
|
|
125928
|
+
case "get": {
|
|
125929
|
+
if (!parsed.id) {
|
|
125930
|
+
console.error("Usage: swarm memory get <id>");
|
|
125931
|
+
process.exit(1);
|
|
125932
|
+
}
|
|
125933
|
+
const memory2 = await adapter.get(parsed.id);
|
|
125934
|
+
if (parsed.json) {
|
|
125935
|
+
if (memory2) {
|
|
125936
|
+
console.log(JSON.stringify({ success: true, memory: memory2 }));
|
|
125937
|
+
} else {
|
|
125938
|
+
console.log(JSON.stringify({ success: false, error: "Memory not found" }));
|
|
125939
|
+
process.exit(1);
|
|
125940
|
+
}
|
|
125941
|
+
} else {
|
|
125942
|
+
p.intro(`swarm memory get: ${parsed.id}`);
|
|
125943
|
+
if (!memory2) {
|
|
125944
|
+
p.log.error("Memory not found");
|
|
125945
|
+
p.outro("Aborted");
|
|
125946
|
+
process.exit(1);
|
|
125947
|
+
} else {
|
|
125948
|
+
console.log();
|
|
125949
|
+
console.log(cyan("Content:"));
|
|
125950
|
+
console.log(memory2.content);
|
|
125951
|
+
console.log();
|
|
125952
|
+
console.log(dim(`Created: ${new Date(memory2.createdAt).toLocaleDateString()}`));
|
|
125953
|
+
console.log(dim(`Collection: ${memory2.collection}`));
|
|
125954
|
+
console.log(dim(`Confidence: ${memory2.confidence ?? 0.7}`));
|
|
125955
|
+
if (memory2.metadata.tags) {
|
|
125956
|
+
console.log(dim(`Tags: ${memory2.metadata.tags.join(", ")}`));
|
|
125957
|
+
}
|
|
125958
|
+
p.outro("Done");
|
|
125959
|
+
}
|
|
125960
|
+
}
|
|
125961
|
+
break;
|
|
125962
|
+
}
|
|
125963
|
+
case "remove": {
|
|
125964
|
+
if (!parsed.id) {
|
|
125965
|
+
console.error("Usage: swarm memory remove <id>");
|
|
125966
|
+
process.exit(1);
|
|
125967
|
+
}
|
|
125968
|
+
await adapter.remove(parsed.id);
|
|
125969
|
+
if (parsed.json) {
|
|
125970
|
+
console.log(JSON.stringify({ success: true }));
|
|
125971
|
+
} else {
|
|
125972
|
+
p.intro("swarm memory remove");
|
|
125973
|
+
p.log.success(`Removed memory: ${parsed.id}`);
|
|
125974
|
+
p.outro("Done");
|
|
125975
|
+
}
|
|
125976
|
+
break;
|
|
125977
|
+
}
|
|
125978
|
+
case "validate": {
|
|
125979
|
+
if (!parsed.id) {
|
|
125980
|
+
console.error("Usage: swarm memory validate <id>");
|
|
125981
|
+
process.exit(1);
|
|
125982
|
+
}
|
|
125983
|
+
await adapter.validate(parsed.id);
|
|
125984
|
+
if (parsed.json) {
|
|
125985
|
+
console.log(JSON.stringify({ success: true }));
|
|
125986
|
+
} else {
|
|
125987
|
+
p.intro("swarm memory validate");
|
|
125988
|
+
p.log.success(`Validated memory: ${parsed.id} (decay timer reset)`);
|
|
125989
|
+
p.outro("Done");
|
|
125990
|
+
}
|
|
125991
|
+
break;
|
|
125992
|
+
}
|
|
125993
|
+
case "stats": {
|
|
125994
|
+
const stats2 = await adapter.stats();
|
|
125995
|
+
if (parsed.json) {
|
|
125996
|
+
console.log(JSON.stringify({ success: true, stats: stats2 }));
|
|
125997
|
+
} else {
|
|
125998
|
+
p.intro("swarm memory stats");
|
|
125999
|
+
console.log();
|
|
126000
|
+
console.log(cyan("Database Statistics:"));
|
|
126001
|
+
console.log(` Memories: ${stats2.memories}`);
|
|
126002
|
+
console.log(` Embeddings: ${stats2.embeddings}`);
|
|
126003
|
+
p.outro("Done");
|
|
126004
|
+
}
|
|
126005
|
+
break;
|
|
126006
|
+
}
|
|
126007
|
+
case "index": {
|
|
126008
|
+
if (parsed.json) {
|
|
126009
|
+
console.log(JSON.stringify({ success: true, message: "Use hivemind_index tool for session indexing" }));
|
|
126010
|
+
} else {
|
|
126011
|
+
p.intro("swarm memory index");
|
|
126012
|
+
p.log.message("Session indexing is handled by the hivemind_index tool");
|
|
126013
|
+
p.log.message("Use: swarm tool hivemind_index");
|
|
126014
|
+
p.outro("Done");
|
|
126015
|
+
}
|
|
126016
|
+
break;
|
|
126017
|
+
}
|
|
126018
|
+
case "sync": {
|
|
126019
|
+
if (parsed.json) {
|
|
126020
|
+
console.log(JSON.stringify({ success: true, message: "Use hivemind_sync tool for git sync" }));
|
|
126021
|
+
} else {
|
|
126022
|
+
p.intro("swarm memory sync");
|
|
126023
|
+
p.log.message("Memory sync to .hive/memories.jsonl is handled by the hivemind_sync tool");
|
|
126024
|
+
p.log.message("Use: swarm tool hivemind_sync");
|
|
126025
|
+
p.outro("Done");
|
|
126026
|
+
}
|
|
126027
|
+
break;
|
|
126028
|
+
}
|
|
126029
|
+
default: {
|
|
126030
|
+
console.error(`Unknown subcommand: ${subcommand}`);
|
|
126031
|
+
console.error("");
|
|
126032
|
+
console.error("Usage: swarm memory <subcommand> [options]");
|
|
126033
|
+
console.error("");
|
|
126034
|
+
console.error("Subcommands:");
|
|
126035
|
+
console.error(" store <info> [--tags <tags>] Store a memory");
|
|
126036
|
+
console.error(" find <query> [--limit <n>] Search memories");
|
|
126037
|
+
console.error(" get <id> Get memory by ID");
|
|
126038
|
+
console.error(" remove <id> Delete memory");
|
|
126039
|
+
console.error(" validate <id> Reset decay timer");
|
|
126040
|
+
console.error(" stats Show database stats");
|
|
126041
|
+
console.error(" index Index sessions (use hivemind_index)");
|
|
126042
|
+
console.error(" sync Sync to git (use hivemind_sync)");
|
|
126043
|
+
console.error("");
|
|
126044
|
+
console.error("Global options:");
|
|
126045
|
+
console.error(" --json Output JSON");
|
|
126046
|
+
process.exit(1);
|
|
126047
|
+
}
|
|
126048
|
+
}
|
|
126049
|
+
} catch (error54) {
|
|
126050
|
+
if (parsed.json) {
|
|
126051
|
+
console.log(JSON.stringify({
|
|
126052
|
+
success: false,
|
|
126053
|
+
error: error54 instanceof Error ? error54.message : String(error54)
|
|
126054
|
+
}));
|
|
126055
|
+
process.exit(1);
|
|
126056
|
+
} else {
|
|
126057
|
+
p.log.error("Memory operation failed");
|
|
126058
|
+
p.log.message(error54 instanceof Error ? error54.message : String(error54));
|
|
126059
|
+
p.outro("Aborted");
|
|
126060
|
+
process.exit(1);
|
|
126061
|
+
}
|
|
126062
|
+
}
|
|
126063
|
+
}
|
|
125811
126064
|
var command = process.argv[2];
|
|
125812
126065
|
switch (command) {
|
|
125813
126066
|
case "setup": {
|
|
@@ -125880,6 +126133,9 @@ switch (command) {
|
|
|
125880
126133
|
case "capture":
|
|
125881
126134
|
await capture3();
|
|
125882
126135
|
break;
|
|
126136
|
+
case "memory":
|
|
126137
|
+
await memory();
|
|
126138
|
+
break;
|
|
125883
126139
|
case "query":
|
|
125884
126140
|
await query();
|
|
125885
126141
|
break;
|
|
@@ -1401,6 +1401,71 @@ const cass_stats = tool({
|
|
|
1401
1401
|
execute: (args, ctx) => execTool("cass_stats", args, ctx),
|
|
1402
1402
|
});
|
|
1403
1403
|
|
|
1404
|
+
// =============================================================================
|
|
1405
|
+
// Hivemind Tools (Unified Memory - Sessions + Learnings)
|
|
1406
|
+
// =============================================================================
|
|
1407
|
+
|
|
1408
|
+
const hivemind_store = tool({
|
|
1409
|
+
description: "Store a memory (learnings, decisions, patterns) with metadata and tags. Include WHY, not just WHAT.",
|
|
1410
|
+
args: {
|
|
1411
|
+
information: tool.schema.string().describe("The learning, decision, or pattern to store (include context and reasoning)"),
|
|
1412
|
+
tags: tool.schema.string().optional().describe("Comma-separated tags for categorization (e.g., 'auth,oauth,tokens')"),
|
|
1413
|
+
},
|
|
1414
|
+
execute: (args, ctx) => execTool("hivemind_store", args, ctx),
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1417
|
+
const hivemind_find = tool({
|
|
1418
|
+
description: "Search all memories (learnings + sessions) by semantic similarity. Use BEFORE implementing to check if any agent solved it before.",
|
|
1419
|
+
args: {
|
|
1420
|
+
query: tool.schema.string().describe("Search query (e.g., 'token refresh race condition')"),
|
|
1421
|
+
limit: tool.schema.number().optional().describe("Max results to return (default: 5)"),
|
|
1422
|
+
collection: tool.schema.string().optional().describe("Filter by collection: 'default' (learnings), 'claude', 'cursor', etc., or omit for all"),
|
|
1423
|
+
},
|
|
1424
|
+
execute: (args, ctx) => execTool("hivemind_find", args, ctx),
|
|
1425
|
+
});
|
|
1426
|
+
|
|
1427
|
+
const hivemind_get = tool({
|
|
1428
|
+
description: "Get specific memory by ID",
|
|
1429
|
+
args: {
|
|
1430
|
+
id: tool.schema.string().describe("Memory ID (e.g., 'mem_xyz123')"),
|
|
1431
|
+
},
|
|
1432
|
+
execute: (args, ctx) => execTool("hivemind_get", args, ctx),
|
|
1433
|
+
});
|
|
1434
|
+
|
|
1435
|
+
const hivemind_remove = tool({
|
|
1436
|
+
description: "Delete outdated/incorrect memory",
|
|
1437
|
+
args: {
|
|
1438
|
+
id: tool.schema.string().describe("Memory ID to remove"),
|
|
1439
|
+
},
|
|
1440
|
+
execute: (args, ctx) => execTool("hivemind_remove", args, ctx),
|
|
1441
|
+
});
|
|
1442
|
+
|
|
1443
|
+
const hivemind_validate = tool({
|
|
1444
|
+
description: "Confirm memory is still accurate (resets 90-day decay timer)",
|
|
1445
|
+
args: {
|
|
1446
|
+
id: tool.schema.string().describe("Memory ID to validate"),
|
|
1447
|
+
},
|
|
1448
|
+
execute: (args, ctx) => execTool("hivemind_validate", args, ctx),
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1451
|
+
const hivemind_stats = tool({
|
|
1452
|
+
description: "Memory statistics and health check (documents, chunks, embeddings)",
|
|
1453
|
+
args: {},
|
|
1454
|
+
execute: (args, ctx) => execTool("hivemind_stats", args, ctx),
|
|
1455
|
+
});
|
|
1456
|
+
|
|
1457
|
+
const hivemind_index = tool({
|
|
1458
|
+
description: "Index AI session directories (automatically indexes ~/.config/opencode/sessions, ~/.cursor-tutor, etc.)",
|
|
1459
|
+
args: {},
|
|
1460
|
+
execute: (args, ctx) => execTool("hivemind_index", args, ctx),
|
|
1461
|
+
});
|
|
1462
|
+
|
|
1463
|
+
const hivemind_sync = tool({
|
|
1464
|
+
description: "Sync learnings to .hive/memories.jsonl for git-backed team sharing",
|
|
1465
|
+
args: {},
|
|
1466
|
+
execute: (args, ctx) => execTool("hivemind_sync", args, ctx),
|
|
1467
|
+
});
|
|
1468
|
+
|
|
1404
1469
|
// =============================================================================
|
|
1405
1470
|
// Plugin Export
|
|
1406
1471
|
// =============================================================================
|
|
@@ -2573,6 +2638,15 @@ const SwarmPlugin: Plugin = async (
|
|
|
2573
2638
|
cass_health,
|
|
2574
2639
|
cass_index,
|
|
2575
2640
|
cass_stats,
|
|
2641
|
+
// Hivemind (Unified Memory - Sessions + Learnings)
|
|
2642
|
+
hivemind_store,
|
|
2643
|
+
hivemind_find,
|
|
2644
|
+
hivemind_get,
|
|
2645
|
+
hivemind_remove,
|
|
2646
|
+
hivemind_validate,
|
|
2647
|
+
hivemind_stats,
|
|
2648
|
+
hivemind_index,
|
|
2649
|
+
hivemind_sync,
|
|
2576
2650
|
},
|
|
2577
2651
|
|
|
2578
2652
|
// Swarm-aware compaction hook with LLM-powered continuation prompts
|
|
@@ -1401,6 +1401,71 @@ const cass_stats = tool({
|
|
|
1401
1401
|
execute: (args, ctx) => execTool("cass_stats", args, ctx),
|
|
1402
1402
|
});
|
|
1403
1403
|
|
|
1404
|
+
// =============================================================================
|
|
1405
|
+
// Hivemind Tools (Unified Memory - Sessions + Learnings)
|
|
1406
|
+
// =============================================================================
|
|
1407
|
+
|
|
1408
|
+
const hivemind_store = tool({
|
|
1409
|
+
description: "Store a memory (learnings, decisions, patterns) with metadata and tags. Include WHY, not just WHAT.",
|
|
1410
|
+
args: {
|
|
1411
|
+
information: tool.schema.string().describe("The learning, decision, or pattern to store (include context and reasoning)"),
|
|
1412
|
+
tags: tool.schema.string().optional().describe("Comma-separated tags for categorization (e.g., 'auth,oauth,tokens')"),
|
|
1413
|
+
},
|
|
1414
|
+
execute: (args, ctx) => execTool("hivemind_store", args, ctx),
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1417
|
+
const hivemind_find = tool({
|
|
1418
|
+
description: "Search all memories (learnings + sessions) by semantic similarity. Use BEFORE implementing to check if any agent solved it before.",
|
|
1419
|
+
args: {
|
|
1420
|
+
query: tool.schema.string().describe("Search query (e.g., 'token refresh race condition')"),
|
|
1421
|
+
limit: tool.schema.number().optional().describe("Max results to return (default: 5)"),
|
|
1422
|
+
collection: tool.schema.string().optional().describe("Filter by collection: 'default' (learnings), 'claude', 'cursor', etc., or omit for all"),
|
|
1423
|
+
},
|
|
1424
|
+
execute: (args, ctx) => execTool("hivemind_find", args, ctx),
|
|
1425
|
+
});
|
|
1426
|
+
|
|
1427
|
+
const hivemind_get = tool({
|
|
1428
|
+
description: "Get specific memory by ID",
|
|
1429
|
+
args: {
|
|
1430
|
+
id: tool.schema.string().describe("Memory ID (e.g., 'mem_xyz123')"),
|
|
1431
|
+
},
|
|
1432
|
+
execute: (args, ctx) => execTool("hivemind_get", args, ctx),
|
|
1433
|
+
});
|
|
1434
|
+
|
|
1435
|
+
const hivemind_remove = tool({
|
|
1436
|
+
description: "Delete outdated/incorrect memory",
|
|
1437
|
+
args: {
|
|
1438
|
+
id: tool.schema.string().describe("Memory ID to remove"),
|
|
1439
|
+
},
|
|
1440
|
+
execute: (args, ctx) => execTool("hivemind_remove", args, ctx),
|
|
1441
|
+
});
|
|
1442
|
+
|
|
1443
|
+
const hivemind_validate = tool({
|
|
1444
|
+
description: "Confirm memory is still accurate (resets 90-day decay timer)",
|
|
1445
|
+
args: {
|
|
1446
|
+
id: tool.schema.string().describe("Memory ID to validate"),
|
|
1447
|
+
},
|
|
1448
|
+
execute: (args, ctx) => execTool("hivemind_validate", args, ctx),
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1451
|
+
const hivemind_stats = tool({
|
|
1452
|
+
description: "Memory statistics and health check (documents, chunks, embeddings)",
|
|
1453
|
+
args: {},
|
|
1454
|
+
execute: (args, ctx) => execTool("hivemind_stats", args, ctx),
|
|
1455
|
+
});
|
|
1456
|
+
|
|
1457
|
+
const hivemind_index = tool({
|
|
1458
|
+
description: "Index AI session directories (automatically indexes ~/.config/opencode/sessions, ~/.cursor-tutor, etc.)",
|
|
1459
|
+
args: {},
|
|
1460
|
+
execute: (args, ctx) => execTool("hivemind_index", args, ctx),
|
|
1461
|
+
});
|
|
1462
|
+
|
|
1463
|
+
const hivemind_sync = tool({
|
|
1464
|
+
description: "Sync learnings to .hive/memories.jsonl for git-backed team sharing",
|
|
1465
|
+
args: {},
|
|
1466
|
+
execute: (args, ctx) => execTool("hivemind_sync", args, ctx),
|
|
1467
|
+
});
|
|
1468
|
+
|
|
1404
1469
|
// =============================================================================
|
|
1405
1470
|
// Plugin Export
|
|
1406
1471
|
// =============================================================================
|
|
@@ -2573,6 +2638,15 @@ const SwarmPlugin: Plugin = async (
|
|
|
2573
2638
|
cass_health,
|
|
2574
2639
|
cass_index,
|
|
2575
2640
|
cass_stats,
|
|
2641
|
+
// Hivemind (Unified Memory - Sessions + Learnings)
|
|
2642
|
+
hivemind_store,
|
|
2643
|
+
hivemind_find,
|
|
2644
|
+
hivemind_get,
|
|
2645
|
+
hivemind_remove,
|
|
2646
|
+
hivemind_validate,
|
|
2647
|
+
hivemind_stats,
|
|
2648
|
+
hivemind_index,
|
|
2649
|
+
hivemind_sync,
|
|
2576
2650
|
},
|
|
2577
2651
|
|
|
2578
2652
|
// Swarm-aware compaction hook with LLM-powered continuation prompts
|
package/package.json
CHANGED