feat(memory): add /memory inbox command for reviewing extracted skills (#24544)

This commit is contained in:
Sandy Tao
2026-04-08 11:08:49 -07:00
committed by GitHub
parent 4ebc43bc66
commit a837b39f8d
10 changed files with 1346 additions and 1 deletions
@@ -457,4 +457,78 @@ describe('memoryCommand', () => {
);
});
});
describe('/memory inbox', () => {
let inboxCommand: SlashCommand;
beforeEach(() => {
inboxCommand = memoryCommand.subCommands!.find(
(cmd) => cmd.name === 'inbox',
)!;
expect(inboxCommand).toBeDefined();
});
it('should return custom_dialog when config is available and flag is enabled', () => {
if (!inboxCommand.action) throw new Error('Command has no action');
const mockConfig = {
reloadSkills: vi.fn(),
isMemoryManagerEnabled: vi.fn().mockReturnValue(true),
};
const context = createMockCommandContext({
services: {
agentContext: { config: mockConfig },
},
ui: {
removeComponent: vi.fn(),
reloadCommands: vi.fn(),
},
});
const result = inboxCommand.action(context, '');
expect(result).toHaveProperty('type', 'custom_dialog');
expect(result).toHaveProperty('component');
});
it('should return info message when memory manager is disabled', () => {
if (!inboxCommand.action) throw new Error('Command has no action');
const mockConfig = {
isMemoryManagerEnabled: vi.fn().mockReturnValue(false),
};
const context = createMockCommandContext({
services: {
agentContext: { config: mockConfig },
},
});
const result = inboxCommand.action(context, '');
expect(result).toEqual({
type: 'message',
messageType: 'info',
content:
'The memory inbox requires the experimental memory manager. Enable it with: experimental.memoryManager = true in settings.',
});
});
it('should return error when config is not loaded', () => {
if (!inboxCommand.action) throw new Error('Command has no action');
const context = createMockCommandContext({
services: {
agentContext: null,
},
});
const result = inboxCommand.action(context, '');
expect(result).toEqual({
type: 'message',
messageType: 'error',
content: 'Config not loaded.',
});
});
});
});
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import React from 'react';
import {
addMemory,
listMemoryFiles,
@@ -13,9 +14,11 @@ import {
import { MessageType } from '../types.js';
import {
CommandKind,
type OpenCustomDialogActionReturn,
type SlashCommand,
type SlashCommandActionReturn,
} from './types.js';
import { SkillInboxDialog } from '../components/SkillInboxDialog.js';
export const memoryCommand: SlashCommand = {
name: 'memory',
@@ -124,5 +127,45 @@ export const memoryCommand: SlashCommand = {
);
},
},
{
name: 'inbox',
description:
'Review skills extracted from past sessions and move them to global or project skills',
kind: CommandKind.BUILT_IN,
autoExecute: true,
action: (
context,
): OpenCustomDialogActionReturn | SlashCommandActionReturn | void => {
const config = context.services.agentContext?.config;
if (!config) {
return {
type: 'message',
messageType: 'error',
content: 'Config not loaded.',
};
}
if (!config.isMemoryManagerEnabled()) {
return {
type: 'message',
messageType: 'info',
content:
'The memory inbox requires the experimental memory manager. Enable it with: experimental.memoryManager = true in settings.',
};
}
return {
type: 'custom_dialog',
component: React.createElement(SkillInboxDialog, {
config,
onClose: () => context.ui.removeComponent(),
onReloadSkills: async () => {
await config.reloadSkills();
context.ui.reloadCommands();
},
}),
};
},
},
],
};