opencodekit 0.23.1 → 0.23.3
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 +354 -825
- package/dist/template/.opencode/AGENTS.md +15 -2
- package/dist/template/.opencode/command/init.md +198 -34
- package/dist/template/.opencode/context/fallow.md +137 -0
- package/dist/template/.opencode/opencode.json +12 -315
- package/dist/template/.opencode/plugin/codesearch.ts +730 -0
- package/dist/template/.opencode/plugin/memory/compile.ts +171 -186
- package/dist/template/.opencode/plugin/memory/index-generator.ts +118 -133
- package/dist/template/.opencode/plugin/memory/lint.ts +253 -275
- package/dist/template/.opencode/plugin/memory/tools.ts +224 -268
- package/dist/template/.opencode/plugin/memory/validate.ts +154 -164
- package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/web-search-preview.ts +13 -30
- package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/web-search-shared.ts +25 -0
- package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/web-search.ts +17 -34
- package/dist/template/.opencode/plugin/session-summary.ts +0 -2
- package/dist/template/.opencode/plugin/srcwalk.ts +646 -667
- package/dist/template/.opencode/skill/code-navigation/SKILL.md +10 -10
- package/dist/template/.opencode/skill/code-review-and-quality/SKILL.md +1 -1
- package/dist/template/.opencode/skill/condition-based-waiting/example.ts +15 -2
- package/dist/template/.opencode/skill/debugging-and-error-recovery/SKILL.md +1 -1
- package/dist/template/.opencode/skill/deep-module-design/SKILL.md +1 -1
- package/dist/template/.opencode/skill/fallow/SKILL.md +409 -0
- package/dist/template/.opencode/skill/fallow/references/cli-reference.md +1905 -0
- package/dist/template/.opencode/skill/fallow/references/gotchas.md +644 -0
- package/dist/template/.opencode/skill/fallow/references/patterns.md +791 -0
- package/dist/template/.opencode/skill/planning-and-task-breakdown/SKILL.md +1 -1
- package/dist/template/.opencode/skill/srcwalk/SKILL.md +10 -13
- package/dist/template/.opencode/skill/ubiquitous-language/SKILL.md +1 -1
- package/dist/template/.opencode/tool/grepsearch.ts +92 -103
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { upsertMemoryFile } from "./db/maintenance.js";
|
|
12
12
|
import type { ObservationRow } from "./db/types.js";
|
|
13
|
-
import { getMemoryDB } from "./db.js";
|
|
13
|
+
import { getMemoryDB } from "./db/schema.js";
|
|
14
14
|
import { TYPE_ICONS, parseConcepts } from "./helpers.js";
|
|
15
15
|
|
|
16
16
|
// ============================================================================
|
|
@@ -18,17 +18,17 @@ import { TYPE_ICONS, parseConcepts } from "./helpers.js";
|
|
|
18
18
|
// ============================================================================
|
|
19
19
|
|
|
20
20
|
export interface IndexEntry {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
id: number;
|
|
22
|
+
type: string;
|
|
23
|
+
title: string;
|
|
24
|
+
concepts: string[];
|
|
25
|
+
created_at: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export interface IndexResult {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
entryCount: number;
|
|
30
|
+
conceptCount: number;
|
|
31
|
+
content: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// ============================================================================
|
|
@@ -40,131 +40,116 @@ export interface IndexResult {
|
|
|
40
40
|
* Groups by type, lists concept clusters, and writes to memory_files.
|
|
41
41
|
*/
|
|
42
42
|
export function generateMemoryIndex(): IndexResult {
|
|
43
|
-
|
|
43
|
+
const db = getMemoryDB();
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
const observations = db
|
|
46
|
+
.query(
|
|
47
|
+
`SELECT id, type, title, concepts, created_at FROM observations
|
|
48
48
|
WHERE superseded_by IS NULL
|
|
49
49
|
ORDER BY type, created_at_epoch DESC`,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
lines.push("");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const content = lines.join("\n");
|
|
160
|
-
|
|
161
|
-
// Store in memory_files
|
|
162
|
-
upsertMemoryFile("index", content, "replace");
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
entryCount: observations.length,
|
|
166
|
-
conceptCount: allConcepts.size,
|
|
167
|
-
content,
|
|
168
|
-
};
|
|
50
|
+
)
|
|
51
|
+
.all() as Pick<ObservationRow, "id" | "type" | "title" | "concepts" | "created_at">[];
|
|
52
|
+
|
|
53
|
+
// Group by type
|
|
54
|
+
const byType = new Map<string, IndexEntry[]>();
|
|
55
|
+
const allConcepts = new Map<string, number[]>();
|
|
56
|
+
|
|
57
|
+
for (const obs of observations) {
|
|
58
|
+
const entry: IndexEntry = {
|
|
59
|
+
id: obs.id,
|
|
60
|
+
type: obs.type,
|
|
61
|
+
title: obs.title,
|
|
62
|
+
concepts: parseConcepts(obs.concepts),
|
|
63
|
+
created_at: obs.created_at,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const group = byType.get(obs.type) ?? [];
|
|
67
|
+
group.push(entry);
|
|
68
|
+
byType.set(obs.type, group);
|
|
69
|
+
|
|
70
|
+
for (const concept of entry.concepts) {
|
|
71
|
+
const ids = allConcepts.get(concept) ?? [];
|
|
72
|
+
ids.push(obs.id);
|
|
73
|
+
allConcepts.set(concept, ids);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Build markdown
|
|
78
|
+
const lines: string[] = [];
|
|
79
|
+
lines.push("# Memory Index");
|
|
80
|
+
lines.push("");
|
|
81
|
+
lines.push(`> Auto-generated catalog of ${observations.length} active observations.`);
|
|
82
|
+
lines.push(`> Last updated: ${new Date().toISOString().slice(0, 19)}`);
|
|
83
|
+
lines.push("");
|
|
84
|
+
|
|
85
|
+
// Summary table
|
|
86
|
+
lines.push("## Summary");
|
|
87
|
+
lines.push("");
|
|
88
|
+
lines.push("| Type | Count |");
|
|
89
|
+
lines.push("|------|-------|");
|
|
90
|
+
for (const [type, entries] of byType) {
|
|
91
|
+
const icon = TYPE_ICONS[type] ?? "📌";
|
|
92
|
+
lines.push(`| ${icon} ${type} | ${entries.length} |`);
|
|
93
|
+
}
|
|
94
|
+
lines.push(`| **Total** | **${observations.length}** |`);
|
|
95
|
+
lines.push("");
|
|
96
|
+
|
|
97
|
+
// By type
|
|
98
|
+
for (const [type, entries] of byType) {
|
|
99
|
+
const icon = TYPE_ICONS[type] ?? "📌";
|
|
100
|
+
lines.push(`## ${icon} ${type.charAt(0).toUpperCase() + type.slice(1)} (${entries.length})`);
|
|
101
|
+
lines.push("");
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
const concepts = entry.concepts.length > 0 ? ` [${entry.concepts.join(", ")}]` : "";
|
|
104
|
+
lines.push(
|
|
105
|
+
`- **#${entry.id}** ${entry.title}${concepts} _(${entry.created_at.slice(0, 10)})_`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
lines.push("");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Concept clusters
|
|
112
|
+
const significantConcepts = [...allConcepts.entries()]
|
|
113
|
+
.filter(([, ids]) => ids.length >= 2)
|
|
114
|
+
.sort((a, b) => b[1].length - a[1].length);
|
|
115
|
+
|
|
116
|
+
if (significantConcepts.length > 0) {
|
|
117
|
+
lines.push("## Concept Clusters");
|
|
118
|
+
lines.push("");
|
|
119
|
+
lines.push("Concepts appearing in 2+ observations:");
|
|
120
|
+
lines.push("");
|
|
121
|
+
for (const [concept, ids] of significantConcepts.slice(0, 30)) {
|
|
122
|
+
lines.push(`- **${concept}** (${ids.length}): ${ids.map((id) => `#${id}`).join(", ")}`);
|
|
123
|
+
}
|
|
124
|
+
lines.push("");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Orphan concepts
|
|
128
|
+
const orphanConcepts = [...allConcepts.entries()].filter(([, ids]) => ids.length === 1);
|
|
129
|
+
|
|
130
|
+
if (orphanConcepts.length > 0) {
|
|
131
|
+
lines.push("## Orphan Concepts");
|
|
132
|
+
lines.push("");
|
|
133
|
+
lines.push(`${orphanConcepts.length} concepts appear in only 1 observation:`);
|
|
134
|
+
lines.push("");
|
|
135
|
+
const orphanList = orphanConcepts
|
|
136
|
+
.slice(0, 20)
|
|
137
|
+
.map(([concept, ids]) => `${concept} (#${ids[0]})`);
|
|
138
|
+
lines.push(orphanList.join(", "));
|
|
139
|
+
if (orphanConcepts.length > 20) {
|
|
140
|
+
lines.push(`... and ${orphanConcepts.length - 20} more`);
|
|
141
|
+
}
|
|
142
|
+
lines.push("");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const content = lines.join("\n");
|
|
146
|
+
|
|
147
|
+
// Store in memory_files
|
|
148
|
+
upsertMemoryFile("index", content, "replace");
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
entryCount: observations.length,
|
|
152
|
+
conceptCount: allConcepts.size,
|
|
153
|
+
content,
|
|
154
|
+
};
|
|
169
155
|
}
|
|
170
|
-
|