opencode-swarm-plugin 0.6.3 → 0.10.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/scripts/setup.ts DELETED
@@ -1,371 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * OpenCode Swarm Plugin - Setup Script
4
- *
5
- * Checks for required dependencies and installs them if missing.
6
- * Mac-specific (uses Homebrew).
7
- *
8
- * Usage:
9
- * bunx opencode-swarm-plugin/scripts/setup.ts
10
- * # or after cloning:
11
- * bun scripts/setup.ts
12
- */
13
-
14
- import { $ } from "bun";
15
- import { existsSync, mkdirSync, copyFileSync } from "fs";
16
- import { homedir } from "os";
17
- import { join } from "path";
18
-
19
- // ANSI colors
20
- const green = (s: string) => `\x1b[32m${s}\x1b[0m`;
21
- const red = (s: string) => `\x1b[31m${s}\x1b[0m`;
22
- const yellow = (s: string) => `\x1b[33m${s}\x1b[0m`;
23
- const blue = (s: string) => `\x1b[34m${s}\x1b[0m`;
24
- const dim = (s: string) => `\x1b[2m${s}\x1b[0m`;
25
-
26
- const CHECK = green("✓");
27
- const CROSS = red("✗");
28
- const WARN = yellow("⚠");
29
- const INFO = blue("→");
30
-
31
- interface Dependency {
32
- name: string;
33
- check: () => Promise<boolean>;
34
- install: () => Promise<void>;
35
- optional?: boolean;
36
- purpose: string;
37
- }
38
-
39
- /**
40
- * Check if a command exists
41
- */
42
- async function commandExists(cmd: string): Promise<boolean> {
43
- try {
44
- const result = await $`which ${cmd}`.quiet().nothrow();
45
- return result.exitCode === 0;
46
- } catch {
47
- return false;
48
- }
49
- }
50
-
51
- /**
52
- * Check if a URL is reachable
53
- */
54
- async function urlReachable(url: string): Promise<boolean> {
55
- try {
56
- const response = await fetch(url, { method: "HEAD" });
57
- return response.ok;
58
- } catch {
59
- return false;
60
- }
61
- }
62
-
63
- /**
64
- * Run a shell command with output
65
- */
66
- async function run(cmd: string, args: string[] = []): Promise<boolean> {
67
- try {
68
- const proc = Bun.spawn([cmd, ...args], {
69
- stdout: "inherit",
70
- stderr: "inherit",
71
- });
72
- const exitCode = await proc.exited;
73
- return exitCode === 0;
74
- } catch {
75
- return false;
76
- }
77
- }
78
-
79
- const dependencies: Dependency[] = [
80
- {
81
- name: "Homebrew",
82
- purpose: "Package manager for installing other dependencies",
83
- check: async () => commandExists("brew"),
84
- install: async () => {
85
- console.log(`${INFO} Installing Homebrew...`);
86
- const script = await fetch(
87
- "https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh",
88
- ).then((r) => r.text());
89
- await $`/bin/bash -c ${script}`;
90
- },
91
- },
92
- {
93
- name: "OpenCode",
94
- purpose: "AI coding assistant (plugin host)",
95
- check: async () => commandExists("opencode"),
96
- install: async () => {
97
- console.log(`${INFO} Installing OpenCode...`);
98
- await run("brew", ["install", "sst/tap/opencode"]);
99
- },
100
- },
101
- {
102
- name: "Beads CLI (bd)",
103
- purpose: "Git-backed issue tracking",
104
- check: async () => commandExists("bd"),
105
- install: async () => {
106
- console.log(`${INFO} Installing Beads...`);
107
- // Try npm global install first
108
- const npmResult = await $`npm install -g @joelhooks/beads`
109
- .quiet()
110
- .nothrow();
111
- if (npmResult.exitCode !== 0) {
112
- console.log(`${WARN} npm install failed, trying go install...`);
113
- await run("go", [
114
- "install",
115
- "github.com/joelhooks/beads/cmd/bd@latest",
116
- ]);
117
- }
118
- },
119
- },
120
- {
121
- name: "Agent Mail MCP",
122
- purpose: "Multi-agent coordination server",
123
- check: async () => {
124
- // Check if server is running
125
- const running = await urlReachable(
126
- "http://127.0.0.1:8765/health/liveness",
127
- );
128
- if (running) return true;
129
- // Check if binary exists
130
- return commandExists("agent-mail");
131
- },
132
- install: async () => {
133
- console.log(`${INFO} Installing Agent Mail...`);
134
- console.log(dim(" Agent Mail requires manual setup:"));
135
- console.log(
136
- dim(" 1. Clone: git clone https://github.com/joelhooks/agent-mail"),
137
- );
138
- console.log(
139
- dim(" 2. Build: cd agent-mail && go build -o agent-mail ./cmd/server"),
140
- );
141
- console.log(dim(" 3. Run: ./agent-mail serve"));
142
- console.log();
143
- console.log(
144
- `${WARN} Skipping automatic install - see instructions above`,
145
- );
146
- },
147
- optional: true,
148
- },
149
- {
150
- name: "Redis",
151
- purpose: "Rate limiting (optional, falls back to SQLite)",
152
- check: async () => {
153
- // Check if redis-server is running or installed
154
- const running = await $`redis-cli ping`.quiet().nothrow();
155
- if (running.exitCode === 0) return true;
156
- return commandExists("redis-server");
157
- },
158
- install: async () => {
159
- console.log(`${INFO} Installing Redis...`);
160
- await run("brew", ["install", "redis"]);
161
- console.log(dim(" Start with: brew services start redis"));
162
- },
163
- optional: true,
164
- },
165
- {
166
- name: "CASS (cass-memory)",
167
- purpose: "Cross-agent session search for historical context",
168
- check: async () => commandExists("cass"),
169
- install: async () => {
170
- console.log(`${INFO} CASS installation...`);
171
- console.log(
172
- dim(" Install from: https://github.com/Dicklesworthstone/cass"),
173
- );
174
- console.log(`${WARN} Skipping automatic install - see link above`);
175
- },
176
- optional: true,
177
- },
178
- {
179
- name: "UBS (bug scanner)",
180
- purpose: "Pre-completion bug scanning",
181
- check: async () => commandExists("ubs"),
182
- install: async () => {
183
- console.log(`${INFO} UBS installation...`);
184
- console.log(dim(" UBS is bundled with OpenCode plugins"));
185
- console.log(
186
- `${WARN} Skipping - should be available if OpenCode is installed`,
187
- );
188
- },
189
- optional: true,
190
- },
191
- ];
192
-
193
- /**
194
- * Setup OpenCode directories and copy plugin
195
- */
196
- async function setupOpenCodeDirs(): Promise<void> {
197
- const configDir = join(homedir(), ".config", "opencode");
198
- const pluginsDir = join(configDir, "plugins");
199
- const commandsDir = join(configDir, "commands");
200
- const agentsDir = join(configDir, "agents");
201
-
202
- // Create directories
203
- for (const dir of [pluginsDir, commandsDir, agentsDir]) {
204
- if (!existsSync(dir)) {
205
- mkdirSync(dir, { recursive: true });
206
- console.log(`${CHECK} Created ${dir}`);
207
- }
208
- }
209
-
210
- // Find plugin files (either in node_modules or local)
211
- const possiblePaths = [
212
- join(process.cwd(), "dist", "plugin.js"),
213
- join(
214
- process.cwd(),
215
- "node_modules",
216
- "opencode-swarm-plugin",
217
- "dist",
218
- "plugin.js",
219
- ),
220
- ];
221
-
222
- let pluginSrc: string | null = null;
223
- for (const p of possiblePaths) {
224
- if (existsSync(p)) {
225
- pluginSrc = p;
226
- break;
227
- }
228
- }
229
-
230
- if (pluginSrc) {
231
- const pluginDest = join(pluginsDir, "swarm.js");
232
- copyFileSync(pluginSrc, pluginDest);
233
- console.log(`${CHECK} Copied plugin to ${pluginDest}`);
234
- } else {
235
- console.log(
236
- `${WARN} Plugin not found - run 'pnpm build' first or install from npm`,
237
- );
238
- }
239
-
240
- // Copy example files if they exist
241
- const examplesDir = join(process.cwd(), "examples");
242
- const nodeModulesExamples = join(
243
- process.cwd(),
244
- "node_modules",
245
- "opencode-swarm-plugin",
246
- "examples",
247
- );
248
-
249
- const examplesSrc = existsSync(examplesDir)
250
- ? examplesDir
251
- : nodeModulesExamples;
252
-
253
- if (existsSync(examplesSrc)) {
254
- const swarmCmd = join(examplesSrc, "commands", "swarm.md");
255
- const plannerAgent = join(examplesSrc, "agents", "swarm-planner.md");
256
-
257
- if (existsSync(swarmCmd)) {
258
- copyFileSync(swarmCmd, join(commandsDir, "swarm.md"));
259
- console.log(`${CHECK} Copied /swarm command`);
260
- }
261
-
262
- if (existsSync(plannerAgent)) {
263
- copyFileSync(plannerAgent, join(agentsDir, "swarm-planner.md"));
264
- console.log(`${CHECK} Copied @swarm-planner agent`);
265
- }
266
- }
267
- }
268
-
269
- /**
270
- * Main setup function
271
- */
272
- async function main() {
273
- console.log();
274
- console.log(
275
- blue("═══════════════════════════════════════════════════════════"),
276
- );
277
- console.log(blue(" OpenCode Swarm Plugin - Setup"));
278
- console.log(
279
- blue("═══════════════════════════════════════════════════════════"),
280
- );
281
- console.log();
282
-
283
- // Check platform
284
- if (process.platform !== "darwin") {
285
- console.log(
286
- `${WARN} This script is optimized for macOS. Some installs may not work.`,
287
- );
288
- console.log();
289
- }
290
-
291
- // Check dependencies
292
- console.log(blue("Checking dependencies...\n"));
293
-
294
- const missing: Dependency[] = [];
295
- const optionalMissing: Dependency[] = [];
296
-
297
- for (const dep of dependencies) {
298
- const installed = await dep.check();
299
- const status = installed ? CHECK : dep.optional ? WARN : CROSS;
300
- const suffix = dep.optional ? dim(" (optional)") : "";
301
-
302
- console.log(`${status} ${dep.name}${suffix}`);
303
- console.log(dim(` ${dep.purpose}`));
304
-
305
- if (!installed) {
306
- if (dep.optional) {
307
- optionalMissing.push(dep);
308
- } else {
309
- missing.push(dep);
310
- }
311
- }
312
- }
313
-
314
- console.log();
315
-
316
- // Install missing required dependencies
317
- if (missing.length > 0) {
318
- console.log(blue("Installing missing required dependencies...\n"));
319
-
320
- for (const dep of missing) {
321
- try {
322
- await dep.install();
323
- const nowInstalled = await dep.check();
324
- if (nowInstalled) {
325
- console.log(`${CHECK} ${dep.name} installed successfully\n`);
326
- } else {
327
- console.log(`${CROSS} ${dep.name} installation may have failed\n`);
328
- }
329
- } catch (error) {
330
- console.log(`${CROSS} Failed to install ${dep.name}: ${error}\n`);
331
- }
332
- }
333
- }
334
-
335
- // Offer to install optional dependencies
336
- if (optionalMissing.length > 0) {
337
- console.log(yellow("Optional dependencies not installed:"));
338
- for (const dep of optionalMissing) {
339
- console.log(` - ${dep.name}: ${dep.purpose}`);
340
- }
341
- console.log();
342
- console.log(
343
- dim("The plugin will work without these, with degraded features."),
344
- );
345
- console.log();
346
- }
347
-
348
- // Setup OpenCode directories
349
- console.log(blue("Setting up OpenCode directories...\n"));
350
- await setupOpenCodeDirs();
351
-
352
- console.log();
353
- console.log(
354
- blue("═══════════════════════════════════════════════════════════"),
355
- );
356
- console.log(blue(" Setup Complete!"));
357
- console.log(
358
- blue("═══════════════════════════════════════════════════════════"),
359
- );
360
- console.log();
361
- console.log("Next steps:");
362
- console.log(
363
- ` 1. ${dim("Start Agent Mail (if using multi-agent):")} agent-mail serve`,
364
- );
365
- console.log(` 2. ${dim("Initialize beads in your project:")} bd init`);
366
- console.log(` 3. ${dim("Start OpenCode:")} opencode`);
367
- console.log(` 4. ${dim("Try the swarm command:")} /swarm "your task here"`);
368
- console.log();
369
- }
370
-
371
- main().catch(console.error);