Files
my-loves-calendar/services/ollamaService.ts
drjones c373bbdab4 first commit
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 21:05:27 -08:00

156 lines
4.6 KiB
TypeScript

import { CalendarEvent, EventCategory, AppSettings } from '../types';
import { v4 as uuidv4 } from 'uuid';
interface OllamaResponse {
model: string;
created_at: string;
response: string;
done: boolean;
}
export const generateOllamaResponse = async (
prompt: string,
settings: AppSettings,
userRole: string
): Promise<{ text: string; event?: CalendarEvent }> => {
const url = `${settings.ollamaUrl}/api/generate`;
const currentDate = new Date();
const systemPrompt = `
You are a mystical calendar oracle for a couple.
Current Date: ${currentDate.toISOString()}
User Role: ${userRole}
Output JSON ONLY.
If user wants an event:
{
"isEvent": true,
"title": "string",
"description": "string",
"startTime": "ISO 8601 string",
"endTime": "ISO 8601 string",
"category": "general" | "chore" | "date" | "work" | "fun" | "magic"
}
If chatting:
{
"isEvent": false,
"message": "your magical response here"
}
`;
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: settings.ollamaModel,
prompt: `${systemPrompt}\n\nUser: ${prompt}`,
stream: false,
format: "json"
})
});
if (!response.ok) throw new Error(`Ollama Error`);
const data: OllamaResponse = await response.json();
const resultText = data.response;
const parsed = JSON.parse(resultText);
if (parsed.isEvent) {
const newEvent: CalendarEvent = {
id: uuidv4(),
title: parsed.title,
description: parsed.description,
startTime: parsed.startTime,
endTime: parsed.endTime,
category: parsed.category || 'general',
createdBy: userRole as any
};
return { text: `The stars have aligned for "${parsed.title}".`, event: newEvent };
} else {
return { text: parsed.message || "The spirits are quiet." };
}
} catch (error) {
console.error("Ollama Error", error);
return { text: "I cannot reach the local spirit realm (Ollama)." };
}
};
export const analyzeScheduleAndSuggest = async (
events: CalendarEvent[],
settings: AppSettings
): Promise<string[]> => {
if (!settings.ollamaUrl) return ["The oracle is disconnected."];
const eventsSummary = events.map(e =>
`- ${e.title} (${e.category}) on ${e.startTime.split('T')[0]}`
).join('\n');
const prompt = `
Analyze this couple's schedule:
${eventsSummary}
Based on these events, suggest 3 specific, thoughtful, or fun additional events they should add to balance their life.
Look for missing date nights, overwhelming work blocks, or chores that need doing.
Return ONLY a JSON array of 3 strings.
`;
try {
const response = await fetch(`${settings.ollamaUrl}/api/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: settings.ollamaModel,
prompt: prompt,
stream: false,
format: "json"
})
});
if (!response.ok) return ["Plan a surprise dinner!", "Go for a moonlit walk.", "Cook a meal together."];
const data = await response.json();
const parsed = JSON.parse(data.response);
return Array.isArray(parsed) ? parsed : ["Plan a surprise dinner!", "Go for a moonlit walk.", "Cook a meal together."];
} catch (e) {
return ["Plan a surprise dinner!", "Go for a moonlit walk.", "Cook a meal together."];
}
};
export const generateDailyHoroscope = async (
momSign: string,
dadSign: string,
settings: AppSettings
): Promise<string> => {
if (!settings.ollamaUrl) return "Stars are silent today.";
const currentDate = new Date().toDateString();
const prompt = `
Generate a very short, mystical horoscope prediction (max 10 words) for a couple with signs ${momSign} and ${dadSign} for today, ${currentDate}.
Focus on their shared energy or love.
Return JSON: { "prediction": "string" }
`;
try {
const response = await fetch(`${settings.ollamaUrl}/api/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: settings.ollamaModel,
prompt: prompt,
stream: false,
format: "json"
})
});
if (!response.ok) return "Cosmic energy flows.";
const data = await response.json();
const parsed = JSON.parse(data.response);
return parsed.prediction || "Alignment looks favorable.";
} catch (e) {
console.error("Horoscope gen failed", e);
return "Magic is in the air.";
}
};