opencodekit 0.15.10 → 0.15.12
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/dist/index.js +1 -1
- package/dist/template/.opencode/agent/build.md +390 -0
- package/dist/template/.opencode/command/implement.md +136 -10
- package/dist/template/.opencode/memory/observations/2026-01-25-decision-agent-roles-build-orchestrates-general-e.md +14 -0
- package/dist/template/.opencode/memory/observations/2026-01-25-decision-simplified-swarm-helper-tool-to-fix-type.md +20 -0
- package/dist/template/.opencode/memory/observations/2026-01-25-decision-use-beads-as-swarm-board-source-of-truth.md +14 -0
- package/dist/template/.opencode/memory/observations/2026-01-25-learning-user-wants-real-swarm-coordination-guida.md +15 -0
- package/dist/template/.opencode/memory/research/opencode-mcp-bug-report.md +126 -0
- package/dist/template/.opencode/opencode.json +151 -46
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/plans/swarm-protocol.md +123 -0
- package/dist/template/.opencode/plugin/README.md +10 -0
- package/dist/template/.opencode/plugin/copilot-auth.ts +104 -77
- package/dist/template/.opencode/plugin/swarm-enforcer.ts +297 -0
- package/dist/template/.opencode/skill/swarm-coordination/SKILL.md +405 -0
- package/dist/template/.opencode/tool/swarm-delegate.ts +175 -0
- package/dist/template/.opencode/tool/swarm-helper.ts +164 -0
- package/package.json +1 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { tool } from "@opencode-ai/plugin";
|
|
4
|
+
|
|
5
|
+
export const SWARM_MAIL_FILE = ".beads/swarm-mail.jsonl";
|
|
6
|
+
|
|
7
|
+
type BaseArgs = {
|
|
8
|
+
team_name: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type GetTeamStatusArgs = BaseArgs & {
|
|
12
|
+
limit?: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type SendTeamMessageArgs = BaseArgs & {
|
|
16
|
+
from_worker?: string;
|
|
17
|
+
to_worker?: string;
|
|
18
|
+
message: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default tool({
|
|
22
|
+
description: `Swarm coordination helper.
|
|
23
|
+
|
|
24
|
+
Operations:
|
|
25
|
+
- getTeamStatus: Read swarm mailbox for worker reports and progress
|
|
26
|
+
- sendTeamMessage: Write to swarm mailbox for coordination
|
|
27
|
+
|
|
28
|
+
Pattern:
|
|
29
|
+
- Build agent orchestrates: parses plan → spawns team → monitors → synthesizes
|
|
30
|
+
- General agent executes: reads delegation packet → makes changes → reports back
|
|
31
|
+
- Coordination via mailbox: .beads/swarm-mail.jsonl (append-only log)
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
getTeamStatus({ team_name: "plan-implementation" })
|
|
35
|
+
→ Returns: worker_status for each worker (pending/working/done/error)
|
|
36
|
+
|
|
37
|
+
sendTeamMessage({
|
|
38
|
+
team_name: "plan-implementation",
|
|
39
|
+
from_worker: "worker-1",
|
|
40
|
+
to_worker: "worker-2",
|
|
41
|
+
message: "Need help with file locking",
|
|
42
|
+
})
|
|
43
|
+
→ Appends JSONL line: { timestamp, from, to, message }
|
|
44
|
+
|
|
45
|
+
`,
|
|
46
|
+
args: {
|
|
47
|
+
team_name: tool.schema
|
|
48
|
+
.string()
|
|
49
|
+
.describe("Team identifier (e.g., plan-implementation, auth-feature)"),
|
|
50
|
+
operation: tool.schema
|
|
51
|
+
.enum(["getTeamStatus", "sendTeamMessage"])
|
|
52
|
+
.describe("Which swarm coordination operation to perform"),
|
|
53
|
+
from_worker: tool.schema
|
|
54
|
+
.string()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Sending worker name (sendTeamMessage)"),
|
|
57
|
+
to_worker: tool.schema
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe("Target worker name (sendTeamMessage)"),
|
|
61
|
+
message: tool.schema
|
|
62
|
+
.string()
|
|
63
|
+
.optional()
|
|
64
|
+
.describe("Message content (sendTeamMessage)"),
|
|
65
|
+
limit: tool.schema
|
|
66
|
+
.number()
|
|
67
|
+
.optional()
|
|
68
|
+
.describe("Limit mailbox entries (getTeamStatus)"),
|
|
69
|
+
},
|
|
70
|
+
execute: async (args) => {
|
|
71
|
+
const operation = args.operation as string;
|
|
72
|
+
|
|
73
|
+
if (operation === "getTeamStatus") {
|
|
74
|
+
const result = await getTeamStatus(args as any);
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (operation === "sendTeamMessage") {
|
|
79
|
+
const result = await sendTeamMessage(args as any);
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return `Error: Unknown operation: ${operation}. Valid: getTeamStatus, sendTeamMessage`;
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
async function getTeamStatus(args: GetTeamStatusArgs) {
|
|
88
|
+
const { team_name, limit } = args;
|
|
89
|
+
|
|
90
|
+
if (!team_name) {
|
|
91
|
+
return "Error: team_name is required.";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const mailPath = path.join(process.cwd(), SWARM_MAIL_FILE);
|
|
95
|
+
let lines: string[];
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const content = await fs.readFile(mailPath, "utf-8");
|
|
99
|
+
lines = content.trim().split("\n").filter(Boolean);
|
|
100
|
+
} catch {
|
|
101
|
+
return `Error: Failed to read ${SWARM_MAIL_FILE}.`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const team_messages = lines
|
|
105
|
+
.map((line) => {
|
|
106
|
+
try {
|
|
107
|
+
return JSON.parse(line) as {
|
|
108
|
+
timestamp: string;
|
|
109
|
+
team_name: string;
|
|
110
|
+
from_worker?: string;
|
|
111
|
+
to_worker?: string;
|
|
112
|
+
message?: string;
|
|
113
|
+
status?: string;
|
|
114
|
+
};
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
.filter(Boolean);
|
|
120
|
+
|
|
121
|
+
const relevant = team_messages.filter((m) => m.team_name === team_name);
|
|
122
|
+
|
|
123
|
+
if (limit && limit > 0) {
|
|
124
|
+
return JSON.stringify(relevant.slice(-limit), null, 2);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return JSON.stringify(relevant, null, 2);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function sendTeamMessage(args: SendTeamMessageArgs) {
|
|
131
|
+
const { team_name, from_worker, to_worker, message } = args;
|
|
132
|
+
|
|
133
|
+
if (!team_name || !message) {
|
|
134
|
+
return "Error: team_name and message are required.";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const mailPath = path.join(process.cwd(), SWARM_MAIL_FILE);
|
|
138
|
+
const entry = {
|
|
139
|
+
timestamp: new Date().toISOString(),
|
|
140
|
+
team_name,
|
|
141
|
+
from_worker: from_worker || "system",
|
|
142
|
+
to_worker: to_worker || "all",
|
|
143
|
+
message,
|
|
144
|
+
status: "unread",
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
await fs.appendFile(mailPath, `${JSON.stringify(entry)}\n`, "utf-8");
|
|
149
|
+
return JSON.stringify(
|
|
150
|
+
{
|
|
151
|
+
success: true,
|
|
152
|
+
team_name,
|
|
153
|
+
from_worker,
|
|
154
|
+
to_worker,
|
|
155
|
+
message,
|
|
156
|
+
mail_file: SWARM_MAIL_FILE,
|
|
157
|
+
},
|
|
158
|
+
null,
|
|
159
|
+
2,
|
|
160
|
+
);
|
|
161
|
+
} catch (error: any) {
|
|
162
|
+
return `Error: Failed to write to ${SWARM_MAIL_FILE}: ${error}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
package/package.json
CHANGED