opencodekit 0.17.13 → 0.18.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.
Files changed (36) hide show
  1. package/dist/index.js +4 -6
  2. package/dist/template/.opencode/dcp.jsonc +81 -81
  3. package/dist/template/.opencode/memory/memory.db +0 -0
  4. package/dist/template/.opencode/memory.db +0 -0
  5. package/dist/template/.opencode/memory.db-shm +0 -0
  6. package/dist/template/.opencode/memory.db-wal +0 -0
  7. package/dist/template/.opencode/opencode.json +199 -23
  8. package/dist/template/.opencode/opencode.json.tui-migration.bak +1380 -0
  9. package/dist/template/.opencode/package.json +1 -1
  10. package/dist/template/.opencode/plugin/lib/capture.ts +177 -0
  11. package/dist/template/.opencode/plugin/lib/context.ts +194 -0
  12. package/dist/template/.opencode/plugin/lib/curator.ts +234 -0
  13. package/dist/template/.opencode/plugin/lib/db/maintenance.ts +312 -0
  14. package/dist/template/.opencode/plugin/lib/db/observations.ts +299 -0
  15. package/dist/template/.opencode/plugin/lib/db/pipeline.ts +520 -0
  16. package/dist/template/.opencode/plugin/lib/db/schema.ts +356 -0
  17. package/dist/template/.opencode/plugin/lib/db/types.ts +211 -0
  18. package/dist/template/.opencode/plugin/lib/distill.ts +376 -0
  19. package/dist/template/.opencode/plugin/lib/inject.ts +126 -0
  20. package/dist/template/.opencode/plugin/lib/memory-admin-tools.ts +188 -0
  21. package/dist/template/.opencode/plugin/lib/memory-db.ts +54 -936
  22. package/dist/template/.opencode/plugin/lib/memory-helpers.ts +202 -0
  23. package/dist/template/.opencode/plugin/lib/memory-hooks.ts +240 -0
  24. package/dist/template/.opencode/plugin/lib/memory-tools.ts +341 -0
  25. package/dist/template/.opencode/plugin/memory.ts +56 -60
  26. package/dist/template/.opencode/plugin/sessions.ts +372 -93
  27. package/dist/template/.opencode/tui.json +15 -0
  28. package/package.json +1 -1
  29. package/dist/template/.opencode/tool/action-queue.ts +0 -313
  30. package/dist/template/.opencode/tool/memory-admin.ts +0 -445
  31. package/dist/template/.opencode/tool/memory-get.ts +0 -143
  32. package/dist/template/.opencode/tool/memory-read.ts +0 -45
  33. package/dist/template/.opencode/tool/memory-search.ts +0 -264
  34. package/dist/template/.opencode/tool/memory-timeline.ts +0 -105
  35. package/dist/template/.opencode/tool/memory-update.ts +0 -63
  36. package/dist/template/.opencode/tool/observation.ts +0 -357
@@ -1,313 +0,0 @@
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 with context-aware hints:
241
- - status: Read last stored queue snapshot. Use for quick checks or when you just refreshed and want a stable view without re-scanning.
242
- - refresh: Recompute queue from Beads + swarm progress and store snapshot. Use when work has changed (new beads, workers progressed, approvals resolved) or when status shows stale counts.
243
- - clear: Clear stored queue snapshot. Use when you want to force a clean slate before a fresh refresh or when stale data is confusing the queue view.
244
-
245
- Examples:
246
- - You see pending approvals but know they were resolved: run refresh to rebuild from live worker progress.
247
- - You want a quick glance during a long session: run status to reuse the last snapshot.
248
- - You suspect the snapshot is corrupted or out of date: run clear, then refresh to rebuild from scratch.`,
249
- args: {
250
- op: tool.schema
251
- .enum(["status", "refresh", "clear"])
252
- .optional()
253
- .default("status")
254
- .describe("Operation: status, refresh, clear"),
255
- },
256
- execute: async (args: { op?: QueueOperation }, ctx) => {
257
- const op = args.op || "status";
258
- const worktree = ctx.worktree || process.cwd();
259
-
260
- if (op === "clear") {
261
- clearActionQueueItems();
262
- return JSON.stringify(
263
- {
264
- op: "clear",
265
- result: "ok",
266
- cleared: true,
267
- queue: buildSnapshot([]),
268
- },
269
- null,
270
- 2,
271
- );
272
- }
273
-
274
- if (op === "refresh") {
275
- const queue = await refreshSnapshot(worktree);
276
- return JSON.stringify(
277
- {
278
- op: "refresh",
279
- result: "ok",
280
- queue,
281
- },
282
- null,
283
- 2,
284
- );
285
- }
286
-
287
- const stored = listActionQueueItems();
288
- if (stored.length === 0) {
289
- const queue = await refreshSnapshot(worktree);
290
- return JSON.stringify(
291
- {
292
- op: "status",
293
- result: "ok",
294
- source: "live-refresh",
295
- queue,
296
- },
297
- null,
298
- 2,
299
- );
300
- }
301
-
302
- return JSON.stringify(
303
- {
304
- op: "status",
305
- result: "ok",
306
- source: "snapshot",
307
- queue: buildSnapshot(stored),
308
- },
309
- null,
310
- 2,
311
- );
312
- },
313
- });