opencode-swarm-plugin 0.46.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 +674 -108
- package/dist/bin/swarm.js +1695 -590
- 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
3
|
* OpenCode Swarm Plugin CLI
|
|
4
4
|
*
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
createDurableStreamAdapter,
|
|
52
52
|
createDurableStreamServer,
|
|
53
53
|
} from "swarm-mail";
|
|
54
|
-
import { execSync } from "child_process";
|
|
54
|
+
import { execSync, spawn } from "child_process";
|
|
55
55
|
import { tmpdir } from "os";
|
|
56
56
|
|
|
57
57
|
// Query & observability tools
|
|
@@ -464,6 +464,15 @@ interface CheckResult {
|
|
|
464
464
|
// ============================================================================
|
|
465
465
|
|
|
466
466
|
const DEPENDENCIES: Dependency[] = [
|
|
467
|
+
{
|
|
468
|
+
name: "Bun",
|
|
469
|
+
command: "bun",
|
|
470
|
+
checkArgs: ["--version"],
|
|
471
|
+
required: true,
|
|
472
|
+
install: "curl -fsSL https://bun.sh/install | bash",
|
|
473
|
+
installType: "manual",
|
|
474
|
+
description: "JavaScript runtime (required for CLI)",
|
|
475
|
+
},
|
|
467
476
|
{
|
|
468
477
|
name: "OpenCode",
|
|
469
478
|
command: "opencode",
|
|
@@ -512,34 +521,53 @@ async function checkCommand(
|
|
|
512
521
|
cmd: string,
|
|
513
522
|
args: string[],
|
|
514
523
|
): Promise<{ available: boolean; version?: string }> {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
524
|
+
return new Promise((resolve) => {
|
|
525
|
+
try {
|
|
526
|
+
const proc = spawn(cmd, args, {
|
|
527
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
let stdout = "";
|
|
531
|
+
proc.stdout?.on("data", (data) => {
|
|
532
|
+
stdout += data.toString();
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
proc.on("error", () => {
|
|
536
|
+
resolve({ available: false });
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
proc.on("close", (exitCode) => {
|
|
540
|
+
if (exitCode === 0) {
|
|
541
|
+
const versionMatch = stdout.match(/v?(\d+\.\d+\.\d+)/);
|
|
542
|
+
resolve({ available: true, version: versionMatch?.[1] });
|
|
543
|
+
} else {
|
|
544
|
+
resolve({ available: false });
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
} catch {
|
|
548
|
+
resolve({ available: false });
|
|
525
549
|
}
|
|
526
|
-
|
|
527
|
-
} catch {
|
|
528
|
-
return { available: false };
|
|
529
|
-
}
|
|
550
|
+
});
|
|
530
551
|
}
|
|
531
552
|
|
|
532
553
|
async function runInstall(command: string): Promise<boolean> {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
554
|
+
return new Promise((resolve) => {
|
|
555
|
+
try {
|
|
556
|
+
const proc = spawn("bash", ["-c", command], {
|
|
557
|
+
stdio: "inherit",
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
proc.on("error", () => {
|
|
561
|
+
resolve(false);
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
proc.on("close", (exitCode) => {
|
|
565
|
+
resolve(exitCode === 0);
|
|
566
|
+
});
|
|
567
|
+
} catch {
|
|
568
|
+
resolve(false);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
543
571
|
}
|
|
544
572
|
|
|
545
573
|
async function checkAllDependencies(): Promise<CheckResult[]> {
|
|
@@ -707,68 +735,173 @@ function buildAgentsSkillsSection(
|
|
|
707
735
|
].join(newline);
|
|
708
736
|
}
|
|
709
737
|
|
|
710
|
-
|
|
738
|
+
/**
|
|
739
|
+
* Build the unified Hivemind section (ADR-011).
|
|
740
|
+
* Replaces separate CASS and Semantic Memory sections.
|
|
741
|
+
*/
|
|
742
|
+
function buildAgentsHivemindSection(newline: string): string {
|
|
711
743
|
return [
|
|
712
|
-
"##
|
|
744
|
+
"## Hivemind - Unified Memory System",
|
|
745
|
+
"",
|
|
746
|
+
"The hive remembers everything. Learnings, sessions, patterns—all searchable.",
|
|
747
|
+
"",
|
|
748
|
+
"**Unified storage:** Manual learnings and AI agent session histories stored in the same database, searchable together. Powered by libSQL vectors + Ollama embeddings.",
|
|
713
749
|
"",
|
|
714
|
-
"
|
|
750
|
+
"**Indexed agents:** Claude Code, Codex, Cursor, Gemini, Aider, ChatGPT, Cline, OpenCode, Amp, Pi-Agent",
|
|
715
751
|
"",
|
|
716
752
|
"### When to Use",
|
|
717
753
|
"",
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
754
|
+
"- **BEFORE implementing** - check if you or any agent solved it before",
|
|
755
|
+
"- **After solving hard problems** - store learnings for future sessions",
|
|
756
|
+
"- **Debugging** - search past sessions for similar errors",
|
|
757
|
+
"- **Architecture decisions** - record reasoning, alternatives, tradeoffs",
|
|
758
|
+
"- **Project-specific patterns** - capture domain rules and gotchas",
|
|
759
|
+
"",
|
|
760
|
+
"### Tools",
|
|
761
|
+
"",
|
|
762
|
+
"| Tool | Purpose |",
|
|
763
|
+
"|------|---------|",
|
|
764
|
+
"| `hivemind_store` | Store a memory (learnings, decisions, patterns) |",
|
|
765
|
+
"| `hivemind_find` | Search all memories (learnings + sessions, semantic + FTS fallback) |",
|
|
766
|
+
"| `hivemind_get` | Get specific memory by ID |",
|
|
767
|
+
"| `hivemind_remove` | Delete outdated/incorrect memory |",
|
|
768
|
+
"| `hivemind_validate` | Confirm memory still accurate (resets 90-day decay timer) |",
|
|
769
|
+
"| `hivemind_stats` | Memory statistics and health check |",
|
|
770
|
+
"| `hivemind_index` | Index AI session directories |",
|
|
771
|
+
"| `hivemind_sync` | Sync to .hive/memories.jsonl (git-backed, team-shared) |",
|
|
721
772
|
"",
|
|
722
773
|
"### Usage",
|
|
723
774
|
"",
|
|
775
|
+
"**Store a learning** (include WHY, not just WHAT):",
|
|
776
|
+
"",
|
|
777
|
+
"```typescript",
|
|
778
|
+
"hivemind_store({",
|
|
779
|
+
' information: "OAuth refresh tokens need 5min buffer before expiry to avoid race conditions. Without buffer, token refresh can fail mid-request if expiry happens between check and use.",',
|
|
780
|
+
' tags: "auth,oauth,tokens,race-conditions"',
|
|
781
|
+
"})",
|
|
782
|
+
"```",
|
|
783
|
+
"",
|
|
784
|
+
"**Search all memories** (learnings + sessions):",
|
|
785
|
+
"",
|
|
786
|
+
"```typescript",
|
|
787
|
+
"// Search everything",
|
|
788
|
+
'hivemind_find({ query: "token refresh", limit: 5 })',
|
|
789
|
+
"",
|
|
790
|
+
"// Search only learnings (manual entries)",
|
|
791
|
+
'hivemind_find({ query: "authentication", collection: "default" })',
|
|
792
|
+
"",
|
|
793
|
+
"// Search only Claude sessions",
|
|
794
|
+
'hivemind_find({ query: "Next.js caching", collection: "claude" })',
|
|
795
|
+
"",
|
|
796
|
+
"// Search only Cursor sessions",
|
|
797
|
+
'hivemind_find({ query: "API design", collection: "cursor" })',
|
|
798
|
+
"```",
|
|
799
|
+
"",
|
|
800
|
+
"**Get specific memory**:",
|
|
801
|
+
"",
|
|
802
|
+
"```typescript",
|
|
803
|
+
'hivemind_get({ id: "mem_xyz123" })',
|
|
804
|
+
"```",
|
|
805
|
+
"",
|
|
806
|
+
"**Delete outdated memory**:",
|
|
807
|
+
"",
|
|
808
|
+
"```typescript",
|
|
809
|
+
'hivemind_remove({ id: "mem_old456" })',
|
|
810
|
+
"```",
|
|
811
|
+
"",
|
|
812
|
+
"**Validate memory is still accurate** (resets decay):",
|
|
813
|
+
"",
|
|
814
|
+
"```typescript",
|
|
815
|
+
"// Confirmed this memory is still relevant",
|
|
816
|
+
'hivemind_validate({ id: "mem_xyz123" })',
|
|
817
|
+
"```",
|
|
818
|
+
"",
|
|
819
|
+
"**Index new sessions**:",
|
|
820
|
+
"",
|
|
821
|
+
"```typescript",
|
|
822
|
+
"// Automatically indexes ~/.config/opencode/sessions, ~/.cursor-tutor, etc.",
|
|
823
|
+
"hivemind_index()",
|
|
824
|
+
"```",
|
|
825
|
+
"",
|
|
826
|
+
"**Sync to git**:",
|
|
827
|
+
"",
|
|
828
|
+
"```typescript",
|
|
829
|
+
"// Writes learnings to .hive/memories.jsonl for git sync",
|
|
830
|
+
"hivemind_sync()",
|
|
831
|
+
"```",
|
|
832
|
+
"",
|
|
833
|
+
"**Check stats**:",
|
|
834
|
+
"",
|
|
835
|
+
"```typescript",
|
|
836
|
+
"hivemind_stats()",
|
|
837
|
+
"```",
|
|
838
|
+
"",
|
|
839
|
+
"### Usage Pattern",
|
|
840
|
+
"",
|
|
724
841
|
"```bash",
|
|
725
|
-
"#
|
|
726
|
-
'
|
|
842
|
+
"# 1. Before starting work - query for relevant learnings",
|
|
843
|
+
'hivemind_find({ query: "<task keywords>", limit: 5 })',
|
|
727
844
|
"",
|
|
728
|
-
"#
|
|
729
|
-
'cass_search(query="useEffect cleanup", agent="claude", days=7)',
|
|
845
|
+
"# 2. Do the work...",
|
|
730
846
|
"",
|
|
731
|
-
"#
|
|
732
|
-
|
|
847
|
+
"# 3. After solving hard problem - store learning",
|
|
848
|
+
"hivemind_store({",
|
|
849
|
+
' information: "<what you learned, WHY it matters>",',
|
|
850
|
+
' tags: "<relevant,tags>"',
|
|
851
|
+
"})",
|
|
733
852
|
"",
|
|
734
|
-
"#
|
|
735
|
-
'
|
|
853
|
+
"# 4. Validate memories when you confirm they're still accurate",
|
|
854
|
+
'hivemind_validate({ id: "<memory-id>" })',
|
|
736
855
|
"```",
|
|
737
856
|
"",
|
|
738
|
-
"
|
|
739
|
-
].join(newline);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
function buildAgentsSemanticMemorySection(newline: string): string {
|
|
743
|
-
return [
|
|
744
|
-
"## Semantic Memory - Persistent Learning",
|
|
857
|
+
"### Integration with Workflow",
|
|
745
858
|
"",
|
|
746
|
-
"
|
|
859
|
+
"**At task start** (query BEFORE implementing):",
|
|
747
860
|
"",
|
|
748
|
-
"
|
|
861
|
+
"```bash",
|
|
862
|
+
"# Check if you or any agent solved similar problems",
|
|
863
|
+
'hivemind_find({ query: "OAuth token refresh buffer", limit: 5 })',
|
|
864
|
+
"```",
|
|
749
865
|
"",
|
|
750
|
-
"
|
|
751
|
-
"- After making architectural decisions - store the reasoning",
|
|
752
|
-
"- Before starting work - search for relevant past learnings",
|
|
753
|
-
"- When you discover project-specific patterns",
|
|
866
|
+
"**During debugging** (search past sessions):",
|
|
754
867
|
"",
|
|
755
|
-
"
|
|
868
|
+
"```bash",
|
|
869
|
+
"# Find similar errors from past sessions",
|
|
870
|
+
'hivemind_find({ query: "cannot read property of undefined", collection: "claude" })',
|
|
871
|
+
"```",
|
|
872
|
+
"",
|
|
873
|
+
"**After solving problems** (store learnings):",
|
|
756
874
|
"",
|
|
757
875
|
"```bash",
|
|
758
|
-
|
|
759
|
-
|
|
876
|
+
'# Store root cause + solution, not just "fixed it"',
|
|
877
|
+
"hivemind_store({",
|
|
878
|
+
' information: "Next.js searchParams causes dynamic rendering. Workaround: destructure in parent, pass as props to cached child.",',
|
|
879
|
+
' tags: "nextjs,cache-components,dynamic-rendering,searchparams"',
|
|
880
|
+
"})",
|
|
881
|
+
"```",
|
|
760
882
|
"",
|
|
761
|
-
"
|
|
762
|
-
'semantic-memory_find(query="token refresh", limit=5)',
|
|
883
|
+
"**Learning from other agents**:",
|
|
763
884
|
"",
|
|
764
|
-
"
|
|
765
|
-
|
|
885
|
+
"```bash",
|
|
886
|
+
"# See how Cursor handled similar feature",
|
|
887
|
+
'hivemind_find({ query: "implement authentication", collection: "cursor" })',
|
|
766
888
|
"```",
|
|
767
889
|
"",
|
|
768
|
-
"**Pro tip:**
|
|
890
|
+
"**Pro tip:** Query Hivemind at the START of complex tasks. Past solutions (yours or other agents') save time and prevent reinventing wheels.",
|
|
769
891
|
].join(newline);
|
|
770
892
|
}
|
|
771
893
|
|
|
894
|
+
// Legacy functions kept for backwards compatibility during migration
|
|
895
|
+
function buildAgentsCassSection(newline: string): string {
|
|
896
|
+
// Redirect to Hivemind section
|
|
897
|
+
return buildAgentsHivemindSection(newline);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function buildAgentsSemanticMemorySection(newline: string): string {
|
|
901
|
+
// Redirect to Hivemind section
|
|
902
|
+
return buildAgentsHivemindSection(newline);
|
|
903
|
+
}
|
|
904
|
+
|
|
772
905
|
function buildAgentsSwarmCoordinatorSection(newline: string): string {
|
|
773
906
|
return [
|
|
774
907
|
"## Swarm Coordinator Checklist (MANDATORY)",
|
|
@@ -935,6 +1068,53 @@ function updateAgentsMdContent({
|
|
|
935
1068
|
changes.push("Updated bundled skills list");
|
|
936
1069
|
}
|
|
937
1070
|
|
|
1071
|
+
// ADR-011: Migrate old tool names to hivemind
|
|
1072
|
+
const hasOldCassTools = /cass_search\(|cass_view\(|cass_expand\(/i.test(updated);
|
|
1073
|
+
const hasOldSemanticTools = /semantic-memory_store\(|semantic-memory_find\(/i.test(updated);
|
|
1074
|
+
const hasHivemindTools = /hivemind_store\(|hivemind_find\(/i.test(updated);
|
|
1075
|
+
|
|
1076
|
+
// If has old tools but not new hivemind tools, we need to update
|
|
1077
|
+
if ((hasOldCassTools || hasOldSemanticTools) && !hasHivemindTools) {
|
|
1078
|
+
// Replace old tool references with hivemind equivalents
|
|
1079
|
+
const beforeMigration = updated;
|
|
1080
|
+
|
|
1081
|
+
// Tool name replacements
|
|
1082
|
+
updated = updated.replace(/semantic-memory_store\(/g, "hivemind_store(");
|
|
1083
|
+
updated = updated.replace(/semantic-memory_find\(/g, "hivemind_find(");
|
|
1084
|
+
updated = updated.replace(/semantic-memory_get\(/g, "hivemind_get(");
|
|
1085
|
+
updated = updated.replace(/semantic-memory_remove\(/g, "hivemind_remove(");
|
|
1086
|
+
updated = updated.replace(/semantic-memory_validate\(/g, "hivemind_validate(");
|
|
1087
|
+
updated = updated.replace(/semantic-memory_list\(/g, "hivemind_find(");
|
|
1088
|
+
updated = updated.replace(/semantic-memory_stats\(/g, "hivemind_stats(");
|
|
1089
|
+
updated = updated.replace(/cass_search\(/g, "hivemind_find(");
|
|
1090
|
+
updated = updated.replace(/cass_view\(/g, "hivemind_get(");
|
|
1091
|
+
updated = updated.replace(/cass_expand\(/g, "hivemind_get(");
|
|
1092
|
+
updated = updated.replace(/cass_health\(/g, "hivemind_stats(");
|
|
1093
|
+
updated = updated.replace(/cass_index\(/g, "hivemind_index(");
|
|
1094
|
+
updated = updated.replace(/cass_stats\(/g, "hivemind_stats(");
|
|
1095
|
+
|
|
1096
|
+
// Table references (without parentheses)
|
|
1097
|
+
updated = updated.replace(/\| `semantic-memory_store` \|/g, "| `hivemind_store` |");
|
|
1098
|
+
updated = updated.replace(/\| `semantic-memory_find` \|/g, "| `hivemind_find` |");
|
|
1099
|
+
updated = updated.replace(/\| `semantic-memory_get` \|/g, "| `hivemind_get` |");
|
|
1100
|
+
updated = updated.replace(/\| `semantic-memory_remove` \|/g, "| `hivemind_remove` |");
|
|
1101
|
+
updated = updated.replace(/\| `semantic-memory_validate` \|/g, "| `hivemind_validate` |");
|
|
1102
|
+
updated = updated.replace(/\| `semantic-memory_list` \|/g, "| `hivemind_find` |");
|
|
1103
|
+
updated = updated.replace(/\| `semantic-memory_stats` \|/g, "| `hivemind_stats` |");
|
|
1104
|
+
updated = updated.replace(/\| `semantic-memory_migrate` \|/g, "| `hivemind_stats` |");
|
|
1105
|
+
updated = updated.replace(/\| `semantic-memory_check` \|/g, "| `hivemind_stats` |");
|
|
1106
|
+
updated = updated.replace(/\| `cass_search` \|/g, "| `hivemind_find` |");
|
|
1107
|
+
updated = updated.replace(/\| `cass_view` \|/g, "| `hivemind_get` |");
|
|
1108
|
+
updated = updated.replace(/\| `cass_expand` \|/g, "| `hivemind_get` |");
|
|
1109
|
+
updated = updated.replace(/\| `cass_health` \|/g, "| `hivemind_stats` |");
|
|
1110
|
+
updated = updated.replace(/\| `cass_index` \|/g, "| `hivemind_index` |");
|
|
1111
|
+
updated = updated.replace(/\| `cass_stats` \|/g, "| `hivemind_stats` |");
|
|
1112
|
+
|
|
1113
|
+
if (updated !== beforeMigration) {
|
|
1114
|
+
changes.push("Migrated cass_*/semantic-memory_* to hivemind_* (ADR-011)");
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
|
|
938
1118
|
// Update tool preferences block if present
|
|
939
1119
|
const toolPrefsResult = updateAgentsToolPreferencesBlock(updated, newline);
|
|
940
1120
|
if (toolPrefsResult.changed) {
|
|
@@ -942,14 +1122,11 @@ function updateAgentsMdContent({
|
|
|
942
1122
|
changes.push("Updated tool_preferences tool list");
|
|
943
1123
|
}
|
|
944
1124
|
|
|
945
|
-
//
|
|
1125
|
+
// Check for sections - now unified under Hivemind
|
|
946
1126
|
const hasSkillsSection =
|
|
947
1127
|
/^#{1,6}\s+Skills\b/im.test(updated) || /skills_list\(\)/.test(updated);
|
|
948
|
-
const
|
|
949
|
-
/^#{1,6}\s
|
|
950
|
-
const hasSemanticMemorySection =
|
|
951
|
-
/^#{1,6}\s+Semantic Memory\b/im.test(updated) ||
|
|
952
|
-
/semantic-memory_store\(/.test(updated);
|
|
1128
|
+
const hasHivemindSection =
|
|
1129
|
+
/^#{1,6}\s+Hivemind\b/im.test(updated) || /hivemind_store\(/.test(updated);
|
|
953
1130
|
const hasSwarmCoordinatorSection =
|
|
954
1131
|
/^#{1,6}\s+Swarm Coordinator\b/im.test(updated) ||
|
|
955
1132
|
/swarm_review\(/.test(updated) ||
|
|
@@ -962,13 +1139,9 @@ function updateAgentsMdContent({
|
|
|
962
1139
|
);
|
|
963
1140
|
changes.push("Added Skills section");
|
|
964
1141
|
}
|
|
965
|
-
if (!
|
|
966
|
-
sectionsToAppend.push(
|
|
967
|
-
changes.push("Added
|
|
968
|
-
}
|
|
969
|
-
if (!hasSemanticMemorySection) {
|
|
970
|
-
sectionsToAppend.push(buildAgentsSemanticMemorySection(newline));
|
|
971
|
-
changes.push("Added Semantic Memory section");
|
|
1142
|
+
if (!hasHivemindSection) {
|
|
1143
|
+
sectionsToAppend.push(buildAgentsHivemindSection(newline));
|
|
1144
|
+
changes.push("Added Hivemind section (unified memory)");
|
|
972
1145
|
}
|
|
973
1146
|
if (!hasSwarmCoordinatorSection) {
|
|
974
1147
|
sectionsToAppend.push(buildAgentsSwarmCoordinatorSection(newline));
|
|
@@ -1434,15 +1607,33 @@ function getFixCommand(dep: Dependency): string | null {
|
|
|
1434
1607
|
}
|
|
1435
1608
|
}
|
|
1436
1609
|
|
|
1437
|
-
async function doctor() {
|
|
1610
|
+
async function doctor(debug = false) {
|
|
1438
1611
|
p.intro("swarm doctor v" + VERSION);
|
|
1439
1612
|
|
|
1613
|
+
if (debug) {
|
|
1614
|
+
p.log.step("Debug info:");
|
|
1615
|
+
p.log.message(dim(` Runtime: ${typeof Bun !== 'undefined' ? 'Bun' : 'Node.js'}`));
|
|
1616
|
+
p.log.message(dim(` Node version: ${process.version}`));
|
|
1617
|
+
p.log.message(dim(` Platform: ${process.platform}`));
|
|
1618
|
+
p.log.message(dim(` Arch: ${process.arch}`));
|
|
1619
|
+
p.log.message(dim(` CWD: ${process.cwd()}`));
|
|
1620
|
+
p.log.message(dim(` PATH entries: ${(process.env.PATH || '').split(':').length}`));
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1440
1623
|
const s = p.spinner();
|
|
1441
1624
|
s.start("Checking dependencies...");
|
|
1442
1625
|
|
|
1443
1626
|
const results = await checkAllDependencies();
|
|
1444
1627
|
|
|
1445
1628
|
s.stop("Dependencies checked");
|
|
1629
|
+
|
|
1630
|
+
if (debug) {
|
|
1631
|
+
p.log.step("Dependency check details:");
|
|
1632
|
+
for (const { dep, available, version } of results) {
|
|
1633
|
+
const status = available ? green("✓") : red("✗");
|
|
1634
|
+
p.log.message(dim(` ${status} ${dep.command} ${dep.checkArgs.join(" ")} → ${available ? `v${version || "unknown"}` : "not found"}`));
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1446
1637
|
|
|
1447
1638
|
const required = results.filter((r) => r.dep.required);
|
|
1448
1639
|
const optional = results.filter((r) => !r.dep.required);
|
|
@@ -1571,6 +1762,23 @@ async function setup(forceReinstall = false, nonInteractive = false) {
|
|
|
1571
1762
|
|
|
1572
1763
|
p.intro("opencode-swarm-plugin v" + VERSION);
|
|
1573
1764
|
|
|
1765
|
+
// CRITICAL: Check for Bun first - the CLI requires Bun runtime
|
|
1766
|
+
const bunCheck = await checkCommand("bun", ["--version"]);
|
|
1767
|
+
if (!bunCheck.available) {
|
|
1768
|
+
p.log.error("Bun is required but not installed!");
|
|
1769
|
+
console.log();
|
|
1770
|
+
console.log(dim(" The swarm CLI requires Bun runtime for Bun-specific APIs."));
|
|
1771
|
+
console.log();
|
|
1772
|
+
console.log(" Install Bun:");
|
|
1773
|
+
console.log(cyan(" curl -fsSL https://bun.sh/install | bash"));
|
|
1774
|
+
console.log();
|
|
1775
|
+
console.log(dim(" Or via Homebrew:"));
|
|
1776
|
+
console.log(cyan(" brew install oven-sh/bun/bun"));
|
|
1777
|
+
console.log();
|
|
1778
|
+
process.exit(1);
|
|
1779
|
+
}
|
|
1780
|
+
p.log.success(`Bun v${bunCheck.version} detected`);
|
|
1781
|
+
|
|
1574
1782
|
// Migrate legacy database if present (do this first, before config check)
|
|
1575
1783
|
const cwd = process.cwd();
|
|
1576
1784
|
const tempDirName = getLibSQLProjectTempDirName(cwd);
|
|
@@ -3008,6 +3216,7 @@ ${cyan("Commands:")}
|
|
|
3008
3216
|
swarm viz Alias for 'swarm serve' (deprecated, use serve)
|
|
3009
3217
|
--port <n> Port to listen on (default: 4483)
|
|
3010
3218
|
swarm cells List or get cells from database (replaces 'swarm tool hive_query')
|
|
3219
|
+
swarm memory Manage unified memory system (learnings + sessions)
|
|
3011
3220
|
swarm log View swarm logs with filtering
|
|
3012
3221
|
swarm stats Show swarm health metrics powered by swarm-insights (strategy success rates, patterns)
|
|
3013
3222
|
swarm o11y Show observability health - hook coverage, event capture, session quality
|
|
@@ -3035,6 +3244,17 @@ ${cyan("Cell Management:")}
|
|
|
3035
3244
|
swarm cells --ready Show next ready (unblocked) cell
|
|
3036
3245
|
swarm cells --json Raw JSON output (array, no wrapper)
|
|
3037
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
|
+
|
|
3038
3258
|
${cyan("Log Viewing:")}
|
|
3039
3259
|
swarm log Tail recent logs (last 50 lines)
|
|
3040
3260
|
swarm log <module> Filter by module (e.g., compaction)
|
|
@@ -3257,7 +3477,7 @@ async function listTools() {
|
|
|
3257
3477
|
// Agents Command - Update AGENTS.md with skill awareness
|
|
3258
3478
|
// ============================================================================
|
|
3259
3479
|
|
|
3260
|
-
async function agents() {
|
|
3480
|
+
async function agents(nonInteractive = false) {
|
|
3261
3481
|
const home = process.env.HOME || process.env.USERPROFILE || "~";
|
|
3262
3482
|
const agentsPath = join(home, ".config", "opencode", "AGENTS.md");
|
|
3263
3483
|
|
|
@@ -3273,44 +3493,70 @@ async function agents() {
|
|
|
3273
3493
|
return;
|
|
3274
3494
|
}
|
|
3275
3495
|
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3496
|
+
if (!nonInteractive) {
|
|
3497
|
+
const result = await p.confirm({
|
|
3498
|
+
message: "Update AGENTS.md with Hivemind unification?",
|
|
3499
|
+
initialValue: true,
|
|
3500
|
+
});
|
|
3280
3501
|
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3502
|
+
if (p.isCancel(result) || !result) {
|
|
3503
|
+
p.outro("Aborted");
|
|
3504
|
+
return;
|
|
3505
|
+
}
|
|
3284
3506
|
}
|
|
3285
3507
|
|
|
3286
3508
|
const s = p.spinner();
|
|
3287
|
-
s.start("Updating AGENTS.md
|
|
3509
|
+
s.start("Updating AGENTS.md via LLM...");
|
|
3288
3510
|
|
|
3289
|
-
const
|
|
3290
|
-
|
|
3511
|
+
const prompt = `You are updating ~/.config/opencode/AGENTS.md to unify memory tools under Hivemind (ADR-011).
|
|
3512
|
+
|
|
3513
|
+
TASK: Update the AGENTS.md file to:
|
|
3514
|
+
|
|
3515
|
+
1. **Rename tool references** throughout the file:
|
|
3516
|
+
- \`cass_search\` → \`hivemind_find\`
|
|
3517
|
+
- \`cass_view\` → \`hivemind_get\`
|
|
3518
|
+
- \`cass_expand\` → \`hivemind_get\`
|
|
3519
|
+
- \`cass_health\` → \`hivemind_stats\`
|
|
3520
|
+
- \`cass_index\` → \`hivemind_index\`
|
|
3521
|
+
- \`cass_stats\` → \`hivemind_stats\`
|
|
3522
|
+
- \`semantic-memory_store\` → \`hivemind_store\`
|
|
3523
|
+
- \`semantic-memory_find\` → \`hivemind_find\`
|
|
3524
|
+
- \`semantic-memory_get\` → \`hivemind_get\`
|
|
3525
|
+
- \`semantic-memory_remove\` → \`hivemind_remove\`
|
|
3526
|
+
- \`semantic-memory_validate\` → \`hivemind_validate\`
|
|
3527
|
+
- \`semantic-memory_list\` → \`hivemind_find\`
|
|
3528
|
+
- \`semantic-memory_stats\` → \`hivemind_stats\`
|
|
3529
|
+
|
|
3530
|
+
2. **Consolidate sections**: If there are separate "CASS" and "Semantic Memory" sections, merge them into a single "Hivemind - Unified Memory System" section that covers:
|
|
3531
|
+
- Unified storage (learnings + sessions in same DB)
|
|
3532
|
+
- All hivemind_* tools with descriptions
|
|
3533
|
+
- Usage examples showing both storing learnings and searching sessions
|
|
3534
|
+
- The 90-day decay and validation workflow
|
|
3535
|
+
|
|
3536
|
+
3. **Update any prose** that mentions "CASS" or "semantic memory" separately to use "Hivemind" terminology.
|
|
3537
|
+
|
|
3538
|
+
4. **Keep existing structure** - don't reorganize unrelated sections.
|
|
3539
|
+
|
|
3540
|
+
Read the file, make the updates, and save it. Create a backup first.`;
|
|
3291
3541
|
|
|
3292
3542
|
try {
|
|
3293
|
-
const
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
const
|
|
3299
|
-
|
|
3300
|
-
if (
|
|
3301
|
-
s.stop("AGENTS.md updated
|
|
3302
|
-
p.log.success("
|
|
3303
|
-
p.log.message(
|
|
3304
|
-
dim("Skills available: skills_list, skills_use, skills_read"),
|
|
3305
|
-
);
|
|
3306
|
-
if (result.backupPath) {
|
|
3307
|
-
p.log.message(dim("Backup: " + result.backupPath));
|
|
3308
|
-
}
|
|
3543
|
+
const proc = Bun.spawn(["opencode", "run", prompt], {
|
|
3544
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
3545
|
+
cwd: home,
|
|
3546
|
+
});
|
|
3547
|
+
|
|
3548
|
+
const exitCode = await proc.exited;
|
|
3549
|
+
|
|
3550
|
+
if (exitCode === 0) {
|
|
3551
|
+
s.stop("AGENTS.md updated via LLM");
|
|
3552
|
+
p.log.success("Hivemind unification complete");
|
|
3309
3553
|
} else {
|
|
3310
|
-
|
|
3554
|
+
const stderr = await new Response(proc.stderr).text();
|
|
3555
|
+
s.stop("LLM update failed");
|
|
3556
|
+
p.log.error(stderr || `Exit code: ${exitCode}`);
|
|
3311
3557
|
}
|
|
3312
3558
|
} catch (error) {
|
|
3313
|
-
s.stop("Failed to
|
|
3559
|
+
s.stop("Failed to run opencode");
|
|
3314
3560
|
p.log.error(String(error));
|
|
3315
3561
|
}
|
|
3316
3562
|
|
|
@@ -5269,6 +5515,319 @@ async function capture() {
|
|
|
5269
5515
|
}
|
|
5270
5516
|
}
|
|
5271
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
|
+
|
|
5272
5831
|
// ============================================================================
|
|
5273
5832
|
// Main
|
|
5274
5833
|
// ============================================================================
|
|
@@ -5282,9 +5841,11 @@ switch (command) {
|
|
|
5282
5841
|
await setup(reinstallFlag || yesFlag, yesFlag);
|
|
5283
5842
|
break;
|
|
5284
5843
|
}
|
|
5285
|
-
case "doctor":
|
|
5286
|
-
|
|
5844
|
+
case "doctor": {
|
|
5845
|
+
const debugFlag = process.argv.includes("--debug") || process.argv.includes("-d");
|
|
5846
|
+
await doctor(debugFlag);
|
|
5287
5847
|
break;
|
|
5848
|
+
}
|
|
5288
5849
|
case "init":
|
|
5289
5850
|
await init();
|
|
5290
5851
|
break;
|
|
@@ -5313,9 +5874,11 @@ switch (command) {
|
|
|
5313
5874
|
}
|
|
5314
5875
|
break;
|
|
5315
5876
|
}
|
|
5316
|
-
case "agents":
|
|
5317
|
-
|
|
5877
|
+
case "agents": {
|
|
5878
|
+
const agentsNonInteractive = process.argv.includes("--yes") || process.argv.includes("-y");
|
|
5879
|
+
await agents(agentsNonInteractive);
|
|
5318
5880
|
break;
|
|
5881
|
+
}
|
|
5319
5882
|
case "migrate":
|
|
5320
5883
|
await migrate();
|
|
5321
5884
|
break;
|
|
@@ -5344,6 +5907,9 @@ switch (command) {
|
|
|
5344
5907
|
case "capture":
|
|
5345
5908
|
await capture();
|
|
5346
5909
|
break;
|
|
5910
|
+
case "memory":
|
|
5911
|
+
await memory();
|
|
5912
|
+
break;
|
|
5347
5913
|
case "query":
|
|
5348
5914
|
await query();
|
|
5349
5915
|
break;
|