156 lines
4.6 KiB
TypeScript
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.";
|
|
}
|
|
}; |