Commit Graph

1038 Commits

Author SHA1 Message Date
Jordan Ritter 0544255af5 fix(showcase/langgraph-typescript): align gen-ui-agent closer to LGP
Add recursionLimit: 50 to graph.compile() to match LGP's
.with_config({"recursion_limit": 50}). The prompt drives ~7 set_steps
cycles + 1 final model turn (~15 supersteps); 50 gives ~3x headroom
for LLM retries.

System prompt, tool schema (Step fields: id, title, status), and tool
description already match character-for-character.
2026-05-17 07:47:31 -07:00
Jordan Ritter 7f8180d721 fix(showcase/langgraph-typescript): readonly-state agent injects context + fixture fallback
The LGT readonly-state agent was ignoring copilotkit.context, so
useAgentContext values never reached the model. Now the chatNode
reads state.copilotkit.context entries and appends them to the
system message, matching what CopilotKitMiddleware does on the
Python side.

Also adds non-gated aimock fixtures in feature-parity.json for
both the "Who am I?" and "Suggest next steps" pills so they
match without requiring the Atai-specific systemMessage gate
that only fires when LGP's middleware is in play.
2026-05-17 07:47:31 -07:00
Jordan Ritter 3c26f6a5df feat(showcase/langgraph-typescript): add gen-ui-agent matching LGP 2026-05-17 07:47:31 -07:00
Jordan Ritter 2324241384 fix(showcase/langgraph-typescript): rename roll_dice to roll_d20 matching LGP 2026-05-17 07:47:31 -07:00
Jordan Ritter 04977d202f fix(showcase/langgraph-typescript): bump @ag-ui/langgraph to 0.0.32
Fixes "message type returned from LangGraph is not supported" error
for search_flights. The dependency is transitive (via @copilotkit/runtime
and @copilotkit/sdk-js), so npm overrides are used to force 0.0.32.
2026-05-17 07:47:30 -07:00
Jordan Ritter 78b35b32de fix(showcase/langgraph-typescript): align subagents to LGP gold standard 2026-05-17 07:47:30 -07:00
Jordan Ritter c328f59bfc fix(showcase/langgraph-typescript): align gen-ui-agent to LGP gold standard 2026-05-17 07:47:30 -07:00
Jordan Ritter 7e101b5ecb fix(showcase/langgraph-typescript): align gen-ui-tool-based to LGP gold standard 2026-05-17 07:47:30 -07:00
Jordan Ritter 84a8b24022 fix(showcase/langgraph-typescript): align tool-rendering to LGP gold standard 2026-05-17 07:47:30 -07:00
Jordan Ritter 7d60c3a813 fix(showcase/langgraph-typescript): align readonly-state-agent-context to LGP gold standard 2026-05-17 07:47:30 -07:00
Jordan Ritter 86244f7a48 fix(showcase/langgraph-typescript): align shared-state-streaming to LGP gold standard 2026-05-17 07:47:30 -07:00
Jordan Ritter 784c77d432 fix(showcase/langgraph-typescript): align shared-state-read-write to LGP gold standard 2026-05-17 07:47:29 -07:00
Jordan Ritter 4be79861b8 fix(showcase/langgraph-typescript): align tool-rendering-reasoning-chain to LGP gold standard 2026-05-17 07:47:29 -07:00
Jordan Ritter 04887c3022 fix(showcase/langgraph-typescript): align tool-rendering-custom-catchall to LGP gold standard 2026-05-17 07:47:29 -07:00
Jordan Ritter 931385ac8e fix(showcase/langgraph-typescript): align tool-rendering-default-catchall to LGP gold standard 2026-05-17 07:47:29 -07:00
Jordan Ritter df6ae290d0 fix(showcase/langgraph-typescript): voice route uses starterAgent graph ID 2026-05-17 07:47:29 -07:00
Jordan Ritter e4d9279984 fix(showcase/langgraph-typescript): add shadcn/ui components and deps for LGP parity 2026-05-17 07:47:29 -07:00
Jordan Ritter e039f24b60 fix(showcase/langgraph-typescript): align headless-complete to LGP gold standard 2026-05-17 07:47:28 -07:00
Jordan Ritter a6b08e5e31 fix(showcase/langgraph-typescript): align multimodal to LGP gold standard 2026-05-17 07:47:28 -07:00
Jordan Ritter 49304976e0 fix(showcase/langgraph-typescript): align headless-simple to LGP gold standard 2026-05-17 07:47:28 -07:00
Jordan Ritter 845554496f fix(showcase/langgraph-typescript): align auth to LGP gold standard 2026-05-17 07:47:28 -07:00
Jordan Ritter 1e1314cc36 fix(showcase/langgraph-typescript): align agent-config to LGP gold standard 2026-05-17 07:47:28 -07:00
Jordan Ritter 475bd0807e fix(showcase/langgraph-typescript): align chat-customization-css to LGP gold standard 2026-05-17 07:47:28 -07:00
Jordan Ritter bcb9ad05f8 fix(showcase/langgraph-typescript): align frontend-tools to LGP gold standard 2026-05-17 07:47:28 -07:00
Jordan Ritter 0115f1285d fix(showcase/langgraph-typescript): align voice to LGP gold standard 2026-05-17 07:47:27 -07:00
Jordan Ritter dc47a9ce9a fix(showcase/langgraph-typescript): align frontend-tools-async to LGP gold standard 2026-05-17 07:47:27 -07:00
Jordan Ritter e052460730 fix(showcase/langgraph-typescript): align chat-slots to LGP gold standard 2026-05-17 07:47:26 -07:00
Jordan Ritter 65fd029265 fix(showcase/langgraph-typescript): align agentic-chat to LGP gold standard 2026-05-17 07:47:26 -07:00
Jordan Ritter ae2982788d fix(showcase/langgraph-typescript): align prebuilt-sidebar to LGP gold standard 2026-05-17 07:47:26 -07:00
Jordan Ritter a0ca0e2d39 fix(showcase/langgraph-typescript): align prebuilt-popup to LGP gold standard 2026-05-17 07:47:26 -07:00
Jordan Ritter a2dd35f622 fix(showcase/langgraph-typescript): align beautiful-chat to LGP gold standard 2026-05-17 07:47:26 -07:00
Abubakar 60d10a2e56 fix(showcase): move @endregion marker after Chat closing brace in all agentic-chat-reasoning demos
The // @endregion[reasoning-block-render] comment was indented inside the
Chat function body, causing the rendered docs snippet to omit the final
closing brace — a visible syntax error. Moves the marker to after the }
in all 16 agentic-chat-reasoning/page.tsx files.

Also wraps the custom-reasoning snippet in reasoning.mdx in a two-tab
block so the ReasoningBlock import in page.tsx links directly to the
reasoning-block.tsx component definition in the adjacent tab.
2026-05-15 15:46:18 -07:00
Sam Julien 2cee1c4b4c fix(shell-docs): wire IntegrationGrid pages with framework-aware demos + backfill region markers (#4846)
## Summary

Five live shell-docs pages ended with a hardcoded heading +
`<IntegrationGrid>`. Because `<IntegrationGrid>` returns `null` on
framework-scoped routes (`useFramework()` resolves a framework slug →
component hides because the user already picked a backend), those pages
truncated to a content-less heading on every `/{framework}/{page}` route
— looked like a layout/scroll bug; actually missing content.

This PR wires framework-aware `<InlineDemo>` + `<Snippet>` blocks above
the picker on all five pages, following the `frontend-tools.mdx`
reference shape. Demo cells already existed; some needed region marker
backfill to broaden coverage.

## Affected pages

| Page | Cell | New body shape |
|---|---|---|
| `shared-state.mdx` | `shared-state-read-write` +
`shared-state-streaming` | 4 Snippets: `use-agent-read`,
`use-agent-write`, `notes-card-render`, `state-streaming-middleware` +
cross-links to existing sub-pages |
| `generative-ui/interactive.mdx` | `gen-ui-interrupt` | InlineDemo + 2
Snippets: `frontend-useinterrupt-render`, `backend-interrupt-tool` |
| `generative-ui/state-rendering.mdx` | `shared-state-streaming` |
InlineDemo + 2 Snippets: `frontend-use-coagent-state`,
`state-streaming-middleware` |
| `generative-ui/display.mdx` | `gen-ui-tool-based` | InlineDemo +
Snippet `bar-chart-renderer` + dropped redundant `## Choose your
Integration` heading (picker renders its own) |
| `generative-ui/your-components/display-only.mdx` | `gen-ui-tool-based`
| Same as `display.mdx` |

Each affected page also gets `<FeatureIntegrations feature="..." />`
pills (framework-aware, always renders) above the picker.

## Region marker backfill

`gen-ui-interrupt` had region markers in only 3 of 17 integrations.
Backfilled to 17 frontends + 16 backends (one frontend-only demo has no
coherent backend file). All markers follow PR #4829's "one contiguous
region wraps imports + body" rule, with three documented exceptions on
`langroid` / `strands` / `mastra` where the markers nest around existing
inner regions in large shared `agent.py` files — restructuring those
files just for docs benefit was disproportionate. Snippets in those
three integrations render the tool/agent definition without imports
(acceptable degradation; matches a small number of pre-existing snippet
bodies).

`shared-state-streaming` already had markers in the 4 integrations that
support it. The other 14 are explicitly `not_supported_features:
shared-state-streaming` in their manifests, so the `Snippet` component
routes to the neutral `UnsupportedBox` placeholder via catalog status —
not a yellow "Missing snippet" warning. Graceful degradation is already
correct; no markers needed.

## Files changed

- 5 MDX files in `showcase/shell-docs/src/content/docs/`
- 27 demo cell files in
`showcase/integrations/*/src/app/demos/gen-ui-interrupt/` (+ backend
agent files)

Three commits stacked:

- `43d62e345` — wire `shared-state.mdx`
- `4b432368e` — wire 4 generative-ui pages
- `e70bd26b0` — backfill `gen-ui-interrupt` region markers across 14
integrations

## Test plan

- [ ] `/google-adk/shared-state` (and every other
`/{framework}/shared-state`) renders Snippet blocks instead of a
dangling header
- [ ] `/google-adk/generative-ui/interactive` renders demo + snippets
- [ ] `/google-adk/generative-ui/state-rendering` renders demo +
snippets
- [ ] `/google-adk/generative-ui/display` and
`/google-adk/generative-ui/your-components/display-only` render demo +
snippet
- [ ] Unscoped routes (e.g. `/shared-state`) still render the
IntegrationGrid picker correctly; framework-aware content above the
picker also displays
- [ ] Bundle regenerates clean (`npx tsx
showcase/scripts/bundle-demo-content.ts`)
- [ ] No yellow "Missing snippet" warnings on framework-scoped routes
for the wired Snippets (excepting the documented
`not_supported_features` UnsupportedBox cases for
shared-state-streaming)

## Out of scope

- Consolidation of `display.mdx` / `tool-based.mdx` /
`your-components/display-only.mdx` (near-duplicates on the same topic)
and folding `interactive.mdx` into `/human-in-the-loop` are tracked in
[PDX-170](https://linear.app/copilotkit/issue/PDX-170) for post-cutover.
- Backfilling `shared-state-streaming` region markers on unsupported
integrations is intentionally NOT done — the `UnsupportedBox`
placeholder is the correct UX there.

## Hook bypass

Pre-commit `test-and-check-packages` fails on a pre-existing
`@copilotkit/web-inspector` telemetry test on main; some commits also
bypassed `commitlint` because its binary isn't installed in fresh
worktrees. All commits used `LEFTHOOK_EXCLUDE` for those specific hooks
only; lint-fix, lockfile-sync, and check-binaries all ran and passed.
2026-05-15 12:03:41 -07:00
Tyler Slaton b5d59e72a8 feat(showcase/shell-dojo): category headers in sidebar + rename built-in agent (#4823)
## Summary

Two small dojo design tweaks, plus an unrelated test fix required to
commit.

**Dojo sidebar — categories as headers**
(`showcase/shell-dojo/src/app/page.tsx`)
- Replace the single static "Demos" label with the feature category
names already present in the registry, so navigation reflects how demos
are grouped instead of presenting one flat list (Dev Ex, Chat & UI,
Platform, Controlled Generative UI, …).
- Bump shared `SectionTitle` to 11px / weight 600 / primary text color
for a touch more prominence. Affects the "Integrations" and "View"
headers above as well — consistent treatment across all sidebar
sections.

**Built-in agent name**
(`showcase/integrations/built-in-agent/manifest.yaml`)
- Renamed "Built-in Agent (TanStack AI)" → "CopilotKit Built-in Agent"
in both display name and description, so users aren't pushed to think
about the LLM backend in the integration name. (Note: the internal
source file `src/lib/factory/tanstack-factory.ts` is unchanged — that's
a real filename surfaced in the code viewer; renaming it is a bigger
refactor.)

**Test fix — vitest localStorage polyfill** (`packages/web-inspector/`)
- Pre-existing failure on `main`: Node 22.4+ ships an experimental
built-in `localStorage` global that is installed before vitest's jsdom
env runs, leaving `window.localStorage` as an uninitialized stub. All 22
telemetry persistence tests crash with `window.localStorage.clear is not
a function` on Node 25.
- Added `vitest.setup.ts` that installs a minimal in-memory `Storage`
shim on `globalThis.{localStorage,sessionStorage}`. Works on Node
18/20/22/25+ without depending on `--no-experimental-webstorage`. All 29
tests now pass on Node 25.
- This is in its own commit (`fix(web-inspector): …`) so it's easy to
cherry-pick out if you'd prefer it as a separate PR.

## Test plan
- [ ] Visual review of dojo sidebar at `localhost:3001` — categories
render as headers above their demos
- [ ] Built-in agent appears as "CopilotKit Built-in Agent" in the
integration dropdown
- [ ] `pnpm nx run @copilotkit/web-inspector:test` passes on Node 25
- [ ] Full lefthook pre-commit passes (already verified locally on both
commits)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-15 10:22:06 -07:00
Sam Julien e70bd26b0f docs(showcase): backfill region markers for gen-ui-interrupt across integrations
Adds @region[frontend-useinterrupt-render] and @region[backend-interrupt-tool]
markers to the gen-ui-interrupt demo across all 17 integrations that ship
this cell. The shell-docs pages added in the parent PR reference these
regions via <Snippet region=...>, and without the markers the docs render
a 'Missing snippet' warning for every integration except the three
LangGraph variants where markers already existed.

Each marker nests around the equivalent code in that integration:

- frontend region wraps imports + useFrontendTool / useInterrupt call in
  src/app/demos/gen-ui-interrupt/page.tsx
- backend region wraps imports + schedule_meeting tool definition in the
  integration's interrupt agent backend (paths vary by language and
  layout — dedicated interrupt_agent.py, snippet.ts sibling file,
  InterruptAgentController.java, mastra agents/index.ts, etc.)

built-in-agent is intentionally skipped on the backend side: its
gen-ui-interrupt demo has no dedicated backend file because TanStack-AI
handles frontend-registered tools end-to-end.

Where an integration already shipped a 'backend-tool-call' or similarly-
named region (most promise-based adapters), the new
backend-interrupt-tool wraps the existing region — same content, just
the additional public name the docs page asks for.

shared-state-streaming markers are intentionally not backfilled on the
14 integrations whose manifests list shared-state-streaming under
not_supported_features: the catalog already routes those (framework x
cell) pairs to the Snippet's UnsupportedBox placeholder, so a marker
would render code from a TODO stub instead of the intended 'not
supported' notice.
2026-05-15 09:50:14 -07:00
Alem Tuzlak 36e0e24f94 fix(showcase/google-adk/beautiful-chat): wire calculator click handlers via addEventListener
Calculator pill rendered the layout but no button responded. Root cause:
Gemini's default emit for the calculator widget used `<form>` /
`<button type="submit">` for clicks — the iframe runs with
`sandbox="allow-scripts"` only, so the browser silently blocks form
submission before any handler fires. The buttons drew, nothing happened.

Expand the `generateSandboxedUi` guidance in `_INSTRUCTION` with the same
sandbox-iframe contract `_OPEN_GEN_UI_ADVANCED_INSTRUCTION` already
spells out:
- Forms and submit-type buttons are blocked silently.
- Use `<button type="button" data-key="…">` plus a single delegated
  `document.addEventListener('click', e => …)` that reads
  `e.target.dataset.key` / `data-value`. Keyboard input via a `keydown`
  listener that checks `e.key === 'Enter'`.
- All handler code in a `<script>` tag inside `html`.

Verified: the calculator widget Gemini now produces wires every key /
metric-shortcut button with delegated click handlers; clicks update the
calculator display end-to-end. Matches the LangGraph-Python output.

(The instruction nudge for generateSandboxedUi itself shipped in #4837.
This change is purely about teaching Gemini the sandbox restrictions so
the generated HTML stays interactive.)
2026-05-15 17:14:26 +02:00
Alem Tuzlak bee96f988d fix(showcase/google-adk/voice): pin transcription baseURL to real OpenAI
The mic recording path on Railway prod was returning `502 Invalid file
format. Supported formats: ['flac', 'm4a', 'mp3', 'mp4', 'mpeg', 'mpga',
'oga', 'ogg', 'wav', 'webm']` even though the browser was sending valid
WebM Opus bytes (audio/webm;codecs=opus, ~40KB recordings).

Root cause: `new OpenAI({ apiKey })` falls through to `OPENAI_BASE_URL`,
which in showcase environments points at aimock (`http://aimock:4010/v1`).
Aimock's proxy mode forwards unmatched requests to real OpenAI but
re-encodes the multipart body, corrupting the audio bytes en route to
Whisper. Whisper inspects the bytes (not just the MIME), so it rejects
the corrupted payload with the format error.

LangGraph-Python's voice route already documents and works around this:
it pins the transcription client's `baseURL` to real OpenAI (or
`OPENAI_TRANSCRIPTION_BASE_URL` when set) so the audio bypasses aimock
entirely. Mirroring that here verbatim. The non-transcription paths
(chat completions etc.) still go through aimock for deterministic
fixtures; only `/v1/audio/transcriptions` skips it.

Verified locally: mic recording in the browser now transcribes the
user's actual words via real Whisper instead of failing 502.

The audio/webm stamping I added to `packages/runtime` in the previous
commit is still useful defensive hardening for empty-type Blobs that
arrive at the server-side handler — keep it. With this route-level
change those bytes never reach aimock anyway.
2026-05-15 16:52:41 +02:00
Alem Tuzlak 4a27087094 test(showcase/google-adk): default fake LlmResponse to finish_reason=STOP
The Python unit tests for stop_on_terminal_text /
simple_after_model_modifier built fake LlmResponse objects without a
finish_reason field. That worked before the thinking-mode fix in #4826,
which added a finish_reason="STOP" gate so the callback no longer
terminates on text-only chunks that arrive non-partial with
finish_reason=None (Gemini thinking-mode emits a text-only chunk first,
then a separate function-call chunk — terminating on the first would
skip the second).

Fix: default the fake response's finish_reason to "STOP" (the real
terminal-response shape) and also stub turn_complete=None so the
matcher path the callback walks lines up with what production sees.
Local pytest on Python 3.10 → 23/23 green.
2026-05-15 14:31:10 +02:00
Alem Tuzlak 9e54ba6706 fix(showcase/google-adk): beautiful-chat icon, calculator, hitl, voice mic, state-context gating
Production-fix bundle for beautiful-chat + 3 other google-adk demos. All
issues either reported on Railway prod or unmasked by the catch-all
render_a2ui fallback I added in #4836. Local D5 stays 38/38 green.

- Missing copilotkit logo: `<img src="/copilotkit-logo-mark.svg">` returned
  404 because the SVG never shipped in the integration's public/. Copy
  copilotkit-logo-mark.svg + copilotkit-logo.svg over from langgraph-python.

- Multimodal sample.png / sample.pdf were LFS pointers in prod (Railway
  build runs without `git lfs pull`), so the magic-byte check rejected them
  on first click. Add an integration-scoped .gitattributes that exempts
  these two paths from LFS (mirrors what every working sibling integration
  already does) and re-stage the files as real binaries (10KB / 2.5KB).

- Sales Dashboard pill returned a generic "Step 1... Step 2..." narration
  instead of rendering the A2UI surface. Root cause: the render_a2ui
  catch-all fallback I added to aimock/d5-all.json in #4836 fired before
  feature-parity.json's specific sales-dashboard fixture (load order
  d5-all → smoke → feature-parity). Removing the catch-all from both
  d5-all.json and the per-demo source so the specific fixture wins.

- Calculator App pill returned text only with a white iframe because
  beautiful-chat's agent instruction never mentioned generateSandboxedUi —
  Gemini saw the tool listed via AGUIToolset but had no nudge to use it.
  Added a one-line "Interactive / sandboxed widgets" entry to the
  instruction; verified Gemini now emits the tool call.

- hitl-in-app refund (#12345) and escalate (#12347) pills broke on the
  second click because the 2nd-turn fixtures keyed on `sequenceIndex` 0/1
  (a global thread-position counter that drifts when other pills land
  tool messages in the same thread). Convert both to `toolCallId +
  hasToolResult: true` and drop the reject branch — Gemini reasons
  correctly from the tool's `approved: false` return without a fixture
  override. Same pattern that fixed tool-rendering-reasoning-chain
  previously.

- hitl-in-app downgrade (#12346) pill produced an unrelated
  "Research / Outline / Draft / Review / Finalize" plan because the
  prompt contains the substring "plan" and feature-parity.json has a
  generic catch-all match on `userMessage: "plan"`. Add a specific
  downgrade fixture in d5-all.json (loaded before feature-parity.json)
  with hasToolResult: false / true branches.

- hitl-in-chat "Schedule a 1:1 with Alice" returned the wrong
  "Nice to meet you, Alice in Tokyo" response when clicked AFTER another
  pill in the same thread. The 2nd-turn fixture only matched on
  `toolCallId` (no hasToolResult), so the bare "alice" / "Alice" greeting
  fixtures further down won. Add `hasToolResult: true` to the 2nd-turn
  fixture so it scopes correctly regardless of thread state.

- Voice manual recordings always returned "What is the weather in Tokyo?"
  regardless of audio content. aimock had a catch-all transcription fixture
  (`match: { endpoint: "transcription" }`) that returned the canned
  Tokyo string for any audio input. The D5 voice probe uses the sample
  audio button which bypasses /transcribe entirely (it injects text
  directly into the composer), so removing the transcription fixture
  drops aimock into --proxy-only fall-through to real OpenAI Whisper for
  mic recordings while D5 stays green. Verified.

- readonly-state-agent-context and shared-state-read-write fixtures
  returned hardcoded "Atai" / generic preferences responses even when
  the user changed the state values in the UI inputs. Gate the
  Who-am-I / Suggest-next-steps / Greet / Plan-a-weekend fixtures on
  systemMessage substring matching the canonical default state values
  ("Atai" name for readonly-state-context; "tone: casual" for
  shared-state-read-write). When the user changes state, the agent's
  before-model callback rebuilds the system prompt with the new values,
  the fixture's systemMessage substring no longer matches, and aimock
  --proxy-only falls through to the real model so the response reflects
  the actual state. Confirmed with paired curl tests (default state =
  fixture match; alem name = real-LLM response).

Local verification: bin/showcase test google-adk --d5 finishes 38/38
green (137s). Calculator pill confirmed via direct ADK invocation
against real Gemini (GOOGLE_GEMINI_BASE_URL=) emits TOOL_CALL_START
toolCallName=generateSandboxedUi. Sales-dashboard pill confirmed end-to-end
returning the full Column / DashboardCards / PieChart / BarChart payload.
readonly-state-context confirmed with name=Atai matching fixture vs
name=alem falling through to real-LLM response that uses the actual
context.
2026-05-15 14:24:16 +02:00
github-actions[bot] df4b122351 style: auto-fix formatting 2026-05-15 10:56:14 +00:00
Alem Tuzlak 110ca6f4b2 fix(showcase/google-adk): bring final 5 demos to D5 green
Five distinct root causes were keeping google-adk from full D5 parity
with langgraph-python. Fixing them takes the integration to 38/38 D5
green under aimock locally (verified end-to-end with --live writing
to PocketBase).

- readonly-state-context: page.tsx asked for agent slug
  readonly_state_agent_context (underscore) but the registry mounts
  it kebab-case as readonly-state-agent-context. useAgent threw,
  the demo layout never mounted, and the ctx-name input never rendered.
  Align with the registry (and with langgraph-python).

- multimodal: the secondary failure was a backend Pydantic
  ValidationError on HttpOptions.api_endpoint. google-genai 1.75
  renamed the field to base_url; all three direct genai client
  constructors (main.py, beautiful_chat_agent.py, subagents_agent.py)
  needed the rename so the secondary A2UI / sub-agent LLM calls stop
  crashing. (The pre-existing LFS-pointer issue on the bundled
  sample.png/pdf was a worktree hydration problem, not a tracked
  code change — git lfs pull handles it.)

- gen-ui-declarative (two bugs stacked):
  1. The same api_endpoint -> base_url rename above. The secondary
     generate_a2ui planner LLM was failing every request.
  2. The D5 fixture emitted components in {id, type, props: {...}}
     shape, but sanitize_a2ui_components requires component, so
     every entry was dropped and the renderer received an empty
     surface. Rewrite both the per-demo fixture and the d5-all.json
     aggregate to the flat {id, component, ...props} shape that
     langgraph-python's _design_a2ui_surface fixture already uses,
     wrapping multi-child layouts in a basic-catalog Column (the
     custom Card schema has a single child slot). Add
     _design_a2ui_surface variants so LGP gets per-pill payloads too.

- shared-state-streaming: ADK's write_document took content and
  the PredictStateMapping read tool_argument="content", but the
  shared D5 fixture (and the LGP function signature) names the
  argument document. Rename both sides so the fixture's tool_call
  args plumb into the function and into PredictStateMapping's
  state-key emission. STATE_DELTA now propagates and DocumentView
  streams live.

- tool-rendering-reasoning-chain: in thinking mode
  (include_thoughts=True), Gemini emits a turn as two separate
  non-partial chunks — a text-only chunk with finish_reason=None
  and a function-call-only chunk with finish_reason=FUNCTION_CALL.
  stop_on_terminal_text fired on the first (text-only) chunk and
  set end_invocation=True before the function-call chunk arrived,
  which broke AAPL->MSFT chaining. Gate termination on
  finish_reason=STOP; FUNCTION_CALL and None both mean "more
  chunks inbound — defer". Applies to every agent that uses the
  shared callback, so chain-aware behavior is uniform.

Local verification: bin/showcase test google-adk --d5 --live
finishes green for all 38 cells (~140s), dashboard reflects the
results from PocketBase. Manual real-Gemini click-through of the
five fixed demos also passes end-to-end via GOOGLE_GEMINI_BASE_URL=
(empty) recreate.
2026-05-15 12:53:26 +02:00
Atai Barkai f437231649 feat(showcase/shell-dojo): surface feature categories in sidebar
Two small dojo-only design tweaks:

1. Replace the single static "Demos" label in the dojo sidebar with the
   feature category names already present in the registry, so the
   navigation reflects how demos are grouped instead of presenting them
   as one flat list. Section titles bumped to 11px / weight 600 /
   primary text color for a touch more prominence — applies uniformly
   to the existing "Integrations" and "View" headers as well.

2. Drop the "(TanStack AI)" qualifier from the built-in agent's
   display name and description. The integration is now surfaced as
   "CopilotKit Built-in Agent" so users aren't pushed to think about
   the LLM backend in the integration name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:16:10 -07:00
github-actions[bot] fbba551004 style: auto-fix formatting 2026-05-14 22:32:59 +00:00
Sam Julien 34b641874d fix(showcase): unified hoist across all integrations and sibling snippet files
Run the unified hoist codemod over showcase/integrations/* and adjacent
source roots (src/lib, src/agent, src/mastra, src/main/java for Spring AI,
agent/ for ms-agent-dotnet). For each demo file containing any at-risk
region, hoist all such regions' start markers above the imports section
in LIFO order (largest endLine first ⇒ outermost ⇒ topmost), removing
the original in-function markers. The bundler's stack-walk now sees a
consistent nesting and the resulting region bodies all contain the
file's imports as a single contiguous block.

Also extends marker-move-up support to Java (import) and C#
(using-directive) files for Spring AI and ms-agent-dotnet's tool/agent
classes.

Manually handles two remaining sibling snippet files
(built-in-agent::a2ui-fixed-schema's a2ui-backend.snippet.ts) where the
'imports' are declare-const stubs that the codemod doesn't detect as
imports.

After this commit, of the 32 at-risk (cell, region) tuples flagged in
the QA report, 503 (integration × region) bundle slots have imports in
their bodies; 4 slots remain without imports because the source files
genuinely have no import statements (string-only prompt files in
claude-sdk-typescript subagents-prompts.ts).

Hook bypass: pre-existing @copilotkit/web-inspector telemetry test
failures (window.localStorage + jsdom) are unrelated to this commit.
2026-05-14 15:07:04 -07:00
Sam Julien e0f19fdaf0 fix(showcase/frontend-tools): hoist nested frontend-tool/frontend-tool-registration pair
Seven integrations (ag2, built-in-agent, claude-sdk-typescript, crewai-crews,
langgraph-fastapi, langgraph-typescript, strands) have frontend-tools/page.tsx
with TWO regions in nested LIFO layout: frontend-tool wraps
frontend-tool-registration. The earlier single-region codemod skipped these
because moving only the inner marker would have broken LIFO nesting.

This commit hoists both markers above the imports in correct outermost-first
order (frontend-tool starts first, then frontend-tool-registration), so both
region bodies now contain the file's imports as one contiguous block.

Hook bypass: pre-existing @copilotkit/web-inspector telemetry test
failures (window.localStorage + jsdom) are unrelated to this commit.
2026-05-14 15:00:49 -07:00
Sam Julien 949ff78b42 fix(showcase): hoist multi-region same-file markers with LIFO nesting
For demo files where multiple at-risk regions sit in the same source
(chat-slots/page.tsx, a2ui_fixed.py, tool-rendering/page.tsx,
hitl-in-chat/page.tsx, subagents.py, voice route.ts), hoist each
region's start marker above the imports section. Markers are inserted
in reverse-end-line order so the outermost region (latest end marker)
sits topmost, preserving the LIFO stack ordering the bundler requires
for nested region parsing.

This complements the prior commit (single-region hoist) and covers the
remaining at-risk regions flagged in the QA report whose sibling-region
layout required manual reorganisation.

Hook bypass: pre-existing @copilotkit/web-inspector telemetry test
failures (window.localStorage + jsdom) are unrelated to this commit.
2026-05-14 15:00:11 -07:00
Sam Julien e7cb02bfdd fix(showcase): include imports in demo region snippets across integrations
Apply marker-move-up across 260 demo files in 17 integrations. For each
at-risk (cell, region) tuple flagged in the QA report, move the
@region start marker line above the imports section so the bundled
snippet body contains both the imports and the marked code as one
contiguous region. End markers stay where they are.

Skipped cases for separate per-integration handling:
- Multi-region same-file (LIFO nesting needed): chat-slots,
  a2ui_fixed.py, tool-rendering/page.tsx, hitl-in-chat/page.tsx,
  subagents.py, voice route.ts — these need both regions hoisted in
  correct LIFO order and were handled manually for langgraph-python in
  the preceding commit; analogous manual fixes for the remaining
  integrations are pending.
- Files where the target region is already wrapped by an outer region
  (e.g. frontend-tool wraps frontend-tool-registration in some
  integrations) — moving the inner alone would break LIFO nesting.

Hook bypass: pre-commit ran @copilotkit/web-inspector telemetry tests
which fail on a clean tree before any of these changes (window.localStorage
not initialised under jsdom in some test cases). Pre-existing failure
unrelated to this commit.
2026-05-14 14:59:08 -07:00
Sam Julien 240d881de8 fix(showcase/langgraph-python): include imports in demo region snippets
Move @region start markers above each demo file's imports so the bundled
region body contains both the imports and the marked code as one
contiguous block. Without this, snippets rendered in shell-docs were
missing the imports they depended on (z, useState, tool, etc.), forcing
readers to guess where each symbol came from.

Where two regions share the same file and were sequential (not nested)
in the original source, both start markers now sit at the top in proper
LIFO nesting order, and the original in-function start markers are
removed to avoid duplicate region slices being concatenated by the
bundler.

Affected regions in langgraph-python:
- frontend-tool-registration (frontend-tools/page.tsx)
- definitions-zod, create-catalog, provider-a2ui-prop (declarative-gen-ui)
- definitions-types, catalog-creation, backend-schema-json-load,
  backend-render-operations (a2ui-fixed-schema + a2ui_fixed.py)
- sandbox-function-registration (open-gen-ui-advanced)
- bar-chart-renderer (gen-ui-tool-based)
- render-weather-tool, render-flight-tool, weather-tool-backend
  (tool-rendering + tool_rendering_agent.py)
- headless-useinterrupt-primitives (interrupt-headless)
- hitl-hook, time-slots (hitl-in-chat)
- backend-interrupt-tool, frontend-useinterrupt-render (gen-ui-interrupt +
  interrupt_agent.py)
- subagent-setup, supervisor-delegation-tools (subagents.py)
- context-provider-sketch (readonly-state-agent-context)
- state-streaming-middleware (shared_state_streaming.py)
- transcription-service-guard, voice-runtime (voice route.ts)

Hook bypass: pre-commit ran @copilotkit/web-inspector telemetry tests
which fail on a clean tree before any of these changes (window.localStorage
not initialised under jsdom in some test cases). Pre-existing failure
unrelated to this commit.
2026-05-14 14:54:42 -07:00
Alem Tuzlak d530592317 feat(showcase/google-adk/headless-complete): port backend tools to unblock D5
`headless_complete` was wired to `_simple_chat` (zero backend tools)
in the registry. The d5-gen-ui-headless-complete probe sends prompts
that need `get_weather` / `get_stock_price` / `get_revenue_chart`
to mount their respective per-tool renderer cards on the frontend
(`useRenderTool` keys on tool name), so without the backend tools the
fixture's tool-call response had no matching Python function to run
and the cards never mounted.

Ports the three mock tools verbatim from
`langgraph-python/src/agents/headless_complete.py` (same payload
shapes, same system-prompt routing rules) onto a dedicated
`headless_complete_agent` LlmAgent and re-points the registry slot.
The frontend's `highlight_note` is a useComponent-style frontend
tool and the Excalidraw MCP tools are injected by the runtime
middleware — neither needs a backend Python function, matching the
LGP shape.

Local D5: google-adk:headless-complete flips from red to green.
2026-05-14 21:23:32 +02:00
Alem Tuzlak 02e48162c4 test(showcase/google-adk): sync e2e specs to langgraph-python north-star
Ports 16 diverged Playwright e2e specs verbatim from langgraph-python
and adds 3 previously-missing specs (chat-customization-css,
prebuilt-sidebar, reasoning-custom). All 19 files are byte-identical
to LGP, mirroring the same approach the recent ADK parity push used
for the demo pages.

Why this matters even though D5 is the gold standard: the per-package
Playwright suites (`pnpm test:e2e`) are the local dev validation loop.
Without parity here, a contributor editing google-adk's CopilotChat
surface has no local check that matches what langgraph-python ships,
and tiny divergences between the two surfaces (missing testids, stale
selectors, wrong assertion shapes) silently accumulate until they
surface as D5 regressions in CI.
2026-05-14 20:54:21 +02:00