opencode-swarm-plugin 0.47.0 → 0.48.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/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
@@ -77826,12 +77826,18 @@ This will be recorded as a negative learning signal.`;
77826
77826
  memoryError = `Failed to store memory: ${error452 instanceof Error ? error452.message : String(error452)}`;
77827
77827
  console.warn(`[swarm_complete] ${memoryError}`);
77828
77828
  }
77829
+ let reservationsReleased = false;
77830
+ let reservationsReleasedCount = 0;
77831
+ let reservationsReleaseError;
77829
77832
  try {
77830
- await releaseSwarmFiles({
77833
+ const releaseResult = await releaseSwarmFiles({
77831
77834
  projectPath: args.project_key,
77832
77835
  agentName: args.agent_name
77833
77836
  });
77837
+ reservationsReleased = true;
77838
+ reservationsReleasedCount = releaseResult.released;
77834
77839
  } catch (error452) {
77840
+ reservationsReleaseError = error452 instanceof Error ? error452.message : String(error452);
77835
77841
  console.warn(`[swarm] Failed to release file reservations for ${args.agent_name}:`, error452);
77836
77842
  }
77837
77843
  const epicId2 = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
@@ -77867,7 +77873,9 @@ This will be recorded as a negative learning signal.`;
77867
77873
  success: true,
77868
77874
  bead_id: args.bead_id,
77869
77875
  closed: true,
77870
- reservations_released: true,
77876
+ reservations_released: reservationsReleased,
77877
+ reservations_released_count: reservationsReleasedCount,
77878
+ reservations_release_error: reservationsReleaseError,
77871
77879
  synced: syncSuccess,
77872
77880
  sync_error: syncError,
77873
77881
  message_sent: messageSent,
@@ -103366,12 +103374,18 @@ This will be recorded as a negative learning signal.`;
103366
103374
  memoryError = `Failed to store memory: ${error54 instanceof Error ? error54.message : String(error54)}`;
103367
103375
  console.warn(`[swarm_complete] ${memoryError}`);
103368
103376
  }
103377
+ let reservationsReleased = false;
103378
+ let reservationsReleasedCount = 0;
103379
+ let reservationsReleaseError;
103369
103380
  try {
103370
- await releaseSwarmFiles3({
103381
+ const releaseResult = await releaseSwarmFiles3({
103371
103382
  projectPath: args2.project_key,
103372
103383
  agentName: args2.agent_name
103373
103384
  });
103385
+ reservationsReleased = true;
103386
+ reservationsReleasedCount = releaseResult.released;
103374
103387
  } catch (error54) {
103388
+ reservationsReleaseError = error54 instanceof Error ? error54.message : String(error54);
103375
103389
  console.warn(`[swarm] Failed to release file reservations for ${args2.agent_name}:`, error54);
103376
103390
  }
103377
103391
  const epicId2 = args2.bead_id.includes(".") ? args2.bead_id.split(".")[0] : args2.bead_id;
@@ -103407,7 +103421,9 @@ This will be recorded as a negative learning signal.`;
103407
103421
  success: true,
103408
103422
  bead_id: args2.bead_id,
103409
103423
  closed: true,
103410
- reservations_released: true,
103424
+ reservations_released: reservationsReleased,
103425
+ reservations_released_count: reservationsReleasedCount,
103426
+ reservations_release_error: reservationsReleaseError,
103411
103427
  synced: syncSuccess,
103412
103428
  sync_error: syncError,
103413
103429
  message_sent: messageSent,
@@ -124211,6 +124227,7 @@ ${cyan("Commands:")}
124211
124227
  swarm viz Alias for 'swarm serve' (deprecated, use serve)
124212
124228
  --port <n> Port to listen on (default: 4483)
124213
124229
  swarm cells List or get cells from database (replaces 'swarm tool hive_query')
124230
+ swarm memory Manage unified memory system (learnings + sessions)
124214
124231
  swarm log View swarm logs with filtering
124215
124232
  swarm stats Show swarm health metrics powered by swarm-insights (strategy success rates, patterns)
124216
124233
  swarm o11y Show observability health - hook coverage, event capture, session quality
@@ -124238,6 +124255,17 @@ ${cyan("Cell Management:")}
124238
124255
  swarm cells --ready Show next ready (unblocked) cell
124239
124256
  swarm cells --json Raw JSON output (array, no wrapper)
124240
124257
 
124258
+ ${cyan("Memory Management (Hivemind):")}
124259
+ swarm memory store <info> [--tags <tags>] Store a learning/memory
124260
+ swarm memory find <query> [--limit <n>] Search all memories (semantic + FTS)
124261
+ swarm memory get <id> Get specific memory by ID
124262
+ swarm memory remove <id> Delete outdated/incorrect memory
124263
+ swarm memory validate <id> Confirm accuracy (resets 90-day decay)
124264
+ swarm memory stats Show database statistics
124265
+ swarm memory index Index AI sessions (use hivemind_index tool)
124266
+ swarm memory sync Sync to .hive/memories.jsonl (use hivemind_sync tool)
124267
+ swarm memory <command> --json Output JSON for all commands
124268
+
124241
124269
  ${cyan("Log Viewing:")}
124242
124270
  swarm log Tail recent logs (last 50 lines)
124243
124271
  swarm log <module> Filter by module (e.g., compaction)
@@ -125808,6 +125836,247 @@ async function capture3() {
125808
125836
  process.exit(1);
125809
125837
  }
125810
125838
  }
125839
+ function parseMemoryArgs(subcommand, args3) {
125840
+ let json4 = false;
125841
+ let info;
125842
+ let query2;
125843
+ let id;
125844
+ let tags;
125845
+ let limit;
125846
+ let collection;
125847
+ if (args3.length > 0 && !args3[0].startsWith("--")) {
125848
+ if (subcommand === "store") {
125849
+ info = args3[0];
125850
+ } else if (subcommand === "find") {
125851
+ query2 = args3[0];
125852
+ } else if (subcommand === "get" || subcommand === "remove" || subcommand === "validate") {
125853
+ id = args3[0];
125854
+ }
125855
+ }
125856
+ for (let i = 0;i < args3.length; i++) {
125857
+ const arg = args3[i];
125858
+ if (arg === "--json") {
125859
+ json4 = true;
125860
+ } else if (arg === "--tags" && i + 1 < args3.length) {
125861
+ tags = args3[++i];
125862
+ } else if (arg === "--limit" && i + 1 < args3.length) {
125863
+ const val = parseInt(args3[++i], 10);
125864
+ if (!isNaN(val))
125865
+ limit = val;
125866
+ } else if (arg === "--collection" && i + 1 < args3.length) {
125867
+ collection = args3[++i];
125868
+ }
125869
+ }
125870
+ return { json: json4, info, query: query2, id, tags, limit, collection };
125871
+ }
125872
+ async function memory() {
125873
+ const subcommand = process.argv[3];
125874
+ const args3 = process.argv.slice(4);
125875
+ const parsed = parseMemoryArgs(subcommand, args3);
125876
+ const projectPath = process.cwd();
125877
+ try {
125878
+ const { getDb: getDb2 } = await import("swarm-mail");
125879
+ const tempDirName = getLibSQLProjectTempDirName(projectPath);
125880
+ const tempDir = join29(tmpdir3(), tempDirName);
125881
+ if (!existsSync20(tempDir)) {
125882
+ mkdirSync11(tempDir, { recursive: true });
125883
+ }
125884
+ const dbPath = join29(tempDir, "streams.db");
125885
+ const dbUrl = `file://${dbPath}`;
125886
+ const db2 = await getDb2(dbUrl);
125887
+ const { createMemoryAdapter: createMemoryAdapter3 } = await import("swarm-mail");
125888
+ const adapter = createMemoryAdapter3(db2, {
125889
+ ollamaHost: process.env.OLLAMA_HOST || "http://localhost:11434",
125890
+ ollamaModel: process.env.OLLAMA_MODEL || "mxbai-embed-large"
125891
+ });
125892
+ switch (subcommand) {
125893
+ case "store": {
125894
+ if (!parsed.info) {
125895
+ console.error("Usage: swarm memory store <information> [--tags <tags>]");
125896
+ process.exit(1);
125897
+ }
125898
+ const result = await adapter.store(parsed.info, {
125899
+ tags: parsed.tags,
125900
+ collection: parsed.collection || "default"
125901
+ });
125902
+ if (parsed.json) {
125903
+ console.log(JSON.stringify({ success: true, id: result.id }));
125904
+ } else {
125905
+ p.intro("swarm memory store");
125906
+ p.log.success(`Stored memory: ${result.id}`);
125907
+ if (result.autoTags) {
125908
+ p.log.message(`Auto-tags: ${result.autoTags.tags.join(", ")}`);
125909
+ }
125910
+ p.outro("Done");
125911
+ }
125912
+ break;
125913
+ }
125914
+ case "find": {
125915
+ if (!parsed.query) {
125916
+ console.error("Usage: swarm memory find <query> [--limit <n>] [--collection <name>]");
125917
+ process.exit(1);
125918
+ }
125919
+ const results = await adapter.find(parsed.query, {
125920
+ limit: parsed.limit || 10,
125921
+ collection: parsed.collection
125922
+ });
125923
+ if (parsed.json) {
125924
+ console.log(JSON.stringify({ success: true, results }));
125925
+ } else {
125926
+ p.intro(`swarm memory find: "${parsed.query}"`);
125927
+ if (results.length === 0) {
125928
+ p.log.warn("No memories found");
125929
+ } else {
125930
+ for (const result of results) {
125931
+ console.log();
125932
+ console.log(cyan(`[${result.memory.id}] Score: ${result.score.toFixed(3)}`));
125933
+ console.log(dim(` Created: ${new Date(result.memory.createdAt).toLocaleDateString()}`));
125934
+ console.log(` ${result.memory.content.slice(0, 200)}${result.memory.content.length > 200 ? "..." : ""}`);
125935
+ if (result.memory.metadata.tags) {
125936
+ console.log(dim(` Tags: ${result.memory.metadata.tags.join(", ")}`));
125937
+ }
125938
+ }
125939
+ }
125940
+ p.outro(`Found ${results.length} result(s)`);
125941
+ }
125942
+ break;
125943
+ }
125944
+ case "get": {
125945
+ if (!parsed.id) {
125946
+ console.error("Usage: swarm memory get <id>");
125947
+ process.exit(1);
125948
+ }
125949
+ const memory2 = await adapter.get(parsed.id);
125950
+ if (parsed.json) {
125951
+ if (memory2) {
125952
+ console.log(JSON.stringify({ success: true, memory: memory2 }));
125953
+ } else {
125954
+ console.log(JSON.stringify({ success: false, error: "Memory not found" }));
125955
+ process.exit(1);
125956
+ }
125957
+ } else {
125958
+ p.intro(`swarm memory get: ${parsed.id}`);
125959
+ if (!memory2) {
125960
+ p.log.error("Memory not found");
125961
+ p.outro("Aborted");
125962
+ process.exit(1);
125963
+ } else {
125964
+ console.log();
125965
+ console.log(cyan("Content:"));
125966
+ console.log(memory2.content);
125967
+ console.log();
125968
+ console.log(dim(`Created: ${new Date(memory2.createdAt).toLocaleDateString()}`));
125969
+ console.log(dim(`Collection: ${memory2.collection}`));
125970
+ console.log(dim(`Confidence: ${memory2.confidence ?? 0.7}`));
125971
+ if (memory2.metadata.tags) {
125972
+ console.log(dim(`Tags: ${memory2.metadata.tags.join(", ")}`));
125973
+ }
125974
+ p.outro("Done");
125975
+ }
125976
+ }
125977
+ break;
125978
+ }
125979
+ case "remove": {
125980
+ if (!parsed.id) {
125981
+ console.error("Usage: swarm memory remove <id>");
125982
+ process.exit(1);
125983
+ }
125984
+ await adapter.remove(parsed.id);
125985
+ if (parsed.json) {
125986
+ console.log(JSON.stringify({ success: true }));
125987
+ } else {
125988
+ p.intro("swarm memory remove");
125989
+ p.log.success(`Removed memory: ${parsed.id}`);
125990
+ p.outro("Done");
125991
+ }
125992
+ break;
125993
+ }
125994
+ case "validate": {
125995
+ if (!parsed.id) {
125996
+ console.error("Usage: swarm memory validate <id>");
125997
+ process.exit(1);
125998
+ }
125999
+ await adapter.validate(parsed.id);
126000
+ if (parsed.json) {
126001
+ console.log(JSON.stringify({ success: true }));
126002
+ } else {
126003
+ p.intro("swarm memory validate");
126004
+ p.log.success(`Validated memory: ${parsed.id} (decay timer reset)`);
126005
+ p.outro("Done");
126006
+ }
126007
+ break;
126008
+ }
126009
+ case "stats": {
126010
+ const stats2 = await adapter.stats();
126011
+ if (parsed.json) {
126012
+ console.log(JSON.stringify({ success: true, stats: stats2 }));
126013
+ } else {
126014
+ p.intro("swarm memory stats");
126015
+ console.log();
126016
+ console.log(cyan("Database Statistics:"));
126017
+ console.log(` Memories: ${stats2.memories}`);
126018
+ console.log(` Embeddings: ${stats2.embeddings}`);
126019
+ p.outro("Done");
126020
+ }
126021
+ break;
126022
+ }
126023
+ case "index": {
126024
+ if (parsed.json) {
126025
+ console.log(JSON.stringify({ success: true, message: "Use hivemind_index tool for session indexing" }));
126026
+ } else {
126027
+ p.intro("swarm memory index");
126028
+ p.log.message("Session indexing is handled by the hivemind_index tool");
126029
+ p.log.message("Use: swarm tool hivemind_index");
126030
+ p.outro("Done");
126031
+ }
126032
+ break;
126033
+ }
126034
+ case "sync": {
126035
+ if (parsed.json) {
126036
+ console.log(JSON.stringify({ success: true, message: "Use hivemind_sync tool for git sync" }));
126037
+ } else {
126038
+ p.intro("swarm memory sync");
126039
+ p.log.message("Memory sync to .hive/memories.jsonl is handled by the hivemind_sync tool");
126040
+ p.log.message("Use: swarm tool hivemind_sync");
126041
+ p.outro("Done");
126042
+ }
126043
+ break;
126044
+ }
126045
+ default: {
126046
+ console.error(`Unknown subcommand: ${subcommand}`);
126047
+ console.error("");
126048
+ console.error("Usage: swarm memory <subcommand> [options]");
126049
+ console.error("");
126050
+ console.error("Subcommands:");
126051
+ console.error(" store <info> [--tags <tags>] Store a memory");
126052
+ console.error(" find <query> [--limit <n>] Search memories");
126053
+ console.error(" get <id> Get memory by ID");
126054
+ console.error(" remove <id> Delete memory");
126055
+ console.error(" validate <id> Reset decay timer");
126056
+ console.error(" stats Show database stats");
126057
+ console.error(" index Index sessions (use hivemind_index)");
126058
+ console.error(" sync Sync to git (use hivemind_sync)");
126059
+ console.error("");
126060
+ console.error("Global options:");
126061
+ console.error(" --json Output JSON");
126062
+ process.exit(1);
126063
+ }
126064
+ }
126065
+ } catch (error54) {
126066
+ if (parsed.json) {
126067
+ console.log(JSON.stringify({
126068
+ success: false,
126069
+ error: error54 instanceof Error ? error54.message : String(error54)
126070
+ }));
126071
+ process.exit(1);
126072
+ } else {
126073
+ p.log.error("Memory operation failed");
126074
+ p.log.message(error54 instanceof Error ? error54.message : String(error54));
126075
+ p.outro("Aborted");
126076
+ process.exit(1);
126077
+ }
126078
+ }
126079
+ }
125811
126080
  var command = process.argv[2];
125812
126081
  switch (command) {
125813
126082
  case "setup": {
@@ -125880,6 +126149,9 @@ switch (command) {
125880
126149
  case "capture":
125881
126150
  await capture3();
125882
126151
  break;
126152
+ case "memory":
126153
+ await memory();
126154
+ break;
125883
126155
  case "query":
125884
126156
  await query();
125885
126157
  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
package/dist/index.js CHANGED
@@ -47140,12 +47140,18 @@ This will be recorded as a negative learning signal.`;
47140
47140
  memoryError = `Failed to store memory: ${error45 instanceof Error ? error45.message : String(error45)}`;
47141
47141
  console.warn(`[swarm_complete] ${memoryError}`);
47142
47142
  }
47143
+ let reservationsReleased = false;
47144
+ let reservationsReleasedCount = 0;
47145
+ let reservationsReleaseError;
47143
47146
  try {
47144
- await releaseSwarmFiles2({
47147
+ const releaseResult = await releaseSwarmFiles2({
47145
47148
  projectPath: args.project_key,
47146
47149
  agentName: args.agent_name
47147
47150
  });
47151
+ reservationsReleased = true;
47152
+ reservationsReleasedCount = releaseResult.released;
47148
47153
  } catch (error45) {
47154
+ reservationsReleaseError = error45 instanceof Error ? error45.message : String(error45);
47149
47155
  console.warn(`[swarm] Failed to release file reservations for ${args.agent_name}:`, error45);
47150
47156
  }
47151
47157
  const epicId2 = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
@@ -47181,7 +47187,9 @@ This will be recorded as a negative learning signal.`;
47181
47187
  success: true,
47182
47188
  bead_id: args.bead_id,
47183
47189
  closed: true,
47184
- reservations_released: true,
47190
+ reservations_released: reservationsReleased,
47191
+ reservations_released_count: reservationsReleasedCount,
47192
+ reservations_release_error: reservationsReleaseError,
47185
47193
  synced: syncSuccess,
47186
47194
  sync_error: syncError,
47187
47195
  message_sent: messageSent,
package/dist/plugin.js CHANGED
@@ -46736,12 +46736,18 @@ This will be recorded as a negative learning signal.`;
46736
46736
  memoryError = `Failed to store memory: ${error45 instanceof Error ? error45.message : String(error45)}`;
46737
46737
  console.warn(`[swarm_complete] ${memoryError}`);
46738
46738
  }
46739
+ let reservationsReleased = false;
46740
+ let reservationsReleasedCount = 0;
46741
+ let reservationsReleaseError;
46739
46742
  try {
46740
- await releaseSwarmFiles2({
46743
+ const releaseResult = await releaseSwarmFiles2({
46741
46744
  projectPath: args.project_key,
46742
46745
  agentName: args.agent_name
46743
46746
  });
46747
+ reservationsReleased = true;
46748
+ reservationsReleasedCount = releaseResult.released;
46744
46749
  } catch (error45) {
46750
+ reservationsReleaseError = error45 instanceof Error ? error45.message : String(error45);
46745
46751
  console.warn(`[swarm] Failed to release file reservations for ${args.agent_name}:`, error45);
46746
46752
  }
46747
46753
  const epicId2 = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
@@ -46777,7 +46783,9 @@ This will be recorded as a negative learning signal.`;
46777
46783
  success: true,
46778
46784
  bead_id: args.bead_id,
46779
46785
  closed: true,
46780
- reservations_released: true,
46786
+ reservations_released: reservationsReleased,
46787
+ reservations_released_count: reservationsReleasedCount,
46788
+ reservations_release_error: reservationsReleaseError,
46781
46789
  synced: syncSuccess,
46782
46790
  sync_error: syncError,
46783
46791
  message_sent: messageSent,
@@ -1 +1 @@
1
- {"version":3,"file":"swarm-orchestrate.d.ts","sourceRoot":"","sources":["../src/swarm-orchestrate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"swarm-orchestrate.d.ts","sourceRoot":"","sources":["../src/swarm-orchestrate.ts"],"names":[],"mappings":"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"}
@@ -23624,12 +23624,18 @@ This will be recorded as a negative learning signal.`;
23624
23624
  memoryError = `Failed to store memory: ${error45 instanceof Error ? error45.message : String(error45)}`;
23625
23625
  console.warn(`[swarm_complete] ${memoryError}`);
23626
23626
  }
23627
+ let reservationsReleased = false;
23628
+ let reservationsReleasedCount = 0;
23629
+ let reservationsReleaseError;
23627
23630
  try {
23628
- await releaseSwarmFiles({
23631
+ const releaseResult = await releaseSwarmFiles({
23629
23632
  projectPath: args.project_key,
23630
23633
  agentName: args.agent_name
23631
23634
  });
23635
+ reservationsReleased = true;
23636
+ reservationsReleasedCount = releaseResult.released;
23632
23637
  } catch (error45) {
23638
+ reservationsReleaseError = error45 instanceof Error ? error45.message : String(error45);
23633
23639
  console.warn(`[swarm] Failed to release file reservations for ${args.agent_name}:`, error45);
23634
23640
  }
23635
23641
  const epicId2 = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
@@ -23665,7 +23671,9 @@ This will be recorded as a negative learning signal.`;
23665
23671
  success: true,
23666
23672
  bead_id: args.bead_id,
23667
23673
  closed: true,
23668
- reservations_released: true,
23674
+ reservations_released: reservationsReleased,
23675
+ reservations_released_count: reservationsReleasedCount,
23676
+ reservations_release_error: reservationsReleaseError,
23669
23677
  synced: syncSuccess,
23670
23678
  sync_error: syncError,
23671
23679
  message_sent: messageSent,
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm-plugin",
3
- "version": "0.47.0",
3
+ "version": "0.48.1",
4
4
  "description": "Multi-agent swarm coordination for OpenCode with learning capabilities, beads integration, and Agent Mail",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -64,7 +64,7 @@
64
64
  "minimatch": "^10.1.1",
65
65
  "pino": "^9.6.0",
66
66
  "pino-roll": "^1.3.0",
67
- "swarm-mail": "1.7.0",
67
+ "swarm-mail": "1.7.1",
68
68
  "yaml": "^2.8.2",
69
69
  "zod": "4.1.8"
70
70
  },