feat(memory): add Auto Memory inbox flow with canonical-patch contract (#26338)

This commit is contained in:
Sandy Tao
2026-05-04 12:07:13 -07:00
committed by GitHub
parent 60a6a47d56
commit a7beb890d0
26 changed files with 4279 additions and 115 deletions
@@ -208,12 +208,20 @@ vi.mock('../config/scoped-config.js', async (importOriginal) => {
...actual,
runWithScopedWorkspaceContext: vi.fn(actual.runWithScopedWorkspaceContext),
createScopedWorkspaceContext: vi.fn(actual.createScopedWorkspaceContext),
runWithScopedAutoMemoryExtractionWriteAccess: vi.fn(
actual.runWithScopedAutoMemoryExtractionWriteAccess,
),
runWithScopedMemoryInboxAccess: vi.fn(
actual.runWithScopedMemoryInboxAccess,
),
};
});
import {
runWithScopedWorkspaceContext,
createScopedWorkspaceContext,
runWithScopedAutoMemoryExtractionWriteAccess,
runWithScopedMemoryInboxAccess,
} from '../config/scoped-config.js';
const mockedRunWithScopedWorkspaceContext = vi.mocked(
runWithScopedWorkspaceContext,
@@ -221,6 +229,12 @@ const mockedRunWithScopedWorkspaceContext = vi.mocked(
const mockedCreateScopedWorkspaceContext = vi.mocked(
createScopedWorkspaceContext,
);
const mockedRunWithScopedMemoryInboxAccess = vi.mocked(
runWithScopedMemoryInboxAccess,
);
const mockedRunWithScopedAutoMemoryExtractionWriteAccess = vi.mocked(
runWithScopedAutoMemoryExtractionWriteAccess,
);
const MockedGeminiChat = vi.mocked(GeminiChat);
const mockedGetDirectoryContextString = vi.mocked(getDirectoryContextString);
@@ -422,6 +436,8 @@ describe('LocalAgentExecutor', () => {
mockedLogAgentFinish.mockReset();
mockedRunWithScopedWorkspaceContext.mockClear();
mockedCreateScopedWorkspaceContext.mockClear();
mockedRunWithScopedMemoryInboxAccess.mockClear();
mockedRunWithScopedAutoMemoryExtractionWriteAccess.mockClear();
mockedPromptIdContext.getStore.mockReset();
mockedPromptIdContext.run.mockImplementation((_id, fn) => fn());
@@ -941,6 +957,52 @@ describe('LocalAgentExecutor', () => {
expect(mockedRunWithScopedWorkspaceContext).toHaveBeenCalledOnce();
});
it('should use runWithScopedMemoryInboxAccess when memoryInboxAccess is set', async () => {
const definition = createTestDefinition();
definition.memoryInboxAccess = true;
const executor = await LocalAgentExecutor.create(
definition,
mockConfig,
onActivity,
);
mockModelResponse([
{
name: COMPLETE_TASK_TOOL_NAME,
args: { finalResult: 'done' },
id: 'c1',
},
]);
await executor.run({ goal: 'test' }, signal);
expect(mockedRunWithScopedMemoryInboxAccess).toHaveBeenCalledOnce();
});
it('should use the extraction write scope when autoMemoryExtractionWriteAccess is set', async () => {
const definition = createTestDefinition();
definition.autoMemoryExtractionWriteAccess = true;
const executor = await LocalAgentExecutor.create(
definition,
mockConfig,
onActivity,
);
mockModelResponse([
{
name: COMPLETE_TASK_TOOL_NAME,
args: { finalResult: 'done' },
id: 'c1',
},
]);
await executor.run({ goal: 'test' }, signal);
expect(
mockedRunWithScopedAutoMemoryExtractionWriteAccess,
).toHaveBeenCalledOnce();
});
it('should not use runWithScopedWorkspaceContext when workspaceDirectories is not set', async () => {
const definition = createTestDefinition();
const executor = await LocalAgentExecutor.create(
@@ -962,6 +1024,10 @@ describe('LocalAgentExecutor', () => {
expect(mockedCreateScopedWorkspaceContext).not.toHaveBeenCalled();
expect(mockedRunWithScopedWorkspaceContext).not.toHaveBeenCalled();
expect(mockedRunWithScopedMemoryInboxAccess).not.toHaveBeenCalled();
expect(
mockedRunWithScopedAutoMemoryExtractionWriteAccess,
).not.toHaveBeenCalled();
});
});