claude-conversation-memory-mcp 0.1.0 โ 0.2.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/README.md +88 -0
- package/dist/cli/commands.d.ts +9 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +572 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/help.d.ts +16 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +255 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +111 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/embeddings/ConfigManager.d.ts +46 -0
- package/dist/embeddings/ConfigManager.d.ts.map +1 -0
- package/dist/embeddings/ConfigManager.js +177 -0
- package/dist/embeddings/ConfigManager.js.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts.map +1 -1
- package/dist/embeddings/providers/OpenAIEmbeddings.js +1 -2
- package/dist/embeddings/providers/OpenAIEmbeddings.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +49 -115
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +22 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +120 -0
- package/dist/mcp-server.js.map +1 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -93,6 +93,94 @@ Start Claude Code CLI and ask:
|
|
|
93
93
|
|
|
94
94
|
If you see a response like "Indexed 3 conversations with 1247 messages", it's working!
|
|
95
95
|
|
|
96
|
+
## ๐ฅ๏ธ Standalone CLI / REPL Mode
|
|
97
|
+
|
|
98
|
+
Beyond the MCP server, this package includes a powerful **standalone CLI** for managing your conversation memory directly from the terminal.
|
|
99
|
+
|
|
100
|
+
### Three Modes of Operation
|
|
101
|
+
|
|
102
|
+
**1. Interactive REPL Mode** (Default)
|
|
103
|
+
```bash
|
|
104
|
+
claude-conversation-memory-mcp
|
|
105
|
+
# Starts interactive shell with 40+ commands
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**2. Single Command Mode**
|
|
109
|
+
```bash
|
|
110
|
+
claude-conversation-memory-mcp status
|
|
111
|
+
claude-conversation-memory-mcp "search authentication"
|
|
112
|
+
claude-conversation-memory-mcp mistakes --limit 5
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**3. MCP Server Mode** (Used by Claude Code CLI)
|
|
116
|
+
```bash
|
|
117
|
+
claude-conversation-memory-mcp --server
|
|
118
|
+
# Or automatically via stdio from Claude Code CLI
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Quick CLI Examples
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# View database status
|
|
125
|
+
claude-conversation-memory-mcp status
|
|
126
|
+
|
|
127
|
+
# Index conversations
|
|
128
|
+
claude-conversation-memory-mcp index --include-mcp
|
|
129
|
+
|
|
130
|
+
# Search for topics
|
|
131
|
+
claude-conversation-memory-mcp "search database migration" --limit 3
|
|
132
|
+
|
|
133
|
+
# Find past mistakes
|
|
134
|
+
claude-conversation-memory-mcp mistakes "async" --type logic_error
|
|
135
|
+
|
|
136
|
+
# Check file context before editing
|
|
137
|
+
claude-conversation-memory-mcp check src/auth.ts
|
|
138
|
+
|
|
139
|
+
# Configure embedding model
|
|
140
|
+
claude-conversation-memory-mcp config
|
|
141
|
+
claude-conversation-memory-mcp set model mxbai-embed-large
|
|
142
|
+
claude-conversation-memory-mcp set dimensions 1024
|
|
143
|
+
|
|
144
|
+
# View help
|
|
145
|
+
claude-conversation-memory-mcp help
|
|
146
|
+
claude-conversation-memory-mcp "help search"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Configuration Management
|
|
150
|
+
|
|
151
|
+
The CLI includes built-in commands for managing embedding models and dimensions:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# View current configuration
|
|
155
|
+
claude-conversation-memory-mcp config
|
|
156
|
+
|
|
157
|
+
# Switch to Ollama with mxbai-embed-large (1024 dimensions)
|
|
158
|
+
claude-conversation-memory-mcp set provider ollama
|
|
159
|
+
claude-conversation-memory-mcp set model mxbai-embed-large
|
|
160
|
+
claude-conversation-memory-mcp set dimensions 1024
|
|
161
|
+
|
|
162
|
+
# Switch to Transformers.js (offline, no setup)
|
|
163
|
+
claude-conversation-memory-mcp set provider transformers
|
|
164
|
+
claude-conversation-memory-mcp set model Xenova/all-MiniLM-L6-v2
|
|
165
|
+
claude-conversation-memory-mcp set dimensions 384
|
|
166
|
+
|
|
167
|
+
# Get specific config value
|
|
168
|
+
claude-conversation-memory-mcp get provider
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Available Commands
|
|
172
|
+
|
|
173
|
+
- **๐ฅ Indexing**: `index`, `reindex`
|
|
174
|
+
- **๐ Search**: `search`, `decisions`, `mistakes`, `similar`
|
|
175
|
+
- **๐ Files**: `check`, `history`
|
|
176
|
+
- **๐ Git**: `commits`
|
|
177
|
+
- **๐ Other**: `requirements`, `tools`, `docs`
|
|
178
|
+
- **โน๏ธ Info**: `status`, `version`, `help`
|
|
179
|
+
- **โ๏ธ Config**: `config`, `get`, `set`
|
|
180
|
+
- **๐งน Maintenance**: `vacuum`, `reset`
|
|
181
|
+
|
|
182
|
+
**๐ See [Complete CLI Guide](docs/CLI-USAGE.md) for all commands, examples, and workflows**
|
|
183
|
+
|
|
96
184
|
## ๐ฏ Usage Examples
|
|
97
185
|
|
|
98
186
|
### First Time Setup
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command execution and parsing for CLI
|
|
3
|
+
*/
|
|
4
|
+
import { ToolHandlers } from "../tools/ToolHandlers.js";
|
|
5
|
+
/**
|
|
6
|
+
* Execute a command
|
|
7
|
+
*/
|
|
8
|
+
export declare function executeCommand(input: string, handlers: ToolHandlers): Promise<string | null>;
|
|
9
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAqCxD;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4JxB"}
|
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command execution and parsing for CLI
|
|
3
|
+
*/
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import Table from "cli-table3";
|
|
6
|
+
import { getSQLiteManager } from "../storage/SQLiteManager.js";
|
|
7
|
+
import { showHelp, showCommandHelp } from "./help.js";
|
|
8
|
+
import { ConfigManager } from "../embeddings/ConfigManager.js";
|
|
9
|
+
/**
|
|
10
|
+
* Parse command line arguments
|
|
11
|
+
*/
|
|
12
|
+
function parseArgs(input) {
|
|
13
|
+
const parts = input.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
|
|
14
|
+
const command = parts[0] || "";
|
|
15
|
+
const rest = parts.slice(1);
|
|
16
|
+
const args = [];
|
|
17
|
+
const options = {};
|
|
18
|
+
for (let i = 0; i < rest.length; i++) {
|
|
19
|
+
const part = rest[i];
|
|
20
|
+
if (part.startsWith("--")) {
|
|
21
|
+
const key = part.slice(2);
|
|
22
|
+
const nextPart = rest[i + 1];
|
|
23
|
+
if (nextPart && !nextPart.startsWith("--")) {
|
|
24
|
+
options[key] = nextPart.replace(/^"(.*)"$/, "$1");
|
|
25
|
+
i++;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
options[key] = true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
args.push(part.replace(/^"(.*)"$/, "$1"));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { command, args, options };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Execute a command
|
|
39
|
+
*/
|
|
40
|
+
export async function executeCommand(input, handlers) {
|
|
41
|
+
const { command, args, options } = parseArgs(input);
|
|
42
|
+
// Handle exit commands
|
|
43
|
+
if (command === "exit" || command === "quit" || command === "q") {
|
|
44
|
+
return "exit";
|
|
45
|
+
}
|
|
46
|
+
// Handle clear
|
|
47
|
+
if (command === "clear") {
|
|
48
|
+
return "clear";
|
|
49
|
+
}
|
|
50
|
+
// Handle help
|
|
51
|
+
if (command === "help" || command === "?") {
|
|
52
|
+
if (args.length > 0) {
|
|
53
|
+
return showCommandHelp(args[0]);
|
|
54
|
+
}
|
|
55
|
+
return showHelp();
|
|
56
|
+
}
|
|
57
|
+
// Handle version
|
|
58
|
+
if (command === "version") {
|
|
59
|
+
return chalk.cyan("Claude Conversation Memory v0.2.0");
|
|
60
|
+
}
|
|
61
|
+
// Handle status/stats
|
|
62
|
+
if (command === "status" || command === "stats") {
|
|
63
|
+
return await handleStatus();
|
|
64
|
+
}
|
|
65
|
+
// Handle index
|
|
66
|
+
if (command === "index") {
|
|
67
|
+
return await handleIndex(handlers, options);
|
|
68
|
+
}
|
|
69
|
+
// Handle reindex
|
|
70
|
+
if (command === "reindex") {
|
|
71
|
+
return await handleReindex(handlers, options);
|
|
72
|
+
}
|
|
73
|
+
// Handle search
|
|
74
|
+
if (command === "search" || command === "find") {
|
|
75
|
+
if (args.length === 0) {
|
|
76
|
+
return chalk.yellow("Usage: search <query> [options]");
|
|
77
|
+
}
|
|
78
|
+
return await handleSearch(handlers, args.join(" "), options);
|
|
79
|
+
}
|
|
80
|
+
// Handle decisions
|
|
81
|
+
if (command === "decisions" || command === "why") {
|
|
82
|
+
if (args.length === 0) {
|
|
83
|
+
return chalk.yellow("Usage: decisions <topic> [options]");
|
|
84
|
+
}
|
|
85
|
+
return await handleDecisions(handlers, args.join(" "), options);
|
|
86
|
+
}
|
|
87
|
+
// Handle mistakes
|
|
88
|
+
if (command === "mistakes" || command === "errors") {
|
|
89
|
+
if (args.length === 0) {
|
|
90
|
+
return chalk.yellow("Usage: mistakes <query> [options]");
|
|
91
|
+
}
|
|
92
|
+
return await handleMistakes(handlers, args.join(" "), options);
|
|
93
|
+
}
|
|
94
|
+
// Handle check
|
|
95
|
+
if (command === "check") {
|
|
96
|
+
if (args.length === 0) {
|
|
97
|
+
return chalk.yellow("Usage: check <file>");
|
|
98
|
+
}
|
|
99
|
+
return await handleCheck(handlers, args[0]);
|
|
100
|
+
}
|
|
101
|
+
// Handle history/evolution
|
|
102
|
+
if (command === "history" || command === "evolution") {
|
|
103
|
+
if (args.length === 0) {
|
|
104
|
+
return chalk.yellow("Usage: history <file> [options]");
|
|
105
|
+
}
|
|
106
|
+
return await handleHistory(handlers, args[0], options);
|
|
107
|
+
}
|
|
108
|
+
// Handle commits/git
|
|
109
|
+
if (command === "commits" || command === "git") {
|
|
110
|
+
return await handleCommits(handlers, args.join(" "), options);
|
|
111
|
+
}
|
|
112
|
+
// Handle similar/related
|
|
113
|
+
if (command === "similar" || command === "related") {
|
|
114
|
+
if (args.length === 0) {
|
|
115
|
+
return chalk.yellow("Usage: similar <query> [options]");
|
|
116
|
+
}
|
|
117
|
+
return await handleSimilar(handlers, args.join(" "), options);
|
|
118
|
+
}
|
|
119
|
+
// Handle requirements/deps
|
|
120
|
+
if (command === "requirements" || command === "deps") {
|
|
121
|
+
if (args.length === 0) {
|
|
122
|
+
return chalk.yellow("Usage: requirements <component> [options]");
|
|
123
|
+
}
|
|
124
|
+
return await handleRequirements(handlers, args.join(" "), options);
|
|
125
|
+
}
|
|
126
|
+
// Handle tools
|
|
127
|
+
if (command === "tools" || command === "history-tools") {
|
|
128
|
+
return await handleTools(handlers, options);
|
|
129
|
+
}
|
|
130
|
+
// Handle docs/generate
|
|
131
|
+
if (command === "docs" || command === "generate") {
|
|
132
|
+
return await handleDocs(handlers, options);
|
|
133
|
+
}
|
|
134
|
+
// Handle reset
|
|
135
|
+
if (command === "reset") {
|
|
136
|
+
return await handleReset();
|
|
137
|
+
}
|
|
138
|
+
// Handle vacuum
|
|
139
|
+
if (command === "vacuum") {
|
|
140
|
+
return await handleVacuum();
|
|
141
|
+
}
|
|
142
|
+
// Handle config
|
|
143
|
+
if (command === "config") {
|
|
144
|
+
if (args.length === 0) {
|
|
145
|
+
return handleConfigShow();
|
|
146
|
+
}
|
|
147
|
+
else if (args.length === 2) {
|
|
148
|
+
return handleConfigSet(args[0], args[1]);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
return chalk.yellow("Usage: config (show current config)\n config <key> <value> (set config value)");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Handle get
|
|
155
|
+
if (command === "get") {
|
|
156
|
+
if (args.length === 0) {
|
|
157
|
+
return chalk.yellow("Usage: get <key>");
|
|
158
|
+
}
|
|
159
|
+
return handleConfigGet(args[0]);
|
|
160
|
+
}
|
|
161
|
+
// Handle set
|
|
162
|
+
if (command === "set") {
|
|
163
|
+
if (args.length < 2) {
|
|
164
|
+
return chalk.yellow("Usage: set <key> <value>");
|
|
165
|
+
}
|
|
166
|
+
return handleConfigSet(args[0], args[1]);
|
|
167
|
+
}
|
|
168
|
+
// Handle commands
|
|
169
|
+
if (command === "commands") {
|
|
170
|
+
return showHelp();
|
|
171
|
+
}
|
|
172
|
+
// Unknown command
|
|
173
|
+
return chalk.yellow(`Unknown command: ${command}\nType 'help' for available commands.`);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Handle status command
|
|
177
|
+
*/
|
|
178
|
+
async function handleStatus() {
|
|
179
|
+
const dbManager = getSQLiteManager();
|
|
180
|
+
const db = dbManager.getDatabase();
|
|
181
|
+
const stats = dbManager.getStats();
|
|
182
|
+
const dbPath = stats.dbPath.replace(process.env.HOME || "", "~");
|
|
183
|
+
// Query counts from database
|
|
184
|
+
const conversations = db.prepare("SELECT COUNT(*) as count FROM conversations").get().count;
|
|
185
|
+
const messages = db.prepare("SELECT COUNT(*) as count FROM messages").get().count;
|
|
186
|
+
const decisions = db.prepare("SELECT COUNT(*) as count FROM decisions").get().count;
|
|
187
|
+
const mistakes = db.prepare("SELECT COUNT(*) as count FROM mistakes").get().count;
|
|
188
|
+
const commits = db.prepare("SELECT COUNT(*) as count FROM git_commits").get().count;
|
|
189
|
+
const embeddings = db.prepare("SELECT COUNT(*) as count FROM message_embeddings").get().count;
|
|
190
|
+
const table = new Table({
|
|
191
|
+
head: [chalk.cyan("Metric"), chalk.cyan("Value")],
|
|
192
|
+
colWidths: [30, 30],
|
|
193
|
+
});
|
|
194
|
+
table.push(["Database", dbPath], ["Conversations", String(conversations)], ["Messages", String(messages)], ["Decisions", String(decisions)], ["Mistakes", String(mistakes)], ["Git Commits", String(commits)], ["Embeddings", String(embeddings)], ["Semantic Search", embeddings > 0 ? chalk.green("enabled") : chalk.yellow("disabled")]);
|
|
195
|
+
let output = "\n" + table.toString() + "\n";
|
|
196
|
+
if (conversations === 0) {
|
|
197
|
+
output += "\n" + chalk.yellow("โ ๏ธ No conversations indexed yet. Run 'index' to get started.\n");
|
|
198
|
+
}
|
|
199
|
+
return output;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Handle index command
|
|
203
|
+
*/
|
|
204
|
+
async function handleIndex(handlers, options) {
|
|
205
|
+
const args = {
|
|
206
|
+
project_path: typeof options.project === "string" ? options.project : process.cwd(),
|
|
207
|
+
};
|
|
208
|
+
if (typeof options.session === "string") {
|
|
209
|
+
args.session_id = options.session;
|
|
210
|
+
}
|
|
211
|
+
if (options["exclude-mcp"]) {
|
|
212
|
+
args.exclude_mcp_conversations = "all-mcp";
|
|
213
|
+
}
|
|
214
|
+
if (options["include-mcp"]) {
|
|
215
|
+
args.exclude_mcp_conversations = false;
|
|
216
|
+
}
|
|
217
|
+
if (options["no-git"]) {
|
|
218
|
+
args.enable_git = false;
|
|
219
|
+
}
|
|
220
|
+
if (options.thinking) {
|
|
221
|
+
args.include_thinking = true;
|
|
222
|
+
}
|
|
223
|
+
console.log(chalk.blue("Indexing conversations..."));
|
|
224
|
+
const result = await handlers.indexConversations(args);
|
|
225
|
+
return chalk.green(`\nโ Indexing complete!\n\n${JSON.stringify(result, null, 2)}`);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Handle reindex command
|
|
229
|
+
*/
|
|
230
|
+
async function handleReindex(handlers, options) {
|
|
231
|
+
console.log(chalk.yellow("โ ๏ธ This will clear all indexed data and re-index."));
|
|
232
|
+
console.log(chalk.yellow("Press Ctrl+C to cancel, or wait 3 seconds to continue..."));
|
|
233
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
234
|
+
// Clear database
|
|
235
|
+
const db = getSQLiteManager().getDatabase();
|
|
236
|
+
db.exec("DELETE FROM conversations");
|
|
237
|
+
db.exec("DELETE FROM messages");
|
|
238
|
+
db.exec("DELETE FROM decisions");
|
|
239
|
+
db.exec("DELETE FROM mistakes");
|
|
240
|
+
db.exec("DELETE FROM git_commits");
|
|
241
|
+
console.log(chalk.blue("Database cleared. Indexing conversations..."));
|
|
242
|
+
return await handleIndex(handlers, options);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Handle search command
|
|
246
|
+
*/
|
|
247
|
+
async function handleSearch(handlers, query, options) {
|
|
248
|
+
const args = { query };
|
|
249
|
+
if (typeof options.limit === "string") {
|
|
250
|
+
args.limit = parseInt(options.limit, 10);
|
|
251
|
+
}
|
|
252
|
+
const result = await handlers.searchConversations(args);
|
|
253
|
+
if (!result.results || result.results.length === 0) {
|
|
254
|
+
return chalk.yellow(`No results found for: ${query}`);
|
|
255
|
+
}
|
|
256
|
+
let output = chalk.green(`\nFound ${result.results.length} results:\n\n`);
|
|
257
|
+
result.results.forEach((r, i) => {
|
|
258
|
+
output += chalk.cyan(`${i + 1}. `) + `[${r.timestamp}] Session ${r.conversation_id.slice(0, 8)}\n`;
|
|
259
|
+
output += ` ${r.snippet.slice(0, 200)}${r.snippet.length > 200 ? "..." : ""}\n`;
|
|
260
|
+
output += chalk.gray(` Similarity: ${(r.similarity * 100).toFixed(1)}%\n\n`);
|
|
261
|
+
});
|
|
262
|
+
return output;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Handle decisions command
|
|
266
|
+
*/
|
|
267
|
+
async function handleDecisions(handlers, query, options) {
|
|
268
|
+
const args = { query };
|
|
269
|
+
if (typeof options.file === "string") {
|
|
270
|
+
args.file_path = options.file;
|
|
271
|
+
}
|
|
272
|
+
if (typeof options.limit === "string") {
|
|
273
|
+
args.limit = parseInt(options.limit, 10);
|
|
274
|
+
}
|
|
275
|
+
const result = await handlers.getDecisions(args);
|
|
276
|
+
if (!result.decisions || result.decisions.length === 0) {
|
|
277
|
+
return chalk.yellow(`No decisions found for: ${query}`);
|
|
278
|
+
}
|
|
279
|
+
let output = chalk.green(`\nFound ${result.decisions.length} decisions:\n\n`);
|
|
280
|
+
result.decisions.forEach((d, i) => {
|
|
281
|
+
output += chalk.cyan(`${i + 1}. ${d.decision_text}\n`);
|
|
282
|
+
output += ` Date: ${d.timestamp}\n`;
|
|
283
|
+
output += ` Rationale: ${d.rationale || "N/A"}\n`;
|
|
284
|
+
if (d.alternatives_considered && d.alternatives_considered.length > 0) {
|
|
285
|
+
output += ` Alternatives: ${d.alternatives_considered.join(", ")}\n`;
|
|
286
|
+
}
|
|
287
|
+
output += "\n";
|
|
288
|
+
});
|
|
289
|
+
return output;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Handle mistakes command
|
|
293
|
+
*/
|
|
294
|
+
async function handleMistakes(handlers, query, options) {
|
|
295
|
+
const args = { query };
|
|
296
|
+
if (typeof options.type === "string") {
|
|
297
|
+
args.mistake_type = options.type;
|
|
298
|
+
}
|
|
299
|
+
if (typeof options.limit === "string") {
|
|
300
|
+
args.limit = parseInt(options.limit, 10);
|
|
301
|
+
}
|
|
302
|
+
const result = await handlers.searchMistakes(args);
|
|
303
|
+
if (!result.mistakes || result.mistakes.length === 0) {
|
|
304
|
+
return chalk.yellow(`No mistakes found for: ${query}`);
|
|
305
|
+
}
|
|
306
|
+
let output = chalk.green(`\nFound ${result.mistakes.length} mistakes:\n\n`);
|
|
307
|
+
result.mistakes.forEach((m, i) => {
|
|
308
|
+
output += chalk.red(`${i + 1}. [${m.mistake_type}] ${m.what_went_wrong}\n`);
|
|
309
|
+
output += ` Date: ${m.timestamp}\n`;
|
|
310
|
+
output += chalk.green(` Fix: ${m.correction || m.user_correction_message || "N/A"}\n\n`);
|
|
311
|
+
});
|
|
312
|
+
return output;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Handle check command
|
|
316
|
+
*/
|
|
317
|
+
async function handleCheck(handlers, filePath) {
|
|
318
|
+
const result = await handlers.checkBeforeModify({ file_path: filePath });
|
|
319
|
+
return chalk.green(`\nContext for: ${filePath}\n\n`) + JSON.stringify(result, null, 2);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Handle history command
|
|
323
|
+
*/
|
|
324
|
+
async function handleHistory(handlers, filePath, options) {
|
|
325
|
+
const args = { file_path: filePath };
|
|
326
|
+
if (options["no-commits"]) {
|
|
327
|
+
args.include_commits = false;
|
|
328
|
+
}
|
|
329
|
+
if (options["no-decisions"]) {
|
|
330
|
+
args.include_decisions = false;
|
|
331
|
+
}
|
|
332
|
+
const result = await handlers.getFileEvolution(args);
|
|
333
|
+
return chalk.green(`\nFile evolution for: ${filePath}\n\n`) + JSON.stringify(result, null, 2);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Handle commits command
|
|
337
|
+
*/
|
|
338
|
+
async function handleCommits(handlers, query, options) {
|
|
339
|
+
const args = {};
|
|
340
|
+
if (query) {
|
|
341
|
+
args.query = query;
|
|
342
|
+
}
|
|
343
|
+
if (typeof options.conversation === "string") {
|
|
344
|
+
args.conversation_id = options.conversation;
|
|
345
|
+
}
|
|
346
|
+
if (typeof options.limit === "string") {
|
|
347
|
+
args.limit = parseInt(options.limit, 10);
|
|
348
|
+
}
|
|
349
|
+
const result = await handlers.linkCommitsToConversations(args);
|
|
350
|
+
return chalk.green("\nCommits linked to conversations:\n\n") + JSON.stringify(result, null, 2);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Handle similar command
|
|
354
|
+
*/
|
|
355
|
+
async function handleSimilar(handlers, query, options) {
|
|
356
|
+
const args = { query };
|
|
357
|
+
if (typeof options.limit === "string") {
|
|
358
|
+
args.limit = parseInt(options.limit, 10);
|
|
359
|
+
}
|
|
360
|
+
const result = await handlers.findSimilarSessions(args);
|
|
361
|
+
return chalk.green("\nSimilar sessions:\n\n") + JSON.stringify(result, null, 2);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Handle requirements command
|
|
365
|
+
*/
|
|
366
|
+
async function handleRequirements(handlers, component, options) {
|
|
367
|
+
const args = { component };
|
|
368
|
+
if (typeof options.type === "string") {
|
|
369
|
+
args.type = options.type;
|
|
370
|
+
}
|
|
371
|
+
const result = await handlers.getRequirements(args);
|
|
372
|
+
return chalk.green(`\nRequirements for: ${component}\n\n`) + JSON.stringify(result, null, 2);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Handle tools command
|
|
376
|
+
*/
|
|
377
|
+
async function handleTools(handlers, options) {
|
|
378
|
+
const args = {};
|
|
379
|
+
if (typeof options.file === "string") {
|
|
380
|
+
args.file_path = options.file;
|
|
381
|
+
}
|
|
382
|
+
if (typeof options.tool === "string") {
|
|
383
|
+
args.tool_name = options.tool;
|
|
384
|
+
}
|
|
385
|
+
if (typeof options.limit === "string") {
|
|
386
|
+
args.limit = parseInt(options.limit, 10);
|
|
387
|
+
}
|
|
388
|
+
const result = await handlers.getToolHistory(args);
|
|
389
|
+
return chalk.green("\nTool usage history:\n\n") + JSON.stringify(result, null, 2);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Handle docs command
|
|
393
|
+
*/
|
|
394
|
+
async function handleDocs(handlers, options) {
|
|
395
|
+
const args = {
|
|
396
|
+
project_path: process.cwd(),
|
|
397
|
+
};
|
|
398
|
+
if (typeof options.scope === "string") {
|
|
399
|
+
args.scope = options.scope;
|
|
400
|
+
}
|
|
401
|
+
if (typeof options.module === "string") {
|
|
402
|
+
args.module_filter = options.module;
|
|
403
|
+
}
|
|
404
|
+
console.log(chalk.blue("Generating documentation..."));
|
|
405
|
+
const result = await handlers.generateDocumentation(args);
|
|
406
|
+
return chalk.green("\nโ Documentation generated!\n\n") + JSON.stringify(result, null, 2);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Handle reset command
|
|
410
|
+
*/
|
|
411
|
+
async function handleReset() {
|
|
412
|
+
console.log(chalk.red("โ ๏ธ WARNING: This will delete ALL indexed data!"));
|
|
413
|
+
console.log(chalk.yellow("Press Ctrl+C to cancel, or wait 5 seconds to continue..."));
|
|
414
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
415
|
+
const db = getSQLiteManager().getDatabase();
|
|
416
|
+
db.exec("DELETE FROM conversations");
|
|
417
|
+
db.exec("DELETE FROM messages");
|
|
418
|
+
db.exec("DELETE FROM decisions");
|
|
419
|
+
db.exec("DELETE FROM mistakes");
|
|
420
|
+
db.exec("DELETE FROM git_commits");
|
|
421
|
+
return chalk.green("\nโ Database reset complete.\n");
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Handle vacuum command
|
|
425
|
+
*/
|
|
426
|
+
async function handleVacuum() {
|
|
427
|
+
const db = getSQLiteManager().getDatabase();
|
|
428
|
+
const beforeSize = db.prepare("PRAGMA page_count").get();
|
|
429
|
+
db.exec("VACUUM");
|
|
430
|
+
const afterSize = db.prepare("PRAGMA page_count").get();
|
|
431
|
+
const beforeKB = (beforeSize.page_count * 4096) / 1024;
|
|
432
|
+
const afterKB = (afterSize.page_count * 4096) / 1024;
|
|
433
|
+
return chalk.green(`\nโ Database vacuumed: ${beforeKB.toFixed(1)}KB โ ${afterKB.toFixed(1)}KB\n`);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Handle config show command
|
|
437
|
+
*/
|
|
438
|
+
function handleConfigShow() {
|
|
439
|
+
const sources = ConfigManager.getConfigSources();
|
|
440
|
+
const configPath = ConfigManager.getConfigPath();
|
|
441
|
+
const configExists = ConfigManager.configExists();
|
|
442
|
+
let output = chalk.cyan("\n=== Embedding Configuration ===\n\n");
|
|
443
|
+
// Show effective config
|
|
444
|
+
output += chalk.bold("Current (Effective) Configuration:\n");
|
|
445
|
+
const table = new Table({
|
|
446
|
+
head: [chalk.cyan("Key"), chalk.cyan("Value")],
|
|
447
|
+
colWidths: [20, 50],
|
|
448
|
+
});
|
|
449
|
+
table.push(["Provider", sources.effective.provider], ["Model", sources.effective.model], ["Dimensions", String(sources.effective.dimensions || "auto")], ["Base URL", sources.effective.baseUrl || "N/A"], ["API Key", sources.effective.apiKey ? "***" + sources.effective.apiKey.slice(-4) : "N/A"]);
|
|
450
|
+
output += table.toString() + "\n\n";
|
|
451
|
+
// Show sources breakdown
|
|
452
|
+
output += chalk.bold("Configuration Sources:\n\n");
|
|
453
|
+
if (sources.home) {
|
|
454
|
+
output += chalk.green(`โ Home Config: ${configPath}\n`);
|
|
455
|
+
output += ` Provider: ${sources.home.provider || "not set"}\n`;
|
|
456
|
+
output += ` Model: ${sources.home.model || "not set"}\n`;
|
|
457
|
+
output += ` Dimensions: ${sources.home.dimensions || "not set"}\n\n`;
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
output += chalk.gray(` Home Config: ${configPath} (not found)\n\n`);
|
|
461
|
+
}
|
|
462
|
+
if (sources.project) {
|
|
463
|
+
output += chalk.green("โ Project Config: .claude-memory-config.json\n");
|
|
464
|
+
output += ` Provider: ${sources.project.provider || "not set"}\n`;
|
|
465
|
+
output += ` Model: ${sources.project.model || "not set"}\n\n`;
|
|
466
|
+
}
|
|
467
|
+
if (Object.keys(sources.env).length > 0) {
|
|
468
|
+
output += chalk.green("โ Environment Variables:\n");
|
|
469
|
+
if (sources.env.provider) {
|
|
470
|
+
output += ` EMBEDDING_PROVIDER=${sources.env.provider}\n`;
|
|
471
|
+
}
|
|
472
|
+
if (sources.env.model) {
|
|
473
|
+
output += ` EMBEDDING_MODEL=${sources.env.model}\n`;
|
|
474
|
+
}
|
|
475
|
+
if (sources.env.dimensions) {
|
|
476
|
+
output += ` EMBEDDING_DIMENSIONS=${sources.env.dimensions}\n`;
|
|
477
|
+
}
|
|
478
|
+
if (sources.env.baseUrl) {
|
|
479
|
+
output += ` EMBEDDING_BASE_URL=${sources.env.baseUrl}\n`;
|
|
480
|
+
}
|
|
481
|
+
if (sources.env.apiKey) {
|
|
482
|
+
output += ` OPENAI_API_KEY=***\n`;
|
|
483
|
+
}
|
|
484
|
+
output += "\n";
|
|
485
|
+
}
|
|
486
|
+
// Show usage instructions
|
|
487
|
+
output += chalk.bold("Usage:\n");
|
|
488
|
+
output += ` ${chalk.cyan("config")} Show this config\n`;
|
|
489
|
+
output += ` ${chalk.cyan("config <key> <value>")} Set config value\n`;
|
|
490
|
+
output += ` ${chalk.cyan("get <key>")} Get specific value\n`;
|
|
491
|
+
output += ` ${chalk.cyan("set <key> <value>")} Set specific value\n\n`;
|
|
492
|
+
output += chalk.bold("Valid Keys:\n");
|
|
493
|
+
output += ` ${chalk.cyan("provider")} ollama, transformers, openai\n`;
|
|
494
|
+
output += ` ${chalk.cyan("model")} Model name (e.g., mxbai-embed-large)\n`;
|
|
495
|
+
output += ` ${chalk.cyan("dimensions")} Embedding dimensions (e.g., 1024)\n`;
|
|
496
|
+
output += ` ${chalk.cyan("baseUrl")} Ollama base URL (default: http://localhost:11434)\n`;
|
|
497
|
+
output += ` ${chalk.cyan("apiKey")} OpenAI API key\n\n`;
|
|
498
|
+
output += chalk.gray(`Config file location: ${configPath}\n`);
|
|
499
|
+
if (!configExists) {
|
|
500
|
+
output += chalk.yellow("Config file will be created on first 'set' command.\n");
|
|
501
|
+
}
|
|
502
|
+
return output;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Handle config get command
|
|
506
|
+
*/
|
|
507
|
+
function handleConfigGet(key) {
|
|
508
|
+
try {
|
|
509
|
+
const value = ConfigManager.getConfigValue(key);
|
|
510
|
+
if (value === undefined || value === null) {
|
|
511
|
+
return chalk.yellow(`Config key '${key}' is not set`);
|
|
512
|
+
}
|
|
513
|
+
// Mask API keys
|
|
514
|
+
if (key === "apiKey" || key === "api_key") {
|
|
515
|
+
const apiKey = value;
|
|
516
|
+
return chalk.green(`${key}: ***${apiKey.slice(-4)}`);
|
|
517
|
+
}
|
|
518
|
+
return chalk.green(`${key}: ${value}`);
|
|
519
|
+
}
|
|
520
|
+
catch (error) {
|
|
521
|
+
return chalk.red(`Error: ${error.message}`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Handle config set command
|
|
526
|
+
*/
|
|
527
|
+
function handleConfigSet(key, value) {
|
|
528
|
+
try {
|
|
529
|
+
ConfigManager.setConfigValue(key, value);
|
|
530
|
+
// Show confirmation with helpful info
|
|
531
|
+
let output = chalk.green(`โ Config updated: ${key} = ${value}\n\n`);
|
|
532
|
+
// If setting dimensions, suggest matching models
|
|
533
|
+
if (key === "dimensions") {
|
|
534
|
+
const dims = parseInt(value, 10);
|
|
535
|
+
output += chalk.cyan("Models with matching dimensions:\n");
|
|
536
|
+
if (dims === 384) {
|
|
537
|
+
output += " - Xenova/all-MiniLM-L6-v2 (transformers)\n";
|
|
538
|
+
output += " - all-minilm (ollama)\n";
|
|
539
|
+
}
|
|
540
|
+
else if (dims === 768) {
|
|
541
|
+
output += " - nomic-embed-text (ollama)\n";
|
|
542
|
+
output += " - Xenova/all-mpnet-base-v2 (transformers)\n";
|
|
543
|
+
}
|
|
544
|
+
else if (dims === 1024) {
|
|
545
|
+
output += " - mxbai-embed-large (ollama) โญ default\n";
|
|
546
|
+
output += " - snowflake-arctic-embed (ollama)\n";
|
|
547
|
+
}
|
|
548
|
+
else if (dims === 1536) {
|
|
549
|
+
output += " - text-embedding-3-small (openai)\n";
|
|
550
|
+
output += " - text-embedding-ada-002 (openai)\n";
|
|
551
|
+
}
|
|
552
|
+
else if (dims === 3072) {
|
|
553
|
+
output += " - text-embedding-3-large (openai)\n";
|
|
554
|
+
}
|
|
555
|
+
output += "\n";
|
|
556
|
+
}
|
|
557
|
+
// If setting model, suggest dimensions
|
|
558
|
+
if (key === "model") {
|
|
559
|
+
const knownDims = ConfigManager.getKnownModelDimensions(value);
|
|
560
|
+
if (knownDims) {
|
|
561
|
+
output += chalk.cyan(`๐ก Tip: This model uses ${knownDims} dimensions\n`);
|
|
562
|
+
output += ` Run: ${chalk.green(`set dimensions ${knownDims}`)}\n\n`;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
output += chalk.gray(`Config saved to: ${ConfigManager.getConfigPath()}\n`);
|
|
566
|
+
return output;
|
|
567
|
+
}
|
|
568
|
+
catch (error) {
|
|
569
|
+
return chalk.red(`Error: ${error.message}`);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
//# sourceMappingURL=commands.js.map
|