ai cooking
0
fork

Configure Feed

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

Merge remote-tracking branch 'origin/master'

+36 -10
+1
.gitignore
··· 5 5 *.so 6 6 *.dylib 7 7 /cmd/careme/careme 8 + /careme 8 9 9 10 # Test binary, built with `go test -c` 10 11 *.test
+2 -2
go.mod
··· 10 10 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 11 11 github.com/alpkeskin/gotoon v0.1.1 12 12 github.com/invopop/jsonschema v0.13.0 13 - github.com/openai/openai-go/v2 v2.7.1 13 + github.com/openai/openai-go/v3 v3.10.0 14 14 github.com/samber/slog-multi v1.5.0 15 15 github.com/sendgrid/rest v2.6.9+incompatible 16 16 github.com/sendgrid/sendgrid-go v3.16.1+incompatible ··· 45 45 github.com/perimeterx/marshmallow v1.1.5 // indirect 46 46 github.com/speakeasy-api/jsonpath v0.6.0 // indirect 47 47 github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect 48 - github.com/tidwall/gjson v1.14.4 // indirect 48 + github.com/tidwall/gjson v1.18.0 // indirect 49 49 github.com/tidwall/match v1.1.1 // indirect 50 50 github.com/tidwall/pretty v1.2.1 // indirect 51 51 github.com/tidwall/sjson v1.2.5 // indirect
+4 -4
go.sum
··· 104 104 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 105 105 github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= 106 106 github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= 107 - github.com/openai/openai-go/v2 v2.7.1 h1:/tfvTJhfv7hTSL8mWwc5VL4WLLSDL5yn9VqVykdu9r8= 108 - github.com/openai/openai-go/v2 v2.7.1/go.mod h1:jrJs23apqJKKbT+pqtFgNKpRju/KP9zpUTZhz3GElQE= 107 + github.com/openai/openai-go/v3 v3.10.0 h1:l9/stPpyf9WRtx3G+BDyIbdVPiYLk18d7lG9hVlQfOY= 108 + github.com/openai/openai-go/v3 v3.10.0/go.mod h1:cdufnVK14cWcT9qA1rRtrXx4FTRsgbDPW7Ia7SS5cZo= 109 109 github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= 110 110 github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= 111 111 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= ··· 138 138 github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 139 139 github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 140 140 github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 141 - github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= 142 - github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 141 + github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= 142 + github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 143 143 github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 144 144 github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 145 145 github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+5 -4
internal/ai/client.go
··· 14 14 "time" 15 15 16 16 "github.com/alpkeskin/gotoon" 17 - openai "github.com/openai/openai-go/v2" 18 - "github.com/openai/openai-go/v2/option" 19 - "github.com/openai/openai-go/v2/responses" 17 + openai "github.com/openai/openai-go/v3" 18 + "github.com/openai/openai-go/v3/option" 19 + "github.com/openai/openai-go/v3/responses" 20 20 "github.com/samber/lo" 21 21 22 22 "github.com/invopop/jsonschema" ··· 44 44 Instructions []string `json:"instructions"` 45 45 Health string `json:"health"` 46 46 DrinkPairing string `json:"drink_pairing"` 47 + OriginHash string `json:"origin_hash"` 47 48 } 48 49 49 50 // ComputeHash calculates the SHA256 hash of the recipe content ··· 113 114 client := openai.NewClient(option.WithAPIKey(c.apiKey)) 114 115 115 116 params := responses.ResponseNewParams{ 116 - Model: openai.ChatModelGPT5, 117 + Model: openai.ChatModelGPT5_1, 117 118 Instructions: openai.String(systemMessage), 118 119 119 120 Input: responses.ResponseNewParamsInputUnion{
+1
internal/recipes/generator.go
··· 171 171 172 172 // Save each recipe separately by its hash 173 173 for _, recipe := range shoppingList.Recipes { 174 + recipe.OriginHash = p.Hash() 174 175 recipeJSON := lo.Must(json.Marshal(recipe)) 175 176 if err := g.cache.Set("recipe/"+recipe.ComputeHash(), string(recipeJSON)); err != nil { 176 177 slog.ErrorContext(ctx, "failed to cache individual recipe", "recipe", recipe.Title, "error", err)
+8
internal/recipes/server.go
··· 65 65 ID: "", 66 66 Name: "Unknown Location", 67 67 }, time.Now()) 68 + if recipe.OriginHash != "" { 69 + p, err = s.generator.LoadParamsFromHash(recipe.OriginHash) 70 + if err != nil { 71 + slog.ErrorContext(ctx, "failed to load params for hash", "hash", recipe.OriginHash, "error", err) 72 + http.Error(w, "recipe not found or expired", http.StatusNotFound) 73 + return 74 + } 75 + } 68 76 69 77 list := ai.ShoppingList{ 70 78 Recipes: []ai.Recipe{*recipe},
+15
internal/templates/chat.html
··· 5 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 6 <title>Careme Recipes</title> 7 7 8 + {{if .Recipes}} 9 + <!-- Open Graph meta tags for social sharing (WhatsApp, Facebook, etc.) --> 10 + <meta property="og:title" content="{{(index .Recipes 0).Title}}" /> 11 + <meta property="og:description" content="{{(index .Recipes 0).Description}}" /> 12 + <meta property="og:image" content="https://careme.cooking/favicon.ico" /> 13 + <meta property="og:type" content="website" /> 14 + <meta property="og:site_name" content="Careme" /> 15 + 16 + <!-- Twitter Card meta tags --> 17 + <meta name="twitter:card" content="summary" /> 18 + <meta name="twitter:title" content="{{(index .Recipes 0).Title}}" /> 19 + <meta name="twitter:description" content="{{(index .Recipes 0).Description}}" /> 20 + <meta name="twitter:image" content="https://careme.cooking/favicon.ico" /> 21 + {{end}} 22 + 8 23 {{template "tailwind_head"}} 9 24 10 25 {{.ClarityScript}}