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,357 +0,0 @@
1
- import { tool } from "@opencode-ai/plugin";
2
- import {
3
- type ConfidenceLevel,
4
- type ObservationInput,
5
- type ObservationType,
6
- storeObservation,
7
- } from "../plugin/lib/memory-db.js";
8
-
9
- const TYPE_ICONS: Record<ObservationType, string> = {
10
- decision: "🎯",
11
- bugfix: "🐛",
12
- feature: "✨",
13
- pattern: "🔄",
14
- discovery: "💡",
15
- learning: "📚",
16
- warning: "⚠️",
17
- };
18
-
19
- const CONFIDENCE_ICONS: Record<ConfidenceLevel, string> = {
20
- high: "🟢",
21
- medium: "🟡",
22
- low: "🔴",
23
- };
24
-
25
- // Patterns to detect file references in observation content
26
- const FILE_PATTERNS = [
27
- // file:line format (e.g., src/auth.ts:42)
28
- /(?:^|\s)([a-zA-Z0-9_\-./]+\.[a-zA-Z]{2,4}):(\d+)/g,
29
- // backtick file paths (e.g., `src/auth.ts`)
30
- /`([a-zA-Z0-9_\-./]+\.[a-zA-Z]{2,4})`/g,
31
- // common source paths
32
- /(?:^|\s)(src\/[a-zA-Z0-9_\-./]+\.[a-zA-Z]{2,4})/g,
33
- /(?:^|\s)(\.opencode\/[a-zA-Z0-9_\-./]+\.[a-zA-Z]{2,4})/g,
34
- ];
35
-
36
- interface FileReference {
37
- file: string;
38
- line?: number;
39
- }
40
-
41
- // Extract file references from observation content
42
- function extractFileReferences(content: string): FileReference[] {
43
- const refs: FileReference[] = [];
44
- const seen = new Set<string>();
45
-
46
- for (const pattern of FILE_PATTERNS) {
47
- // Reset regex state
48
- pattern.lastIndex = 0;
49
- let match = pattern.exec(content);
50
-
51
- while (match !== null) {
52
- const file = match[1];
53
- const line = match[2] ? Number.parseInt(match[2], 10) : undefined;
54
- const key = `${file}:${line || ""}`;
55
-
56
- if (!seen.has(key) && !file.includes("node_modules")) {
57
- seen.add(key);
58
- refs.push({ file, line });
59
- }
60
- match = pattern.exec(content);
61
- }
62
- }
63
-
64
- return refs;
65
- }
66
-
67
- export default tool({
68
- description: `Create a structured observation for future reference.
69
-
70
- Purpose:
71
- - Capture decisions, bugs, features, patterns, discoveries, learnings, or warnings
72
- - Auto-detects file references from content (file:line, \`path\`, src/, .opencode/)
73
- - Stores in SQLite with FTS5 index for fast search
74
- - Supports enhanced schema: facts, subtitle, files_read/files_modified
75
-
76
- Confidence guidance:
77
- - high: verified by tests, logs, or direct inspection (default)
78
- - medium: likely, but not fully verified
79
- - low: uncertain or speculative
80
-
81
- Type-specific examples:
82
- decision
83
- observation({
84
- type: "decision",
85
- title: "Use JWT for auth",
86
- narrative: "Chose JWT for stateless auth across services.",
87
- facts: "stateless, scalable",
88
- concepts: "authentication, jwt",
89
- confidence: "high"
90
- })
91
-
92
- bugfix
93
- observation({
94
- type: "bugfix",
95
- title: "Fix null pointer on login",
96
- narrative: "Guarded optional user in src/auth.ts:42 to prevent crash.",
97
- files_modified: "src/auth.ts",
98
- concepts: "auth, null-check",
99
- confidence: "high"
100
- })
101
-
102
- feature
103
- observation({
104
- type: "feature",
105
- title: "Add CLI --dry-run",
106
- narrative: "Introduce dry-run mode to show planned changes without writing.",
107
- files_modified: "src/commands/init.ts",
108
- concepts: "cli, ux",
109
- confidence: "medium"
110
- })
111
-
112
- pattern
113
- observation({
114
- type: "pattern",
115
- title: "Use zod for input validation",
116
- narrative: "All command inputs validated with zod schemas before execute.",
117
- concepts: "validation, zod",
118
- confidence: "high"
119
- })
120
-
121
- discovery
122
- observation({
123
- type: "discovery",
124
- title: "Build copies .opencode/ to dist/template/",
125
- narrative: "Found rsync step in build.ts that bundles .opencode/.",
126
- files_read: "build.ts",
127
- confidence: "high"
128
- })
129
-
130
- learning
131
- observation({
132
- type: "learning",
133
- title: "Bun test respects --watch",
134
- narrative: "Observed bun test --watch keeps runner active during edits.",
135
- confidence: "medium"
136
- })
137
-
138
- warning
139
- observation({
140
- type: "warning",
141
- title: "Do not edit dist/ directly",
142
- narrative: "dist/ is built output and overwritten on build.",
143
- concepts: "build, generated",
144
- confidence: "high"
145
- })`,
146
- args: {
147
- type: tool.schema
148
- .string()
149
- .describe(
150
- "Observation type: decision, bugfix, feature, pattern, discovery, learning, warning",
151
- ),
152
- title: tool.schema.string().describe("Brief title for the observation"),
153
- subtitle: tool.schema
154
- .string()
155
- .optional()
156
- .describe("Optional subtitle or tagline"),
157
- facts: tool.schema
158
- .string()
159
- .optional()
160
- .describe("Comma-separated key facts (e.g., 'stateless, scalable')"),
161
- narrative: tool.schema
162
- .string()
163
- .optional()
164
- .describe("Detailed observation content with context"),
165
- content: tool.schema
166
- .string()
167
- .optional()
168
- .describe(
169
- "DEPRECATED: Use 'narrative' instead. Alias for backward compat.",
170
- ),
171
- concepts: tool.schema
172
- .string()
173
- .optional()
174
- .describe(
175
- "Comma-separated concept tags (e.g., 'authentication, oauth, security')",
176
- ),
177
- files_read: tool.schema
178
- .string()
179
- .optional()
180
- .describe("Comma-separated files that were read (e.g., 'src/auth.ts')"),
181
- files_modified: tool.schema
182
- .string()
183
- .optional()
184
- .describe("Comma-separated files that were modified"),
185
- files: tool.schema
186
- .string()
187
- .optional()
188
- .describe(
189
- "DEPRECATED: Use 'files_modified' instead. Alias for backward compat.",
190
- ),
191
- bead_id: tool.schema
192
- .string()
193
- .optional()
194
- .describe("Related bead ID for traceability"),
195
- confidence: tool.schema
196
- .string()
197
- .optional()
198
- .describe(
199
- "Confidence level: high (verified), medium (likely), low (uncertain). Defaults to high.",
200
- ),
201
- supersedes: tool.schema
202
- .string()
203
- .optional()
204
- .describe(
205
- "ID or filename of observation this supersedes (for contradiction handling)",
206
- ),
207
- },
208
- execute: async (args: {
209
- type: string;
210
- title: string;
211
- subtitle?: string;
212
- facts?: string;
213
- narrative?: string;
214
- content?: string;
215
- concepts?: string;
216
- files_read?: string;
217
- files_modified?: string;
218
- files?: string;
219
- bead_id?: string;
220
- confidence?: string;
221
- supersedes?: string;
222
- }) => {
223
- // Validate type
224
- const validTypes: ObservationType[] = [
225
- "decision",
226
- "bugfix",
227
- "feature",
228
- "pattern",
229
- "discovery",
230
- "learning",
231
- "warning",
232
- ];
233
- const obsType = args.type.toLowerCase() as ObservationType;
234
- if (!validTypes.includes(obsType)) {
235
- return `Error: Invalid observation type '${args.type}'.\nValid types: ${validTypes.join(", ")}`;
236
- }
237
-
238
- // Validate confidence level
239
- const validConfidence: ConfidenceLevel[] = ["high", "medium", "low"];
240
- const confidence = (args.confidence?.toLowerCase() ||
241
- "high") as ConfidenceLevel;
242
- if (!validConfidence.includes(confidence)) {
243
- return `Error: Invalid confidence level '${args.confidence}'.\nValid levels: ${validConfidence.join(", ")}`;
244
- }
245
-
246
- // Handle deprecated fields (backward compat)
247
- const narrative = args.narrative || args.content || "";
248
- const filesModifiedRaw = args.files_modified || args.files || "";
249
-
250
- // Parse arrays from comma-separated strings
251
- const facts = args.facts
252
- ? args.facts
253
- .split(",")
254
- .map((f) => f.trim())
255
- .filter(Boolean)
256
- : [];
257
- const concepts = args.concepts
258
- ? args.concepts
259
- .split(",")
260
- .map((c) => c.trim())
261
- .filter(Boolean)
262
- : [];
263
- let filesRead = args.files_read
264
- ? args.files_read
265
- .split(",")
266
- .map((f) => f.trim())
267
- .filter(Boolean)
268
- : [];
269
- const filesModified = filesModifiedRaw
270
- ? filesModifiedRaw
271
- .split(",")
272
- .map((f) => f.trim())
273
- .filter(Boolean)
274
- : [];
275
-
276
- // Auto-detect file references from narrative
277
- const detectedRefs = extractFileReferences(narrative);
278
- const detectedFiles = detectedRefs.map((r) => r.file);
279
-
280
- // Merge detected files with explicitly provided files
281
- filesRead = [...new Set([...filesRead, ...detectedFiles])];
282
-
283
- // Parse supersedes (could be numeric ID or filename)
284
- let supersedesId: number | undefined;
285
- if (args.supersedes) {
286
- const parsed = Number.parseInt(args.supersedes, 10);
287
- if (!Number.isNaN(parsed)) {
288
- supersedesId = parsed;
289
- }
290
- }
291
-
292
- // Prepare observation input
293
- const input: ObservationInput = {
294
- type: obsType,
295
- title: args.title,
296
- subtitle: args.subtitle,
297
- facts: facts.length > 0 ? facts : undefined,
298
- narrative: narrative || undefined,
299
- concepts: concepts.length > 0 ? concepts : undefined,
300
- files_read: filesRead.length > 0 ? filesRead : undefined,
301
- files_modified: filesModified.length > 0 ? filesModified : undefined,
302
- confidence,
303
- bead_id: args.bead_id,
304
- supersedes: supersedesId,
305
- };
306
-
307
- try {
308
- // Store in SQLite (single source of truth)
309
- const sqliteId = storeObservation(input);
310
-
311
- // Update bead notes if bead_id provided
312
- let beadUpdate = "";
313
- if (args.bead_id) {
314
- try {
315
- const { execSync } = await import("node:child_process");
316
- const noteContent = `${TYPE_ICONS[obsType]} ${obsType}: ${args.title}`;
317
- execSync(
318
- `br edit ${args.bead_id} --note "${noteContent.replace(/"/g, '\\"')}"`,
319
- {
320
- cwd: process.cwd(),
321
- encoding: "utf-8",
322
- timeout: 5000,
323
- },
324
- );
325
- beadUpdate = `\nBead updated: ${args.bead_id}`;
326
- } catch {
327
- beadUpdate = `\nWarning: Could not update bead ${args.bead_id}`;
328
- }
329
- }
330
-
331
- // Build output
332
- const icon = TYPE_ICONS[obsType];
333
- const confIcon = CONFIDENCE_ICONS[confidence];
334
-
335
- let output = `✓ Observation #${sqliteId} saved\n\n`;
336
- output += `**Type**: ${icon} ${obsType}\n`;
337
- output += `**Title**: ${args.title}\n`;
338
- output += `**Confidence**: ${confIcon} ${confidence}\n`;
339
-
340
- if (concepts.length > 0) {
341
- output += `**Concepts**: ${concepts.join(", ")}\n`;
342
- }
343
- if (facts.length > 0) {
344
- output += `**Facts**: ${facts.length} extracted\n`;
345
- }
346
-
347
- output += beadUpdate;
348
-
349
- return output;
350
- } catch (error) {
351
- if (error instanceof Error) {
352
- return `Error saving observation: ${error.message}`;
353
- }
354
- return "Unknown error saving observation";
355
- }
356
- },
357
- });