Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Optional AI assistant on recipe and menu pages

Aperta
#633 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
rust
Ambito
ai, backend, frontend

Direzione di ricerca

Start by reading the server routes and recipe editor flow, especially PUT /api/recipes/{path}, the /api/shopping_list/events SSE endpoint, and crates/core/src/parser.rs; also review tests/locales_test.rs and the editor dialog pattern. The issue describes a broad feature spanning provider configuration, streamed conversations, access control, safe edit proposals, UI, docs, and tests, so first map those existing entry points and split the work into smaller pieces. Done means the configured assistant works across recipe and menu pages, remains inert when unconfigured, and its behavior is covered by the listed mock-provider and access-control tests.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

area: server feature request needs discussion

cook server can display and edit recipes, but it can't help with the questions that come up while reading one. For example: is this right? Can I make it without an oven? Why is dough on my shopping list? Nothing checks a recipe for the mistakes the parser accepts but that still give a wrong shopping list: a step's product written again as an @ingredient, or the same ingredient under two names or in units that don't add up. An LLM that knows Cooklang and CookCLI's conventions could answer those questions and propose fixes, as long as it never writes anything the user hasn't seen and approved.

Proposal

An assistant that stays off unless the server is configured for it. Without configuration nothing changes: no button, no route, no request leaving the server.

Configuration (environment only)

Everything is set through environment variables. That keeps the API key out of command lines and ps, and a Docker deployment only needs -e:

Variable
COOK_AI_PROVIDER turns the assistant on openai, anthropic, gemini, mistral, groq, deepseek, ollama, …
COOK_AI_MODEL required with a provider e.g. gpt-4.1-mini, claude-sonnet-…, llama3.1:8b
COOK_AI_API_KEY not needed for Ollama never sent to the browser
COOK_AI_BASE_URL optional Ollama host, or any OpenAI-compatible endpoint (OpenRouter, LM Studio, vLLM, a proxy)
COOK_AI_ALLOW_EDITS optional, off by default lets the assistant propose changes that can be applied (see below)
COOK_AI_INSTRUCTIONS_FILE optional house rules appended to the system prompt (units, diet, tone, …)

A multi-provider crate such as genai speaks to all of these, Ollama and custom endpoints included, so CookCLI doesn't need a client per vendor. It would sit behind an ai cargo feature, the same way sync does. On startup the server logs one line naming the provider and model (never the key). A provider without a model, or an unknown provider, is a startup error rather than a silent no-op.

In the web UI
  • An Ask AI button in the action bar of the recipe page and the menu page. It is hidden in static mode and from viewers who may not use it.
  • The button opens an overlay modal (the same backdrop + .card + role="dialog" pattern as the editor's dialogs) with:
    • quick actions:
      • Analyze this recipe: list problems and suggestions, change nothing;
      • Correct this recipe: Cooklang syntax and CookCLI conventions only;
      • Improve this recipe: clarity, missing quantities, times, servings;
    • a free-text box for any other question ("can I replace the cream?", "how do I make this for 10?", "what wine goes with this menu?");
    • a conversation that takes follow-ups. It lives in the page only, is never stored on the server, and is gone when the page is left.
  • Answers stream in as they are generated (SSE, like /api/shopping_list/events). The model's output is rendered as text and never inserted as HTML.
  • The assistant answers in the UI's language, because the current locale is passed to it. New strings go into all locales (tests/locales_test.rs).
What the assistant knows

The server builds the system prompt for each request:

  1. Cooklang as CookCLI parses it:

    • @ingredient{qty%unit}, #cookware{}, ~timer{};
    • YAML front matter (not the deprecated >> metadata), sections, notes and comments;
    • recipe references @./path{…}.

    CookCLI's parser runs with no extensions (Extensions::empty() in crates/core/src/parser.rs), so the prompt must keep the model away from extension syntax CookCLI doesn't understand, such as @&(~1)dough{} intermediate references or @? modifiers.

  2. CookCLI conventions that shape the shopping list and pantry:

    • every @ingredient lands on the shopping list. The product of an earlier step ("the dough", "the sauce", "the marinade") is therefore written as plain text, not declared again as an ingredient;
    • a component that is a recipe of its own is a reference (@./Shared/Pizza Dough{6%balls}), which the shopping list expands;
    • one name per ingredient and compatible units, so quantities add up. Names should match aisle.conf and pantry.conf;
    • for menus: .menu files, sections and dated sections, and {2} / {3%servings} scaling of referenced recipes.
  3. The file being looked at:

    • its raw source (not the rendered page) and its path;
    • the diagnostics the parser currently reports for it (cookcli_core::parse_recipe), so Analyze starts from real warnings;
    • for a menu, the titles and servings of the recipes it references.

The prompt lives in the repository (e.g. a Markdown file pulled in with include_str!), so it is reviewed like code and versioned with the parser it describes. COOK_AI_INSTRUCTIONS_FILE can add to it but not replace it.

Proposing changes (only with COOK_AI_ALLOW_EDITS)

The assistant never writes a file itself. When edits are allowed and the user asks for a change, it replies with:

  1. a short summary of what it is going to change and why;
  2. the complete new text of the file, in a fenced block the server extracts. This works with every provider and with small local models, whereas tool calling isn't supported by every Ollama model.

The modal shows the summary and a line diff against the current file, then offers:

  • Apply;
  • Open in editor: the editor opens pre-filled with the proposal, and the user saves from there as usual;
  • Discard, or keep chatting to adjust the proposal.

Nothing is saved without an explicit click.

  • Before Apply is offered, the server parses the proposed text. If it doesn't parse, or adds errors the current file doesn't have, the diagnostics are shown and the proposal can only be opened in the editor or sent back to the assistant to fix.
  • Apply saves through the editor's existing path (PUT /api/recipes/{path}). It therefore needs the same role as the editor and is logged by activity::record, e.g. updated "Pancakes.cook" (AI proposal).
  • Apply is refused (409) if the file changed since the proposal was made, because the proposal carries a hash of the text it was based on.
  • Without COOK_AI_ALLOW_EDITS, the assistant still analyses and suggests in prose, and the modal shows no Apply or Open in editor.
Access
  • Sign-in on (users.toml):
    • any signed-in user can chat; guests don't see the button and get 401 from the routes;
    • applying a proposal needs editor (EditRecipes), as the editor does;
    • a new POST route defaults to Administer in required_capability, so this needs a way to say "any signed-in user" (Reader).
  • Sign-in off: whoever reaches the server can chat, just as they can already edit. The docs should warn that a public server with the assistant on spends the operator's API credits, and point to sign-in.
  • --recipes-only guests: no assistant.
Cost, privacy, safety
  • The file's text is sent to the configured provider. The docs should say so, and that Ollama keeps everything on the machine.
  • Limits: request size, conversation length and output tokens, a timeout, and a cap on concurrent requests (like --max-lsp-sessions).
  • The model gets no tools: it cannot read other files or write anything. A recipe containing instructions aimed at the model can at worst produce a bad proposal, which the user sees as a diff before applying it.
  • The API key never appears in a page, a log line or an error sent to the browser.
Testing
  • A mock provider (or a local OpenAI-compatible stub) lets cargo test and Playwright cover the modal, streaming, the diff and Apply without a key or network.
  • Cases to cover:
    • unconfigured: no button and no routes;
    • roles: guest 401, reader can ask but not apply, editor can apply;
    • a stale proposal gets 409;
    • a proposal that doesn't parse can't be applied.
Follow-ups (not in this issue)
  • A general Ask AI in the navigation with no recipe open: what can I cook with leeks, or draft a new recipe, with a search over the collection.
  • Assistant actions inside the editor (on a selection).
  • Cleaning up cook import results, suggesting aisles for uncategorised ingredients (#630), or drafting a meal plan.
  • A cook ai CLI command.
Lingua principale
Rust
Stelle
1.4k
Fork
120
Merge medio
1g 20h
PR unite (30g)
116

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di cooklang/cookcli

Tutte le issue di cooklang/cookcli

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.