package app_test import ( "context" "fmt" "os" "path/filepath" "strings" "testing" "time" promptkitadapter "gitea.maximumdirect.net/eric/weatherreporter/internal/adapters/promptkit" "gitea.maximumdirect.net/eric/weatherreporter/internal/app" "gitea.maximumdirect.net/eric/weatherreporter/internal/config" "gitea.maximumdirect.net/eric/weatherreporter/internal/report" ) func TestPromptInspectionResolvesEmbeddedAndOverriddenProfilesOffline(t *testing.T) { inspect := func(t *testing.T, adapter *promptkitadapter.Adapter, id report.ID, profile string, wantID string, wantBackend string, wantModel string) { t.Helper() result, err := app.InspectPromptExecution(context.Background(), app.PromptInspectionRequest{ Resolved: resolvedPromptProfile(t, id), Executor: adapter, Promptkit: config.PromptkitConfig{Profile: profile}, }) if err != nil { t.Fatalf("InspectPromptExecution() error = %v", err) } if result.ProfileID != wantID || result.BackendID != wantBackend || result.ModelName != wantModel { t.Fatalf("inspection = %#v, want profile/backend/model %q/%q/%q", result, wantID, wantBackend, wantModel) } } embedded, err := promptkitadapter.New(promptkitadapter.Config{}) if err != nil { t.Fatalf("New(embedded) error = %v", err) } inspect(t, embedded, report.Hourly, "", "weather-light", "openrouter", "deepseek/deepseek-v4-flash") inspect(t, embedded, report.Daily, "", "weather-balanced", "openrouter", "~google/gemini-flash-latest") inspect(t, embedded, report.Daily, "weather-deep", "weather-deep", "openrouter", "~anthropic/claude-sonnet-latest") override, err := promptkitadapter.New(promptkitadapter.Config{ProfileFile: writeProfileFile(t, `id: weather-light endpoint: https://local.example/v1 backend: openrouter model: local-weather `)}) if err != nil { t.Fatalf("New(override) error = %v", err) } inspect(t, override, report.Hourly, "", "weather-light", "openrouter", "local-weather") } func TestPromptInspectionAcceptsMaintainedEndpointOnlyProfile(t *testing.T) { adapter, err := promptkitadapter.New(promptkitadapter.Config{ProfileFile: filepath.Join("..", "..", "examples", "weather-light-local-profile.yml")}) if err != nil { t.Fatalf("New() error = %v", err) } result, err := app.InspectPromptExecution(context.Background(), app.PromptInspectionRequest{ Resolved: resolvedPromptProfile(t, report.Hourly), Executor: adapter, }) if err != nil { t.Fatalf("InspectPromptExecution() error = %v", err) } if result.ProfileID != "weather-light" || result.BackendID != "" || result.ModelName != "weather-local" { t.Fatalf("inspection = %#v", result) } if strings.Contains(fmt.Sprintf("%#v", result), "127.0.0.1") { t.Fatalf("inspection leaks endpoint: %#v", result) } } func TestPromptInspectionSupportsRakestrawhomeProfileOffline(t *testing.T) { adapter, err := promptkitadapter.New(promptkitadapter.Config{}) if err != nil { t.Fatalf("New() error = %v", err) } prompt, err := app.InspectPromptExecution(context.Background(), app.PromptInspectionRequest{ Resolved: resolvedPromptProfile(t, report.Hourly), Executor: adapter, Promptkit: config.PromptkitConfig{Profile: "rakestrawhome-gemma-4-31b"}, }) if err != nil { t.Fatalf("InspectPromptExecution() error = %v", err) } if prompt.ProfileID != "rakestrawhome-gemma-4-31b" || prompt.BackendID != "rakestrawhome" || prompt.ModelName == "" { t.Fatalf("prompt inspection = %#v", prompt) } comparison, err := app.InspectComparisonExecution(context.Background(), app.ComparisonInspectionRequest{ Resolved: resolvedPromptProfile(t, report.Hourly), ProfileIDs: []string{"rakestrawhome-gemma-4-31b", "weather-deep"}, Executor: adapter, }) if err != nil { t.Fatalf("InspectComparisonExecution() error = %v", err) } if len(comparison.Profiles) != 2 || comparison.Profiles[0].ProfileID != "rakestrawhome-gemma-4-31b" || comparison.Profiles[0].BackendID != "rakestrawhome" || comparison.Profiles[0].ModelName == "" { t.Fatalf("comparison inspection = %#v", comparison) } } func resolvedPromptProfile(t *testing.T, id report.ID) report.Resolved { t.Helper() now := time.Date(2026, 5, 29, 12, 0, 0, 0, time.UTC) request := report.ResolveRequest{Now: now, Location: time.UTC} if id == report.Daily { request.Date = now } resolved, err := report.DefaultRegistry().Resolve(id, request) if err != nil { t.Fatalf("Resolve(%q) error = %v", id, err) } return resolved } func writeProfileFile(t *testing.T, profile string) string { t.Helper() path := filepath.Join(t.TempDir(), "profile.yml") if err := os.WriteFile(path, []byte(profile), 0o600); err != nil { t.Fatalf("write profile: %v", err) } return path }