- Automatic browser geolocation capture on event creation - Reverse geocoding via Nominatim API for place names - Full-text search with SQLite FTS5 - Calendar view for browsing past entries - DateNavigator component for day navigation - SearchModal with Ctrl+K shortcut - QuickAddWidget with Ctrl+J shortcut - Starlight documentation site with GitHub Pages deployment - Multiple AI provider support (Groq, OpenAI, Anthropic, Ollama, LM Studio) - Multi-user registration support BREAKING: Events now include latitude/longitude/placeName fields
67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import type { AIProvider, AIProviderConfig, AIProviderResult } from './provider';
|
|
|
|
export class OllamaProvider implements AIProvider {
|
|
provider = 'ollama' as const;
|
|
private baseUrl: string;
|
|
private model: string;
|
|
|
|
constructor(config: AIProviderConfig) {
|
|
this.baseUrl = config.baseUrl || 'http://localhost:11434';
|
|
this.model = config.model || 'llama3.2';
|
|
}
|
|
|
|
async generate(prompt: string, systemPrompt?: string, options?: { jsonMode?: boolean }): Promise<AIProviderResult> {
|
|
const requestBody = {
|
|
model: this.model,
|
|
stream: false,
|
|
messages: [
|
|
...(systemPrompt ? [{ role: 'system', content: systemPrompt }] : []),
|
|
{ role: 'user', content: prompt },
|
|
],
|
|
};
|
|
|
|
const response = await fetch(`${this.baseUrl}/api/chat`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(requestBody),
|
|
});
|
|
|
|
const responseData = await response.json();
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Ollama API error: ${response.status} ${JSON.stringify(responseData)}`);
|
|
}
|
|
|
|
let content = responseData.message?.content || '';
|
|
let title: string | undefined;
|
|
|
|
if (options?.jsonMode) {
|
|
try {
|
|
const parsed = JSON.parse(content);
|
|
title = parsed.title;
|
|
content = parsed.content || content;
|
|
} catch {
|
|
// If JSON parsing fails, use content as-is
|
|
}
|
|
}
|
|
|
|
return {
|
|
content,
|
|
title,
|
|
request: requestBody,
|
|
response: responseData,
|
|
};
|
|
}
|
|
|
|
async validate(): Promise<boolean> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/tags`);
|
|
return response.ok;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
}
|