opencode-swarm-plugin 0.1.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/.beads/.local_version +1 -0
- package/.beads/README.md +81 -0
- package/.beads/config.yaml +62 -0
- package/.beads/issues.jsonl +549 -0
- package/.beads/metadata.json +4 -0
- package/.gitattributes +3 -0
- package/Dockerfile +30 -0
- package/README.md +312 -0
- package/bun.lock +212 -0
- package/dist/index.js +14627 -0
- package/dist/plugin.js +14562 -0
- package/docker/agent-mail/Dockerfile +23 -0
- package/docker/agent-mail/__pycache__/server.cpython-314.pyc +0 -0
- package/docker/agent-mail/requirements.txt +3 -0
- package/docker/agent-mail/server.py +879 -0
- package/docker-compose.yml +45 -0
- package/package.json +52 -0
- package/scripts/docker-entrypoint.sh +54 -0
- package/src/agent-mail.integration.test.ts +1321 -0
- package/src/agent-mail.ts +665 -0
- package/src/anti-patterns.ts +430 -0
- package/src/beads.integration.test.ts +688 -0
- package/src/beads.ts +603 -0
- package/src/index.ts +267 -0
- package/src/learning.integration.test.ts +1104 -0
- package/src/learning.ts +438 -0
- package/src/pattern-maturity.ts +487 -0
- package/src/plugin.ts +11 -0
- package/src/schemas/bead.ts +152 -0
- package/src/schemas/evaluation.ts +133 -0
- package/src/schemas/index.test.ts +199 -0
- package/src/schemas/index.ts +77 -0
- package/src/schemas/task.ts +129 -0
- package/src/structured.ts +708 -0
- package/src/swarm.integration.test.ts +763 -0
- package/src/swarm.ts +1411 -0
- package/tsconfig.json +28 -0
- package/vitest.integration.config.ts +13 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Swarm Plugin
|
|
3
|
+
*
|
|
4
|
+
* A type-safe plugin for multi-agent coordination with beads issue tracking
|
|
5
|
+
* and Agent Mail integration. Provides structured tools for swarm operations.
|
|
6
|
+
*
|
|
7
|
+
* @module opencode-swarm-plugin
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // In opencode.jsonc
|
|
12
|
+
* {
|
|
13
|
+
* "plugins": ["opencode-swarm-plugin"]
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Programmatic usage
|
|
20
|
+
* import { beadsTools, agentMailTools } from "opencode-swarm-plugin"
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import type { Plugin, PluginInput, Hooks } from "@opencode-ai/plugin";
|
|
24
|
+
|
|
25
|
+
import { beadsTools } from "./beads";
|
|
26
|
+
import {
|
|
27
|
+
agentMailTools,
|
|
28
|
+
type AgentMailState,
|
|
29
|
+
AGENT_MAIL_URL,
|
|
30
|
+
} from "./agent-mail";
|
|
31
|
+
import { structuredTools } from "./structured";
|
|
32
|
+
import { swarmTools } from "./swarm";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* OpenCode Swarm Plugin
|
|
36
|
+
*
|
|
37
|
+
* Registers all swarm coordination tools:
|
|
38
|
+
* - beads:* - Type-safe beads issue tracker wrappers
|
|
39
|
+
* - agent-mail:* - Multi-agent coordination via Agent Mail MCP
|
|
40
|
+
* - structured:* - Structured output parsing and validation
|
|
41
|
+
* - swarm:* - Swarm orchestration and task decomposition
|
|
42
|
+
*
|
|
43
|
+
* @param input - Plugin context from OpenCode
|
|
44
|
+
* @returns Plugin hooks including tools, events, and tool execution hooks
|
|
45
|
+
*/
|
|
46
|
+
export const SwarmPlugin: Plugin = async (
|
|
47
|
+
input: PluginInput,
|
|
48
|
+
): Promise<Hooks> => {
|
|
49
|
+
const { $ } = input;
|
|
50
|
+
|
|
51
|
+
/** Track active sessions for cleanup */
|
|
52
|
+
let activeAgentMailState: AgentMailState | null = null;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Release all file reservations for the active agent
|
|
56
|
+
* Best-effort cleanup - errors are logged but not thrown
|
|
57
|
+
*/
|
|
58
|
+
async function releaseReservations(): Promise<void> {
|
|
59
|
+
if (
|
|
60
|
+
!activeAgentMailState ||
|
|
61
|
+
activeAgentMailState.reservations.length === 0
|
|
62
|
+
) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(`${AGENT_MAIL_URL}/mcp/`, {
|
|
68
|
+
method: "POST",
|
|
69
|
+
headers: { "Content-Type": "application/json" },
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
jsonrpc: "2.0",
|
|
72
|
+
id: crypto.randomUUID(),
|
|
73
|
+
method: "tools/call",
|
|
74
|
+
params: {
|
|
75
|
+
name: "release_file_reservations",
|
|
76
|
+
arguments: {
|
|
77
|
+
project_key: activeAgentMailState.projectKey,
|
|
78
|
+
agent_name: activeAgentMailState.agentName,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (response.ok) {
|
|
85
|
+
console.log(
|
|
86
|
+
`[swarm-plugin] Auto-released ${activeAgentMailState.reservations.length} file reservation(s)`,
|
|
87
|
+
);
|
|
88
|
+
activeAgentMailState.reservations = [];
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
// Agent Mail might not be running - that's ok
|
|
92
|
+
console.warn(
|
|
93
|
+
`[swarm-plugin] Could not auto-release reservations: ${error instanceof Error ? error.message : String(error)}`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
/**
|
|
100
|
+
* Register all tools from modules
|
|
101
|
+
*
|
|
102
|
+
* Tools are namespaced by module:
|
|
103
|
+
* - beads:create, beads:query, beads:update, etc.
|
|
104
|
+
* - agent-mail:init, agent-mail:send, agent-mail:reserve, etc.
|
|
105
|
+
*/
|
|
106
|
+
tool: {
|
|
107
|
+
...beadsTools,
|
|
108
|
+
...agentMailTools,
|
|
109
|
+
...structuredTools,
|
|
110
|
+
...swarmTools,
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Event hook for session lifecycle
|
|
115
|
+
*
|
|
116
|
+
* Handles cleanup when session becomes idle:
|
|
117
|
+
* - Releases any held file reservations
|
|
118
|
+
*/
|
|
119
|
+
event: async ({ event }) => {
|
|
120
|
+
// Auto-release reservations on session idle
|
|
121
|
+
if (event.type === "session.idle") {
|
|
122
|
+
await releaseReservations();
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Hook after tool execution for automatic cleanup
|
|
128
|
+
*
|
|
129
|
+
* Auto-releases file reservations after swarm:complete or beads:close
|
|
130
|
+
* to prevent stale locks when tasks finish.
|
|
131
|
+
*/
|
|
132
|
+
"tool.execute.after": async (input, output) => {
|
|
133
|
+
const toolName = input.tool;
|
|
134
|
+
|
|
135
|
+
// Track Agent Mail state for cleanup
|
|
136
|
+
if (toolName === "agentmail_init" && output.output) {
|
|
137
|
+
try {
|
|
138
|
+
const result = JSON.parse(output.output);
|
|
139
|
+
if (result.agent) {
|
|
140
|
+
activeAgentMailState = {
|
|
141
|
+
projectKey: result.project?.human_key || "",
|
|
142
|
+
agentName: result.agent.name,
|
|
143
|
+
reservations: [],
|
|
144
|
+
startedAt: new Date().toISOString(),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
} catch {
|
|
148
|
+
// Parsing failed - ignore
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Track reservations from output
|
|
153
|
+
if (
|
|
154
|
+
toolName === "agentmail_reserve" &&
|
|
155
|
+
output.output &&
|
|
156
|
+
activeAgentMailState
|
|
157
|
+
) {
|
|
158
|
+
// Extract reservation count from output if present
|
|
159
|
+
const match = output.output.match(/Reserved (\d+) path/);
|
|
160
|
+
if (match) {
|
|
161
|
+
// Track reservation for cleanup
|
|
162
|
+
activeAgentMailState.reservations.push(Date.now());
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Auto-release after swarm:complete
|
|
167
|
+
if (toolName === "swarm_complete" && activeAgentMailState) {
|
|
168
|
+
await releaseReservations();
|
|
169
|
+
console.log(
|
|
170
|
+
"[swarm-plugin] Auto-released reservations after swarm:complete",
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Auto-sync beads after closing
|
|
175
|
+
if (toolName === "beads_close") {
|
|
176
|
+
// Trigger async sync without blocking - fire and forget
|
|
177
|
+
void $`bd sync`
|
|
178
|
+
.quiet()
|
|
179
|
+
.nothrow()
|
|
180
|
+
.then(() => {
|
|
181
|
+
console.log("[swarm-plugin] Auto-synced beads after close");
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Default export for OpenCode plugin loading
|
|
190
|
+
*
|
|
191
|
+
* OpenCode loads plugins by their default export, so this allows:
|
|
192
|
+
* ```json
|
|
193
|
+
* { "plugins": ["opencode-swarm-plugin"] }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export default SwarmPlugin;
|
|
197
|
+
|
|
198
|
+
// =============================================================================
|
|
199
|
+
// Re-exports for programmatic use
|
|
200
|
+
// =============================================================================
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Re-export all schemas for type-safe usage
|
|
204
|
+
*/
|
|
205
|
+
export * from "./schemas";
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Re-export beads module
|
|
209
|
+
*
|
|
210
|
+
* Includes:
|
|
211
|
+
* - beadsTools - All bead tool definitions
|
|
212
|
+
* - Individual tool exports (beads_create, beads_query, etc.)
|
|
213
|
+
* - BeadError, BeadValidationError - Error classes
|
|
214
|
+
*/
|
|
215
|
+
export * from "./beads";
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Re-export agent-mail module
|
|
219
|
+
*
|
|
220
|
+
* Includes:
|
|
221
|
+
* - agentMailTools - All agent mail tool definitions
|
|
222
|
+
* - AgentMailError, FileReservationConflictError - Error classes
|
|
223
|
+
* - AgentMailState - Session state type
|
|
224
|
+
*
|
|
225
|
+
* NOTE: We selectively export to avoid exporting constants like AGENT_MAIL_URL
|
|
226
|
+
* which would confuse the plugin loader (it tries to call all exports as functions)
|
|
227
|
+
*/
|
|
228
|
+
export {
|
|
229
|
+
agentMailTools,
|
|
230
|
+
AgentMailError,
|
|
231
|
+
AgentMailNotInitializedError,
|
|
232
|
+
FileReservationConflictError,
|
|
233
|
+
type AgentMailState,
|
|
234
|
+
} from "./agent-mail";
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Re-export structured module
|
|
238
|
+
*
|
|
239
|
+
* Includes:
|
|
240
|
+
* - structuredTools - Structured output parsing tools
|
|
241
|
+
* - Utility functions for JSON extraction
|
|
242
|
+
*/
|
|
243
|
+
export {
|
|
244
|
+
structuredTools,
|
|
245
|
+
extractJsonFromText,
|
|
246
|
+
formatZodErrors,
|
|
247
|
+
getSchemaByName,
|
|
248
|
+
} from "./structured";
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Re-export swarm module
|
|
252
|
+
*
|
|
253
|
+
* Includes:
|
|
254
|
+
* - swarmTools - Swarm orchestration tools
|
|
255
|
+
* - SwarmError, DecompositionError - Error classes
|
|
256
|
+
* - formatSubtaskPrompt, formatEvaluationPrompt - Prompt helpers
|
|
257
|
+
*
|
|
258
|
+
* NOTE: Prompt template strings (DECOMPOSITION_PROMPT, etc.) are NOT exported
|
|
259
|
+
* to avoid confusing the plugin loader which tries to call all exports as functions
|
|
260
|
+
*/
|
|
261
|
+
export {
|
|
262
|
+
swarmTools,
|
|
263
|
+
SwarmError,
|
|
264
|
+
DecompositionError,
|
|
265
|
+
formatSubtaskPrompt,
|
|
266
|
+
formatEvaluationPrompt,
|
|
267
|
+
} from "./swarm";
|