Refactor chat view and add conversation state management

Introduce ConversationStateManager to handle short, medium, and long-term
context for improved conversation flow. Update ChatView to use this manager
and refactor input handling to accept values directly for better testability.

Update OllamaClient with non-streaming chat support and improved error
handling for malformed chunks. Enhance vault indexer with caching, better
scoring, and stop word filtering. Refactor main plugin entry point and
semantic cache initialization for robustness.
This commit is contained in:
2026-05-08 11:52:31 +02:00
parent b37ca2c178
commit 771db09d24
30 changed files with 2184 additions and 1287 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ jest.mock('../src/semantic-cache', () => ({
setCache: mockSetCache,
clearCache: mockClearCache,
})),
));
}));
import { OllamaClient } from '../src/ollama-client';
+12 -14
View File
@@ -39,16 +39,21 @@ describe('SemanticCacheService', () => {
let mockChromaClient: any;
let mockCollection: any;
beforeEach(() => {
beforeEach(async () => {
// Reset all mocks
jest.clearAllMocks();
// Create a fresh instance for each test
cacheService = new SemanticCacheService(mockOllamaUrl, mockCacheConfig);
await cacheService.initialize();
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ embedding: [0.1, 0.2, 0.3] }),
});
// Access the internal mocks
mockChromaClient = (ChromaClient as jest.Mock).mock.instances[0];
mockCollection = mockChromaClient.getOrCreateCollection.mock.results[0].value;
mockChromaClient = (ChromaClient as jest.Mock).mock.results[0].value;
mockCollection = await mockChromaClient.getOrCreateCollection.mock.results[0].value;
});
describe('constructor', () => {
@@ -72,6 +77,7 @@ describe('SemanticCacheService', () => {
});
it('should not initialize when cache is disabled', async () => {
jest.clearAllMocks();
const disabledConfig: CacheConfig = { ...mockCacheConfig, enabled: false };
const disabledCacheService = new SemanticCacheService(mockOllamaUrl, disabledConfig);
@@ -83,6 +89,7 @@ describe('SemanticCacheService', () => {
describe('getCache', () => {
it('should return null when cache is disabled', async () => {
jest.clearAllMocks();
const disabledConfig: CacheConfig = { ...mockCacheConfig, enabled: false };
const disabledCacheService = new SemanticCacheService(mockOllamaUrl, disabledConfig);
@@ -122,6 +129,7 @@ describe('SemanticCacheService', () => {
describe('setCache', () => {
it('should not set cache when disabled', async () => {
jest.clearAllMocks();
const disabledConfig: CacheConfig = { ...mockCacheConfig, enabled: false };
const disabledCacheService = new SemanticCacheService(mockOllamaUrl, disabledConfig);
@@ -131,25 +139,15 @@ describe('SemanticCacheService', () => {
});
it('should add content to cache', async () => {
const mockEmbedding = [0.1, 0.2, 0.3];
// Mock the fetch function for embedding generation
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ embedding: mockEmbedding }),
});
await cacheService.setCache('test query', 'test response');
expect(mockCollection.add).toHaveBeenCalled();
// Clean up
global.fetch = undefined as any;
});
});
describe('clearCache', () => {
it('should not clear when cache is disabled', async () => {
jest.clearAllMocks();
const disabledConfig: CacheConfig = { ...mockCacheConfig, enabled: false };
const disabledCacheService = new SemanticCacheService(mockOllamaUrl, disabledConfig);