Feature 04 task 4: Default seeding for AI settings and notification preferences (#28)
CI / ci (push) Successful in 1m26s
CI / ci (push) Successful in 1m26s
Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com> Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
This commit was merged in pull request #28.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
package household
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/db"
|
||||
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/store"
|
||||
)
|
||||
|
||||
// DefaultPersonaPrompt is the default AI system prompt (CTXD PROMPTS.MD §4).
|
||||
// SeedAISettings stores it on first boot and the Admin reset restores it.
|
||||
const DefaultPersonaPrompt = `You are MealQuest, a dinner planning assistant for one household. Suggest dinners
|
||||
similar to their regular rotation, nudging them to try something a little new each
|
||||
week. Prefer weeknight-friendly recipes with common grocery-store ingredients.
|
||||
Flag crock pot meals and anything 30 minutes or less as "quick". Keep explanations
|
||||
short, warm and specific — mention the household's own regular dinners when you
|
||||
explain why something fits. Never suggest a dinner they already make or have
|
||||
declined.`
|
||||
|
||||
// Seed values for the AI settings (CTXD CONTEXT.MD). The base URL and model
|
||||
// are empty until the household picks a provider preset; there is no key.
|
||||
const (
|
||||
SeedAIProvider = "anthropic"
|
||||
SeedAIBaseURL = ""
|
||||
SeedAIModel = ""
|
||||
SeedAITemperature = 0.7
|
||||
)
|
||||
|
||||
// seedNotificationPrefs are the notification preferences for a new
|
||||
// household, one per event: push for every event, chat only for the plan
|
||||
// and the shopping list.
|
||||
var seedNotificationPrefs = []struct {
|
||||
Event string
|
||||
Push, Chat bool
|
||||
}{
|
||||
{Event: "plan_ready", Push: true, Chat: true},
|
||||
{Event: "list_ready", Push: true, Chat: true},
|
||||
{Event: "day_of_reminder", Push: true, Chat: false},
|
||||
{Event: "new_suggestions", Push: true, Chat: false},
|
||||
{Event: "rotation_review", Push: true, Chat: false},
|
||||
}
|
||||
|
||||
// SeedAISettings creates the AI settings row with the seed values and
|
||||
// DefaultPersonaPrompt if it does not exist. An existing row is never
|
||||
// changed.
|
||||
func SeedAISettings(ctx context.Context, st *store.Store) error {
|
||||
return st.WithTx(ctx, func(tx *sql.Tx) error {
|
||||
q := db.New(tx)
|
||||
_, err := q.GetAISettings(ctx)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
return fmt.Errorf("household: read AI settings: %w", err)
|
||||
}
|
||||
now := store.Now().String()
|
||||
_, err = q.UpsertAISettings(ctx, db.UpsertAISettingsParams{
|
||||
Provider: SeedAIProvider,
|
||||
BaseUrl: SeedAIBaseURL,
|
||||
Model: SeedAIModel,
|
||||
Temperature: SeedAITemperature,
|
||||
SystemPrompt: sql.NullString{String: DefaultPersonaPrompt, Valid: true},
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("household: seed AI settings: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// SeedNotificationPrefs creates the seed notification preference row of
|
||||
// every event that has none. Existing rows are never changed.
|
||||
func SeedNotificationPrefs(ctx context.Context, st *store.Store) error {
|
||||
return st.WithTx(ctx, func(tx *sql.Tx) error {
|
||||
now := store.Now().String()
|
||||
for _, p := range seedNotificationPrefs {
|
||||
_, err := tx.ExecContext(ctx,
|
||||
`INSERT INTO notification_prefs (event, push, chat, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT (event) DO NOTHING`,
|
||||
p.Event, p.Push, p.Chat, now, now)
|
||||
if err != nil {
|
||||
return fmt.Errorf("household: seed notification preference %s: %w", p.Event, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user