ai cooking
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Use broad categories for wholefoods wine (#341)

* pagination

* hack for wf wine for now

---------

Co-authored-by: paul miller <paul.miller>

authored by

Paul Miller
paul miller
and committed by
GitHub
7c273350 3b1fe096

+78 -1
+6 -1
internal/recipes/generator.go
··· 7 7 "careme/internal/kroger" 8 8 "careme/internal/locations" 9 9 "careme/internal/parallelism" 10 + "careme/internal/wholefoods" 10 11 "context" 11 12 "encoding/base64" 12 13 "errors" ··· 61 62 62 63 func (g *Generator) PickAWine(ctx context.Context, conversationID string, location string, recipe ai.Recipe, date time.Time) (*ai.WineSelection, error) { 63 64 var styles []string 64 - //THIS is broken for wholefoods until we put in product search or just fetch all red/whiteines. 65 65 for _, style := range recipe.WineStyles { 66 66 style = strings.TrimSpace(style) 67 67 if style != "" { //would this ever happen? 68 68 styles = append(styles, style) 69 69 } 70 + } 71 + 72 + //whole foods search not actually implmented hard code categories 73 + if wholefoods.NewIdentityProvider().IsID(location) { 74 + styles = []string{"red-wine", "white-wine", "sparkling"} //rose 70 75 } 71 76 72 77 if len(styles) == 0 {
+72
internal/recipes/generator_test.go
··· 6 6 "careme/internal/kroger" 7 7 "careme/internal/locations" 8 8 "context" 9 + "slices" 10 + "sync" 9 11 "testing" 10 12 "time" 11 13 ) ··· 15 17 answer string 16 18 recipeTitle string 17 19 selection *ai.WineSelection 20 + } 21 + 22 + type captureWineStaplesProvider struct { 23 + mu sync.Mutex 24 + searches []string 25 + responses map[string][]kroger.Ingredient 18 26 } 19 27 20 28 func (c *captureWineQuestionAIClient) GenerateRecipes(ctx context.Context, location *locations.Location, ingredients []kroger.Ingredient, instructions []string, date time.Time, lastRecipes []string) (*ai.ShoppingList, error) { ··· 45 53 return nil 46 54 } 47 55 56 + func (s *captureWineStaplesProvider) FetchStaples(ctx context.Context, location *locations.Location) ([]kroger.Ingredient, error) { 57 + panic("unexpected call to FetchStaples") 58 + } 59 + 60 + func (s *captureWineStaplesProvider) GetIngredients(_ context.Context, _ string, searchTerm string, _ int) ([]kroger.Ingredient, error) { 61 + s.mu.Lock() 62 + s.searches = append(s.searches, searchTerm) 63 + s.mu.Unlock() 64 + return slices.Clone(s.responses[searchTerm]), nil 65 + } 66 + 67 + func (s *captureWineStaplesProvider) searchTerms() []string { 68 + s.mu.Lock() 69 + defer s.mu.Unlock() 70 + return slices.Clone(s.searches) 71 + } 72 + 48 73 func TestWineIngredientsCacheKey_UsesStyleDateAndLocation(t *testing.T) { 49 74 got := wineIngredientsCacheKey(" Pinot Noir ", "70500874", time.Date(2026, 2, 1, 8, 0, 0, 0, time.UTC)) 50 75 want := "wines/0XY3COdxwHk" ··· 106 131 t.Fatalf("expected recipe title %q, got %q", "Roast Chicken", aiStub.recipeTitle) 107 132 } 108 133 } 134 + 135 + func TestPickAWine_WholeFoodsUsesHardcodedWineCategories(t *testing.T) { 136 + aiStub := &captureWineQuestionAIClient{ 137 + answer: "Try one of these bottles.", 138 + selection: &ai.WineSelection{ 139 + Wines: []ai.Ingredient{ 140 + {Name: "Whole Foods Red"}, 141 + {Name: "Whole Foods White"}, 142 + {Name: "Whole Foods Bubbly"}, 143 + }, 144 + Commentary: "Try one of these bottles.", 145 + }, 146 + } 147 + staplesStub := &captureWineStaplesProvider{ 148 + responses: map[string][]kroger.Ingredient{ 149 + "red-wine": {{Description: loPtr("Whole Foods Red")}}, 150 + "white-wine": {{Description: loPtr("Whole Foods White")}}, 151 + "sparkling": {{Description: loPtr("Whole Foods Bubbly")}}, 152 + }, 153 + } 154 + g := &Generator{ 155 + io: IO(cache.NewFileCache(t.TempDir())), 156 + aiClient: aiStub, 157 + staplesProvider: staplesStub, 158 + } 159 + 160 + got, err := g.PickAWine(t.Context(), "conv-wholefoods", "wholefoods_10216", ai.Recipe{ 161 + Title: "Salmon", 162 + WineStyles: []string{"Pinot Noir"}, 163 + }, time.Date(2026, 3, 9, 0, 0, 0, 0, time.UTC)) 164 + if err != nil { 165 + t.Fatalf("PickAWine returned error: %v", err) 166 + } 167 + 168 + searches := staplesStub.searchTerms() 169 + slices.Sort(searches) 170 + wantSearches := []string{"red-wine", "sparkling", "white-wine"} 171 + if !slices.Equal(searches, wantSearches) { 172 + t.Fatalf("unexpected whole foods wine searches: got %v want %v", searches, wantSearches) 173 + } 174 + if got == nil || len(got.Wines) != 3 { 175 + t.Fatalf("unexpected wine selection: %+v", got) 176 + } 177 + if aiStub.recipeTitle != "Salmon" { 178 + t.Fatalf("expected recipe title %q, got %q", "Salmon", aiStub.recipeTitle) 179 + } 180 + }