open-memex 0.3.0-alpha → 0.3.0-alpha.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/AGENTS.md +12 -6
- package/README.md +16 -7
- package/README.zh-CN.md +15 -6
- package/dist/capture/keywords.js +43 -0
- package/dist/cli.js +531 -0
- package/dist/config.js +123 -0
- package/dist/doctor.js +151 -0
- package/dist/index.js +121 -0
- package/dist/init.js +323 -0
- package/dist/mcp.js +85 -0
- package/dist/paths.js +36 -0
- package/dist/redact.js +249 -0
- package/dist/retrieve/cjk.js +58 -0
- package/dist/retrieve/inject.js +25 -0
- package/dist/retrieve/search.js +147 -0
- package/dist/scope.js +70 -0
- package/dist/store/db.js +132 -0
- package/dist/store/lifecycle.js +214 -0
- package/dist/store/markdown.js +197 -0
- package/dist/store/migrate.js +109 -0
- package/dist/store/sync.js +88 -0
- package/dist/store/v2migrate.js +158 -0
- package/dist/tools/memory.js +40 -0
- package/dist/tools/ops.js +186 -0
- package/docs/V2-DESIGN.md +19 -0
- package/package.json +5 -3
- package/src/cli.ts +37 -21
- package/src/doctor.ts +16 -5
- package/src/init.ts +55 -6
- package/tsconfig.build.json +1 -0
- package/bin/open-memex.js +0 -28
package/src/init.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// `open-memex init` — one-command project setup (§17 adoption path).
|
|
2
2
|
// Pure file operation: no DB, no network. Safe to run in any directory.
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { execFileSync } from "node:child_process";
|
|
6
7
|
import { createInterface } from "node:readline/promises";
|
|
@@ -46,6 +47,9 @@ export function resolveMcpCommand(): McpCommand {
|
|
|
46
47
|
const INSTRUCTIONS = `${MARKER}
|
|
47
48
|
# OpenMemex memory
|
|
48
49
|
|
|
50
|
+
> Applies only when the \`open-memex\` MCP server is available in this session
|
|
51
|
+
> (the \`memory_*\` tools exist). Otherwise ignore this section.
|
|
52
|
+
|
|
49
53
|
You have a local memory MCP server (\`open-memex\`) with five tools:
|
|
50
54
|
\`memory_add\`, \`memory_search\`, \`memory_list\`, \`memory_supersede\`, \`memory_forget\`.
|
|
51
55
|
|
|
@@ -186,9 +190,26 @@ function writeVisualStudioMcpJson(root: string, force: boolean): string | null {
|
|
|
186
190
|
return file;
|
|
187
191
|
}
|
|
188
192
|
|
|
189
|
-
function writeInstructions(
|
|
190
|
-
|
|
191
|
-
|
|
193
|
+
function writeInstructions(
|
|
194
|
+
root: string,
|
|
195
|
+
scope: "personal" | "project",
|
|
196
|
+
client: string,
|
|
197
|
+
): string {
|
|
198
|
+
const file =
|
|
199
|
+
scope === "project"
|
|
200
|
+
? path.join(root, ".github", "copilot-instructions.md")
|
|
201
|
+
: client === "visualstudio"
|
|
202
|
+
? path.join(os.homedir(), "copilot-instructions.md")
|
|
203
|
+
: path.join(os.homedir(), ".copilot", "copilot-instructions.md");
|
|
204
|
+
if (scope === "personal") {
|
|
205
|
+
// A previous project-scoped init may have left the section behind — flag it
|
|
206
|
+
// so the repo can go back to being open-memex-free for teammates.
|
|
207
|
+
const proj = path.join(root, ".github", "copilot-instructions.md");
|
|
208
|
+
if (fs.existsSync(proj) && fs.readFileSync(proj, "utf8").includes(MARKER)) {
|
|
209
|
+
console.log(` ! project-level instructions still present at ${proj}`);
|
|
210
|
+
console.log(` remove the open-memex section there to keep the repo clean.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
192
213
|
if (fs.existsSync(file)) {
|
|
193
214
|
const cur = fs.readFileSync(file, "utf8");
|
|
194
215
|
if (cur.includes(MARKER)) {
|
|
@@ -197,7 +218,7 @@ function writeInstructions(root: string): string {
|
|
|
197
218
|
}
|
|
198
219
|
fs.writeFileSync(file, cur.replace(/\s+$/, "") + "\n\n" + INSTRUCTIONS);
|
|
199
220
|
} else {
|
|
200
|
-
fs.mkdirSync(
|
|
221
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
201
222
|
fs.writeFileSync(file, INSTRUCTIONS);
|
|
202
223
|
}
|
|
203
224
|
console.log(` + ${file}`);
|
|
@@ -254,10 +275,26 @@ async function promptClient(): Promise<string | null> {
|
|
|
254
275
|
}
|
|
255
276
|
}
|
|
256
277
|
|
|
278
|
+
/** D22: where the Copilot memory instructions live. Personal (default) is the
|
|
279
|
+
* Copilot user-level location — all projects, never checked in. */
|
|
280
|
+
async function promptInstructionsScope(): Promise<"personal" | "project"> {
|
|
281
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
282
|
+
try {
|
|
283
|
+
console.log("Where should the Copilot memory instructions live?");
|
|
284
|
+
console.log(" 1) personal — user-level, all projects, never checked into a repo");
|
|
285
|
+
console.log(" 2) project — .github/copilot-instructions.md, shared with the repo");
|
|
286
|
+
const ans = (await rl.question("Choice [1]: ")).trim();
|
|
287
|
+
return ans === "2" ? "project" : "personal";
|
|
288
|
+
} finally {
|
|
289
|
+
rl.close();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
257
293
|
export async function initProject(opts: {
|
|
258
294
|
client?: string;
|
|
259
295
|
force: boolean;
|
|
260
296
|
yes: boolean;
|
|
297
|
+
instructions?: string;
|
|
261
298
|
}): Promise<void> {
|
|
262
299
|
const interactive = !opts.yes && !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
263
300
|
let client = normalizeClient(opts.client ?? "");
|
|
@@ -267,12 +304,22 @@ export async function initProject(opts: {
|
|
|
267
304
|
}
|
|
268
305
|
if (!client && interactive) client = (await promptClient()) ?? "";
|
|
269
306
|
if (!client && !interactive) client = "vscode"; // historical default for scripts / one-shot npx
|
|
307
|
+
let scope: "personal" | "project" = "personal";
|
|
308
|
+
if (opts.instructions) {
|
|
309
|
+
if (opts.instructions !== "personal" && opts.instructions !== "project") {
|
|
310
|
+
console.error(`unknown --instructions "${opts.instructions}" (personal|project)`);
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
scope = opts.instructions;
|
|
314
|
+
} else if (interactive) {
|
|
315
|
+
scope = await promptInstructionsScope();
|
|
316
|
+
}
|
|
270
317
|
if (interactive) {
|
|
271
318
|
// Install-time settings (D19). Non-default answers persist to the JSONC
|
|
272
319
|
// config file; `open-memex config set` changes them later.
|
|
273
320
|
const patch: Record<string, unknown> = {};
|
|
274
321
|
const keywordCaptureEnabled = await askBool(
|
|
275
|
-
"Auto-capture keywords like
|
|
322
|
+
"Auto-capture keywords like remember… / note that… into memory?",
|
|
276
323
|
DEFAULT_CONFIG.keywordCaptureEnabled,
|
|
277
324
|
);
|
|
278
325
|
if (keywordCaptureEnabled !== DEFAULT_CONFIG.keywordCaptureEnabled)
|
|
@@ -296,7 +343,9 @@ export async function initProject(opts: {
|
|
|
296
343
|
writeMcpJson(root, client, opts.force);
|
|
297
344
|
// copilot-instructions.md is VS Code/Cursor-shaped; opencode as a plain MCP
|
|
298
345
|
// consumer already gets the guidance from the tool descriptions (D16).
|
|
299
|
-
|
|
346
|
+
// D22: personal scope (default) writes to the Copilot user-level location
|
|
347
|
+
// so the repo stays clean for teammates without open-memex.
|
|
348
|
+
if (client !== "opencode") writeInstructions(root, scope, client);
|
|
300
349
|
} else {
|
|
301
350
|
console.log(" - editor setup skipped");
|
|
302
351
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"compilerOptions":{"declaration":false,"noEmit":false,"outDir":"dist","rewriteRelativeImportExtensions":true,"sourceMap":false},"extends":"./tsconfig.json","include":["src/**/*.ts"]}
|
package/bin/open-memex.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// `open-memex` bin launcher: re-execs src/cli.ts with TypeScript type-stripping
|
|
3
|
-
// enabled, so the command works on Node 22.6+ without the user passing
|
|
4
|
-
// --experimental-strip-types themselves. (Plain JS — no build step.)
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
|
-
import path from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
|
|
9
|
-
const entry = path.join(
|
|
10
|
-
path.dirname(fileURLToPath(import.meta.url)),
|
|
11
|
-
"..",
|
|
12
|
-
"src",
|
|
13
|
-
"cli.ts",
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
const child = spawn(
|
|
17
|
-
process.execPath,
|
|
18
|
-
["--experimental-strip-types", entry, ...process.argv.slice(2)],
|
|
19
|
-
{ stdio: "inherit" },
|
|
20
|
-
);
|
|
21
|
-
child.on("error", (err) => {
|
|
22
|
-
console.error(`open-memex: failed to start: ${err.message}`);
|
|
23
|
-
process.exit(1);
|
|
24
|
-
});
|
|
25
|
-
child.on("exit", (code, signal) => {
|
|
26
|
-
if (signal) process.kill(process.pid, signal);
|
|
27
|
-
else process.exit(code ?? 0);
|
|
28
|
-
});
|