Commit Graph

208 Commits

Author SHA1 Message Date
Tyler Slaton 9e40b1bf64 feat(showcase/langgraph-python): Frontend Tools + HITL family
Frontend Tools (in-app + async) demonstrate the spectrum of agent →
client tool calls:

- frontend-tools — useFrontendTool with a synchronous handler that
  mutates page state. The agent calls `change_background` with any CSS
  background value and the canvas re-paints. <CopilotSidebar /> layout;
  default background is solid indigo so the canvas reads as a clean
  start.
- frontend-tools-async — useFrontendTool with an async handler. The
  agent calls `query_notes`, the handler awaits a 500ms simulated DB
  query, and the agent uses the returned notes in its reply. Pure
  frontend tool — backend has tools=[].

HITL family — three patterns for human-in-the-loop, all keyed on the
useHumanInTheLoop / useInterrupt primitives:

- hitl — step-feedback variant rendering inside the chat via
  useHumanInTheLoop + useInterrupt (the v2 replacement for
  useLangGraphInterrupt, which is not exported in v2).
- hitl-in-chat — time-slot picker variant. Backend graph (hitl_in_chat)
  calls `interrupt({slots, …})` and resumes when the user picks. This
  is the canonical "in-chat HITL" demo; the manifest entry points here.
- hitl-in-app — async useFrontendTool with an app-LEVEL approval modal
  (rendered via createPortal OUTSIDE the chat). The completion callback
  resolves the pending tool Promise with the user's decision. This is
  HITL where the human surface is your app's UI, not the chat.
- gen-ui-interrupt — the lower-level useInterrupt primitive. Backend
  (src/agents/interrupt_agent.py) has a real `schedule_meeting` tool
  that emits an interrupt with topic / attendee / slots, and the
  frontend renders an inline TimePickerCard.
2026-05-06 23:17:21 -07:00
Tyler Slaton 3e157a1e02 feat(showcase/langgraph-python): Multimodal + Voice + Beautiful Chat
Three "production-feel" chat demos that exercise the same convention
(page.tsx as entry point + suggestions extracted) and add their own
specialized hooks:

- multimodal — image + PDF uploads via CopilotChat attachments. Includes
  a LegacyConverterShim (until @ag-ui/langgraph ships an updated
  converter), magic-byte + LFS-pointer guard for safe content sniffing,
  and sample-attachment-buttons that inject test images via DataTransfer
  + dispatch `change` event so screenshots / Playwright reproduce.
- voice — speech-to-text via @copilotkit/voice. Uses the V2 runtime
  directly with [[...slug]] catch-all because `transcriptionService` is
  V2-only. A guarded sample-audio-button injects deterministic sample
  text via the textarea's native value setter (CopilotChat has no
  controlled-input prop today). useSingleEndpoint={false} opts into the
  V2 multi-endpoint protocol.
- beautiful-chat — flagship polished starter chat with brand fonts,
  theme tokens, suggestion pills, generative-UI charts, and
  enableAppMode / enableChatMode tools. Backend
  (src/agents/beautiful_chat.py) wires query_data, manage_todos,
  search_flights, and an A2UI dynamic generator (generate_a2ui) that
  hits a secondary LLM for schema design. Model: gpt-5-mini.

The convention pass extracted suggestions into separate files for each
demo and slimmed page.tsx down to imports + provider + render.
2026-05-06 23:17:00 -07:00
Tyler Slaton 4737eb46f1 feat(showcase/langgraph-python): Prebuilt — CopilotChat / Sidebar / Popup
Three demos showing the prebuilt component formats. All three share the
neutral assistant graph and follow the page-as-entry-point convention:
each page.tsx slimmed to imports + provider + the suggestions hook
mount + JSX, with `useConfigureSuggestions` extracted to its own file.

- agentic-chat (Prebuilt: CopilotChat) — full-page CopilotChat. Plain
  text suggestions (joke / fun fact / limerick) — earlier drafts had a
  "Weather in Paris" prompt but the agent has no weather tool; trimmed
  to non-tool prompts so suggestions actually work.
- prebuilt-sidebar (Pre-Built: Sidebar) — <CopilotSidebar /> docked to
  the edge of the viewport. Page content centered in mx-auto max-w-2xl
  column with icon + heading + paragraph. The sidebar genuinely PUSHES
  the page now — see the body width fix in src/app/globals.css from the
  scaffolding commit.
- prebuilt-popup (Pre-Built: Popup) — <CopilotPopup /> with a floating
  launcher. Same centered content shape as the sidebar demo.

Removed: src/app/demos/agentic-chat/agent.py — TODO stub with a
misleading docstring; the real graph is at src/agents/agentic_chat.py.
2026-05-06 23:16:40 -07:00
Tyler Slaton ac89b11efd feat(showcase/langgraph-python): Reasoning - Default + Custom
A pair of demos that exercise the same backend reasoning graph but
differ only in whether the frontend overrides the
`messageView.reasoningMessage` slot.

Backend (src/agents/reasoning_agent.py): uses a reasoning-capable OpenAI
model (gpt-5-mini by default, override via OPENAI_REASONING_MODEL) routed
through the Responses API so the model's chain-of-thought streams as
AG-UI REASONING_MESSAGE_* events with `role: "reasoning"`. The prompt
asks for a concrete physics answer, which reliably triggers reasoning;
meta-prompts like "show your reasoning step by step" produce no
reasoning summary because the model recognizes those as a request to
reveal chain-of-thought (which it refuses).

Frontend:
- reasoning-default/ — no slot override; built-in
  CopilotChatReasoningMessage renders the "Thinking… / Thought for X"
  header with an expandable content region.
- reasoning-custom/ — overrides `messageView.reasoningMessage` with a
  ReasoningBlock (amber banner with `data-testid="reasoning-block"`).
  The label flips from "Thinking…" while streaming to "Agent reasoning"
  once the stream settles.

Suggestions live in their own files (per the page-as-entry-point
convention). Both demos share `agent="reasoning-default"` /
`agent="reasoning-custom"` against the same `reasoning_agent` graph,
registered in api/copilotkit/route.ts.

Removed:
- src/app/demos/agentic-chat-reasoning/ — replaced by reasoning-custom/
  for naming clarity.
- src/app/demos/reasoning-default-render/ — earlier draft of the Default
  demo with a slightly different page name.
- tests/e2e/agentic-chat-reasoning.spec.ts — replaced by
  reasoning-custom.spec.ts.
2026-05-06 23:16:13 -07:00
Tyler Slaton 4ff8dd608c feat(showcase/langgraph-python): chat customization (CSS + Slots)
Two paired demos showing the spectrum of "change the look" without
rewriting components:

CSS theming (chat-customization-css/) — HALCYON, a warm-paper editorial
brand. Two layers do the work:
  1. v2 token overrides on `[data-copilotkit]` recolor every Tailwind
     utility (cpk:bg-muted, cpk:text-foreground, …) the runtime renders.
  2. Class-targeted styling on .copilotKitChat, .copilotKitMessage*,
     .copilotKitInput, suggestions, scrollbar, welcome screen for the
     editorial details that CSS variables alone can't express.
Aesthetic: cream parchment surface, sharp 90° corners, copper-ember
accents, italic display serif (Instrument Serif) + Fraunces body +
JetBrains Mono dispatch, paper-grain noise via inline SVG, mono masthead
pinned under the top edge. All selectors namespaced under
`.chat-css-demo-scope` — no leakage.

Slot atlas (chat-slots/) — every overrideable slot wrapped in a
dashed-outline marker. Markers nest correctly: each shows ONLY its own
label on hover via `:has(.slot-marker:hover)` rather than lighting up
every nested label as the cursor enters the outermost one. Each label is
a click-to-copy button (✓ flash on success) that copies the slot's
PascalCase component path (`Input.TextArea`,
`MessageView.AssistantMessage`, …) so a developer can paste straight
into IDE search. SuggestionPill, ScrollToBottomButton, and Feather slots
are all wired. CustomFeather has its own `FeatherCopyLabel` because the
default Feather uses position:absolute and can't share SlotMarker.

Both demos use the neutral assistant graph (chat-customization-css and
chat-slots are entries in the route.ts neutralAssistantCells list).
2026-05-06 23:15:49 -07:00
Tyler Slaton bd9da67c48 feat(showcase/langgraph-python): rebuild Headless UI: Complete (modular)
Full headless surface — a hand-rolled CopilotChat replacement that wires
every render hook on top of shadcn/ui primitives. Visual chrome matches
Headless: Simple so the two read as a paired sibling demo.

Architecture is progressive-disclosure: the entry file is a 30-line
HeadlessCompleteRoot that enumerates capabilities, each registered via
a focused hook module:

  page.tsx
  hooks/
    use-tool-renderers.tsx     — useRenderTool x3, useDefaultRenderTool
    use-frontend-components.ts — useComponent (highlight_note)
    use-headless-suggestions.ts — useConfigureSuggestions
  chat/
    chat.tsx, header.tsx, empty-state.tsx, composer.tsx,
    suggestion-bar.tsx, message-list.tsx, message-user.tsx,
    message-assistant.tsx, message-activity.tsx, typing-indicator.tsx
  attachments/use-attachments-config.ts + attachment-preview.tsx
  tools/weather-card.tsx, stock-card.tsx, chart-card.tsx,
        generic-tool-card.tsx, highlight-note.tsx

Backend (src/agents/headless_complete.py): get_weather, get_stock_price,
get_revenue_chart tools; the chart tool replaces the previous Excalidraw
"Sketch a diagram" suggestion (MCP capability stays wired).

Bug fixes folded in:
- Tool-call cards stuck "running" forever — message-list.tsx indexes
  role:"tool" messages by toolCallId and passes the matching ToolMessage
  to renderToolCall so cards advance to "complete".
- Empty state was hugging the top of the viewport — Radix ScrollArea
  wraps content in a `display: table` div that breaks h-full propagation.
  Empty state now renders OUTSIDE the ScrollArea.
- SuggestionBar duplicated the empty-state prompts on first paint.
  Hidden until the conversation starts.
2026-05-06 23:15:26 -07:00
Tyler Slaton 83884b0be5 feat(showcase/langgraph-python): rebuild Headless UI: Simple
Minimum-viable headless chat that wires only `useAgent` + `useCopilotKit`,
dressed in shadcn/ui primitives. Five small single-purpose files so a
reader can grok the surface in under a minute:

  page.tsx        — provider + <Chat />, ~10 lines
  chat.tsx        — useAgent + useCopilotKit + send loop
  composer.tsx    — Textarea + send button
  empty-state.tsx — sparkles + sample prompts
  message-bubble.tsx + typing-indicator.tsx — render pieces

Wires runtimeUrl="/api/copilotkit" + agent="headless-simple" against
the neutral assistant graph registered in route.ts.

Also adds the v2 catch-all route at copilotkit-mcp-apps/[[...slug]]/route.ts
(used by Headless: Complete in the next commit). v2 hooks POST to subpaths
like /v2/agent/run; the previous flat route 404'd, leaving headless demos
stuck on "Thinking…".
2026-05-06 23:15:03 -07:00
Tyler Slaton 3ac7ac7977 chore(showcase/langgraph-python): scaffold showcase shell
Foundational layer that the per-demo work in subsequent commits builds on.

- Manifest-driven landing page (src/app/page.tsx) — auto-generated grid
  of demo cards from manifest.yaml, grouped by tag with explicit ordering
  for chat-ui / interactivity / generative-ui / agent-state / multi-agent
  / headless / platform.
- Per-demo titles (src/middleware.ts + src/app/demos/layout.tsx).
- Diagnostic console gated to NODE_ENV=production in app/layout.tsx so
  deployed showcases surface uncaught errors and iframe context.
- src/app/globals.css — Tailwind v4 @theme inline block that maps
  showcase CSS variables into Tailwind theme tokens (without it, shadcn
  utilities like bg-muted / text-foreground compile to nothing). body
  intentionally NOT given width:100% so <CopilotSidebar /> can shrink
  the document via marginInlineEnd.
- shadcn primitives under src/components/ui/ + src/lib/utils.ts.
- tsconfig.json — @/* path alias rooted at src/.

Removed:
- src/app/copilotkit-overrides.css (global override layer, superseded
  by per-demo theming)
- src/app/api/copilotkit-mcp-apps/route.ts (replaced with
  [[...slug]]/route.ts so v2 subpath POSTs like /v2/agent/run resolve)
2026-05-06 23:14:11 -07:00
Alem Tuzlak 48cd3b2c93 feat(showcase/voice): D5 mapping + sample-button bypasses /transcribe (#4674)
## Summary

- **Dashboard mapping fix.** `CATALOG_TO_D5_KEY` in
`showcase/shell-dashboard/src/lib/live-status.ts` was missing `voice →
["voice"]`, so `computeMaxPossible` capped the langgraph-python voice
cell at D4 even when the d5-voice probe row was green. The harness
`REGISTRY_TO_D5` already had the entry; only the dashboard mirror was
out of sync.
- **Sample-button decoupled from `/transcribe`.** The "Play sample"
button used to fetch `sample.wav` and POST it to the runtime's
transcription endpoint, which made the sample button and the mic
indistinguishable under aimock (both returned the canned transcription).
Reworked it into a synchronous static-text injector — sample button is
now a deterministic test/demo affordance, and the mic is the only path
that exercises real Whisper transcription. Synced across all 18
voice-enabled integrations. Phrase stays `"What is the weather in
Tokyo?"` so aimock's `weather in Tokyo` substring fixture still matches.
- **Probe-test parity.** Added the missing `d5-voice.test.ts` companion
(every other `d5-*.ts` script has one) — 9 tests covering registration,
`buildTurns`, `preFill` (sample-button click + textarea-poll path), and
the weather/Tokyo assertion.
- **QA + e2e cleanup** for langgraph-python: dropped the
no-longer-applicable "Transcribing…" mid-flight assertion and the `block
/demo-audio/sample.wav` error-state subsection. Other 16 integrations'
qa/e2e files follow in a parity sync PR.

## Test plan

- [x] `nx test @copilotkit/showcase-harness -- --run d5-voice` → 9/9
pass
- [x] `npm test` in `showcase/shell-dashboard` → 509/510 pass (1
skipped, 0 failed)
- [x] `nx build @copilotkit/showcase-harness` → clean
- [x] Local boot: `langgraph-cli dev` (port 8123) + `next dev` (port
3000) + dashboard (port 3002) — voice page at `/demos/voice` renders,
"Play sample" injects the canned phrase instantly, send → agent returns
weather, mic → real Whisper transcription with `OPENAI_API_KEY` set
- [ ] Reviewer: confirm the langgraph-python voice cell on the live
dashboard advances to D5 once the next d5-voice probe tick lands a green
row
2026-05-06 18:25:33 +02:00
Alem Tuzlak 728ed61ce8 feat(showcase/voice): D5 mapping + sample-button bypasses /transcribe
The langgraph-python voice cell sat at D4 even when its d5-voice probe
row was green. Root cause: the dashboard's CATALOG_TO_D5_KEY mirror in
showcase/shell-dashboard/src/lib/live-status.ts was missing voice ->
["voice"], so computeMaxPossible capped voice at D4 regardless of probe
state. The harness REGISTRY_TO_D5 already had the entry; only the
dashboard mirror was out of sync.

Separately, the "Play sample" button used to fetch sample.wav and POST
it to /transcribe. With aimock that meant both the sample button AND
the mic returned the same canned response, which made it impossible to
demo the mic path locally without conflating the two affordances.
Reworked the button into a synchronous static-text injector
(onTranscribed(sampleText)) so:

- Sample button = deterministic test/demo affordance, no runtime calls.
- Mic = real Whisper transcription via /transcribe.

Synced across all 18 voice-enabled integrations. Phrase stays "What is
the weather in Tokyo?" so aimock's "weather in Tokyo" substring fixture
still matches.

Also adds the missing d5-voice.test.ts companion (every other d5-* probe
script has one) and trims the langgraph-python qa/voice.md + e2e steps
that depended on the now-removed async behavior.
2026-05-06 18:11:24 +02:00
Alem Tuzlak 3eb53a8621 feat(showcase): D5 probe for headless-complete + extend headless-simple (langgraph-python)
Promotes /demos/headless-complete to its own D5 feature type so the
dashboard cell can reach D5 instead of riding on the headless-simple
probe (which was navigating to /demos/headless-simple regardless of
which catalog feature triggered it).

- New gen-ui-headless-complete D5 feature type + script that clicks
  each suggestion chip via preFill and asserts the right surface
  renders: WeatherCard (get_weather), StockCard (get_stock_price),
  HighlightNote (frontend useComponent), Excalidraw best-effort, and
  the canonical "Asia is the largest continent" text reply.
- Existing gen-ui-headless script now drives both turns by chip
  click (Profile card + Largest continent) instead of typing.
- Fixtures pin narration legs with both userMessage AND toolCallId
  and order them before the bare userMessage toolCall fixture —
  aimock's toolCallId matcher reads the LAST tool message in the
  request, but in a multi-turn probe that "last tool" stays on a
  previous turn's id until a new tool runs, which would otherwise
  hijack a later turn's prompt with a stale narration.
- headless-complete UserBubble + AssistantBubble now carry
  data-message-role so the harness conversation runner can detect
  message arrivals (mirrors the headless-simple convention).
- Mappings updated in lockstep:
    - REGISTRY_TO_D5:  headless-complete -> ["gen-ui-headless-complete"]
    - CATALOG_TO_D5_KEY (dashboard): same.
2026-05-06 16:21:43 +02:00
Alem Tuzlak 23d4770537 feat(showcase): hand-rolled headless-chat suggestion chips + parity across 17 integrations (#4669)
## Summary

Adds hand-rolled persistent suggestion chips to the `headless-simple`
and `headless-complete` demos in the langgraph-python north-star,
propagates the same surface to the other 17 showcase integrations, and
adds a deterministic aimock fixture so a new chip-click e2e test
("Largest continent") rounds-trips against a stable `Asia is the largest
continent…` response across all 18 demos.

## What changed

**Phase 0 — north-star (commit `7cbc5ea8`)**
- `showcase/aimock/feature-parity.json` — new fixture: `What is the
largest continent?` → `Asia is the largest continent — about 30% of
Earth's land area, home to over 4.6 billion people.`
- `langgraph-python/src/app/demos/headless-{simple,complete}/page.tsx` —
refactor `send` / `handleSubmit` to accept `(override?: string)` so chip
clicks dispatch synchronously without a `setInput` round-trip; render a
persistent `<div data-testid="headless-suggestions">` chip row above the
composer with 5 canonical entries; remove the dead
`useConfigureSuggestions` call from headless-complete (it was
registering suggestions nothing rendered).
- `langgraph-python/tests/e2e/headless-{simple,complete}.spec.ts` —
append one new test in each spec asserting chip click → user message →
`Asia` reply.

**Phase 1 — parity propagation across 17 integrations (commit
`4882c61f`)**
- Spec files `headless-simple.spec.ts` and `headless-complete.spec.ts`
are now byte-identical to the north-star in every integration (10 tests
each = 5 simple + 5 complete; verified via `cmp` for all 34 spec files).
- The 5-entry `suggestions` const is byte-identical between every
integration's simple and complete demos.
- All 17 integrations now expose the same selector surface (canonical
headings, empty-state text, `data-testid="headless-complete-messages"`,
dynamic placeholder, `rounded-br-sm` user bubble, no CopilotChat-default
testids).

**Glue preserved per integration** (verified by post-blitz code review):
- `built-in-agent`: `<CopilotKitProvider runtimeUrl="/api/copilotkit"
useSingleEndpoint>` + `agentId: "default"`
- `google-adk` / `llamaindex`: `agentId: "headless_simple"` /
`"headless_complete"` (Python-style underscores)
- `claude-sdk-typescript`: headless-complete
`runtimeUrl="/api/copilotkit-headless-complete"`
- `spring-ai`: 70-line `deduplicateMessages` adapter workaround +
`useMemo` import preserved verbatim
- All `@region[...]` markers preserved in place

**Adapter-specific decisions worth flagging in review:**
- `google-adk` headless-complete: rewrote `message-list.tsx` from
`msg-user`/`msg-assistant`/`agent-thinking` testid scheme to the
canonical `headless-complete-messages` wrapper; rewrote `input-bar.tsx`
placeholder to canonical dynamic; added the missing subtitle and
empty-state hint
- `ms-agent-dotnet`: extracted inline composer to a new `input-bar.tsx`
to match north-star structure
- `llamaindex`, `ms-agent-python`: added the canonical empty-state hint
(was missing entirely)
- `agno`, `built-in-agent`, `crewai-crews`, `mastra`, `ms-agent-dotnet`,
`pydantic-ai`: replaced per-integration empty-state hint with the
canonical Excalidraw line — chosen for parity over per-integration
accuracy (some demos don't actually wire an Excalidraw tool; alignment
was the explicit goal)

## Verification

- `validate-parity.ts`: 18/18 packages pass, 0 MUST failures
- `aimock-fixtures` test suite: 18/18 pass
- aimock fixture probed directly: `What is the largest continent?`
returns the canonical Asia response
- Each propagation slot reported `tsc --noEmit` clean (0 new errors) +
`playwright --list` shows all 10 expected tests
- Code review (`pr-review-toolkit:code-reviewer`) on the full diff: 0
Critical / Important / Minor findings, 1 stylistic nit (north-star
`input-bar.tsx` `onSubmit` type contravariant-loose, harmless)

## What was NOT done

Live per-integration Playwright runs against rebuilt Docker images. The
17 containers would each need a no-cache rebuild (~5-15 min each = hours
total) and the canonical local-test path is `showcase test <slug>` per
the existing CLI / CI pipeline. Static + structural verification covers
the propagation pattern.

## Test plan

- [ ] Run `showcase test <slug>` (or equivalent CI job) for at least one
drift-heavy integration: `google-adk` (testid scheme rewrite),
`built-in-agent` (provider glue), `spring-ai` (dedup workaround),
`llamaindex` (added testid + empty-state)
- [ ] Run the existing per-integration Playwright suites for at least
the north-star (`langgraph-python`) to confirm the new chip test passes
against a real backend + aimock
- [ ] Confirm aimock fixture validation still passes after deploy
2026-05-05 18:27:48 +02:00
Alem Tuzlak 602fb2d190 fix(showcase): trim headless-simple chips to in-surface set + add tool wildcard to google-adk/headless-complete
The validate-fixture-tool-surface check on PR #4669 flagged 18 drift
violations: every headless-simple demo carried 'Weather in Tokyo' /
'AAPL stock price' / 'Highlight a note' / 'Sketch a diagram' chips
that substring-match aimock fixtures returning tool calls
(get_weather / get_stock_price / highlight_note / etc.) — but
headless-simple demos only register 'show_card' via useComponent.
Tool-call dispatch had no matching renderer.

Trim the headless-simple chip list to two in-surface entries:
- 'Profile card' → 'Show me a profile card for Ada Lovelace' (existing
  show_card fixture; show_card is already registered by useComponent).
- 'Largest continent' → 'What is the largest continent?' (text-only
  fixture from Phase 0; no tool dependency).

The chip-click e2e test only asserts on the 'Largest continent' chip,
so the trim is test-compatible.

Headless-complete keeps the canonical 5-chip list (its tool surface
covers weather/stock/highlight/excalidraw via tool-renderers.tsx and
backend agents).

For google-adk/headless-complete: add a useDefaultRenderTool() wildcard
catch-all. The validator looks at page.tsx + hooks/* and a backend
agent file; google-adk's tool registrations live in tool-renderers.tsx
(unparsed) and there's no matching agents/headless_complete.py file,
so the validator saw an empty tool surface. The wildcard registers '*'
which matches every fixture tool — same pattern north-star already
uses in its own tool-renderers.tsx.
2026-05-05 18:03:03 +02:00
github-actions[bot] f6e184baa8 style: auto-fix formatting 2026-05-05 14:43:04 +00:00
Alem Tuzlak 8c7ea92bb1 fix(showcase/beautiful-chat): render A2UI surfaces (fixed + dynamic schema)
Search Flights and Sales Dashboard pills both produce visible surfaces
on the langgraph-python beautiful-chat demo. Three independent bugs were
masking each other:

- Flight TypedDict required `id` + `statusIcon`, which the aimock fixture
  doesn't supply. langchain rejected the call with `flights.0.id: Field
  required` and the agent surfaced the error string as the tool result.
  Made the type permissive (only the fields `_build_flight_components`
  reads need to be there).
- search_flights now expands flights into literal-children FlightCard
  components server-side instead of relying on the structural-children
  template form (the binder doesn't reliably expand it for our custom
  catalog — sibling demos avoid the form for the same reason).
- Sales Dashboard pill went into a tool-call loop because the
  userMessage+toolName fixtures matched both the initial call and the
  post-tool turn. Hoisted the toolCallId fixture above them so the
  follow-up turn returns content and breaks the loop.

Custom Row/Column reintroduced with `gap` support — the basic catalog's
versions ignore it, leaving cards squished. Children are array-of-strings
only (matches what the agent and fixture emit).

Two new e2e tests cover both pills end-to-end. 3s wait in beforeEach so
the v2 chat provider hydrates before the click dispatches. Full spec:
7/7 green.
2026-05-05 16:38:43 +02:00
Alem Tuzlak 7cbc5ea80e feat(showcase): hand-rolled suggestion chips + Largest-continent fixture in north-star headless demos 2026-05-05 14:22:13 +02:00
Alem Tuzlak 51db05f666 fix(showcase): emit reasoning events in langgraph-python and langgraph-fastapi (#4579)
## Summary

The `agentic-chat-reasoning` and `reasoning-default-render` cells in
`langgraph-python` and `langgraph-fastapi` never rendered any reasoning
content. Root cause: both agents were configured with `gpt-4o-mini` +
`use_responses_api=False`, so the underlying model produced no reasoning
content blocks and the Chat Completions API has no reasoning summary
surface in the first place. The frontend's `reasoningMessage` slot
stayed empty even though the cells are billed as reasoning demos.

This PR:

- Switches both agents (and their `tool_rendering_reasoning_chain`
siblings) to `gpt-5-mini` through the Responses API with
`reasoning={"effort":"medium","summary":"detailed"}`, mirroring the
`langgraph-typescript` and `pydantic-ai` agents that already worked.
Model is overridable via `OPENAI_REASONING_MODEL`.
- Updates the aimock `d5-all.json` fixture (and the matching harness
`reasoning-display.json`) to set the `reasoning` field on the `show your
reasoning step by step` match. Aimock now emits
`response.reasoning_summary_text.delta` events so the demo renders
deterministically without a real LLM call.
- Adds a `Show reasoning` `useConfigureSuggestions` pill on both
reasoning pages in both integrations so the demo is one click to
exercise.
- Tightens the `d5-reasoning-display` probe to also assert that a
reasoning-role message rendered (`[data-testid="reasoning-block"]` or
`[data-message-role="reasoning"]`), not just that the word "reasoning"
appears in the transcript.
- Un-skips the three streaming reasoning-block tests in
`agentic-chat-reasoning.spec.ts`, adds a suggestion-pill test, and
extends `reasoning-default-render.spec.ts` to cover the default
reasoning slot.
- Updates the `langgraph-python` QA doc to describe the new model +
Responses API setup and the pill flow.

Verified locally end-to-end: clicking the pill at
`/demos/agentic-chat-reasoning` renders the amber `ReasoningBlock` with
the fixture's reasoning text above the final answer bubble.

## Out of scope

Other integrations were audited and intentionally left alone:

- `langgraph-typescript`, `pydantic-ai` already use a reasoning model +
Responses API and work today.
- `agno`, `claude-sdk-python`, `ms-agent-python` use deliberate
workarounds (XML-tag reasoning + custom AGUI handler, Claude
extended-thinking deltas, `think` tool respectively) because their AG-UI
bridges either don't translate Responses-API reasoning items, run a
multi-call CoT loop incompatible with fixture replay, or don't emit
reasoning events at all.
- `llamaindex` uses `gpt-4.1` and surfaces reasoning inline as assistant
text. Its bridge (`llama-index-protocols-ag-ui`) does not translate
Responses-API reasoning items into AG-UI events; fixing that needs an
upstream patch and is out of scope here.

## Notes

Committed with `--no-verify` (explicit user request) — this worktree has
no `node_modules`, so the lefthook `test-and-check-packages` step
couldn't run locally. Changes are entirely under `showcase/` and CI runs
the same checks.

## Test plan

- [ ] CI fixture-validation passes on `showcase/aimock/d5-all.json`
- [ ] `showcase test langgraph-python --d5 --verbose` —
`reasoning-display` probe green (asserts `reasoning-block` selector +
keyword)
- [ ] `showcase test langgraph-fastapi --d5 --verbose` — same
- [ ] `nx run @copilotkit/showcase-langgraph-python:test:e2e -- --grep
reasoning` — un-skipped specs pass against the deployed Railway image
- [ ] Manual: visit `/demos/agentic-chat-reasoning` on a deployed
langgraph-python, click `Show reasoning`, confirm amber `REASONING —
Agent reasoning` block renders with italic step text above the final
answer bubble
- [ ] Manual: same on `/demos/reasoning-default-render`, confirm
CopilotKit's default `CopilotChatReasoningMessage` card renders
2026-05-01 13:40:10 +02:00
Ran Shemtov 41b7fa1cb3 Merge branch 'main' into chore/upgrade-langgraph-integration-demos 2026-05-01 13:35:10 +02:00
github-actions[bot] 6032b374c4 style: auto-fix formatting 2026-05-01 11:32:58 +00:00
Alem Tuzlak dca1b9894d fix(showcase): emit reasoning events in langgraph-python and langgraph-fastapi
The agentic-chat-reasoning and reasoning-default-render cells in
langgraph-python and langgraph-fastapi were configured with
gpt-4o-mini + use_responses_api=False, which never produces AG-UI
REASONING_MESSAGE_* events: gpt-4o-mini is not a reasoning model and
the Chat Completions API does not surface reasoning summary items at
all. The frontend's reasoningMessage slot was rendering nothing,
even though the cells were billed as "reasoning" demos.

- Switch both reasoning agents to gpt-5-mini (override via
  OPENAI_REASONING_MODEL) routed through the Responses API with
  reasoning={"effort":"medium","summary":"detailed"} so the model's
  chain of thought streams as content blocks that @ag-ui/langgraph
  translates into REASONING_MESSAGE_* events.
- Update the aimock d5-all.json and harness reasoning-display.json
  fixtures to include a "reasoning" field so aimock emits
  response.reasoning_summary_text.delta SSE events deterministically
  in CI without hitting a real LLM.
- Add a "Show reasoning" useConfigureSuggestions pill on both
  reasoning demo pages so the user can trigger the fixture-matched
  prompt with one click.
- Tighten the d5-reasoning-display probe: it now also asserts a
  reasoning-role message rendered via [data-testid="reasoning-block"]
  or [data-message-role="reasoning"], so a plain text response
  containing the word "reasoning" no longer falsely passes.
- Un-skip the three streaming reasoning-block tests in
  langgraph-python's agentic-chat-reasoning.spec.ts and add a
  suggestion-pill test; expand the reasoning-default-render spec to
  cover the default reasoning slot.
- Update the langgraph-python QA doc to describe the new model +
  Responses API setup and the suggestion-pill flow.
2026-05-01 13:30:28 +02:00
Alem Tuzlak f13c49f92f fix(showcase): drop hardcoded white chat background that broke dark mode (#4577)
## Summary

-
`showcase/integrations/{langgraph-python,langgraph-typescript,mastra,built-in-agent}/src/app/copilotkit-overrides.css`
(and the starter template that seeds new integrations) all forced
`.copilotKitChat { background-color: #fff !important; }`. The
`!important` won over the per-demo `ThemeProvider`, so the
`beautiful-chat` demo rendered a white chat panel in dark mode.
- `langgraph-fastapi` has no overrides file and was already correct —
this PR brings the other four to parity by deleting just the offending
rule (the `.copilotKitInput` border styles are kept).
- Updated `showcase/STYLING-GUIDE.md` with a warning so the example
block doesn't get pasted back in.

## Test plan

- [ ] Open `/demos/beautiful-chat` in `langgraph-python` with the OS in
dark mode — chat background follows the dark theme (no white panel).
- [ ] Same check for `langgraph-typescript`, `mastra`, and
`built-in-agent`.
- [ ] `langgraph-fastapi` unchanged (regression check on the working
baseline).
- [ ] Light mode in all four still renders correctly (chat picks up the
v2 light tokens).
2026-05-01 12:56:02 +02:00
Alem Tuzlak f396638c32 fix(aimock): add HITL 1:1-with-Alice fixture before broad Alice match (#4576)
## Summary

The hitl-in-chat demo's **"Schedule a 1:1 with Alice next week to review
Q2 goals."** suggestion was being intercepted by the broad `userMessage:
"Alice"` matcher used by the memory/context demo, which returns a
generic "Nice to meet you, Alice! I see you're in Tokyo — wonderful
city..." greeting. The HITL flow never fired and the user saw a
nonsensical reply.

Aimock's matcher uses `text.includes(match.userMessage)` (substring) +
first-fixture-wins by file order, so any message containing "Alice"
hijacked the suggestion before the HITL flow could trigger.

## Fix

Added a fixture pair earlier in `showcase/aimock/feature-parity.json`
with the **full suggestion sentence** as the matcher:

- `hasToolResult: false` → returns a `book_call` toolCall, letting the
frontend `useHumanInTheLoop` render the time-picker.
- `hasToolResult: true` → returns the booking confirmation message.

The substring-match-on-full-sentence is effectively exact — no other
realistic user message will contain that whole sentence — so the broad
`Alice` / `alice` fixtures stay scoped to the memory demo where the user
actually says "I'm Alice" or similar.

## Test plan

- [ ] Click "Schedule a 1:1 with Alice next week to review Q2 goals." in
the langgraph-python hitl-in-chat demo against an aimock-backed
deployment → expect the time-picker card to render and a booking
confirmation after picking a slot.
- [ ] The memory/context demo (where users type "I'm Alice") still gets
the Tokyo greeting — broad fixtures unchanged.
- [x] Pre-commit hooks pass (test, check-packages, commitlint).
2026-05-01 12:55:46 +02:00
Alem Tuzlak 25e03ef0e8 fix(showcase): drop hardcoded white chat background that broke dark mode
The shared `copilotkit-overrides.css` files in langgraph-python,
langgraph-typescript, mastra, built-in-agent, and the starter template
forced `.copilotKitChat { background-color: #fff !important; }`, which
won over the demo-level `ThemeProvider` and made the beautiful-chat
demo render a white panel in dark mode. langgraph-fastapi has no
overrides file and was unaffected — same fix gets the others to parity.

Also add a warning in showcase/STYLING-GUIDE.md so the example block
isn't pasted back in by the next contributor.
2026-05-01 12:43:15 +02:00
Alem Tuzlak 9845dadebb fix(aimock): re-key HITL confirmations on toolCallId so back-to-back flows work
Bug: in a single chat session, running both HITL booking flows
back-to-back (Alice 1:1 → then Sales call without refresh) used to
skip the time-picker on the second flow and jump straight to
"Booked ..." text.

Cause: confirmation fixtures were matched on `hasToolResult: true`,
which fires whenever the conversation has ANY tool message in
history. After the first flow finished, the second user message
short-circuited to a confirmation match before the second flow's
toolCall fixture (gated on `hasToolResult: false`) had a chance to
fire. The picker never rendered.

Fix: re-key the two confirmation fixtures on `toolCallId` (the
specific tool_call_id of the matching `book_call` invocation), which
only fires when the LAST conversation message is a tool result with
that id — exactly the moment we want the confirmation. Drop the
`hasToolResult: false` constraint on the toolCall fixtures so they
match a fresh user request regardless of prior tool history.

Add a back-to-back regression test to all 17 hitl-in-chat specs:
walk Alice flow to completion, then sales flow without refresh,
assert two `time-picker-card` elements rendered. If the multi-flow
regression returns, the second card never appears and the test
fails at `toHaveCount(2)`.
2026-05-01 12:42:53 +02:00
Ran Shem Tov 84af438694 chore: use latest cpk 2026-05-01 12:31:05 +02:00
Ran Shem Tov 8bae258b84 chore: fix peripherals for smoke tests and parity 2026-05-01 12:31:04 +02:00
Ran Shem Tov 0b41bebe23 chore: fix showcase drift 2026-05-01 12:31:04 +02:00
Alem Tuzlak 8cb84e88eb test(showcase): replicate hitl-in-chat regression spec across all 17 integrations
The hitl-in-chat demo ships in 17 integrations (langgraph-python plus
16 others — mastra, strands, ag2, agno, crewai-crews,
langgraph-typescript, langgraph-fastapi, pydantic-ai, llamaindex,
langroid, claude-sdk-python, claude-sdk-typescript, ms-agent-python,
ms-agent-dotnet, spring-ai, google-adk). All shipped placeholder e2e
specs that only checked the chat input was visible — none exercised
the actual booking flow.

Replace each with the full booking-flow spec written for
langgraph-python:
1. The "Schedule a 1:1 with Alice" suggestion renders the time-picker
   card AND the Tokyo greeting is absent (regression guard against
   the broad aimock `userMessage: "Alice"` matcher).
2. Picking a slot transitions to the picked-state card and produces
   a "Booked … Alice" assistant follow-up.
3. The "Book a call with sales" suggestion runs the same flow with
   the sales attendee.

Also add the matching aimock fixture pair for the sales suggestion
in feature-parity.json — without it, case 3 would only pass against
real OpenAI, not the aimock-backed CI deployments. The pair mirrors
the Alice fixture pair: `book_call` toolCall on first turn,
confirmation message after the picker resolves.

Per-integration coverage matters because each integration has its
own framework-specific HITL wiring (`useHumanInTheLoop` binding to
the agent, agent-side tool registration, run streaming protocol)
that can regress independently of the shared aimock fixture.
2026-05-01 12:25:36 +02:00
Alem Tuzlak 846a8a8938 test(showcase): add hitl-in-chat regression spec for Alice 1:1 suggestion
Pins the contract that the new full-sentence aimock fixture pair beats
the broad `userMessage: "Alice"` matcher:

1. Sending the suggestion `"Schedule a 1:1 with Alice next week to
   review Q2 goals."` renders `[data-testid="time-picker-card"]`,
   not the Tokyo greeting. The test explicitly asserts the Tokyo
   greeting is absent — `toHaveCount(0)` against
   `/Nice to meet you, Alice/i` — so any future broad-match
   regression fails here loudly.
2. Clicking a slot transitions to `[data-testid="time-picker-picked"]`
   and the assistant follow-up message contains "Booked ... Alice",
   verifying the `hasToolResult: true` branch of the fixture pair
   also wires through.
2026-05-01 12:17:24 +02:00
Alem Tuzlak e79cac1208 fix(showcase): unblock gen-ui-agent recursion + drop deepagents wrapper
Verified end-to-end against a local langgraph-python stack: agent now
walks plan → step1 in_progress → step1 completed → ... → final summary,
and the frontend renders a single inline progress card that updates in
place all the way to "All 3 steps complete".

Two real changes pulled out from the verification round:

1. agent.py: drop the `deepagents.create_deep_agent` wrapper for the
   plain `langchain.agents.create_agent` ReAct loop. The deepagents
   planner / sub-agent / write_todos middleware ate enough supersteps
   per turn that the run regularly tripped LangGraph's recursion
   limit before the agent could publish all three step transitions.
   The plain ReAct loop is one superstep per LLM/tool call, and
   `state_schema=GenUiAgentState` is supported directly so the
   middleware-only state-extension hack is gone.

2. route.ts: bake `recursion_limit: 100` into every LangGraphAgent
   via `assistantConfig`. `with_config({"recursion_limit": ...})` on
   the compiled Python graph does NOT propagate when the graph is
   served via the langgraph runs API — the wrapper is invisible to
   the assistant config the server hands to Pregel, which then falls
   through to langchain_core's hard-coded default of 25. Setting
   `assistantConfig.recursion_limit` on the JS side makes the limit
   travel with every run kicked off through this route, regardless
   of what the Python graph thinks its config is.
2026-05-01 11:47:40 +02:00
Alem Tuzlak 0fcf904978 fix(showcase): switch langgraph-python gen-ui-agent to v2 useAgent
The langgraph-python gen-ui-agent demo was the only one of 18
integrations using the V1 `useCoAgentStateRender` hook. That hook
binds renders to messages via per-message claims, so each
state-changing tool call (each `set_steps` invocation) produced its
own card snapshot in the chat — a typical 3-step plan run pushed
~7+ stacked cards instead of one updating card.

Migrate the page to the canonical V2 pattern already used by every
other gen-ui-agent demo (mastra, strands, ag2, agno, crewai-crews,
langgraph-typescript, pydantic-ai, ...): subscribe to live state via
`useAgent` and render a single `InlineAgentStateCard` inside
`messageView.children`. The card now re-renders in place as state
streams — no per-message claims, no duplicates.

Also tighten the agent system prompt with an explicit numbered tool
sequence (1 plan + 6 transitions + final message) to make the
"step 3 stuck in_progress" tail-of-run failure less likely with
gpt-4o-mini. The UI is robust to a missed final transition either
way: when `agent.isRunning` flips to false, the card headlines
"All N steps complete" regardless of step.status.

Replace the stale e2e spec (which targeted a long-removed
`task-progress` test id) with one that pins the contract:
- exactly one `agent-state-card` rendered, even after the run
  finishes
- every `agent-step` ends in `data-status="completed"`
2026-05-01 11:11:17 +02:00
Jordan Ritter 463b0b7d0b feat(showcase): D5 voice test for langgraph-python
Add D5 voice test that exercises sample-audio transcription via aimock.
Infrastructure: voice in D5 feature type registry + mapping, skipFill
support in conversation runner (9 new tests), inputValue forwarding
in e2e-deep Page wrappers, aimock transcription fixture, tool-free
weather fallback fixture for agents without tools. Verified locally:
D5 suite passes green on langgraph-python (60.4s).
2026-04-30 22:15:45 -07:00
Jordan Ritter 738a85cfe9 fix(showcase): restore langgraph-python declarative-gen-ui to a2ui_dynamic graph
PR #4542 incorrectly changed graphId from "a2ui_dynamic" to
"sample_agent" and removed injectA2UITool: false. The a2ui_dynamic
graph owns the generate_a2ui tool itself — the runtime must NOT
auto-inject. This caused langgraph-python to regress from 31/31 to red.
2026-04-30 17:50:23 -07:00
Jordan Ritter 1db0bd7042 fix(showcase): resolve agent-not-found errors across integrations
- ms-agent-dotnet auth: V1→V2 CopilotKit import for proper agent discovery
- ms-agent-python: register interrupt agents (array declared but never iterated)
- claude-sdk-python: register hitl-in-chat-booking agent + fix stale dates
- ag2 + langgraph-python: declarative-gen-ui routes use default agent with
  runtime auto-injection instead of custom backend a2ui agents
- google-adk: hoist copilotRuntimeNextJSAppRouterEndpoint to module scope
  (per-request invocation caused race condition in agent Promise chain)
- langgraph-fastapi: remove AgentConfigLangGraphAgent that caused HTTP 400
  with LangGraph 0.6.0+; add default alias for open-gen-ui
2026-04-30 17:04:55 -07:00
Alem Tuzlak 0eb81b1406 fix(showcase): unbreak agent-config + byoc D5, reaching 31/31 green
agent-config: drop the AgentConfigLangGraphAgent subclass and use plain
LangGraphAgent. The subclass repacked CopilotKit provider properties
into forwardedProps.config.configurable.properties so the Python graph
could read them via RunnableConfig.configurable.properties — but
@ag-ui/langgraph@0.0.31 builds the LangGraph SDK request as
{ ..., config, context: { ...input.context, ...config.configurable } }
which merges configurable INTO context. LangGraph 0.6.0+ then rejects
with HTTP 400 'Cannot specify both configurable and context' on every
chat round-trip. Net effect: chat sent the user message, runtime 400'd,
no assistant response ever rendered. Removing the subclass unbreaks
the round-trip; the Python agent falls back to its DEFAULT_* constants
so the demo's frontend toggles no longer steer the system prompt
(known regression, tracked separately pending @ag-ui/langgraph fix
that decouples context from configurable).

byoc:
- D5 probe now sends the 'Sales dashboard' pill prompt (matches the
  fixtures added in main:f0a89b843 in feature-parity.json) instead of
  the previous generic 'render a byoc hashbrown' prompt that had no
  matching JSON-shaped fixture. Removed the now-obsolete byoc.json D5
  fixture file and regenerated the d5-all.json bundle (52 -> 50
  fixtures).
- Added data-testid='copilot-assistant-message' + data-message-role=
  'assistant' to the byoc-hashbrown and byoc-json-render renderer
  wrapper divs. The CopilotChat default assistantMessage slot includes
  these markers; overriding the slot with a custom JSON-rendering
  component dropped them, so the e2e-deep conversation runner's
  settle-detection cascade (which counts these selectors) never saw
  the response and timed out at 30s. Re-attaching the markers is a
  purely additive change that doesn't affect the renderers'
  behavior.
- D5 byoc assertion now waits for [data-testid='metric-card'] AND a
  chart (bar-chart or pie-chart) to render — a structural check on
  the BYOC contract output, not a transcript-keyword check that the
  custom renderer would never produce.

E2E status: 31/31 passing locally against
./bin/showcase up langgraph-python aimock with this branch's bundle.
2026-04-30 15:11:19 +02:00
Alem Tuzlak f1b02a4616 fix(showcase): stop infinite tool-call loop in beautiful-chat + restore brand styling
Beautiful Chat suggestion clicks looped forever because feature-parity.json
tool-calling fixtures lacked an `id` and a paired `toolCallId` followup.
After the agent ran the tool and re-prompted aimock, the same userMessage
substring matched again and the same toolCall was returned indefinitely.
Added explicit ids to 10 broken fixtures (pieChart, barChart, render_*_chart,
scheduleTime, search_flights, toggleTheme) and 11 paired toolCallId
followups returning content summaries — same convention the file already
uses for show_card, weather, etc.

Beautiful Chat layout also showed a black/white split and a broken logo on
the 8 integrations using the full ExampleLayout pattern (crewai-crews,
langgraph-fastapi, langgraph-python, langgraph-typescript, mastra,
ms-agent-dotnet, ms-agent-python, pydantic-ai). Two issues:

1. globals.css hardcoded `body { background: #fafaf9 }` and never defined
   the brand tokens (--background, --foreground, --card, --primary, …) that
   the layout, mode-toggle, todo card/column, and chart components reference
   via Tailwind 4 arbitrary values. ThemeProvider was also adding `dark` to
   <html> from system preference, so CopilotKit's chat went dark while body
   stayed cream.
2. example-layout/index.tsx renders <img src="/copilotkit-logo.svg" /> but
   the file did not exist in any integration's public/.

Added the full token set (light + dark) under :root and :root.dark/.dark,
registered the Tailwind 4 dark variant, switched body to var(--background)
/var(--foreground), and copied copilotkit-logo.svg + copilotkit-logo-mark.svg
into each integration's public/ from examples/integrations/langgraph-python.
2026-04-30 12:42:26 +02:00
Jordan Ritter 534cd1efa7 fix(showcase): D5 integration fixes across 12 frameworks
Per-framework fixes to pass D5 e2e-deep probes:
- agno: deduplicate agent_server routes
- claude-sdk-python: handle ParsedContentBlockStopEvent (SDK v0.97+)
- claude-sdk-typescript: remove orphan tool-rendering page
- crewai-crews: add backend tool_rendering agent + shared_state fix
- google-adk: add AGUIToolset to all ADK agents for frontend tools
- langgraph-typescript: remove stale import
- langroid: emit ToolCallResultEvent for backend tools + fix adapter
- llamaindex: v2 provider import, book_call stub, PYTHONPATH fix
- ms-agent-python: disable Responses API store for aimock compat
- pydantic-ai: simplify gen-ui page component
- spring-ai: raise tool iteration cap (1→5) + fix connection pooling
- strands: shared tools symlink + requirements update
2026-04-29 19:40:10 -07:00
Sam Julien 8ba692c426 fix(showcase): regenerate all 18 integration package-lock.json files
Recent feature commits added new dependencies to integration package.json
files (@copilotkit/voice, @hashbrownai/{core,react}, @json-render/{core,react})
and bumped Next.js from 15.4.10 to 15.5.15, but never regenerated the
corresponding package-lock.json. The Showcase Build & Deploy workflow runs
`npm ci --legacy-peer-deps` which strictly enforces lock sync, so every
deploy attempt has been failing at the install step. No new images have been
pushed to GHCR, so Railway services have stayed on stale code and any cell
added since each fw's last successful deploy iframes 404.

Regenerated all 18 lockfiles via `npm install --legacy-peer-deps
--package-lock-only --ignore-scripts` per integration. Verified each with
`npm ci --dry-run --legacy-peer-deps` — all clean.

Refs PDX-90.
2026-04-29 15:39:13 -07:00
github-actions[bot] c3dbba44c8 style: auto-fix formatting 2026-04-29 14:49:39 -07:00
Sam Julien 3b45398251 fix(showcase): repair @endregion[sample-audio-button] placement broken by region-marker script
The marker-insertion script in ac3885fe0 used a brace counter that
counted opening braces from the destructured function parameters as
the start of the function body, then matched the destructuring's
closing `}` as the body's close. The result on every fw was an
`@endregion[sample-audio-button]` jammed onto the same line as the
destructuring's `}`, with the actual function body falling outside the
region — broken structure plus a format violation (`}// @endregion` on
one line).

Fixes both: strips the broken inline endregion and appends a proper
@endregion marker at end-of-file (which is where the function actually
ends, since these files contain only the single SampleAudioButton
function below the imports + interface). 17 files restored.
2026-04-29 14:49:39 -07:00
Sam Julien 9ac8e0644a docs(showcase): switch voice from siblings to region markers in actual demo source
Prior commit (878259e20) deployed sibling .snippet.* files for voice across
all 18 frameworks. That was the wrong call — siblings are a *fallback* for
demos that legitimately diverge from the canonical teaching shape. The
voice demos in 17 frameworks already match the canonical (V2 runtime +
TranscriptionService + sample-audio-button), so the right move is to tag
region markers on the real source.

Changes:
- 17 frameworks (everything except google-adk): add `@region[…]` markers
  to actual demo source for `voice-runtime`, `transcription-service-guard`,
  `voice-page`, `sample-audio-button`. 51 source files modified, no
  behavioral changes — just `// @region[name]` / `// @endregion[name]`
  comments wrapping existing code.
- crewai-crews/manifest.yaml: add `highlight:` block to the voice demo
  with the route file path so the bundler picks up the runtime regions.
  Every other framework already had this entry.
- 17 frameworks: delete the wrong sibling files (`voice-runtime.snippet.ts`
  and `voice-frontend.snippet.tsx`) that 878259e20 created.
- google-adk: KEEP the two siblings — google-adk genuinely diverges
  (uses the shared `/api/copilotkit` route rather than a dedicated
  `/api/copilotkit-voice`), which is exactly when the sibling fallback
  is the right answer.

Result: snippet audit B-docs-gap = 0; every framework's voice page
renders real demo code via `<Snippet>` refs. The 16 standard frameworks
pull from their actual route.ts / page.tsx / sample-audio-button.tsx;
google-adk pulls from its sibling.
2026-04-29 14:49:38 -07:00
Sam Julien 10cfd1009e docs(showcase): voice siblings + rewrite /voice.mdx to use <Snippet> refs
The first pass of /voice.mdx had inline code blocks. Rewrites the page
to use <Snippet> references against per-framework sibling files, matching
how the rest of shell-docs sources its code samples.

- Two siblings per framework (×18 fws = 36 files):
  - voice-runtime.snippet.ts: V2 CopilotRuntime + TranscriptionService
    setup, including the GuardedOpenAITranscriptionService wrapper that
    returns a clean 4xx when OPENAI_API_KEY is missing. Regions:
    `voice-runtime`, `transcription-service-guard`.
  - voice-frontend.snippet.tsx: chat surface with auto-mic-button, plus
    the SampleAudioButton that bypasses the mic for Playwright /
    screenshot flows. Regions: `voice-page`, `sample-audio-button`.
- /voice.mdx now uses 4 `<Snippet region="..." />` refs instead of
  inline code, so the docs reference real teaching code that lives next
  to each framework's actual demo (and stays in sync with the established
  per-framework sibling convention from PR #4439).
2026-04-29 14:49:38 -07:00
Sam Julien 63005ec842 chore(showcase/integrations): drop final stale null overrides for now-canonical features
5 cells unblocked by removing per-framework null overrides that were
overriding the canonical defaults landing in the companion commit:

- google-adk: drop nulls for voice, byoc-hashbrown, byoc-json-render
  (canonicals now wired in feature-registry).
- langgraph-python: drop nulls for voice, byoc-hashbrown,
  byoc-json-render (same).

After this commit, no framework has a stale `null` override for any
documented feature. The remaining intentional opt-outs (subagents on 4
fws) keep their existing nulls because they're genuinely framework-
specific decisions, not stale config.
2026-04-29 14:49:38 -07:00
Sam Julien bbc658a521 chore(showcase/integrations): drop stale null overrides for now-canonical features
7 cells unblocked by removing per-framework null overrides that were
overriding working canonical defaults:

- google-adk: drop nulls for `chat-customization-css`, `subagents`,
  `multimodal` (canonicals already wired), and the now-canonical
  `agent-config` + `auth` (added in companion commits). `voice`,
  `byoc-hashbrown`, and `byoc-json-render` kept null pending PDX-85,
  PDX-88, PDX-89.
- langgraph-python: drop nulls for `multimodal` + `agent-config` (now
  resolvable via canonical defaults). `voice` + `byoc-*` kept null
  pending the same tickets.
2026-04-29 13:25:52 -07:00
Sam Julien 933d37150b chore(showcase): introduce agent_config_pattern + auth_pattern manifest flags
Adds two new manifest pattern flags (matching the existing
`interrupt_pattern` / `a2ui_pattern` convention) so the canonical
`/agent-config` and `/auth` shell-docs pages can gate their per-pattern
sections via `<WhenFrameworkHas>` and only render the implementation that
applies to the framework the user has selected.

- `agent_config_pattern: shared-state | runtime-properties | null`
  - `runtime-properties` (1 fw): built-in-agent
  - `shared-state` (17 fws): everything else that wires agent-config

- `auth_pattern: langgraph | ag2-context-variables | microsoft-agent-framework | runtime-onrequest | null`
  - `langgraph` (3 fws): langgraph-python, langgraph-typescript, langgraph-fastapi
  - `ag2-context-variables` (1 fw): ag2
  - `microsoft-agent-framework` (2 fws): ms-agent-python, ms-agent-dotnet
  - `runtime-onrequest` (12 fws): everything else

Also fills in the previously-missing `a2ui_pattern` flag on 6 frameworks
that have wired demos but were rendering near-empty doc pages because
none of the existing `<WhenFrameworkHas>` gates matched. Audit-driven:
ag2/agno/claude-sdk-{python,typescript}/langroid use schema-loading;
built-in-agent uses schema-inline.
2026-04-29 13:25:02 -07:00
Sam Julien 54fe66467e chore(showcase/integrations): correct cell docs links across frameworks
Audit-driven corrections to per-framework docs-links.json so every
supported (wired/stub) cell on the dashboard resolves to a real
shell-docs page and a non-stale OG URL. Result: 545 → 613 cells fully
working; remaining 78 cells are known docs gaps tracked separately
(voice → PDX-85; auth/agent-config/byoc-* across frameworks where no
canonical page exists).

- built-in-agent: drop 6 stale `/features/*` OG overrides retired by
  the IA reorg. Cells now inherit canonical OGs that still exist on
  docs.copilotkit.ai (`/human-in-the-loop`, `/generative-ui/...`,
  etc.).
- langgraph-python: fix `auth` OG (`/langgraph/authentication` →
  `/langgraph/auth`) + add framework-specific shell override (`/auth`
  resolves to `integrations/langgraph/auth.mdx`). Null `voice` and
  `byoc-hashbrown` OGs that pointed to retired pages.
- google-adk: replace 27 `shell_docs_path: null` opt-outs with
  explicit canonical paths so cells route to real shell-docs pages
  (mix of canonical root + adk-specific overrides). The original
  rationale ("shell does not have a google-adk-scoped docs tree") is
  now stale — shell-docs has an `integrations/adk/` tree (11 pages),
  and the rest resolve via canonical inheritance. Also fix two retired
  a2ui sub-paths (dynamic-schema/fixed-schema) that are now combined
  on a single `/adk/generative-ui/a2ui` page on docs.copilotkit.ai.
- ag2 / ms-agent-python / ms-agent-dotnet: add framework-specific auth
  overrides pointing at `/<framework>/auth` on both OG and shell.
2026-04-29 10:31:44 -07:00
Sam Julien 7de5292f1f chore(showcase/integrations): drop stale per-integration shell_docs_path overrides
Two integration docs-links.json files had stale shell_docs_path overrides
that 404'd on shell-docs:

- built-in-agent: 6 entries pointed at /docs/features/<feature> placeholder
  paths that never existed in shell-docs. Removed; the new DocsRow
  fallback inherits the (correct) feature-registry defaults instead.
- langgraph-python: auth + byoc-hashbrown overrides pointed at
  /authentication and /byoc-hashbrown which don't exist. Removed; both
  feature defaults are null (no shell-docs page yet — tracked as
  docs/eng follow-up).

The og_docs_url overrides on each are unchanged. Net effect: the 8
previously-broken shell-docs links per the dashboard now either resolve
cleanly via inherited defaults (built-in-agent's 6) or surface the
honest 'no page yet' state (langgraph-python's 2).
2026-04-29 09:22:26 -07:00
Sam Julien 7699e95166 chore(showcase): manifest a2ui_pattern + interrupt_pattern field values
Sets the per-framework values that drive the new <WhenFrameworkHas>
gating on /generative-ui/a2ui/fixed-schema and /human-in-the-loop/* docs
pages.

  a2ui_pattern values:
    schema-loading — backend loads schema from JSON at startup
                     (langgraph-python/typescript/fastapi, llamaindex,
                      crewai-crews, pydantic-ai, ms-agent-python,
                      google-adk)
    schema-inline  — backend defines schema inline in code
                     (spring-ai, ms-agent-dotnet)
    llm-driven     — backend generates schema dynamically per request
                     (mastra, strands)
    omit           — cell unshipped for the framework

  interrupt_pattern values:
    native        — framework has interrupt() primitive
                    (langgraph-python/typescript/fastapi)
    promise-based — demo uses useFrontendTool + Promise resolution
                    (ms-agent-python, ms-agent-dotnet)
    omit          — cells unshipped for the framework

Same commit also closes a presentation gap on the shell-dashboard
drilldown by adding the missing a2ui sibling files to highlight: lists:
- strands: catalog.ts, definitions.ts, renderers.tsx
- crewai-crews: same three
- google-adk: definitions.ts
2026-04-29 08:15:15 -07:00
Alem Tuzlak cd91555095 Merge remote-tracking branch 'origin/main' into docs/langgraph-python-demo-readmes
# Conflicts:
#	showcase/integrations/ag2/src/app/demos/a2ui-fixed-schema/README.md
#	showcase/integrations/ag2/src/app/demos/agentic-chat-reasoning/README.md
#	showcase/integrations/ag2/src/app/demos/chat-slots/README.md
#	showcase/integrations/ag2/src/app/demos/declarative-gen-ui/README.md
#	showcase/integrations/ag2/src/app/demos/frontend-tools-async/README.md
#	showcase/integrations/ag2/src/app/demos/headless-complete/README.md
#	showcase/integrations/ag2/src/app/demos/hitl-in-app/README.md
#	showcase/integrations/ag2/src/app/demos/hitl-in-chat/README.md
#	showcase/integrations/ag2/src/app/demos/mcp-apps/README.md
#	showcase/integrations/ag2/src/app/demos/readonly-state-agent-context/README.md
#	showcase/integrations/ag2/src/app/demos/reasoning-default-render/README.md
#	showcase/integrations/ag2/src/app/demos/tool-rendering-custom-catchall/README.md
#	showcase/integrations/ag2/src/app/demos/tool-rendering-default-catchall/README.md
#	showcase/integrations/ag2/src/app/demos/tool-rendering-reasoning-chain/README.md
#	showcase/integrations/claude-sdk-python/src/app/demos/headless-simple/README.md
#	showcase/integrations/claude-sdk-python/src/app/demos/prebuilt-popup/README.md
#	showcase/integrations/claude-sdk-python/src/app/demos/prebuilt-sidebar/README.md
#	showcase/integrations/crewai-crews/src/app/demos/beautiful-chat/README.md
#	showcase/integrations/langgraph-fastapi/src/app/demos/gen-ui-interrupt/README.md
#	showcase/integrations/langgraph-fastapi/src/app/demos/interrupt-headless/README.md
#	showcase/integrations/langgraph-python/src/app/demos/shared-state-read-write/README.md
#	showcase/integrations/langgraph-python/src/app/demos/shared-state-read/README.md
#	showcase/integrations/langgraph-python/src/app/demos/shared-state-streaming/README.md
#	showcase/integrations/langgraph-python/src/app/demos/subagents/README.md
#	showcase/shell-docs/src/data/demo-content.json
#	showcase/shell-dojo/src/data/demo-content.json
#	showcase/shell/src/data/demo-content.json
#	showcase/shell/src/data/registry.json
2026-04-29 16:27:56 +02:00
Jordan Ritter 17e7e0a406 fix(showcase): add missing D5 demo entries and feature IDs to manifests
Add demo entries for hitl, hitl-in-app, hitl-in-chat, tool-rendering,
shared-state-read-write, and gen-ui-tool-based across 14 integrations.
Ensure every demo ID also appears in the features list so the showcase
matrix and D5 probes discover them correctly.
2026-04-28 22:20:58 -07:00