## Summary
Two multimodal D5 fixes, both locally verified green.
**ms-agent-python (31/31 green):** `_MultimodalAgent.run()` override
used `*args/**kwargs` but `AgentFrameworkAgent.run()` expects
`input_data: dict`. Changed to match the base class signature and yield
events from the base generator.
**langroid (31/31 green):** `_normalize_part()` checked
`isinstance(part, dict)` but Pydantic deserializes AG-UI content parts
as model instances, not dicts. All multimodal parts were silently
dropped. Added Pydantic model detection via `model_dump()`.
## Test plan
- [x] ms-agent-python: 31/31 D5 green locally
- [x] langroid: 31/31 D5 green locally (both image + PDF turns pass)
The _normalize_part function in multimodal_agent.py checked
isinstance(part, dict) to gate all content-part processing.
When RunAgentInput is deserialized via Pydantic, ag_ui.core
types (TextInputContent, ImageInputContent, DocumentInputContent)
are model instances — not dicts — so every multimodal content
part was silently dropped.
This caused the D5 multimodal probe's PDF turn to fail: the user
message text was lost, the aimock matched the stale turn-1 fixture
instead of the turn-2 fixture, and the assertion saw the image
response where it expected the document response.
Convert Pydantic models to dicts via model_dump(by_alias=True)
before processing, preserving camelCase field names (mimeType)
that the rest of the function relies on.
## Summary
The `_MultimodalAgent.run()` override used `*args/**kwargs` but
`AgentFrameworkAgent.run()` expects `input_data: dict`. The mismatch
caused `TypeError: got an unexpected keyword argument 'messages'` at
runtime, making the multimodal endpoint return RUN_ERROR on every
request.
Fixed to match the base class signature and yield events from the base
generator.
Locally verified: ms-agent-python 31/31 D5 green.
## Test plan
- [x] ms-agent-python passes 31/31 D5 features locally
- [ ] CI passes
The _MultimodalAgent.run() override used *args/**kwargs but
AgentFrameworkAgent.run() expects input_data: dict. The mismatch
caused TypeError at runtime. Changed to match the base signature
and yield events from the base generator.
## Summary
- Switch `gen-ui-interrupt` and `interrupt-headless` demo pages in
built-in-agent from V1 `CopilotKit` (with named `agent=` prop) to V2
`CopilotKitProvider` with `useSingleEndpoint`
- Remove `agentId` prop from `CopilotChat` in both pages
## Why
The built-in-agent runtime (`/api/copilotkit/route.ts`) uses
CopilotRuntime V2 with `mode: "single-route"` and only registers a
single `default` agent. The two interrupt pages were using V1
`CopilotKit` with `agent="gen-ui-interrupt"` and
`agent="interrupt-headless"` respectively, which caused the runtime to
return agent-not-found errors since those named agents don't exist in
the V2 registry.
All other built-in-agent demo pages already use V2 `CopilotKitProvider`
with `useSingleEndpoint`. This PR aligns the two interrupt pages with
that pattern.
## Test plan
- [ ] D5 probe for `gen-ui-interrupt` on built-in-agent turns green
- [ ] D5 probe for `interrupt-headless` on built-in-agent turns green
- [ ] Other built-in-agent D5 features remain unaffected
gen-ui-interrupt and interrupt-headless pages were using V1 CopilotKit
with named agents (agent="gen-ui-interrupt", agent="interrupt-headless")
but the built-in-agent runtime only registers a single "default" agent
via CopilotRuntime V2. This caused 404/agent-not-found errors at D5.
Switch both pages to CopilotKitProvider with useSingleEndpoint and
remove agentId from CopilotChat, matching the pattern used by all
other built-in-agent demo pages.
## Summary
- Routes PostHog analytics through `docs.copilotkit.ai/ingest/*`
(rewritten to `eu.i.posthog.com`) so requests bypass ad blockers and
tracking-protection that target the PostHog hostname directly.
- Mirrors the existing setup on the marketing website (`../website`).
- Drops the `NEXT_PUBLIC_POSTHOG_HOST` dependency — host is now
hardcoded since it's tied to the proxy path.
## Changes
- `docs/next.config.mjs` — added two `beforeFiles` rewrites:
`/ingest/static/:path*` → `eu-assets.i.posthog.com/static/*`,
`/ingest/:path*` → `eu.i.posthog.com/*`
- `docs/lib/providers/posthog-provider.tsx` — `api_host: '/ingest'`,
`ui_host: 'https://eu.posthog.com'`, removed `POSTHOG_HOST` env-var
check
- `docs/middleware.ts` — excluded `ingest` from the redirect-middleware
matcher so proxy traffic skips it
## Test plan
- [ ] Deploy preview — confirm DevTools shows PostHog requests going to
`docs.copilotkit.ai/ingest/*` instead of `eu.i.posthog.com`
- [ ] Verify `$pageview` events appear in the PostHog dashboard (EU
project)
- [ ] Test with uBlock Origin / Brave Shields enabled — events should
still capture
- [ ] Verify session recordings still load (uses `/ingest/static/*` for
assets)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Routes PostHog analytics through docs.copilotkit.ai/ingest/* (rewrites to
eu.i.posthog.com) so requests bypass ad blockers and tracking-protection
that target the PostHog hostname directly. Mirrors the existing setup in
the marketing website.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reverts the example-app integration that was used for local end-to-end
testing of the inspector against an intelligence-backed runtime. The
example app is not part of the pnpm workspace, ships its own
package-lock.json, and pulls @copilotkit/* from the npm registry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary
PR #4542 incorrectly changed the langgraph-python declarative-gen-ui
route from `graphId: "a2ui_dynamic"` to `graphId: "sample_agent"` and
removed `injectA2UITool: false`. This caused a regression from 31/31
green to red.
The `a2ui_dynamic` graph owns the `generate_a2ui` tool itself — the
runtime must NOT auto-inject its own A2UI tool on top (`injectA2UITool:
false`). The `sample_agent` graph is a generic chat agent with no tools,
which can never produce A2UI surfaces.
## Test plan
- [ ] langgraph-python returns to D5 green (31/31)
PR #4542 incorrectly changed graphId from "a2ui_dynamic" to
"sample_agent" and removed injectA2UITool: false. The a2ui_dynamic
graph owns the generate_a2ui tool itself — the runtime must NOT
auto-inject. This caused langgraph-python to regress from 31/31 to red.
## Summary
- Switch byoc-hashbrown and byoc-json-render agent factories from `type:
"tanstack"` to `type: "custom"` with a dedicated stream converter,
matching the proven pattern used by the main built-in-agent factory
(`tanstack-factory.ts`)
- Remove invalid `response_format: { type: "json_object" }` from
`modelOptions` -- TanStack AI v0.8.x uses the OpenAI Responses API which
does not support this Chat Completions parameter
- System prompts already enforce JSON-only output; `temperature: 0.2` is
retained as a valid Responses API parameter
The `type: "tanstack"` path routes through the runtime's
`convertTanStackStream` which has a `runFinished` flag (PR #4476) that
blocks all events after the first `RUN_FINISHED`. Combined with the
invalid `response_format` parameter being silently rejected by the
Responses API, this prevented text events from reaching the frontend,
causing the D5 probe to timeout waiting for
`[data-testid="copilot-assistant-message"]`.
## Test plan
- [ ] Verify byoc-hashbrown D5 passes locally with `bin/showcase test
built-in-agent --d5`
- [ ] Verify all other 27 built-in-agent features still pass D5
- [ ] Verify byoc-json-render D5 passes (same fix pattern)
The byoc-hashbrown and byoc-json-render agents used `type: "tanstack"`
which routes through the runtime's `convertTanStackStream`. That
converter has a `runFinished` flag (PR #4476) that blocks all events
after the first RUN_FINISHED, which can prevent text events from
reaching the frontend.
Additionally, both agents passed `response_format: { type: "json_object" }`
via `modelOptions`. TanStack AI's OpenAI adapter v0.8.x uses the
Responses API (`client.responses.create()`), not Chat Completions. The
Responses API does not support `response_format` (it uses `text.format`
instead), so this parameter was silently causing failures.
Fix both issues by:
- Switching from `type: "tanstack"` to `type: "custom"` with a dedicated
stream converter that skips RUN_FINISHED and forwards text events,
matching the proven pattern in tanstack-factory.ts
- Removing the invalid `response_format` from modelOptions (the system
prompt already enforces JSON-only output)
- Keeping `temperature: 0.2` which is valid for the Responses API
## Summary
- Remove `from __future__ import annotations` from 3 llamaindex agents
that were timing out at D5
- The deferred annotations import causes Pydantic to fail with
"class-not-fully-defined" when resolving `Annotated[str, "..."]` tool
parameters, producing a `RUN_ERROR` SSE event instead of streaming text
- The D5 conversation runner cannot detect `RUN_ERROR` as an assistant
response, so it times out after 30s
## Affected agents
- `a2ui_fixed.py` (gen-ui-a2ui-fixed / a2ui-fixed-schema feature)
- `a2ui_dynamic.py` (gen-ui-declarative / declarative-gen-ui feature)
- `tool_rendering_reasoning_chain_agent.py`
(tool-rendering-reasoning-chain feature)
## Root cause
`from __future__ import annotations` (PEP 563) defers evaluation of all
annotations to strings. When the LlamaIndex `AGUIChatWorkflow` passes
`backend_tools` to Pydantic for schema generation, `Annotated[str,
"Origin airport code"]` is stored as the string `"Annotated[str, 'Origin
airport code']"` instead of the actual type. Pydantic cannot resolve
this and raises `PydanticUserError: class-not-fully-defined`.
Agents without `backend_tools` (like `reasoning_agent.py`) were
unaffected because the code path that triggers Pydantic schema
validation is never reached with an empty tool list.
## Test plan
- [x] Built Docker image locally and curled all 3 endpoints directly
- [x] Before fix: all 3 returned `RUN_ERROR` with Pydantic
class-not-fully-defined
- [x] After fix: all 3 stream `TEXT_MESSAGE_CHUNK` events and finish
with `RUN_FINISHED`
- [ ] CI green
- [ ] D5 probe passes for all 3 features on production
The `from __future__ import annotations` import causes all type
annotations to be stored as strings rather than evaluated at
definition time. When the LlamaIndex AGUIChatWorkflow validates
backend_tools via Pydantic, `Annotated[str, "..."]` parameters
fail with "class-not-fully-defined" because Pydantic cannot
resolve the deferred string annotations.
This caused RUN_ERROR on every request to these three agents,
which the D5 conversation runner cannot detect as a response,
leading to the 30s timeout.
Affected agents:
- tool_rendering_reasoning_chain_agent.py (4 backend tools)
- a2ui_fixed.py (display_flight backend tool)
- a2ui_dynamic.py (generate_a2ui backend tool)
Verified locally: all three endpoints now stream
TEXT_MESSAGE_CHUNK events and finish with RUN_FINISHED.
## Summary
The docs-only early return in `ComposedCellInner` only rendered
`DocsLayer`, skipping `LinksLayer` which renders `CommandCell` for demos
with a `command` field. The `npx copilotkit@latest init` starter command
disappeared from the matrix.
Fix: render `LinksLayer` alongside `DocsLayer` when links overlay is
active.
## Test plan
- [ ] CLI Start Command row shows the `npx` command text (not just docs
links)
- [ ] Other docs-only features unaffected
## Summary
- Fix race condition in the D5 auth probe where the post-signout chat
message was sent before React's `useEffect` flushed `setHeaders()`,
causing the request to go out with valid auth headers (no 401, no error
surface, 8s timeout)
- After clicking sign-out, the probe now waits for the auth banner to
flip to `data-authenticated="false"` plus a 500ms settle delay before
triggering the probe send
- Add unit test covering the new "banner doesn't flip" failure mode
## Test plan
- [x] All 7 d5-auth unit tests pass (including new banner-flip test)
- [x] TypeScript compiles clean
- [x] Verified all 18 integrations already have
`data-testid="auth-banner"` with `data-authenticated` attribute
- [ ] CI green
## Summary
- Add missing `agents.interrupt_crew` and `agents.tool_rendering` stubs
to the `_stub_agent_server_deps` fixture in `test_forwarded_props.py`
- The interrupt_crew import was added to `agent_server.py` in d6b784ee9
(interrupt demos PR) but the test fixture was not updated, causing
`ModuleNotFoundError` on all 5 tests that `import agent_server`
## Test plan
- [x] All 8 tests in `test_forwarded_props.py` pass locally (Python 3.9)
- [ ] CI: Python unit tests (3.10) pass
- [ ] CI: Python unit tests (3.12) pass
The docs-only early return only rendered DocsLayer, skipping LinksLayer
which is responsible for rendering CommandCell when a demo has a
command field. The npx starter command disappeared from the matrix.
After clicking sign-out, React's useEffect that calls setHeaders() runs
async (after paint). The probe was immediately filling the textarea and
sending a message before useEffect flushed, so the request went out with
valid auth headers — no 401 occurred, no error surface rendered, and the
probe timed out at 8s.
Add a waitForSelector gate on the auth banner's data-authenticated="false"
attribute plus a 500ms settle delay to ensure setHeaders() has flushed
before the probe triggers the post-signout chat send.
The _stub_agent_server_deps fixture was missing stubs for
agents.interrupt_crew and agents.tool_rendering, which were added to
agent_server.py in d6b784ee9 (interrupt demos). The missing
interrupt_crew stub caused ModuleNotFoundError on import, failing 5
tests on both Python 3.10 and 3.12 in the Showcase: Validate workflow.
## Summary
- Add missing `data-testid="copilot-assistant-message"` and
`data-message-role="assistant"` to claude-sdk-python's BYOC hashbrown
renderer, matching langgraph-python and claude-sdk-typescript
- Fix D5 auth probe to use JS-level `element.click()` instead of
Playwright `force: true`, which `<cpk-web-inspector>` silently
intercepts
## Details
**byoc**: The custom `AssistantMessageRenderer` in the hashbrown
renderer was missing the harness testid attributes. Without them the
conversation runner sees 0 assistant messages and times out at 30s.
**auth**: Playwright's `page.click(sel, { force: true })` dispatches
pointer events that the `<cpk-web-inspector>` overlay absorbs before
React's synthetic event system fires the `onClick`. Switching to
`page.evaluate(() => document.querySelector(sel).click())` triggers the
DOM click directly, reliably flipping the auth state so the 401 error
surface appears.
## Test plan
- [x] `showcase test claude-sdk-python --d5 --verbose` — 29/29 green on
two consecutive runs
- [x] No changes to demo functionality — both fixes are test
infrastructure / harness plumbing
## Summary
Fixes D5 (deep conversation) probe failures across 16 showcase
integrations, addressing 39 of 42 failing features. After this PR, we
expect 15-16/18 integrations at D5 green (up from 2/18).
**Root causes identified and fixed:**
- **byoc-hashbrown testid** (12 integrations): The custom HashBrown
renderer overrides CopilotChat's `assistantMessage` slot, dropping the
`data-testid="copilot-assistant-message"` attribute that the D5
conversation runner uses to count responses
- **langgraph-typescript server.mjs** (14 features): Only 5 of 25 graphs
were registered in the production LangGraph server — all unregistered
graph endpoints returned 404
- **Agent-not-found errors** (8 integrations): V1→V2 import mismatches,
missing agent registrations, per-request runtime creation race
conditions, and stale AgentConfig subclasses incompatible with LangGraph
0.6.0+
- **byoc-hashbrown backend wiring** (5 integrations): Agent name
mismatches, missing default aliases, wrong agent (mastra used
weatherAgent instead of a dedicated hashbrown agent)
- **Agno reasoning**: Stock Agno handler emits STEP_STARTED/FINISHED
(ignored by CopilotKit); replaced with custom handler emitting
REASONING_MESSAGE AG-UI events
- **ms-agent-python**: Missing chat-slots components, unregistered
interrupt agents, missing public/demo-files/ assets
- **mastra subagents**: e2e test expected nonexistent UI elements
**Remaining (3 llamaindex timeouts):** tool-rendering-reasoning-chain,
gen-ui-declarative, gen-ui-a2ui-fixed — exhaustive static analysis found
no code bug; hypothesis is a LlamaIndex `astream_chat_with_tools`
streaming issue when tool definitions are present but the response is
text-only. Needs runtime testing.
## Test plan
- [ ] CI passes
- [ ] Deploy to Railway (auto-deploy on merge)
- [ ] Wait for next D5 probe cycle (~15 min)
- [ ] Verify 15+ integrations at D5 green on the showcase dashboard
- [ ] Investigate remaining llamaindex timeouts with local Docker
container
The custom _run_reasoning_agent handler had a bug where text messages
weren't rendered by the frontend despite the backend emitting correct
AG-UI events. The stock AGUI handler works with reasoning=False and
aimock fixtures — the D5 probe checks for reasoning keywords in the
transcript, not for REASONING_MESSAGE events specifically.
Locally verified: 28/29 D5 features pass (only auth fails — pre-existing
auth gate regression unrelated to this change).
The CLI Start Command feature (kind: "docs-only") was rendering empty
cells in the dashboard grid because the docs row only displayed when the
"docs" overlay was explicitly toggled on. Since docs are the only content
for docs-only features, show the docs row whenever any content-producing
overlay is active (links, depth, health, or docs), not just docs alone.
The dashboard Dockerfile uses COPY paths prefixed with `showcase/...`
which expect the repo root as build context. The compose entry was
using `build: ./shell-dashboard` which set context to
showcase/shell-dashboard/, causing COPY failures in worktrees.
Split into explicit context (../ relative to compose file = repo root)
and dockerfile path so COPY paths resolve correctly.
The _run_reasoning_agent handler's fallback path (for aimock fixtures
that return plain text with "Reasoning:" prefix) was setting
answer_text="" which skipped emitting any TEXT_MESSAGE events.
CopilotKit requires a text message to render an assistant bubble in
the conversation view -- reasoning events alone produce no visible
DOM element that the D5 probe selectors can match, causing both
reasoning-display and tool-rendering-reasoning-chain to timeout
with 0 assistant messages.
Fix: set answer_text = full_text so the response is emitted as both
a reasoning message (for the ReasoningBlock slot) and a text message
(for the conversation transcript the probe reads).
The production LangGraph server only registered 5 of 25 graphs from
langgraph.json, causing 404s for all unregistered graph endpoints.
Also adds 6 missing agent registrations to the main route and
normalizes deploymentUrl trailing slashes across dedicated routes.
- agno: add default agent alias + per-request runtime
- langgraph-fastapi: add default agent alias
- llamaindex: fix agent name mismatch (byoc_hashbrown → byoc-hashbrown-demo)
- mastra: create dedicated byocHashbrownAgent with hashbrown system prompt
(was using weatherAgent which produced plain text instead of JSON)
- ms-agent-dotnet: upgrade byoc page to V2 CopilotKit import
The D5 conversation runner detects assistant responses via
data-testid="copilot-assistant-message". The byoc-hashbrown demo
overrides the assistantMessage slot with a custom HashBrown renderer,
which dropped that attribute. Without it the harness sees 0 messages
and times out.
## Summary
Adds `--isolate [name]` flag to `showcase test` so multiple
agents/sessions can run D5 probes without Docker container conflicts.
- `showcase test agno --d5 --isolate` — auto-names project
`isolate-<PID>`
- `showcase test agno --d5 --isolate d5verify` — explicit project name
When active, `apply_isolation()` offsets all host ports by +200, renames
containers from `showcase-*` to `<name>-*`, and sets
`COMPOSE_PROJECT_NAME`. The EXIT trap tears down the isolated group and
restores both `local-ports.json` and `docker-compose.local.yml` on exit.
## Test plan
- [x] Verified `--isolate d5verify` shows correct offset ports (3309 =
3109 + 200)
- [x] Containers start with `d5verify-*` names, don't conflict with
existing `showcase-*` group
- [x] Cleanup restores files and tears down containers on exit
- [ ] CI passes
Reverts #4504. The parallelized fetch change broke the dashboard's live
status connection, causing all integrations to show 'offline' and the
Feature Matrix to show 'OFFLINE'.
When passed to `showcase test`, creates an isolated Docker Compose
project with offset ports (+200) and renamed containers, allowing
multiple agents/sessions to run showcase tests simultaneously without
container conflicts.
Usage:
showcase test agno --d5 --isolate # auto-names isolate-<PID>
showcase test agno --d5 --isolate d5verify # explicit name
## Summary
Follow-up to #4502. With matrix cells memoized and SSE deltas coalesced,
the dashboard is much smoother — but the **initial dashboard load**
still freezes for a few seconds because:
1. **Initial PB fetch is 10 sequential round-trips.** `fetchInitial`
walks `getList(page=1, 200) → getList(page=2, 200) → …` up to 10 pages,
each awaiting the previous. Network wall time stacks.
2. **First commit with real data is unavoidably a full-matrix
re-render.** The empty-map → populated-map transition invalidates
per-key memo checks on every cell — that's 720 cell renders in one
synchronous React commit, blocking the main thread.
## Changes
- **Parallelize the initial fetch.** Pull page 1 sequentially to learn
`totalItems`, then fire pages 2..N concurrently via `Promise.all`. Wall
time drops from `sum(rtt_per_page)` to roughly `max(rtt_per_page)`
modulo network parallelism. PocketBase reads are independent so this is
safe.
- **`startTransition` around the initial `setRows(initial)`.** The first
big commit is unavoidable, but marking it as a transition lets React 19
yield to user input mid-walk instead of blocking for the entire render.
`setStatus` stays urgent so the "connecting → live" indicator still
flips immediately.
- **`startTransition` around the SSE flush.** Bursts that the 16ms
coalescer can't fully absorb (large reconnect replays, simultaneous
probe completions) still need to yield rather than block.
## Test plan
- [x] `useLiveStatus.test.tsx` 15/15 pass with parallelized fetch (the
mock handles arbitrary page numbers).
- [x] `composed-cell.test.tsx` 9/10 pass (1 pre-existing failure, same
as #4502).
- [x] No new TypeScript errors in `useLiveStatus.ts`.
- [ ] **Manual perf trace before/after on the live dashboard.**
Expected: initial-load wall time drops sharply (sequential → parallel
pages), and any remaining heavy commit no longer blocks the main thread
(transition lets React yield).
- [ ] **Functional sanity** — confirm rows still arrive correctly when
pages return out of order, and the "connecting → live" status transition
still fires before the heavy render.
## Summary
- The eval workflow command was missing `--ci`, causing it to try Docker
Compose lifecycle in CI — which immediately fails because
`showcase/.env` doesn't exist in the runner environment.
- This is why the auto-triggered eval on PR #4541 failed with exit code
1.
- The `--ci` flag tells the eval orchestrator to skip Docker lifecycle
and assume services are already running (or use native execution via
`ci-native-eval.sh`).
## Test plan
- [ ] Trigger eval on a PR, verify it no longer fails with "env file not
found"
Add interrupt demos (Strategy B), byoc-json-render demo (zero-tool
agent + @json-render frontend), and shared-state-streaming (per-token
STATE_SNAPSHOT emission via tool-call argument interception).
Spring AI moves from 4 unsupported features to 0.
Replace gen-ui-interrupt and interrupt-headless "not supported" stubs
with working demos using useFrontendTool + async Promise pattern.
Backend agents use system prompt + tools=[] — CopilotKit runtime
routes tool calls to the frontend handler. Pattern proven by
ms-agent-python/dotnet, now extended to ag2, agno, built-in-agent,
claude-sdk-python, claude-sdk-typescript, crewai-crews, google-adk,
langroid, llamaindex, mastra, pydantic-ai, strands.
The eval workflow was missing --ci, causing it to try Docker Compose
lifecycle in CI (which fails because there's no .env file). The --ci
flag skips Docker and assumes services are already running or uses
native execution.
## Summary
- The "Run Evaluation" link in PR comments was a GET endpoint that
dispatched the eval workflow directly. GitHub's link unfurling/preview
bot fetches URLs embedded in comments, which caused evals to
auto-trigger on every PR push without anyone clicking the link.
- Changed the GET endpoint to render a confirmation page (no side
effects). The actual dispatch now requires a POST via the form button
click.
- After dispatch, the response opens in a new tab (via `target="_blank"`
on the form) and redirects to the Actions workflow run page where
progress can be monitored — instead of redirecting back to the PR.
## Test plan
- [ ] Deploy eval-webhook to Railway
- [ ] Open a test PR, verify the bot comment link shows the confirmation
page (no auto-dispatch)
- [ ] Click "Run Evaluation" on the confirmation page, verify eval
dispatches and new tab opens to Actions run
- [ ] Verify the original tab preserves navigation history
Split GET /trigger/eval into a two-step flow: GET renders a confirmation
page with a "Run Evaluation" button, POST performs the actual dispatch.
This prevents GitHub's link unfurling bot from auto-triggering evals
when it fetches the URL from PR comments.
The POST handler polls for the Actions run URL after dispatch and opens
it in a new tab via window.open, with a fallback link if the run isn't
found within 5 seconds.
The intelligence-backed example was a standalone npm-managed monorepo
pinned to published @copilotkit/runtime 1.56.3, so iterating on the
runtime against an Intelligence platform required publishing a release
or hand-linking. Pulling its two JS apps into the pnpm workspace lets
them resolve workspace:* and use whatever the local packages currently
build to.
Specific changes:
- Adds the example's app and bff to pnpm-workspace.yaml.
- Switches their @copilotkit/* deps to workspace:*; adds
@copilotkit/web-inspector as a workspace dep on the frontend so the
inspector can mount alongside the chat.
- Adds a small <Inspector /> React component that side-effect-imports
@copilotkit/web-inspector to register the custom element and assigns
the CopilotKit core via a ref (Lit elements expect properties, not
attributes, for complex values).
- Bumps the docker-compose image to the rc.16 composite, which is the
earliest published tag containing CopilotKit/Intelligence#144's
/api/_inspect/threads/:id/{events,state} endpoints.
- Drops the example's package-lock.json so npm and pnpm don't fight
over lockfiles in the workspace.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The threads-detail sub-tabs (Conversation, Agent State, AG-UI Events)
all fetched eagerly on threadId change. Against an Intelligence-backed
runtime, the AG-UI events response can be many MB; the JSON.parse alone
blocks the main thread for several seconds while the user is still on
the conversation tab. Any sub-tab click queued during that window
couldn't fire until the parse finished, so the tab itself appeared
unresponsive — the user perceived 15s of frozen UI before the panel
swapped, and the active-tab highlight didn't paint either.
Two fixes:
1. Defer the events / state fetches to first sub-tab click. Conversation
stays eager because it's the default tab and visible immediately.
When the user clicks an Agent State or AG-UI Events sub-tab the fetch
kicks off then — so the heavy JSON.parse blocks AFTER the click has
registered, not before.
2. Add a `_panelInitializing` flag set on tab change and cleared in the
next animation frame. The render switches to a generic "Loading…"
placeholder while the flag is true, so the active-tab highlight and
spinner paint before the heavy per-tab render runs.
Total wait for events to display is unchanged; perceived responsiveness
of the click is now immediate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>