coding-friend-cli 1.32.0 → 1.32.1
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/{chunk-5OXEUKOE.js → chunk-355AR2X5.js} +155 -102
- package/dist/{chunk-U7IVVN45.js → chunk-5W7ZOVDU.js} +7 -24
- package/dist/{config-OBCZNDKV.js → config-FUEEFM5N.js} +2 -2
- package/dist/index.js +19 -15
- package/dist/{init-H2EOLWJ5.js → init-3UITY4LD.js} +3 -3
- package/dist/{mcp-G4FEXMZW.js → mcp-LJ5NX6XE.js} +10 -6
- package/dist/mcp-serve-3FEPFVVQ.js +27 -0
- package/dist/{memory-SO33RAI5.js → memory-2ZD4WU3S.js} +3 -3
- package/package.json +1 -1
- package/dist/{host-N3GQ6OJM.js → host-RNYPAE4D.js} +3 -3
- package/dist/{status-EFEXM3ZM.js → status-FU5GR3MP.js} +3 -3
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
getMemoryMcpStatus,
|
|
7
7
|
memoryConfigMenu,
|
|
8
8
|
writeMemoryMcpEntry
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import {
|
|
11
|
-
getLibPath
|
|
12
|
-
} from "./chunk-RZRT7NGT.js";
|
|
9
|
+
} from "./chunk-5W7ZOVDU.js";
|
|
13
10
|
import {
|
|
14
11
|
loadConfig,
|
|
15
12
|
resolveMemoryDir
|
|
16
13
|
} from "./chunk-GTX6I57V.js";
|
|
14
|
+
import {
|
|
15
|
+
getLibPath
|
|
16
|
+
} from "./chunk-RZRT7NGT.js";
|
|
17
17
|
import {
|
|
18
18
|
showConfigHint
|
|
19
19
|
} from "./chunk-HPNRQYLM.js";
|
|
@@ -34,17 +34,74 @@ import {
|
|
|
34
34
|
} from "./chunk-5UVDWG5L.js";
|
|
35
35
|
|
|
36
36
|
// src/commands/memory.ts
|
|
37
|
-
import { existsSync, readdirSync, statSync, rmSync } from "fs";
|
|
38
|
-
import { join, resolve, sep } from "path";
|
|
37
|
+
import { existsSync as existsSync2, readdirSync, statSync, rmSync } from "fs";
|
|
38
|
+
import { join as join2, resolve, sep } from "path";
|
|
39
39
|
import { homedir } from "os";
|
|
40
40
|
import { confirm } from "@inquirer/prompts";
|
|
41
|
+
|
|
42
|
+
// src/lib/mcp-state.ts
|
|
43
|
+
import { existsSync } from "fs";
|
|
44
|
+
import { join } from "path";
|
|
41
45
|
import chalk from "chalk";
|
|
46
|
+
function warnStaleMcpJson(memoryDir) {
|
|
47
|
+
const localMcpPath = join(process.cwd(), ".mcp.json");
|
|
48
|
+
if (!existsSync(localMcpPath)) return;
|
|
49
|
+
const mcpJson = readJson(localMcpPath);
|
|
50
|
+
if (mcpJson === null) {
|
|
51
|
+
log.warn(".mcp.json exists but could not be parsed \u2014 check for syntax errors.");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const state = detectMemoryMcpState(mcpJson, existsSync);
|
|
55
|
+
if (state.kind === "stale" || state.kind === "legacy-valid") {
|
|
56
|
+
if (memoryDir) {
|
|
57
|
+
writeMemoryMcpEntry(memoryDir);
|
|
58
|
+
if (state.kind === "stale") {
|
|
59
|
+
log.success("Auto-updated stale .mcp.json to version-stable npx format.");
|
|
60
|
+
} else {
|
|
61
|
+
log.success("Updated .mcp.json to version-stable npx format.");
|
|
62
|
+
}
|
|
63
|
+
console.log();
|
|
64
|
+
} else if (state.kind === "stale") {
|
|
65
|
+
console.log(chalk.yellow(`\u26A0 Stale MCP config detected in .mcp.json`));
|
|
66
|
+
console.log(chalk.dim(` Path no longer exists: ${state.path}`));
|
|
67
|
+
console.log(chalk.dim(` Run "cf memory mcp" to update to the new format.`));
|
|
68
|
+
console.log();
|
|
69
|
+
} else {
|
|
70
|
+
console.log(chalk.cyan(`\u2139 .mcp.json uses an absolute path for coding-friend-memory.`));
|
|
71
|
+
console.log(chalk.dim(` Consider running "cf memory mcp" to switch to the version-stable format.`));
|
|
72
|
+
console.log();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function detectMemoryMcpState(mcpJson, pathExists) {
|
|
77
|
+
if (!mcpJson) return { kind: "none" };
|
|
78
|
+
const servers = mcpJson.mcpServers;
|
|
79
|
+
if (!servers) return { kind: "none" };
|
|
80
|
+
const entry = servers["coding-friend-memory"];
|
|
81
|
+
if (!entry) return { kind: "none" };
|
|
82
|
+
const command = entry.command;
|
|
83
|
+
if (!command) return { kind: "none" };
|
|
84
|
+
if (command === "npx") return { kind: "npx" };
|
|
85
|
+
if (command === "node") {
|
|
86
|
+
const args = entry.args;
|
|
87
|
+
const serverPath = args?.[0];
|
|
88
|
+
if (!serverPath) return { kind: "none" };
|
|
89
|
+
if (!pathExists(serverPath)) {
|
|
90
|
+
return { kind: "stale", path: serverPath };
|
|
91
|
+
}
|
|
92
|
+
return { kind: "legacy-valid", path: serverPath };
|
|
93
|
+
}
|
|
94
|
+
return { kind: "none" };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/commands/memory.ts
|
|
98
|
+
import chalk2 from "chalk";
|
|
42
99
|
function countMdFiles(dir) {
|
|
43
|
-
if (!
|
|
100
|
+
if (!existsSync2(dir)) return 0;
|
|
44
101
|
let count = 0;
|
|
45
102
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
46
103
|
if (entry.isDirectory()) {
|
|
47
|
-
count += countMdFiles(
|
|
104
|
+
count += countMdFiles(join2(dir, entry.name));
|
|
48
105
|
} else if (entry.name.endsWith(".md") && entry.name !== "README.md") {
|
|
49
106
|
count++;
|
|
50
107
|
}
|
|
@@ -64,7 +121,7 @@ function truncateError(text) {
|
|
|
64
121
|
return [...head, ` ... (${skipped} lines omitted) ...`, ...tail].join("\n");
|
|
65
122
|
}
|
|
66
123
|
function ensureMemoryBuilt(mcpDir) {
|
|
67
|
-
if (!
|
|
124
|
+
if (!existsSync2(join2(mcpDir, "node_modules"))) {
|
|
68
125
|
log.step("Installing memory server dependencies (one-time setup)...");
|
|
69
126
|
const result = runWithStderr("npm", ["install"], { cwd: mcpDir });
|
|
70
127
|
if (result.exitCode !== 0) {
|
|
@@ -74,7 +131,7 @@ function ensureMemoryBuilt(mcpDir) {
|
|
|
74
131
|
}
|
|
75
132
|
log.success("Done.");
|
|
76
133
|
}
|
|
77
|
-
if (!
|
|
134
|
+
if (!existsSync2(join2(mcpDir, "dist"))) {
|
|
78
135
|
log.step("Building memory server...");
|
|
79
136
|
const result = runWithStderr("npm", ["run", "build"], { cwd: mcpDir });
|
|
80
137
|
if (result.exitCode !== 0) {
|
|
@@ -86,23 +143,23 @@ function ensureMemoryBuilt(mcpDir) {
|
|
|
86
143
|
}
|
|
87
144
|
}
|
|
88
145
|
function printMemoryMcpConfig(serverPath, memoryDir) {
|
|
89
|
-
console.log(
|
|
146
|
+
console.log(chalk2.dim("Add this to your MCP client config:"));
|
|
90
147
|
console.log();
|
|
91
148
|
console.log(
|
|
92
|
-
|
|
149
|
+
chalk2.yellow.bold("--- Claude Code (.mcp.json in project root) ---")
|
|
93
150
|
);
|
|
94
151
|
console.log(`
|
|
95
152
|
{
|
|
96
153
|
"mcpServers": {
|
|
97
154
|
"coding-friend-memory": {
|
|
98
|
-
"command": "
|
|
99
|
-
"args": ["
|
|
155
|
+
"command": "npx",
|
|
156
|
+
"args": ["-y", "coding-friend-cli", "mcp-serve", "${memoryDir}"]
|
|
100
157
|
}
|
|
101
158
|
}
|
|
102
159
|
}`);
|
|
103
160
|
console.log();
|
|
104
161
|
console.log(
|
|
105
|
-
|
|
162
|
+
chalk2.yellow.bold(
|
|
106
163
|
"--- Claude Desktop / Claude Chat (claude_desktop_config.json) ---"
|
|
107
164
|
)
|
|
108
165
|
);
|
|
@@ -116,39 +173,39 @@ function printMemoryMcpConfig(serverPath, memoryDir) {
|
|
|
116
173
|
}
|
|
117
174
|
}`);
|
|
118
175
|
console.log();
|
|
119
|
-
console.log(
|
|
176
|
+
console.log(chalk2.yellow.bold("--- Generic MCP client ---"));
|
|
120
177
|
console.log(`
|
|
121
178
|
Server command: node ${serverPath} ${memoryDir}
|
|
122
179
|
Transport: stdio`);
|
|
123
180
|
console.log();
|
|
124
|
-
console.log(
|
|
181
|
+
console.log(chalk2.yellow.bold("--- Available tools ---"));
|
|
125
182
|
console.log();
|
|
126
183
|
console.log(
|
|
127
|
-
` ${
|
|
184
|
+
` ${chalk2.white("memory_store")} ${chalk2.dim("Store a new memory")}`
|
|
128
185
|
);
|
|
129
186
|
console.log(
|
|
130
|
-
` ${
|
|
187
|
+
` ${chalk2.white("memory_search")} ${chalk2.dim("Search memories (keyword match)")}`
|
|
131
188
|
);
|
|
132
189
|
console.log(
|
|
133
|
-
` ${
|
|
190
|
+
` ${chalk2.white("memory_retrieve")} ${chalk2.dim("Get a specific memory by ID")}`
|
|
134
191
|
);
|
|
135
192
|
console.log(
|
|
136
|
-
` ${
|
|
193
|
+
` ${chalk2.white("memory_list")} ${chalk2.dim("List memories with filtering")}`
|
|
137
194
|
);
|
|
138
195
|
console.log(
|
|
139
|
-
` ${
|
|
196
|
+
` ${chalk2.white("memory_update")} ${chalk2.dim("Update existing memory")}`
|
|
140
197
|
);
|
|
141
198
|
console.log(
|
|
142
|
-
` ${
|
|
199
|
+
` ${chalk2.white("memory_delete")} ${chalk2.dim("Delete a memory")}`
|
|
143
200
|
);
|
|
144
201
|
console.log();
|
|
145
|
-
console.log(
|
|
202
|
+
console.log(chalk2.yellow.bold("--- Resources ---"));
|
|
146
203
|
console.log();
|
|
147
204
|
console.log(
|
|
148
|
-
` ${
|
|
205
|
+
` ${chalk2.white("memory://index")} ${chalk2.dim("Browse all memories")}`
|
|
149
206
|
);
|
|
150
207
|
console.log(
|
|
151
|
-
` ${
|
|
208
|
+
` ${chalk2.white("memory://stats")} ${chalk2.dim("Storage statistics")}`
|
|
152
209
|
);
|
|
153
210
|
console.log();
|
|
154
211
|
log.warn(
|
|
@@ -166,43 +223,43 @@ async function memoryStatusCommand() {
|
|
|
166
223
|
const docCount = countMdFiles(memoryDir);
|
|
167
224
|
const mcpDir = getLibPath("cf-memory");
|
|
168
225
|
ensureMemoryBuilt(mcpDir);
|
|
169
|
-
const { isDaemonRunning, getDaemonInfo } = await import(
|
|
170
|
-
const { areSqliteDepsAvailable } = await import(
|
|
226
|
+
const { isDaemonRunning, getDaemonInfo } = await import(join2(mcpDir, "dist/daemon/process.js"));
|
|
227
|
+
const { areSqliteDepsAvailable } = await import(join2(mcpDir, "dist/lib/lazy-install.js"));
|
|
171
228
|
const sqliteAvailable = areSqliteDepsAvailable();
|
|
172
229
|
const running = await isDaemonRunning();
|
|
173
230
|
const daemonInfo = getDaemonInfo();
|
|
174
231
|
let tierLabel;
|
|
175
232
|
if (sqliteAvailable) {
|
|
176
|
-
tierLabel =
|
|
233
|
+
tierLabel = chalk2.cyan("Tier 1 (SQLite + Hybrid)");
|
|
177
234
|
} else if (running) {
|
|
178
|
-
tierLabel =
|
|
235
|
+
tierLabel = chalk2.cyan("Tier 2 (MiniSearch + Daemon)");
|
|
179
236
|
} else {
|
|
180
|
-
tierLabel =
|
|
237
|
+
tierLabel = chalk2.cyan("Tier 3 (Markdown)");
|
|
181
238
|
}
|
|
182
239
|
printBanner("\u{1F9E0} Coding Friend Memory");
|
|
183
240
|
console.log();
|
|
184
241
|
log.info(`Tier: ${tierLabel}`);
|
|
185
|
-
log.info(`Memory dir: ${
|
|
186
|
-
log.info(`Memories in this dir: ${
|
|
242
|
+
log.info(`Memory dir: ${chalk2.cyan(memoryDir)}`);
|
|
243
|
+
log.info(`Memories in this dir: ${chalk2.green(String(docCount))}`);
|
|
187
244
|
if (running && daemonInfo) {
|
|
188
245
|
const uptime = (Date.now() - daemonInfo.startedAt) / 1e3;
|
|
189
246
|
log.info(
|
|
190
|
-
`Daemon: ${
|
|
247
|
+
`Daemon: ${chalk2.green("running")} (PID ${daemonInfo.pid}, uptime ${formatUptime(uptime)}) ${chalk2.dim('Turn it off by "cf memory stop-daemon"')}`
|
|
191
248
|
);
|
|
192
249
|
} else if (sqliteAvailable) {
|
|
193
250
|
log.info(
|
|
194
|
-
`Daemon: ${
|
|
251
|
+
`Daemon: ${chalk2.dim("stopped")} ${chalk2.dim("(not needed \u2014 Tier 1 uses SQLite directly)")}`
|
|
195
252
|
);
|
|
196
253
|
} else {
|
|
197
254
|
log.info(
|
|
198
|
-
`Daemon: ${
|
|
255
|
+
`Daemon: ${chalk2.dim("stopped")} ${chalk2.dim('(run "cf memory start-daemon" for Tier 2 search)')}`
|
|
199
256
|
);
|
|
200
257
|
}
|
|
201
258
|
if (sqliteAvailable) {
|
|
202
|
-
log.info(`SQLite deps: ${
|
|
259
|
+
log.info(`SQLite deps: ${chalk2.green("installed")}`);
|
|
203
260
|
} else {
|
|
204
261
|
log.info(
|
|
205
|
-
`SQLite deps: ${
|
|
262
|
+
`SQLite deps: ${chalk2.dim("not installed")} (run "cf memory init" to enable Tier 1)`
|
|
206
263
|
);
|
|
207
264
|
}
|
|
208
265
|
const config = loadConfig();
|
|
@@ -210,33 +267,33 @@ async function memoryStatusCommand() {
|
|
|
210
267
|
if (embeddingConfig?.provider || embeddingConfig?.model) {
|
|
211
268
|
const provider = embeddingConfig.provider ?? "transformers";
|
|
212
269
|
const model = embeddingConfig.model ?? (provider === "ollama" ? "all-minilm:l6-v2" : "Xenova/all-MiniLM-L6-v2");
|
|
213
|
-
log.info(`Embedding: ${
|
|
270
|
+
log.info(`Embedding: ${chalk2.cyan(model)} ${chalk2.dim(`(${provider})`)}`);
|
|
214
271
|
}
|
|
215
272
|
const mcpStatus = getMemoryMcpStatus();
|
|
216
273
|
if (mcpStatus.configured && mcpStatus.scope === "local") {
|
|
217
274
|
log.info(
|
|
218
|
-
`MCP: ${
|
|
275
|
+
`MCP: ${chalk2.green("configured")} ${chalk2.dim("(local .mcp.json)")}`
|
|
219
276
|
);
|
|
220
277
|
} else if (mcpStatus.configured && mcpStatus.scope === "global") {
|
|
221
278
|
log.info(
|
|
222
|
-
`MCP: ${
|
|
279
|
+
`MCP: ${chalk2.green("configured")} ${chalk2.dim("(global ~/.claude/.mcp.json)")} ${chalk2.yellow("\u26A0 global config uses a fixed path \u2014 only works for one project")}`
|
|
223
280
|
);
|
|
224
281
|
} else {
|
|
225
282
|
log.info(
|
|
226
|
-
`MCP: ${
|
|
283
|
+
`MCP: ${chalk2.dim("not configured in this project")} ${chalk2.dim('(run "cf memory init" or add manually via "cf memory mcp")')}`
|
|
227
284
|
);
|
|
228
285
|
}
|
|
229
286
|
const autoCapture = config.memory?.autoCapture ?? false;
|
|
230
287
|
log.info(
|
|
231
|
-
`Auto-capture: ${autoCapture ?
|
|
288
|
+
`Auto-capture: ${autoCapture ? chalk2.green("on") : chalk2.dim("off")}`
|
|
232
289
|
);
|
|
233
|
-
if (
|
|
290
|
+
if (existsSync2(memoryDir)) {
|
|
234
291
|
const categories = readdirSync(memoryDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => {
|
|
235
|
-
const catCount = countMdFiles(
|
|
292
|
+
const catCount = countMdFiles(join2(memoryDir, d.name));
|
|
236
293
|
return `${d.name} (${catCount})`;
|
|
237
294
|
}).filter((s) => !s.endsWith("(0)"));
|
|
238
295
|
if (categories.length > 0) {
|
|
239
|
-
log.info(`Categories: ${
|
|
296
|
+
log.info(`Categories: ${chalk2.dim(categories.join(", "))}`);
|
|
240
297
|
}
|
|
241
298
|
}
|
|
242
299
|
console.log();
|
|
@@ -245,7 +302,7 @@ async function memoryStatusCommand() {
|
|
|
245
302
|
}
|
|
246
303
|
async function memorySearchCommand(query) {
|
|
247
304
|
const memoryDir = getMemoryDir();
|
|
248
|
-
if (!
|
|
305
|
+
if (!existsSync2(memoryDir)) {
|
|
249
306
|
log.error(`Memory dir not found: ${memoryDir}`);
|
|
250
307
|
log.dim("Run `cf init` to create project folders.");
|
|
251
308
|
process.exit(1);
|
|
@@ -257,7 +314,7 @@ async function memorySearchCommand(query) {
|
|
|
257
314
|
[
|
|
258
315
|
"-e",
|
|
259
316
|
`
|
|
260
|
-
import { MarkdownBackend } from ${JSON.stringify(
|
|
317
|
+
import { MarkdownBackend } from ${JSON.stringify(join2(mcpDir, "dist/backends/markdown.js"))};
|
|
261
318
|
const backend = new MarkdownBackend(${JSON.stringify(memoryDir)});
|
|
262
319
|
const results = await backend.search({ query: process.env.CF_SEARCH_QUERY, limit: 10 });
|
|
263
320
|
for (const r of results) {
|
|
@@ -280,7 +337,7 @@ async function memoryListCommand(opts) {
|
|
|
280
337
|
return memoryListProjectsCommand();
|
|
281
338
|
}
|
|
282
339
|
const memoryDir = getMemoryDir();
|
|
283
|
-
if (!
|
|
340
|
+
if (!existsSync2(memoryDir)) {
|
|
284
341
|
log.info(`No memory directory found at: ${memoryDir}`);
|
|
285
342
|
log.dim(
|
|
286
343
|
"This folder has no memories yet. Use --projects to list all project databases."
|
|
@@ -297,7 +354,7 @@ async function memoryListCommand(opts) {
|
|
|
297
354
|
[
|
|
298
355
|
"-e",
|
|
299
356
|
`
|
|
300
|
-
import { MarkdownBackend } from ${JSON.stringify(
|
|
357
|
+
import { MarkdownBackend } from ${JSON.stringify(join2(mcpDir, "dist/backends/markdown.js"))};
|
|
301
358
|
const backend = new MarkdownBackend(${JSON.stringify(memoryDir)});
|
|
302
359
|
const metas = await backend.list({});
|
|
303
360
|
if (metas.length === 0) { console.log("No memories found."); process.exit(0); }
|
|
@@ -333,7 +390,7 @@ async function memoryStartDaemonCommand() {
|
|
|
333
390
|
const memoryDir = getMemoryDir();
|
|
334
391
|
const mcpDir = getLibPath("cf-memory");
|
|
335
392
|
ensureMemoryBuilt(mcpDir);
|
|
336
|
-
const { isDaemonRunning, getDaemonInfo, spawnDaemon } = await import(
|
|
393
|
+
const { isDaemonRunning, getDaemonInfo, spawnDaemon } = await import(join2(mcpDir, "dist/daemon/process.js"));
|
|
337
394
|
if (await isDaemonRunning()) {
|
|
338
395
|
const info = getDaemonInfo();
|
|
339
396
|
log.info(`Daemon already running (PID ${info?.pid})`);
|
|
@@ -345,7 +402,7 @@ async function memoryStartDaemonCommand() {
|
|
|
345
402
|
const result = await spawnDaemon(memoryDir, embedding, {});
|
|
346
403
|
if (result) {
|
|
347
404
|
log.success(`Daemon started (PID ${result.pid})`);
|
|
348
|
-
log.info(`Watching ${
|
|
405
|
+
log.info(`Watching ${chalk2.cyan(memoryDir)} for changes`);
|
|
349
406
|
} else {
|
|
350
407
|
log.error("Daemon did not start within 3 seconds");
|
|
351
408
|
process.exit(1);
|
|
@@ -354,7 +411,7 @@ async function memoryStartDaemonCommand() {
|
|
|
354
411
|
async function memoryStopDaemonCommand() {
|
|
355
412
|
const mcpDir = getLibPath("cf-memory");
|
|
356
413
|
ensureMemoryBuilt(mcpDir);
|
|
357
|
-
const { stopDaemon, isDaemonRunning } = await import(
|
|
414
|
+
const { stopDaemon, isDaemonRunning } = await import(join2(mcpDir, "dist/daemon/process.js"));
|
|
358
415
|
if (!await isDaemonRunning()) {
|
|
359
416
|
log.info("Daemon is not running.");
|
|
360
417
|
return;
|
|
@@ -371,10 +428,10 @@ async function memoryRebuildCommand() {
|
|
|
371
428
|
const memoryDir = getMemoryDir();
|
|
372
429
|
const mcpDir = getLibPath("cf-memory");
|
|
373
430
|
ensureMemoryBuilt(mcpDir);
|
|
374
|
-
const { areSqliteDepsAvailable } = await import(
|
|
431
|
+
const { areSqliteDepsAvailable } = await import(join2(mcpDir, "dist/lib/lazy-install.js"));
|
|
375
432
|
if (areSqliteDepsAvailable()) {
|
|
376
433
|
log.step("Rebuilding SQLite index + embeddings...");
|
|
377
|
-
const { SqliteBackend } = await import(
|
|
434
|
+
const { SqliteBackend } = await import(join2(mcpDir, "dist/backends/sqlite/index.js"));
|
|
378
435
|
const config = loadConfig();
|
|
379
436
|
const embedding = config.memory?.embedding;
|
|
380
437
|
const opts = embedding ? { embedding, skipVec: false } : { skipVec: false };
|
|
@@ -384,7 +441,7 @@ async function memoryRebuildCommand() {
|
|
|
384
441
|
const stats = await backend.stats();
|
|
385
442
|
log.success(`Rebuilt: ${stats.total} memories indexed.`);
|
|
386
443
|
if (backend.isVecEnabled()) {
|
|
387
|
-
log.info(`Vector search: ${
|
|
444
|
+
log.info(`Vector search: ${chalk2.green("enabled")}`);
|
|
388
445
|
}
|
|
389
446
|
if (!backend.isRebuildNeeded()) {
|
|
390
447
|
log.info("Embedding dimensions: up to date");
|
|
@@ -394,14 +451,14 @@ async function memoryRebuildCommand() {
|
|
|
394
451
|
}
|
|
395
452
|
return;
|
|
396
453
|
}
|
|
397
|
-
const { isDaemonRunning, getDaemonPaths } = await import(
|
|
454
|
+
const { isDaemonRunning, getDaemonPaths } = await import(join2(mcpDir, "dist/daemon/process.js"));
|
|
398
455
|
if (!await isDaemonRunning()) {
|
|
399
456
|
log.info("No SQLite deps and daemon not running. Nothing to rebuild.");
|
|
400
457
|
log.dim("Install Tier 1 deps: cf memory init");
|
|
401
458
|
log.dim("Or start the daemon: cf memory start-daemon");
|
|
402
459
|
return;
|
|
403
460
|
}
|
|
404
|
-
const { DaemonClient } = await import(
|
|
461
|
+
const { DaemonClient } = await import(join2(mcpDir, "dist/lib/daemon-client.js"));
|
|
405
462
|
const paths = getDaemonPaths();
|
|
406
463
|
const client = new DaemonClient(paths.socketPath);
|
|
407
464
|
log.step("Rebuilding search index via daemon...");
|
|
@@ -418,7 +475,7 @@ function getDbPath(memoryDir) {
|
|
|
418
475
|
const stripped = resolved.replace(/\/docs\/memory$/, "").replace(/\/memory$/, "");
|
|
419
476
|
const id = stripped.replace(/\//g, "-");
|
|
420
477
|
const home = homedir();
|
|
421
|
-
const dbPath =
|
|
478
|
+
const dbPath = join2(
|
|
422
479
|
home,
|
|
423
480
|
".coding-friend",
|
|
424
481
|
"memory",
|
|
@@ -426,7 +483,7 @@ function getDbPath(memoryDir) {
|
|
|
426
483
|
id,
|
|
427
484
|
"db.sqlite"
|
|
428
485
|
);
|
|
429
|
-
return
|
|
486
|
+
return existsSync2(dbPath) ? dbPath : null;
|
|
430
487
|
} catch {
|
|
431
488
|
return null;
|
|
432
489
|
}
|
|
@@ -435,7 +492,7 @@ async function ensureSqliteDepsIfNeeded(mcpDir) {
|
|
|
435
492
|
const config = loadConfig();
|
|
436
493
|
const tier = config.memory?.tier ?? "auto";
|
|
437
494
|
if (tier === "markdown" || tier === "lite") return true;
|
|
438
|
-
const { ensureDeps, areSqliteDepsAvailable } = await import(
|
|
495
|
+
const { ensureDeps, areSqliteDepsAvailable } = await import(join2(mcpDir, "dist/lib/lazy-install.js"));
|
|
439
496
|
if (areSqliteDepsAvailable()) return true;
|
|
440
497
|
log.step("Installing SQLite dependencies...");
|
|
441
498
|
const installed = await ensureDeps({
|
|
@@ -506,7 +563,7 @@ async function memoryInitWizard(memoryDir, mcpDir) {
|
|
|
506
563
|
}
|
|
507
564
|
const depsOk = await ensureSqliteDepsIfNeeded(mcpDir);
|
|
508
565
|
if (!depsOk) return;
|
|
509
|
-
if (!
|
|
566
|
+
if (!existsSync2(memoryDir)) {
|
|
510
567
|
log.info(
|
|
511
568
|
"No memory directory found. Memories will be indexed as they're created."
|
|
512
569
|
);
|
|
@@ -522,7 +579,7 @@ async function memoryInitWizard(memoryDir, mcpDir) {
|
|
|
522
579
|
return;
|
|
523
580
|
}
|
|
524
581
|
log.step(`Importing ${docCount} existing memories into SQLite...`);
|
|
525
|
-
const { SqliteBackend } = await import(
|
|
582
|
+
const { SqliteBackend } = await import(join2(mcpDir, "dist/backends/sqlite/index.js"));
|
|
526
583
|
const embedding = config.memory?.embedding;
|
|
527
584
|
const backend = new SqliteBackend(memoryDir, {
|
|
528
585
|
skipVec: false,
|
|
@@ -533,7 +590,7 @@ async function memoryInitWizard(memoryDir, mcpDir) {
|
|
|
533
590
|
const stats = await backend.stats();
|
|
534
591
|
log.success(`Imported ${stats.total} memories. DB: ${backend.getDbPath()}`);
|
|
535
592
|
log.info(
|
|
536
|
-
`Vector search: ${backend.isVecEnabled() ?
|
|
593
|
+
`Vector search: ${backend.isVecEnabled() ? chalk2.green("enabled") : chalk2.dim("disabled (sqlite-vec not available)")}`
|
|
537
594
|
);
|
|
538
595
|
} finally {
|
|
539
596
|
await backend.close();
|
|
@@ -542,13 +599,13 @@ async function memoryInitWizard(memoryDir, mcpDir) {
|
|
|
542
599
|
console.log();
|
|
543
600
|
log.success('Memory initialized! Run "cf memory status" to verify.');
|
|
544
601
|
log.info(
|
|
545
|
-
`Tip: Run ${
|
|
602
|
+
`Tip: Run ${chalk2.cyan("/cf-scan")} in Claude Code to populate memory with project knowledge.`
|
|
546
603
|
);
|
|
547
604
|
}
|
|
548
|
-
async function setupMemoryMcp(memoryDir,
|
|
605
|
+
async function setupMemoryMcp(memoryDir, _mcpDir) {
|
|
549
606
|
const mcpStatus = getMemoryMcpStatus();
|
|
550
607
|
if (mcpStatus.configured && mcpStatus.scope === "local") {
|
|
551
|
-
log.info(`MCP: ${
|
|
608
|
+
log.info(`MCP: ${chalk2.green("already configured")} in .mcp.json`);
|
|
552
609
|
return;
|
|
553
610
|
}
|
|
554
611
|
console.log();
|
|
@@ -564,14 +621,7 @@ async function setupMemoryMcp(memoryDir, mcpDir) {
|
|
|
564
621
|
log.dim('Skipped. Run "cf memory mcp" anytime to get the config.');
|
|
565
622
|
return;
|
|
566
623
|
}
|
|
567
|
-
|
|
568
|
-
if (!existsSync(serverPath)) {
|
|
569
|
-
log.warn(
|
|
570
|
-
"cf-memory not built yet. Run `cf memory mcp` after building to get the config."
|
|
571
|
-
);
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
writeMemoryMcpEntry(serverPath, memoryDir);
|
|
624
|
+
writeMemoryMcpEntry(memoryDir);
|
|
575
625
|
}
|
|
576
626
|
async function memoryInitCommand() {
|
|
577
627
|
const memoryDir = getMemoryDir();
|
|
@@ -604,7 +654,7 @@ async function memoryConfigCommand() {
|
|
|
604
654
|
}
|
|
605
655
|
function getProjectsBaseDir() {
|
|
606
656
|
const home = homedir();
|
|
607
|
-
return
|
|
657
|
+
return join2(home, ".coding-friend", "memory", "projects");
|
|
608
658
|
}
|
|
609
659
|
function formatSize(bytes) {
|
|
610
660
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -622,9 +672,9 @@ function formatDate(raw) {
|
|
|
622
672
|
}
|
|
623
673
|
function dirSize(dir) {
|
|
624
674
|
let total = 0;
|
|
625
|
-
if (!
|
|
675
|
+
if (!existsSync2(dir)) return 0;
|
|
626
676
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
627
|
-
const p =
|
|
677
|
+
const p = join2(dir, entry.name);
|
|
628
678
|
if (entry.isFile()) {
|
|
629
679
|
total += statSync(p).size;
|
|
630
680
|
} else if (entry.isDirectory()) {
|
|
@@ -634,7 +684,7 @@ function dirSize(dir) {
|
|
|
634
684
|
return total;
|
|
635
685
|
}
|
|
636
686
|
function getProjectInfo(projectDir, projectId, mcpDir, knownSourceDir) {
|
|
637
|
-
const dbPath =
|
|
687
|
+
const dbPath = join2(projectDir, "db.sqlite");
|
|
638
688
|
const size = dirSize(projectDir);
|
|
639
689
|
const info = {
|
|
640
690
|
id: projectId,
|
|
@@ -643,7 +693,7 @@ function getProjectInfo(projectDir, projectId, mcpDir, knownSourceDir) {
|
|
|
643
693
|
size,
|
|
644
694
|
lastUpdated: null
|
|
645
695
|
};
|
|
646
|
-
if (!
|
|
696
|
+
if (!existsSync2(dbPath)) return info;
|
|
647
697
|
try {
|
|
648
698
|
const backfillDir = knownSourceDir ? JSON.stringify(knownSourceDir) : "null";
|
|
649
699
|
const result = run(
|
|
@@ -684,7 +734,7 @@ async function memoryListProjectsCommand() {
|
|
|
684
734
|
const baseDir = getProjectsBaseDir();
|
|
685
735
|
const mcpDir = getLibPath("cf-memory");
|
|
686
736
|
ensureMemoryBuilt(mcpDir);
|
|
687
|
-
if (!
|
|
737
|
+
if (!existsSync2(baseDir)) {
|
|
688
738
|
log.info("No memory projects found.");
|
|
689
739
|
log.dim('Run "cf memory init" in a project to create one.');
|
|
690
740
|
return;
|
|
@@ -695,35 +745,35 @@ async function memoryListProjectsCommand() {
|
|
|
695
745
|
return;
|
|
696
746
|
}
|
|
697
747
|
const currentMemoryDir = resolve(getMemoryDir());
|
|
698
|
-
const { projectId } = await import(
|
|
748
|
+
const { projectId } = await import(join2(mcpDir, "dist/backends/sqlite/index.js"));
|
|
699
749
|
const currentProjectId = projectId(currentMemoryDir);
|
|
700
750
|
log.step(`Scanning ${dirs.length} project(s)...
|
|
701
751
|
`);
|
|
702
752
|
const projects = [];
|
|
703
753
|
for (const id of dirs) {
|
|
704
754
|
const knownDir = id === currentProjectId ? currentMemoryDir : void 0;
|
|
705
|
-
projects.push(getProjectInfo(
|
|
755
|
+
projects.push(getProjectInfo(join2(baseDir, id), id, mcpDir, knownDir));
|
|
706
756
|
}
|
|
707
757
|
projects.sort((a, b) => b.size - a.size);
|
|
708
758
|
const totalSize = projects.reduce((sum, p) => sum + p.size, 0);
|
|
709
759
|
const idxW = String(projects.length).length;
|
|
710
760
|
const header = `${"#".padStart(idxW)} ${"SIZE".padStart(10)} ${"MEMS".padStart(4)} ${"PROJECT ID".padEnd(12)} ${"UPDATED".padEnd(16)} PATH`;
|
|
711
|
-
console.log(
|
|
712
|
-
console.log(
|
|
761
|
+
console.log(chalk2.bold(header));
|
|
762
|
+
console.log(chalk2.dim("-".repeat(header.length + 10)));
|
|
713
763
|
projects.forEach((p, i) => {
|
|
714
|
-
const idx =
|
|
715
|
-
const sizeStr =
|
|
716
|
-
const memCount =
|
|
717
|
-
const idStr =
|
|
718
|
-
const dateStr = p.lastUpdated ? formatDate(p.lastUpdated).padEnd(16) :
|
|
719
|
-
const pathStr = p.sourceDir ?
|
|
764
|
+
const idx = chalk2.dim(String(i + 1).padStart(idxW));
|
|
765
|
+
const sizeStr = chalk2.yellow(formatSize(p.size).padStart(10));
|
|
766
|
+
const memCount = chalk2.green(String(p.memories).padStart(4));
|
|
767
|
+
const idStr = chalk2.cyan(p.id.padEnd(12));
|
|
768
|
+
const dateStr = p.lastUpdated ? formatDate(p.lastUpdated).padEnd(16) : chalk2.dim("n/a".padEnd(16));
|
|
769
|
+
const pathStr = p.sourceDir ? chalk2.dim(p.sourceDir) : chalk2.dim("(unknown)");
|
|
720
770
|
console.log(
|
|
721
771
|
`${idx} ${sizeStr} ${memCount} ${idStr} ${dateStr} ${pathStr}`
|
|
722
772
|
);
|
|
723
773
|
});
|
|
724
774
|
console.log();
|
|
725
775
|
console.log(
|
|
726
|
-
|
|
776
|
+
chalk2.bold(
|
|
727
777
|
`Total: ${projects.length} project(s), ${formatSize(totalSize)}`
|
|
728
778
|
)
|
|
729
779
|
);
|
|
@@ -731,7 +781,7 @@ async function memoryListProjectsCommand() {
|
|
|
731
781
|
}
|
|
732
782
|
async function memoryRmCommand(opts) {
|
|
733
783
|
const baseDir = getProjectsBaseDir();
|
|
734
|
-
if (!
|
|
784
|
+
if (!existsSync2(baseDir)) {
|
|
735
785
|
log.info("No memory projects found. Nothing to remove.");
|
|
736
786
|
return;
|
|
737
787
|
}
|
|
@@ -741,9 +791,9 @@ async function memoryRmCommand(opts) {
|
|
|
741
791
|
const dirs = readdirSync(baseDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name);
|
|
742
792
|
const orphaned = [];
|
|
743
793
|
for (const id of dirs) {
|
|
744
|
-
const projectDir =
|
|
794
|
+
const projectDir = join2(baseDir, id);
|
|
745
795
|
const info = getProjectInfo(projectDir, id, mcpDir);
|
|
746
|
-
if (info.sourceDir && !
|
|
796
|
+
if (info.sourceDir && !existsSync2(info.sourceDir)) {
|
|
747
797
|
orphaned.push({
|
|
748
798
|
id,
|
|
749
799
|
reason: `source dir missing: ${info.sourceDir}`,
|
|
@@ -767,7 +817,7 @@ async function memoryRmCommand(opts) {
|
|
|
767
817
|
);
|
|
768
818
|
console.log();
|
|
769
819
|
for (const o of orphaned) {
|
|
770
|
-
console.log(` ${
|
|
820
|
+
console.log(` ${chalk2.cyan(o.id)} ${chalk2.dim(o.reason)}`);
|
|
771
821
|
}
|
|
772
822
|
console.log();
|
|
773
823
|
const ok = await confirm({
|
|
@@ -779,7 +829,7 @@ async function memoryRmCommand(opts) {
|
|
|
779
829
|
return;
|
|
780
830
|
}
|
|
781
831
|
for (const o of orphaned) {
|
|
782
|
-
rmSync(
|
|
832
|
+
rmSync(join2(baseDir, o.id), { recursive: true, force: true });
|
|
783
833
|
}
|
|
784
834
|
log.success(
|
|
785
835
|
`Deleted ${orphaned.length} orphaned project(s) (${formatSize(totalSize)}).`
|
|
@@ -795,7 +845,7 @@ async function memoryRmCommand(opts) {
|
|
|
795
845
|
return;
|
|
796
846
|
}
|
|
797
847
|
const totalSize = dirs.reduce(
|
|
798
|
-
(sum, d) => sum + dirSize(
|
|
848
|
+
(sum, d) => sum + dirSize(join2(baseDir, d.name)),
|
|
799
849
|
0
|
|
800
850
|
);
|
|
801
851
|
log.warn(
|
|
@@ -812,19 +862,19 @@ async function memoryRmCommand(opts) {
|
|
|
812
862
|
return;
|
|
813
863
|
}
|
|
814
864
|
for (const d of dirs) {
|
|
815
|
-
rmSync(
|
|
865
|
+
rmSync(join2(baseDir, d.name), { recursive: true, force: true });
|
|
816
866
|
}
|
|
817
867
|
log.success(`Deleted ${dirs.length} project database(s).`);
|
|
818
868
|
return;
|
|
819
869
|
}
|
|
820
870
|
if (opts.projectId) {
|
|
821
|
-
const projectDir =
|
|
871
|
+
const projectDir = join2(baseDir, opts.projectId);
|
|
822
872
|
const resolved = resolve(projectDir);
|
|
823
873
|
if (!resolved.startsWith(resolve(baseDir) + sep)) {
|
|
824
874
|
log.error("Invalid project ID.");
|
|
825
875
|
process.exit(1);
|
|
826
876
|
}
|
|
827
|
-
if (!
|
|
877
|
+
if (!existsSync2(projectDir)) {
|
|
828
878
|
log.error(`Project "${opts.projectId}" not found.`);
|
|
829
879
|
log.dim('Run "cf memory list --projects" to see available projects.');
|
|
830
880
|
process.exit(1);
|
|
@@ -855,11 +905,14 @@ async function memoryMcpCommand() {
|
|
|
855
905
|
const memoryDir = getMemoryDir();
|
|
856
906
|
const mcpDir = getLibPath("cf-memory");
|
|
857
907
|
ensureMemoryBuilt(mcpDir);
|
|
858
|
-
|
|
908
|
+
warnStaleMcpJson(memoryDir);
|
|
909
|
+
const serverPath = join2(mcpDir, "dist", "index.js");
|
|
859
910
|
printMemoryMcpConfig(serverPath, memoryDir);
|
|
860
911
|
}
|
|
861
912
|
|
|
862
913
|
export {
|
|
914
|
+
warnStaleMcpJson,
|
|
915
|
+
detectMemoryMcpState,
|
|
863
916
|
ensureMemoryBuilt,
|
|
864
917
|
printMemoryMcpConfig,
|
|
865
918
|
memoryStatusCommand,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getLibPath
|
|
3
|
-
} from "./chunk-RZRT7NGT.js";
|
|
4
1
|
import {
|
|
5
2
|
resolveMemoryDir
|
|
6
3
|
} from "./chunk-GTX6I57V.js";
|
|
4
|
+
import {
|
|
5
|
+
getLibPath
|
|
6
|
+
} from "./chunk-RZRT7NGT.js";
|
|
7
7
|
import {
|
|
8
8
|
BACK,
|
|
9
9
|
askScope,
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
} from "./chunk-5UVDWG5L.js";
|
|
25
25
|
|
|
26
26
|
// src/lib/memory-prompts.ts
|
|
27
|
-
import { existsSync } from "fs";
|
|
28
27
|
import { homedir } from "os";
|
|
29
28
|
import { confirm, input, select } from "@inquirer/prompts";
|
|
30
29
|
import chalk from "chalk";
|
|
@@ -219,7 +218,7 @@ async function editMemoryEmbedding(globalCfg, localCfg) {
|
|
|
219
218
|
if (ollamaUrl) embedding.ollamaUrl = ollamaUrl;
|
|
220
219
|
writeMemoryField(scope, "embedding", embedding);
|
|
221
220
|
}
|
|
222
|
-
function writeMemoryMcpEntry(
|
|
221
|
+
function writeMemoryMcpEntry(memoryDir) {
|
|
223
222
|
const mcpPath = join(process.cwd(), ".mcp.json");
|
|
224
223
|
const existing = readJson(mcpPath) ?? {};
|
|
225
224
|
const servers = existing.mcpServers ?? {};
|
|
@@ -228,8 +227,8 @@ function writeMemoryMcpEntry(serverPath, memoryDir) {
|
|
|
228
227
|
mcpServers: {
|
|
229
228
|
...servers,
|
|
230
229
|
"coding-friend-memory": {
|
|
231
|
-
command: "
|
|
232
|
-
args: [
|
|
230
|
+
command: "npx",
|
|
231
|
+
args: ["-y", "coding-friend-cli", "mcp-serve", memoryDir]
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
});
|
|
@@ -261,24 +260,8 @@ async function editMemoryMcp() {
|
|
|
261
260
|
});
|
|
262
261
|
if (!reconfigure) return;
|
|
263
262
|
}
|
|
264
|
-
let mcpDir;
|
|
265
|
-
try {
|
|
266
|
-
mcpDir = getLibPath("cf-memory");
|
|
267
|
-
} catch {
|
|
268
|
-
log.warn(
|
|
269
|
-
"cf-memory package not found. Install the CLI first: npm i -g coding-friend-cli"
|
|
270
|
-
);
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
const serverPath = join(mcpDir, "dist", "index.js");
|
|
274
|
-
if (!existsSync(serverPath)) {
|
|
275
|
-
log.warn(
|
|
276
|
-
'cf-memory not built yet. Run "cf memory mcp" after building to get the config.'
|
|
277
|
-
);
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
263
|
const memoryDir = resolveMemoryDir();
|
|
281
|
-
writeMemoryMcpEntry(
|
|
264
|
+
writeMemoryMcpEntry(memoryDir);
|
|
282
265
|
}
|
|
283
266
|
async function memoryConfigMenu(opts) {
|
|
284
267
|
while (true) {
|
package/dist/index.js
CHANGED
|
@@ -30,21 +30,25 @@ program.command("enable").description("Re-enable the Coding Friend plugin").opti
|
|
|
30
30
|
await enableCommand(opts);
|
|
31
31
|
});
|
|
32
32
|
program.command("init").description("Initialize coding-friend in current project").action(async () => {
|
|
33
|
-
const { initCommand } = await import("./init-
|
|
33
|
+
const { initCommand } = await import("./init-3UITY4LD.js");
|
|
34
34
|
await initCommand();
|
|
35
35
|
});
|
|
36
36
|
program.command("config").description("Manage Coding Friend configuration").action(async () => {
|
|
37
|
-
const { configCommand } = await import("./config-
|
|
37
|
+
const { configCommand } = await import("./config-FUEEFM5N.js");
|
|
38
38
|
await configCommand();
|
|
39
39
|
});
|
|
40
40
|
program.command("host").description("Build and serve learning docs as a static website").argument("[path]", "path to docs folder").option("-p, --port <port>", "port number", "3333").action(async (path, opts) => {
|
|
41
|
-
const { hostCommand } = await import("./host-
|
|
41
|
+
const { hostCommand } = await import("./host-RNYPAE4D.js");
|
|
42
42
|
await hostCommand(path, opts);
|
|
43
43
|
});
|
|
44
44
|
program.command("mcp").description("Setup MCP server for learning docs").argument("[path]", "path to docs folder").action(async (path) => {
|
|
45
|
-
const { mcpCommand } = await import("./mcp-
|
|
45
|
+
const { mcpCommand } = await import("./mcp-LJ5NX6XE.js");
|
|
46
46
|
await mcpCommand(path);
|
|
47
47
|
});
|
|
48
|
+
program.command("mcp-serve").description("Start the cf-memory MCP server (used internally by npx)").argument("<memoryDir>", "path to memory directory").action(async (memoryDir) => {
|
|
49
|
+
const { mcpServeCommand } = await import("./mcp-serve-3FEPFVVQ.js");
|
|
50
|
+
await mcpServeCommand(memoryDir);
|
|
51
|
+
});
|
|
48
52
|
program.command("permission").description("Manage Claude Code permission rules for Coding Friend").option("--all", "Apply all recommended permissions without prompts").option("--user", "Save to user-level settings (~/.claude/settings.json)").option(
|
|
49
53
|
"--project",
|
|
50
54
|
"Save to project-level settings (.claude/settings.local.json)"
|
|
@@ -61,7 +65,7 @@ program.command("update").description("Update coding-friend plugin, CLI, and sta
|
|
|
61
65
|
await updateCommand(opts);
|
|
62
66
|
});
|
|
63
67
|
program.command("status").description("Show comprehensive Coding Friend status").action(async () => {
|
|
64
|
-
const { statusCommand } = await import("./status-
|
|
68
|
+
const { statusCommand } = await import("./status-FU5GR3MP.js");
|
|
65
69
|
await statusCommand();
|
|
66
70
|
});
|
|
67
71
|
var session = program.command("session").description("Save and load Claude Code sessions across machines");
|
|
@@ -100,43 +104,43 @@ Memory subcommands:
|
|
|
100
104
|
memory mcp Show MCP server setup instructions`
|
|
101
105
|
);
|
|
102
106
|
memory.command("status").description("Show memory system status").action(async () => {
|
|
103
|
-
const { memoryStatusCommand } = await import("./memory-
|
|
107
|
+
const { memoryStatusCommand } = await import("./memory-2ZD4WU3S.js");
|
|
104
108
|
await memoryStatusCommand();
|
|
105
109
|
});
|
|
106
110
|
memory.command("search").description("Search memories by query").argument("<query>", "search query").action(async (query) => {
|
|
107
|
-
const { memorySearchCommand } = await import("./memory-
|
|
111
|
+
const { memorySearchCommand } = await import("./memory-2ZD4WU3S.js");
|
|
108
112
|
await memorySearchCommand(query);
|
|
109
113
|
});
|
|
110
114
|
memory.command("list").description(
|
|
111
115
|
"List memories in current project, or all projects with --projects"
|
|
112
116
|
).option("--projects", "List all project databases with size and metadata").action(async (opts) => {
|
|
113
|
-
const { memoryListCommand } = await import("./memory-
|
|
117
|
+
const { memoryListCommand } = await import("./memory-2ZD4WU3S.js");
|
|
114
118
|
await memoryListCommand(opts);
|
|
115
119
|
});
|
|
116
120
|
memory.command("init").description(
|
|
117
121
|
"Initialize memory system \u2014 interactive wizard (first time) or config menu"
|
|
118
122
|
).action(async () => {
|
|
119
|
-
const { memoryInitCommand } = await import("./memory-
|
|
123
|
+
const { memoryInitCommand } = await import("./memory-2ZD4WU3S.js");
|
|
120
124
|
await memoryInitCommand();
|
|
121
125
|
});
|
|
122
126
|
memory.command("config").description("Configure memory system settings").action(async () => {
|
|
123
|
-
const { memoryConfigCommand } = await import("./memory-
|
|
127
|
+
const { memoryConfigCommand } = await import("./memory-2ZD4WU3S.js");
|
|
124
128
|
await memoryConfigCommand();
|
|
125
129
|
});
|
|
126
130
|
memory.command("start-daemon").description("Start the memory daemon (Tier 2 \u2014 MiniSearch)").action(async () => {
|
|
127
|
-
const { memoryStartDaemonCommand } = await import("./memory-
|
|
131
|
+
const { memoryStartDaemonCommand } = await import("./memory-2ZD4WU3S.js");
|
|
128
132
|
await memoryStartDaemonCommand();
|
|
129
133
|
});
|
|
130
134
|
memory.command("stop-daemon").description("Stop the memory daemon").action(async () => {
|
|
131
|
-
const { memoryStopDaemonCommand } = await import("./memory-
|
|
135
|
+
const { memoryStopDaemonCommand } = await import("./memory-2ZD4WU3S.js");
|
|
132
136
|
await memoryStopDaemonCommand();
|
|
133
137
|
});
|
|
134
138
|
memory.command("rebuild").description("Rebuild the daemon search index").action(async () => {
|
|
135
|
-
const { memoryRebuildCommand } = await import("./memory-
|
|
139
|
+
const { memoryRebuildCommand } = await import("./memory-2ZD4WU3S.js");
|
|
136
140
|
await memoryRebuildCommand();
|
|
137
141
|
});
|
|
138
142
|
memory.command("mcp").description("Show MCP server setup instructions").action(async () => {
|
|
139
|
-
const { memoryMcpCommand } = await import("./memory-
|
|
143
|
+
const { memoryMcpCommand } = await import("./memory-2ZD4WU3S.js");
|
|
140
144
|
await memoryMcpCommand();
|
|
141
145
|
});
|
|
142
146
|
memory.command("rm").description("Remove a project database").option("--project-id <id>", "Project ID to remove").option("--all", "Remove all project databases").option(
|
|
@@ -144,7 +148,7 @@ memory.command("rm").description("Remove a project database").option("--project-
|
|
|
144
148
|
"Remove orphaned projects (source dir missing or 0 memories)"
|
|
145
149
|
).action(
|
|
146
150
|
async (opts) => {
|
|
147
|
-
const { memoryRmCommand } = await import("./memory-
|
|
151
|
+
const { memoryRmCommand } = await import("./memory-2ZD4WU3S.js");
|
|
148
152
|
await memoryRmCommand(opts);
|
|
149
153
|
}
|
|
150
154
|
);
|
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
ensureMemoryBuilt,
|
|
3
3
|
isMemoryInitialized,
|
|
4
4
|
memoryInitWizard
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-355AR2X5.js";
|
|
6
6
|
import {
|
|
7
7
|
memoryConfigMenu
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-5W7ZOVDU.js";
|
|
9
|
+
import "./chunk-GTX6I57V.js";
|
|
9
10
|
import {
|
|
10
11
|
getLibPath
|
|
11
12
|
} from "./chunk-RZRT7NGT.js";
|
|
12
|
-
import "./chunk-GTX6I57V.js";
|
|
13
13
|
import {
|
|
14
14
|
findStatuslineHookPath,
|
|
15
15
|
getCurrentAccountEmail,
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
detectMemoryMcpState,
|
|
2
3
|
ensureMemoryBuilt,
|
|
3
|
-
printMemoryMcpConfig
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
getLibPath
|
|
8
|
-
} from "./chunk-RZRT7NGT.js";
|
|
4
|
+
printMemoryMcpConfig,
|
|
5
|
+
warnStaleMcpJson
|
|
6
|
+
} from "./chunk-355AR2X5.js";
|
|
7
|
+
import "./chunk-5W7ZOVDU.js";
|
|
9
8
|
import {
|
|
10
9
|
resolveDocsDir,
|
|
11
10
|
resolveMemoryDir
|
|
12
11
|
} from "./chunk-GTX6I57V.js";
|
|
12
|
+
import {
|
|
13
|
+
getLibPath
|
|
14
|
+
} from "./chunk-RZRT7NGT.js";
|
|
13
15
|
import "./chunk-DHH6SRXV.js";
|
|
14
16
|
import "./chunk-HPNRQYLM.js";
|
|
15
17
|
import {
|
|
@@ -38,6 +40,7 @@ function countMdFiles(dir) {
|
|
|
38
40
|
return count;
|
|
39
41
|
}
|
|
40
42
|
async function mcpCommand(path) {
|
|
43
|
+
warnStaleMcpJson(resolveMemoryDir());
|
|
41
44
|
const docsDir = resolveDocsDir(path);
|
|
42
45
|
const mcpDir = getLibPath("learn-mcp");
|
|
43
46
|
if (!existsSync(docsDir)) {
|
|
@@ -152,5 +155,6 @@ function printMemoryMcp() {
|
|
|
152
155
|
printMemoryMcpConfig(serverPath, memoryDir);
|
|
153
156
|
}
|
|
154
157
|
export {
|
|
158
|
+
detectMemoryMcpState,
|
|
155
159
|
mcpCommand
|
|
156
160
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLibPath
|
|
3
|
+
} from "./chunk-RZRT7NGT.js";
|
|
4
|
+
import {
|
|
5
|
+
log
|
|
6
|
+
} from "./chunk-NREZK463.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/mcp-serve.ts
|
|
9
|
+
import { spawn } from "child_process";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
async function mcpServeCommand(memoryDir) {
|
|
12
|
+
const mcpDir = getLibPath("cf-memory");
|
|
13
|
+
const serverPath = join(mcpDir, "dist", "index.js");
|
|
14
|
+
const child = spawn("node", [serverPath, memoryDir], {
|
|
15
|
+
stdio: "inherit"
|
|
16
|
+
});
|
|
17
|
+
child.on("error", (err) => {
|
|
18
|
+
log.error(`Failed to start memory MCP server: ${err.message}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
});
|
|
21
|
+
child.on("exit", (code) => {
|
|
22
|
+
process.exit(code ?? 0);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
mcpServeCommand
|
|
27
|
+
};
|
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
memoryStatusCommand,
|
|
14
14
|
memoryStopDaemonCommand,
|
|
15
15
|
printMemoryMcpConfig
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-RZRT7NGT.js";
|
|
16
|
+
} from "./chunk-355AR2X5.js";
|
|
17
|
+
import "./chunk-5W7ZOVDU.js";
|
|
19
18
|
import "./chunk-GTX6I57V.js";
|
|
19
|
+
import "./chunk-RZRT7NGT.js";
|
|
20
20
|
import "./chunk-DHH6SRXV.js";
|
|
21
21
|
import "./chunk-HPNRQYLM.js";
|
|
22
22
|
import "./chunk-EVGXUDX4.js";
|
package/package.json
CHANGED