mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
blitz/angular-v21/integration
10887 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e1137bb2f7 | Merge branch 'main' into alem/fix-bucket-c-d5-probes-followup | ||
|
|
d1827973bd |
fix(showcase/langgraph-python): rename internal A2UI tool so middleware doesn't intercept (#4734)
## Summary Follow-up to #4733. The Sales Dashboard pill on Beautiful Chat and the KPI Dashboard pill on Declarative Gen UI were still failing on deploy with: - `A2UI render error: Catalog not found: declarative-gen-ui-catalog` (beautiful-chat) - `A2UI render error: Cannot create component root without a type` infinite loop (declarative-gen-ui) ### Root cause `@ag-ui/a2ui-middleware`'s default `a2uiToolNames = ["render_a2ui"]` makes the middleware **synthesise ACTIVITY_SNAPSHOT events from the streaming tool-call args of any matching call**, using the LLM's RAW `catalogId` + `components` before the Python tool body runs. Both `generate_a2ui` implementations bound a structured-output helper named `render_a2ui` to a secondary LLM — so the secondary LLM's hallucinated `catalogId` and malformed root components were getting emitted to the frontend through the bypass. The force-pin and defensive validation #4733 added were correct but ran on the tool-result; the middleware had already fired its synthetic events from the streaming args. ### Fix Rename the internal helper from `render_a2ui` to `_design_a2ui_surface` so it falls outside the middleware's intercept list. The outer `generate_a2ui`'s `a2ui.render(operations=...)` return is then the only path to the frontend, and the Python validation layer is authoritative again. Two files: `src/agents/beautiful_chat.py`, `src/agents/a2ui_dynamic.py`. No frontend / runtime / package changes. ## Test plan - [x] **Local — Beautiful Chat → Sales Dashboard pill**: renders dashboard surface (Total Revenue / New Customers / etc.) with no errors. Previously: `Catalog not found: declarative-gen-ui-catalog`. - [x] **Local — Beautiful Chat → Search Flights pill**: still renders FlightCards (regression check on the previous fix). - [ ] **Deploy — Beautiful Chat → Sales Dashboard pill**: confirm no `Catalog not found` error. - [ ] **Deploy — Declarative Gen UI → KPI Dashboard pill**: confirm no `Cannot create component root without a type` loop. |
||
|
|
c91a9c9aff |
fix(showcase/langgraph-python): A2UI fixed-schema loop + propagate rename to shared tools and aimock
Two follow-up fixes layered on the previous internal-tool rename: (1) `a2ui_fixed.py` — fixed-schema demo infinite loop on deploy. The `display_flight` tool returns the raw `a2ui.render(...)` JSON descriptor as its tool result. gpt-4o-mini reads that opaque blob, can't tell the flight was rendered, and re-calls `display_flight` indefinitely (visible on the deployed showcase as 6+ duplicate flight cards stacked under repeated assistant text). Local was just lucky. Hardened the docstring + system prompt to spell out: the JSON return value is the surface descriptor, the card is already rendered, do NOT call again, reply with one short confirmation and stop. (2) Rename `render_a2ui` → `_design_a2ui_surface` in shared and langgraph-python parity copies of `tools/generate_a2ui.py` (+ `tools/__init__.py` re-export `RENDER_A2UI_TOOL_SCHEMA` → `DESIGN_A2UI_SURFACE_TOOL_SCHEMA`), and in `showcase/shared/typescript/ tools/generate-a2ui.ts`. These shared helpers were the source-of-truth for the secondary-LLM tool name across integrations; renaming here keeps parity with the langgraph-python agents already renamed in `beautiful_chat.py` / `a2ui_dynamic.py`. Other framework integrations keep their own `render_a2ui` for now (separate parity sweep). (3) `showcase/aimock/feature-parity.json` — added a sibling fixture matching `toolName: "_design_a2ui_surface"` for the beautiful-chat Sales Dashboard pill so the langgraph-python e2e suite still hits a deterministic mock on Railway. The original `render_a2ui` fixture is kept above it so other integrations whose secondary LLM still requests `render_a2ui` continue to match. (4) Comment update in `beautiful-chat.spec.ts` to name the new internal tool. |
||
|
|
f8b2be774d |
chore: retarget "Talk to engineers" CTAs to /talk-to-an-engineer (#4735)
## Summary - Retargets the docs navbar and showcase shell-docs brand-nav "Talk to engineers" CTAs from `copilotkit.ai/contact-us` to `copilotkit.ai/talk-to-an-engineer`. - PostHog `talk_to_us_clicked` capture is unchanged — only the destination URL moves. ## Test plan - [ ] Click "Talk to engineers" in the docs navbar and confirm it lands on `/talk-to-an-engineer`. - [ ] Click "Talk to engineers" in the showcase shell-docs brand-nav and confirm the same destination. - [ ] Verify `talk_to_us_clicked` still fires in PostHog with `location: "docs_nav"`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
017e19455a |
chore: retarget "Talk to engineers" CTAs to /talk-to-an-engineer
Updates the docs navbar and showcase shell-docs brand-nav so the "Talk to engineers" CTA points at copilotkit.ai/talk-to-an-engineer instead of the deprecated /contact-us endpoint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5d3abc6680 |
fix(showcase/langgraph-python): rename internal A2UI tool so middleware doesn't intercept
The A2UI middleware (`@ag-ui/a2ui-middleware`) defaults `a2uiToolNames` to `["render_a2ui"]` and synthesises ACTIVITY_SNAPSHOT events from the streaming tool-call args of any matching call — using the LLM's RAW catalogId and components verbatim, before the Python tool body has a chance to validate or normalise. Both `beautiful_chat.py` and `a2ui_dynamic.py` use a `generate_a2ui` tool that internally invokes a secondary LLM bound to a structured-output `render_a2ui` helper. Because the helper's name matched the middleware's default intercept list, the secondary LLM's hallucinated catalogId (`declarative-gen-ui-catalog` leaking into the beautiful-chat dashboard) and malformed root components (no `component` field on KPI dashboard) were emitted to the frontend bypass, surfacing as: - "A2UI render error: Catalog not found: declarative-gen-ui-catalog" on the beautiful-chat Sales Dashboard pill - "A2UI render error: Cannot create component root without a type" infinite-loop on the declarative-gen-ui KPI Dashboard pill The earlier force-pin of `catalog_id` and the defensive component sweep in `generate_a2ui` were correct but ran too late — they execute on the tool-result, after the middleware has already fired surface events from the streaming args. Fix: rename the internal helper to `_design_a2ui_surface` (and update `tool_choice`, prompt header, and module docstring) so it falls outside the middleware's intercept list. The explicit `a2ui.render(...)` ops the outer `generate_a2ui` returns are then the only path to the frontend, and our Python validation layer is authoritative. Verified locally: Beautiful Chat → Sales Dashboard pill renders Total Revenue / New Customers / etc. with no errors. |
||
|
|
3b3908e353 |
fix(showcase/langgraph-python): restore A2UI rendering for beautiful-chat + declarative-gen-ui (#4733)
## Summary - Beautiful Chat **Search Flights** pill: restored `_build_flight_components` so the agent emits a flat literal-children FlightCard tree (the structural-children template form via `flight_schema.json` + `update_data_model` doesn't expand correctly through GenericBinder for our custom catalog — it was working until the recent flagship-cell pass swapped it back). FlightCards render again instead of falling through to the default tool card. - Beautiful Chat **Sales Dashboard** pill: hardened `generate_a2ui` so the secondary LLM gets explicit catalog-id + component-shape rules and the resulting `catalog_id` is force-pinned to the registered catalog. Kills the "Catalog not found: declarative-gen-ui-catalog" sibling-demo hallucination. - **Declarative Gen UI** (`a2ui_dynamic.py`): same `generate_a2ui` hardening, plus a defensive sweep that drops malformed components and bails clean when the LLM omits a typed root. Kills the "Cannot create component root without a type" infinite-loop renderer error reported on the KPI Dashboard pill. Two files touched (`src/agents/beautiful_chat.py`, `src/agents/a2ui_dynamic.py`); no frontend / runtime / package changes. Existing aimock fixtures in `feature-parity.json` already use the canonical catalogId and well-formed components, so e2e specs should pass without fixture changes. ## Test plan - [x] Verified locally: `langgraph_cli dev` + `next dev`, clicked **Search Flights** on `/demos/beautiful-chat` — Delta DL 405 ($329) and United UA 120 ($289) FlightCards rendered live with airline, route, times, status, Select. - [x] Verified locally: clicked **Show a KPI dashboard** on `/demos/declarative-gen-ui` — REVENUE / SIGNUPS / CHURN metric tree rendered cleanly, no "Cannot create component root without a type" error. - [ ] CI / `nx run @copilotkit/showcase-langgraph-python:e2e` (beautiful-chat spec already authored against the literal-children form). |
||
|
|
d1efb2bbc4 | style: auto-fix formatting | ||
|
|
462e200d45 |
fix(showcase/harness): assert on actual DOM signals, not unreleased testids
Six probe-side fixes landing five additional D5 flips on the
langgraph-python column. None of the fixes touch demo or runtime
code — just the harness-side selectors / signal predicates so each
probe matches what the published langgraph-python image actually
renders today.
Per-probe changes:
- d5-tool-rendering-default-catchall: add a fallback path that
scans copilot-assistant-message bubbles for the literal tool name
+ a 'done'/'running' status label, alongside the strict testid
contract added in unreleased commit
|
||
|
|
3ac103b3bf |
fix(showcase/langgraph-python): restore A2UI rendering for beautiful-chat + declarative-gen-ui
Three regressions, two files. Without these the Search Flights pill falls
through to the default tool card instead of rendering FlightCards, the
Sales Dashboard pill errors with "Catalog not found:
declarative-gen-ui-catalog", and the Declarative Gen UI cell loops on
"Cannot create component root without a type."
beautiful_chat.py — search_flights:
- Restore _build_flight_components and have search_flights emit the flat
literal-children component tree it produces, instead of the
flight_schema.json structural-children template (Row.children =
{ componentId, path: "/flights" }) plus update_data_model. The
GenericBinder doesn't reliably expand the structural form for our
custom FlightCard catalog — sibling demos avoid the form for the same
reason. The literal form has been the working shape since it was
introduced; the recent flagship-cell pass swapped it back to the
schema/data-model form and broke fixed-schema rendering.
- Make Flight TypedDict permissive (total=False) and drop the required
id / statusIcon fields. langchain rejected calls when the LLM (or
aimock fixture) omitted those, surfacing the validation string as the
tool result and never producing a surface.
beautiful_chat.py + a2ui_dynamic.py — generate_a2ui:
- Prepend a hard-requirements header to the secondary LLM's prompt
pinning the canonical catalogId and the component-shape contract
(every entry — including root — must carry both `id` AND `component`).
With injectA2UITool: false the runtime context alone leaves the LLM
enough room to hallucinate sibling-demo catalog IDs (e.g.
declarative-gen-ui-catalog leaking into the beautiful-chat dashboard)
and to omit `component` on the root entry (the source of the
"Cannot create component root without a type" infinite loop).
- Force catalog_id to the module-level CUSTOM_CATALOG_ID after the tool
call so any residual hallucination still routes to the registered
frontend catalog.
- Drop malformed component entries before constructing the operations
list, and bail with a clean error string if no valid root survives —
fail-soft instead of looping the renderer.
The renderer-side definitions.ts/renderers.tsx changes from the same
flagship pass are kept as-is; their Row/Column children union
(string-array OR { componentId, path }) is forward-compatible and
doesn't hurt the literal-children path.
|
||
|
|
4ce76d4576 |
fix(showcase/harness): drive gen-ui-headless-complete via textarea, not chip click
The demo has TWO chip surfaces with diverging aria-label shapes: EmptyState (first paint) emits aria-label='Try suggestion: <message>' with the visible text being the message string, while SuggestionBar (post-first-message) emits aria-label='Suggestion: <title>' with visible text being the short title. Which surface is mounted at any given turn depends on messages.length — timing-dependent. Both my prior selectors matched only one surface and timed out on the other. Drop the chip-click preFill entirely; let the runner's normal fillAndPress hit the textarea with the verbatim prompt. Chip clicks and textarea-Enter dispatch the same runAgent path, so the fixture matcher catches either route — and the textarea is always present. Also refresh e2e-deep.test.ts: a stale test assertion expected the old REGISTRY_TO_D5 mapping shape (tool-rendering-default-catchall → tool-rendering D5 type), but the Phase-2A split repointed it to its own D5 type of the same name. Update the expected skipped list and sideKeys to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
4541d3a7dd | Merge branch 'main' into claude/publish-agentcore-runner-NarcF | ||
|
|
1d8d1b0783 |
fix(showcase/aimock): disambiguate frontend-tools fixtures with toolCallId follow-ups
In replay mode (no real OpenAI), the existing frontend-tools fixtures match by 'userMessage' substring only. Each pill (Sunset / Forest / Cosmic) had a single fixture that returned both content + a change_background toolCall. After the frontend tool ran, the agent's follow-up LLM call still has the same last user message — substring matches the same fixture again — agent re-fires change_background, loops to langgraph's recursion limit, probe's settle window never quiets, run reds out at the assistant-settle timeout. Add a toolCallId-keyed follow-up per pill that returns content-only, plus a static tool_call_id on the first-turn toolCall for the follow- up to pin to. The follow-up combines userMessage + toolCallId so it can't cross-match the next pill's first-turn request (which still has a tool result in history from the prior pill, but a different last user message). Probe result: d5:langgraph-python/frontend-tools flips green again in replay mode — was passing in PR #4724 only because the real-LLM run that PR was tested against happened to settle without re-firing. |
||
|
|
c2bc645228 |
fix(showcase/aimock): drop redundant recorded fixtures, let canonical d5-all.json take precedence
Investigation of the remaining bucket-C D4 cells uncovered that the 'recorded' fixtures shipped in PR #4725 are at best redundant with hand-curated canonical fixtures already in d5-all.json, and at worst override them with worse data — the recordings collapsed beautiful-chat's canonical $349/$289 search_flights payload to the LLM-of-the-day's $319/$289 (probe asserts $349 verbatim) and reasoning-custom's canonical fixture (which carries a 'reasoning' field) with a content-only recording (refused chain-of-thought disclosure). Net D5 effect of removing the recordings: - d5:langgraph-python/gen-ui-custom (catalog gen-ui-tool-based) → green (canonical d5-all.json #39/#40) - d5:langgraph-python/reasoning-display (catalog reasoning-custom) → green (canonical d5-all.json #91 with 'reasoning' field that cleanly satisfies the probe's reasoning-role testid contract) Both flips confirmed live against PocketBase via --d5 --live. The aimock record/replay infrastructure introduced alongside these fixtures (showcase/docker-compose.{record,replay}.yml, showcase/scripts/record-d5-fixtures.mjs) stays — it is reusable for future demos where canonical fixtures don't yet cover the prompts — just without the misleading initial recordings. Bucket-C cells that remain at D4 after this change require fixes outside the fixture/recording scope; see the PR description for per-cell findings (release-blocked package testids, frontend-tool dispatch defect, suggestion-bar misrender, resume-from-interrupt UI, built-in reasoning-message testid). |
||
|
|
88b61cb3e4 | style: auto-fix formatting | ||
|
|
f8c711d2bb |
feat(showcase): aimock record/replay infra for deterministic D5 fixtures
Adds a record/replay loop on top of the existing local Docker stack so each langgraph-python D5 demo can capture real-LLM responses once and replay them deterministically thereafter. One fewer source of D5 flake per demo: no more 'tests pass with real OpenAI / fail with aimock' because the prompts have no fixture coverage. What lands here: - showcase/docker-compose.record.yml — overlays aimock with --record + --provider-openai/anthropic and a writable mount for the recording dir. Drops the baseline d5-all.json/feature-parity.json/smoke.json loads so prompts that already match a stale fixture can still proxy through to the real provider. - showcase/docker-compose.replay.yml — same writable mount, no --record, no provider URLs; layers the per-demo fixtures alongside the baseline ones for normal probe runs. - showcase/scripts/record-d5-fixtures.mjs — orchestrator. For each demo (catalog feature ID), drops any prior consolidated <slug>.json, restarts aimock to clear in-memory recorded fixtures, snapshots recorded/, runs the d5 probe through pnpm exec tsx, then merges every per-call file written under recorded/ into a single showcase/aimock/d5-recorded/<slug>.json (one fixture per LLM turn, in chronological order). - showcase/aimock/d5-recorded/<slug>.json × 6 — initial recordings for the still-red bucket-C cells: beautiful-chat (8), gen-ui-interrupt (2), gen-ui-tool-based (1), headless-complete (1), reasoning-custom (1), tool-rendering-default-catchall (2). 15 fixtures total. - showcase/aimock/d5-recorded/.gitignore — keeps the per-call recorded/ scratch dir out of the tree (orchestrator deletes per-call files after consolidation, this just guards against re-runs). D5 impact: replaying the recordings flips d5:langgraph-python/gen-ui-custom (catalog gen-ui-tool-based) from red to green deterministically. The other five demos still fail their UI or assertion-side checks, but their LLM-side responses are now fixed, so the remaining work is probe/UI fixes against a stable baseline rather than flake hunting. Aimock recorder requires a one-line patch (turnIndex + hasToolResult on each recorded fixture's match) for multi-turn flows to record correctly. Upstream fix proposed for @copilotkit/aimock; until it ships, the orchestrator probes for the patch and aborts loudly with the missing-fields message rather than silently producing single-turn fixtures. See the script's header comment for the exact patch payload. |
||
|
|
920e0bcc01 |
fix(showcase/langgraph-python): flip auth, frontend-tools, voice from D4 to D5 (#4724)
## Summary Three independent D5 fixes for the langgraph-python column. Together these flip 3 cells from D4 → D5 in the showcase dashboard. Production also has these same D4 cells, so the harness/showcase changes here apply to prod as well once merged. - **auth** — conversation runner now defers chat-input resolution until after the first turn's `preFill` runs, so idiomatic auth demos that mount the chat tree only after a sign-in click work end-to-end. - **frontend-tools** — D5 assertion accepts any chromatic-family hex via RGB-channel-dominance, not just the fixture-pinned substrings. Real OpenAI returned valid forest greens (`#005f00`, `#4caf50`) that the fixed substring list couldn't enumerate. - **voice** — disabled `<cpk-web-inspector>` on the voice demo. The dev-only inspector auto-mounts on any localhost host (including local Docker at `localhost:3100`) and intercepts pointer events on the voice sample-audio button. Production isn't localhost, so prod was unaffected — that's why prod was D5 and local was D4. Each commit is scoped to one fix with regression tests where applicable. ## Verification Verified locally against a fresh `aimock` + `pocketbase` + `dashboard` + `langgraph-python` stack with real `OPENAI_API_KEY`: | Cell | Before | After | |---|---|---| | `d5:langgraph-python/auth` | red | green | | `d5:langgraph-python/frontend-tools` | red | green | | `d5:langgraph-python/voice` | red | green | Harness tests added: - `conversation-runner.test.ts` — pins the post-fix invariant: cascade probe throws while the chat input is unmounted, `preFill` makes it visible, runner then resolves and proceeds. Without the fix the runner would resolve up-front and time out. - `d5-frontend-tools.test.ts` — two new tests: accepts arbitrary green hex via channel-dominance (real-LLM nondeterminism guard), and still rejects sunset-hex emitted under the forest pill (regression guard so the fallback can't degrade into "any color passes"). All 42 tests in the affected files pass; format and oxlint both clean on touched files. ## Test plan - [ ] CI green on the `langgraph-python` D5 cron (auth, frontend-tools, voice) - [ ] Production `dashboard.showcase.copilotkit.ai` shows 3 D4 → D5 transitions on the langgraph-python column after deploy - [ ] No regression on the rest of the langgraph-python column |
||
|
|
247f061456 |
fix(showcase/langgraph-python): disable inspector on voice demo for D5 parity
The voice demo's <CopilotKit> didn't pass enableInspector, so
shouldShowDevConsole(undefined) defaulted to isLocalhost(), which
auto-mounts <cpk-web-inspector> on any local Docker host
(localhost:3100 in showcase compose). The inspector overlay
intercepts pointer events on top of the voice sample-audio button,
so dev/D5 probe runs can't click it through Playwright.
Production isn't localhost, so the inspector never mounts there —
voice is D5 in prod and D4 locally for this reason alone. Set
enableInspector={false} explicitly so the demo behaves the same in
both environments.
Probe result: d5:langgraph-python/voice flips green.
|
||
|
|
2e27b8c7c2 |
fix(showcase/harness): accept arbitrary green hex via channel-dominance fallback
PILL_GRADIENT_HINTS pinned the fixture/aimock output deterministically with a fixed substring list (color words + the exact hex codes from the fixtures). Real OpenAI emits any chromatic-family hex (e.g. forest as '#005f00 / #4caf50') that the fixed substring list can't enumerate, so the assertion failed for valid green output. Add a channel-dominance fallback: parse all 6-digit hex codes from the gradient and accept when at least one satisfies the per-pill RGB rule (g > r && g > b for forest, r > g && r > b for sunset, b > g or purple-channel for cosmic). MIN_DOMINANCE_DELTA + MIN_DOMINANT_VALUE prevent near-grey or near-black hexes from cross-matching. Word and fixture-hex match still runs first; channel-dominance is the fallback only. Probe result: d5:langgraph-python/frontend-tools flips green. |
||
|
|
8b095e1340 |
fix(showcase/harness): defer chat-input cascade until after preFill
Idiomatic auth demos (langgraph-python) render a SignInCard until the user clicks 'Sign in with demo token' — the chat textarea only mounts after that click, which preFill performs. The conversation runner was resolving the chat-input cascade up front, before any turn-level preFill ran, so the cascade timed out at 5s on SignInCard and turn 1 failed with 'chat input not found'. Move resolution and the initial assistant-message baseline into the per-turn loop, lazy on first turn. Subsequent turns reuse the cached selector. Probe result: d5:langgraph-python/auth flips green. |
||
|
|
f5987af1fd |
chore(showcase): snippet sweep pre-cutover (region markers + state-streaming unsupported flips) (#4717)
## Summary Closes the remaining yellow-box snippet gaps in shell-docs ahead of the Tue 5/12 cutover. Replaces 5 individual one-PR-per-framework attempts with a single consolidated PR. ## What's in here **Region marker additions** (5 commits, comment-only changes — zero runtime impact): - `claude-sdk-typescript` `gen-ui-interrupt::backend-tool-call` — sibling teaching file (no per-demo backend in claude-sdk-ts; mirrors claude-sdk-python's Strategy B SYSTEM_PROMPT shape) - `langroid` `gen-ui-interrupt::backend-tool-call` — in-place around the existing `ScheduleMeetingTool` `ToolMessage` subclass (preserves langroid's idiom — no forced LangGraph shape) - `pydantic-ai` `gen-ui-tool-based::bar-chart-renderer` — sibling teaching file (production demo is haiku-generator via `useFrontendTool`, not a `useComponent` bar-chart) - `spring-ai` `shared-state-streaming` (2 regions: `frontend-use-coagent-state` + `state-streaming-middleware`) — in-place; backend Java file already in `manifest.yaml` `highlight:` - `strands` `gen-ui-interrupt::backend-tool-call` — in-place around the canonical `@tool def schedule_meeting` All follow the [Mastra Round playbook](https://www.notion.so/34f3aa38185281c0b41dc6b6c63c89c6) for in-place vs sibling decisions. **Catalog flips** (2 commits, manifest-only): - 11 non-LangGraph frameworks: move `shared-state-streaming` from `features` to `not_supported_features` (ag2, agno, claude-sdk-{python,typescript}, crewai-crews, langroid, llamaindex, mastra, ms-agent-{dotnet,python}, pydantic-ai) - 6 more without working demos: built-in-agent, google-adk, strands, langgraph-typescript, langgraph-fastapi, spring-ai - Per team's call 2026-05-07: state-streaming only works on LangGraph variants currently. Anything without a working demo gets the blue `UnsupportedBox` instead of yellow `Missing snippet` warnings. Engineering can flip these back to `features` once impls land. Final catalog state for `shared-state-streaming`: 17 unsupported, 1 wired (`langgraph-python` — canonical reference). ## Why now This PR is cutover-blocking. Sam's bar for Tuesday: zero yellow boxes anywhere in shell-docs. The current state had 33+ yellow boxes from the post-2026-04-29 audit refresh; this PR drives that to zero (in conjunction with the previously-merged PDX-122 fix in #4685). ## Verification - `npx tsx showcase/scripts/bundle-demo-content.ts` — all newly-marked regions resolve in `demo-content.json` - `npx tsx showcase/scripts/generate-registry.ts` — catalog regenerates clean with the manifest changes - Generated `catalog.json` files are gitignored artifacts; not in this diff ## Test plan - [ ] Build shell-docs locally: `cd showcase/shell-docs && npm run build` clean - [ ] Visit a few `shared-state/streaming.mdx` pages on framework variants — should render the blue "Not supported on X" box for the 17 unsupported frameworks - [ ] Visit `langgraph-python/shared-state/streaming.mdx` — should still render the working snippets - [ ] Visit the 4 fixed B-cell pages (claude-sdk-typescript/langroid/strands `human-in-the-loop/useInterrupt.mdx`, pydantic-ai `generative-ui/tool-based.mdx`, spring-ai `shared-state/streaming.mdx`) — all snippets resolve, no yellow boxes |
||
|
|
afcc7e4880 |
feat(shell-docs): add sitemap, robots, and per-framework self-canonical metadata (#4703)
## Summary
Phase 3 of the docs.copilotkit.ai cutover. Surfaces a complete sitemap,
basic robots config, and per-framework self-canonical metadata so every
URL variant is indexed under its own canonical instead of collapsing
onto a single root.
- **sitemap.ts** — emits one entry per (root URL × framework variant)
pair plus reference, AG-UI, and per-framework override pages.
`lastModified` resolves from MDX frontmatter \`lastmod\` first, then
file mtime, then \`new Date()\`. Strips Next.js route-group \`(name)\`
segments and trailing \`/index\` so URLs match what the routers actually
serve. ~2,250 entries.
- **robots.ts** — allow all, disallow \`/api/\`, sitemap pointer at
\`\${NEXT_PUBLIC_BASE_URL}/sitemap.xml\`.
- **sitemap-helpers.ts** — shared MDX walking + base-URL resolution.
- **generateMetadata()** added to the four catch-all docs routes
(\`[[...slug]]\`, \`[framework]/[[...slug]]\`, \`reference/[...slug]\`,
\`ag-ui/[[...slug]]\`). Each sets \`alternates.canonical\` to the page's
own full URL — per-framework self-canonical, not root canonical. So
\`/langgraph-python/quickstart\` declares itself canonical,
\`/agno/quickstart\` declares itself canonical, and the bare
\`/quickstart\` declares itself canonical too.
- **.env.example** — documents \`NEXT_PUBLIC_BASE_URL\` and
\`NEXT_PUBLIC_SHELL_URL\`. Extended the existing comment in
\`next.config.ts\` with the new consumers.
## Test plan
- [x] \`npm run build\` from \`showcase/shell-docs/\` passes; route
table shows \`/sitemap.xml\` and \`/robots.txt\` as static.
- [x] \`curl http://localhost:3099/sitemap.xml\` returns valid XML;
2,254 \`<url>\` entries covering bare unscoped, framework-scoped,
reference, and AG-UI URLs; no \`(other)\` route-group leakage; no
trailing \`/index\` artifacts.
- [x] \`curl http://localhost:3099/robots.txt\` returns the expected
User-Agent / Allow / Disallow / Sitemap config.
- [x] \`/shared-state\` HTML contains \`<link rel="canonical"
href=".../shared-state">\`.
- [x] \`/langgraph-python/quickstart\` HTML contains \`<link
rel="canonical" href=".../langgraph-python/quickstart">\` (NOT pointing
at the bare \`/quickstart\`).
- [x] \`/agno/quickstart\` and \`/reference/components/CopilotChat\` and
\`/ag-ui/concepts/architecture\` all self-canonical.
|
||
|
|
a6a74c513d |
chore(reference): handle langgraph_agent → langgraph_agui_agent rename (#4701)
## Summary - Updates the V1 reference autogen entry in `scripts/docs/lib/files.ts` for the upstream rename of `sdk-python/copilotkit/langgraph_agent.py` to `langgraph_agui_agent.py`. The class also renamed from `LangGraphAgent` to `LangGraphAGUIAgent` (now subclasses the upstream `LangGraphAgent`). - Updates `sourcePath`, `destinationPath` (now `LangGraphAGUIAgent.mdx`), `title`, `description`, and `pythonSymbols` to match. - Regenerates `showcase/shell-docs/src/content/reference/sdk/python/LangGraphAGUIAgent.mdx`. The autogen run now reports 26/26 entries succeeding (was 25/26 — the previous entry failed silently via `Promise.allSettled` because the source file no longer existed). Stacked on top of #4693 (autogen-retarget). Once that lands this PR can be retargeted at `main`. ## Test plan - [x] `tsx scripts/docs/gen.ts` from repo root succeeds with `All reference docs processed (26/26 succeeded)`. - [x] `npm run build` in `showcase/shell-docs/` clean (Next build prerendered 27/27 routes). - [ ] Spot-check rendered `/reference/sdk/python/LangGraphAGUIAgent` on a dev server. Note: the new `LangGraphAGUIAgent` class in `sdk-python` does not yet carry a class-level docstring, so the generated MDX is currently frontmatter-only. Adding a docstring upstream will populate the page on the next pipeline run. |
||
|
|
d35e114e93 |
feat(reference): retarget V1 reference autogen pipeline to shell-docs (#4693)
## Summary
Two commits porting the V1 reference autogen pipeline so it writes into
shell-docs instead of the legacy upstream tree. Without this,
`/reference/v1/*` URLs (around 20k pageviews per quarter on
`docs.copilotkit.ai`) would 404 or 301 to a stub on shell-docs after the
cutover.
- `c30613c8d` Retarget the autogen pipeline. `scripts/docs/gen.ts` is
the entrypoint; `scripts/docs/lib/files.ts` carries the `REFERENCE_DOCS`
array with hardcoded `destinationPath` strings. Switched all
destinationPath strings from `docs/content/docs/reference/v1/...` to
`showcase/shell-docs/src/content/reference/v1/...`. Routing was verified
via `src/app/reference/[...slug]/page.tsx` (which reads from
`src/content/reference/`, not the legacy `content/docs/reference/`
tree). Anchored cwd to repo root in `gen.ts` to fix a latent
path-resolution bug that had broken the pipeline upstream too. Switched
the orchestration to `Promise.allSettled` so one source-rename rot
doesn't abort the rest.
- `55e72eeec` Lefthook auto-format pass.
## What this generates
25 of 26 V1 reference docs land in
`showcase/shell-docs/src/content/reference/v1/`:
- 20 under `reference/v1/{components,hooks,classes}` (TypeScript-source
autogen)
- 5 under `reference/v1/sdk/python/` (Python-source autogen)
The 26th entry (`sdk-python/copilotkit/langgraph_agent.py` to
`langgraph_agui_agent.py` rename) is tracked separately as a follow-up.
## Test plan
- [ ] `npm run build` from `showcase/shell-docs/` clean.
- [ ] Visit `/reference/v1/hooks/useCopilotAction`,
`/reference/v1/classes/CopilotRuntime`,
`/reference/v1/components/chat/CopilotChat`,
`/reference/v1/sdk/python/LangGraph` on the dev server. Confirm full
content renders.
- [ ] Re-run `tsx scripts/docs/gen.ts` on a clean checkout. Confirm
25/26 entries succeed; the LangGraph SDK Python entry fails gracefully
without aborting the rest.
## Timing note
Merging this pre-cutover means upstream's
`docs/content/docs/reference/v1/*` MDX files freeze at their current
state. If anyone re-runs autogen between now and 5/12 the regenerated
MDX goes to shell-docs only. V1 surface is stable so the practical risk
is small, but the safest move is to hold this PR until cutover day. Open
question for review.
|
||
|
|
e69cdd660d |
chore(README): Update video asset the the "What is CopilotKit" section (#4698)
Updated AG-UI Protocol link and asset URL in README. <!-- Thank you for sending the PR! We appreciate you spending the time to work on these changes. Help us understand your motivation by explaining why you decided to make this change. **Please PLEASE reach out to us first before starting any significant work on new or existing features.** By the time you've gotten here, you're looking at creating a pull request so hopefully we're not too late. We love community contributions! That said, we want to make sure we're all on the same page before you start. Investing a lot of time and effort just to find out it doesn't align with the upstream project feels awful, and we don't want that to happen. It also helps to make sure the work you're planning isn't already in progress. As described in our contributing guide, please file an issue first: https://github.com/ag-ui-protocol/ag-ui/issues Or, reach out to us on Discord: https://discord.com/invite/6dffbvGU3D You can learn more about contributing to copilotkit here: https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md Happy contributing! --> ## What does this PR do? (Describe the changes introduced in this PR) ## Related PRs and Issues - (Direct link to related PR or issue, if relevant) ## Checklist - [ ] I have read the [Contribution Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md) - [ ] If the PR changes or adds functionality, I have updated the relevant documentation - [ ] "Allow edits by maintainers" is checked (lets us help iterate on your PR directly — faster turnaround for everyone) |
||
|
|
7155da28df |
fix(showcase): realign D5 probes/fixtures with idiomatic langgraph-python demos (#4723)
## Summary Five targeted fixes for the post-merge red rows on langgraph-python's D5 column, all driven from PB error-class diagnostics on the cycles after #4718 + #4722. Each is independently load-bearing. - **chat-css**: probe selector now matches v2's PREFIXED utility classes (`cpk:bg-muted`) instead of bare `bg-muted`. - **gen-ui-agent**: probe rewritten for the `last-write-wins` reducer model — drop the cross-pill baseline assumption, assert ≥ 2 visible rows + content fingerprint dedup. - **gen-ui-headless-complete**: chip click via stable `aria-label` attribute, not text-content chained selector. - **shared-state-streaming**: fixture argument key was `content`, but `write_document(document: str)` tool expects `document` — renamed in both per-feature fixture and `d5-all.json`. - **reasoning-display**: fixture now emits a `reasoning` field so aimock fires REASONING_MESSAGE_* events; probe's `[data-testid="reasoning-block"]` mounts only when a reasoning-role message lands. The remaining 6 reds (auth, frontend-tools, gen-ui-open*, agent-config, beautiful-chat-toggle-theme, beautiful-chat-search-flights, gen-ui-declarative, tool-rendering-{default,custom}-catchall, gen-ui-interrupt) need either runtime debugging or more investigation; they're tracked separately. ## Test plan - [ ] Land + watch the next e2e-deep cycle in PB - [ ] Confirm chat-css, gen-ui-agent, gen-ui-headless-complete, shared-state-streaming, reasoning-display all flip green - [ ] No regression on previously-green features 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
e60332bf02 |
fix(showcase): realign D5 probes/fixtures with idiomatic langgraph-python demos
After PR #4718 + the timeout bump in #4722 unblocked the abort-cascade, post-merge cycles surfaced the real per-probe failures that were previously hidden. Each fix here is targeted at one real failure mode identified from PB error class + message: * chat-css: HALCYON probe selector was `[class~="bg-muted"]`, but v2 emits PREFIXED utilities (`cpk:bg-muted`). Whole-token match on the prefixed name (`[class~="cpk:bg-muted"]`) fixes both the static USER_BUBBLE_INNER_SELECTOR and the page.evaluate selector — and is unambiguous against `cpk:bg-muted-foreground` on nested children. * gen-ui-agent: probe assumed `agent-step` DOM rows accumulated across pills (delta ≥ 2 vs. pre-pill baseline). The backend's `set_steps` reducer is `last-write-wins` (per `gen_ui_agent.py`), so each pill REPLACES `state.steps` and the DOM swaps. delta was always 0 after pill 1, even when the new steps rendered correctly. Drop the baseline-capture preFill, assert ≥ 2 visible rows + per-pill fingerprint dedup. Tests rewritten to match the swap model. * gen-ui-headless-complete: chip click used `button >> text="<title>"` (Playwright chained selector). The button has a stable `aria-label="Suggestion: ${title}"` attribute set inline; switch to `button[aria-label="Suggestion: ${title}"]` so we match the moment the DOM exists rather than waiting for inner text-node hydration. * shared-state-streaming: fixture sent `{"content": "..."}` but the langgraph-python `write_document(document: str)` tool expects `document`. Mismatch meant `state.document` never updated; probe saw no content delta. Rename the argument key to `document` in both the per-feature fixture and `d5-all.json` (the runtime fixture). The middleware's `tool_argument="document"` config requires this name. * reasoning-display: fixture only emitted `content` (text response). Probe asserted the v2 `<ReasoningBlock>` (rendered behind `[data-testid="reasoning-block"]`), which mounts only when a reasoning-role message lands in the transcript. Add a `reasoning` field so aimock emits REASONING_MESSAGE_* events. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
90dba50dee |
fix(showcase/harness): raise e2e-deep outer timeout 3min → 10min (#4722)
## Summary - PR #4718 took langgraph-python's D5 feature set to ~28; with FEATURE_CONCURRENCY=2 that's ~210s wall-clock, blowing the prior 3-min outer cap. - Post-merge run confirmed: 17 features flipped green, ~10 hit `errorClass: "abort"` (cascade where the global cap fires before the per-feature loop reaches them). - Bump outer cap to 10 min. Per-feature 5-min cap still bounds wedged features. Lighter integrations exit early so cycle wall-clock barely changes. ## Test plan - [ ] Land + watch the next e2e-deep cycle in PB - [ ] Verify the 10 abort-cascade features (auth, agent-config, voice, multimodal, gen-ui-open, gen-ui-open-advanced, beautiful-chat-pie-chart/bar-chart/search-flights/schedule-meeting) flip from `errorClass: "abort"` to either green or a real `errorClass` - [ ] Confirm other integrations' cycle wall-clock stays unchanged 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
66662d4a88 |
fix(showcase/harness): raise e2e-deep outer timeout 3min → 10min
PR #4718 added the LGP D5 coverage wave, taking langgraph-python's declared D5 feature set to ~28. With FEATURE_CONCURRENCY=2 that's 14 features per worker × ~15s realistic wall-clock = ~210s — over the prior 3-min cap before any slack. Post-merge cycles confirmed the math: 17 langgraph-python features ran cleanly and flipped green, but the remaining ~10 hit `errorClass: "abort"` with `errorDesc: "aborted"`, the abort-cascade signature where the global cap fires before the per-feature loop reaches them. Per-feature timeout (5min) bounds wedged features but doesn't bound the slug's total feature count against the outer cap. Bump to 10 min — gives ~5x headroom at current feature count. Lighter integrations (5–10 features, ~60s) still exit early without sitting on the cap, so cycle wall-clock barely changes (cron stays every 15 min, concurrency=4 hides the slow integration's tail behind the others). Revisit `FEATURE_CONCURRENCY` before raising further — Chromium context count scales with it and the Railway pod's 2.4GB headroom budget assumes the current value. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
11ca7414c1 |
fix(showcase): get langgraph-python D5 cells unblocked (#4718)
## What does this PR do?
Realigns the langgraph-python showcase cells with the recent idiomatic
demo refactors so D5 (e2e-deep multi-turn conversation) probes start
landing green again. Production PocketBase showed 28 of 42 D5 rows
red for langgraph-python before this work; the failure mix was a
combination of dashboard mapping drift, runner-level cascade aborts,
post-refactor selector mismatches, and a few independent fixture or
demo-handler regressions.
The diagnosis and phased plan live in the conversation transcript;
this PR is the implementation. Each phase is its own commit so the
sequence reads top-to-bottom in `git log`.
### Phase 0 — dashboard ↔ harness mapping drift
- `shell-dashboard/src/lib/live-status.ts` `CATALOG_TO_D5_KEY` had three
orphan entries (`hitl→hitl-steps`, `interrupt-headless`, and
`tool-rendering-reasoning-chain`) reading PB rows the harness no
longer emits, plus seven missing entries (e.g. `byoc-json-render`,
`hitl-in-chat-booking`, `open-gen-ui-advanced`,
`tool-rendering-default-catchall`, etc.) that left their cells
stranded at D4 even when the harness wrote green.
- Aligned the dashboard map exactly to harness `REGISTRY_TO_D5` and
added a drift test in
`harness/src/probes/helpers/d5-mapping-drift.test.ts`
asserting structural equality going forward (parses dashboard
source via fs — no cross-package import, since shell-dashboard
intentionally lives outside the pnpm workspace).
### Phase 1 — e2e-deep driver robustness
- Added `isClosed`, `route`, `unroute` to the wrapped `E2eDeepPage`
(optional in the interface so test fakes don't have to track them).
Unblocks `d5-readonly-state-context` which needed `page.route()`.
- `captureDiagnostics` short-circuits when the page is already closed.
- Raised `DEFAULT_TIMEOUT_MS` from 5min to 30min and added a 5-min
per-feature wall-clock race. ~30 features × ~45s avg /
FEATURE_CONCURRENCY=2 was tripping the global limit and aborting
every still-pending feature with fc=1 — that cascade is the bulk of
the recent reds. The per-feature timeout prevents a single wedged
feature from monopolizing the new larger global budget.
### Phase 2 — beautiful-chat toggleTheme cascade root
- `_beautiful-chat-shared.ts:assertToggleTheme` switched from a 200ms
manual `page.evaluate` poll over 30s to Playwright's
`waitForFunction`. The native polling is event-driven inside the
browser context, disconnects cleanly on page-close, and produces a
named diagnostic when the renderer crashes mid-poll. fc=97 historical.
- Demo-side: dropped `[theme, setTheme]` from the `useFrontendTool`
deps array on `toggleTheme`. The handler reads `document` directly
and `setTheme` is stable, so the deps forced a hook re-registration
on every flip — racing with in-flight tool results.
### Phase 3 — probe selector realignment per refactor
- **3A `d5-chat-css`**: HALCYON theme replaced the legacy hot-pink/amber
bubbles. Probe now checks user-bubble inner element's
`border-left-color`
for `rgb(196, 74, 31)` (halcyon-ember), font-family for "JetBrains
Mono",
and assistant bubble font-family for "Fraunces" — three independent
signals each with a specific error.
- **3B `d5-chat-slots`**: Added `data-slot-label={label}` to
`SlotMarker`'s
outer span (idiomatic data attribute, not a testid restoration);
probe asserts `[data-slot-label="MessageView.AssistantMessage"]`.
- **3C `gen-ui-headless` → `headless-simple` (slug rename)**: The
refactor stripped gen-UI capability from headless-simple — it's now
a "two hooks, one shadcn shell" text-only template. Renamed the D5
literal so the slug describes what's tested, removed the old probe
+ fixture + tests, added a lightweight chip-click + assistant-bubble
probe. `headless-complete` keeps its existing literal because it
still drives the full gen-UI surface.
- **3D `d5-gen-ui-headless-complete`**: Rewrote for the new 4-chip
set (Weather / Stock price / Highlight a note / Revenue chart). Per-turn
asserts the matching tool-card testid plus a distinguishing text
fragment. Dropped the missing `[data-testid="headless-suggestions"]`
wrapper selector and the old Excalidraw + continent turns.
- Restored `data-message-role` on both headless demos' UserBubble +
AssistantBubble (the runner cascade documents this as the headless
contract; refactor dropped it).
### Phase 4 — auth lifecycle rework
- New demo unmounts `<CopilotKit>` on sign-out, so the old
401-error-banner surface no longer applies.
- `d5-auth.ts` now: `preFill` clicks the SignInCard's sign-in button to
mount the chat, runner sends one turn, assertion clicks sign-out and
waits for SignInCard re-mount (unmount IS the assertion). Dropped
the brittle 500ms `setTimeout` and the chat-send-and-401 dance.
- `tests/e2e/auth.spec.ts` rewritten: 5 specs covering load, sign-in,
authenticated send, sign-out unmount, sign-in-again.
### Phase 5 — independent fixture/probe regressions
- **5A** `d5-frontend-tools.ts`: PILL_GRADIENT_HINTS now include the
literal 6-digit hex codes from each fixture (`#ff7e5f`, `#0a3d2e`,
`#1e3a8a`, etc.) so the keyword check matches the deterministic
hex-only gradient strings.
- **5C** `gen-ui-agent.json` + **5D** `shared-state-streaming.json`:
Stringified `arguments` to OpenAI wire shape (was a raw object) and
added explicit tool-call `id` fields, matching the dominant fixture
convention.
- **5E** Lifted `clickByJs(page, selector)` from `d5-auth.ts` into
`_genuine-shared.ts`; `d5-gen-ui-interrupt` now uses it to bypass
the `<cpk-web-inspector>` overlay that intercepts pointer events
before React's synthetic event system.
- **5F** Added the `get_stock_price` fixture pair (call + narration)
to `tool-rendering.json` for the `current price of AAPL` prompt.
The custom-catchall probe now mounts both WeatherCard + StockCard.
### Slug alignment notes
- `gen-ui-headless` → `headless-simple` is the only D5 literal renamed.
Rationale lives in the lock-step comment in `d5-registry.ts`.
- The dashboard's `agentic-chat-reasoning`, `interrupt-headless`, and
`tool-rendering-reasoning-chain` mappings were dropped (their D5
scripts were removed in genuine-pass Phase 0). Cells using those
registry IDs now correctly cap at D4 (no mapping = at-ceiling green).
### Known follow-up (NOT in this PR)
- `d5-reasoning-display` stays red. The probe correctly asserts the
demo's reasoning slot renders, but aimock's fixture format only
supports `content` / `toolCalls` — there's no way to emit
`REASONING_MESSAGE_*` events from a fixture. The aimock provider
source isn't in this repo; needs a separate change there.
## Related PRs and Issues
- Builds on the genuine-pass series: #4707
(`test(showcase/langgraph-python): genuine D5 + Layer-1 e2e pass`).
- Builds on the demo refactor commits
|
||
|
|
a5050dbe26 |
fix(showcase): retarget R15/R17 in legacy shell + harness copies
The shell-docs port (
|
||
|
|
f0d83ef0b5 | Merge branch 'main' into tyler/beautiful-haslett-a95038 | ||
|
|
dad0735baf |
feat(shell-docs): port redirect middleware + retarget destinations to shell-docs slugs (#4702)
## Summary
Two-part redirect work for the docs.copilotkit.ai → shell-docs cutover,
in one PR.
### Part 1 — Retarget destinations in `seo-redirects.ts`
shell-docs serves canonical framework docs at `/{fw-slug}/...` from the
host root (no `/docs/` prefix) and uses different framework slugs from
the legacy SHELL surface. The redirect catalogue has been retargeted
accordingly:
- **Drop the `/docs/integrations/` prefix** from every destination.
- **Apply framework-slug renames** in destinations:
- `langgraph` → `langgraph-python`
- `adk` → `google-adk`
- `aws-strands` → `strands`
- `microsoft-agent-framework` → `ms-agent-dotnet`
- `crewai-flows` → `crewai-crews`
- **Re-flip the BIA → unselected rename** — `unselected/` was retired;
destinations now point at `/built-in-agent/`.
- **Slug-rename catch-alls** for the bare `/{old-slug}/*` form so legacy
upstream URLs (e.g. `/langgraph/quickstart`) 301 directly to the new
slug.
- **`/docs/integrations/*` and `/docs/*` catch-alls** so any URL still
carrying the legacy SHELL routing prefix lands at the shell-docs
equivalent.
- **`/migration-guides/*` → `/migrate/*`** (4 URLs).
- **Folder-index redirects** for shell-docs folders without an
`index.mdx` (`/troubleshooting`, `/migrate`, `/premium`, `/concepts`,
`/reference`).
390 redirect entries total in the new catalogue.
### Part 2 — Port middleware to shell-docs
- Copied the retargeted `seo-redirects.ts` to
`showcase/shell-docs/src/lib/`.
- Merged the SHELL redirect-middleware logic into shell-docs's existing
pageview-tracking middleware. Redirects fire first (with the
`seo_redirect` PostHog event); non-redirected requests still get the
`docs_pageview` capture and `distinct_id` cookie.
- Preserved the framework-scoped short-circuit so canonical
`/{fw-slug}/...` URLs are never hijacked by legacy patterns.
- Left the SHELL versions of `middleware.ts` and `seo-redirects.ts` in
place — the SHELL still serves `docs.showcase.copilotkit.ai` until DNS
flips.
## Test plan
- [x] `npm run build` clean in `showcase/shell-docs/`
- [x] `npm run build` clean in `showcase/shell/` (existing operation
unaffected)
- [x] `curl -sI
http://localhost:3099/docs/integrations/langgraph/quickstart` → 301 to
`/langgraph-python/quickstart`
- [x] `curl -sI http://localhost:3099/langgraph/quickstart` → 301 to
`/langgraph-python/quickstart`; `/aws-strands/quickstart` →
`/strands/quickstart`; `/migration-guides/v2` → `/migrate/v2`;
`/troubleshooting` → `/troubleshooting/common-issues`; `/coagents` →
`/langgraph-python`
- [ ] Validate full set against a running shell-docs instance with
`validate-redirects.ts` (run from `showcase/scripts/` against the
deployed preview)
|
||
|
|
d53deb7e45 | style: auto-fix formatting | ||
|
|
691ad27ff2 |
fix(showcase/harness): correct d5-auth idiomatic re-mount test assertion
Test name says "succeeds when SignInCard re-mounts after sign-out" with signInCardRemounts: true, so the assertion should resolve, not reject. The .rejects.toThrow(/SignInCard.*did not re-mount/) was a stale leftover from when the older single-shape probe always failed this scenario; the multi-shape probe added in d8d32fd38 succeeds on this fixture, but the test wasn't updated in lock-step. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
a7d148f487 |
fix(showcase/aimock): stringify set_steps + write_document args in d5-all.json
Per-feature fixtures (gen-ui-agent.json, shared-state-streaming.json) were updated to JSON-stringified arguments + explicit tool-call IDs to match the OpenAI wire shape, but d5-all.json — the runtime fixture mounted by aimock per its Dockerfile — still had raw-object arguments without IDs. The wire-shape parity claim was true for the per-feature files but contradicted by the live fixture; aligning d5-all.json closes that drift so what we tested matches what runs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
197c588c32 |
fix(showcase/langgraph-python): auth e2e spec uses v2 testid not v1 data-message-role
CR Round 3 final: my auth.spec.ts e2e was asserting on [data-message-role="assistant"] which is the v1 react-ui RenderMessage attribute. The auth demo uses v2 CopilotChat — its CopilotChatAssistantMessage only emits data-testid="copilot-assistant-message". The selector would never have matched and both tests would have timed out at 30s when actually run. Verified via grep: - packages/react-core/src/v2/components/chat/CopilotChatAssistantMessage.tsx:192 emits data-testid="copilot-assistant-message" (no data-message-role) - packages/react-ui/src/components/chat/messages/RenderMessage.tsx:32,41 emits data-message-role="user"/"assistant" (v1 path) - All sibling specs in langgraph-python/tests/e2e/ correctly use data-testid="copilot-assistant-message" One-character switch from data-message-role to data-testid with the canonical v2 testid value. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
9560c9d539 |
fix(showcase/harness): d5-auth legacy fallback honors caller's signOutTimeoutMs
CR Round 2 (CR1): the legacy-shape assertion path stacked hardcoded sub-timeouts (idiomatic Math.min(3000, timeout) + 3000ms banner-flip + 500ms sleep + 2000ms fill + 2000ms press + Math.max(2000, timeout-3000) error-poll) — total worst-case ~15.5s when the caller asked for the default 8s. The doc-comment claimed "the total wall-clock budget remains `timeout`" — false. Replaced the hardcoded sub-timeouts with a single deadline computed at function entry (`Date.now() + timeout`) and a helper `remainingMs()` that bounds every subsequent wait. The assertion now genuinely respects the caller's budget. Also bounded the idiomatic-detection inner waitForSelector to `min(200, idiomaticDeadline - now())` so a 100ms-deadline test can't be overshot by a 200ms inner timeout. Test changes: - "fails when legacy banner flips but error surface never appears" now passes signOutTimeoutMs: 4_000 — the prior 200ms test relied on the buggy stacked-sub-timeouts to reach the legacy path. With the budget actually honored, idiomatic-detection consumes a tight budget before legacy can run; that's correct, fail-fast behavior. - New test "fails fast with 'idiomatic detection consumed the budget' when caller passes a tight timeout" pins the new fast-fail behavior so future regressions on this contract are caught. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
80a998d59a |
fix(showcase): CR Round 1 — resolve precedence + probe robustness
Bucket (a) findings from CR Round 1, fixed inline:
A1. shell-dashboard resolveD5Row precedence
Multi-key D5 cells (beautiful-chat → 5 per-pill keys) returned
the first non-null row as worst, only upgrading on red. A degraded
row encountered after a green row was silently dropped → cell
rendered green when it should have been amber. Replaced the
"only red wins" check with a numeric rank table (red=3, degraded=2,
green=1) so red > degraded > green holds regardless of iteration
order. Added 5 multi-key fan-out tests covering: red-after-green,
red-before-green, degraded-vs-green order independence, red-beats-
degraded, all-green-stays-green.
Symbols touched: resolveD5Row (live-status.ts:176), new
D5_STATE_RANK constant. Call-site enumeration: resolveD5Row is
called only by resolveCell at live-status.ts:371 — same input/
output shape, no caller change needed.
A2. fixture _comment lies about aimock arg shape
Both gen-ui-agent.json and shared-state-streaming.json's _comment
claimed `arguments` MUST be JSON-stringified or aimock silently
drops the call. aimock's `normalizeResponse` (verified in
node_modules/@copilotkit/aimock/dist/fixture-loader.cjs:14-19)
auto-stringifies object-valued arguments at load time, so both
shapes work. Updated the comments to reflect reality and stop
misleading future fixture authors.
A3. e2e-deep per-feature timeout race orphaned runFeature
When the synthetic timer won the Promise.race, runFeature was
abandoned but never told to tear down. Browser context stayed
held until the global timeout eventually fired, while the outer
Semaphore.release ran immediately — a NEW feature could acquire
the slot while the orphan still held the context, silently
exceeding FEATURE_CONCURRENCY's pool budget. Now: a per-feature
AbortController forwards the parent abort signal to runFeature;
when the timer wins, .abort() fires so runFeature's finally chain
tears down its page/context. The setTimeout cleanup is in a
try/finally so a thrown rejection (defensive — runFeature's
contract says no) doesn't leak the timer. The parent-abort event
listener is removed on cleanup to prevent listener accumulation
over many feature iterations.
Symbols touched: per-feature loop body in executeE2eDeepDriver
(e2e-deep.ts:982). runFeature signature unchanged.
A5. d5-chat-css user-bubble inner selector substring too loose
`[class*="bg-muted"]` matches `bg-muted-foreground` too. Real
Tailwind output puts `bg-muted-foreground` on nested children of
the user bubble; the probe could read computed styles off the
wrong element and silently mis-validate. Switched to
`[class~="bg-muted"]` (whole-token match in space-separated
class lists), the standard CSS3 way to express "this exact class
is present on the element."
A7. auth legacy fill/press swallowed errors silently
Legacy-shape assertion's catch block dropped fill/press errors
so a chat-input cascade mismatch (or disabled textarea after
sign-out) produced a generic "error surface did not appear"
timeout instead of the real cause. Now captures the error
message and appends it to the eventual error string so the
failure record names what actually broke.
A9. d5-feature-mapping header listed removed `hitl-steps`
The header's "destinations" list still showed `hitl-steps : 1
demo` even though my PR's narrative says it was removed in
genuine-pass Phase 0 — falsifying a claim my own diff makes.
Updated the header to reflect the current REGISTRY_TO_D5 shape:
`hitl-text-input` covers the 3 in-chat HITL variants (including
the legacy `hitl` alias) and mcp-apps/subagents are split.
A6 reclassified to bucket (b) — the 6s waste on chip-driven probes is
sub-10% of the new 5-min per-feature timeout and not load-bearing for
convergence. Documented in the round summary; can be addressed in a
follow-up via a `noSend` ConversationTurn option.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
6788f270e4 |
test(showcase/harness): update d5-gen-ui-interrupt test for clickByJs migration
The probe migrated from `clickable.click()` (Playwright pointer click) to `clickByJs(page, selector)` (page.evaluate-driven JS click) to bypass the cpk-web-inspector overlay. The test was still asserting the old click-mock contract: expect(click).toHaveBeenCalledWith(selector, opts) That assertion can never fire because the probe no longer calls page.click(). Updated to assert page.evaluate() is called with a function whose source contains the slot selector — the indirect shape of the new clickByJs path. Also dropped the "fails when page is missing click()" test — the new probe doesn't depend on page.click being on the structural Page interface, so the runtime guard is gone. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
94363d8e23 |
fix(showcase/harness): probes accept BOTH idiomatic and legacy demo shapes
The harness D5 probes run against ALL 18 integrations, but only langgraph-python has the recent idiomatic refactors. Production PB showed 16 integrations green on chat-css and chat-slots, and 3 green on auth — shipping the previous pure-HALCYON / pure-SlotMarker / pure-SignInCard probes would have regressed those green cells to red. Made all three probes accept either shape, detected at runtime: - d5-chat-css: tries HALCYON anchors (ember border + JetBrains Mono + Fraunces) first, falls back to legacy hot-pink/amber background anchors. Either passing satisfies the assertion. Combined error message names both paths so operators can see WHICH theme the integration was supposed to match against. - d5-chat-slots: combined CSS-OR selector `[data-slot-label="MessageView.AssistantMessage"], [data-testid="custom-assistant-message"]`. Either marker on the page is sufficient evidence the slot wiring fired. - d5-auth: preFill detects shape via brief SignInCard probe — present → idiomatic (click sign-in to mount chat); absent → legacy (chat already mounted, no preFill action). Assertion clicks sign-out then races SignInCard re-mount (idiomatic pass) against banner-flip + error-surface (legacy pass). Each path has a discrete error message so operators can tell which contract failed. Tests rewritten to exercise both paths for each probe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
deb0b7394d | style: auto-fix formatting | ||
|
|
547fb2b6c9 |
fix(showcase/harness): add AAPL stock-price fixture pair to tool-rendering.json
The d5-tool-rendering-custom-catchall probe sends two prompts: "weather in Tokyo" and "What's the current price of AAPL?". Only the weather pair (tool-call + narration) was present in the fixture, so the AAPL turn fell through to a non-deterministic response and the custom-wildcard renderer mounted only one container instead of two — surfacing as the production "rendered 1 container(s) but is missing tool name(s)" error. Add the matching get_stock_price fixture pair (call + narration) keyed on the substring `current price of AAPL` with the same hasToolResult disambiguation pattern as weather. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5e6eb1a2cc |
fix(showcase/harness): use JS-level click in d5-gen-ui-interrupt to bypass cpk-web-inspector
The probe was using Playwright's `page.click()` on the [data-testid="time-picker-slot"] element. The cpk-web-inspector overlay intercepts pointer events before React's synthetic event system picks them up, so the slot's onClick (which calls the LangGraph interrupt's resolve callback) never fires — the time-picker never flips into the picked state and the probe times out at step 3. Lift the JS-level click pattern out of d5-auth.ts:defaultClick into a shared `clickByJs` helper in `_genuine-shared.ts`, then use it from gen-ui-interrupt. The JS-level `.click()` triggers the DOM click event without pointer dispatch, which the inspector overlay doesn't intercept. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
24418a303e |
fix(showcase/harness): stringify write_document arguments in shared-state-streaming fixture
Same root-cause pattern as gen-ui-agent: the three pill fixtures (poem / email / quantum) emitted `arguments` as raw JSON objects. aimock follows OpenAI's tool-call wire shape where `arguments` must be a JSON-stringified string — raw objects silently drop the call, write_document never executes, the shared-state document never streams content, and the probe times out at 60s. Stringify all three pill payloads, add explicit `id` fields, and document the JSON-string requirement in the fixture _comment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
31824a50f9 |
fix(showcase/harness): stringify set_steps arguments in gen-ui-agent fixture
The fixture was emitting `arguments` as a raw JSON object on each set_steps tool call. aimock follows the OpenAI tool-call wire shape where `arguments` is a JSON-stringified string — a raw object silently drops the call so the demo's useAgent never sees a state mutation, the agent-state-card never mounts, and the probe times out at 60s. Stringify the arguments on all three pill fixtures (launch / offsite / competitor research) and add explicit `id` fields per call to match the convention in adjacent fixtures (gen-ui-headless-complete, beautiful-chat-*). Documented the JSON-string requirement in the fixture _comment so the next regression is obvious. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
16dc08cabf |
fix(showcase/harness): include fixture hex anchors in frontend-tools gradient hints
The d5 fixture for frontend-tools emits gradients as pure hex with no English narration: sunset: linear-gradient(135deg, #ff7e5f 0%, #feb47b 50%, #ff6b6b 100%) forest: linear-gradient(135deg, #0a3d2e 0%, #166534 50%, #059669 100%) cosmic: linear-gradient(135deg, #1e3a8a 0%, #6b21a8 50%, #9333ea 100%) PILL_GRADIENT_HINTS only carried color-name keywords (sunset, orange, green, etc.), so the keyword-includes check tripped fc=1 the moment this fixture started shipping pure-hex gradients. Add the literal 6-digit hex codes from each fixture pill to the matching family. Per the file's existing anti-prefix-collision comment, full 6-digit codes preserve the cross-pill differentiation guarantee — a regression that returns the same gradient for every pill still goes red on turn 2 because the baseline ratchet rejects unchanged values regardless of the hint family. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
8d39b53f6e |
fix(showcase): rework auth probe and e2e for unmount-based sign-out flow
The auth demo refactor flipped its lifecycle: unauthenticated is now
the default state, <CopilotKit> only mounts after sign-in, and
sign-out unmounts the entire chat tree (instead of leaving stale
auth headers in a still-mounted chat). The old probe + e2e spec
chased a 401-error-banner surface that no longer exists in the new
demo, plus a brittle 500ms hardcoded `useEffect` flush wait.
Probe rewrite (`d5-auth.ts` + tests):
- Add `buildAuthPreFill` that clicks the SignInCard's sign-in button
before turn 1, then waits for the chat textarea to mount (proves
<CopilotKit> handshook with the runtime).
- `buildAuthAssertion` now clicks sign-out, then waits for SignInCard
to re-mount. The unmount marker IS the proof — no chat-send-and-401
dance is needed (or possible — there's no chat to send into).
- Drop the hardcoded 500ms setTimeout, the unauth-banner wait, and
the error-surface poll. None apply to the new flow.
E2E rewrite (`tests/e2e/auth.spec.ts`):
- "page loads unauthenticated with SignInCard visible"
- "signing in mounts the chat surface with AuthBanner"
- "authenticated send produces an assistant response"
- "signing out unmounts the chat tree and re-renders SignInCard"
- "signing back in re-mounts a fresh chat surface"
Fixture comment updated to reflect the new flow. The user message
("auth check turn 1") and content response are unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
4f26734b4d |
fix(showcase): rewrite d5-gen-ui-headless-complete probe + fixture for new chip set
The headless-complete refactor replaced the old 5-chip set
(Weather/AAPL/Highlight/Sketch/Largest continent) with a new 4-chip
set wired through `useConfigureSuggestions`/SuggestionBar:
Weather → "What's the weather in Tokyo?" → WeatherCard
Stock price → "What's the price of AAPL right now?" → StockCard
Highlight a note → "Highlight this note for me: 'ship the demo on Friday'."
→ HighlightNote
Revenue chart → "Show me a chart of revenue over the last six months."
→ ChartCard
Probe rewrite:
- Drop the wrapper-scoped chip selector (`[data-testid=
"headless-suggestions"] >> text=...`) — the new SuggestionBar
doesn't have that container testid. Click via plain `button >>
text="<chip title>"` instead.
- Per-turn assert the matching tool card testid mounts
(headless-weather-card, headless-stock-card, headless-highlight-card,
headless-revenue-chart) plus a distinguishing text token. Driven
off a TURN_EXPECTATIONS table so adding a chip is one entry.
- Drop the readMessagesText helper that scoped to a missing
`[data-testid="headless-complete-messages"]` container; collect
text by concatenating all `headless-message-assistant` bubbles.
Fixture rewrite:
- Drop the Excalidraw + Largest-continent entries (no longer in the
chip set). Weather is already covered by feature-parity.json.
- Add a Revenue chart fixture for `get_revenue_chart` with inline
data so ChartCard renders without backend.
- Stock + Highlight fixtures preserved (still match the new chip
messages via substring).
Also restore `data-message-role` attributes on the headless-complete
UserBubble + AssistantBubble so the runner's settle plateau cascade
can resolve them — matches the runner's documented headless-template
contract.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
2d78a0f409 |
fix(showcase): rename gen-ui-headless D5 type to headless-simple and rewrite probe
The headless-simple demo was refactored to a deliberately minimal
"two hooks, one shadcn shell" template — text-in/text-out only, no
gen-UI. The D5 type literal `gen-ui-headless` no longer described
what the probe tests, and the old probe (Profile-card useComponent
+ continent fallback) was asserting against UI that no longer exists.
Three coordinated changes:
1. Rename `gen-ui-headless` D5FeatureType to `headless-simple` so the
slug matches the demo. Updated d5-registry, REGISTRY_TO_D5,
CATALOG_TO_D5_KEY (dashboard), and dependent tests/comments.
`headless-complete` keeps its existing literal because that demo
still drives the full gen-UI surface.
2. Replace d5-gen-ui-headless.{ts,test.ts,fixture} with
d5-headless-simple.ts + headless-simple.json fixture. New probe
clicks the "Say hello in one short sentence." chip and asserts the
`[data-testid="headless-message-assistant"]` bubble mounts with
non-empty content.
3. Restore `data-message-role` attributes on the headless-simple
UserBubble + AssistantBubble. The runner's chat-input cascade
documents these as the headless-template contract; the refactor
dropped them, breaking the runner's settle plateau detection.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|