ai generated tasks check for duplicates, existing streaks, and more before creation
This commit is contained in:
@@ -1,8 +1,16 @@
|
||||
import { sanitizePlausibleAiTaskLabels } from "@/lib/ai-habit-utils";
|
||||
import {
|
||||
finalizeNewAiTaskLabels,
|
||||
sanitizePlausibleAiTaskLabels,
|
||||
} from "@/lib/ai-habit-utils";
|
||||
import {
|
||||
formatAiTaskContextForPrompt,
|
||||
type AiTaskContext,
|
||||
} from "@/lib/ai-task-context";
|
||||
import {
|
||||
buildGenerationUserPrompt,
|
||||
MAX_DAILY_AI_TASKS,
|
||||
type AiTaskGenerationOptions,
|
||||
} from "@/lib/ai-task-generation";
|
||||
import { mergeJournalHintsIntoLabels } from "@/lib/ai-journal-hints";
|
||||
|
||||
const OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions";
|
||||
@@ -27,6 +35,7 @@ function extractJsonArray(content: string) {
|
||||
|
||||
export async function generateAiTaskLabels(
|
||||
context: AiTaskContext,
|
||||
options?: AiTaskGenerationOptions,
|
||||
): Promise<string[]> {
|
||||
const apiKey = process.env.OPENROUTER_API_KEY;
|
||||
|
||||
@@ -34,6 +43,7 @@ export async function generateAiTaskLabels(
|
||||
throw new Error("OPENROUTER_API_KEY is not configured.");
|
||||
}
|
||||
|
||||
const maxCount = options?.maxCount ?? MAX_DAILY_AI_TASKS;
|
||||
const siteUrl =
|
||||
process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
|
||||
|
||||
@@ -52,13 +62,13 @@ export async function generateAiTaskLabels(
|
||||
{
|
||||
role: "system",
|
||||
content:
|
||||
"You are a supportive wellness coach for a habit-tracking pet app. Suggest practical, specific daily habits tailored to the user's data. Each task must be a concrete action the user can check off (e.g. 'Drink a full glass of water', 'Go for a swim'). Never suggest vague tasks like 'spend time on hydration' or use abstract focus topics (sleep, movement, hydration, mindfulness) as task names. The journal entry reflects what the user wants to do today — if they mention an activity (e.g. swimming, running, yoga), you MUST include at least one closely related check-off task. If stress is high, include calming or light cardio tasks that fit their journal. Return ONLY a JSON array of 3 to 5 strings. Each string must be a short habit label under 8 words.",
|
||||
"You are a supportive wellness coach for a habit-tracking pet app. Suggest practical, specific daily habits tailored to the user's data. Each task must be a concrete action the user can check off (e.g. 'Drink a full glass of water', 'Go for a swim'). Never suggest vague tasks like 'spend time on hydration', single-word activities like 'Running', or duplicate tasks for the same activity. Never use abstract focus topics (sleep, movement, hydration, mindfulness) as task names. The journal entry reflects what the user wants to do today — if they mention an activity (e.g. swimming, running, yoga), include a closely related check-off task when appropriate. Return ONLY a JSON array of strings. Each string must be a short habit label under 8 words.",
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: `${formatAiTaskContextForPrompt(context)}
|
||||
|
||||
Generate today's personalized habit task labels as a JSON array of strings.`,
|
||||
${buildGenerationUserPrompt(context, options)}`,
|
||||
},
|
||||
],
|
||||
}),
|
||||
@@ -84,11 +94,14 @@ Generate today's personalized habit task labels as a JSON array of strings.`,
|
||||
const labels = mergeJournalHintsIntoLabels(
|
||||
sanitizePlausibleAiTaskLabels(extractJsonArray(content) ?? []),
|
||||
context,
|
||||
{ fillInOnly: true, maxCount, excludeLabels: options?.excludeLabels },
|
||||
);
|
||||
|
||||
if (labels.length === 0) {
|
||||
const finalized = finalizeNewAiTaskLabels(labels, options);
|
||||
|
||||
if (finalized.length === 0 && maxCount > 0) {
|
||||
throw new Error("OpenRouter response did not include valid task labels.");
|
||||
}
|
||||
|
||||
return labels;
|
||||
return finalized;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user