Commit Graph

12110 Commits

Author SHA1 Message Date
Sam Julien 40fb09cb77 feat(shell-docs): instrument framework selector with PostHog event
Fires framework_selected when a user picks a framework so the docs
funnel can attribute drop-off to specific frameworks. Net-new event
(no upstream equivalent in docs/).
2026-05-06 15:32:32 -07:00
Sam Julien 5f7974a32d feat(shell-docs): port Open Graph image route + vercel.json
Adds app/og/[...slug]/route.tsx for per-page social-share image
generation, and a vercel.json with maxDuration: 60 on app/og/** so
the Edge function has enough headroom to render OG cards.
2026-05-06 15:32:32 -07:00
Sam Julien b355a9aec0 feat(shell-docs): port docs telemetry stack
Brings PostHog, GA4, HubSpot, Reo.dev, Scarf, and RB2B into shell-docs
with parity to docs/. Adds the client-side PostHog provider with
session-stitched bootstrap and pageview capture, the AnalyticsClient
wrapper that mounts RB2B + GA4 hooks behind a single client boundary,
the Scarf pixel for OSS attribution, and the HubSpot and Reo.dev
scripts.

Renames POSTHOG_PROJECT_KEY to POSTHOG_KEY across shell and shell-docs
middlewares so the env names match the upstream pattern, and env-drives
POSTHOG_HOST with eu.i.posthog.com as the fallback.
2026-05-06 15:32:31 -07:00
Ben Taylor 905d742468 feat(react-core): auto-mounted IntelligenceIndicator + MemoizedCustomMessage memo gating signals (#4632)
## Summary

Stacked on top of #4629. Two commits:

1. **MemoizedCustomMessage memo gating signals** (Friday's WIP, cleaned
in CR loop). Adds three new memo gating signals to
`MemoizedCustomMessage` so custom message renderers stay reactive across
the structural events that affect "is this slot still authoritative?"
decisions:
- `numberOfMessagesInRun` — invalidates when peers stream into the same
run
   - `isInLatestRun` — invalidates when a newer run starts
- `isRunning` (gated on `isInLatestRun`) — invalidates exactly twice per
run on the latest run's slots, preserving the perf-test guarantee that
completed runs' messages skip re-renders during streaming

`CopilotChatMessageView` consolidates per-run metadata
(run-id-by-message, count-by-run, latest-run) into a single `useMemo`
that runs O(n) per render rather than O(n²) per message.

2. **`IntelligenceIndicator` — auto-mounted** "Using CopilotKit
Intelligence" pill, ported from the visuals of
[CopilotKit/Intelligence#155](https://github.com/CopilotKit/Intelligence/pull/155).

## How the indicator works

- `CopilotChatMessageView` mounts `<IntelligenceIndicator>` for every
message slot whenever `copilotkit.intelligence !== undefined`. No
factory, no provider, no `renderCustomMessages` registration — the
caller doesn't add anything.
- The indicator self-gates so only the canonical slot renders a pill:
last message of the latest in-flight run, with at least one tool call
whose `function.name` matches one of `DEFAULT_TOOL_PATTERNS` (currently
`[/^bash$/]`, the Intelligence MCP server's canonical tool).
- "Exactly one pill at any moment" is structural — only one message can
ever satisfy the gates, so each renderer invocation decides
independently and the result is one pill in the DOM.

### Phase machine (per-instance, all timers local)

- `spinner` while `agent.isRunning`
- → `check` after `agent.isRunning` falls (debounced 500 ms to absorb
step-boundary `RUN_FINISHED → RUN_STARTED` blips)
- → `fading` after 800 ms hold
- → `hidden` after 480 ms fade animation

A 200 ms `agent.isRunning` poll closes the AG-UI snapshot-subscriber gap
(subscribers added INSIDE a run never see that run's `onRunFinalized`).

## API

Nothing new for the user. Configure intelligence on your runtime, and
the pill appears.

```tsx
<CopilotKitProvider runtimeUrl="..."><CopilotChat /></CopilotKitProvider>
```

When `/info` returns `intelligence: { wsUrl: ... }`, the gate flips and
the pill auto-mounts on the canonical slot.

## Configurability

Tool-name matching is currently hardcoded to `[/^bash$/]`. If we need
per-instance customization later (a `CopilotKitProvider` prop, or a
`toolPatterns` field on `IntelligenceRuntimeInfo` so the runtime can
declare its own intelligence tools), the constant becomes the fallback.

## Test plan

- [x] `nx run @copilotkit/react-core:test` — **1158 passed**
- [x] `nx run @copilotkit/core:test` — **424 passed**
- [x] `nx run @copilotkit/web-inspector:test` — **7 passed**
- [x] Build: `react-core`, `core`, `web-inspector` clean. Pill CSS
bundled into `dist/v2/index.css` (10 rules + 3 keyframes).

### New test coverage

- 1 walkthrough — Run A → Run B with multiple bash calls; pill follows
the canonical slot through every phase. Setup passes **no
`renderCustomMessages` prop** to prove auto-mount.
- 4 gate tests: last-in-run / in-flight (with phase-machine fade-out) /
latest-run / tool-match.
- 1 intelligence gate — no pill when `copilotkit.intelligence` is
undefined.
- 1 explicit auto-registration assertion — pill renders solely because
intelligence is set, no user setup.

## Caveats

- Tool-name patterns are hardcoded; not yet configurable by the runtime
or the app caller. Easy follow-up if needed.
- The `CopilotChatConfigurationProvider` dependency that
`CopilotChatMessageView` uses for `agentId` / `threadId` (to query
state-manager) is pre-existing and not addressed here — flagged
separately.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-06 16:55:36 -05:00
Sam Julien b8880450b8 fix(docs): redirect active 404s and repair broken snippet links (#4677)
## Summary

- Repairs broken links in 4 shared snippets that were the root cause of
most internal-referrer 404s on docs.copilotkit.ai
- Adds 35 redirects in \`next.config.mjs\` covering every URL with
\`broken_link_accessed\` events from the last 30 days of PostHog data

## Approach

PostHog tracks 404s via the \`broken_link_accessed\` event (see
\`docs/POSTHOG_BROKEN_LINKS.md\`). I queried the last 30 days, grouped
by \`broken_url\`, and split the results into two buckets:

1. **Source-side bugs** — broken links coming from our own MDX. The
biggest offenders were shared snippets (\`copilot-runtime.mdx\`,
\`generative-ui/a2ui.mdx\`, \`generative-ui-specs-overview.mdx\`,
\`backend/ag-ui.mdx\`) that get inlined into many integration pages,
multiplying each broken link across the site. Fixed at source.

2. **External / legacy traffic** — search results, marketing site links,
partner sites. Added redirects.

For URLs without a clean 1:1 destination, every broken path now
redirects to the closest matching concept page (no hard 404s left). Each
ambiguous mapping was validated by reading the candidate destination's
content.

## Categories of redirects added

- \`/generative-ui/specs/*\` → \`/learn/generative-ui/specs/*\` (section
moved)
- \`/premium/{threads,inspector}\` → root equivalents (those pages are
at root, not under \`/premium\`)
- \`/built-in-agent/guides/*\` → renamed pages or section index (the
\`guides/\` prefix was dropped in the 2026-02 restructure)
- \`/learn/direct-to-llm/*\` → \`/built-in-agent\` (namespace removed)
- \`/learn/langgraph/*\` → \`/langgraph/*\` (was never under \`/learn\`)
- \`/deepagents/{prebuilt-components,custom-look-and-feel/*}\` → root
equivalents (deepagents integration is missing these pages — see
follow-up note below)
-
\`/reference/v1/hooks/{useRenderTool,useComponent,useThreads,useInterrupt,useCapabilities}\`
→ \`/reference/v2/hooks/<same>\` (these hooks are new in v2)
- \`/reference/v2/hooks/useCopilotAction\` →
\`/reference/v2/hooks/useFrontendTool\` (renamed)
- \`/whats-new/*\` → \`/learn/whats-new/*\`
- Doubled-prefix paths (\`/agent-spec/agent-spec/wayflow\`, etc.) —
straightforward un-double
- \`/zh/langgraph/deep-agents\` → \`/deepagents\` (no i18n on this site)

## Follow-up worth tracking separately

The \`integrations/deepagents/\` directory is missing several pages that
other integrations have (\`prebuilt-components.mdx\`,
\`custom-look-and-feel/\`, \`premium/\`, etc.). The redirects in this PR
band-aid the symptom; the integration page itself is incomplete vs
siblings.

## Test plan

- [x] Verified each of the 35 former-404 paths returns 308 → final 200
on local \`next dev\`
- [x] Verified rendered HTML on pages that include the fixed snippets
now emits the new link targets
- [x] Confirmed the failing pre-commit test
(\`@copilotkit/sqlite-runner:test\`) is pre-existing on \`main\` and
unrelated to this docs-only change
2026-05-06 12:40:54 -07:00
MalaikaAbb 73c04f8b1f Docs(Deepagents): Removed Checkpointer in Python code snippet 2026-05-06 22:03:39 +05:00
Sam Julien 495c331098 fix(docs): add redirects for active 404s on docs.copilotkit.ai
Adds 35 redirects in next.config.mjs covering every URL with
broken_link_accessed events from the last 30 days of PostHog data.

Categories:
- /generative-ui/specs/* → /learn/generative-ui/specs/* (section moved)
- /premium/{threads,inspector,premium/overview} → root equivalents
- /built-in-agent/guides/* → renamed pages or section index
- /built-in-agent/{human-in-the-loop,generative-ui/state-rendering,
  cookbook/state-machine} → closest matching concept
- /learn/direct-to-llm/* → /built-in-agent (namespace removed)
- /learn/langgraph/* → /langgraph/* (was never under /learn)
- /deepagents/{prebuilt-components,custom-look-and-feel/*} →
  root equivalents (deepagents integration is missing these pages)
- /guides/* with no /built-in-agent/guides equivalent → closest concept
- /reference/v1/hooks/{useRenderTool,useComponent,useThreads,
  useInterrupt,useCapabilities} → /reference/v2/hooks/<same>
  (these hooks are new in v2)
- /reference/v2/hooks/useCopilotAction → useFrontendTool (renamed)
- /whats-new/* → /learn/whats-new/*
- Doubled-prefix paths: /agent-spec/agent-spec/wayflow,
  /langgraph/langgraph/overview, /premium/premium/overview
- /langgraph/persistence/* → /langgraph/advanced/persistence/*
- /zh/langgraph/deep-agents → /deepagents (no i18n on this site)

Verified locally: every former-404 path returns 308 → 200 final.
2026-05-06 09:56:22 -07:00
Sam Julien 75abdb3a40 fix(docs): repair broken links in shared snippets
Several shared snippets linked to paths that no longer exist:
- /generative-ui/specs/* → /learn/generative-ui/specs/* (specs moved)
- /premium/threads → /threads (page is at root, not under /premium)
- /premium/inspector → /inspector (page is at root, not under /premium)

Because these snippets are inlined into many integration pages,
each broken link multiplied across the site and accounted for the
majority of internal-referrer 404s on docs.copilotkit.ai.
2026-05-06 09:56:09 -07:00
Alem Tuzlak b9ecaaaa7d refactor(showcase): split beautiful-chat D5 probe into per-pill family (5 pills) (#4675)
## Summary

Follow-up to #4672. The aggregated multi-turn probe shipped in that PR
hit a CopilotKit v2 quirk on `/demos/beautiful-chat`: only the FIRST
`useComponent` tool call in a conversation paints its component.
Subsequent tool calls emit (the agent's followup content arrives) but
the component never mounts. Reproduced cleanly without any frontend tool
involvement — pie chart turn 1 paints 5 svg circles in seconds, bar
chart turn 2 emits "Bar chart rendered above…" but paints zero recharts
elements.

Splitting into per-pill scripts means each probe gets its own browser
launch — fresh page state, fresh conversation, no `useComponent`
ordering pollution.

`CATALOG_TO_D5_KEY["beautiful-chat"]` maps to all five literals;
`isD5Green` requires every key green for the cell to advance to D5, and
per-pill failure isolation surfaces in PB row names
(`d5:<slug>/beautiful-chat-pie-chart`, etc.) — a regression points
directly at the broken surface in the dashboard drilldown.

## What's covered (5 pills)

| Literal | Surface | Assertion |
|---|---|---|
| `beautiful-chat-toggle-theme` | frontend `toggleTheme` tool |
`html.dark` class flip |
| `beautiful-chat-pie-chart` | controlled gen-UI `pieChart` | `>= 3 svg
circle` |
| `beautiful-chat-bar-chart` | controlled gen-UI `barChart` | recharts
container + `>= 2 .recharts-bar-rectangle` |
| `beautiful-chat-search-flights` | A2UI fixed-schema FlightCards (#4668
path) | `United` / `Delta` / `$349` / `$289` literals |
| `beautiful-chat-schedule-meeting` | HITL `scheduleTime` | picker
mounts → click slot → "Meeting Scheduled" |

All 5 verified locally end-to-end (5/5 pass, fresh page session per
probe).

## What's NOT in this PR (all four documented in
`_beautiful-chat-shared.ts`)

- **Excalidraw Diagram** — depends on `mcp.excalidraw.com` reachability;
turning D5 reliability into a third-party uptime bet is the wrong
tradeoff.
- **Calculator App** — sandboxed iframe makes Playwright assertions
cross-frame fragile; `generateSandboxedUi` is already covered by
`d5-gen-ui-open` on a different demo route, so this would be duplicate
coverage.
- **Sales Dashboard** — `generate_a2ui` → secondary `render_a2ui` chain
renders Metric labels, but `Row`-bound PieChart / BarChart children
don't paint their recharts containers when driven by aimock fixtures.
Live pill click against the same fixture chain shows the inverse symptom
(containers paint, Metric labels go missing). The shape suggests
aimock's non-progressive arg streaming differs from a live LLM in a way
the A2UI binder is sensitive to. Needs a separate aimock or binder
investigation.
- **Task Manager** — backend `manage_todos` dispatches and the agent
emits closing content, but `StateStreamingMiddleware`'s `state.todos`
propagation doesn't populate the App pane TodoList through aimock — same
suspected root cause as Sales Dashboard.

These four are deliberate exclusions, not deferred work. If we want to
add them later, the path is clear (each gets its own
`beautiful-chat-<surface>` literal + probe file + fixture + mapping
entry).

## Architecture

Mirrors the `_hitl-shared.ts` pattern: shared module with DOM helpers +
per-pill assertions, thin individual probe files registering one
`D5FeatureType` each.

- `_beautiful-chat-shared.ts` — `BeautifulChatPage` extends the runner's
`ConversationPage` with `click()`, with the same runtime guard as
`d5-hitl-text-input.ts`. DOM helpers cast `globalThis` to a structural
shape per closure (the harness's tsconfig has `types: ["node"]`, no DOM
lib) — same pattern as `d5-chat-css.ts`'s `probeChatCss`.
- Each fixture uses unique `d5 beautiful-chat probe: ...` substrings;
the multi-stage Schedule Meeting flow uses `hasToolResult` `false →
true` for round disambiguation. No `toolCallId` leakage concern since
each probe runs in its own fresh page session.

## Test plan

- [x] `npx nx run @copilotkit/showcase-harness:typecheck` — clean
- [x] `npx nx run @copilotkit/showcase-shell-dashboard:typecheck` — no
new errors (5 pre-existing test-file errors unchanged)
- [x] `npx nx run @copilotkit/showcase-harness:build` — clean
- [x] `OPS_BASE_URL=stub npm run build` (shell-dashboard) — clean
- [x] `npm test -- --run d5-registry` — 12/12 pass with the 5 new
literals (and the old `beautiful-chat` literal removed from the
registry)
- [x] Local end-to-end: 5/5 probes pass against the local stack via
Playwright (each in its own fresh page session)
2026-05-06 18:55:52 +02:00
Alem Tuzlak fd6f7d418e Merge remote-tracking branch 'origin/main' into fix/showcase-d5-beautiful-chat-followup
# Conflicts:
#	showcase/aimock/d5-all.json
2026-05-06 18:50:39 +02:00
Alem Tuzlak ff4d7efa2a refactor(showcase): split beautiful-chat D5 probe into per-pill family
The aggregated multi-turn probe from #4672 hit a CopilotKit v2 quirk on
/demos/beautiful-chat: only the FIRST useComponent tool call in a
conversation paints its component. Subsequent tool calls emit (the
agent's followup content arrives) but the component never mounts.
Reproduced cleanly without any frontend tool involvement —
pie-chart turn 1 paints 5 svg circles in seconds, bar-chart turn 2
emits "Bar chart rendered above..." but paints zero recharts elements.

The runner can't sidestep this from inside one conversation without a
page.reload() between turns, which the structural Page type doesn't
expose. Splitting into per-pill scripts means each probe gets its own
browser launch — fresh page state, fresh conversation, no useComponent
ordering pollution. CATALOG_TO_D5_KEY maps `beautiful-chat` to all
listed literals; isD5Green requires every key green for the cell to
advance to D5, and per-pill failure isolation surfaces in PB row names.

Coverage in this PR (5 pills):
  - beautiful-chat-toggle-theme   (frontend tool, html.dark flip)
  - beautiful-chat-pie-chart      (controlled gen-UI useComponent)
  - beautiful-chat-bar-chart      (controlled gen-UI useComponent)
  - beautiful-chat-search-flights (A2UI fixed-schema FlightCards)
  - beautiful-chat-schedule-meeting (HITL with slot-click resolution)

All 5 verified locally end-to-end (5/5 pass against the local stack).

Out of scope, intentionally (track in follow-up):
  - Excalidraw     — depends on mcp.excalidraw.com reachability
  - Calculator     — sandboxed iframe; dup of d5-gen-ui-open
  - Sales Dashboard — generate_a2ui → render_a2ui chain renders
                      Metric labels but Row-bound charts don't paint
                      recharts containers under aimock fixtures (live
                      pill against same fixture chain shows the
                      inverse symptom). Suggests aimock's
                      non-progressive arg streaming differs from a
                      live LLM in a way the A2UI binder is sensitive
                      to. Needs separate aimock/binder investigation.
  - Task Manager   — manage_todos dispatches and agent emits closing
                      content, but StateStreamingMiddleware's
                      state.todos propagation doesn't populate the
                      App pane TodoList through aimock — same suspected
                      root cause as Sales Dashboard.

Architecture details:
  - _beautiful-chat-shared.ts factors DOM helpers + per-pill
    assertions, mirroring _hitl-shared.ts's pattern for an extended
    Page type with click() + a runtime guard
  - Each fixture uses unique D5-prefixed userMessage substrings; the
    multi-stage Schedule Meeting flow uses hasToolResult false→true
    for round disambiguation (no toolCallId leakage since each probe
    runs in its own fresh page session)
2026-05-06 18:40:47 +02:00
Alem Tuzlak e3b696c29d feat(showcase-finance-erp): animate chat tool cards on mount (#4631)
## Summary

Replace the abrupt "cut in" with a 300ms fade + slide-from-bottom
entrance on each chat card so they feel connected to the streaming
response instead of popping in.

Follow-up polish on
[#4587](https://github.com/CopilotKit/CopilotKit/pull/4587).

## What changed

Added `animate-in fade-in slide-in-from-bottom-2 duration-300 ease-out`
to the root element of every tool render surface in the chat:

- `ToolCard` — `SpecializedToolCard` and `DefaultToolCard` (covers
`do_research`, `do_projections`, `navigate_and_filter`, dashboard ops,
`render_chat_visual`, etc.)
- `InlineChart` (both placeholder and rendered chart)
- `CashPositionCard` (both placeholder and full card)
- `InventoryReorderCard` (both placeholder and full card)
- `InvoiceApprovalCard` (both placeholder and full card)

## Why this approach

- **`tw-animate-css` is already imported** in
`examples/showcases/deep-agents-finance-erp/src/app/globals.css` — no
new dependencies.
- **Mount-time CSS animation, not Framer Motion** — the cards are
short-lived per turn and don't need orchestration; CSS keyframes resolve
to `animation-name: enter` exactly once on first paint and don't re-fire
on prop transitions, so swapping between `InProgress` and the populated
state stays smooth.
- 300ms `ease-out` matches the rest of the demo's transition timing.

## Test plan

- [x] Chat → "Cash Position" → cards slide+fade in (verified via
`getComputedStyle().animationName === "enter"`, `animationDuration ===
"0.3s"`).
- [x] Same animation fires for `do_research` / `do_projections` tool
cards, inline charts, approval cards, and inventory reorder cards.
- [x] No layout shift or jank in successive turns.
- [ ] Reviewer: visual verification on a non-mac browser if possible
(animation runs on standard CSS, but worth confirming).

## Notes

- No JS/runtime changes. Pure CSS class additions via Tailwind
utilities.
- Decoupled from the HITL fix in
[#4630](https://github.com/CopilotKit/CopilotKit/pull/4630) — landing
this independently is fine.
2026-05-06 18:27:03 +02:00
Alem Tuzlak b460564b7d fix(showcase-finance-erp): wire request_approval HITL through useInterrupt (#4630)
## Summary

The Approve / Reject card in the finance-erp showcase never worked
end-to-end — the card flashed in then vanished and the agent run
finished with the LangGraph checkpoint left in a half-paused state. This
was a pre-existing bug, not introduced by
[#4587](https://github.com/CopilotKit/CopilotKit/pull/4587).

## Why

The agent's `request_approval` tool calls
`copilotkit_interrupt(action="request_approval", args={...})` which
raises a `GraphInterrupt`. LangGraph pauses the run, stores the
interrupt on the checkpoint, and `ag_ui_langgraph` emits a `CUSTOM`
event with `name: "on_interrupt"` carrying the approval payload. Then
the run finalizes (`RUN_FINISHED`).

The frontend was using `useHumanInTheLoop`, which is the V2 hook for
**frontend-executed** tools (LLM calls a tool, frontend resolves a
Promise — no agent-side execution). It does not subscribe to
`on_interrupt` events at all, so:
- The render registered for `request_approval` saw only the streamed
tool call from `MESSAGES_SNAPSHOT` and rendered with `status:
InProgress` (no `executingToolCallIds` entry was ever set).
- The agent's checkpoint had a pending interrupt that no UI was offering
to resolve.

V2 ships a separate `useInterrupt` hook specifically for LangGraph-style
interrupts. Switching to it fixes the round trip.

## What changed

- `src/hooks/use-request-approval.tsx` — replaced `useHumanInTheLoop`
with `useInterrupt` and bridged the result to the existing
`InvoiceApprovalCard` / `InventoryReorderCard` components (no card
markup changes). The `respond` callback the cards expect is now backed
by `resolve` from `useInterrupt`, which sends
`forwardedProps.command.resume` back to the agent.
- Added a no-op `useRenderTool({ name: "request_approval", render: () =>
null })` so the existing wildcard `useRenderTool({ name: "*" })` in
`shell.tsx` doesn't render a stale generic ToolCard alongside the
interrupt UI.
- JSON-parse `event.value` — the runtime delivers the interrupt payload
as a JSON-encoded **string** (the structured object lives under
`rawEvent.value`). Accessing properties directly silently returns
`undefined` and filters the interrupt out, which is what masked an
earlier iteration of this fix.

## Test plan

- [x] Click "Approve Payments" → agent runs do_research, then surfaces
the InvoiceApprovalCard with the overdue invoices and Approve / Reject
buttons
- [x] Click "Approve Payment" → agent log: `[HITL] request_approval
RESUMED answer='{"approved": true, "message": "Payment approved for 3
invoice(s) totaling $153,500.00"}'`. Run continues with the user
response.
- [x] Click "Reject" → resume command carries `{approved: false}`; agent
acknowledges and stops processing.
- [x] Click "Reorder Inventory" → same flow surfaces
`InventoryReorderCard` with Approve PO / Skip Reorder buttons (the hook
handles both `type` values).
- [ ] Reviewer: please verify against your own LangGraph showcase setup
that no other HITL flow regressed.

## Notes

- No package changes. `@copilotkit/react-core` already exports
`useInterrupt` from V2.
- The fix is contained to a single file (`use-request-approval.tsx`);
the cards themselves are untouched.
2026-05-06 18:26:42 +02:00
Alem Tuzlak 48cd3b2c93 feat(showcase/voice): D5 mapping + sample-button bypasses /transcribe (#4674)
## Summary

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

## Test plan

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

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

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

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

Also adds the missing d5-voice.test.ts companion (every other d5-* probe
script has one) and trims the langgraph-python qa/voice.md + e2e steps
that depended on the now-removed async behavior.
2026-05-06 18:11:24 +02:00
Sam Julien f9393f6083 feat(shell-docs): port OpsPlatformCTA, place sign-up CTAs, rebrand to Enterprise Intelligence Platform (#4670)
## Summary

Brings the docs→dashboard sign-up funnel to shell-docs and pulls the
threads documentation stack into parity with upstream. Mirrors PRs
[#4592](https://github.com/CopilotKit/CopilotKit/pull/4592) (Wave 1, 30+
placements), [#4642](https://github.com/CopilotKit/CopilotKit/pull/4642)
(rebrand + threads restoration), and follow-up commit `0ada76b9a` (CTAs
on threads pages). Lands in four commits:

1. **Port the `OpsPlatformCTA` component** to
`showcase/shell-docs/src/components/react/ops-platform-cta.tsx` and wire
it into the shared MDX registry.
2. **Place 22 `<OpsPlatformCTA>` instances** across shell-docs MDX pages
with stable surface identifiers that match upstream's, so PostHog click
attribution stays continuous across the docs.copilotkit.ai cutover.
3. **Rebrand "CopilotKit platform" → "Enterprise Intelligence
Platform"** in shell-docs prose, mirroring the docs/ rebrand.
4. **Add useThreads at the canonical reference path** + threads-stack
content parity (see "Threads parity" below).

## Adaptations from upstream

- **Visual tokens** — swapped indigo/purple Tailwind utilities for
`--accent` / `--violet-light` / `--border` / `--text*` CSS variables
already used by the rest of shell-docs.
- **No dark mode** — dropped `dark:` modifiers; shell-docs has no dark
theme yet.
- **No lucide-react** — inlined `ArrowRight`, `Info`, and `Sparkles` as
SVG components.
- **No client-side PostHog** — shell-docs ships server-side PostHog
(middleware) only and has no `posthog-js`. UTM params on the dashboard
URL (`utm_source=docs`, `utm_medium=cta`, `utm_campaign=intelligence`,
`utm_content={surface}`) are the source of truth for click attribution.
- **Inline-style overrides** — `text-decoration: none` on the card/tile
wrappers and explicit `color` on the inline-button text and info-link to
defeat shell-docs's `.reference-content a` rule.

## Placement coverage

22 placements: 18 direct ports of upstream surfaces, 3 path-adjusted,
and 1 structural.

**Direct (18):** `inspector`, `shared-state`, `threads`,
`troubleshooting/event-inspector`; integration quickstarts for `a2a`,
`ag2`, `agent-spec`, `built-in-agent` (overview + quickstart),
`crewai-flows`, `deepagents`; `langgraph/prebuilt-components`; the four
shared snippets (`basics/prebuilt-components`, `premium/headless-ui`,
`premium/observability`, `premium/overview`); the shared
`threads/threads` snippet; the canonical `reference/hooks/useThreads`.

**Path-adjusted (3):** `learn/intelligence-platform` →
`premium/intelligence-platform`; `learn/threads` →
`premium/threads-explained`; `learn/tutorials/multi-conversation-chat` →
`tutorials/multi-conversation-chat`.

**Structural (1):** root `prebuilt-components.mdx` →
`prebuilt-components/index.mdx`.

**Skipped:** `quickstart.mdx` (root, routing shim), `(root)/index.mdx`
(no MDX docs landing), per-framework integration `index.mdx` files (no
FrameworkOverview equivalent),
`reference/v2/components/{CopilotChat,CopilotKit}.mdx` and
`reference/v2/index.mdx` (different layout).

## Routing note

A few placement targets are MDX files that shell-docs doesn't currently
expose at a public URL — they're orphans pending a registered framework
slug. Specifically: `agent-spec/quickstart.mdx`,
`deepagents/quickstart.mdx`, `a2a/quickstart.mdx`. Mirroring the
upstream placement here is defensive; tracked as part of the broader IA
gap work in PDX-84.

## Rebrand sweep

11 files updated, 50 occurrences collapsed into the canonical name.
Patterns: `CopilotKit platform` → `Enterprise Intelligence Platform`;
`CopilotKit Intelligence Platform` → `Enterprise Intelligence Platform`;
`Intelligence Platform` (standalone) → `Enterprise Intelligence
Platform`. Also fixes two `a Enterprise` → `an Enterprise` article
typos. URL slugs (`/learn/intelligence-platform`,
`/premium/intelligence-platform`) intentionally untouched.

## Threads parity

The previous version of shell-docs had `useThreads.mdx` at
`src/content/docs/reference/v2/hooks/useThreads.mdx`, but the canonical
reference renderer reads from `src/content/reference/`, not
`src/content/docs/reference/`. Result: `/reference/hooks/useThreads`
404'd while upstream's docs had a working useThreads page for weeks.

This PR moves useThreads to the canonical path so it resolves, and pulls
the rest of the threads stack into content parity with upstream:

- `OpsPlatformCTA` added to the reference page's component map so hook
reference pages can host sign-up CTAs (used here on useThreads itself).
- useThreads recreated at `src/content/reference/hooks/useThreads.mdx`.
Drops the `<ThreadsEarlyAccess>` wrapper (canonical reference dir
doesn't use it — threads is GA) and the `doc_type` frontmatter field
(canonical hooks use plain `title` + `description` only). Keeps the
local `lastRunAt` PropertyReference (deliberately preserved per commit
`9f18b50f0`) and the new CTA placement.
- Cross-links to useThreads in `threads.mdx` and the shared snippet
repointed at `/reference/hooks/useThreads` (canonical) instead of
`/reference/v2/hooks/useThreads` (404).
- Prerequisite version bumped from `@copilotkit/react-core v1.50+` to
`v1.56+` in `threads.mdx` and the shared snippet, matching upstream.

Page-structure differences from upstream are preserved per shell-docs
IA: `learn/threads` stays `premium/threads-explained`,
`learn/intelligence-platform` stays `premium/intelligence-platform`,
`learn/tutorials/...` stays `tutorials/...`.

## Test plan

- [ ] `/inspector`, `/threads`, `/shared-state`,
`/troubleshooting/event-inspector` render the inline CTA above the page
content
- [ ] `/built-in-agent`, `/built-in-agent/quickstart`,
`/ag2/quickstart`, `/crewai-crews/quickstart` render the card CTA above
the prerequisites/video, with no underlines on the title/body and white
button text on the violet button
- [ ] `/langgraph-python/prebuilt-components` renders the inline CTA
above the IframeSwitcher
- [ ] `/premium/intelligence-platform` and `/premium/threads-explained`
render their CTAs between the intro paragraph and the first concept
section
- [ ] `/tutorials/multi-conversation-chat` renders its CTA inside the
early-access wrapper
- [ ] `/prebuilt-components` renders the inline CTA above "Pre-built
components for agentic chat"
- [ ] `/reference/hooks/useThreads` resolves (no 404) and renders the
card CTA above "## Overview", with the `lastRunAt` PropertyReference
still present in the Return Value section
- [ ] CTA buttons all link to
`dashboard.operations.copilotkit.ai/?utm_source=docs&utm_medium=cta&utm_campaign=intelligence&utm_content={surface}`
with the correct surface ID
- [ ] Pages that mention the platform brand consistently say "Enterprise
Intelligence Platform" — no remaining "CopilotKit platform" /
"CopilotKit Intelligence Platform" / bare "Intelligence Platform"
- [ ] `/threads` "Next steps" → "API reference" link goes to the working
`/reference/hooks/useThreads` (not the 404
`/reference/v2/hooks/useThreads`)
2026-05-06 08:58:55 -07:00
Markus Ecker a83acc7fb8 fix(react-core): IntelligenceIndicator matches the renamed copilotkit_knowledge_base_shell tool
The Intelligence platform's MCP tool was renamed from `bash` to
`copilotkit_knowledge_base_shell` (intelligence/mme/integrate-sl
4256c13). Update the indicator's `DEFAULT_TOOL_PATTERNS` to match the
new name so the pill keeps rendering on the right assistant slots.

Test fixtures that previously used the bare `bash` name follow the
rename — both the default in `emitAssistantMessageWithToolCalls` and
the explicit `tc_match` entry in the tool-match condition test.
2026-05-06 17:33:45 +02:00
Alem Tuzlak a86076f76b feat(showcase): D5 probes for headless-simple + headless-complete (langgraph-python) (#4673)
## Summary

- **Promotes `/demos/headless-complete` to its own D5 feature type**
(`gen-ui-headless-complete`) so the dashboard cell can reach D5.
Previously `headless-complete` aliased onto `gen-ui-headless`, which
navigated to `/demos/headless-simple` and asserted on a `show_card` tool
the headless-complete page doesn't even register — i.e. the cell was
never actually being probed.
- **Extends `gen-ui-headless`** (the simple probe) to also click the
"Largest continent" chip and assert the canonical Asia text reply.
- **Both probes now click chips via `preFill`** instead of typing the
prompt — same handler the user clicks, no input drift.
- **Bug fixes uncovered while wiring this up locally** that explain why
the dashboard matrix had been showing every cell as D0 — see "What was
actually broken" below.

## What was added (the feature work)

- New `gen-ui-headless-complete` D5 feature type + script that exercises
**all 5 chips** on `/demos/headless-complete`:
  - `Weather in Tokyo` → `WeatherCard` (per-tool `useRenderTool`)
  - `AAPL stock price` → `StockCard` (per-tool `useRenderTool`)
  - `Highlight a note` → `HighlightNote` (frontend `useComponent`)
- `Sketch a diagram` → best-effort assistant response (Excalidraw MCP
path)
  - `Largest continent` → "Asia is the largest continent…" text reply
- New fixture `harness/fixtures/d5/gen-ui-headless-complete.json` (also
bundled into `aimock/d5-all.json`) for AAPL + highlight + Excalidraw
prompts.
- `headless-complete` `UserBubble` + `AssistantBubble` now carry
`data-message-role` so the harness conversation runner can detect
message arrivals (mirrors the headless-simple convention; required to
probe the page at all).
- Mappings updated in lockstep: `REGISTRY_TO_D5` (harness) and
`CATALOG_TO_D5_KEY` (dashboard) both map `headless-complete →
["gen-ui-headless-complete"]`.

### Non-obvious fixture detail worth flagging

Aimock's `toolCallId` matcher reads only the **last** tool message in
the request, but in a multi-turn probe the "last tool" stays on a
previous turn's id until a new tool runs. A bare `toolCallId` narration
fixture will therefore fire for the *next* turn's prompt and hijack it
with a stale narration. The fix is to pin each narration fixture with
both `userMessage` AND `toolCallId`, and order them BEFORE the bare
`userMessage` toolCall fixture in the array — that way the more-specific
narration only fires on the matching turn's second leg, and the bare
userMessage fixture covers the first leg.

## What was actually broken (incidental bugs fixed)

These were uncovered while running the new probe locally — none of them
were caused by this PR, all of them prevented the dashboard from working
at all in `--live` mode. Each is a separate commit so they can be
reviewed / cherry-picked independently:

1. **`fix(showcase/harness): wire pbWriter into ProbeContext for live
writes`** — `runner.ts` constructed `ctx` without `writer`, so every
per-feature side row from every driver (e2e-deep's
`d5:<slug>/<featureType>`, liveness's `health:<slug>` / `agent:<slug>`,
etc.) was silently dropped on `--live` runs. Only aggregate primary
results made it to PB. This is why the dashboard matrix showed every
cell as D0 even after a successful `--live` probe.
2. **`fix(showcase/harness): align CLI smoke input slug shape with
discovery`** — `buildSmokeInputs` passed `name: manifest.name` (display
name like "LangGraph (Python)") which the liveness driver's `deriveSlug`
used as the slug, producing rows like `health:LangGraph (Python)` that
didn't join with anything else. Matches production discovery shape
(`name = showcase-<slug>`) now.
3. **`fix(showcase/harness): use PB-validator-compliant email for local
superuser`** — PocketBase 0.22 rejects `admin@localhost` (single-label
TLD). Switched the hardcoded local creds to `admin@localhost.dev`.
4. **`chore(showcase/dashboard): plumb NEXT_PUBLIC_* build args in local
compose`** — `NEXT_PUBLIC_POCKETBASE_URL` and `NEXT_PUBLIC_SHELL_URL`
were unset at build time, so the dashboard JS couldn't reach PB from the
browser at all (FATAL-CONFIG banner) and every Demo/Code link in the
matrix rendered as `about:blank#shell-url-missing`.

## Verification

Run locally against the langgraph-python integration:

```sh
docker compose -f showcase/docker-compose.local.yml up -d aimock pocketbase
docker exec showcase-pocketbase /usr/local/bin/pocketbase migrate up --dir=/pb_data
docker exec showcase-pocketbase /usr/local/bin/pocketbase admin create admin@localhost.dev showcase-local-dev --dir=/pb_data
docker compose -f showcase/docker-compose.local.yml up -d --build dashboard langgraph-python

npx tsx showcase/harness/src/cli.ts test langgraph-python --d5 --verbose
# 33/33 passed, including gen-ui-headless and gen-ui-headless-complete

npx tsx showcase/harness/src/cli.ts test langgraph-python --level all --live
# Writes the full ladder to PB
```

Open http://localhost:3200 — the langgraph-python `headless-simple` and
`headless-complete` cells both show **D5** with API ✓ / RT ✓ / CV ✓.

## Test plan

- [ ] Run `npx tsx showcase/harness/src/cli.ts test langgraph-python
--d5 --verbose` and confirm `gen-ui-headless` and
`gen-ui-headless-complete` both green.
- [ ] Run with `--live` and confirm
`d5:langgraph-python/gen-ui-headless-complete` appears in PocketBase as
`green`.
- [ ] Open the dashboard matrix and confirm the langgraph-python
`headless-complete` cell shows D5/D5.
- [ ] Visually click each chip on `/demos/headless-complete` and confirm
the right surface renders (WeatherCard / StockCard / HighlightNote /
Excalidraw / Asia text).
- [ ] D5 probe still passes for every other langgraph-python feature (no
regressions in the existing 32 features).

## What was NOT done

- The `data-message-role` bubble tags are only on the
**langgraph-python** copy of
`headless-complete/{user,assistant}-bubble.tsx`. The other 16
integrations' headless-complete demos still lack the attribute. They
aren't probed at D5 today, so this is fine — but propagate before
bumping any of them to D5.
- The local CLI's `--smoke / --d4 / --d5 / --level all` flag set does
not run the `e2e-demos` driver that emits `e2e:<slug>/<featureId>` rows,
so the depth ladder caps at D2 from those flags alone. Dashboard
verification in this PR populated D3 rows manually. Wiring `e2e-demos`
(or an equivalent D3 generator) into the local CLI is a separate
follow-up.
2026-05-06 17:08:43 +02:00
Alem Tuzlak 53d7999c05 Merge remote-tracking branch 'origin/main' into feat/showcase-d5-headless-chat
# Conflicts:
#	showcase/aimock/d5-all.json
2026-05-06 17:04:00 +02:00
Alem Tuzlak 6b2bdbcfa9 chore(showcase/dashboard): plumb NEXT_PUBLIC_* build args in local compose
The dashboard image was being built with only `OPS_BASE_URL` set; the
two other compile-time env vars used by the matrix view stayed unset:

- NEXT_PUBLIC_POCKETBASE_URL — left at the dev fallback in production
  builds, which surfaces a "FATAL-CONFIG: NEXT_PUBLIC_POCKETBASE_URL
  was unset at build time" banner in the browser console and causes
  the matrix's PB SSE subscription to fail (no live updates).
- NEXT_PUBLIC_SHELL_URL — left unset, so every Demo / Code link in
  the matrix renders as `about:blank#shell-url-missing`.

Pin both at build time:
- POCKETBASE_URL → http://localhost:8090 (host port the user's browser
  reaches; container-internal `pocketbase:8090` is unresolvable from
  outside the compose network).
- SHELL_URL → http://localhost:3100 (langgraph-python integration
  host port; no shared "shell" service in the local stack).
2026-05-06 16:26:17 +02:00
Alem Tuzlak 5034e83054 fix(showcase/harness): use PB-validator-compliant email for local superuser
PocketBase 0.22's email validator rejects `admin@localhost` (single-
label TLD) with `validation_is_email: Must be a valid email address`,
breaking PB auth from the harness CLI on a fresh local stack —
`pb-write-failed` / `pb-auth failed: 400` on every --live run.

Switch the hardcoded local creds to `admin@localhost.dev`. The
matching superuser must be created with the running server's data
directory pinned: `pocketbase admin create admin@localhost.dev
showcase-local-dev --dir=/pb_data` (the create command's default
`./pb_data` differs from the server's `--dir=/pb_data`, so the record
otherwise lands in a different SQLite file and the running server
can't see it).
2026-05-06 16:25:53 +02:00
Alem Tuzlak e5c68c02ee fix(showcase/harness): align CLI smoke input slug shape with discovery
`buildSmokeInputs` was passing `name: manifest.name` (the display name,
e.g. "LangGraph (Python)") which the liveness driver's `deriveSlug`
stripped of a leading `showcase-` prefix and used as the slug —
producing rows like `health:LangGraph (Python)` and
`agent:LangGraph (Python)` that didn't join with anything else on the
dashboard's depth ladder.

Production discovery sets `name` to the Railway service name
(`showcase-<slug>`), which strips cleanly to the slug. Mirror that
shape from the local CLI so all rows for a service share the same
keyspace and the dashboard cell can advance past D0.
2026-05-06 16:25:29 +02:00
Alem Tuzlak 85afa8ee9e fix(showcase/harness): wire pbWriter into ProbeContext for live writes
The CLI's runner.ts created a `pbWriter` when --live was passed but
never plumbed it into `ctx.writer`, so every per-feature side row from
every driver (e2e-deep's `d5:<slug>/<featureType>`, liveness's
`health:<slug>` / `agent:<slug>`, etc.) was silently dropped. Only
the aggregate primary results made it to PocketBase, which is why the
dashboard matrix showed every cell as D0 even after a successful
--live probe run.

Now `ctx.writer = pbWriter` when --live is on; without --live the
field is omitted, matching the legacy "no side emission" behavior.
2026-05-06 16:24:30 +02:00
Alem Tuzlak 3eb53a8621 feat(showcase): D5 probe for headless-complete + extend headless-simple (langgraph-python)
Promotes /demos/headless-complete to its own D5 feature type so the
dashboard cell can reach D5 instead of riding on the headless-simple
probe (which was navigating to /demos/headless-simple regardless of
which catalog feature triggered it).

- New gen-ui-headless-complete D5 feature type + script that clicks
  each suggestion chip via preFill and asserts the right surface
  renders: WeatherCard (get_weather), StockCard (get_stock_price),
  HighlightNote (frontend useComponent), Excalidraw best-effort, and
  the canonical "Asia is the largest continent" text reply.
- Existing gen-ui-headless script now drives both turns by chip
  click (Profile card + Largest continent) instead of typing.
- Fixtures pin narration legs with both userMessage AND toolCallId
  and order them before the bare userMessage toolCall fixture —
  aimock's toolCallId matcher reads the LAST tool message in the
  request, but in a multi-turn probe that "last tool" stays on a
  previous turn's id until a new tool runs, which would otherwise
  hijack a later turn's prompt with a stale narration.
- headless-complete UserBubble + AssistantBubble now carry
  data-message-role so the harness conversation runner can detect
  message arrivals (mirrors the headless-simple convention).
- Mappings updated in lockstep:
    - REGISTRY_TO_D5:  headless-complete -> ["gen-ui-headless-complete"]
    - CATALOG_TO_D5_KEY (dashboard): same.
2026-05-06 16:21:43 +02:00
Markus Ecker faa2a556d0 test(runtime): cover Intelligence MCP auto-attach via forwardedProps
Four cases at the agent layer (BuiltInAgent reading forwardedProps):
  * attaches when `copilotkitIntelligence` carries all three strings
    (userId, apiKey, mcpUrl) — outbound headers carry Authorization +
    X-Cpki-User-Id.
  * does NOT attach when the bag is absent (no Intelligence wiring on
    this run).
  * does NOT attach when the bag is partial (e.g. mcpUrl missing).
  * does NOT attach when the user has already configured an MCP server
    pointing at the same URL — explicit user config wins, with the
    user's headers and resolver hitting the wire.
2026-05-06 16:16:14 +02:00
Markus Ecker a46acc3f94 feat(runtime/agent): auto-attach Intelligence MCP server via input.forwardedProps
Runtime side (intelligence/run.ts): when `runtime.intelligence.mcpServer`
is enabled, build a `copilotkitIntelligence` bag carrying the resolved
user-id, project apiKey, and the platform MCP URL, and pass it through
on `RunAgentInput.forwardedProps` to the agent. Skipped when the flag
is off — runs that don't go through this Intelligence path simply
don't see the bag.

Agent side (BuiltInAgent's run code): if `forwardedProps.copilotkitIntelligence`
contains all three string values AND the user's static `config.mcpServers`
doesn't already include the same URL, append a per-request
`MCPClientConfigHTTP`. Its `options.fetch` closes over apiKey + userId
and stamps `Authorization: Bearer <apiKey>` and `X-Cpki-User-Id:
<userId>` on every outbound MCP call. The custom fetch is the MCP
TypeScript SDK's documented extension point for per-request header
injection — no extra wrapper class, no separate framework concept.

The agent class is otherwise untouched: no new fields, no per-request
side channels, no typed reference to `CopilotKitIntelligence`. Other
agents that don't read `forwardedProps.copilotkitIntelligence` ignore
the bag.

Pulls in the AI SDK's stable `createMCPClient` export (rename from
`experimental_createMCPClient`) — the experimental name was deprecated;
`mcp-clients.test.ts`'s mock setup follows.
2026-05-06 16:15:57 +02:00
Markus Ecker 1de2fae369 feat(runtime): CopilotKitIntelligence.mcpServer opt-in flag + ɵ-accessors
Adds `mcpServer?: boolean` to `CopilotKitIntelligenceConfig` (default
`false`). When true, the runtime emits the per-request bag the agent
needs to attach the platform's MCP server.

Internal accessors `ɵisMcpServerEnabled()` and `ɵgetApiKey()` round
out the existing `ɵgetApiUrl()`. Used by the runtime layer in the
forthcoming auto-attach commit; not part of the public surface.
2026-05-06 16:15:21 +02:00
Markus Ecker 44cb538856 feat(runtime/v2): re-export MCPClient and MCPTransport from @ai-sdk/mcp
Convenience re-exports so consumers wiring custom MCP clients (via
`mcpClients`) or custom transports don't need to add `@ai-sdk/mcp`
to their dependencies just to type the values.
2026-05-06 16:15:06 +02:00
Alem Tuzlak 04e9e969e6 feat(showcase): D5 probe for beautiful-chat (langgraph-python) (#4672)
## Summary

- Add a dedicated D5 conversation probe for `beautiful-chat` so the cell
can advance past D4 in the dashboard. Asserts the A2UI fixed-schema
FlightCard surface renders with stable text fingerprints (`United
Airlines`, `Delta`, `$349`, `$289`) from the `search_flights` tool
round-trip — the same render path that PR #4668 fixed.
- Replace the freeloading `["agentic-chat"]` alias in `REGISTRY_TO_D5`
with a dedicated `["beautiful-chat"]` key, and re-add the matching
`CATALOG_TO_D5_KEY` entry so `computeMaxPossible` lifts the D4 cap to
D5. Commit `974494ecb` had stripped the alias because it would inherit
agentic-chat's green status without exercising any A2UI assertion; this
PR replaces it with a real probe instead of restoring the alias.
- Splice the new fixture (two entries, `hasToolResult` false→true
mirroring the `gen-ui-headless` pattern) into
`showcase/aimock/d5-all.json`.

## What changed

- `showcase/harness/src/probes/scripts/d5-beautiful-chat.ts` — new
probe. Single turn: navigates `/demos/beautiful-chat`, sends the unique
substring `d5 beautiful-chat probe: search flights from SFO to JFK`,
asserts FlightCard literals appear (60s budget on first card, 5s on
siblings).
- `showcase/harness/fixtures/d5/beautiful-chat.json` — new fixture.
Payload mirrors `call_fp_search_flights_001` from `feature-parity.json`
so visual fingerprints match across both runners.
- `showcase/harness/src/probes/helpers/d5-registry.ts` — add
`"beautiful-chat"` to the `D5FeatureType` union + runtime mirror.
- `showcase/harness/src/probes/helpers/d5-feature-mapping.ts:111` —
point at the new probe key, not the agentic-chat alias.
- `showcase/shell-dashboard/src/lib/live-status.ts` — re-add
`"beautiful-chat": ["beautiful-chat"]` to `CATALOG_TO_D5_KEY`.
- `showcase/aimock/d5-all.json` — splice the two new fixture entries
(additions only).

## Why one surface, not all 5 pills

The probe asserts only the Search Flights pill. Lowest-risk surface to
start with: literal-text fingerprints (no LLM-output dependency),
single-turn `search_flights` call, fastest round-trip among the A2UI
pills. Sales Dashboard's `generate_a2ui` is a two-stage flow (secondary
LLM bound to `render_a2ui`) that takes 90s+ on cold starts and would
balloon the probe budget. Once this lands and runs green, it's
straightforward to add surface-specific D5 literals
(`beautiful-chat-flights`, `beautiful-chat-dashboard`, etc.) — the
registry is set up for it and `isD5Green` uses `every` so multi-key
gating just works.

## Test plan

- [x] `npx nx run @copilotkit/showcase-harness:typecheck` — clean
- [x] `npx nx run @copilotkit/showcase-shell-dashboard:typecheck` — no
new errors (5 pre-existing test-file errors unchanged)
- [x] `npm test -- --run d5-registry` (harness) — 12/12 pass with the
new literal
- [x] `npm test -- --run depth-utils` (shell-dashboard) — 35/35 pass
- [x] `npm run build` (harness) — clean
- [x] `OPS_BASE_URL=stub npm run build` (shell-dashboard) — clean
- [x] Local end-to-end: aimock + pocketbase + dashboard up, full D1–D5
ladder seeded into PB, dashboard renders `beautiful-chat ×
langgraph-python` cell as **D5**. Beautiful Chat demo at
`localhost:3100/demos/beautiful-chat` round-trips the new fixture.

## Follow-up (not in this PR)

- The full harness orchestrator running this probe end-to-end was not
exercised locally — verifying it in the Railway deploy is the proper
end-to-end test. The static side (mapping + registry + chip render) is
verified locally via the seeded PB row.
- A vitest unit test for `d5-beautiful-chat.ts` (similar shape to
`d5-chat-slots.test.ts`) is a reasonable next addition. The other
LGP-wave probes in `harness/src/probes/scripts/` mostly don't ship
paired tests, so this PR follows the existing pattern.
2026-05-06 15:34:47 +02:00
Alem Tuzlak 653abdb901 feat(showcase): expand beautiful-chat D5 probe to 7 of 9 pills
Builds on the initial Search Flights-only probe by extending to a
multi-turn ConversationTurn[] that asserts surface-specific render
fingerprints for 7 of the 9 pills in /demos/beautiful-chat.

Pills covered (turn order is load-bearing — see script jsdoc):
  1. Toggle Theme        — html.dark class flip (toggleTheme frontend tool)
  2. Pie Chart           — >= 3 svg circles (pieChart useComponent)
  3. Bar Chart           — recharts container + >= 2 bar rectangles
  4. Search Flights      — A2UI FlightCard literal fingerprints (#4668 path)
  5. Schedule Meeting    — MeetingTimePicker mounts; assertion CLICKS a slot
                           to resolve the HITL pause before subsequent turns
  6. Sales Dashboard     — A2UI dynamic generate_a2ui → secondary render_a2ui;
                           "Total Revenue" + recharts container (90s budget)
  7. Task Manager        — enableAppMode + manage_todos; "To Do" column +
                           canonical todo title visible. MUST be last
                           (flips layout, breaks chat input on narrow widths)

Pills intentionally skipped (track in follow-up):
  - Excalidraw Diagram   — depends on mcp.excalidraw.com reachability,
                           turning D5 reliability into a 3rd-party uptime bet
  - Calculator App       — sandboxed iframe makes assertions cross-frame-fragile;
                           generateSandboxedUi already covered by d5-gen-ui-open
                           on a different demo route (would duplicate coverage)

Probe uses the runner's structural ConversationPage type for most assertions
(via page.evaluate helpers in the d5-chat-css globalThis-cast pattern, which
keeps the harness's Node-only tsconfig clean of DOM lib types). Schedule
Meeting narrows to an extended Page type with click() — same runtime-guarded
cast used in d5-hitl-text-input — so it can dispatch the HITL slot click.

Fixture file expanded from 2 to 15 entries covering all 7 turns plus their
multi-stage chains (Sales Dashboard primary + secondary LLM + post-tool;
Task Manager enableAppMode → manage_todos → narration). Re-bundled into
showcase/aimock/d5-all.json (additions only — no other fixtures changed).

Conversation runner reports failure_turn so per-pill failure isolation is
preserved on the dashboard's drilldown without needing 7 separate D5 literals.
2026-05-06 15:14:09 +02:00
Alem Tuzlak e11c1d0810 feat(showcase): D5 conversation probe for beautiful-chat (langgraph-python)
Beautiful Chat was capped at D4 in the dashboard because it had no
dedicated D5 probe and was deliberately excluded from CATALOG_TO_D5_KEY
(commit 974494ecb stripped the freeloading "agentic-chat" alias). PR
#4668 fixed the A2UI surface rendering and added e2e tests, but those
land at the D3 tier — D5 is a separate probe with its own driver.

Changes:

- New d5-beautiful-chat probe asserts the A2UI fixed-schema FlightCard
  surface renders with literal United/Delta/$349/$289 fingerprints from
  the search_flights tool. 60s budget on first card, 5s on siblings.
- New harness/fixtures/d5/beautiful-chat.json with two-stage fixture
  (hasToolResult false→true) mirroring the gen-ui-headless pattern.
  Fixture spliced into the bundled aimock/d5-all.json.
- New "beautiful-chat" D5FeatureType literal in the registry's union +
  runtime mirror.
- d5-feature-mapping.ts: replace "beautiful-chat": ["agentic-chat"]
  alias with ["beautiful-chat"] so the probe targets its own dedicated
  PB key instead of freeloading agentic-chat's green status.
- live-status.ts CATALOG_TO_D5_KEY: re-add "beautiful-chat":
  ["beautiful-chat"] so computeMaxPossible lifts the D4 cap to D5.
2026-05-06 14:35:07 +02:00
Markus Ecker 5b11748065 docs(react-core): refresh IntelligenceIndicator auto-mount comment
The previous comment referenced a "200 ms poll interval" that the
indicator no longer uses (polling was removed when we switched to the
tool-call pending-grace timer). Updates the rationale to mention the
current self-gates (latest matching-assistant slot + pending grace
window).
2026-05-06 12:18:14 +02:00
Markus Ecker ee1856f1ba refactor(react-core): minimize MemoizedCustomMessage delta to just the auto-mount
Reverts the cosmetic changes that crept in alongside the auto-mount
edit — restores `stateSnapshot?` (always passed at runtime, no functional
difference), the original concise comments around the memo's comparison
function, and the original combined value+type imports. The only
remaining framework change in this PR is the new auto-mount block:
when `copilotkit.intelligence !== undefined` and the message is an
assistant message, push an `<IntelligenceIndicator>` after the message
slot.

Indicator e2e suite still green (10/10).
2026-05-06 12:16:32 +02:00
Markus Ecker af9ea8b987 refactor(core,docs): rename ProxiedCopilotRuntimeAgent.remoteAgentId → runtimeAgentId
Renames the proxy-config field, the field on the agent instance, and
all matching references in tests and the useCopilotKit reference page.
"runtime" reads more naturally now that the proxy concept is documented
as "a local agent that delegates to a runtime agent" rather than
"remote agent" — the latter conflates with `remoteAgents` (the
registry of agents fetched from the runtime), which keeps its name.

No behavioral change; the field still controls the outbound REST URL
used by the proxy.
2026-05-06 12:01:37 +02:00
Markus Ecker b63602241d refactor(react-core): drop MemoizedCustomMessage's run-state inputs
Removes the numberOfMessagesInRun, isInLatestRun, and isRunning props on
MemoizedCustomMessage along with the per-render runMetadata derivation
that fed them. Authored renderers observe run state via useAgent's
OnRunStatusChanged / OnMessagesChanged subscriptions, which forceUpdate
the renderer independently of the memo's bail-out — the extra
invalidation inputs added nothing for that canonical path and only
masked staleness for renderers that read run state from closure
without subscribing.

The IntelligenceIndicator itself uses useAgent and remains correct.

Net change: ~95 lines removed; one less O(n) scan through messages per
chat re-render. All chat e2e tests (587) pass, including the indicator
suite (10).
2026-05-06 11:57:44 +02:00
Markus Ecker 77dab3766a refactor(core,docs): rename ProxiedCopilotRuntimeAgent.remoteAgentId → runtimeAgentId
Renames the proxy-config field, the field on the agent instance, and
all matching references in tests and the useCopilotKit reference page.
"runtime" reads more naturally now that the proxy concept is documented
as "a local agent that delegates to a runtime agent" rather than
"remote agent" — the latter conflates with `remoteAgents` (the
registry of agents fetched from the runtime), which keeps its name.

No behavioral change; the field still controls the outbound REST URL
used by the proxy.
2026-05-06 11:46:44 +02:00
Sam Julien cfe4744024 docs(shell-docs): use prose "public license key" in CTA copy
Three CTA `body` strings rendered "publicLicenseKey" as plain prose,
which reads as code (camelCase identifier) where the surrounding
sentence is conversational. Switches to "public license key" — the
phrase, not the prop name. Code samples and reference docs that
reference the actual `publicLicenseKey` prop are unchanged.
2026-05-05 11:59:49 -07:00
Sam Julien 14469bedf4 feat(shell-docs): add useThreads at canonical reference path + content parity
The useThreads page existed in shell-docs at
\`src/content/docs/reference/v2/hooks/useThreads.mdx\` but that tree
isn't routed — the canonical reference renderer reads from
\`src/content/reference/\`, not \`src/content/docs/reference/\`. As a
result \`/reference/hooks/useThreads\` 404'd while the upstream docs
have had a working useThreads page for weeks.

Moves the page to the canonical location so it resolves at
\`/reference/hooks/useThreads\`, and pulls the rest of the threads
content stack into parity with upstream:

- Add \`OpsPlatformCTA\` to the reference renderer's component map so
  hook reference pages can host sign-up CTAs (used here on useThreads
  itself).
- Recreate useThreads at the canonical path. Drops the
  \`<ThreadsEarlyAccess>\` wrapper (canonical reference dir doesn't use
  it — threads is GA, no banner) and the \`doc_type: reference\`
  frontmatter field (canonical hooks use plain title + description).
  Keeps the local additions: \`<OpsPlatformCTA>\` placement and the
  \`lastRunAt\` PropertyReference (deliberately kept per commit
  9f18b50f0).
- Fix cross-links to useThreads in threads.mdx and the shared snippet
  to point at the canonical \`/reference/hooks/useThreads\` instead of
  the broken \`/reference/v2/hooks/useThreads\`.
- Bump the prerequisite from \`@copilotkit/react-core v1.50+\` to
  \`v1.56+\` in threads.mdx and the shared snippet to match upstream.

Out of scope: the broader \`/reference/v2/hooks/\<Name\>\` broken-link
problem across other shell-docs pages (useFrontendTool, useAgent,
etc. — same dirname mismatch but for hooks unrelated to this PR).
That's tracked under PDX-103 / PDX-84.

Page-structure differences from upstream are preserved per the
shell-docs IA decision to drop the \`learn/\` concept: \`learn/threads\`
stays \`premium/threads-explained\`, \`learn/intelligence-platform\`
stays \`premium/intelligence-platform\`, \`learn/tutorials/...\` stays
\`tutorials/...\`.
2026-05-05 11:55:02 -07:00
Sam Julien a5a48bd94e docs(shell-docs): rebrand "CopilotKit platform" → "Enterprise Intelligence Platform"
Mirrors upstream PR #4642 across shell-docs prose. Three patterns
collapsed into one canonical name:

  - "CopilotKit platform" → "Enterprise Intelligence Platform"
  - "CopilotKit Intelligence Platform" → "Enterprise Intelligence Platform"
  - "Intelligence Platform" → "Enterprise Intelligence Platform"

Also corrects the "a Enterprise" → "an Enterprise" article mismatch
the rename leaves behind in self-hosting prerequisites (vowel-sound
rule).

URL slugs (/learn/intelligence-platform, /premium/intelligence-platform)
are left as-is — text-only rename. Generated artifacts (search-index.json,
demo-content.json) refresh on the next predev / prebuild script.

PDX-113.
2026-05-05 11:40:23 -07:00
Sam Julien 835a55d0ba feat(shell-docs): place OpsPlatformCTA across MDX pages
Mirrors the placements upstream docs/ shipped in PR #4592 (Wave 1) and
PR #4642 (Wave 2 — restored threads pages). 22 placements total: 18
direct ports of upstream surfaces, 3 path-adjusted (learn/* → premium/*
or tutorials/*), and 1 structural (root prebuilt-components → its
shell-docs directory index). Surface identifiers match upstream so
PostHog `try_for_free_clicked` events can be reasoned about across
the cutover.

Skipped:

- `quickstart.mdx` (root) — routing shim, no real content
- `(root)/index.mdx` — shell-docs has no MDX docs landing
- Per-framework integration `index.mdx` files — shell-docs has no
  per-framework overview pages, the upstream FrameworkOverview
  afterFeatures slot has no equivalent
- `reference/v2/components/{CopilotChat,CopilotKit}.mdx` and
  `reference/v2/index.mdx` — shell-docs reference layout differs

PDX-110.
2026-05-05 11:38:29 -07:00
Sam Julien 1685ba84e3 feat(shell-docs): port OpsPlatformCTA component
Adds the four-variant sign-up CTA (card / inline / tile / info) that
upstream docs/ uses to drive the Enterprise Intelligence Platform
funnel. Wires it into the shared MDX registry so MDX pages can drop
`<OpsPlatformCTA>` inline.

Adapted to shell-docs conventions:

- Tokens swapped from indigo/purple Tailwind utilities to the
  --accent / --violet-light / --border / --text* CSS variables that
  shell-docs already uses, so the visuals match the rest of the site.
- Dropped the dark: modifiers (shell-docs has no dark theme yet).
- Replaced the lucide-react import with three inline SVG components
  (ArrowRight, Info, Sparkles) — shell-docs deliberately avoids the
  lucide dep, the mdx-registry uses emoji fallbacks for icons.
- Removed the client-side posthog.capture for try_for_free_clicked.
  shell-docs ships server-side PostHog (middleware) only and has no
  posthog-js; UTM params on the dashboard URL remain the source of
  truth for click attribution. Surface props are preserved as the
  utm_content value.

PDX-109.
2026-05-05 11:38:29 -07:00
Alem Tuzlak 23d4770537 feat(showcase): hand-rolled headless-chat suggestion chips + parity across 17 integrations (#4669)
## Summary

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

## What changed

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

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

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

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

## Verification

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

## What was NOT done

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

## Test plan

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

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

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

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

For google-adk/headless-complete: add a useDefaultRenderTool() wildcard
catch-all. The validator looks at page.tsx + hooks/* and a backend
agent file; google-adk's tool registrations live in tool-renderers.tsx
(unparsed) and there's no matching agents/headless_complete.py file,
so the validator saw an empty tool surface. The wildcard registers '*'
which matches every fixture tool — same pattern north-star already
uses in its own tool-renderers.tsx.
2026-05-05 18:03:03 +02:00
Markus Ecker 8623c4a9b5 fix(react-core): IntelligenceIndicator drops polling, gates on tool-call pending window
Replaces the agent.isRunning-driven phase entry (and its 200 ms polling
fallback) with a 100 ms grace timer on unresolved matching tool calls.
Replay flashes (tool call + result in the same tick during connectAgent
history hydration) no longer cross the threshold, so the pill stops
appearing on completed historical runs.

Spinner exits as soon as either agent.isRunning falls or a "real
follow-up" message arrives — assistant prose, a fresh user turn, or
anything that isn't a tool result / empty-content tool-call wrapper.
Multi-step tool chains stay on a single continuous pill (the
latest-matching-assistant slot still moves between messages without a
fade animation when the next bash assistant lands).

Polling and the snapshot-subscriber comment were a misdiagnosis of a
test artifact: useAgent's OnRunStatusChanged subscription is what the
rest of CopilotKit (CopilotChat stop button, MCPAppsActivityRenderer,
chat suggestions) relies on for isRunning falling-edge re-renders.

Tests cover three new cases: replay-flash suppression, multi-step
continuity across tool-result interleaving, and exit-on-prose-followup.
2026-05-05 17:57:41 +02:00
Alem Tuzlak c95d33d1fc fix(showcase/dashboard): cap maxPossible at D5 and align live-cell + RefDepth chips (#4667)
Follow-up to #4664 — same root cause, two more callsites and one
inflation.

## Two issues

### 1. Live cell + Ref Depth column still rendered red
`composed-cell.tsx`, `feature-grid.tsx` (via `ref-depth-column.tsx`) had
the same regression-vs-ceiling collision the matrix views did: they
passed `regression={depth.isRegression}` to `DepthChip`, and
`regression` short-circuits the chip to red regardless of `maxDepth`.
Switched them to pass `maxDepth={depth.maxPossible}` only.
`RefDepthCellProps.regression?` flips to `maxDepth?` to stop propagating
the dead prop.

### 2. `maxPossible` was inflated to 6
`computeMaxPossible` returned **6** whenever a D5 mapping existed, on
the assumption D6 was structurally reachable. There is no per-feature D6
registry, so D6 is a stretch goal in practice — every D5 cell rendered
amber as "1 below ceiling," even when it was the realistic ceiling. Cap
at 5; D6-green cells still render green because `depthColorClass` treats
`depth >= maxDepth` as at-ceiling.

This restores the cap from commit `eda75a512` (*"D5 mapping means max=5
not 6 (D6 probes are rare)"*) which was lost in the subsequent depth
thrash.

`page.tsx` `healthStats` also dropped its `isRegression` short-circuit
so the stats bar mirrors the chip's graduated logic instead of
double-counting non-ceiling cells as red.

## Verified locally

Pointed dev dashboard at production PocketBase + harness:
- Before: 539 D5 cells **amber**, 162 D4 green
- After: **701 green**, 0 amber, 0 red

## Test plan

- [x] `depth-utils`, `depth-chip`, `parity-matrix`, `cell-matrix`,
`composed-cell`, `feature-grid` test files — 115/115 passing
- [x] Visual check on local dashboard against prod data — all wired
cells now render green
- [ ] On deploy, confirm matrix view at
`dashboard.showcase.copilotkit.ai/#matrix:depth,health` matches local
2026-05-05 17:42:24 +02:00
Alem Tuzlak bf4bef3121 fix(showcase/beautiful-chat): render A2UI surfaces (fixed + dynamic schema) (#4668)
## Summary

Search Flights and Sales Dashboard pills on the langgraph-python
beautiful-chat demo now produce visible A2UI surfaces. Three independent
bugs were masking each other:

- **Tool args were silently rejected.** `Flight` TypedDict required `id`
+ `statusIcon`, which the aimock fixture doesn't supply. langchain
bounced the call with `flights.0.id: Field required` and the agent
surfaced the validation error string as the "tool result" — so the LLM
summarized "Two flights shown above" without any cards ever rendering.
Made `Flight` permissive (`total=False` then `list[dict]`); only the
fields `_build_flight_components` reads need to be there.
- **`search_flights` now expands flights into literal-children
FlightCards server-side.** The structural-children template form
(`Row.children = { componentId, path }`) doesn't reliably expand for our
custom catalog — the working sibling demo (`a2ui-fixed-schema`) avoids
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. Three new fixtures
at the top of `feature-parity.json`: a follow-up content match, the
secondary-LLM `render_a2ui` call, and the primary `generate_a2ui` call.

Reintroduced custom `Row`/`Column` renderers with `gap` support — the
basic catalog versions ignore it and the dashboard cards were squished.
Children are array-of-strings only (matches what the agent and fixture
emit).

## Test plan

- [x] All 7 tests in
`showcase/integrations/langgraph-python/tests/e2e/beautiful-chat.spec.ts`
pass (45s). Two new ones cover both pills end-to-end: `Search Flights
pill renders FlightCard surface from A2UI fixed schema` and `Sales
Dashboard pill renders A2UI dashboard surface`.
- [x] `pnpm test aimock-fixtures` passes (18/18) — fixture schema
validator is happy with the 3 new entries.
- [x] Manual visual confirmation: both pills render full surfaces with
proper card spacing.
- [x] No regression on existing `Toggle Theme` / `Pie Chart` / `Bar
Chart` pills.

## Notes

- Added a 3-second `waitForTimeout` to the spec's `beforeEach` so the v2
chat provider hydrates before suggestion clicks dispatch. Without it,
the click can race past hydration and silently no-op (the existing
pre-existing tests happened to be tolerant of this; the A2UI ones
aren't).
- System prompt cleaned up: dropped references to tools that don't exist
(`log_a2ui_event`, "enable app mode") and named `pieChart`/`barChart`
explicitly.
2026-05-05 17:41:35 +02:00
Lukas Moschitz 7baf4d05e8 fix(react-core): IntelligenceIndicator pill shrinks to content width
The auto-mount in `CopilotChatMessageView` puts the indicator inside
a flex column container (`cpk:flex cpk:flex-col`) whose default
`align-items: stretch` was overriding the pill's intended
`display: inline-flex` shrink-to-content behaviour, leaving the
pill stretched to the full chat width — out of proportion with the
short label.

Add `align-self: flex-start` to opt the pill out of the parent's
stretch. Pill renders at content width, anchored to the chat's
left edge in line with the assistant message bubble it represents.
2026-05-05 17:28:01 +02:00