From fc57fe2415df07f65ef0aa7a69fed42959804a2b Mon Sep 17 00:00:00 2001 From: Sjoerd de Vries Date: Wed, 20 May 2026 17:48:23 +0200 Subject: [PATCH] feat: AI coach functions --- src/ai/coach.ts | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/ai/coach.ts diff --git a/src/ai/coach.ts b/src/ai/coach.ts new file mode 100644 index 0000000..f7f7468 --- /dev/null +++ b/src/ai/coach.ts @@ -0,0 +1,69 @@ +import type { Database } from 'better-sqlite3'; +import { createAiClient } from './client'; +import { buildContext } from './context'; +import { progressPrompt, nextStepPrompt, reschedulePrompt, setupPrompt } from './prompts'; +import { parseScheduleJson, type ScheduleProposal } from './parser'; +import { getSetting } from '../db/settings'; +import { config } from '../config'; + +function getModel(db: Database): string { + return getSetting(db, 'model') ?? config.defaultModel; +} + +async function chat( + db: Database, + system: string, + user: string, + jsonMode = false +): Promise { + const client = createAiClient(); + const model = getModel(db); + const response = await client.chat.completions.create({ + model, + messages: [ + { role: 'system', content: system }, + { role: 'user', content: user }, + ], + ...(jsonMode ? { response_format: { type: 'json_object' } } : {}), + }); + return response.choices[0]?.message.content ?? ''; +} + +export async function getProgressAnalysis(db: Database, today: string): Promise { + const ctx = buildContext(db, today); + const { system, user } = progressPrompt(ctx); + return chat(db, system, user); +} + +export async function getNextStep(db: Database, today: string): Promise { + const ctx = buildContext(db, today); + const { system, user } = nextStepPrompt(ctx); + return chat(db, system, user); +} + +export async function generateSchedule( + db: Database, today: string, note: string | null +): Promise { + const ctx = buildContext(db, today); + const { system, user } = reschedulePrompt(ctx, note); + const raw = await chat(db, system, user); + return parseScheduleJson(raw); +} + +export async function generateSetupSchedule( + db: Database, + today: string, + currentLevel: string, + availability: string, + goal: string +): Promise { + const { system, user } = setupPrompt(currentLevel, availability, goal); + const raw = await chat(db, system, user); + return parseScheduleJson(raw); +} + +export async function freeChat(db: Database, today: string, message: string): Promise { + const ctx = buildContext(db, today); + const { system } = progressPrompt(ctx); + return chat(db, system, message); +}