Commit Graph

6618 Commits

Author SHA1 Message Date
Alem Tuzlak d551a2e779 fix(vscode-extension): resolve @copilotkit/shared to TS source to avoid rolldown CJS TDZ
@copilotkit/shared ships a CJS dist (utils/clipboard.cjs among others)
that rolldown wraps in __commonJSMin lazy-init closures. With circular
imports through react-core's markdown/chat chain, those closures get
accessed before their `let require_clipboard = ...` declaration has run,
producing a TDZ error at runtime:

  Uncaught ReferenceError: Cannot access 'require_clipboard' before initialization

Symptom: the hook-preview webview never renders anything — the module
graph fails to initialize before React can mount.

Fix: add @copilotkit/shared to workspaceSourceAliases so rolldown reads the
TS source directly and skips the CJS wrapper, matching the existing
workaround for @copilotkit/a2ui-renderer.
2026-04-20 10:59:44 +02:00
Alem Tuzlak 8a4cac3460 fix(vscode-extension): HostRoot as state, not useMemo — render pipeline was stuck
Root cause: HostRoot was computed via useMemo([payload]) that read
window.__copilotkit_hookSite. That global is set by executeBundle inside a
separate useEffect([payload]). React runs useMemo during render and
useEffect after commit, so on the first render with a new payload:

  1. setPayload(X) triggers re-render
  2. useMemo runs, reads the stale global → returns null
  3. Render commits showing 'Mounting host…'
  4. useEffect fires, executeBundle writes the global — no state change
  5. Harness mounts with () => null; RegistryReader fires setRegistry
  6. Re-render: useMemo deps unchanged → returns CACHED null
  7. UI stuck forever

mount-capture.test.tsx didn't catch this because it imports the fixture
directly and bypasses the bundle-then-resolve flow.

Fix:
- Extract the export-picking logic into resolve-host-root.ts (pure, unit
  tested) so future readers see the precedence order (default → first
  function) clearly.
- In App.tsx replace HostRoot useMemo with hostRoot useState populated
  inside the executeBundle useEffect. The state write after executeBundle
  triggers the re-render that was missing before. Clear window.__copilotkit_hookSite
  before each execute so a failed bundle can't serve a stale module.
- Wrap the setter's argument in () => fn because useState treats a
  function argument as an updater; we want hostRoot to BE the function,
  not the result of calling it.
2026-04-20 10:48:52 +02:00
Alem Tuzlak 65ea1a760a fix(vscode-extension): exclude __tests__/__fixtures__/__mocks__ from scan + gate saves by workspace
Root cause: HARDCODED_EXCLUDES omitted the standard Jest/Vitest directory
conventions. When running the extension against its own worktree (or any
repo that colocates test fixtures with source), we scanned fixture files
under src/**/__tests__/fixtures/*.tsx and listed them as real hook sites,
polluting the sidebar tree with entries the user perceives as 'outside' the
workspace.

Add __tests__, __fixtures__, __mocks__ to the excluded directory set so
the conventional boundary between test fixtures and shipped code is
respected.

Secondary fix: onDidSaveTextDocument fires for any .ts/.tsx the user saves,
including files opened via File > Open from outside the active workspace.
Those saves would push new sites into the tree via updateSitesForFile.
Gate the save handler on isInsideWorkspace(filePath, workspaceRoot) so a
stray editor tab doesn't leak entries.
2026-04-20 10:48:25 +02:00
Atai Barkai f4d4e6388a fix(ci): remove test-integration-tmp from starter-smoke matrix
I added it to the matrix in c3d105ae0 but the corresponding
examples/integrations/test-integration-tmp/ directory was never
created on this branch — the job fails on every PR run with
"No such file or directory".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:41:54 -07:00
Atai Barkai a12579167e fix(showcase/scripts): validate-parity skips command-only demos in missing-dir check
The auditableDemos filter (introduced for cli-start's informational
`command:` entry) was applied to the spec/qa SHOULD checks but not
the missing-demo-dir MUST check. Result: cli-start in langgraph-python's
manifest triggered a false missing-dir failure even though it has no
on-disk folder by design.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:37:00 -07:00
Atai Barkai 7644f180a6 fix(showcase): restore shared-state-read-write scaffolds + regen starters
Post-merge CI caught two regressions:

1. shared-state-read-write demo directories were on disk but never
   committed — 16 packages' manifests reference the demo but the
   page.tsx scaffolds weren't tracked. This failed validate-parity,
   bundle-demo-content tests, and drift-check transitively.

2. langgraph-python starter templates drifted after main added
   docstring region markers to weather-tool-backend; regenerating
   via `npx tsx generate-starters.ts` syncs the 17 starters.

Bundle (showcase/shell/src/data/demo-content.json) regenerated to
pick up the new demo content.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:34:13 -07:00
Atai Barkai 62a05003c1 Merge remote-tracking branch 'origin/main' into atai/2026-04-18/feature-port-no-docker-restructure
# Conflicts:
#	.github/workflows/showcase_deploy.yml
2026-04-19 21:29:07 -07:00
Atai Barkai 151ccb9ad8 perf(showcase/langgraph-python): mcp-apps — speed-biased system prompt (target <30s generation)
Drops the aspirational 185-line prompt (read_me preflight, multi-call
iteration, palette discipline, zone backgrounds, label/fixedPoint rules,
opening+mid+final cameraUpdates) in favor of a ~35-line shape that biases
the agent toward exactly one create_view call with 3-5 elements and a
single framing cameraUpdate. Downgrades gpt-4.1 → gpt-4o-mini since the
element schema is simple JSON and model latency dominates end-to-end time.

Measured end-to-end (agent/run SSE to RUN_FINISHED) on the showcase
runtime: 5-6s per prompt across two prompts × two runs, all producing a
single create_view call with 8 elements (clean 3-step flowchart;
client/server/db diagram). Previously 3-5 minutes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:14:48 -07:00
Atai Barkai 8e07f479c5 refactor(showcase/langgraph-python): interrupt-headless — side-by-side chat + empty-app-pane popup
Restructure the headless-interrupt cell so the app surface is empty by
default and the popup appears there (not inside the chat or as a global
modal) when the backend calls `interrupt()`. The user triggers the run
from a pre-built suggestion chip in the right-hand `CopilotChat`, which
mirrors the other in-app-action demos (hitl-in-app, gen-ui-interrupt).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:12:57 -07:00
Jordan Ritter e261a1fd70 fix(showcase/agno): read SSE incrementally in smoke route to work around agno SDK success-path hang (#4105)
## Summary

Reimplements the SSE incremental reader workaround from the now-closed
PR #4093 on a fresh branch off `main`.

## Background

PR #4093 was closed under the assumption that PR #4095 (agno SDK upgrade
to 2.5.17) had fixed the underlying SSE stream termination bug at the
source. Follow-up diagnostics on 2026-04-19 revealed that the SDK
upgrade only addressed the **error path**; production `/api/smoke` with
real API keys still hangs because the agno SDK does not reliably emit
`TEXT_MESSAGE_END` / `RUN_FINISHED` on the **success path**.

Documented in Notion page `3473aa38-1852-815b-9765-fd28fa53275a`, item
#5.

## Change

`showcase/packages/agno/src/app/api/smoke/route.ts` — swap `await
res.text()` for an incremental reader:

- Read `res.body` via `getReader()` + `TextDecoder` + string buffer
accumulator.
- On each chunk, check whether the accumulated buffer contains
`"type":"TEXT_MESSAGE_CONTENT"` along with `"OK"` in the delta. Once
seen, cancel the reader and return a 200 success envelope — do not await
a terminal event that the SDK may never send on the success path.
- If the stream closes cleanly without ever producing the confirmation
payload, return a 502 with `stage:"response_incomplete"` so regressions
surface clearly in the smoke monitor.
- Keep `AbortSignal.timeout(45000)` as the final safety net.
- Response envelope shape preserved for the smoke monitor parser.

## Scope

Only the agno `/api/smoke/route.ts` is touched. The other 16 showcase
starters use the same `await res.text()` pattern but none have exhibited
the hang in production — no speculative fixes.

## Caveat — this is a mitigation, not a fix

The real fix belongs upstream in the agno SDK's AG-UI interface. **Do
not merge-and-forget.** Keep this PR open until upstream is addressed
and the fix is verified in production with real API keys, then revisit
whether this client-side workaround can be removed.

## Test plan

- [x] Visual inspection of the diff matches the pattern from PR #4093
- [x] Standalone `tsc --noEmit` against `route.ts` with DOM + ES2017
libs — clean (only missing `@types/node` for `process`, expected in
dry-run; code compiles cleanly otherwise)
- [ ] Production curl sanity check against
`https://showcase-agno-production.up.railway.app/api/smoke` once
deployed
- [ ] Monitor next 12h of `Showcase: Smoke Monitor` runs for agno
stability

Closes/replaces the approach from #4093.
2026-04-19 21:11:59 -07:00
Atai Barkai 9eddb3004e docs(showcase/shell): unselected/prebuilt-components — folder with sub-pages
Convert unselected/prebuilt-components.mdx single-file into a folder
matching the main /docs/prebuilt-components/ structure:
  index.mdx, chat.mdx, sidebar.mdx, popup.mdx, meta.json

This way the nav builder creates a GROUP with CopilotChat /
CopilotSidebar / CopilotPopup children in the Built-in Agent sidebar
section, not just a single page link.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:07:33 -07:00
Jordan Ritter 4d1147d05f fix(showcase/agno): read SSE incrementally in smoke route to work around agno SDK success-path hang
Reimplements the approach from the now-closed PR #4093 (which I closed
after #4095 merged the agno 2.5.17 upgrade, on the belief that the SDK
bump had fixed the underlying SSE termination bug).

Follow-up evidence collected 2026-04-19 showed the SDK upgrade only
addressed the error path — production /api/smoke with real API keys
still hangs because the agno SDK does not reliably emit TEXT_MESSAGE_END
/ RUN_FINISHED on the success path. Documented in Notion page
3473aa381852815b9765fd28fa53275a, item #5.

Change: instead of `await res.text()` (which only resolves when the
server closes the stream), read res.body incrementally with
getReader() + TextDecoder. Short-circuit as soon as the buffer contains
`"type":"TEXT_MESSAGE_CONTENT"` with `"OK"` — the agent has produced
the expected output, so we cancel the reader and return a 200 success
envelope without awaiting a terminal event that may never arrive. If
the stream closes cleanly without confirmation, return a diagnostic
502 with stage="response_incomplete" so regressions surface clearly.
Keep the existing 45s AbortSignal timeout as a final safety net.

Response envelope shape is preserved for the smoke monitor parser.

This is a client-side mitigation, not a fix. The real fix belongs
upstream in the agno SDK's AG-UI interface. Keep this PR open until
upstream is addressed and verified in production with real keys.
2026-04-19 21:07:21 -07:00
Atai Barkai 0b171a5d12 feat(showcase/langgraph-python): mcp-apps — rich Excalidraw prompting guidance
Rewrites the mcp-apps agent system prompt from a minimal "call a tool and
populate the canvas" instruction into a detailed Excalidraw-aware
playbook. Adoptions:

- Workflow: instructs the agent to call `read_me` first (the Excalidraw
  MCP server's own format reference) before `create_view`, and to use
  `restoreCheckpoint` for follow-up edits.
- Layout principles: left-to-right vs. top-down vs. hub-and-spoke,
  3-7 node target, consistent sizing (160x70 rectangles, 120x80
  diamonds) and spacing (40-80px gutters, 60-120px viewport padding).
- Camera framing: opening `cameraUpdate` with a 4:3 size (400x300 →
  1600x1200), optional mid-diagram pans, and a REQUIRED final
  cameraUpdate that re-frames the whole diagram (otherwise the Excalidraw
  animation camera ends zoomed on the last-drawn element).
- Labels: prefer `label: {text, fontSize}` on shapes/arrows (auto-centers,
  auto-resizes) over bare `text:` fields (which Excalidraw silently
  ignores on rectangles).
- Arrow bindings via `fixedPoint` edge anchors rather than hand-placed
  coordinates; dashed stroke for async/optional paths; short label
  annotations on decision transitions.
- Palette discipline: draws from the read_me palette (pastel fills +
  primary strokes), caps at 3-4 background colors per diagram, assigns
  them semantically (blue=frontend, green=success, yellow=decision,
  red=error).
- Progressive emission order so the draw-on animation tells a story
  (zone → shape → its label → its outgoing arrows → next shape), with
  decorations last.

Also upgrades the model from gpt-4o-mini to gpt-4.1 because Excalidraw
element emission is structured/coordinate-heavy and a smarter model
produces visibly cleaner layouts (aligned nodes, edge-bound arrows,
labeled shapes) in practice.

Before: 3 colored boxes with no text (bare `text:` field silently
dropped), arrows ending on shape centers, no camera framing, no title.
After: 3 labeled boxes with consistent palette, edge-bound arrows with
transition labels, title text, cameraUpdate framing the diagram, and
the agent correctly consults `read_me` once per conversation for the
authoritative format reference.

Progressive streaming (Part 2 of the ask) was investigated and flagged
as shared-package-bound: `@ag-ui/mcp-apps-middleware` emits a single
`ACTIVITY_SNAPSHOT` only AFTER `RUN_FINISHED`, so there are no partial
tool-input events to consume in the cell. The Excalidraw MCP server does
animate elements in order once the full input arrives, which gives the
visual impression of progressive drawing without runtime changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:05:00 -07:00
Atai Barkai ac361eb853 feat(showcase/langgraph-python): open-gen-ui — educational visualization suggestions + rich prompt guidance
Replaces the generic greeting-card / Pomodoro / revenue-chart suggestions
on the Fully Open-Ended Generative UI (minimal) cell with a set tuned for
intricate, educational visualisations: 3D airplane pitch/yaw/roll, a
feed-forward neural network's forward pass, quicksort, and a Fourier
series square-wave build-up.

Uses the provider's `openGenerativeUI.designSkill` prop (which injects
agent context for the built-in `generateSandboxedUi` tool) to swap in a
visualisation-tuned authoring prompt in place of the default shadcn
design language — covering SVG/canvas geometry, CSS keyframe motion,
mandatory labels + legends + callouts, a semantic palette (indigo /
emerald / amber / rose / slate), typography scale, and the self-running
constraint for the minimal cell. Agent system prompt updated in parallel
so the LLM knows the cell's focus and contract up-front.

Advanced variant untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:01:21 -07:00
Atai Barkai 420bc802b6 fix(showcase/langgraph-python): interrupt-headless cell re-run flow
The per-kickoff `agent.setMessages([])` call was racing with the
subsequent `addMessage` + `runAgent` pair, causing the second run
attempt to silently not dispatch (connection-refused on resume in some
timings). Drop the reset — rely on the fresh langgraph thread that each
`runAgent` implicitly produces, and on the existing `runId` marker to
gate ResultCard visibility so the stale result doesn't flash under the
button mid-run.

Validated: initial → modal → result → re-click → modal appears again,
all without a page refresh.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:01:06 -07:00
Atai Barkai 4bc5f0f179 refactor(showcase/langgraph-python): gen-ui-agent uses CopilotKitMiddleware + direct state_schema
`create_deep_agent` does not accept `state_schema=` as a kwarg (confirmed
against the installed signature; state schema is only pluggable via
middleware). The minimal state-extending middleware is kept but renamed
to `_GenUiStateMiddleware` with a comment pinning its one purpose, and
`CopilotKitMiddleware` is added so this cell matches every other
langgraph-python cell.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:57:10 -07:00
Atai Barkai 319d2fac19 fix(showcase/shell): prebuilt-components customization ladder — avoid nested <p> hydration error
MDX wraps inline text inside HTML elements in <p> tags. Using <p> as
the outer wrapper for each card's description causes <p><p>text</p></p>
which breaks hydration. Switch to <div> as the outer wrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:56:21 -07:00
Atai Barkai 9a737b6c8d fix(showcase/langgraph-python): open-gen-ui-advanced sandbox-function bridge round-trip
The sandboxed iframe runs with `sandbox="allow-scripts"` only, so a
`<form>` with `<button type="submit">` had its submit blocked by the
browser BEFORE the onsubmit handler could call `e.preventDefault()` —
which meant `Websandbox.connection.remote.evaluateExpression(...)`
never fired. The agent also read `res.result` while the host handler
returns `{ ok, value }`.

Tightened the system prompt and per-suggestion prompts to explicitly
forbid `<form>` / `type="submit"` and to steer the LLM toward the
handler's exact return shape (`res.value` / `res.error`). Validated
end-to-end via Playwright: both `evaluateExpression` and `notifyHost`
now round-trip with visible results in the sandbox UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:53:45 -07:00
Atai Barkai d8e9092e99 feat(showcase/langgraph-python): declarative-gen-ui — advertise PieChart + BarChart in a2ui_dynamic system prompt
The PieChart + BarChart renderers were added in 8be81821e as part of the
brand-polish pass, but the a2ui_dynamic agent's system prompt was still
only mentioning dashboards/status/KPIs. Expand the prompt to enumerate
the registered catalog (Card, StatusBadge, Metric, InfoRow, PrimaryButton,
PieChart, BarChart) and name when each chart fits — so the LLM reliably
reaches for PieChart on part-of-whole breakdowns and BarChart on
cross-category comparisons.

Validated on port 4100 with Playwright: "Show a pie chart of sales by
region" renders a brand-coloured donut with legend + percentages, and
"Render a bar chart of quarterly revenue" renders a polished Recharts bar
chart with tooltip. No "Unknown component" errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:50:54 -07:00
Atai Barkai a425ffc273 chore(showcase): regenerate registry after gen-ui-agent reorder 2026-04-19 20:50:18 -07:00
Atai Barkai 01b8d17578 refactor(showcase): move gen-ui-agent to bottom of Operational Generative UI
Reorders gen-ui-agent (Agentic Generative UI / In-Chat State Rendering)
to appear AFTER Reasoning (Default Render) in the Operational
Generative UI category, per user preference.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:50:11 -07:00
Jordan Ritter 61b4ea62e5 ci(showcase): emit red→green transition alerts for deploy + smoke workflows (#4103)
## Why

#oss-alerts currently fires red alerts on failure but never posts a
recovery message when `Showcase: Build & Deploy` or `Starter Deployed
Smoke Tests` flip back to passing. Team reported this gap — there's no
positive signal when the pipeline is healthy again after an outage. Per
the oss-alerts verbosity policy, we want red→green transitions (but not
green→green spam).

## What

Mirrors the per-service transition pattern already shipped in
`showcase_smoke-monitor.yml` (`✅ agno recovered (was
down since <iso8601>)`), applied at the workflow level for these two
pipelines.

### `showcase_deploy.yml` (notify job)

- Restore previous run's status from `actions/cache` (same
key/restore-keys pattern the smoke monitor uses:
`showcase-deploy-state-<run_id>` save key, prefix-based restore)
- Classify outcome as `failure | success | skip`
- `failure` → post existing red alert (unchanged wording) + set state to
`failure`
- `success` AND `PREV=failure` → post recovery message + clear state to
`ok`
- `success` AND `PREV=ok` → silent (green→green — matches prior behavior
for bulk drift rebuilds)
- `skip` (no-changes push, cancellation, indeterminate) → no state
change, no post

### `starter_deployed_smoke.yml`

- Restore state before tests run
- After the test step, classify via `steps.playwright.outcome`
- On red→green, post recovery message alongside the existing
failure-alert path
- On any terminal outcome (passed or failed tests), save state;
cancelled runs leave state untouched so streaks aren't broken

## Design choices

- **State storage: `actions/cache`** — not a committed JSON file. Avoids
commit-loop concerns entirely. TTL is ~7 days, far longer than the run
cadence of either workflow (showcase deploy fires on every main push +
manual dispatch; starter smoke runs every 6h + on every deploy). Same
pattern as the smoke monitor, which has been stable.
- **First-ever run**: initialize state to `ok` so we don't emit a false
recovery alert on the first green run after this ships.
- **Recovery wording** (matches smoke-monitor convention):
- `✅ *Showcase deploy*: recovered (was down since
<iso8601>) | <url|View run>`
- `✅ *Starter Deployed Smoke Tests*: recovered (was
down since <iso8601>) | <url|View run>`
- **Existing red-alert wording is unchanged.**

## Edge cases considered

- First-ever run with no prior state: initializes to `ok` — no spurious
recovery alert
- Cancelled / mid-matrix cancellation / no-changes push: no state
change, prior red state survives into next run
- Cache eviction beyond TTL: same as first-ever run (assume `ok`)
- `workflow_dispatch` with single service: doesn't post Slack today,
doesn't update state (unchanged behavior)

## Note for reviewer

This PR touches `.github/workflows/*.yml` so **please merge via the UI**
— my `gh` token can't admin-merge workflow-touching PRs.

## Test plan

- [ ] CI passes
- [ ] Merge → next failing deploy run writes `lastStatus=failure` to
cache
- [ ] Next green run after a failure posts `✅ *Showcase
deploy*: recovered ...` in #oss-alerts
- [ ] Subsequent green runs stay silent
- [ ] Same verification for starter smoke tests
2026-04-19 20:41:09 -07:00
Atai Barkai 8be81821e2 refactor(showcase/langgraph-python): polish custom cell components to CopilotKit brand
Apply the verified CopilotKit brand palette (lilac #BEC2FF, mint #85ECCE,
near-black #010507, neutral greys) across every custom-defined component in
the langgraph-python cells. Replaces ad-hoc indigo/purple/amber/slate
Tailwind classes with brand tokens, softens corners (rounded-xl/2xl),
switches shadow-lg to shadow-sm, and normalises pill/label styling to
10-11px uppercase tracking-wider.

Preserves all component props, data-testid attributes, and @region markers.
Beautiful-chat (reference) is untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:38:36 -07:00
Atai Barkai bed8081340 chore(showcase): regenerate bundles after HITL row rename
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:32:53 -07:00
Atai Barkai 0cb9cd13ba refactor(showcase): rename In-Chat HITL rows to name the hook API
gen-ui-interrupt and hitl-in-chat both render an interactive time-picker
inline in the chat, but via different API layers:

- gen-ui-interrupt -> useInterrupt (low-level primitive)
- hitl-in-chat -> useHumanInTheLoop (ergonomic wrapper)

Rename to make the dashboard row label reflect the API distinction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:32:23 -07:00
Atai Barkai 52b9b2012a docs(showcase/shell): custom-look-and-feel — CSS first, Slots (Subcomponents), align unselected tree
- Reorder meta.json so CSS is the first sub-page (easiest rung of the
  customization ladder), then Slots, Headless UI, Reasoning Messages.
- Retitle slots.mdx frontmatter to "Slots (Subcomponents)" so the sidebar
  nav reads the user-facing term people actually search for.
- css.mdx: demonstrate the new file+lines Snippet by pulling the
  user/assistant bubble block straight from the cell's theme.css.
- headless-ui.mdx: expand from a bare IntegrationGrid stub into a full
  page with minimal + complete examples, the three core hooks, and
  Snippet pulls from both headless-simple and headless-complete cells.
- Mirror the css/slots changes into unselected/custom-look-and-feel/ so
  the framework-agnostic tree stays in step (add css.mdx, reorder
  meta.json, retitle slots nav).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:30:53 -07:00
Atai Barkai 384a803935 docs(showcase/shell): prebuilt-components — customization spectrum + per-component sub-pages
- Rewrite overview to present the 4-level customization ladder (drop-in →
  CSS → slots → headless), with a 2x2 card grid linking out to each rung.
- Add a new chat.mdx sub-page for CopilotChat with intro, InlineDemo,
  the CopilotChat GIF, provider-setup snippet, and the standard code
  example from docs.copilotkit.ai.
- Reorder meta.json to chat → sidebar → popup.
- Add gif embeds to sidebar.mdx and popup.mdx (matching docs.copilotkit.ai).
- Point stale /prebuilt-components cross-links at the new
  /prebuilt-components/chat page.
- Align unselected/prebuilt-components.mdx with the ladder framing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:30:38 -07:00
Atai Barkai e01168e5ef feat(showcase/shell): add Snippet file+lines support for arbitrary-file inclusion
<Snippet> now supports a second lookup mode alongside the existing
region="..." marker: file="..." lines="A-B" pulls a line range (or
the whole file when lines is omitted) from any file in the cell's
bundled files[]. Region lookup wins when both are passed, preserving
all existing call sites.

Parses dash ("10-20"), en-dash, and single-line ("12") ranges.
Surfaces the same graceful WarningBox on missing files / bad ranges
as the region path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:30:24 -07:00
Atai Barkai 63a0c19de7 refactor(showcase/langgraph-python): gen-ui-agent as deep agent with explicit state + tool
Rewrites the gen-ui-agent demo as a minimal deepagents-powered agent that
defines its own `GenUiAgentState` schema (extending langchain's AgentState)
and exposes a custom `set_steps` tool. The tool returns Command(update=...)
to mutate the typed `steps: list[Step]` field, and a one-line middleware
registers the extended schema with deepagents. A last-wins reducer on
`steps` tolerates concurrent tool calls.

No StateGraph, no copilotkit_emit_state, no TodoListMiddleware - the pattern
mirrors how real applications extend deepagents with domain state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 17:02:21 -07:00
Atai Barkai a1ed347faa Merge remote-tracking branch 'origin/main' into atai/2026-04-18/feature-port-no-docker-restructure
# Conflicts:
#	showcase/scripts/__tests__/bundle-demo-content.test.ts
#	showcase/scripts/lib/manifest.ts
#	showcase/scripts/validate-parity.ts
2026-04-19 16:40:48 -07:00
Atai Barkai d32e780696 refactor(showcase/langgraph-python): rewrite reasoning agents as minimal deep agents
Replace the synthetic _ReasoningEmitterModel + hand-rolled StateGraph
scaffolding in reasoning_agent.py and tool_rendering_reasoning_chain_agent.py
with minimal create_deep_agent graphs (mirrors gen_ui_agent). Drops ~340
lines of custom graph wrappers / synthetic reasoning emitters while
keeping the four mock tools (get_weather, search_flights, get_stock_price,
roll_dice) intact for the tool-rendering-reasoning-chain cell.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:31:47 -07:00
Atai Barkai 4bc956346f fix(showcase): null out hallucinated docs-links entries (wrong framework, wrong shell path)
Prior 4085 port blindly copied 4084 docs-links.json patterns, producing many
entries that pointed at wrong-framework docs (e.g. crewai-crews → crewai-flows),
nonexistent shell paths (e.g. /claude-sdk-typescript/... prefix doubled into
/claude-sdk-typescript/claude-sdk-typescript/...), or the wrong field name
(mastra used `shell_docs_url` with absolute http://localhost:3000 URLs).

Audit against live docs.copilotkit.ai and the 4085 shell at :4010 surfaced:
- 9 og_docs_url 404s (8 on claude-sdk-typescript under a nonexistent
  /claude-sdk-typescript/* slug, 1 on /ag2/multi-agent/subagents)
- 24 shell_docs_path 404s (8 claude-sdk-typescript, 6 pydantic-ai, 4 strands,
  4 mastra, 2 langgraph-python)
- crewai-crews pointing entirely at /crewai-flows/... (different product)

Fix: point each entry at a real docs.copilotkit.ai page scoped to the correct
framework OR null it out; normalize shell_docs_path to leading-slash form
that composes with the DocsRow `${shellUrl}/${slug}/unselected${path}` scheme;
null google-adk shell paths (no google-adk-scoped shell docs exist, better to
show ✗ than mislead). Regenerated registry + docs-status bundles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:11:52 -07:00
Atai Barkai dfaae83bcf refactor(showcase/langgraph-python): promote gen-ui-agent to primary via useCoAgentStateRender
- Backend: rewrite `gen_ui_agent.py` as a custom StateGraph that plans a
  3-5 step list via an LLM, then walks through pending->running->completed
  transitions for each step, publishing updates via copilotkit_emit_state.
  The planner LLM call uses copilotkit_customize_config(emit_messages=False)
  so its raw JSON plan never leaks into the chat transcript.
- Frontend: replace the v2 messageView.children + useAgent subscription
  with v1 useCoAgentStateRender from @copilotkit/react-core. The v1
  CopilotKit provider wraps v2 internally, so v2 CopilotChat still works
  inside it. The render prop receives {state, nodeName, status} and
  inlines an InlineAgentStateCard reading the agent's `steps` list.
- InlineAgentStateCard: refactor from a generic key/value dump to a
  proper stepwise tracker with per-step marker (pending number, running
  spinner, completed check) and completion headline.
- Registry: drop `kind: testing` from gen-ui-agent in feature-registry
  and polish its description to highlight the canonical pattern; also
  tighten the manifest.yaml demo description for the same reason.
- Regenerated showcase bundles (registry.json, demo-content.json,
  constraints.json) via `pnpm --filter @copilotkit/showcase-scripts run
  generate-registry && bundle-content`.

Validation (Playwright against localhost:4100/demos/gen-ui-agent):
- Initial: clean welcome screen + three suggestion pills.
- Mid-run: "Step 2 of 5" with first step checkmarked, second spinning,
  rest numbered -- planner JSON no longer leaking as raw text.
- Final: "All 5 steps complete" card + 1-2 sentence LLM summary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:06:00 -07:00
Atai Barkai a84eaaadc9 fix(showcase/langgraph-python): a2ui-fixed-schema book button updates after click (per beautiful-chat)
Override the basic catalog's stateless Button with an ActionButton that
tracks a local `done` state, so clicking "Book flight" visually
transitions to a disabled "✓ Booked" confirmation. Mirrors the
beautiful-chat ActionButton pattern in
src/app/demos/beautiful-chat/declarative-generative-ui/renderers.tsx.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:04:08 -07:00
Atai Barkai 1935abd120 feat(showcase/langgraph-python): add Frontend Tools (Async) cell demonstrating async useFrontendTool handler
Introduces the "Frontend Tools (Async)" showcase cell — the async sibling
to the in-app-actions "Frontend Tools" cell. Demonstrates the canonical
async useFrontendTool pattern where the handler awaits a real client-side
async operation and RETURNS A RESULT the agent uses.

Concept: a simulated client-side "notes database" query. The frontend
registers a `query_notes` tool whose async handler sleeps 500ms (emulating
IndexedDB / localStorage / local-cache latency) then filters an in-browser
notes array by keyword and returns matching notes. The agent awaits the
result and summarizes matches for the user.

Files:
- src/agents/frontend_tools_async.py — helpful-assistant graph with no
  backend tools; system prompt instructs the model to call `query_notes`
  for note searches (schema is injected at runtime from the frontend via
  CopilotKitMiddleware)
- src/app/demos/frontend-tools-async/page.tsx — CopilotKit provider +
  CopilotChat, `useFrontendTool({ handler: async (...) => { await sleep;
  return matches; } })` + per-tool render hook that shows a branded
  NotesCard, `useConfigureSuggestions` with three prompts
- src/app/demos/frontend-tools-async/notes-card.tsx — emerald/teal
  gradient card listing matched notes with tag chips
- langgraph.json — register `frontend_tools_async` graph
- manifest.yaml — features list + demos entry
- feature-registry.json — expanded description + docs URLs point to the
  canonical /frontend-tools docs (shared with the sibling cell)
- constraints.yaml — added to all three generative_ui profiles
- docs-links.json — langgraph-python override pointing at /frontend-tools

Validated end-to-end: agent successfully calls `query_notes` with keywords
extracted from natural-language prompts, awaits the async handler, and
summarizes the returned notes for the user.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:00:02 -07:00
Atai Barkai 5596c0f08f chore(showcase): delete Frontend Tools (Sync) cell (tool-rendering-frontend-tools)
Removes the `tool-rendering-frontend-tools` cell which was rendering as
"Frontend Tools (Sync)" on the dashboard. Also removes the orphaned
`frontend-tools-sync` feature-registry entry (no package referenced it).
A replacement "Frontend Tools (Async)" cell lands in a follow-up commit.

- Delete demo: src/app/demos/tool-rendering-frontend-tools/ (page + weather-card)
- Delete agent: src/agents/tool_rendering_frontend_tools.py
- Remove from: feature-registry, constraints.yaml (all three generative_ui
  profiles), manifest.yaml (features + demos), langgraph.json (graph),
  docs-links.json

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:59:37 -07:00
Atai Barkai 2c10faef6b refactor(showcase): rename hitl-in-app to "(Frontend Tools + async HITL)"
Clarify the positioning of the In-App Human in the Loop cell. The old
label was ambiguous with the in-chat variant; the new label surfaces
the core technical story at-a-glance: this is the async useFrontendTool
pattern where the approval UI pops up OUTSIDE the chat surface.

Also register the cell in the langgraph-python manifest (features list
+ demos entry pointing to the new files).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:58:33 -07:00
Atai Barkai 41fe1eb2e6 feat(showcase/langgraph-python): add hitl-in-app cell — async frontend-tool HITL with in-app popup
Introduces the "In-App Human in the Loop" cell, demonstrating the
canonical async useFrontendTool HITL pattern where the approval UI
lives OUTSIDE the chat surface.

Flow:
- Agent calls `request_user_approval` (frontend-registered)
- The async handler returns a Promise and stashes its `resolve` in
  component state
- An app-level modal dialog (portal'd to <body>, grid-sibling of
  CopilotChat — NOT inside the chat bubble tree) opens with the
  agent's message + optional context
- User clicks Approve / Reject (with optional note) → completion
  callback fires `resolve({ approved, reason })`
- Handler returns the value to the agent, which continues based on
  approval outcome

Files:
- src/agents/hitl_in_app.py — support-ops agent with tools=[] and a
  system prompt that requires calling `request_user_approval` before
  any customer-affecting action
- src/app/demos/hitl-in-app/page.tsx — layout (support-inbox panel +
  CopilotChat + app-level modal), frontend-tool registration,
  resolve-capture pattern, suggestions
- src/app/demos/hitl-in-app/approval-dialog.tsx — modal (createPortal
  to document.body) with Approve/Reject + optional reason textarea
- langgraph.json — register `hitl_in_app` graph

Starter mirror auto-generated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:56:21 -07:00
Atai Barkai 3653ff81fa feat(showcase/shell-internal): add per-column Red/Green status tally to Feature Matrix headers
Adds a compact ✓N · ✗M tally directly under each integration's name + language
sublabel in the Feature Matrix dashboard header. The tally aggregates the same
binary signals each cell already renders (docs-og, docs-shell, E2E, Smoke,
health) using DocsRow / CellStatus's resolution rules — including per-column
docs-links overrides — so the totals stay consistent with what's visible in
the body. QA age and ?/unknown/stale signals are intentionally skipped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:55:06 -07:00
Atai Barkai 8034be2c1f fix(showcase/langgraph-python): wire declarative-gen-ui + a2ui-fixed-schema using beautiful-chat pattern
Port the working beautiful-chat A2UI topology to the standalone A2UI cells.
Both previously mounted on the main /api/copilotkit with `injectA2UITool: true`,
which left the dynamic cell blank (no rendered surface) and crashed the
fixed-schema cell with React error #31 on unresolved `{ path }` bindings.

- Split each cell onto its own runtime endpoint
  (/api/copilotkit-declarative-gen-ui, /api/copilotkit-a2ui-fixed-schema),
  each with `a2ui.injectA2UITool: false`, mirroring beautiful-chat and the
  canonical examples/integrations/langgraph-python reference
- Rewrite src/agents/a2ui_dynamic.py to own an explicit `generate_a2ui`
  tool that binds `render_a2ui` via a secondary LLM (beautiful-chat pattern)
- Fix a2ui-fixed-schema catalog definitions to use a `DynString` union
  (string | { path: string }) so the GenericBinder resolves path bindings
  before handing props to renderers
- Drop the scoped `a2ui: { injectA2UITool: true, agents: [...] }` block
  from the main /api/copilotkit route since both cells now own their own
  runtimes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:54:06 -07:00
Atai Barkai 3d16f0e85b refactor(showcase): rename open-gen-ui-advanced to emphasize frontend function calling
The advanced variant's distinguishing feature is that the agent-authored,
sandboxed UI can invoke frontend-registered sandbox functions via
Websandbox.connection.remote.<name>(args). The old label "(Advanced)"
did not convey this. Rename to "Open-Ended Gen UI (Advanced: with
frontend function calling)" in both the feature registry and the
langgraph-python manifest, and update descriptions to match. The id
stays `open-gen-ui-advanced` so URLs remain stable.

Regenerate derived bundles (registry.json, demo-content.json,
docs-status.json).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:47:46 -07:00
Atai Barkai a04d8b04a4 fix(showcase/langgraph-python): wire open-gen-ui + advanced using beautiful-chat pattern
Replace the hardcoded copilotkit_manually_emit_tool_call stubs with
proper LLM-driven agents (create_agent + CopilotKitMiddleware) matching
the beautiful-chat reference. The runtime's openGenerativeUI flag
auto-registers generateSandboxedUi as a frontend tool; the middleware
merges it into the agent's tool list, so the LLM can generate real,
user-specific sandboxed UIs instead of emitting a canned "Hello!" card.

For the advanced cell, strengthen the sandbox-function bridge: swap the
trivial notifyHost for an evaluateExpression function that the UI
visibly round-trips via Websandbox.connection.remote, and update the
suggestion prompts to explicitly exercise the bridge.

Also wire starter suggestions on the minimal cell so users have a
one-click entry point.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:47:18 -07:00
Atai Barkai 8cef57aacb fix(showcase/langgraph-python): wire useFrontendTool render for final tool state
The `tool-rendering-frontend-tools` cell rendered its WeatherCard stuck at
the `--° F` / `--%` / `-- mph` placeholders even after the tool completed
and the chat text showed the real values. `useFrontendTool`'s render
callback receives `result` as a JSON-stringified string (core's run-handler
`JSON.stringify`s any non-string handler return before delivery), but the
render was just type-casting the string to an object — so every
`parsed.temperature` / `parsed.humidity` / `parsed.wind_speed` read was
`undefined` and each field fell through to the `??"--"` placeholder.

Parse `result` via a `parseJsonResult` helper (mirroring the primary
`tool-rendering` cell) so `status === "complete"` actually populates the
card with the handler's real values.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:45:24 -07:00
Atai Barkai 7cb19385b6 chore(showcase): delete declarative-gen-ui-hardcoded testing cell
The "Declarative Generative UI (A2UI — Custom Catalog)" single-file
prototype variant was a testing-only companion to the canonical
declarative-gen-ui 3-file BYOC pattern. Drop it everywhere:

- Delete src/app/demos/declarative-gen-ui-hardcoded/ cell directory
- Delete src/agents/a2ui_dynamic_hardcoded.py
- Remove from langgraph-python manifest.yaml (features + demos) and
  langgraph.json graphs
- Remove from docs-links.json, route.ts (agent entry + a2ui agents
  list), shared/feature-registry.json, shared/constraints.yaml
- Drop the Callout promoting it from a2ui/dynamic-schema.mdx
- Bump expected langgraph-python count 32 → 31 in generate-registry
  test; regenerate all bundles

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:33:43 -07:00
Atai Barkai 1b9b7ab0e6 chore(showcase): remove redundant prebuilt-chat row
Pre-Built: Chat was redundant with Pre-Built: CopilotChat — both rows
referred to the same CopilotChat surface with slightly different
framing. Drop prebuilt-chat everywhere:

- Delete src/app/demos/prebuilt-chat/ cell directory
- Remove from langgraph-python manifest.yaml features + demos
- Remove from shared/feature-registry.json features + chat-ui allowlist
- Remove from shared/constraints.yaml constrained-explicit
- Remove from src/app/api/copilotkit/route.ts neutral-fallthrough list
- Update expected counts in bundle-demo-content + generate-registry
  tests (langgraph now exposes 32 features, down from 33)
- Fix stale src/agents/main.py test expectation to
  src/agents/agentic_chat.py (main.py was split into a neutral assistant
  by an earlier Phase-1 fix commit)
- Regenerate shell/src/data/{registry,constraints,demo-content,
  docs-status}.json

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:22:51 -07:00
Atai Barkai 8f51a4ecf1 chore(showcase): regenerate demo-content bundle after highlight slim
Regenerated via `pnpm --filter @copilotkit/showcase-scripts run bundle-content`
after trimming the `highlight:` lists on langgraph-python cells so the
"show all files" toggle in the code viewer exposes materially more files
than the default "core" view.

Spot-check (core / all):
  beautiful-chat               9 / 31
  headless-complete            5 / 13
  tool-rendering               5 / 7
  tool-rendering-reasoning-chain  5 / 7
  chat-slots                   4 / 6
  gen-ui-tool-based            4 / 5
  open-gen-ui-advanced         4 / 5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:14:28 -07:00
Atai Barkai f9b09cb225 chore(showcase/langgraph-python): slim manifest highlight lists to true pedagogical core
Previously the `highlight:` list on many cells had been expanded to include
nearly every file in the demo folder — which made the code viewer's
"show all files" toggle meaningless because the default "core" view already
contained everything.

Reduce each large cell's highlight list to the pedagogically-core files
(page.tsx, main backend agent .py, the cell-specific runtime route, plus
1-2 signature named components) while leaving the rest of the demo folder
to show up in the "show all" view:

- beautiful-chat: 32/33 -> 9/31 (dropped ui/* primitives, theme css,
  lib/utils, hooks/index, use-theme, secondary canvas/layout pieces,
  todo-column/list, charts/config, meeting-time-picker, headless-chat,
  tool-rendering, declarative-generative-ui, + db.csv and schema json)
- headless-complete: 13/13 -> 5/13 (dropped per-role bubbles, cards,
  input-bar, typing-indicator, tool-renderers, highlight-note, weather/
  stock cards — they stay bundled as they sit in the demo folder)
- tool-rendering: 6/7 -> 5/7 (dropped custom-catchall-renderer)
- tool-rendering-reasoning-chain: 7/7 -> 5/7 (dropped reasoning-block and
  custom-catchall-renderer)
- chat-slots: 6/6 -> 4/6 (dropped custom-assistant-message and
  custom-disclaimer)
- gen-ui-tool-based: 5/5 -> 4/5 (dropped pie-chart)
- open-gen-ui-advanced: 5/5 -> 4/5 (dropped suggestions.ts)

Cells where every file is genuinely core (declarative-gen-ui 6/6,
a2ui-fixed-schema 8/8, shared-state-read-write 5/5, subagents 4/4) and
small cells (3-4 files) are untouched — task brief called these out as
acceptable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:14:16 -07:00
Atai Barkai 614927a809 chore(showcase): regenerate demo-content bundle after highlight expansion
Re-runs `pnpm --filter @copilotkit/showcase-scripts run bundle-content`
to repopulate `showcase/shell/src/data/demo-content.json` with the
expanded `highlight:` file lists from the previous commit. Affects only
`langgraph-python::*` entries; all other framework demos are unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:52:17 -07:00
Atai Barkai a951d9030c chore(showcase/langgraph-python): expand manifest highlight lists to include all relevant cell files
The langgraph-python manifest's `highlight:` lists were skimpy — most cells
listed only `page.tsx` even when the cell pulled in supporting components,
hooks, A2UI catalog files, dedicated runtime routes, or split per-cell agent
graphs. The code-viewer's left file tree at
`/integrations/langgraph-python/<cell>/code` therefore showed users a single
file when the actual relevant code lived across 5–30 files.

This commit walks every cell in the manifest and rebuilds each `highlight:`
list to cover:

- All `.tsx`/`.ts` files in `src/app/demos/<cell>/**` (recursively)
- The actual backend agent `.py` file (e.g. `agentic_chat.py`,
  `hitl_in_chat_agent.py`, `tool_rendering_frontend_tools.py`,
  `headless_complete.py`) — many cells were pointing at `main.py` even
  though they have their own dedicated graph
- The runtime `route.ts` the cell registers against
  (`copilotkit`, `copilotkit-ogui`, `copilotkit-mcp-apps`, or
  `copilotkit-beautiful-chat`)
- A2UI/data assets where applicable (`a2ui_schemas/*.json`,
  `beautiful_chat_data/*`)

The flagship `beautiful-chat` cell now surfaces all 32 supporting files
(components/example-canvas/*, components/example-layout/*,
components/generative-ui/*, components/ui/*, hooks/*, lib/*,
declarative-generative-ui/*, etc.) plus the backend agent + dedicated
runtime route.

No source code is touched — only the manifest's `highlight:` references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:51:56 -07:00
Atai Barkai 39740ac135 fix(showcase/shell): kill per-line gray rectangles in code viewer
The oneLight SyntaxHighlighter theme sets a near-white background on
both <pre> and the inner <code>. customStyle overrides the <pre>, but
the <code> child keeps its own background — and since <code> renders
inline, that bg hugs each line of text and shows as a pale per-line
rectangle against the dark page chrome, making untouched code look
like it's text-selected. Unset the <code> background so the chosen
<pre> background reads as a flat block.

Same fix 4084 already landed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:50:04 -07:00