opencode-swarm-plugin 0.46.0 → 0.47.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 +346 -108
- package/dist/bin/swarm.js +1439 -590
- 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",
|
|
713
745
|
"",
|
|
714
|
-
"
|
|
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.",
|
|
749
|
+
"",
|
|
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);
|
|
@@ -3257,7 +3465,7 @@ async function listTools() {
|
|
|
3257
3465
|
// Agents Command - Update AGENTS.md with skill awareness
|
|
3258
3466
|
// ============================================================================
|
|
3259
3467
|
|
|
3260
|
-
async function agents() {
|
|
3468
|
+
async function agents(nonInteractive = false) {
|
|
3261
3469
|
const home = process.env.HOME || process.env.USERPROFILE || "~";
|
|
3262
3470
|
const agentsPath = join(home, ".config", "opencode", "AGENTS.md");
|
|
3263
3471
|
|
|
@@ -3273,44 +3481,70 @@ async function agents() {
|
|
|
3273
3481
|
return;
|
|
3274
3482
|
}
|
|
3275
3483
|
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3484
|
+
if (!nonInteractive) {
|
|
3485
|
+
const result = await p.confirm({
|
|
3486
|
+
message: "Update AGENTS.md with Hivemind unification?",
|
|
3487
|
+
initialValue: true,
|
|
3488
|
+
});
|
|
3280
3489
|
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3490
|
+
if (p.isCancel(result) || !result) {
|
|
3491
|
+
p.outro("Aborted");
|
|
3492
|
+
return;
|
|
3493
|
+
}
|
|
3284
3494
|
}
|
|
3285
3495
|
|
|
3286
3496
|
const s = p.spinner();
|
|
3287
|
-
s.start("Updating AGENTS.md
|
|
3497
|
+
s.start("Updating AGENTS.md via LLM...");
|
|
3288
3498
|
|
|
3289
|
-
const
|
|
3290
|
-
|
|
3499
|
+
const prompt = `You are updating ~/.config/opencode/AGENTS.md to unify memory tools under Hivemind (ADR-011).
|
|
3500
|
+
|
|
3501
|
+
TASK: Update the AGENTS.md file to:
|
|
3502
|
+
|
|
3503
|
+
1. **Rename tool references** throughout the file:
|
|
3504
|
+
- \`cass_search\` → \`hivemind_find\`
|
|
3505
|
+
- \`cass_view\` → \`hivemind_get\`
|
|
3506
|
+
- \`cass_expand\` → \`hivemind_get\`
|
|
3507
|
+
- \`cass_health\` → \`hivemind_stats\`
|
|
3508
|
+
- \`cass_index\` → \`hivemind_index\`
|
|
3509
|
+
- \`cass_stats\` → \`hivemind_stats\`
|
|
3510
|
+
- \`semantic-memory_store\` → \`hivemind_store\`
|
|
3511
|
+
- \`semantic-memory_find\` → \`hivemind_find\`
|
|
3512
|
+
- \`semantic-memory_get\` → \`hivemind_get\`
|
|
3513
|
+
- \`semantic-memory_remove\` → \`hivemind_remove\`
|
|
3514
|
+
- \`semantic-memory_validate\` → \`hivemind_validate\`
|
|
3515
|
+
- \`semantic-memory_list\` → \`hivemind_find\`
|
|
3516
|
+
- \`semantic-memory_stats\` → \`hivemind_stats\`
|
|
3517
|
+
|
|
3518
|
+
2. **Consolidate sections**: If there are separate "CASS" and "Semantic Memory" sections, merge them into a single "Hivemind - Unified Memory System" section that covers:
|
|
3519
|
+
- Unified storage (learnings + sessions in same DB)
|
|
3520
|
+
- All hivemind_* tools with descriptions
|
|
3521
|
+
- Usage examples showing both storing learnings and searching sessions
|
|
3522
|
+
- The 90-day decay and validation workflow
|
|
3523
|
+
|
|
3524
|
+
3. **Update any prose** that mentions "CASS" or "semantic memory" separately to use "Hivemind" terminology.
|
|
3525
|
+
|
|
3526
|
+
4. **Keep existing structure** - don't reorganize unrelated sections.
|
|
3527
|
+
|
|
3528
|
+
Read the file, make the updates, and save it. Create a backup first.`;
|
|
3291
3529
|
|
|
3292
3530
|
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
|
-
}
|
|
3531
|
+
const proc = Bun.spawn(["opencode", "run", prompt], {
|
|
3532
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
3533
|
+
cwd: home,
|
|
3534
|
+
});
|
|
3535
|
+
|
|
3536
|
+
const exitCode = await proc.exited;
|
|
3537
|
+
|
|
3538
|
+
if (exitCode === 0) {
|
|
3539
|
+
s.stop("AGENTS.md updated via LLM");
|
|
3540
|
+
p.log.success("Hivemind unification complete");
|
|
3309
3541
|
} else {
|
|
3310
|
-
|
|
3542
|
+
const stderr = await new Response(proc.stderr).text();
|
|
3543
|
+
s.stop("LLM update failed");
|
|
3544
|
+
p.log.error(stderr || `Exit code: ${exitCode}`);
|
|
3311
3545
|
}
|
|
3312
3546
|
} catch (error) {
|
|
3313
|
-
s.stop("Failed to
|
|
3547
|
+
s.stop("Failed to run opencode");
|
|
3314
3548
|
p.log.error(String(error));
|
|
3315
3549
|
}
|
|
3316
3550
|
|
|
@@ -5282,9 +5516,11 @@ switch (command) {
|
|
|
5282
5516
|
await setup(reinstallFlag || yesFlag, yesFlag);
|
|
5283
5517
|
break;
|
|
5284
5518
|
}
|
|
5285
|
-
case "doctor":
|
|
5286
|
-
|
|
5519
|
+
case "doctor": {
|
|
5520
|
+
const debugFlag = process.argv.includes("--debug") || process.argv.includes("-d");
|
|
5521
|
+
await doctor(debugFlag);
|
|
5287
5522
|
break;
|
|
5523
|
+
}
|
|
5288
5524
|
case "init":
|
|
5289
5525
|
await init();
|
|
5290
5526
|
break;
|
|
@@ -5313,9 +5549,11 @@ switch (command) {
|
|
|
5313
5549
|
}
|
|
5314
5550
|
break;
|
|
5315
5551
|
}
|
|
5316
|
-
case "agents":
|
|
5317
|
-
|
|
5552
|
+
case "agents": {
|
|
5553
|
+
const agentsNonInteractive = process.argv.includes("--yes") || process.argv.includes("-y");
|
|
5554
|
+
await agents(agentsNonInteractive);
|
|
5318
5555
|
break;
|
|
5556
|
+
}
|
|
5319
5557
|
case "migrate":
|
|
5320
5558
|
await migrate();
|
|
5321
5559
|
break;
|