fix: cherry-pick improvements from feature/semantic_caching
- semantic-cache.ts: use upsert instead of add to avoid duplicate-ID errors - semantic-cache.ts: add crypto.randomUUID() fallback for constrained runtimes - ollama-client.ts: JSON.stringify non-string Ollama errors to avoid [object Object] - tests: update semantic-cache mocks and assertions for upsert
This commit is contained in:
+15
-5
@@ -196,7 +196,9 @@ export class OllamaClient {
|
||||
}
|
||||
|
||||
if (parsed.error) {
|
||||
throw new Error(`Ollama error: ${parsed.error}`);
|
||||
const errorMsg =
|
||||
typeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed.error);
|
||||
throw new Error(`Ollama error: ${errorMsg}`);
|
||||
}
|
||||
|
||||
yield this.normalizeMessage(parsed.message);
|
||||
@@ -216,7 +218,9 @@ export class OllamaClient {
|
||||
}
|
||||
|
||||
if (parsed?.error) {
|
||||
throw new Error(`Ollama error: ${parsed.error}`);
|
||||
const errorMsg =
|
||||
typeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed.error);
|
||||
throw new Error(`Ollama error: ${errorMsg}`);
|
||||
}
|
||||
|
||||
if (parsed?.message) {
|
||||
@@ -226,7 +230,10 @@ export class OllamaClient {
|
||||
} catch (error) {
|
||||
if (retryCount < this.maxRetries && this.isRetryableError(error, controller)) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
Logger.warn(`Retrying after error (attempt ${retryCount + 1}): ${errorMessage}`, 'ollama-client');
|
||||
Logger.warn(
|
||||
`Retrying after error (attempt ${retryCount + 1}): ${errorMessage}`,
|
||||
'ollama-client'
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 10 * Math.pow(2, retryCount)));
|
||||
yield* this.streamChatWithRetry(messages, tools, retryCount + 1);
|
||||
} else {
|
||||
@@ -267,7 +274,7 @@ export class OllamaClient {
|
||||
throw new ApiError(`Ollama API error: ${response.status}`, response.status);
|
||||
}
|
||||
|
||||
const data = await response.json() as unknown;
|
||||
const data = (await response.json()) as unknown;
|
||||
if (!this.isChatResponse(data)) {
|
||||
return this.normalizeMessage();
|
||||
}
|
||||
@@ -275,7 +282,10 @@ export class OllamaClient {
|
||||
} catch (error) {
|
||||
if (retryCount < this.maxRetries && this.isRetryableError(error, controller)) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
Logger.warn(`Retrying after error (attempt ${retryCount + 1}): ${errorMessage}`, 'ollama-client');
|
||||
Logger.warn(
|
||||
`Retrying after error (attempt ${retryCount + 1}): ${errorMessage}`,
|
||||
'ollama-client'
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 10 * Math.pow(2, retryCount)));
|
||||
return this.chatWithRetry(messages, tools, retryCount + 1);
|
||||
} else {
|
||||
|
||||
+10
-2
@@ -62,12 +62,20 @@ export class SemanticCacheService {
|
||||
}
|
||||
}
|
||||
|
||||
private static generateId(): string {
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
// Fallback for environments without crypto.randomUUID
|
||||
return 'cache_' + Date.now() + '_' + Math.random().toString(36).substring(2, 11);
|
||||
}
|
||||
|
||||
async setCache(query: string, response: string): Promise<void> {
|
||||
if (!this.config.enabled || !this.collection) return;
|
||||
|
||||
try {
|
||||
await this.collection.add({
|
||||
ids: [crypto.randomUUID()],
|
||||
await this.collection.upsert({
|
||||
ids: [SemanticCacheService.generateId()],
|
||||
documents: [response],
|
||||
embeddings: await this.generateEmbedding(query),
|
||||
metadatas: [{ source: 'ollama' }],
|
||||
|
||||
@@ -10,6 +10,7 @@ jest.mock('chromadb', () => ({
|
||||
getOrCreateCollection: jest.fn().mockResolvedValue({
|
||||
query: jest.fn(),
|
||||
add: jest.fn(),
|
||||
upsert: jest.fn(),
|
||||
reset: jest.fn(),
|
||||
}),
|
||||
deleteCollection: jest.fn(),
|
||||
@@ -135,13 +136,13 @@ describe('SemanticCacheService', () => {
|
||||
|
||||
await disabledCacheService.setCache('test query', 'test response');
|
||||
|
||||
expect(mockCollection.add).not.toHaveBeenCalled();
|
||||
expect(mockCollection.upsert).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should add content to cache', async () => {
|
||||
await cacheService.setCache('test query', 'test response');
|
||||
|
||||
expect(mockCollection.add).toHaveBeenCalled();
|
||||
expect(mockCollection.upsert).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user