mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
main
143 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f1d55a40f5 |
feat(showcase/langgraph-python): add identity testids and aimock fixtures for readonly-state-agent-context
Add four production-code testids on demo-layout.tsx:
- identity-name on the user-name display
- identity-timezone on the timezone display
- identity-avatar on the first-letter avatar circle
- activity-<slug> on each activity <label>, kebab-case of activity name
These let Playwright lock the identity card against the published
context defaults (Atai, America/Los_Angeles, A) and assert the
default-checked activity rows ("Viewed the pricing page", "Watched
the product demo video") without depending on assistant text.
Add two verbatim-prompt aimock fixtures to showcase/aimock/d5-all.json
for the demo's suggestion pills:
- "What do you know about me from my context?" leading phrase
"I see you're Atai, and you're in the America/Los_Angeles timezone.
Recently, you viewed the pricing page and watched the product demo
video."
- "Based on my recent activity, what should I try next?" leading phrase
"Since you recently viewed the pricing page and watched the product
demo video, ..."
Pinned to the verbatim message bodies so they don't contend with the
showcase-assistant catch-all fixture.
|
||
|
|
f9cef5048d | style: auto-fix formatting | ||
|
|
ebad989855 |
chore(showcase/langgraph-python): manifest, runtime, e2e, cleanup
Cross-cutting changes that don't belong with any one demo: manifest + landing-page tags, runtime route adjustments, e2e + QA notes that follow the demo renames, and a few small cleanups. Manifest (manifest.yaml + src/app/page.tsx tag labels): - Naming convention: every demo uses `Thing: Subthing` (Generative UI: Tool Rendering - Default / Custom Default / Specific; Open Generative UI: Default / Advanced; Shared State: Streaming / Read + Write; Reasoning: Default / Custom; Frontend Tools: In-App Actions / Async; Human in the Loop: In-chat / In-App / Interrupt based; Chat Customization: CSS / Slots; Headless UI: Simple / Complete). - Retags: Auth → `platform`; HITL Step Selection + Interrupt-based → `interactivity`; Reasoning Default + Custom → `chat-ui`; Generative UI: Tools → `generative-ui`. - Renames: Readonly State (Agent Context) → Frontend Context Sharing. - HITL slot points at /demos/hitl-in-chat (working useHumanInTheLoop+interrupt path) instead of the previous /demos/hitl that had no backend `interrupt()` calls. - Highlight paths corrected for the rebuilt headless demos (root-level paths replaced with hooks/, chat/, tools/, attachments/ subdirs). - Descriptions rewritten where they had drifted from the implementation (gen-ui-agent: dropped useCoAgentStateRender claim; headless-simple: shadcn primitives, not raw Tailwind; headless-complete: enumerates the actual hooks wired). Runtime / route: - src/app/api/copilotkit/route.ts — 30 agents registered (incl. the reasoning-custom rename from agentic-chat-reasoning). - copilotkit-mcp-apps/route.ts replaced with [[...slug]]/route.ts so v2 subpath POSTs (/v2/agent/run) resolve. - src/app/api/copilotkit-voice/[[...slug]]/route.ts — env var standardized (was `AGENT_URL || LANGGRAPH_DEPLOYMENT_URL`, now matches the rest of the showcase with just LANGGRAPH_DEPLOYMENT_URL); trailing `/` removed from deploymentUrl. Tests / QA: - e2e specs renamed and paths updated for the demo renames. - qa notes for a2ui-fixed-schema (booked-state checklist removed) and byoc-json-render (Wave 4a residue removed). - docs-links.json key renamed for reasoning-custom. Cleanup: - Removed remaining stub agent.py files in demo dirs (real graphs in src/agents/); removed dead beautiful-chat/components/headless-chat.tsx (zero importers); removed [A2UI-DEBUG] / [A2UI-RESPONSE] print statements from beautiful_chat.py; gpt-5.4-mini → gpt-5-mini typo fix in beautiful_chat.py:249 (would have 4xx'd every model call); stripped iframe-restriction LLM-prompt copy bleed from open-gen-ui-advanced suggestion titles. The convention pass that ran across ~28 demos earlier in this branch is already reflected in their per-demo commits — every page.tsx reads as imports + provider + suggestions hook + JSX, with `useConfigureSuggestions` extracted to a sibling suggestions.ts. |
||
|
|
7a380ecbeb |
feat(showcase/langgraph-python): Platform — Auth + Agent Config
Two demos that showcase how a platform team integrates CopilotKit:
auth gating and runtime config injection.
Auth — defaults UNAUTHENTICATED. First paint is a centered shadcn Card
with the demo token visible (`demo-token-123`) and a "Sign in" button.
<CopilotKit> doesn't mount until the user signs in; clicking the button
stores the token in localStorage and triggers a re-render that mounts
the chat with `Authorization: Bearer <token>` header attached. Reload
preserves the token; sign-out clears it and returns to the card.
Earlier drafts of this demo defaulted to authenticated with a
ChatErrorBoundary + onError-driven banner to recover from <CopilotChat>
's 401-on-mount crash. Both have been removed — gating the chat behind
`isAuthenticated` means it never mounts with bad creds, so the boundary
has no purpose.
Backend route uses `createCopilotRuntimeHandler` from
@copilotkit/runtime/v2 directly because the Next.js adapter does not
forward `hooks`. The `onRequest` hook validates the bearer token and
throws a Response(401) on missing/wrong tokens.
Agent Config — typed knobs (tone / expertise / responseLength) that
change the agent's behavior per turn. Pivoted to `useAgentContext` from
the original `<CopilotKit properties={...}>` transport, which silently
dropped the values in @ag-ui/langgraph 0.0.31 — those payloads landed
at the top level of the LangGraph stream and weren't routed into
RunnableConfig["configurable"]. A prior workaround that repacked them
there triggered LangGraph 0.6's "cannot specify both configurable and
context" 400.
useAgentContext is the supported LangGraph 0.6+ path for "frontend →
agent runtime context." A small ConfigContextRelay component sits inside
the provider and publishes the live toggles. The Python graph collapses
to a single static system prompt with three rulebooks; CopilotKitMiddleware
injects the context entry into the model's prompt automatically.
|
||
|
|
a78e6bddc7 |
feat(showcase/langgraph-python): Shared State + Sub-Agents
Four state-flow demos plus the multi-agent demo, all sharing the
page-as-entry-point convention with extracted suggestions.
- shared-state-streaming (Shared State: Streaming) —
StateStreamingMiddleware(state_key="document", tool="write_document",
tool_argument="document"). The argument name MUST match the state_key
for the partial-JSON streamer to index correctly. Fixed in this pass
(previous version had a name mismatch). Frontend renders `LIVE` badge
+ char counter so per-token streaming is visible.
- shared-state-read-write (Shared State: Read + Write) — bidirectional.
UI writes preferences via `agent.setState`; agent writes notes via a
`set_notes` tool that returns Command(update={...}). PreferencesInjector
middleware reads the state on every turn and injects it as a system
message. CopilotPopup layout, 2-col card UI, "Agent Scratch pad"
copy.
- shared-state-read (deprecated route stub) — kept for back-compat with
any external links; the canonical demo is shared-state-read-write.
- readonly-state-agent-context (Frontend Context Sharing) — frontend
publishes read-only context via useAgentContext (the LangGraph 0.6+
idiom). Backend has tools=[] and only CopilotKitMiddleware; read-only
is enforced by the absence of any state-write tool, not a flag.
- subagents (Sub-Agents) — supervisor + research / writer / critic
sub-agents. Per-tool useRenderTool registrations surface delegation
events to the chat. State has a delegations[] log; the Python side
only writes status="completed" so the type was tightened (dropped
unused "running" / "failed" legs from both Python TypedDict and the
TypeScript shape). Frontend infers active sub-agent from in-flight
tool calls via a defensive structural probe over agent.messages.
|
||
|
|
a7a6a5c6fd |
feat(showcase/langgraph-python): Declarative UI + BYOC + Open Generative UI
A single commit for the "agent-authored UI" cluster — five distinct
strategies, all sharing a common shape (declare a catalog, let the
agent pick + populate components):
- declarative-gen-ui (Declarative UI: A2UI) — A2UI dynamic schema. The
agent calls `generate_a2ui` (not the runtime's auto-injected
`render_a2ui`) which secondary-binds an internal render tool with
forced tool_choice, then returns operations via `a2ui.render(...)`.
Custom catalog (Card / StatusBadge / Metric / InfoRow / PrimaryButton
/ PieChart / BarChart) wired via `a2ui.catalog` on the provider.
- a2ui-fixed-schema (Declarative UI: A2UI Fixed Schema) — fixed
server-side schema. The "Book flight" button is an inert label; the
earlier draft tried a schema swap to a booked-confirmation but the
SDK doesn't yet expose `action_handlers` from Python. Removed
BOOKED_SCHEMA + booked_schema.json since they were dead weight.
Cleaned 8 (props as Record<string, any>) casts down to a single
shared `s()` helper.
- mcp-apps — MCP server-driven UI via activity renderers. The runtime's
`mcpApps.servers` config wires Excalidraw; agent has tools=[] and
the middleware emits activity events that the built-in
MCPAppsActivityRenderer auto-mounts as a sandboxed iframe.
- byoc-hashbrown (Declarative UI: Hashbrown) — streaming structured
output via @hashbrownai/react. Agent prompt locks output to JSON via
`response_format: json_object` with a `{ ui: [{ tag: { props } }] }`
contract. Custom slot override on messageView.assistantMessage parses
the streaming JSON.
- byoc-json-render (Declarative UI: json-render) — streaming hierarchical
JSON UI spec via @json-render/react with a Zod-validated catalog.
Catalog (defineCatalog) + registry (defineRegistry) split keeps the
schema as the single source of truth.
- open-gen-ui (Open Generative UI: Default) — runtime's
`openGenerativeUI` config injects a sandboxed UI tool; design-skill
override steers the agent toward educational visualizations. Built-in
OpenGenerativeUIActivityRenderer auto-mounts.
- open-gen-ui-advanced (Open Generative UI: Advanced) — adds frontend
sandboxFunctions registered on the provider; each Zod-typed handler
is exposed to the iframe via the host bridge. Suggestion titles read
as normal user prompts (no iframe-restriction LLM-prompt copy bleed).
Backends sit at src/agents/{a2ui_fixed,byoc_hashbrown_agent,
byoc_json_render_agent}.py and the MCP runtime at
src/app/api/copilotkit-byoc-hashbrown/route.ts.
|
||
|
|
8ad38cfdf2 |
feat(showcase/langgraph-python): Generative UI tool-rendering family
Five demos exercising the per-tool / catch-all / agent-state rendering
patterns. The three tool-rendering cells share the tool_rendering_agent
graph; they differ only in how the frontend renders the same tool
calls.
- tool-rendering (Tool Rendering - Specific) — per-tool useRenderTool
for get_weather + search_flights, plus a useDefaultRenderTool wildcard
for everything else.
- tool-rendering-default-catchall (Tool Rendering - Default) — single
shadcn-styled wildcard via useDefaultRenderTool. Without registering
*some* renderer the runtime has no `*` entry and tool calls render
invisibly; this demo shows the minimum-viable shape.
- tool-rendering-custom-catchall (Tool Rendering - Custom Default) —
same single-wildcard shape, branded with a custom card.
Backend system prompt (src/agents/tool_rendering_agent.py) defaults to
ONE tool per user question. Chaining is opt-in via a "Chain tools"
suggestion that triggers an explicit-ask exception in the prompt — the
previous default-on-chaining generated extra unsolicited tool-call
cards on every turn.
- gen-ui-tool-based (Generative UI: useComponent) — useComponent for
render_bar_chart + render_pie_chart with Zod schemas; backend has
tools=[] and the runtime injects the tools.
- gen-ui-agent (Generative UI: Agent State) — agent-state-driven step
list. The Python graph plans steps via a `set_steps` tool that
returns Command(update={"steps": …}); the frontend reads via
useAgent({updates: [OnStateChanged]}) + a custom MessageList that
renders steps inside CopilotChat's messageView.children slot.
Removed: src/app/demos/{tool-rendering,gen-ui-agent}/agent.py — TODO
stubs; real graphs live in src/agents/.
|
||
|
|
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.
|
||
|
|
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.
|
||
|
|
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. |
||
|
|
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. |
||
|
|
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).
|
||
|
|
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.
|
||
|
|
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…". |
||
|
|
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) |
||
|
|
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 |
||
|
|
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. |
||
|
|
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.
|
||
|
|
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
|
||
|
|
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. |
||
|
|
f6e184baa8 | style: auto-fix formatting | ||
|
|
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. |
||
|
|
7cbc5ea80e | feat(showcase): hand-rolled suggestion chips + Largest-continent fixture in north-star headless demos | ||
|
|
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
|
||
|
|
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.
|
||
|
|
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).
|
||
|
|
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.
|
||
|
|
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.
|
||
|
|
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"` |
||
|
|
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). |
||
|
|
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. |
||
|
|
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 |
||
|
|
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.
|
||
|
|
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.
|
||
|
|
c3dbba44c8 | style: auto-fix formatting | ||
|
|
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. |
||
|
|
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. |
||
|
|
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).
|
||
|
|
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 |
||
|
|
2fc196aa8b |
fix(showcase): guard preferences-card.tsx against undefined interests
STATE_SNAPSHOT can deliver a Preferences object with interests undefined, crashing .includes(), .filter(), and spread at 4 sites per file. Add (value.interests ?? []) guards across all 17 integrations. |
||
|
|
23a3b24a01 |
feat(showcase/integrations): shared-state-read-write + subagents demos across 15 packages
Adds real working Shared State (Read+Write) and Sub-Agents demos to 15 showcase integrations, mirroring the canonical langgraph-python and google-adk reference implementations. Fills rows previously empty on the showcase coverage dashboard. Packages: ag2, agno, claude-sdk-python, claude-sdk-typescript, crewai-crews, langgraph-fastapi, langgraph-typescript, langroid, llamaindex, mastra, ms-agent-dotnet, ms-agent-python, pydantic-ai, spring-ai, strands. (built-in-agent landed independently on main as PR #4321 — its variant is canonical; this PR no longer touches it.) Per-package deliverables: framework-native backend agents (preferences-injection middleware/callback + set_notes tool; supervisor + 3 sub-agents wired as tools with running -> completed /failed delegation log); frontend page.tsx + preferences-card.tsx / notes-card.tsx for SSRW and delegation-log.tsx for subagents — wired to useAgent({ updates: [OnStateChanged] }); manifest entries; runtime route registration + per-package agent server config; real QA scripts. Includes targeted hardening fixes from a 7-agent code-review loop: - Sub-agent failure paths now correctly emit status: "failed" (previously hardcoded "completed" or unreachable in mastra/strands/langgraph-fastapi/langgraph-typescript/ag2) - Parallel-tool-call delegation race fixed in langgraph-fastapi (Annotated[list, add]) and langgraph-typescript (concat reducer) - Silent data loss eliminated in claude-sdk-python/claude-sdk-typescript/crewai-crews — empty JSON.parse catches now log + emit error events - ms-agent-dotnet set_notes writes to per-thread slot via AsyncLocal - mastra working-memory writes are deterministic via src/mastra/tools/working-memory.ts helper - spring-ai tool-call envelope ids match supervisor's tc.id() and AG-UI event ordering reordered; CopyOnWriteArrayList for parallel-call safety - Stack trace + raw error message leaks scrubbed across 8+ Next.js routes — log server-side with errorId + return generic envelope - Sub-agent calls no longer block event loops in ag2 (asyncio.to_thread), langroid (llm_response_async), pydantic-ai (async run + async tools) - langroid lru_cache cross-request contamination dropped - Numerous smaller items: claude-sdk-python invalid model id, Callable annotation, /health endpoint exposed; crewai-crews supervisor no longer resets delegations every turn; pydantic-ai snapshot uses model_dump() CI fixes folded in: - crewai-crews test_forwarded_props: extend the stubbed ag_ui_crewai.endpoint module to expose add_crewai_flow_fastapi_endpoint and add stub agents.shared_state_read_write / agents.subagents modules - generate-catalog test: bump crewai-crews wired-cell expectation 28 -> 30; replace hardcoded total-wired count with an invariant (wired + stub + unshipped = 737) plus a lower-bound floor - oxfmt run on the qa/shared-state-read-write.md files in mastra + spring-ai Rebased onto latest main (post showcase/packages -> showcase/integrations rename + post built-in-agent landing). Original blitz history preserved at the blitz-pre-rebase-snapshot tag. Known follow-ups (deferred to follow-up PR): - agno sync sub_agent.run() blocks event loop (perf only) - ms-agent-python asyncio thread-fallback fragility - llamaindex initial-state coercion when UI clears state - Manifest highlight audit (langgraph-typescript headless-complete, langgraph-fastapi byoc-* missing route.ts highlights) - agno hitl-in-chat declared in demos but not features; duplicate /demos/hitl-in-chat route - langgraph-typescript server.mjs graphSpec only registers 3 graphs vs 23 in langgraph.json (pre-existing) - mastra hitl legacy demo missing from features list - claude-sdk-python agents/agent.py line 474 also has the legacy claude-opus-4-5 default - PARITY_NOTES vs manifest mismatches for hitl-in-app across spring-ai/agno/ag2 (pre-existing) - spring-ai a2ui-fixed-schema missing from generative_ui list |
||
|
|
a16eaa1b74 |
fix(showcase): repair agent-config (LangGraph 1.x context) + multimodal fixtures
agent-config — empty stream
The /demos/agent-config runtime returned RUN_ERROR on every send. The
existing route wrapper repacked the provider's properties into
forwardedProps.config.configurable.properties so the agent could read
them via RunnableConfig["configurable"]["properties"]. LangGraph 1.x
(deployed langgraph 1.1.x / langgraph-api 0.7.x) now rejects any run
that sends configurable with "Cannot specify both configurable and
context. Prefer setting context alone." because it auto-injects an
empty context and refuses both channels at once.
Switch to LangGraph 1.x's context API: route wrapper repacks user props
onto forwardedProps.context instead, the Python graph defines
context_schema=AgentConfigContext and reads via the
Runtime[AgentConfigContext] parameter, and RunnableConfig is no longer
consulted. Unit tests updated to pass the flat context dict directly.
Add context to RESERVED_FORWARDED_PROPS_KEYS so a caller that
explicitly sets forwardedProps.context is preserved (and merged with
provider-supplied properties) instead of being treated as a user prop
and double-wrapped.
multimodal — PDF "doesn't work"
The multimodal pipeline (legacy-shape rewrite shim → ag-ui-langgraph
converter → _PdfFlattenMiddleware running pypdf) is fine; sample.pdf
extraction shows up correctly in the run state snapshot. The visible
breakage is the aimock fixture file: aimock matches userMessage as a
substring, and the generic "hi" fixture lives early enough to swallow
any prompt containing "this" — including "What is in this PDF?" and
"What is in this image?" — short-circuiting before the request reaches
real OpenAI and returning a generic "I'm your showcase assistant"
greeting that never references the attachment.
Add two more-specific fixtures ("this PDF", "this image") ahead of the
"hi" entry so multimodal prompts return responses grounded in the
bundled samples. The "hi" fixture stays in place so the several E2E
specs that fill literal "hi" still match it.
|
||
|
|
dd06dd89d1 |
refactor(showcase): rename packages/ to integrations/
The showcase framework directories better reflect their role as integration examples rather than distributable packages. Renames showcase/packages/ -> showcase/integrations/ and updates the test docker-compose file reference accordingly. |