Tags: mexicanamerican/CopilotKit
Tags
fix(showcase): narrow aimock fixture patterns + add drift guardrail (C… …opilotKit#4155) ## Summary Showcase demos (e.g. gen-ui-tool-based's "Traffic pie chart", Beautiful Chat's pie/bar-chart suggestions) were rendering nothing in prod because aimock's substring-match fixtures cross-fired across demos with different tool surfaces, returning tool names the target agent never registered. This PR narrows the fixture patterns to fix the immediate breakage and adds a static validator so the same class of drift fails CI before it reaches prod. ## What broke Aimock serves deterministic responses in prod for cost reasons. Fixtures substring-match the user message and return hardcoded tool calls. The `"pie chart"` pattern returned `query_data` (for Beautiful Chat's two-step flow where it has that tool), but the same substring also fires for gen-ui-tool-based's suggestions — which only registers `render_pie_chart`. The returned `query_data` call dangles, no UI renders. Beautiful Chat also looped on the same fixture: aimock has no conversation-turn awareness, so after `query_data` returned its tool result, the follow-up model call had the same user-message context and the fixture re-matched, emitting `query_data` again — infinite until LangGraph's iteration cap. Exposed by PR CopilotKit#4113 (showcase-ops) / the prod-mode migration cluster that started routing prod traffic through aimock. The fixtures themselves had been incrementally drifting for a while, but the routing change turned silent drift into user-visible breakage across many demos simultaneously. ## Fix #1 — narrow the fixture patterns `showcase/aimock/feature-parity.json`: - Replaced the generic `"pie chart"` / `"bar chart"` / `"show pie"` / `"show bar"` patterns with **6 per-suggestion specific-phrase matches**. gen-ui-tool-based and declarative-gen-ui get `render_pie_chart` / `render_bar_chart` directly; Beautiful Chat gets `pieChart` / `barChart` with real data (skipping the query_data loop). - Narrowed `"schedule"` + `"meeting"` into one match for Beautiful Chat's "30-minute meeting to learn about CopilotKit" → `scheduleTime`. - Narrowed `"flight"` / `"fly"` to `"flights from SFO to JFK"`. - Narrowed `"background"` to `"sunset-themed gradient"`. - Removed `"trip"`, `"sales"`, `"pipeline"`, `"todo"` — too generic, substring-false-firing across unrelated demos. Interrupt and A2UI demos with those prompts fall through to the real LLM proxy. ## Fix #2 — static drift guardrail New `showcase/scripts/validate-fixture-tool-surface.ts`: - Pure `validate()` function: for each fixture with tool-call responses, finds every demo whose suggestion prompt contains the fixture's match substring, then asserts the fixture's returned tool names are all registered by that demo's agent. - CLI walks `packages/*/` collecting: - suggestions from `page.tsx` + sibling `hooks/*.tsx` - frontend tools from `useComponent` / `useHumanInTheLoop` / `useFrontendTool` / `useRenderTool` / `useDefaultRenderTool` calls - backend tools via `api/copilotkit*/route.ts` → agentId→graphId map → `langgraph.json` graph→Python-file → `@tool` decorators + `tools=[...]` arrays - 7 vitest cases written TDD-first (watched fail, then implemented) covering: drift detection, content-only fixtures, no-matching-demo, case-insensitivity, multi-demo cross-check, multi-tool responses. Runs as `npx tsx showcase/scripts/validate-fixture-tool-surface.ts`. Exit 0 = clean; exit 1 = per-fixture drift report. Current state: **33 fixtures × 191 demos, no drift.** Counterfactual: reverting just the pie-chart fixture fix correctly flags `langgraph-python/gen-ui-tool-based` and `langgraph-python/declarative-gen-ui` — i.e. the exact demos that broke in prod. ## Also fixed — unrelated LangGraph Python Dockerfile bug `showcase/packages/langgraph-python/Dockerfile`: `WORKDIR /app` left `/app` owned by root; the explicit `--chown=app:app` on COPY lines chowned *contents* but not the directory itself, so the `app` user couldn't create `.langgraph_api` (the in-memory LangGraph runtime's cache dir) and the agent crashed on boot with `PermissionError: [Errno 13]`. Added a non-recursive `chown app:app /app` (preserves the perf intent of not doing a recursive chown). ## Known follow-ups (out of scope for this PR) - Interrupt demos (`gen-ui-interrupt`, `interrupt-headless`, `hitl-in-chat`) and A2UI demos (`declarative-gen-ui`, `a2ui-fixed-schema`, `mcp-apps`, Calculator App) currently fall through to the real LLM when unmatched. Faithful fakes would need per-agent fixture keying in the aimock engine — separate upstream change. - Python backend-tool parser uses regex; misses star-spread collections like `tools=[query_data, *todo_tools]`. Safe failure mode — missing tools surface as guardrail drift rather than silently pass. - Add this validator to `.github/workflows/showcase_*.yml` so CI runs it on every PR touching fixtures or demos. ## Test plan - [x] `npx vitest run showcase/scripts/__tests__/validate-fixture-tool-surface.test.ts` — 7/7 pass - [x] `npx vitest run showcase/scripts/__tests__/aimock-fixtures.test.ts` — 17/17 still pass (no regression) - [x] `npx tsx showcase/scripts/validate-fixture-tool-surface.ts` — 33 fixtures × 191 demos, 0 drift - [x] Counterfactual: revert fixture fix, validator flags gen-ui-tool-based + declarative-gen-ui exactly - [x] Direct aimock probe (localhost:4010) for all 8 fixed prompts → returns correct tool call - [x] End-to-end through local LangGraph agent (localhost:3100) → gen-ui-tool-based "Traffic pie chart" suggestion → `render_pie_chart` with real data - [ ] Merge → Railway redeploys aimock + langgraph-python → smoke cycle on Beautiful Chat + gen-ui-tool-based + declarative-gen-ui suggestions
PreviousNext