Skip to content

Commit 100d146

Browse files
committed
IDE v1.0.5
1 parent c4ef7f8 commit 100d146

File tree

8 files changed

+319
-13
lines changed

8 files changed

+319
-13
lines changed

IDE/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Give your AI tools instant access to your entire coding history. OpenMemory reme
77
- Works with GitHub Copilot, Cursor, Claude, Windsurf, Codex, and any MCP-compatible AI
88
- Auto-configures all AI tools on first run with zero manual setup
99
- Tracks every file edit, save, and open automatically
10+
- **NEW**: Manually add code selections to memory with a single click
1011
- Compresses memories to reduce tokens by 30-70%
1112
- Query responses under 80ms with smart caching
1213
- Real-time token savings and compression metrics
@@ -29,10 +30,14 @@ Backend server required.
2930
- `openmemory.apiKey`: API key for auth (optional)
3031
- `openmemory.useMCP`: Use MCP protocol mode (default: `false`) - connects to backend MCP server with tools: `openmemory_query`, `openmemory_store`, `openmemory_list`, `openmemory_get`, `openmemory_reinforce`
3132
- `openmemory.mcpServerPath`: Path to backend MCP server (default: `backend/dist/ai/mcp.js`)
33+
- `openmemory.userId`: Custom User ID (optional, defaults to auto-generated)
34+
- `openmemory.projectName`: Custom Project Name (optional, defaults to workspace name)
3235

3336
## Commands
3437

3538
- `OpenMemory: Query Context` - Search your coding memory
39+
- `OpenMemory: Add Selection to Memory` - Save selected code to memory
40+
- `OpenMemory: Quick Note` - Add a manual note to memory
3641
- `OpenMemory: View Patterns` - View detected patterns
3742
- `OpenMemory: Toggle Tracking` - Pause or resume tracking
3843
- `OpenMemory: Setup` - Configure backend and settings

IDE/package.json

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "openmemory-vscode",
33
"displayName": "OpenMemory for VS Code",
44
"description": "Cognitive memory system that remembers your coding context across sessions",
5-
"version": "1.0.3",
5+
"version": "1.0.5",
66
"publisher": "Nullure",
77
"icon": "icon.png",
88
"engines": {
@@ -12,6 +12,15 @@
1212
"Machine Learning",
1313
"Other"
1414
],
15+
"keywords": [
16+
"AI",
17+
"Memory",
18+
"Context",
19+
"Copilot",
20+
"Cursor",
21+
"Claude",
22+
"LLM"
23+
],
1524
"activationEvents": [
1625
"onStartupFinished"
1726
],
@@ -25,6 +34,18 @@
2534
{
2635
"command": "openmemory.queryContext",
2736
"title": "OpenMemory: Query Context"
37+
},
38+
{
39+
"command": "openmemory.addToMemory",
40+
"title": "OpenMemory: Add Selection to Memory"
41+
},
42+
{
43+
"command": "openmemory.quickNote",
44+
"title": "OpenMemory: Quick Note"
45+
},
46+
{
47+
"command": "openmemory.dashboard",
48+
"title": "OpenMemory: Dashboard"
2849
}
2950
],
3051
"configuration": {
@@ -54,6 +75,16 @@
5475
"type": "string",
5576
"default": "",
5677
"description": "Path to MCP server executable (leave empty to use built-in backend MCP)"
78+
},
79+
"openmemory.userId": {
80+
"type": "string",
81+
"default": "",
82+
"description": "Custom User ID for OpenMemory (leave empty to auto-generate)"
83+
},
84+
"openmemory.projectName": {
85+
"type": "string",
86+
"default": "",
87+
"description": "Custom Project Name (leave empty to use workspace name)"
5788
}
5889
}
5990
}

IDE/src/extension.ts

Lines changed: 105 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { writeClaudeConfig } from './writers/claude';
55
import { writeWindsurfConfig } from './writers/windsurf';
66
import { writeCopilotConfig } from './writers/copilot';
77
import { writeCodexConfig } from './writers/codex';
8+
import { DashboardPanel } from './panels/DashboardPanel';
89

910
let session_id: string | null = null;
1011
let backend_url = 'http://localhost:8080';
@@ -15,6 +16,7 @@ let auto_linked = false;
1516
let use_mcp = false;
1617
let mcp_server_path = '';
1718
let is_enabled = true;
19+
let user_id = '';
1820

1921
export function activate(context: vscode.ExtensionContext) {
2022
const config = vscode.workspace.getConfiguration('openmemory');
@@ -23,6 +25,7 @@ export function activate(context: vscode.ExtensionContext) {
2325
api_key = config.get('apiKey') || undefined;
2426
use_mcp = config.get('useMCP') || false;
2527
mcp_server_path = config.get('mcpServerPath') || '';
28+
user_id = getUserId(context, config);
2629

2730
status_bar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
2831
status_bar.command = 'openmemory.statusBarClick';
@@ -48,19 +51,67 @@ export function activate(context: vscode.ExtensionContext) {
4851
});
4952

5053
const status_click = vscode.commands.registerCommand('openmemory.statusBarClick', () => show_menu());
54+
5155
const query_cmd = vscode.commands.registerCommand('openmemory.queryContext', async () => {
5256
const editor = vscode.window.activeTextEditor;
5357
if (!editor) {
5458
vscode.window.showErrorMessage('No active editor');
5559
return;
5660
}
61+
62+
await vscode.window.withProgress({
63+
location: vscode.ProgressLocation.Notification,
64+
title: "OpenMemory: Querying Context...",
65+
cancellable: false
66+
}, async () => {
67+
try {
68+
const query = editor.document.getText(editor.selection) || editor.document.getText();
69+
const memories = await query_context(query, editor.document.uri.fsPath);
70+
const doc = await vscode.workspace.openTextDocument({ content: format_memories(memories), language: 'markdown' });
71+
await vscode.window.showTextDocument(doc);
72+
} catch (error) {
73+
vscode.window.showErrorMessage(`Query failed: ${error}`);
74+
}
75+
});
76+
});
77+
78+
const add_cmd = vscode.commands.registerCommand('openmemory.addToMemory', async () => {
79+
const editor = vscode.window.activeTextEditor;
80+
if (!editor) {
81+
vscode.window.showErrorMessage('No active editor');
82+
return;
83+
}
84+
const selection = editor.document.getText(editor.selection);
85+
if (!selection) {
86+
vscode.window.showErrorMessage('No text selected');
87+
return;
88+
}
89+
90+
await vscode.window.withProgress({
91+
location: vscode.ProgressLocation.Notification,
92+
title: "OpenMemory: Saving Selection...",
93+
cancellable: false
94+
}, async () => {
95+
try {
96+
await add_memory(selection, editor.document.uri.fsPath);
97+
vscode.window.showInformationMessage('Selection added to OpenMemory');
98+
} catch (error) {
99+
vscode.window.showErrorMessage(`Failed to add memory: ${error}`);
100+
}
101+
});
102+
});
103+
104+
const note_cmd = vscode.commands.registerCommand('openmemory.quickNote', async () => {
105+
const input = await vscode.window.showInputBox({ prompt: 'Enter a quick note to remember', placeHolder: 'e.g. Refactored the auth logic to use JWT' });
106+
if (!input) return;
107+
57108
try {
58-
const query = editor.document.getText(editor.selection) || editor.document.getText();
59-
const memories = await query_context(query, editor.document.uri.fsPath);
60-
const doc = await vscode.workspace.openTextDocument({ content: format_memories(memories), language: 'markdown' });
61-
await vscode.window.showTextDocument(doc);
109+
const editor = vscode.window.activeTextEditor;
110+
const file = editor ? editor.document.uri.fsPath : 'manual-note';
111+
await add_memory(input, file);
112+
vscode.window.showInformationMessage('Note added to OpenMemory');
62113
} catch (error) {
63-
vscode.window.showErrorMessage(`Query failed: ${error}`);
114+
vscode.window.showErrorMessage(`Failed to add note: ${error}`);
64115
}
65116
});
66117

@@ -86,6 +137,10 @@ export function activate(context: vscode.ExtensionContext) {
86137

87138
const setup_cmd = vscode.commands.registerCommand('openmemory.setup', () => show_quick_setup());
88139

140+
const dashboard_cmd = vscode.commands.registerCommand('openmemory.dashboard', () => {
141+
DashboardPanel.createOrShow(context.extensionUri);
142+
});
143+
89144
const change_listener = vscode.workspace.onDidChangeTextDocument((e) => {
90145
if (is_enabled && is_tracking && e.document.uri.scheme === 'file') {
91146
for (const change of e.contentChanges) {
@@ -114,7 +169,7 @@ export function activate(context: vscode.ExtensionContext) {
114169
}
115170
});
116171

117-
context.subscriptions.push(status_click, query_cmd, patterns_cmd, toggle_cmd, setup_cmd, change_listener, save_listener, open_listener, close_listener);
172+
context.subscriptions.push(status_click, query_cmd, add_cmd, note_cmd, patterns_cmd, dashboard_cmd, toggle_cmd, setup_cmd, change_listener, save_listener, open_listener, close_listener);
118173
}
119174

120175
export function deactivate() {
@@ -174,13 +229,17 @@ async function show_menu() {
174229

175230
const items = [];
176231
items.push(is_tracking ? { label: '$(debug-pause) Pause Tracking', action: 'pause' } : { label: '$(play) Resume Tracking', action: 'resume' });
177-
items.push({ label: '$(search) Query Context', action: 'query' }, { label: '$(graph) View Patterns', action: 'patterns' }, { label: use_mcp ? '$(link) Switch to Direct HTTP' : '$(server-process) Switch to MCP Mode', action: 'toggle_mcp' }, { label: '$(circle-slash) Disable Extension', action: 'disable' }, { label: '$(gear) Setup', action: 'setup' }, { label: '$(refresh) Reconnect', action: 'reconnect' });
232+
items.push({ label: '$(dashboard) Open Dashboard', action: 'dashboard' });
233+
items.push({ label: '$(search) Query Context', action: 'query' }, { label: '$(add) Add Selection', action: 'add' }, { label: '$(pencil) Quick Note', action: 'note' }, { label: '$(graph) View Patterns', action: 'patterns' }, { label: use_mcp ? '$(link) Switch to Direct HTTP' : '$(server-process) Switch to MCP Mode', action: 'toggle_mcp' }, { label: '$(circle-slash) Disable Extension', action: 'disable' }, { label: '$(gear) Setup', action: 'setup' }, { label: '$(refresh) Reconnect', action: 'reconnect' });
178234
const choice = await vscode.window.showQuickPick(items, { placeHolder: 'OpenMemory Actions' });
179235
if (!choice) return;
180236
switch (choice.action) {
237+
case 'dashboard': vscode.commands.executeCommand('openmemory.dashboard'); break;
181238
case 'pause': is_tracking = false; update_status_bar('paused'); break;
182239
case 'resume': is_tracking = true; update_status_bar('active'); break;
183240
case 'query': vscode.commands.executeCommand('openmemory.queryContext'); break;
241+
case 'add': vscode.commands.executeCommand('openmemory.addToMemory'); break;
242+
case 'note': vscode.commands.executeCommand('openmemory.quickNote'); break;
184243
case 'patterns': vscode.commands.executeCommand('openmemory.viewPatterns'); break;
185244
case 'toggle_mcp':
186245
use_mcp = !use_mcp;
@@ -290,6 +349,26 @@ async function show_quick_setup() {
290349
}
291350
}
292351

352+
function getUserId(context: vscode.ExtensionContext, config: vscode.WorkspaceConfiguration): string {
353+
// 1. Check if user has configured a custom userId
354+
const configuredUserId = config.get<string>('userId');
355+
if (configuredUserId) return configuredUserId;
356+
357+
// 2. Check if we have a persistent userId in global state
358+
let persistedUserId = context.globalState.get<string>('openmemory.userId');
359+
if (persistedUserId) return persistedUserId;
360+
361+
// 3. Generate a new unique userId based on machine ID
362+
const machineId = vscode.env.machineId; // Unique per machine
363+
const userName = process.env.USERNAME || process.env.USER || 'user';
364+
persistedUserId = `${userName}-${machineId.substring(0, 8)}`;
365+
366+
// 4. Persist it for future sessions
367+
context.globalState.update('openmemory.userId', persistedUserId);
368+
369+
return persistedUserId;
370+
}
371+
293372
async function check_connection(): Promise<boolean> {
294373
try {
295374
const response = await fetch(`${backend_url}/health`, { method: 'GET', headers: get_headers() });
@@ -307,8 +386,10 @@ function get_headers(): Record<string, string> {
307386

308387
async function start_session() {
309388
try {
310-
const project = vscode.workspace.workspaceFolders?.[0]?.name || 'unknown';
311-
const response = await fetch(`${backend_url}/api/ide/session/start`, { method: 'POST', headers: get_headers(), body: JSON.stringify({ user_id: 'vscode-user', project_name: project, ide_name: 'vscode' }) });
389+
const config = vscode.workspace.getConfiguration('openmemory');
390+
const configuredProject = config.get<string>('projectName');
391+
const project = configuredProject || vscode.workspace.workspaceFolders?.[0]?.name || 'unknown';
392+
const response = await fetch(`${backend_url}/api/ide/session/start`, { method: 'POST', headers: get_headers(), body: JSON.stringify({ user_id: user_id, project_name: project, ide_name: 'vscode' }) });
312393
if (!response.ok) throw new Error(`HTTP ${response.status}`);
313394
const data = await response.json();
314395
session_id = data.session_id;
@@ -342,6 +423,21 @@ async function query_context(query: string, file: string) {
342423
return data.memories || [];
343424
}
344425

426+
async function add_memory(content: string, file: string) {
427+
const response = await fetch(`${backend_url}/memory/add`, {
428+
method: 'POST',
429+
headers: get_headers(),
430+
body: JSON.stringify({
431+
content,
432+
user_id: user_id,
433+
tags: ['manual', 'ide-selection'],
434+
metadata: { source: 'vscode', file }
435+
})
436+
});
437+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
438+
return await response.json();
439+
}
440+
345441
async function get_patterns(sid: string) {
346442
const response = await fetch(`${backend_url}/api/ide/patterns/${sid}`, { method: 'GET', headers: get_headers() });
347443
const data = await response.json();

0 commit comments

Comments
 (0)