/
GreyCat
/
openhuman
Обзор
Документация
Войти
/
GreyCat
/
openhuman
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
app/src/services/memorySourcesService.test.ts
193 строки
6 KB
Steven Enamakel's Droid
feat(memory): add Conversation as a memory source kind (#3441)
06 июн 2026, 22:55
Не верифицирован
06 июн 2026, 22:55
6cf53c0
Код
Авторство
О чём код?
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { callCoreRpc } from './coreRpcClient'; import { addMemorySource, applyAllIn, listMemorySources, type MemorySourceEntry, removeMemorySource, SOURCE_KIND_ICONS, SOURCE_KIND_LABEL_KEYS, updateMemorySource, } from './memorySourcesService'; vi.mock('./coreRpcClient', () => ({ callCoreRpc: vi.fn() })); const mockedCall = vi.mocked(callCoreRpc); describe('memorySourcesService', () => { beforeEach(() => { mockedCall.mockReset(); }); it('listMemorySources returns sources from envelope-wrapped response', async () => { mockedCall.mockResolvedValue({ result: { sources: [{ id: 'src_1', kind: 'folder', label: 'Notes', enabled: true, path: '/tmp' }], }, logs: [], } as never); const sources = await listMemorySources(); expect(mockedCall).toHaveBeenCalledWith({ method: 'openhuman.memory_sources_list' }); expect(sources).toHaveLength(1); expect(sources[0].kind).toBe('folder'); }); it('listMemorySources handles flat (un-wrapped) response', async () => { mockedCall.mockResolvedValue({ sources: [] } as never); const sources = await listMemorySources(); expect(sources).toEqual([]); }); it('addMemorySource sends kind-specific flat fields', async () => { mockedCall.mockResolvedValue({ result: { source: { id: 'src_new', kind: 'folder', label: 'Test', enabled: true, path: '/x' }, }, logs: [], } as never); const result = await addMemorySource({ kind: 'folder', label: 'Test', enabled: true, path: '/x', }); expect(mockedCall).toHaveBeenCalledWith({ method: 'openhuman.memory_sources_add', params: { kind: 'folder', label: 'Test', enabled: true, path: '/x' }, }); expect(result.id).toBe('src_new'); }); it('updateMemorySource sends id + patch fields', async () => { mockedCall.mockResolvedValue({ result: { source: { id: 'src_1', kind: 'folder', label: 'X', enabled: false } }, logs: [], } as never); await updateMemorySource('src_1', { enabled: false, label: 'X' }); expect(mockedCall).toHaveBeenCalledWith({ method: 'openhuman.memory_sources_update', params: { id: 'src_1', enabled: false, label: 'X' }, }); }); it('removeMemorySource returns boolean', async () => { mockedCall.mockResolvedValue({ result: { removed: true }, logs: [] } as never); const removed = await removeMemorySource('src_1'); expect(removed).toBe(true); }); it('exposes labels and icons for every source kind', () => { const kinds = [ 'composio', 'conversation', 'folder', 'github_repo', 'twitter_query', 'rss_feed', 'web_page', ] as const; for (const kind of kinds) { expect(SOURCE_KIND_LABEL_KEYS[kind]).toBeTruthy(); expect(SOURCE_KIND_ICONS[kind]).toBeTruthy(); } }); it('addMemorySource sends conversation source with no extra fields', async () => { mockedCall.mockResolvedValue({ result: { source: { id: 'src_conv', kind: 'conversation', label: 'Conversations', enabled: true }, }, logs: [], } as never); const result = await addMemorySource({ kind: 'conversation', label: 'Conversations', enabled: true, }); expect(mockedCall).toHaveBeenCalledWith({ method: 'openhuman.memory_sources_add', params: { kind: 'conversation', label: 'Conversations', enabled: true }, }); expect(result.id).toBe('src_conv'); expect(result.kind).toBe('conversation'); }); // --------------------------------------------------------------------------- // applyAllIn // --------------------------------------------------------------------------- it('applyAllIn calls the correct RPC method', async () => { mockedCall.mockResolvedValue({ result: { sources: [{ id: 'src_1', kind: 'github_repo', label: 'All Repos', enabled: true }], sync_triggered: 1, }, logs: [], } as never); const result = await applyAllIn(); expect(mockedCall).toHaveBeenCalledWith({ method: 'openhuman.memory_sources_apply_all_in' }); expect(result.sync_triggered).toBe(1); expect(result.sources).toHaveLength(1); expect(result.sources[0].id).toBe('src_1'); }); it('applyAllIn handles envelope-wrapped response', async () => { mockedCall.mockResolvedValue({ result: { sources: [], sync_triggered: 0 }, logs: [] } as never); const result = await applyAllIn(); expect(result.sources).toEqual([]); expect(result.sync_triggered).toBe(0); }); it('applyAllIn handles flat (un-wrapped) response', async () => { mockedCall.mockResolvedValue({ sources: [{ id: 'src_2', kind: 'folder', label: 'Docs', enabled: true }], sync_triggered: 1, } as never); const result = await applyAllIn(); expect(result.sources).toHaveLength(1); }); // --------------------------------------------------------------------------- // MemorySourceEntry interface includes all limit fields // --------------------------------------------------------------------------- it('MemorySourceEntry interface accepts all limit fields at compile-time', () => { // This test is a type-level assertion: if the fields are missing from the // interface the assignment below would fail TypeScript compilation. const entry: MemorySourceEntry = { id: 'src_1', kind: 'github_repo', label: 'Test', enabled: true, max_commits: 100, max_issues: 200, max_prs: 50, max_items: 500, since_days: 30, sync_depth_days: 90, max_tokens_per_sync: 100_000, max_cost_per_sync_usd: 1.5, }; expect(entry.max_commits).toBe(100); expect(entry.max_issues).toBe(200); expect(entry.max_prs).toBe(50); expect(entry.since_days).toBe(30); expect(entry.sync_depth_days).toBe(90); expect(entry.max_tokens_per_sync).toBe(100_000); expect(entry.max_cost_per_sync_usd).toBe(1.5); }); });