memextend 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/dist/commands/edit.d.ts +2 -0
- package/dist/commands/edit.d.ts.map +1 -0
- package/dist/commands/edit.js +84 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/export.d.ts +8 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +88 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/forget.d.ts +10 -0
- package/dist/commands/forget.d.ts.map +1 -0
- package/dist/commands/forget.js +199 -0
- package/dist/commands/forget.js.map +1 -0
- package/dist/commands/help.d.ts +2 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +437 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/commands/import.d.ts +7 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +138 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +258 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +7 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +67 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/save.d.ts +8 -0
- package/dist/commands/save.d.ts.map +1 -0
- package/dist/commands/save.js +95 -0
- package/dist/commands/save.js.map +1 -0
- package/dist/commands/search.d.ts +8 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +82 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +231 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +7 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +188 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/webui.d.ts +7 -0
- package/dist/commands/webui.d.ts.map +1 -0
- package/dist/commands/webui.js +314 -0
- package/dist/commands/webui.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +97 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// apps/cli/src/commands/init.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { mkdir, writeFile, readFile } from 'fs/promises';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
const MEMEXTEND_DIR = join(homedir(), '.memextend');
|
|
10
|
+
const CONFIG_PATH = join(MEMEXTEND_DIR, 'config.json');
|
|
11
|
+
const DB_PATH = join(MEMEXTEND_DIR, 'memextend.db');
|
|
12
|
+
const VECTORS_PATH = join(MEMEXTEND_DIR, 'vectors');
|
|
13
|
+
const MODELS_PATH = join(MEMEXTEND_DIR, 'models');
|
|
14
|
+
const CLAUDE_DIR = join(homedir(), '.claude');
|
|
15
|
+
const CLAUDE_SETTINGS_PATH = join(CLAUDE_DIR, 'settings.json');
|
|
16
|
+
const CLAUDE_MD_PATH = join(CLAUDE_DIR, 'CLAUDE.md');
|
|
17
|
+
const CLAUDE_MD_TEMPLATE = `# memextend - AI Memory Extension
|
|
18
|
+
|
|
19
|
+
You have persistent memory across sessions via memextend.
|
|
20
|
+
|
|
21
|
+
## Available MCP Tools
|
|
22
|
+
|
|
23
|
+
- **memextend_search** - Search your memories for past decisions, patterns, or context
|
|
24
|
+
Example: "How did we implement caching?" → Use memextend_search to find relevant memories
|
|
25
|
+
|
|
26
|
+
- **memextend_save** - Save important decisions or context for this project
|
|
27
|
+
Example: After making an architectural decision, save it for future reference
|
|
28
|
+
|
|
29
|
+
- **memextend_save_global** - Save cross-project preferences (coding style, preferred tools)
|
|
30
|
+
Example: "User prefers TypeScript strict mode" → Save as global preference
|
|
31
|
+
|
|
32
|
+
- **memextend_forget** - Delete a specific memory by ID
|
|
33
|
+
|
|
34
|
+
- **memextend_status** - Check memory statistics and system status
|
|
35
|
+
|
|
36
|
+
## When to Use Memory
|
|
37
|
+
|
|
38
|
+
**Search memories when:**
|
|
39
|
+
- Starting work on a project you've worked on before
|
|
40
|
+
- The user references past decisions ("like we did before", "as discussed")
|
|
41
|
+
- You need context about project architecture or conventions
|
|
42
|
+
|
|
43
|
+
**Save memories when:**
|
|
44
|
+
- Making significant architectural decisions
|
|
45
|
+
- Establishing project conventions or patterns
|
|
46
|
+
- The user shares important preferences
|
|
47
|
+
- Completing a major feature or fix
|
|
48
|
+
|
|
49
|
+
## Memory is Automatic
|
|
50
|
+
|
|
51
|
+
Memories are automatically captured from your sessions and injected at startup.
|
|
52
|
+
Use the tools above to actively search for more detail or save important context.
|
|
53
|
+
`;
|
|
54
|
+
const DEFAULT_CONFIG = {
|
|
55
|
+
version: 1,
|
|
56
|
+
storage: {
|
|
57
|
+
path: MEMEXTEND_DIR,
|
|
58
|
+
sqlite: 'memextend.db',
|
|
59
|
+
vectors: 'vectors',
|
|
60
|
+
},
|
|
61
|
+
embedding: {
|
|
62
|
+
model: 'nomic-embed-text-v1.5-GGUF',
|
|
63
|
+
dimensions: 384,
|
|
64
|
+
},
|
|
65
|
+
capture: {
|
|
66
|
+
tools: ['Edit', 'Write', 'Bash', 'Task'],
|
|
67
|
+
skipTools: ['Read', 'Glob', 'Grep', 'TodoWrite', 'AskUserQuestion'],
|
|
68
|
+
maxContentLength: 2000,
|
|
69
|
+
},
|
|
70
|
+
retrieval: {
|
|
71
|
+
autoInject: true,
|
|
72
|
+
maxMemories: 0,
|
|
73
|
+
recentDays: 0,
|
|
74
|
+
includeGlobal: true,
|
|
75
|
+
},
|
|
76
|
+
adapters: {
|
|
77
|
+
'claude-code': {
|
|
78
|
+
enabled: true,
|
|
79
|
+
hooksRegistered: false,
|
|
80
|
+
mcpRegistered: false,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
export async function initCommand(options) {
|
|
85
|
+
console.log(chalk.bold('\n memextend v0.1.0\n'));
|
|
86
|
+
if (options.manual) {
|
|
87
|
+
printManualInstructions();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const spinner = ora();
|
|
91
|
+
try {
|
|
92
|
+
// Step 1: Create directories
|
|
93
|
+
spinner.start('Creating memextend directory...');
|
|
94
|
+
await mkdir(MEMEXTEND_DIR, { recursive: true });
|
|
95
|
+
await mkdir(VECTORS_PATH, { recursive: true });
|
|
96
|
+
await mkdir(MODELS_PATH, { recursive: true });
|
|
97
|
+
spinner.succeed('Created ~/.memextend/');
|
|
98
|
+
// Step 2: Initialize SQLite database
|
|
99
|
+
spinner.start('Initializing SQLite database...');
|
|
100
|
+
const { SQLiteStorage } = await import('@memextend/core');
|
|
101
|
+
const sqlite = new SQLiteStorage(DB_PATH);
|
|
102
|
+
sqlite.close();
|
|
103
|
+
spinner.succeed('Initialized SQLite database');
|
|
104
|
+
// Step 3: Initialize LanceDB
|
|
105
|
+
spinner.start('Initializing LanceDB vectors...');
|
|
106
|
+
const { LanceDBStorage } = await import('@memextend/core');
|
|
107
|
+
const lancedb = await LanceDBStorage.create(VECTORS_PATH);
|
|
108
|
+
await lancedb.close();
|
|
109
|
+
spinner.succeed('Initialized LanceDB vectors');
|
|
110
|
+
// Step 4: Write config
|
|
111
|
+
spinner.start('Writing configuration...');
|
|
112
|
+
await writeFile(CONFIG_PATH, JSON.stringify(DEFAULT_CONFIG, null, 2));
|
|
113
|
+
spinner.succeed('Configuration saved');
|
|
114
|
+
// Step 5: Register with Claude Code
|
|
115
|
+
spinner.start('Registering with Claude Code...');
|
|
116
|
+
const registered = await registerWithClaudeCode();
|
|
117
|
+
if (registered) {
|
|
118
|
+
spinner.succeed('Registered hooks and MCP server with Claude Code');
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
spinner.warn('Could not auto-register with Claude Code (see manual instructions)');
|
|
122
|
+
}
|
|
123
|
+
// Step 6: Create CLAUDE.md template
|
|
124
|
+
spinner.start('Creating CLAUDE.md template...');
|
|
125
|
+
const claudeMdCreated = await createClaudeMd();
|
|
126
|
+
if (claudeMdCreated) {
|
|
127
|
+
spinner.succeed('Created ~/.claude/CLAUDE.md with memory tool guidance');
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
spinner.warn('CLAUDE.md already exists (skipped)');
|
|
131
|
+
}
|
|
132
|
+
// Done!
|
|
133
|
+
console.log(chalk.green('\n ✅ memextend is ready!\n'));
|
|
134
|
+
console.log(' Start a new Claude Code session to begin building memory.\n');
|
|
135
|
+
if (!registered) {
|
|
136
|
+
console.log(chalk.yellow(' Note: Run `memextend init --manual` for manual setup instructions.\n'));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
spinner.fail('Initialization failed');
|
|
141
|
+
console.error(chalk.red(`\n Error: ${error instanceof Error ? error.message : error}\n`));
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async function registerWithClaudeCode() {
|
|
146
|
+
try {
|
|
147
|
+
// Check if Claude Code settings exist
|
|
148
|
+
if (!existsSync(CLAUDE_SETTINGS_PATH)) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
const settingsContent = await readFile(CLAUDE_SETTINGS_PATH, 'utf-8');
|
|
152
|
+
const settings = JSON.parse(settingsContent);
|
|
153
|
+
// Add hooks configuration
|
|
154
|
+
if (!settings.hooks) {
|
|
155
|
+
settings.hooks = {};
|
|
156
|
+
}
|
|
157
|
+
// Find the installed package location
|
|
158
|
+
const packagePath = findPackagePath();
|
|
159
|
+
if (!packagePath) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
const hooksPath = join(packagePath, 'packages', 'adapters', 'claude-code', 'dist', 'hooks');
|
|
163
|
+
const mcpPath = join(packagePath, 'packages', 'adapters', 'claude-code', 'dist', 'mcp');
|
|
164
|
+
// Register SessionStart hook
|
|
165
|
+
settings.hooks.SessionStart = {
|
|
166
|
+
command: 'node',
|
|
167
|
+
args: [join(hooksPath, 'session-start.cjs')],
|
|
168
|
+
timeout: 30000,
|
|
169
|
+
};
|
|
170
|
+
// Register Stop hook
|
|
171
|
+
settings.hooks.Stop = {
|
|
172
|
+
command: 'node',
|
|
173
|
+
args: [join(hooksPath, 'stop.cjs')],
|
|
174
|
+
timeout: 30000,
|
|
175
|
+
};
|
|
176
|
+
// Register MCP server
|
|
177
|
+
if (!settings.mcpServers) {
|
|
178
|
+
settings.mcpServers = {};
|
|
179
|
+
}
|
|
180
|
+
settings.mcpServers.memextend = {
|
|
181
|
+
command: 'node',
|
|
182
|
+
args: [join(mcpPath, 'server.cjs')],
|
|
183
|
+
};
|
|
184
|
+
// Write updated settings
|
|
185
|
+
await writeFile(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2));
|
|
186
|
+
// Update our config to reflect registration
|
|
187
|
+
const config = { ...DEFAULT_CONFIG };
|
|
188
|
+
config.adapters['claude-code'].hooksRegistered = true;
|
|
189
|
+
config.adapters['claude-code'].mcpRegistered = true;
|
|
190
|
+
await writeFile(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function findPackagePath() {
|
|
198
|
+
// Try to find the installed package
|
|
199
|
+
// For now, return null and rely on manual setup
|
|
200
|
+
// In production, this would resolve the npm package location
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
async function createClaudeMd() {
|
|
204
|
+
try {
|
|
205
|
+
// Create .claude directory if it doesn't exist
|
|
206
|
+
await mkdir(CLAUDE_DIR, { recursive: true });
|
|
207
|
+
// Check if CLAUDE.md already exists
|
|
208
|
+
if (existsSync(CLAUDE_MD_PATH)) {
|
|
209
|
+
// Check if it already contains memextend section
|
|
210
|
+
const existing = await readFile(CLAUDE_MD_PATH, 'utf-8');
|
|
211
|
+
if (existing.includes('memextend')) {
|
|
212
|
+
return false; // Already has memextend content
|
|
213
|
+
}
|
|
214
|
+
// Append to existing file
|
|
215
|
+
await writeFile(CLAUDE_MD_PATH, existing + '\n\n' + CLAUDE_MD_TEMPLATE);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
// Create new file
|
|
219
|
+
await writeFile(CLAUDE_MD_PATH, CLAUDE_MD_TEMPLATE);
|
|
220
|
+
}
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function printManualInstructions() {
|
|
228
|
+
console.log(chalk.bold('Manual Configuration Instructions\n'));
|
|
229
|
+
console.log('1. Create the memextend directory:');
|
|
230
|
+
console.log(chalk.cyan(' mkdir -p ~/.memextend\n'));
|
|
231
|
+
console.log('2. Add the following to your Claude Code settings (~/.claude/settings.json):');
|
|
232
|
+
console.log(chalk.cyan(`
|
|
233
|
+
{
|
|
234
|
+
"hooks": {
|
|
235
|
+
"SessionStart": {
|
|
236
|
+
"command": "node",
|
|
237
|
+
"args": ["/path/to/memextend/dist/hooks/session-start.cjs"],
|
|
238
|
+
"timeout": 30000
|
|
239
|
+
},
|
|
240
|
+
"Stop": {
|
|
241
|
+
"command": "node",
|
|
242
|
+
"args": ["/path/to/memextend/dist/hooks/stop.cjs"],
|
|
243
|
+
"timeout": 30000
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
"mcpServers": {
|
|
247
|
+
"memextend": {
|
|
248
|
+
"command": "node",
|
|
249
|
+
"args": ["/path/to/memextend/dist/mcp/server.cjs"]
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
`));
|
|
254
|
+
console.log('3. Replace /path/to/memextend with the actual installation path.');
|
|
255
|
+
console.log(' You can find it by running: npm root -g\n');
|
|
256
|
+
console.log('4. Restart Claude Code to apply changes.\n');
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAaA,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CrE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// apps/cli/src/commands/list.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
import { createHash } from 'crypto';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
const MEMEXTEND_DIR = join(homedir(), '.memextend');
|
|
10
|
+
const DB_PATH = join(MEMEXTEND_DIR, 'memextend.db');
|
|
11
|
+
export async function listCommand(options) {
|
|
12
|
+
if (!existsSync(DB_PATH)) {
|
|
13
|
+
console.log(chalk.yellow('\n ⚠ memextend not initialized. Run `memextend init` first.\n'));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const { SQLiteStorage } = await import('@memextend/core');
|
|
18
|
+
const sqlite = new SQLiteStorage(DB_PATH);
|
|
19
|
+
const limit = parseInt(options.limit ?? '20', 10);
|
|
20
|
+
let projectId;
|
|
21
|
+
if (options.project) {
|
|
22
|
+
projectId = getProjectId(process.cwd());
|
|
23
|
+
}
|
|
24
|
+
const memories = sqlite.getAllMemories(projectId, limit);
|
|
25
|
+
console.log(chalk.bold(`\n Recent Memories${options.project ? ' (current project)' : ''}\n`));
|
|
26
|
+
if (memories.length === 0) {
|
|
27
|
+
console.log(chalk.yellow(' No memories found.\n'));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
memories.forEach((memory, i) => {
|
|
31
|
+
const preview = memory.content.split('\n')[0].slice(0, 70);
|
|
32
|
+
const date = formatDate(memory.createdAt);
|
|
33
|
+
const type = memory.sourceTool ? `[${memory.sourceTool}]` : '[manual]';
|
|
34
|
+
console.log(` ${chalk.cyan(`${i + 1}.`)} ${chalk.dim(type)} ${preview}`);
|
|
35
|
+
console.log(chalk.dim(` Date: ${date} | ID: ${memory.id}\n`));
|
|
36
|
+
});
|
|
37
|
+
console.log(chalk.dim(` Showing ${memories.length} of ${sqlite.getMemoryCount()} total memories.\n`));
|
|
38
|
+
}
|
|
39
|
+
sqlite.close();
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error(chalk.red(`\n Error: ${error instanceof Error ? error.message : error}\n`));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function getProjectId(cwd) {
|
|
47
|
+
try {
|
|
48
|
+
const gitRoot = execSync('git rev-parse --show-toplevel', {
|
|
49
|
+
cwd,
|
|
50
|
+
encoding: 'utf-8',
|
|
51
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
52
|
+
}).trim();
|
|
53
|
+
return createHash('sha256').update(gitRoot).digest('hex').slice(0, 16);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function formatDate(isoDate) {
|
|
60
|
+
const date = new Date(isoDate);
|
|
61
|
+
return date.toLocaleDateString('en-US', {
|
|
62
|
+
year: 'numeric',
|
|
63
|
+
month: 'short',
|
|
64
|
+
day: 'numeric',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../../src/commands/save.ts"],"names":[],"mappings":"AAcA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA+FrE"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// apps/cli/src/commands/save.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { createInterface } from 'readline';
|
|
8
|
+
import { randomUUID } from 'crypto';
|
|
9
|
+
const MEMEXTEND_DIR = join(homedir(), '.memextend');
|
|
10
|
+
const DB_PATH = join(MEMEXTEND_DIR, 'memextend.db');
|
|
11
|
+
const VECTORS_PATH = join(MEMEXTEND_DIR, 'vectors');
|
|
12
|
+
export async function saveCommand(options) {
|
|
13
|
+
if (!existsSync(DB_PATH)) {
|
|
14
|
+
console.log(chalk.yellow('\n memextend not initialized. Run `memextend init` first.\n'));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const { SQLiteStorage, LanceDBStorage, LocalEmbedding, getCurrentProjectId } = await import('@memextend/core');
|
|
19
|
+
let content = options.message;
|
|
20
|
+
// If no message provided, prompt for content interactively
|
|
21
|
+
if (!content) {
|
|
22
|
+
console.log(chalk.cyan('\n Enter memory content (press Enter twice to finish, or Ctrl+C to cancel):\n'));
|
|
23
|
+
const rl = createInterface({
|
|
24
|
+
input: process.stdin,
|
|
25
|
+
output: process.stdout,
|
|
26
|
+
});
|
|
27
|
+
const lines = [];
|
|
28
|
+
let emptyLineCount = 0;
|
|
29
|
+
content = await new Promise((resolve) => {
|
|
30
|
+
const askLine = () => {
|
|
31
|
+
rl.question(' > ', (line) => {
|
|
32
|
+
if (line === '') {
|
|
33
|
+
emptyLineCount++;
|
|
34
|
+
if (emptyLineCount >= 2) {
|
|
35
|
+
rl.close();
|
|
36
|
+
resolve(lines.join('\n').trim());
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
emptyLineCount = 0;
|
|
42
|
+
}
|
|
43
|
+
lines.push(line);
|
|
44
|
+
askLine();
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
askLine();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (!content) {
|
|
51
|
+
console.log(chalk.yellow('\n No content provided. Memory not saved.\n'));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Determine project ID
|
|
55
|
+
let projectId = null;
|
|
56
|
+
if (!options.global) {
|
|
57
|
+
projectId = options.project || getCurrentProjectId();
|
|
58
|
+
if (!projectId) {
|
|
59
|
+
console.log(chalk.yellow('\n Could not determine project. Use --global for global memory or --project <id>.\n'));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Initialize storage
|
|
64
|
+
const sqlite = new SQLiteStorage(DB_PATH);
|
|
65
|
+
const lancedb = await LanceDBStorage.create(VECTORS_PATH);
|
|
66
|
+
const embedder = await LocalEmbedding.create(MEMEXTEND_DIR);
|
|
67
|
+
// Create memory
|
|
68
|
+
const memoryId = randomUUID();
|
|
69
|
+
const memory = {
|
|
70
|
+
id: memoryId,
|
|
71
|
+
projectId,
|
|
72
|
+
content,
|
|
73
|
+
type: 'manual',
|
|
74
|
+
sourceTool: null,
|
|
75
|
+
createdAt: new Date().toISOString(),
|
|
76
|
+
sessionId: null,
|
|
77
|
+
metadata: null
|
|
78
|
+
};
|
|
79
|
+
// Save to SQLite
|
|
80
|
+
sqlite.insertMemory(memory);
|
|
81
|
+
// Generate and save embedding
|
|
82
|
+
const embedding = await embedder.embed(content);
|
|
83
|
+
await lancedb.insertVector(memoryId, embedding);
|
|
84
|
+
sqlite.close();
|
|
85
|
+
await lancedb.close();
|
|
86
|
+
const scope = projectId ? `project: ${projectId.slice(0, 8)}...` : 'global';
|
|
87
|
+
console.log(chalk.green(`\n Memory saved (${scope})`));
|
|
88
|
+
console.log(chalk.dim(` ID: ${memoryId}\n`));
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error(chalk.red(`\n Error: ${error instanceof Error ? error.message : error}\n`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.js","sourceRoot":"","sources":["../../src/commands/save.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAaA,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA0ExF"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// apps/cli/src/commands/search.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
const MEMEXTEND_DIR = join(homedir(), '.memextend');
|
|
8
|
+
const DB_PATH = join(MEMEXTEND_DIR, 'memextend.db');
|
|
9
|
+
const VECTORS_PATH = join(MEMEXTEND_DIR, 'vectors');
|
|
10
|
+
const MODELS_PATH = join(MEMEXTEND_DIR, 'models');
|
|
11
|
+
export async function searchCommand(query, options) {
|
|
12
|
+
if (!existsSync(DB_PATH)) {
|
|
13
|
+
console.log(chalk.yellow('\n ⚠ memextend not initialized. Run `memextend init` first.\n'));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const { SQLiteStorage, LanceDBStorage, MemoryRetriever, createEmbedFunction, getProjectId } = await import('@memextend/core');
|
|
18
|
+
const sqlite = new SQLiteStorage(DB_PATH);
|
|
19
|
+
const lancedb = await LanceDBStorage.create(VECTORS_PATH);
|
|
20
|
+
// Create embedding function (uses real model if available)
|
|
21
|
+
const embedder = await createEmbedFunction(MODELS_PATH);
|
|
22
|
+
const retriever = new MemoryRetriever(sqlite, lancedb, embedder.embedQuery);
|
|
23
|
+
const limit = parseInt(options.limit ?? '10', 10);
|
|
24
|
+
let projectId;
|
|
25
|
+
if (options.project) {
|
|
26
|
+
projectId = getProjectId(process.cwd());
|
|
27
|
+
}
|
|
28
|
+
// Perform search
|
|
29
|
+
console.log(chalk.bold(`\n Searching for: "${query}"`));
|
|
30
|
+
if (!embedder.isReal) {
|
|
31
|
+
console.log(chalk.dim(' (Using fallback embeddings - run `memextend init` to download model)\n'));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log('');
|
|
35
|
+
}
|
|
36
|
+
let results;
|
|
37
|
+
if (options.global) {
|
|
38
|
+
// Search global profile only
|
|
39
|
+
const profiles = sqlite.getGlobalProfiles(limit);
|
|
40
|
+
console.log(chalk.dim(` Found ${profiles.length} global profile entries:\n`));
|
|
41
|
+
profiles.forEach((profile, i) => {
|
|
42
|
+
console.log(` ${i + 1}. [${profile.key}] ${profile.content}`);
|
|
43
|
+
console.log(chalk.dim(` Created: ${formatDate(profile.createdAt)}\n`));
|
|
44
|
+
});
|
|
45
|
+
sqlite.close();
|
|
46
|
+
await lancedb.close();
|
|
47
|
+
await embedder.close();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
results = await retriever.hybridSearch(query, { limit, projectId });
|
|
51
|
+
if (results.length === 0) {
|
|
52
|
+
console.log(chalk.yellow(' No memories found matching your query.\n'));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log(chalk.dim(` Found ${results.length} memories:\n`));
|
|
56
|
+
results.forEach((result, i) => {
|
|
57
|
+
const { memory, score, source } = result;
|
|
58
|
+
const preview = memory.content.split('\n')[0].slice(0, 80);
|
|
59
|
+
const date = formatDate(memory.createdAt);
|
|
60
|
+
console.log(` ${chalk.cyan(`${i + 1}.`)} ${preview}`);
|
|
61
|
+
console.log(chalk.dim(` Score: ${score.toFixed(3)} | Source: ${source} | Date: ${date}`));
|
|
62
|
+
console.log(chalk.dim(` ID: ${memory.id}\n`));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
sqlite.close();
|
|
66
|
+
await lancedb.close();
|
|
67
|
+
await embedder.close();
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error(chalk.red(`\n Error: ${error instanceof Error ? error.message : error}\n`));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function formatDate(isoDate) {
|
|
75
|
+
const date = new Date(isoDate);
|
|
76
|
+
return date.toLocaleDateString('en-US', {
|
|
77
|
+
year: 'numeric',
|
|
78
|
+
month: 'short',
|
|
79
|
+
day: 'numeric',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAgBA,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA0EzE"}
|