opencodekit 0.16.15 → 0.16.18
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/README.md +77 -242
- package/dist/index.js +19 -6
- package/dist/template/.opencode/AGENTS.md +72 -236
- package/dist/template/.opencode/README.md +49 -482
- package/dist/template/.opencode/agent/build.md +71 -345
- package/dist/template/.opencode/agent/explore.md +47 -139
- package/dist/template/.opencode/agent/general.md +61 -172
- package/dist/template/.opencode/agent/looker.md +65 -161
- package/dist/template/.opencode/agent/painter.md +46 -200
- package/dist/template/.opencode/agent/plan.md +37 -220
- package/dist/template/.opencode/agent/review.md +72 -153
- package/dist/template/.opencode/agent/scout.md +44 -486
- package/dist/template/.opencode/agent/vision.md +63 -178
- package/dist/template/.opencode/command/create.md +75 -307
- package/dist/template/.opencode/command/design.md +53 -589
- package/dist/template/.opencode/command/handoff.md +76 -180
- package/dist/template/.opencode/command/init.md +45 -211
- package/dist/template/.opencode/command/plan.md +62 -514
- package/dist/template/.opencode/command/pr.md +56 -226
- package/dist/template/.opencode/command/research.md +55 -266
- package/dist/template/.opencode/command/resume.md +33 -138
- package/dist/template/.opencode/command/review-codebase.md +54 -202
- package/dist/template/.opencode/command/ship.md +78 -127
- package/dist/template/.opencode/command/start.md +47 -577
- package/dist/template/.opencode/command/status.md +60 -353
- package/dist/template/.opencode/command/ui-review.md +52 -298
- package/dist/template/.opencode/command/verify.md +36 -250
- package/dist/template/.opencode/memory.db-shm +0 -0
- package/dist/template/.opencode/memory.db-wal +0 -0
- package/dist/template/.opencode/opencode.json +133 -35
- package/dist/template/.opencode/plugin/README.md +40 -166
- package/dist/template/.opencode/plugin/compaction.ts +162 -131
- package/dist/template/.opencode/plugin/lib/memory-db.ts +112 -0
- package/dist/template/.opencode/plugin/swarm-enforcer.ts +182 -27
- package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +112 -0
- package/dist/template/.opencode/skill/augment-context-engine/mcp.json +6 -0
- package/dist/template/.opencode/skill/core-data-expert/SKILL.md +82 -0
- package/dist/template/.opencode/skill/core-data-expert/references/batch-operations.md +543 -0
- package/dist/template/.opencode/skill/core-data-expert/references/cloudkit-integration.md +259 -0
- package/dist/template/.opencode/skill/core-data-expert/references/concurrency.md +522 -0
- package/dist/template/.opencode/skill/core-data-expert/references/fetch-requests.md +643 -0
- package/dist/template/.opencode/skill/core-data-expert/references/glossary.md +233 -0
- package/dist/template/.opencode/skill/core-data-expert/references/migration.md +393 -0
- package/dist/template/.opencode/skill/core-data-expert/references/model-configuration.md +597 -0
- package/dist/template/.opencode/skill/core-data-expert/references/performance.md +300 -0
- package/dist/template/.opencode/skill/core-data-expert/references/persistent-history.md +553 -0
- package/dist/template/.opencode/skill/core-data-expert/references/project-audit.md +60 -0
- package/dist/template/.opencode/skill/core-data-expert/references/saving.md +574 -0
- package/dist/template/.opencode/skill/core-data-expert/references/stack-setup.md +625 -0
- package/dist/template/.opencode/skill/core-data-expert/references/testing.md +300 -0
- package/dist/template/.opencode/skill/core-data-expert/references/threading.md +589 -0
- package/dist/template/.opencode/skill/swift-concurrency/SKILL.md +246 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/actors.md +640 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-algorithms.md +822 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-await-basics.md +249 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-sequences.md +670 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/core-data.md +533 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/glossary.md +128 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/linting.md +142 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/memory-management.md +542 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/migration.md +1076 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/performance.md +574 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/sendable.md +578 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/tasks.md +604 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/testing.md +565 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/threading.md +452 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/SKILL.md +290 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/state-management.md +447 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/view-structure.md +276 -0
- package/dist/template/.opencode/tool/action-queue.ts +308 -0
- package/dist/template/.opencode/tool/swarm.ts +65 -40
- package/package.json +16 -3
- package/dist/template/.opencode/.agents/skills/context7/SKILL.md +0 -88
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { tool } from "@opencode-ai/plugin";
|
|
6
|
+
import {
|
|
7
|
+
type ActionQueueItemInput,
|
|
8
|
+
clearActionQueueItems,
|
|
9
|
+
listActionQueueItems,
|
|
10
|
+
replaceActionQueueItems,
|
|
11
|
+
} from "../plugin/lib/memory-db.js";
|
|
12
|
+
|
|
13
|
+
const execFileAsync = promisify(execFile);
|
|
14
|
+
const SWARM_PROGRESS_FILE = ".beads/swarm-progress.jsonl";
|
|
15
|
+
|
|
16
|
+
type QueueOperation = "status" | "refresh" | "clear";
|
|
17
|
+
|
|
18
|
+
interface QueueWorkerEntry {
|
|
19
|
+
timestamp?: string;
|
|
20
|
+
team_name?: string;
|
|
21
|
+
worker_id?: string;
|
|
22
|
+
phase?: string;
|
|
23
|
+
progress?: number;
|
|
24
|
+
status?: string;
|
|
25
|
+
file?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface QueueBeadTask {
|
|
29
|
+
id: string;
|
|
30
|
+
title: string;
|
|
31
|
+
status?: string;
|
|
32
|
+
priority?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parsePayload(payload: string | null): Record<string, unknown> {
|
|
36
|
+
if (!payload) return {};
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(payload) as Record<string, unknown>;
|
|
39
|
+
return parsed;
|
|
40
|
+
} catch {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function buildSnapshot(
|
|
46
|
+
items: ActionQueueItemInput[] | ReturnType<typeof listActionQueueItems>,
|
|
47
|
+
) {
|
|
48
|
+
const normalized = items.map((item) => ({
|
|
49
|
+
id: item.id,
|
|
50
|
+
source: item.source,
|
|
51
|
+
status: item.status,
|
|
52
|
+
title: item.title,
|
|
53
|
+
owner: item.owner ?? null,
|
|
54
|
+
payload:
|
|
55
|
+
"payload" in item && typeof item.payload === "string"
|
|
56
|
+
? parsePayload(item.payload)
|
|
57
|
+
: (item.payload ?? {}),
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
const pendingApprovals = normalized.filter(
|
|
61
|
+
(item) => item.source === "approval" && item.status === "pending",
|
|
62
|
+
);
|
|
63
|
+
const readyTasks = normalized.filter(
|
|
64
|
+
(item) => item.source === "bead" && item.status === "ready",
|
|
65
|
+
);
|
|
66
|
+
const idleWorkers = normalized.filter(
|
|
67
|
+
(item) => item.source === "worker" && item.status === "idle",
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
generated_at: new Date().toISOString(),
|
|
72
|
+
pending_approvals: pendingApprovals,
|
|
73
|
+
ready_tasks: readyTasks,
|
|
74
|
+
idle_workers: idleWorkers,
|
|
75
|
+
counts: {
|
|
76
|
+
pending_approvals: pendingApprovals.length,
|
|
77
|
+
ready_tasks: readyTasks.length,
|
|
78
|
+
idle_workers: idleWorkers.length,
|
|
79
|
+
total: normalized.length,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function readReadyTasks(worktree: string): Promise<QueueBeadTask[]> {
|
|
85
|
+
try {
|
|
86
|
+
const { stdout } = await execFileAsync("br", ["ready", "--json"], {
|
|
87
|
+
cwd: worktree,
|
|
88
|
+
timeout: 15000,
|
|
89
|
+
});
|
|
90
|
+
const parsed = JSON.parse(stdout) as QueueBeadTask[];
|
|
91
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
92
|
+
} catch {
|
|
93
|
+
try {
|
|
94
|
+
const { stdout } = await execFileAsync("br", ["ready"], {
|
|
95
|
+
cwd: worktree,
|
|
96
|
+
timeout: 15000,
|
|
97
|
+
});
|
|
98
|
+
const tasks: QueueBeadTask[] = [];
|
|
99
|
+
for (const line of stdout.split("\n")) {
|
|
100
|
+
const match = line.match(
|
|
101
|
+
/^#?(\S+)\s+\[(\w+)\]\s+(?:\(P(\d)\))?\s*(.+)$/,
|
|
102
|
+
);
|
|
103
|
+
if (!match) continue;
|
|
104
|
+
tasks.push({
|
|
105
|
+
id: match[1],
|
|
106
|
+
status: match[2],
|
|
107
|
+
priority: match[3] ? Number.parseInt(match[3], 10) : 2,
|
|
108
|
+
title: match[4],
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return tasks;
|
|
112
|
+
} catch {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function readWorkerEntries(
|
|
119
|
+
worktree: string,
|
|
120
|
+
): Promise<QueueWorkerEntry[]> {
|
|
121
|
+
const progressPath = path.join(worktree, SWARM_PROGRESS_FILE);
|
|
122
|
+
try {
|
|
123
|
+
const content = await fs.readFile(progressPath, "utf-8");
|
|
124
|
+
const entries = content
|
|
125
|
+
.trim()
|
|
126
|
+
.split("\n")
|
|
127
|
+
.filter(Boolean)
|
|
128
|
+
.map((line) => JSON.parse(line) as QueueWorkerEntry);
|
|
129
|
+
|
|
130
|
+
const latestByWorker = new Map<string, QueueWorkerEntry>();
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
if (!entry.worker_id) continue;
|
|
133
|
+
const previous = latestByWorker.get(entry.worker_id);
|
|
134
|
+
if (!previous) {
|
|
135
|
+
latestByWorker.set(entry.worker_id, entry);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const currentEpoch = Date.parse(entry.timestamp || "");
|
|
140
|
+
const previousEpoch = Date.parse(previous.timestamp || "");
|
|
141
|
+
if (Number.isNaN(previousEpoch) || currentEpoch >= previousEpoch) {
|
|
142
|
+
latestByWorker.set(entry.worker_id, entry);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return Array.from(latestByWorker.values());
|
|
147
|
+
} catch {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function toQueueItems(
|
|
153
|
+
readyTasks: QueueBeadTask[],
|
|
154
|
+
workerEntries: QueueWorkerEntry[],
|
|
155
|
+
): ActionQueueItemInput[] {
|
|
156
|
+
const items: ActionQueueItemInput[] = [];
|
|
157
|
+
|
|
158
|
+
for (const task of readyTasks) {
|
|
159
|
+
items.push({
|
|
160
|
+
id: `bead:${task.id}`,
|
|
161
|
+
source: "bead",
|
|
162
|
+
status: "ready",
|
|
163
|
+
title: task.title,
|
|
164
|
+
owner: task.id,
|
|
165
|
+
payload: {
|
|
166
|
+
bead_id: task.id,
|
|
167
|
+
priority: task.priority ?? null,
|
|
168
|
+
status: task.status ?? "ready",
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
for (const worker of workerEntries) {
|
|
174
|
+
const workerId = worker.worker_id || "unknown";
|
|
175
|
+
const status = (worker.status || "").toLowerCase();
|
|
176
|
+
const phase = (worker.phase || "").toLowerCase();
|
|
177
|
+
const needsApproval =
|
|
178
|
+
status.includes("approval") ||
|
|
179
|
+
status === "awaiting_approval" ||
|
|
180
|
+
status === "needs_approval" ||
|
|
181
|
+
phase.includes("approval");
|
|
182
|
+
|
|
183
|
+
if (status === "idle") {
|
|
184
|
+
items.push({
|
|
185
|
+
id: `worker:${workerId}`,
|
|
186
|
+
source: "worker",
|
|
187
|
+
status: "idle",
|
|
188
|
+
title: `Worker ${workerId} is idle`,
|
|
189
|
+
owner: workerId,
|
|
190
|
+
payload: {
|
|
191
|
+
phase: worker.phase || null,
|
|
192
|
+
progress: worker.progress ?? null,
|
|
193
|
+
file: worker.file || null,
|
|
194
|
+
timestamp: worker.timestamp || null,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (needsApproval) {
|
|
200
|
+
items.push({
|
|
201
|
+
id: `approval:${workerId}`,
|
|
202
|
+
source: "approval",
|
|
203
|
+
status: "pending",
|
|
204
|
+
title: `Approval needed for worker ${workerId}`,
|
|
205
|
+
owner: workerId,
|
|
206
|
+
payload: {
|
|
207
|
+
phase: worker.phase || null,
|
|
208
|
+
status: worker.status || null,
|
|
209
|
+
progress: worker.progress ?? null,
|
|
210
|
+
file: worker.file || null,
|
|
211
|
+
timestamp: worker.timestamp || null,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return items;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async function refreshSnapshot(worktree: string) {
|
|
221
|
+
const [readyTasks, workerEntries] = await Promise.all([
|
|
222
|
+
readReadyTasks(worktree),
|
|
223
|
+
readWorkerEntries(worktree),
|
|
224
|
+
]);
|
|
225
|
+
|
|
226
|
+
const items = toQueueItems(readyTasks, workerEntries);
|
|
227
|
+
replaceActionQueueItems(items);
|
|
228
|
+
|
|
229
|
+
return buildSnapshot(items);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export default tool({
|
|
233
|
+
description: `Unified action queue for operators.
|
|
234
|
+
|
|
235
|
+
Returns a consumable queue with:
|
|
236
|
+
- pending approvals
|
|
237
|
+
- ready tasks
|
|
238
|
+
- idle workers
|
|
239
|
+
|
|
240
|
+
Operations:
|
|
241
|
+
- status: Read last stored queue snapshot
|
|
242
|
+
- refresh: Recompute queue from Beads + swarm progress and store snapshot
|
|
243
|
+
- clear: Clear stored queue snapshot`,
|
|
244
|
+
args: {
|
|
245
|
+
op: tool.schema
|
|
246
|
+
.enum(["status", "refresh", "clear"])
|
|
247
|
+
.optional()
|
|
248
|
+
.default("status")
|
|
249
|
+
.describe("Operation: status, refresh, clear"),
|
|
250
|
+
},
|
|
251
|
+
execute: async (args: { op?: QueueOperation }, ctx) => {
|
|
252
|
+
const op = args.op || "status";
|
|
253
|
+
const worktree = ctx.worktree || process.cwd();
|
|
254
|
+
|
|
255
|
+
if (op === "clear") {
|
|
256
|
+
clearActionQueueItems();
|
|
257
|
+
return JSON.stringify(
|
|
258
|
+
{
|
|
259
|
+
op: "clear",
|
|
260
|
+
result: "ok",
|
|
261
|
+
cleared: true,
|
|
262
|
+
queue: buildSnapshot([]),
|
|
263
|
+
},
|
|
264
|
+
null,
|
|
265
|
+
2,
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (op === "refresh") {
|
|
270
|
+
const queue = await refreshSnapshot(worktree);
|
|
271
|
+
return JSON.stringify(
|
|
272
|
+
{
|
|
273
|
+
op: "refresh",
|
|
274
|
+
result: "ok",
|
|
275
|
+
queue,
|
|
276
|
+
},
|
|
277
|
+
null,
|
|
278
|
+
2,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const stored = listActionQueueItems();
|
|
283
|
+
if (stored.length === 0) {
|
|
284
|
+
const queue = await refreshSnapshot(worktree);
|
|
285
|
+
return JSON.stringify(
|
|
286
|
+
{
|
|
287
|
+
op: "status",
|
|
288
|
+
result: "ok",
|
|
289
|
+
source: "live-refresh",
|
|
290
|
+
queue,
|
|
291
|
+
},
|
|
292
|
+
null,
|
|
293
|
+
2,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return JSON.stringify(
|
|
298
|
+
{
|
|
299
|
+
op: "status",
|
|
300
|
+
result: "ok",
|
|
301
|
+
source: "snapshot",
|
|
302
|
+
queue: buildSnapshot(stored),
|
|
303
|
+
},
|
|
304
|
+
null,
|
|
305
|
+
2,
|
|
306
|
+
);
|
|
307
|
+
},
|
|
308
|
+
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import { tool } from "@opencode-ai/plugin";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Unified swarm orchestration tool.
|
|
@@ -38,7 +38,7 @@ Usage:
|
|
|
38
38
|
// Monitor args
|
|
39
39
|
team: tool.schema.string().optional().describe("Team name (monitor)"),
|
|
40
40
|
action: tool.schema
|
|
41
|
-
.
|
|
41
|
+
.enum(["update", "render", "status", "clear", "push", "pull"])
|
|
42
42
|
.optional()
|
|
43
43
|
.describe(
|
|
44
44
|
"Monitor action: update, render, status, clear | Sync action: push, pull",
|
|
@@ -82,7 +82,7 @@ Usage:
|
|
|
82
82
|
.describe("Write to file (delegate)"),
|
|
83
83
|
// Sync args
|
|
84
84
|
filter: tool.schema
|
|
85
|
-
.
|
|
85
|
+
.enum(["open", "in_progress", "all"])
|
|
86
86
|
.optional()
|
|
87
87
|
.describe("Filter: open, in_progress, all (sync)"),
|
|
88
88
|
},
|
|
@@ -96,7 +96,7 @@ Usage:
|
|
|
96
96
|
case "monitor":
|
|
97
97
|
return monitorOperation(args, worktree);
|
|
98
98
|
case "delegate":
|
|
99
|
-
return delegateOperation(args);
|
|
99
|
+
return delegateOperation(args, worktree);
|
|
100
100
|
case "sync":
|
|
101
101
|
return syncOperation(args, worktree);
|
|
102
102
|
default:
|
|
@@ -240,10 +240,21 @@ interface ProgressEntry {
|
|
|
240
240
|
file?: string;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
type MonitorAction = "update" | "render" | "status" | "clear";
|
|
244
|
+
type SyncAction = "push" | "pull";
|
|
245
|
+
type SyncFilter = "open" | "in_progress" | "all";
|
|
246
|
+
|
|
247
|
+
const MONITOR_ACTIONS = new Set<MonitorAction>([
|
|
248
|
+
"update",
|
|
249
|
+
"render",
|
|
250
|
+
"status",
|
|
251
|
+
"clear",
|
|
252
|
+
]);
|
|
253
|
+
|
|
243
254
|
async function monitorOperation(
|
|
244
255
|
args: {
|
|
245
256
|
team?: string;
|
|
246
|
-
action?:
|
|
257
|
+
action?: MonitorAction | SyncAction;
|
|
247
258
|
worker_id?: string;
|
|
248
259
|
phase?: string;
|
|
249
260
|
progress?: number;
|
|
@@ -253,7 +264,10 @@ async function monitorOperation(
|
|
|
253
264
|
worktree: string,
|
|
254
265
|
): Promise<string> {
|
|
255
266
|
const team = args.team || "default";
|
|
256
|
-
|
|
267
|
+
if (args.action && !MONITOR_ACTIONS.has(args.action as MonitorAction)) {
|
|
268
|
+
return `Invalid monitor action: ${args.action}`;
|
|
269
|
+
}
|
|
270
|
+
const action: MonitorAction = (args.action as MonitorAction) || "status";
|
|
257
271
|
|
|
258
272
|
switch (action) {
|
|
259
273
|
case "update":
|
|
@@ -367,16 +381,19 @@ async function clearTeam(team: string, worktree: string): Promise<string> {
|
|
|
367
381
|
// DELEGATE OPERATION (from swarm-delegate.ts)
|
|
368
382
|
// ============================================================
|
|
369
383
|
|
|
370
|
-
function delegateOperation(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
384
|
+
async function delegateOperation(
|
|
385
|
+
args: {
|
|
386
|
+
bead_id?: string;
|
|
387
|
+
title?: string;
|
|
388
|
+
outcome?: string;
|
|
389
|
+
must_do?: string;
|
|
390
|
+
must_not?: string;
|
|
391
|
+
checks?: string;
|
|
392
|
+
context?: string;
|
|
393
|
+
write?: boolean;
|
|
394
|
+
},
|
|
395
|
+
worktree: string,
|
|
396
|
+
): Promise<string> {
|
|
380
397
|
if (!args.bead_id) return "Error: bead_id required";
|
|
381
398
|
if (!args.outcome) return "Error: outcome required";
|
|
382
399
|
|
|
@@ -405,24 +422,21 @@ function delegateOperation(args: {
|
|
|
405
422
|
|
|
406
423
|
if (!args.write) return packet;
|
|
407
424
|
|
|
408
|
-
|
|
409
|
-
const artifactDir = path.join(
|
|
410
|
-
process.cwd(),
|
|
411
|
-
".beads",
|
|
412
|
-
"artifacts",
|
|
413
|
-
args.bead_id,
|
|
414
|
-
);
|
|
425
|
+
const artifactDir = path.join(worktree, ".beads", "artifacts", args.bead_id);
|
|
415
426
|
const outPath = path.join(artifactDir, "delegation.md");
|
|
416
|
-
fs.mkdir(artifactDir, { recursive: true })
|
|
417
|
-
.then(() =>
|
|
418
|
-
fs.appendFile(
|
|
419
|
-
outPath,
|
|
420
|
-
`\n---\nGenerated: ${new Date().toISOString()}\n---\n\n${packet}\n`,
|
|
421
|
-
),
|
|
422
|
-
)
|
|
423
|
-
.catch(() => {});
|
|
424
427
|
|
|
425
|
-
|
|
428
|
+
try {
|
|
429
|
+
await fs.mkdir(artifactDir, { recursive: true });
|
|
430
|
+
await fs.appendFile(
|
|
431
|
+
outPath,
|
|
432
|
+
`\n---\nGenerated: ${new Date().toISOString()}\n---\n\n${packet}\n`,
|
|
433
|
+
"utf-8",
|
|
434
|
+
);
|
|
435
|
+
return `✓ Delegation packet written to ${outPath}\n\n${packet}`;
|
|
436
|
+
} catch (error: unknown) {
|
|
437
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
438
|
+
return `Error writing delegation packet: ${message}`;
|
|
439
|
+
}
|
|
426
440
|
}
|
|
427
441
|
|
|
428
442
|
// ============================================================
|
|
@@ -446,10 +460,14 @@ interface BeadTask {
|
|
|
446
460
|
}
|
|
447
461
|
|
|
448
462
|
async function syncOperation(
|
|
449
|
-
args: { action?:
|
|
463
|
+
args: { action?: MonitorAction | SyncAction; filter?: SyncFilter },
|
|
450
464
|
worktree: string,
|
|
451
465
|
): Promise<string> {
|
|
452
|
-
|
|
466
|
+
if (args.action && args.action !== "push" && args.action !== "pull") {
|
|
467
|
+
return `Invalid sync action: ${args.action}`;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const action: SyncAction = (args.action as SyncAction) || "push";
|
|
453
471
|
|
|
454
472
|
if (action === "push") {
|
|
455
473
|
return pushBeadsToTodos(worktree, args.filter || "open");
|
|
@@ -462,12 +480,17 @@ async function syncOperation(
|
|
|
462
480
|
|
|
463
481
|
async function pushBeadsToTodos(
|
|
464
482
|
worktree: string,
|
|
465
|
-
filter:
|
|
483
|
+
filter: SyncFilter,
|
|
466
484
|
): Promise<string> {
|
|
467
485
|
try {
|
|
468
|
-
const
|
|
469
|
-
|
|
486
|
+
const args = ["list", "--json"];
|
|
487
|
+
if (filter !== "all") {
|
|
488
|
+
args.push("--status", filter);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const { stdout } = await execFileAsync("br", args, {
|
|
470
492
|
cwd: worktree,
|
|
493
|
+
timeout: 15000,
|
|
471
494
|
});
|
|
472
495
|
|
|
473
496
|
let tasks: BeadTask[];
|
|
@@ -532,10 +555,12 @@ async function pullTodosToBeads(worktree: string): Promise<string> {
|
|
|
532
555
|
for (const todo of todos) {
|
|
533
556
|
if (todo.beadId && todo.status === "completed") {
|
|
534
557
|
try {
|
|
535
|
-
await
|
|
536
|
-
|
|
558
|
+
await execFileAsync(
|
|
559
|
+
"br",
|
|
560
|
+
["close", todo.beadId, "--reason", "Completed via todo"],
|
|
537
561
|
{
|
|
538
562
|
cwd: worktree,
|
|
563
|
+
timeout: 15000,
|
|
539
564
|
},
|
|
540
565
|
);
|
|
541
566
|
updated++;
|
package/package.json
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencodekit",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.18",
|
|
4
4
|
"description": "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agents",
|
|
7
|
+
"cli",
|
|
8
|
+
"mcp",
|
|
9
|
+
"opencode",
|
|
10
|
+
"opencodekit",
|
|
11
|
+
"template"
|
|
12
|
+
],
|
|
6
13
|
"license": "MIT",
|
|
7
14
|
"author": "OpenCodeKit",
|
|
8
15
|
"repository": {
|
|
@@ -12,7 +19,10 @@
|
|
|
12
19
|
"bin": {
|
|
13
20
|
"ock": "dist/index.js"
|
|
14
21
|
},
|
|
15
|
-
"files": [
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
16
26
|
"type": "module",
|
|
17
27
|
"publishConfig": {
|
|
18
28
|
"access": "public",
|
|
@@ -26,6 +36,9 @@
|
|
|
26
36
|
"typecheck": "tsc --noEmit",
|
|
27
37
|
"test": "bun test",
|
|
28
38
|
"test:watch": "bun test --watch",
|
|
39
|
+
"validate:command-doc": "bun run src/validation/command-doc.ts --check",
|
|
40
|
+
"validate:docs-drift": "bun run src/validation/docs-drift.ts --check",
|
|
41
|
+
"validate:governance": "npm run validate:command-doc && npm run validate:docs-drift",
|
|
29
42
|
"lint": "oxlint .",
|
|
30
43
|
"lint:fix": "oxlint --fix .",
|
|
31
44
|
"format": "oxfmt",
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: context7
|
|
3
|
-
description: Retrieve up-to-date documentation for software libraries, frameworks, and components via the Context7 API. This skill should be used when looking up documentation for any programming library or framework, finding code examples for specific APIs or features, verifying correct usage of library functions, or obtaining current information about library APIs that may have changed since training.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Context7
|
|
7
|
-
|
|
8
|
-
## Overview
|
|
9
|
-
|
|
10
|
-
This skill enables retrieval of current documentation for software libraries and components by querying the Context7 API via curl. Use it instead of relying on potentially outdated training data.
|
|
11
|
-
|
|
12
|
-
## Workflow
|
|
13
|
-
|
|
14
|
-
### Step 1: Search for the Library
|
|
15
|
-
|
|
16
|
-
To find the Context7 library ID, query the search endpoint:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
curl -s "https://context7.com/api/v2/libs/search?libraryName=LIBRARY_NAME&query=TOPIC" | jq '.results[0]'
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**Parameters:**
|
|
23
|
-
|
|
24
|
-
- `libraryName` (required): The library name to search for (e.g., "react", "nextjs", "fastapi", "axios")
|
|
25
|
-
- `query` (required): A description of the topic for relevance ranking
|
|
26
|
-
|
|
27
|
-
**Response fields:**
|
|
28
|
-
|
|
29
|
-
- `id`: Library identifier for the context endpoint (e.g., `/websites/react_dev_reference`)
|
|
30
|
-
- `title`: Human-readable library name
|
|
31
|
-
- `description`: Brief description of the library
|
|
32
|
-
- `totalSnippets`: Number of documentation snippets available
|
|
33
|
-
|
|
34
|
-
### Step 2: Fetch Documentation
|
|
35
|
-
|
|
36
|
-
To retrieve documentation, use the library ID from step 1:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
curl -s "https://context7.com/api/v2/context?libraryId=LIBRARY_ID&query=TOPIC&type=txt"
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**Parameters:**
|
|
43
|
-
|
|
44
|
-
- `libraryId` (required): The library ID from search results
|
|
45
|
-
- `query` (required): The specific topic to retrieve documentation for
|
|
46
|
-
- `type` (optional): Response format - `json` (default) or `txt` (plain text, more readable)
|
|
47
|
-
|
|
48
|
-
## Examples
|
|
49
|
-
|
|
50
|
-
### React hooks documentation
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
# Find React library ID
|
|
54
|
-
curl -s "https://context7.com/api/v2/libs/search?libraryName=react&query=hooks" | jq '.results[0].id'
|
|
55
|
-
# Returns: "/websites/react_dev_reference"
|
|
56
|
-
|
|
57
|
-
# Fetch useState documentation
|
|
58
|
-
curl -s "https://context7.com/api/v2/context?libraryId=/websites/react_dev_reference&query=useState&type=txt"
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Next.js routing documentation
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
# Find Next.js library ID
|
|
65
|
-
curl -s "https://context7.com/api/v2/libs/search?libraryName=nextjs&query=routing" | jq '.results[0].id'
|
|
66
|
-
|
|
67
|
-
# Fetch app router documentation
|
|
68
|
-
curl -s "https://context7.com/api/v2/context?libraryId=/vercel/next.js&query=app+router&type=txt"
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### FastAPI dependency injection
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
# Find FastAPI library ID
|
|
75
|
-
curl -s "https://context7.com/api/v2/libs/search?libraryName=fastapi&query=dependencies" | jq '.results[0].id'
|
|
76
|
-
|
|
77
|
-
# Fetch dependency injection documentation
|
|
78
|
-
curl -s "https://context7.com/api/v2/context?libraryId=/fastapi/fastapi&query=dependency+injection&type=txt"
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Tips
|
|
82
|
-
|
|
83
|
-
- Use `type=txt` for more readable output
|
|
84
|
-
- Use `jq` to filter and format JSON responses
|
|
85
|
-
- Be specific with the `query` parameter to improve relevance ranking
|
|
86
|
-
- If the first search result is not correct, check additional results in the array
|
|
87
|
-
- URL-encode query parameters containing spaces (use `+` or `%20`)
|
|
88
|
-
- No API key is required for basic usage (rate-limited)
|