context-eng 0.1.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.
- package/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/categories.d.ts +27 -0
- package/dist/categories.js +71 -0
- package/dist/categories.js.map +1 -0
- package/dist/cli-entry.d.ts +2 -0
- package/dist/cli-entry.js +7 -0
- package/dist/cli-entry.js.map +1 -0
- package/dist/cli.d.ts +30 -0
- package/dist/cli.js +327 -0
- package/dist/cli.js.map +1 -0
- package/dist/db.d.ts +40 -0
- package/dist/db.js +158 -0
- package/dist/db.js.map +1 -0
- package/dist/engine.d.ts +149 -0
- package/dist/engine.js +589 -0
- package/dist/engine.js.map +1 -0
- package/dist/harness.d.ts +56 -0
- package/dist/harness.js +358 -0
- package/dist/harness.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect-cli.d.ts +2 -0
- package/dist/inspect-cli.js +96 -0
- package/dist/inspect-cli.js.map +1 -0
- package/dist/inspect.d.ts +33 -0
- package/dist/inspect.js +149 -0
- package/dist/inspect.js.map +1 -0
- package/dist/map.d.ts +39 -0
- package/dist/map.js +106 -0
- package/dist/map.js.map +1 -0
- package/dist/mcp.d.ts +5 -0
- package/dist/mcp.js +348 -0
- package/dist/mcp.js.map +1 -0
- package/dist/migrate.d.ts +7 -0
- package/dist/migrate.js +107 -0
- package/dist/migrate.js.map +1 -0
- package/dist/paths.d.ts +29 -0
- package/dist/paths.js +69 -0
- package/dist/paths.js.map +1 -0
- package/dist/search.d.ts +144 -0
- package/dist/search.js +449 -0
- package/dist/search.js.map +1 -0
- package/dist/secrets.d.ts +28 -0
- package/dist/secrets.js +135 -0
- package/dist/secrets.js.map +1 -0
- package/dist/text.d.ts +22 -0
- package/dist/text.js +153 -0
- package/dist/text.js.map +1 -0
- package/dist/tokens.d.ts +6 -0
- package/dist/tokens.js +15 -0
- package/dist/tokens.js.map +1 -0
- package/dist/typesafe.d.ts +40 -0
- package/dist/typesafe.js +170 -0
- package/dist/typesafe.js.map +1 -0
- package/package.json +51 -0
- package/system_prompts/AGENTS.md +14 -0
- package/system_prompts/CLAUDE.md +14 -0
- package/system_prompts/rules.md +157 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createInterface } from "node:readline/promises";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { parseArgs } from "node:util";
|
|
7
|
+
import { Engine } from "./engine.js";
|
|
8
|
+
import { detectHarnesses, formatHarnessReport, installDetectedHarnesses, pathHasCommand, promptHarnessChoice, } from "./harness.js";
|
|
9
|
+
import { runStdio } from "./mcp.js";
|
|
10
|
+
import { resolveProjectPath } from "./paths.js";
|
|
11
|
+
import { ensureTypeSafeKey, loadTypeSafeApiKey, openOsKeychain } from "./secrets.js";
|
|
12
|
+
import { TypeSafeRelevanceEvaluator } from "./typesafe.js";
|
|
13
|
+
const MARKER_START = "<!-- context-eng:start -->";
|
|
14
|
+
const MARKER_END = "<!-- context-eng:end -->";
|
|
15
|
+
const CURSOR_RULE_FILE = "context-eng-memory.mdc";
|
|
16
|
+
const CURSOR_RULE_FRONTMATTER = `---
|
|
17
|
+
description: Use context-eng MCP memory tools for local project memory.
|
|
18
|
+
alwaysApply: true
|
|
19
|
+
---
|
|
20
|
+
`;
|
|
21
|
+
const RULE_SCOPES = ["global", "project", "both"];
|
|
22
|
+
const CLAUDE_RULE_FILE = "context-eng-memory.md";
|
|
23
|
+
const USAGE = `Usage:
|
|
24
|
+
context-eng mcp [--project <path>]
|
|
25
|
+
context-eng init [--project <path>] [--yes]
|
|
26
|
+
context-eng init --codex-only
|
|
27
|
+
context-eng init --cursor-only [--scope global|project|both] [--project <path>]
|
|
28
|
+
context-eng init --claude-only [--scope global|project|both] [--project <path>]
|
|
29
|
+
`;
|
|
30
|
+
export function upsertMarkedBlock(existing, block) {
|
|
31
|
+
const unit = block.trimEnd();
|
|
32
|
+
if (existing == null || existing.trim() === "") {
|
|
33
|
+
return `${unit}\n`;
|
|
34
|
+
}
|
|
35
|
+
const start = existing.indexOf(MARKER_START);
|
|
36
|
+
const end = existing.indexOf(MARKER_END);
|
|
37
|
+
if (start !== -1 && end !== -1 && end > start) {
|
|
38
|
+
const before = existing.slice(0, start);
|
|
39
|
+
const after = existing.slice(end + MARKER_END.length);
|
|
40
|
+
const out = `${before}${unit}${after}`;
|
|
41
|
+
return out.endsWith("\n") ? out : `${out}\n`;
|
|
42
|
+
}
|
|
43
|
+
const head = existing.replace(/\s+$/, "");
|
|
44
|
+
return `${head}\n\n${unit}\n`;
|
|
45
|
+
}
|
|
46
|
+
function repoRoot() {
|
|
47
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
48
|
+
}
|
|
49
|
+
export function agentPointerBlock() {
|
|
50
|
+
const raw = readFileSync(path.join(repoRoot(), "system_prompts", "AGENTS.md"), "utf8");
|
|
51
|
+
const start = raw.indexOf(MARKER_START);
|
|
52
|
+
const end = raw.indexOf(MARKER_END);
|
|
53
|
+
const inner = start !== -1 && end !== -1 && end > start
|
|
54
|
+
? raw.slice(start + MARKER_START.length, end)
|
|
55
|
+
: raw;
|
|
56
|
+
const adapted = inner
|
|
57
|
+
.replaceAll("memory.search", "memory_search")
|
|
58
|
+
.replaceAll("memory.create", "memory_create")
|
|
59
|
+
.replaceAll("memory.delete", "memory_delete")
|
|
60
|
+
.replaceAll("memory.edit", "memory_edit")
|
|
61
|
+
.replaceAll("memory.map", "memory_map")
|
|
62
|
+
.replaceAll("memory.promote", "memory_promote")
|
|
63
|
+
.replaceAll("memory.demote", "memory_demote")
|
|
64
|
+
.trim();
|
|
65
|
+
return `${MARKER_START}\n${adapted}\n${MARKER_END}\n`;
|
|
66
|
+
}
|
|
67
|
+
function writePointer(file, block) {
|
|
68
|
+
const existing = existsSync(file) ? readFileSync(file, "utf8") : null;
|
|
69
|
+
writeFileSync(file, upsertMarkedBlock(existing, block), "utf8");
|
|
70
|
+
}
|
|
71
|
+
export function updateExistingPointer(file, block) {
|
|
72
|
+
if (!existsSync(file))
|
|
73
|
+
return false;
|
|
74
|
+
writePointer(file, block);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
function usage(exitCode = 1) {
|
|
78
|
+
(exitCode === 0 ? console.log : console.error)(USAGE);
|
|
79
|
+
process.exit(exitCode);
|
|
80
|
+
}
|
|
81
|
+
function engineOpts(project) {
|
|
82
|
+
if (project !== undefined)
|
|
83
|
+
return { projectPath: project };
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
export function codexAgentsPath(home = os.homedir()) {
|
|
87
|
+
return path.join(home, ".codex", "AGENTS.md");
|
|
88
|
+
}
|
|
89
|
+
export function writeCodexAgentsPointer(block, home = os.homedir()) {
|
|
90
|
+
const file = codexAgentsPath(home);
|
|
91
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
92
|
+
writePointer(file, block);
|
|
93
|
+
return file;
|
|
94
|
+
}
|
|
95
|
+
export function globalCursorRulePath(home = os.homedir()) {
|
|
96
|
+
return path.join(home, ".cursor", "rules", CURSOR_RULE_FILE);
|
|
97
|
+
}
|
|
98
|
+
export function cursorRulePath(projectPath) {
|
|
99
|
+
return path.join(projectPath, ".cursor", "rules", CURSOR_RULE_FILE);
|
|
100
|
+
}
|
|
101
|
+
export function resolveRuleScope(scope, project) {
|
|
102
|
+
if (scope !== undefined) {
|
|
103
|
+
if (!RULE_SCOPES.includes(scope)) {
|
|
104
|
+
throw new Error(`scope must be one of: ${RULE_SCOPES.join(", ")}`);
|
|
105
|
+
}
|
|
106
|
+
return scope;
|
|
107
|
+
}
|
|
108
|
+
if (project !== undefined)
|
|
109
|
+
return "project";
|
|
110
|
+
return "global";
|
|
111
|
+
}
|
|
112
|
+
export const resolveCursorRuleScope = resolveRuleScope;
|
|
113
|
+
function splitCursorRule(existing) {
|
|
114
|
+
if (existing.startsWith("---\n")) {
|
|
115
|
+
const end = existing.indexOf("\n---\n", 4);
|
|
116
|
+
if (end !== -1) {
|
|
117
|
+
return {
|
|
118
|
+
frontmatter: existing.slice(0, end + 5),
|
|
119
|
+
body: existing.slice(end + 5),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return { frontmatter: CURSOR_RULE_FRONTMATTER.trimEnd(), body: existing };
|
|
124
|
+
}
|
|
125
|
+
export function writeCursorRuleFile(block, file) {
|
|
126
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
127
|
+
const existing = existsSync(file) ? readFileSync(file, "utf8") : null;
|
|
128
|
+
if (existing == null || existing.trim() === "") {
|
|
129
|
+
writeFileSync(file, `${CURSOR_RULE_FRONTMATTER}\n${block.trimEnd()}\n`, "utf8");
|
|
130
|
+
return file;
|
|
131
|
+
}
|
|
132
|
+
const { frontmatter, body } = splitCursorRule(existing);
|
|
133
|
+
const nextBody = upsertMarkedBlock(body.trim() === "" ? null : body, block);
|
|
134
|
+
writeFileSync(file, `${frontmatter}\n${nextBody}`, "utf8");
|
|
135
|
+
return file;
|
|
136
|
+
}
|
|
137
|
+
export function writeCursorRule(block, projectPath) {
|
|
138
|
+
return writeCursorRuleFile(block, cursorRulePath(projectPath));
|
|
139
|
+
}
|
|
140
|
+
export function writeCursorRules(block, opts) {
|
|
141
|
+
const files = [];
|
|
142
|
+
const home = opts.home ?? os.homedir();
|
|
143
|
+
if (opts.scope === "global" || opts.scope === "both") {
|
|
144
|
+
files.push(writeCursorRuleFile(block, globalCursorRulePath(home)));
|
|
145
|
+
}
|
|
146
|
+
if (opts.scope === "project" || opts.scope === "both") {
|
|
147
|
+
if (opts.project === undefined) {
|
|
148
|
+
throw new Error("scope project or both requires --project <path>");
|
|
149
|
+
}
|
|
150
|
+
files.push(writeCursorRuleFile(block, cursorRulePath(resolveProjectPath(opts.project))));
|
|
151
|
+
}
|
|
152
|
+
return files;
|
|
153
|
+
}
|
|
154
|
+
export function globalClaudeAgentsPath(home = os.homedir()) {
|
|
155
|
+
return path.join(home, ".claude", "CLAUDE.md");
|
|
156
|
+
}
|
|
157
|
+
export function writeGlobalClaudePointer(block, home = os.homedir()) {
|
|
158
|
+
const file = globalClaudeAgentsPath(home);
|
|
159
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
160
|
+
writePointer(file, block);
|
|
161
|
+
return file;
|
|
162
|
+
}
|
|
163
|
+
export function claudeRulePath(projectPath) {
|
|
164
|
+
return path.join(projectPath, ".claude", "rules", CLAUDE_RULE_FILE);
|
|
165
|
+
}
|
|
166
|
+
export function writeClaudeRuleFile(block, file) {
|
|
167
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
168
|
+
writePointer(file, block);
|
|
169
|
+
return file;
|
|
170
|
+
}
|
|
171
|
+
export function writeClaudeRule(block, projectPath) {
|
|
172
|
+
return writeClaudeRuleFile(block, claudeRulePath(projectPath));
|
|
173
|
+
}
|
|
174
|
+
export function writeClaudeRules(block, opts) {
|
|
175
|
+
const files = [];
|
|
176
|
+
const home = opts.home ?? os.homedir();
|
|
177
|
+
if (opts.scope === "global" || opts.scope === "both") {
|
|
178
|
+
files.push(writeGlobalClaudePointer(block, home));
|
|
179
|
+
}
|
|
180
|
+
if (opts.scope === "project" || opts.scope === "both") {
|
|
181
|
+
if (opts.project === undefined) {
|
|
182
|
+
throw new Error("scope project or both requires --project <path>");
|
|
183
|
+
}
|
|
184
|
+
files.push(writeClaudeRuleFile(block, claudeRulePath(resolveProjectPath(opts.project))));
|
|
185
|
+
}
|
|
186
|
+
return files;
|
|
187
|
+
}
|
|
188
|
+
async function confirmHarnessReplacement(id, file) {
|
|
189
|
+
const prompt = createInterface({ input: process.stdin, output: process.stdout });
|
|
190
|
+
try {
|
|
191
|
+
const answer = await prompt.question(`${id} already has a different context-eng server in ${file}. Replace it? [y/N] `);
|
|
192
|
+
return /^y(?:es)?$/i.test(answer.trim());
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
prompt.close();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
export async function main() {
|
|
202
|
+
let values;
|
|
203
|
+
let positionals;
|
|
204
|
+
try {
|
|
205
|
+
const parsed = parseArgs({
|
|
206
|
+
args: process.argv.slice(2),
|
|
207
|
+
options: {
|
|
208
|
+
project: { type: "string" },
|
|
209
|
+
scope: { type: "string" },
|
|
210
|
+
help: { type: "boolean", short: "h" },
|
|
211
|
+
yes: { type: "boolean" },
|
|
212
|
+
"codex-only": { type: "boolean" },
|
|
213
|
+
"cursor-only": { type: "boolean" },
|
|
214
|
+
"claude-only": { type: "boolean" },
|
|
215
|
+
},
|
|
216
|
+
allowPositionals: true,
|
|
217
|
+
strict: true,
|
|
218
|
+
});
|
|
219
|
+
values = parsed.values;
|
|
220
|
+
positionals = parsed.positionals;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
usage();
|
|
224
|
+
}
|
|
225
|
+
if (values.help)
|
|
226
|
+
usage(0);
|
|
227
|
+
if (positionals.length !== 1) {
|
|
228
|
+
usage();
|
|
229
|
+
}
|
|
230
|
+
const command = positionals[0];
|
|
231
|
+
if (command !== "mcp" && command !== "init") {
|
|
232
|
+
usage();
|
|
233
|
+
}
|
|
234
|
+
if (command === "mcp") {
|
|
235
|
+
const loaded = await loadTypeSafeApiKey();
|
|
236
|
+
if (loaded.warning)
|
|
237
|
+
console.error(loaded.warning);
|
|
238
|
+
const engine = new Engine({
|
|
239
|
+
...engineOpts(values.project),
|
|
240
|
+
deferProject: values.project === undefined,
|
|
241
|
+
});
|
|
242
|
+
await runStdio(engine, new TypeSafeRelevanceEvaluator({ apiKey: loaded.apiKey }));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (values["codex-only"] || values["cursor-only"] || values["claude-only"]) {
|
|
246
|
+
const block = agentPointerBlock();
|
|
247
|
+
if (values["codex-only"]) {
|
|
248
|
+
console.log(`Updated ${writeCodexAgentsPointer(block)}`);
|
|
249
|
+
}
|
|
250
|
+
const scopedOpts = values.project === undefined
|
|
251
|
+
? undefined
|
|
252
|
+
: { project: values.project };
|
|
253
|
+
if (values["cursor-only"]) {
|
|
254
|
+
const scope = resolveRuleScope(values.scope, values.project);
|
|
255
|
+
const cursorOpts = scopedOpts === undefined ? { scope } : { scope, ...scopedOpts };
|
|
256
|
+
for (const file of writeCursorRules(block, cursorOpts)) {
|
|
257
|
+
console.log(`Updated ${file}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (values["claude-only"]) {
|
|
261
|
+
const scope = resolveRuleScope(values.scope, values.project);
|
|
262
|
+
const claudeOpts = scopedOpts === undefined ? { scope } : { scope, ...scopedOpts };
|
|
263
|
+
for (const file of writeClaudeRules(block, claudeOpts)) {
|
|
264
|
+
console.log(`Updated ${file}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const projectPath = resolveProjectPath(values.project);
|
|
270
|
+
if (!existsSync(projectPath) || !statSync(projectPath).isDirectory()) {
|
|
271
|
+
throw new Error(`project path must be an existing directory: ${projectPath}`);
|
|
272
|
+
}
|
|
273
|
+
await ensureTypeSafeKey({
|
|
274
|
+
store: await openOsKeychain(),
|
|
275
|
+
interactive: process.stdin.isTTY === true,
|
|
276
|
+
});
|
|
277
|
+
const engine = new Engine({ projectPath });
|
|
278
|
+
try {
|
|
279
|
+
const block = agentPointerBlock();
|
|
280
|
+
const projectAgents = path.join(engine.layout.projectPath, "AGENTS.md");
|
|
281
|
+
const projectClaude = path.join(engine.layout.projectPath, "CLAUDE.md");
|
|
282
|
+
const canWriteGlobal = process.stdin.isTTY === true || values.yes === true;
|
|
283
|
+
const globalCodexAgents = canWriteGlobal ? writeCodexAgentsPointer(block) : undefined;
|
|
284
|
+
const projectAgentsUpdated = updateExistingPointer(projectAgents, block);
|
|
285
|
+
const projectClaudeUpdated = updateExistingPointer(projectClaude, block);
|
|
286
|
+
console.log("");
|
|
287
|
+
console.log("Agent pointers");
|
|
288
|
+
if (projectAgentsUpdated)
|
|
289
|
+
console.log(` project AGENTS.md: ${projectAgents}`);
|
|
290
|
+
if (projectClaudeUpdated)
|
|
291
|
+
console.log(` project CLAUDE.md: ${projectClaude}`);
|
|
292
|
+
if (globalCodexAgents)
|
|
293
|
+
console.log(` codex AGENTS.md: ${globalCodexAgents}`);
|
|
294
|
+
console.log("");
|
|
295
|
+
console.log("Data layout");
|
|
296
|
+
console.log(` home: ${engine.layout.home}`);
|
|
297
|
+
console.log(` projectDir: ${engine.layout.projectDir}`);
|
|
298
|
+
console.log(` projectKey: ${engine.layout.projectKey}`);
|
|
299
|
+
console.log("");
|
|
300
|
+
const home = os.homedir();
|
|
301
|
+
const installed = detectHarnesses({ home, hasCommand: pathHasCommand })
|
|
302
|
+
.filter((hit) => hit.installed)
|
|
303
|
+
.map((hit) => hit.id);
|
|
304
|
+
const selected = values.yes === true
|
|
305
|
+
? installed
|
|
306
|
+
: process.stdin.isTTY === true
|
|
307
|
+
? await promptHarnessChoice(installed)
|
|
308
|
+
: [];
|
|
309
|
+
const report = await installDetectedHarnesses({
|
|
310
|
+
home,
|
|
311
|
+
hasCommand: pathHasCommand,
|
|
312
|
+
selected,
|
|
313
|
+
...(process.stdin.isTTY === true && values.yes !== true
|
|
314
|
+
? { confirmReplace: confirmHarnessReplacement }
|
|
315
|
+
: {}),
|
|
316
|
+
});
|
|
317
|
+
const claude = report.harnesses.find((item) => item.id === "claude");
|
|
318
|
+
if (canWriteGlobal && claude?.installed && !claude.skipped && !claude.error && !claude.preserved) {
|
|
319
|
+
console.log(` global Claude instructions: ${writeGlobalClaudePointer(block, home)}`);
|
|
320
|
+
}
|
|
321
|
+
console.log(formatHarnessReport(report));
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
engine.close();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/db.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
export type Db = Database.Database;
|
|
3
|
+
export declare function nowSeconds(): number;
|
|
4
|
+
export interface MemoryRow {
|
|
5
|
+
id: string;
|
|
6
|
+
project_id: string;
|
|
7
|
+
chat_id: string | null;
|
|
8
|
+
category: string;
|
|
9
|
+
content: string;
|
|
10
|
+
subject: string | null;
|
|
11
|
+
topics: string | null;
|
|
12
|
+
tags: string | null;
|
|
13
|
+
links: string | null;
|
|
14
|
+
importance: number;
|
|
15
|
+
active: number;
|
|
16
|
+
created_at: number;
|
|
17
|
+
updated_at: number;
|
|
18
|
+
}
|
|
19
|
+
export interface CategoryRecord {
|
|
20
|
+
canonical: string;
|
|
21
|
+
display_name: string;
|
|
22
|
+
db_file: string;
|
|
23
|
+
created_at: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function openCategoryDb(file: string): Db;
|
|
26
|
+
/** Compatibility alias for callers that open a single category database. */
|
|
27
|
+
export declare const openDb: typeof openCategoryDb;
|
|
28
|
+
export declare function openCatalog(file: string): Db;
|
|
29
|
+
export declare function listCategories(catalog: Db): CategoryRecord[];
|
|
30
|
+
export declare function categoryRecord(catalog: Db, canonical: string): CategoryRecord | undefined;
|
|
31
|
+
export declare function registerCategory(catalog: Db, record: CategoryRecord): CategoryRecord;
|
|
32
|
+
export declare function metadataValue(catalog: Db, key: string): string | undefined;
|
|
33
|
+
export declare function setMetadata(catalog: Db, key: string, value: string): void;
|
|
34
|
+
export declare function insertRow(db: Db, row: MemoryRow, ignore?: boolean): void;
|
|
35
|
+
export declare function updateRow(db: Db, row: MemoryRow): void;
|
|
36
|
+
export declare function replaceLabels(db: Db, memoryId: string, labels: {
|
|
37
|
+
topics: readonly string[];
|
|
38
|
+
tags: readonly string[];
|
|
39
|
+
links: readonly string[];
|
|
40
|
+
}): void;
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { mkdirSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const MS_FLOOR = 1_000_000_000_000;
|
|
5
|
+
export function nowSeconds() {
|
|
6
|
+
return Math.floor(Date.now() / 1000);
|
|
7
|
+
}
|
|
8
|
+
const CATEGORY_SCHEMA = `
|
|
9
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
10
|
+
id TEXT PRIMARY KEY,
|
|
11
|
+
project_id TEXT NOT NULL,
|
|
12
|
+
chat_id TEXT,
|
|
13
|
+
category TEXT NOT NULL,
|
|
14
|
+
content TEXT NOT NULL,
|
|
15
|
+
subject TEXT,
|
|
16
|
+
topics TEXT,
|
|
17
|
+
tags TEXT,
|
|
18
|
+
links TEXT,
|
|
19
|
+
importance REAL DEFAULT 0.5,
|
|
20
|
+
active INTEGER DEFAULT 1,
|
|
21
|
+
created_at INTEGER NOT NULL,
|
|
22
|
+
updated_at INTEGER NOT NULL
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
CREATE INDEX IF NOT EXISTS memories_chat_idx ON memories(chat_id, active);
|
|
26
|
+
CREATE INDEX IF NOT EXISTS memories_subject_idx ON memories(subject);
|
|
27
|
+
CREATE INDEX IF NOT EXISTS memories_importance_idx ON memories(importance);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS memories_created_idx ON memories(created_at);
|
|
29
|
+
CREATE INDEX IF NOT EXISTS memories_updated_idx ON memories(updated_at);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS memory_labels (
|
|
32
|
+
memory_id TEXT NOT NULL,
|
|
33
|
+
kind TEXT NOT NULL CHECK(kind IN ('topic', 'tag', 'link')),
|
|
34
|
+
value TEXT NOT NULL,
|
|
35
|
+
PRIMARY KEY(memory_id, kind, value),
|
|
36
|
+
FOREIGN KEY(memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
37
|
+
);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS memory_labels_lookup_idx ON memory_labels(kind, value, memory_id);
|
|
39
|
+
|
|
40
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
41
|
+
content,
|
|
42
|
+
subject,
|
|
43
|
+
topics,
|
|
44
|
+
tags,
|
|
45
|
+
links,
|
|
46
|
+
content='memories',
|
|
47
|
+
content_rowid='rowid',
|
|
48
|
+
tokenize='porter unicode61'
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
52
|
+
INSERT INTO memories_fts(rowid, content, subject, topics, tags, links)
|
|
53
|
+
VALUES (new.rowid, new.content, new.subject, new.topics, new.tags, new.links);
|
|
54
|
+
END;
|
|
55
|
+
|
|
56
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
57
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, subject, topics, tags, links)
|
|
58
|
+
VALUES ('delete', old.rowid, old.content, old.subject, old.topics, old.tags, old.links);
|
|
59
|
+
END;
|
|
60
|
+
|
|
61
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
62
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, subject, topics, tags, links)
|
|
63
|
+
VALUES ('delete', old.rowid, old.content, old.subject, old.topics, old.tags, old.links);
|
|
64
|
+
INSERT INTO memories_fts(rowid, content, subject, topics, tags, links)
|
|
65
|
+
VALUES (new.rowid, new.content, new.subject, new.topics, new.tags, new.links);
|
|
66
|
+
END;
|
|
67
|
+
`;
|
|
68
|
+
const CATALOG_SCHEMA = `
|
|
69
|
+
CREATE TABLE IF NOT EXISTS categories (
|
|
70
|
+
canonical TEXT PRIMARY KEY,
|
|
71
|
+
display_name TEXT NOT NULL,
|
|
72
|
+
db_file TEXT NOT NULL UNIQUE,
|
|
73
|
+
created_at INTEGER NOT NULL
|
|
74
|
+
);
|
|
75
|
+
CREATE TABLE IF NOT EXISTS metadata (
|
|
76
|
+
key TEXT PRIMARY KEY,
|
|
77
|
+
value TEXT NOT NULL
|
|
78
|
+
);
|
|
79
|
+
`;
|
|
80
|
+
function configure(db) {
|
|
81
|
+
db.pragma("journal_mode = WAL");
|
|
82
|
+
db.pragma("busy_timeout = 5000");
|
|
83
|
+
db.pragma("synchronous = NORMAL");
|
|
84
|
+
db.pragma("foreign_keys = ON");
|
|
85
|
+
}
|
|
86
|
+
export function openCategoryDb(file) {
|
|
87
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
88
|
+
const db = new Database(file);
|
|
89
|
+
configure(db);
|
|
90
|
+
db.exec(CATEGORY_SCHEMA);
|
|
91
|
+
db.exec(`
|
|
92
|
+
UPDATE memories SET created_at = created_at / 1000 WHERE created_at >= ${MS_FLOOR};
|
|
93
|
+
UPDATE memories SET updated_at = updated_at / 1000 WHERE updated_at >= ${MS_FLOOR};
|
|
94
|
+
`);
|
|
95
|
+
return db;
|
|
96
|
+
}
|
|
97
|
+
/** Compatibility alias for callers that open a single category database. */
|
|
98
|
+
export const openDb = openCategoryDb;
|
|
99
|
+
export function openCatalog(file) {
|
|
100
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
101
|
+
const db = new Database(file);
|
|
102
|
+
configure(db);
|
|
103
|
+
db.exec(CATALOG_SCHEMA);
|
|
104
|
+
return db;
|
|
105
|
+
}
|
|
106
|
+
export function listCategories(catalog) {
|
|
107
|
+
return catalog
|
|
108
|
+
.prepare(`SELECT canonical, display_name, db_file, created_at FROM categories ORDER BY display_name`)
|
|
109
|
+
.all();
|
|
110
|
+
}
|
|
111
|
+
export function categoryRecord(catalog, canonical) {
|
|
112
|
+
return catalog
|
|
113
|
+
.prepare(`SELECT canonical, display_name, db_file, created_at FROM categories WHERE canonical = ?`)
|
|
114
|
+
.get(canonical);
|
|
115
|
+
}
|
|
116
|
+
export function registerCategory(catalog, record) {
|
|
117
|
+
catalog
|
|
118
|
+
.prepare(`INSERT OR IGNORE INTO categories (canonical, display_name, db_file, created_at)
|
|
119
|
+
VALUES (@canonical, @display_name, @db_file, @created_at)`)
|
|
120
|
+
.run(record);
|
|
121
|
+
return categoryRecord(catalog, record.canonical) ?? record;
|
|
122
|
+
}
|
|
123
|
+
export function metadataValue(catalog, key) {
|
|
124
|
+
const row = catalog.prepare(`SELECT value FROM metadata WHERE key = ?`).get(key);
|
|
125
|
+
return row?.value;
|
|
126
|
+
}
|
|
127
|
+
export function setMetadata(catalog, key, value) {
|
|
128
|
+
catalog
|
|
129
|
+
.prepare(`INSERT INTO metadata (key, value) VALUES (?, ?)
|
|
130
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`)
|
|
131
|
+
.run(key, value);
|
|
132
|
+
}
|
|
133
|
+
export function insertRow(db, row, ignore = false) {
|
|
134
|
+
db.prepare(`INSERT ${ignore ? "OR IGNORE " : ""}INTO memories
|
|
135
|
+
(id, project_id, chat_id, category, content, subject, topics, tags, links,
|
|
136
|
+
importance, active, created_at, updated_at)
|
|
137
|
+
VALUES (@id, @project_id, @chat_id, @category, @content, @subject, @topics, @tags, @links,
|
|
138
|
+
@importance, @active, @created_at, @updated_at)`).run(row);
|
|
139
|
+
}
|
|
140
|
+
export function updateRow(db, row) {
|
|
141
|
+
db.prepare(`UPDATE memories SET content = @content, category = @category, subject = @subject,
|
|
142
|
+
topics = @topics, tags = @tags, links = @links, importance = @importance,
|
|
143
|
+
chat_id = @chat_id, updated_at = @updated_at WHERE id = @id`).run(row);
|
|
144
|
+
}
|
|
145
|
+
export function replaceLabels(db, memoryId, labels) {
|
|
146
|
+
const remove = db.prepare(`DELETE FROM memory_labels WHERE memory_id = ?`);
|
|
147
|
+
const insert = db.prepare(`INSERT INTO memory_labels (memory_id, kind, value) VALUES (?, ?, ?)`);
|
|
148
|
+
db.transaction(() => {
|
|
149
|
+
remove.run(memoryId);
|
|
150
|
+
for (const value of labels.topics)
|
|
151
|
+
insert.run(memoryId, "topic", value);
|
|
152
|
+
for (const value of labels.tags)
|
|
153
|
+
insert.run(memoryId, "tag", value);
|
|
154
|
+
for (const value of labels.links)
|
|
155
|
+
insert.run(memoryId, "link", value);
|
|
156
|
+
})();
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=db.js.map
|
package/dist/db.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
|