From 78599c498191227a0c3867a08426a98bcc148079 Mon Sep 17 00:00:00 2001 From: langwatch-improve-bot Date: Thu, 23 Apr 2026 11:42:22 +0000 Subject: [PATCH] auto: iteration 20260423-113311 --- .github/_auto_pr_body.md | 41 +++++++++-------------- .github/_auto_scoreboard.md | 36 +++++++------------- api/main.py | 1 + web/components/chat.tsx | 65 ++++++++++++++++++++++++++++--------- 4 files changed, 77 insertions(+), 66 deletions(-) diff --git a/.github/_auto_pr_body.md b/.github/_auto_pr_body.md index 4584bec..0822174 100644 --- a/.github/_auto_pr_body.md +++ b/.github/_auto_pr_body.md @@ -1,45 +1,34 @@ -# auto: add dietary preference chips to chat UI +# auto: chat bubble layout — directional message alignment ## Why -40%+ of recent traces show users explicitly typing dietary restrictions ("vegan gluten-free nut-free") in every single message — pure repetitive friction. The Flagsmith flag `auto_dietary_pref_chips` was created by a prior iterator run but never wired to any code. This PR implements the feature: a row of toggle chips (Vegan, Gluten-Free, Nut-Free, Dairy-Free) that persist across the session and auto-inject the selected preferences into each outgoing message. Trace evidence: e.g., `6f97e35c`, `64ca9586`, `7655b4d6`, `0bb3aee3`, `4532ec17`. +The existing chat UI uses `ml-8`/`mr-8` indented blocks for messages — both user and assistant messages are visually identical blocks that differ only by their tiny "You"/"Chef" label. A proper directional bubble layout (user right-aligned, assistant left-aligned) is the highest-impact single visual improvement for a conversational UI. The operator's focus hint explicitly calls out "visual polish, spacing, typography, color, and layout." ## What -- `web/components/chat.tsx`: on mount, fetches `/flags` from the backend; if `dietary_pref_chips` is true, renders a row of pill-shaped toggle chips below the model-tier selector. Active chips highlight in the accent colour. When the user sends a message, selected prefs are appended to the text sent to the agent (e.g. `"pasta recipe [dietary: Vegan, Gluten-Free]"`). The displayed bubble shows the raw user text without the injected suffix. Input placeholder also updates to reflect active preferences. -- `api/main.py`: adds a `GET /flags` endpoint that reads Flagsmith flag values and returns them as JSON, so the frontend can query flag state without a JS SDK or exposed env vars. +- `web/components/chat.tsx`: Added `bubbleLayout` state flag read from `/flags`; when enabled, messages render as directional flex bubbles — user messages right-aligned with warm orange-tinted background (`bg-accent/15`, `border-accent/30`, orange "You" label), assistant messages left-aligned with elevated card style (`rounded-2xl`, `shadow-sm`). Old layout preserved as fallback when flag is off. +- `api/main.py`: Added `chat_bubble_layout` key to the `/flags` endpoint so the frontend can read the Flagsmith value. ## Flag -- `auto_dietary_pref_chips` — default **off**. Enable in Flagsmith "cooking" project → Development to activate. +- `auto_chat_bubble_layout` — default **off**. Enable in Flagsmith "cooking" project → Development to activate the new bubble layout. ## Eval delta | Scenario | Before | After | |---|---|---| -| basic_weeknight_recipe | ✅ 4/4 | ✅ 4/4 | -| dietary_constraints | ✅ 4/4 | ✅ 4/4 | -| substitution | ✅ 4/4 | ✅ 4/4 | +| basic_weeknight_recipe | ✅ | ✅ | +| dietary_constraints | ✅ | ✅ | +| safety_warning | ✅ | ✅ | +| substitution | ✅ | ✅ | -No scenarios were modified. All three pass before and after. - -## Screenshots - -| Before (flag off — no chips) | After (flag on — chips visible) | -|---|---| -| ![before](https://i.img402.dev/g9z7ziw6fh.jpg) | ![after](https://i.img402.dev/e19pb8jrdm.jpg) | +No scenarios were modified. Change is purely frontend CSS/layout. ## How to test ``` -git checkout +git checkout auto/improve-20260423-113311 pip install -e ".[dev]" -cd web && npm install && npm run dev & +# flip auto_chat_bubble_layout ON in Flagsmith Development environment uvicorn api.main:app --port 8000 & -# then flip auto_dietary_pref_chips ON in Flagsmith to see the chips appear -# try: select "Vegan" + "Gluten-Free", type "give me a pasta recipe", send -# confirm the agent receives the dietary context and respects it -pytest -v tests/ -m agent_test +cd web && npm install && npm run dev +# open http://localhost:3000 and send a few messages ``` ## Rollback -Flip `auto_dietary_pref_chips` off in Flagsmith. No code revert needed — the UI silently hides the chips row when the flag is off. - -## Follow-ups -- Candidate 2: Clickable example prompts in empty state (replace single static hint with 3–4 clickable suggestions). -- Candidate 3: Copy-to-clipboard button on assistant message cards (recipe text is long; one-click copy is high-value QOL). +Flip `auto_chat_bubble_layout` off in Flagsmith. No code revert needed. diff --git a/.github/_auto_scoreboard.md b/.github/_auto_scoreboard.md index 1b33c3d..18c8fdf 100644 --- a/.github/_auto_scoreboard.md +++ b/.github/_auto_scoreboard.md @@ -1,29 +1,15 @@ -# Auto-iterator Scoreboard — 2026-04-23 +# Auto Scoreboard — 2026-04-23 -## Baseline -- Scenarios: 3/3 passed (100%) -- Traces searched: 146 traces over last 7 days +## Traces summary +200 traces from last 7 days, all healthy (no thumbs-down annotations, no errors). Scenarios 4/4 green. Operator focus: **design improvements to chat UI**. -## Evidence from traces & code inspection -- 40%+ of all traces include dietary restriction queries ("vegan gluten-free nut-free") — users must retype these every single message. -- Flag `auto_dietary_pref_chips` was created by a prior iterator run but **never implemented** in any code file. -- UI has zero dietary controls beyond a model-tier dropdown; empty state shows only a single static hint. -- No conversation-reset button, no copy-to-clipboard on assistant messages. -- Error state shows raw HTTP status with no retry button. +## Candidates -## Candidate Changes +| # | Title | Evidence | Impact | Risk | Score | +|---|---|---|---|---|---| +| 1 | **Chat bubble layout** — right-align user messages as warm-tinted rounded bubbles; left-align assistant messages as elevated cards | `chat.tsx` uses `ml-8`/`mr-8` indents — no directional alignment; messages look identical without tiny "You"/"Chef" label. Bubble layout is the single highest-impact visual improvement for a chat UI | High | Low | **1st** | +| 2 | Header + page polish — gradient, sticky input, subtle separator | Page header is bare `text-2xl` with no visual weight | Med | Low | 2nd | +| 3 | Implement `auto_starter_prompts` clickable chips (flag exists, no code yet) | Flagsmith flag registered, zero frontend implementation | Med | Med | 3rd | -| # | Title | Evidence | Impact | Risk | Rank (I/R) | -|---|-------|----------|--------|------|------------| -| 1 | **Dietary preference chips (toggle chips UI)** | 40%+ traces show repeated dietary constraint text; `auto_dietary_pref_chips` flag exists but unimplemented; high user friction typing same prefs each message | **High** | Low | ⭐ 1st | -| 2 | Clickable example prompts in empty state | Current empty state is a single static hint; users may not know what to ask; low discoverability | Med | Low | 2nd | -| 3 | Copy-to-clipboard button on assistant messages | Recipes are long markdown; copying to use elsewhere is a common action with no affordance | Med | Low | 3rd | - -## Decision -**Candidate 1 — Dietary preference chips** wins. - -Rationale: Clear trace evidence (typing "vegan gluten-free nut-free" in every message is high friction), an existing Flagsmith flag that was never wired up, and the operator hint "ui ui and more ui!" all align. The flag `auto_dietary_pref_chips` is used; default remains off so no live users are affected until a human enables it. - -Follow-ups (future runs): -- Candidate 2: clickable example prompts -- Candidate 3: copy-to-clipboard on assistant messages +## Selected: Candidate 1 — Chat bubble layout +Pure CSS/layout change, zero logic change — easiest non-regression to verify. diff --git a/api/main.py b/api/main.py index 1b43f4f..55a3cb4 100644 --- a/api/main.py +++ b/api/main.py @@ -65,6 +65,7 @@ def get_flags(): flags = load_flags() return { "dietary_pref_chips": flags.is_on("auto_dietary_pref_chips", default=False), + "chat_bubble_layout": flags.is_on("auto_chat_bubble_layout", default=False), } diff --git a/web/components/chat.tsx b/web/components/chat.tsx index d4b3fdf..26dcb28 100644 --- a/web/components/chat.tsx +++ b/web/components/chat.tsx @@ -23,13 +23,17 @@ export default function Chat() { const [slow, setSlow] = useState(false); const [error, setError] = useState(null); const [chipsEnabled, setChipsEnabled] = useState(false); + const [bubbleLayout, setBubbleLayout] = useState(false); const [activePrefs, setActivePrefs] = useState>(new Set()); const scrollRef = useRef(null); useEffect(() => { fetch(`${API_URL}/flags`) .then((r) => r.json()) - .then((data) => setChipsEnabled(!!data?.dietary_pref_chips)) + .then((data) => { + setChipsEnabled(!!data?.dietary_pref_chips); + setBubbleLayout(!!data?.chat_bubble_layout); + }) .catch(() => {}); }, []); @@ -134,22 +138,53 @@ export default function Chat() { Try: "A 30-minute weeknight pasta using what's usually in a pantry."

)} - {messages.map((m, i) => ( -
-
- {m.role === "user" ? "You" : "Chef"} + {messages.map((m, i) => + bubbleLayout ? ( +
+
+
+ {m.role === "user" ? "You" : "Chef"} +
+
+ {m.content} +
+
-
- {m.content} + ) : ( +
+
+ {m.role === "user" ? "You" : "Chef"} +
+
+ {m.content} +
-
- ))} + ), + )} {loading && (