Skip to content
This repository was archived by the owner on May 20, 2026. It is now read-only.

Commit c3fd133

Browse files
authored
Add memory viewing command and update chat panel session resource definitions (#3754)
* Add memory viewing command and update chat panel session resource definitions * refactor: rename memory commands and add clear memories functionality * add memory show and clear commands to chat tools * refactor: improve memory clearing logic and add user feedback for no memories found
1 parent b490b57 commit c3fd133

3 files changed

Lines changed: 138 additions & 11 deletions

File tree

package.json

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2500,6 +2500,16 @@
25002500
"icon": "$(inspect)",
25012501
"category": "Developer"
25022502
},
2503+
{
2504+
"command": "github.copilot.chat.tools.memory.showMemories",
2505+
"title": "%github.copilot.command.showMemories%",
2506+
"category": "Chat"
2507+
},
2508+
{
2509+
"command": "github.copilot.chat.tools.memory.clearMemories",
2510+
"title": "%github.copilot.command.clearMemories%",
2511+
"category": "Chat"
2512+
},
25032513
{
25042514
"command": "github.copilot.terminal.explainTerminalLastCommand",
25052515
"title": "%github.copilot.command.explainTerminalLastCommand%",
@@ -4958,6 +4968,14 @@
49584968
{
49594969
"command": "github.copilot.nes.captureExpected.submit",
49604970
"when": "github.copilot.inlineEditsEnabled"
4971+
},
4972+
{
4973+
"command": "github.copilot.chat.tools.memory.showMemories",
4974+
"when": "config.github.copilot.chat.tools.memory.enabled"
4975+
},
4976+
{
4977+
"command": "github.copilot.chat.tools.memory.clearMemories",
4978+
"when": "config.github.copilot.chat.tools.memory.enabled"
49614979
}
49624980
],
49634981
"view/title": [
@@ -6001,4 +6019,4 @@
60016019
"node-gyp": "npm:node-gyp@10.3.1",
60026020
"zod": "3.25.76"
60036021
}
6004-
}
6022+
}

package.nls.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@
109109
"github.copilot.command.showContextInspectorView": "Inspect Language Context",
110110
"github.copilot.command.validateNesRename": "Validate NES Rename",
111111
"github.copilot.command.resetVirtualToolGroups": "Reset Virtual Tool Groups",
112+
"github.copilot.command.showMemories": "Show Memories",
113+
"github.copilot.command.clearMemories": "Clear All Memories",
112114
"github.copilot.command.applySuggestionWithCopilot": "Apply Suggestion",
113115
"github.copilot.command.explainTerminalLastCommand": "Explain Last Terminal Command",
114116
"github.copilot.command.collectWorkspaceIndexDiagnostics": "Collect Workspace Index Diagnostics",

src/extension/tools/vscode-node/tools.ts

Lines changed: 117 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { isVscodeLanguageModelTool } from '../common/toolsRegistry';
1414
import { IToolsService } from '../common/toolsService';
1515
import { IToolGroupingCache, IToolGroupingService } from '../common/virtualTools/virtualToolTypes';
1616
import '../node/allTools';
17+
import { extractSessionId } from '../node/memoryTool';
1718
import './allTools';
1819

1920
export class ToolsContribution extends Disposable {
@@ -52,21 +53,127 @@ export class ToolsContribution extends Disposable {
5253
vscode.window.showInformationMessage(l10n.t('Tool groups have been reset. They will be regenerated on the next agent request.'));
5354
}));
5455

55-
this._register(vscode.commands.registerCommand('github.copilot.chat.tools.memory.openFolder', async () => {
56+
this._register(vscode.commands.registerCommand('github.copilot.chat.tools.memory.showMemories', async () => {
57+
const globalStorageUri = this.extensionContext.globalStorageUri;
5658
const storageUri = this.extensionContext.storageUri;
57-
if (!storageUri) {
58-
vscode.window.showErrorMessage(l10n.t('No workspace is currently open. Memory operations require an active workspace.'));
59+
60+
interface MemoryItem extends vscode.QuickPickItem {
61+
fileUri?: URI;
62+
}
63+
64+
const items: MemoryItem[] = [];
65+
66+
// Collect user-scoped memories from globalStorageUri/memory-tool/memories/
67+
if (globalStorageUri) {
68+
const userMemoryUri = URI.joinPath(globalStorageUri, 'memory-tool/memories');
69+
try {
70+
const entries = await vscode.workspace.fs.readDirectory(vscode.Uri.from(userMemoryUri));
71+
const fileEntries = entries.filter(([name, type]) => type === vscode.FileType.File && !name.startsWith('.'));
72+
if (fileEntries.length > 0) {
73+
items.push({ label: '/memories', kind: vscode.QuickPickItemKind.Separator });
74+
for (const [name] of fileEntries) {
75+
items.push({
76+
label: `$(file) ${name}`,
77+
description: 'user',
78+
fileUri: URI.joinPath(userMemoryUri, name),
79+
});
80+
}
81+
}
82+
} catch {
83+
// User memory directory may not exist yet
84+
}
85+
}
86+
87+
// Collect session-scoped memories from storageUri/memory-tool/memories/<sessionId>/
88+
const sessionResource = vscode.window.activeChatPanelSessionResource;
89+
if (storageUri && sessionResource) {
90+
const sessionId = extractSessionId(sessionResource.toString());
91+
const sessionMemoryUri = URI.joinPath(storageUri, 'memory-tool/memories', sessionId);
92+
try {
93+
const entries = await vscode.workspace.fs.readDirectory(vscode.Uri.from(sessionMemoryUri));
94+
const fileEntries = entries.filter(([name, type]) => type === vscode.FileType.File && !name.startsWith('.'));
95+
if (fileEntries.length > 0) {
96+
items.push({ label: '/memories/session', kind: vscode.QuickPickItemKind.Separator });
97+
for (const [name] of fileEntries) {
98+
items.push({
99+
label: `$(file) ${name}`,
100+
description: 'session',
101+
fileUri: URI.joinPath(sessionMemoryUri, name),
102+
});
103+
}
104+
}
105+
} catch {
106+
// Session memory directory may not exist yet
107+
}
108+
}
109+
110+
if (items.length === 0) {
111+
vscode.window.showInformationMessage(l10n.t('No memories found.'));
59112
return;
60113
}
61-
const memoryFolderUri = URI.joinPath(storageUri, 'memory-tool/memories');
62-
try {
63-
const stat = await vscode.workspace.fs.stat(vscode.Uri.from(memoryFolderUri));
64-
if (stat.type === vscode.FileType.Directory) {
65-
return vscode.env.openExternal(vscode.Uri.from(memoryFolderUri));
114+
115+
const selected = await vscode.window.showQuickPick(items, {
116+
title: l10n.t('Memory'),
117+
placeHolder: l10n.t('Select a memory file to view'),
118+
});
119+
120+
if (selected?.fileUri) {
121+
await vscode.commands.executeCommand('vscode.open', vscode.Uri.from(selected.fileUri));
122+
}
123+
}));
124+
125+
this._register(vscode.commands.registerCommand('github.copilot.chat.tools.memory.clearMemories', async () => {
126+
const confirm = await vscode.window.showWarningMessage(
127+
l10n.t('Are you sure you want to clear all memories? This cannot be undone.'),
128+
{ modal: true },
129+
l10n.t('Clear All'),
130+
);
131+
if (confirm !== l10n.t('Clear All')) {
132+
return;
133+
}
134+
135+
const globalStorageUri = this.extensionContext.globalStorageUri;
136+
const storageUri = this.extensionContext.storageUri;
137+
let hasError = false;
138+
let hasDeleted = false;
139+
140+
// Clear user-scoped memories
141+
if (globalStorageUri) {
142+
const userMemoryUri = URI.joinPath(globalStorageUri, 'memory-tool/memories');
143+
try {
144+
await vscode.workspace.fs.delete(vscode.Uri.from(userMemoryUri), { recursive: true });
145+
hasDeleted = true;
146+
} catch (e) {
147+
if (e instanceof vscode.FileSystemError && e.code === 'FileNotFound') {
148+
// Nothing to delete
149+
} else {
150+
hasError = true;
151+
}
66152
}
67-
} catch {
68153
}
69-
vscode.window.showInformationMessage(l10n.t('No memories have been saved yet. The memory folder will be created when the first memory is saved.'));
154+
155+
// Clear all session memories
156+
if (storageUri) {
157+
const sessionMemoryUri = URI.joinPath(storageUri, 'memory-tool/memories');
158+
try {
159+
await vscode.workspace.fs.delete(vscode.Uri.from(sessionMemoryUri), { recursive: true });
160+
hasDeleted = true;
161+
} catch (e) {
162+
if (e instanceof vscode.FileSystemError && e.code === 'FileNotFound') {
163+
// Nothing to delete
164+
} else {
165+
hasError = true;
166+
}
167+
}
168+
}
169+
170+
if (hasError) {
171+
vscode.window.showErrorMessage(l10n.t('Some memories could not be cleared. Please try again.'));
172+
} else if (!hasDeleted) {
173+
vscode.window.showInformationMessage(l10n.t('No memories found.'));
174+
} else {
175+
vscode.window.showInformationMessage(l10n.t('All memories have been cleared.'));
176+
}
70177
}));
71178

72179
this._register(autorun(reader => {

0 commit comments

Comments
 (0)