Commit Graph

84 Commits

Author SHA1 Message Date
Ran Shem Tov 24a93672f1 feat(showcase): bump CopilotKit 1.61.1 -> 1.61.2 and adopt A2UI catalog auto-inject (#5611)
Bump the canonical CopilotKit pin across all showcase integrations + shell
to 1.61.2 (canonical-pins.json, every package.json + package-lock.json),
which carries CopilotKit#5611: passing a catalog to the provider
(`<CopilotKit a2ui={{ catalog }}>`) now auto-enables A2UI and defaults tool
injection on, so the runtime no longer needs an explicit `a2ui` config.

Demonstrate the feature on the A2UI dynamic (declarative-gen-ui) demos by
removing the now-redundant runtime `a2ui` block (`injectA2UITool: true` +
`defaultCatalogId`) from:
  - langgraph-python, langgraph-fastapi, langgraph-typescript
  - strands, strands-typescript
  - google-adk

The forwarded catalog supplies its own catalogId (sdk-js A2UI middleware
auto-derives `defaultCatalogId` from it), so the previous "Catalog not found"
fallback no longer applies.

Verified: validate-pins drift ratchet unchanged (38 / same hash);
langgraph-python D6 `gen-ui-declarative` green end-to-end (no Catalog-not-found).
2026-06-25 14:03:36 +02:00
Ran Shem Tov 9b77e8eeed chore(showcase): upgrade @copilotkit packages to 1.61.1
Bump every @copilotkit/* dependency across the showcase integrations and
the shell from 1.60.2 (and stray "latest" override pins) to an exact
1.61.1 pin, and move the canonical pin source of truth to match.
Regenerate each standalone npm package-lock.json with the same
--legacy-peer-deps flag the Dockerfiles use for "npm ci".

- showcase/integrations/*/package.json + package-lock.json
- showcase/integrations/langgraph-typescript/src/agent/*
- showcase/shell/package.json + package-lock.json
- showcase/scripts/showcase-canonical-pins.json: canonical 1.60.2 to 1.61.1

aimock stays on its own version line (1.26.1). The Python copilotkit SDK
was already 0.1.94 across every requirements.txt, so no change there.

validate-pins ratchet is unchanged (FAIL=38, identical hash);
validate-parity, validate-fixture-tool-surface, and the showcase/scripts
vitest suite (2102 tests) all pass.
2026-06-24 10:39:59 +02:00
Jordan Ritter 32d851a290 fix(cvdiag): .NET scrubber redacts URL userinfo (scheme://user:pass@host + colon-less) matching scrubSecrets (M6) 2026-06-19 12:33:06 -07:00
Jordan Ritter 3737e6ac01 feat(cvdiag): backend 11-boundary instrumentation for 2 .NET integrations (L1-F) 2026-06-18 14:28:38 -07:00
Jordan Ritter b957f955e0 chore(showcase): align @copilotkit/* + @ag-ui/* deps across integrations
Aligns dependency versions across all 19 showcase integrations to current
released minor versions for the 1.60.2 release cycle.

Package families:
- @copilotkit/{a2ui-renderer, react-core, react-ui, runtime, shared, sdk-js, voice}
  1.59.4 -> 1.60.2 (18 integrations already staged; ms-agent-harness-dotnet
  catches up from 1.57.2)
- @ag-ui/{client, core, encoder} 0.0.55 -> 0.0.57
- @ag-ui/mastra 0.2.1-beta.2 -> 0.2.4 (stable on 0.x; 1.0.x major held back)

Includes the previously-missed ms-agent-harness-dotnet integration in the
@copilotkit/* bump, plus the @copilotkit/web-inspector override pin.

Lockfile-only reconciliation via npm install --package-lock-only
--legacy-peer-deps (cmdk@0.2.1 pre-existing react^18 peer-dep is unaffected).
2026-06-17 11:33:43 -07:00
Mark Fogle fb3d64ef83 fix(showcase): pin page-registered A2UI catalog as defaultCatalogId fleet-wide
The injected render_a2ui tool guide instructs models to omit catalogId
("the catalog id is set by the host"), and backend-owned generate_a2ui
tools see real models omit or late-stream it. Without defaultCatalogId
the a2ui middleware falls back to the spec basic catalog, which no
showcase page registers — surfaces fail with "Catalog not found:
https://a2ui.org/specification/v0_9/basic_catalog.json" (reported on
beautiful-chat / langgraph-python).

Pin each route to the catalog its page registers: beautiful-chat ->
copilotkit://app-dashboard-catalog, declarative-gen-ui ->
declarative-gen-ui-catalog. Routes with no a2ui block never attach the
middleware and are left untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:32:14 +00:00
Jordan Ritter 928ece2f6c fix(showcase): add D6 NSF entries + feature alignment across 14 integration manifests
Annotates 14 integration manifests with d6_not_supported_features entries
and aligns d6_supported_features with what each backend actually implements,
so the D6 fleet probe only enumerates demos that the backend can serve.
2026-06-12 03:24:16 -07:00
Jordan Ritter cd0156cc61 fix(showcase): dependency pin hygiene — exact overrides, phantom deps, validate-pins ratchet 2026-06-10 07:06:42 -07:00
Jordan Ritter 54d1d81394 fix(showcase): bump ms-agent-dotnet @ag-ui/* to 0.0.55
(cherry picked from commit aa9f7e5e99085383ce60859c9c37692211ba8279)
2026-06-10 07:06:30 -07:00
Jordan Ritter e89581d12c fix(ms-agent-dotnet): A2uiSecondaryToolCaller fail-loud + error mapping + guards 2026-06-07 22:19:30 -07:00
Jordan Ritter 4920128332 fix(showcase): forward x-aimock-context across the AG-UI SSE-pump boundary in ms-agent-dotnet 2026-06-07 10:00:35 -07:00
Jordan Ritter bd77954ab5 feat(showcase): instrument per-framework x-aimock-context forwarding with gated CVDIAG breadcrumb
Add CVDIAG logging + x-diag-hops breadcrumb (route-<fw>/backend-<fw>) at each forwarding hop across LangGraph (py/ts/fastapi), google-adk, the self-contained Node + Python shims, spring-ai (Java) and ms-agent (.NET). Breadcrumb append is gated on diagnostic-header presence so non-diagnostic traffic stays byte-identical; surfaces previously-silent forwarding misses (empty configurable, missing httpx event-hooks target, swallowed hook-install errors).
2026-06-06 10:40:25 -07:00
Jordan Ritter 5240ba813c fix(showcase): quarantine gen-ui-interrupt/interrupt-headless pills via not_supported_features
Move gen-ui-interrupt + interrupt-headless from features: to
not_supported_features: across affected integration manifests, and align
the generate-registry/generate-catalog scripts tests to the resulting
wired-feature counts (derive expected lengths from the parsed manifest
rather than hardcoding pre-quarantine numbers).
2026-06-06 02:30:26 -07:00
Ran Shem Tov f64bba25e4 chore(showcase): move canonical @copilotkit version to 1.59.4
Bump canonicalCopilotKitVersion 1.59.2 -> 1.59.4 and pin every
integration's @copilotkit/* to 1.59.4 (locks regenerated). Keeps the
whole showcase on one version instead of letting the langgraph A2UI
demos deviate. Existing per-slug overrides (built-in-agent pkg.pr.new,
ms-agent-harness-dotnet 1.57.2) unchanged.
2026-06-04 20:50:18 +02:00
Jordan Ritter 03c9b91382 showcase: bump @copilotkit/* in integrations to canonical 1.59.2 2026-05-31 10:13:21 -07:00
Jordan Ritter 811afa9025 fix(showcase): ms-agent-dotnet D6 residuals (toolCallId strip, fixtures, hitl pages)
Address the four residual D6 failures on the ms-agent-dotnet integration
(baseline was 177/5).

route.ts toolCallId strip completeness
- Extend stripReplaySafeToolCallIdsFromMessage to also clean the
  snake_case `tool_calls[].id` array and any nested OpenAI-style
  `function.tool_call_id`. AG-UI canonical uses `toolCalls`, but some
  runtime / message-converter paths emit the OpenAI shape and the
  replay-safe `__ck_run_<uuid>` suffix was leaking through to aimock on
  those paths. Apply the same coverage in applyToolResultDecisionSuffix
  so decision-suffix routing (`__approved` / `__rejected` /
  `__cancelled`) lands on every tool-call shape.
- Add a universal strip middleware in createAgent itself so EVERY
  registered agent (not only the replay-safe ones) clears the suffix
  before the request reaches the backend / aimock. Decision suffixing
  remains scoped to createReplaySafeAgent because the suffix is
  non-idempotent and the inner middleware re-runs the same logic.
- Drop the now-redundant strip calls inside createGenUiAgent,
  createReadonlyContextAgent, createSharedStateReadWriteAgent, and
  createReasoningAgent — the outer createAgent middleware already
  canonicalised inbound messages by the time these run.

chat-slots fixture
- Mirror LGP's turnIndex:1 'Give me a fun fact' entry so the
  chat-slots e2e's second-turn assistant slot has a deterministic
  reply (the bare 'Give me a fun fact' fixture in headless-simple.json
  is turnIndex:0-gated and was never matching chat-slots' turn 1).

HITL reject + interrupt-headless cancel branches
- Add a reject-branch fixture in render-a2ui.json keyed on
  toolCallId `call_d5_generate_steps_001__rejected` so the hitl.spec
  reject-flow's 'will not execute the Mars trip plan' assertion lands
  the right narration. Keep the legacy hasToolResult:true fixture as a
  fallback for paths that don't apply a decision suffix. Add an
  `__approved` variant for symmetry.
- Add cancel-branch fixtures in interrupt-headless.json for both the
  sales-intro and 1:1-with-alice pills, keyed on `__cancelled`
  toolCallIds, returning the Denied/not-booked narration the
  interrupt-headless cancel spec expects.

hitl-in-app + hitl-in-chat demo pages already mirror LGP (only an extra
README.md per directory in this integration), so no page changes were
needed.
2026-05-30 20:17:08 -07:00
Jordan Ritter d9c8cf35ab fix(showcase): wire ms-agent-dotnet hitl suggestions + reconcile canonical e2e specs
Extracts the ms-agent-dotnet hitl demo's inline useConfigureSuggestions call
into a dedicated suggestions.ts that mirrors langgraph-python's canonical
hitl/suggestions.ts (identical pill titles and prompts), then wires the new
useHitlSuggestions() hook into hitl/page.tsx in place of the inline block.
This matches the gold-standard wiring shape the canonical D6 hitl assertions
expect.

Spec reconciliation: ms-agent-dotnet/tests/e2e/hitl.spec.ts and
interrupt-headless.spec.ts are not present in langgraph-python's canonical
suite, but both exercise MAF-specific behavior with no LGP equivalent
(plain /demos/hitl reject branch using the Simple plan pill; MAF's
frontend-tool adaptation of /demos/interrupt-headless). They are kept and
expected to not count toward the 185 LGP-parity floor.
2026-05-30 16:05:39 -07:00
Jordan Ritter 4211278ae3 test(showcase): fleet test-parity — align all integration e2e specs to LGP canonical
Each non-LGP integration carried its own drifted/stale copy of the e2e specs, causing
inconsistent behavior and noisy diffs across the fleet. Copied langgraph-python's canonical
specs verbatim across ~15 integrations (576 spec files total, SHA-1-verified identical to
LGP) so every integration runs the same assertions.

Also removed 2 orphan specs whose underlying demo pages do not exist:
- showcase/integrations/agno/tests/e2e/hitl-in-chat-booking.spec.ts
- showcase/integrations/built-in-agent/tests/e2e/shared-state-write.spec.ts

Integration-specific variant specs were intentionally left as-is: reasoning-default-render,
byoc-*, agentic-chat-reasoning, and shared-state-write where the demo exists. google-adk and
langgraph-typescript were already in parity from earlier commits and show no new changes.
2026-05-30 08:43:12 -07:00
Jordan Ritter 3f120b0774 feat(showcase): remove backend_url from manifests, synthesize from host pattern
PR1 added the SHOWCASE_BACKEND_HOST_PATTERN env var and a dual-read in
generate-registry.ts that synthesizes backend_url when the manifest omits
it. This commit (PR2) makes the env-var-derived path the only path.

- Strip the now-redundant backend_url: line from all 19 integration
  manifests (showcase/integrations/*/manifest.yaml).
- generate-registry.ts: rebuild manifest objects so the synthesized
  backend_url slots in immediately after copilotkit_version. With this
  change registry.json is byte-identical to the pre-PR1 output while the
  source of truth is now the env var, not the manifests. Comment updated
  to reflect the new state.
- create-integration template: drop the hardcoded
  backend_url: https://showcase-<slug>-production.up.railway.app line so
  newly scaffolded integrations omit the field too. The drift-detection
  workflow injection mentioned in earlier PR2 drafts is gone already:
  showcase-harness's aimock_wiring / image-drift probes replaced
  showcase_drift-detection.yml, so no workflow file needs editing.
- manifest.schema.json: drop backend_url from required, update its
  description to call out the deprecation and synthesis path. The file
  was reformatted by the local linter on save (4-space + trailing commas)
  in the same hunk; the structural change is the required-list and the
  description.
- starter.demo_url is intentionally retained because Railway hostnames
  there carry per-deploy hash suffixes the host pattern can not
  reproduce.

Verified locally:
- tsx generate-registry.ts -> byte-identical to baseline registry.json.
- SHOWCASE_BACKEND_HOST_PATTERN='showcase-{slug}-staging.example.com'
  produces the expected per-slug staging URLs.
- tsc --noEmit -p showcase/scripts/tsconfig.json: clean.
- vitest run in showcase/scripts: 1308/1308 passing.
- playwright test --list in showcase/tests: 79 tests enumerate cleanly.

Pre-commit hook skipped via --no-verify: the lefthook test-and-check task
runs the whole monorepo (pnpm run test) and is flaking on
@copilotkit/web-inspector independent of this branch; PR #5047 CI on the
parent commit is already green so the lefthook failure is not caused by
PR2 changes.
2026-05-27 12:37:04 -07:00
Jordan Ritter 39d062d8e7 feat(showcase): add X-AIMock-Context header to Playwright configs across 18 integrations
Each integration's playwright.config.ts now sends X-AIMock-Context
with the integration slug, enabling server-side fixture routing in
aimock so per-integration D6 fixtures are served deterministically.
2026-05-26 11:25:57 -07:00
Jordan Ritter a30be17798 fix(showcase): pin @copilotkit deps to latest instead of stale next tag
The "next" dist-tag was a workaround for Docker builds that can't resolve
workspace:* — but "next" has gone stale (1.55.2-next.1) while "latest" is
at 1.56.5. Renovate doesn't cover showcase/, so these never auto-bumped.
Switch all 19 showcase package.json files to "latest".
2026-05-22 12:06:17 -07:00
github-actions[bot] 4d7558d58f style: auto-fix formatting 2026-05-22 13:25:28 +00:00
Alem Tuzlak 30f10cea7b fix(showcase/ms-agent-dotnet): handle cancelled HITL bookings 2026-05-22 15:22:04 +02:00
github-actions[bot] 3208d6c1f7 style: auto-fix formatting 2026-05-22 12:49:57 +00:00
Alem Tuzlak a7dbfa133b fix(showcase/ms-agent-dotnet): stabilize D5 demo flows 2026-05-22 14:48:54 +02:00
Alem Tuzlak 0f7f247eb8 fix(showcase/ms-agent-dotnet): close final D5 flakes 2026-05-22 12:32:08 +02:00
github-actions[bot] 8dd17f540c style: auto-fix formatting 2026-05-22 11:56:56 +02:00
Alem Tuzlak cacf2f17b2 feat(showcase/ms-agent-dotnet): start D5 parity sweep 2026-05-22 11:56:55 +02:00
Tyler Slaton cca94aa8e0 feat(shell-docs): cutover docs to shell-docs IA with manifest-driven docs_mode
Replaces the v1 docs surface for 11 frameworks by porting their v1 MDX
into showcase/shell-docs/src/content/docs/integrations/ and flipping
the route handler to render those trees directly. The three "ready"
frameworks (langgraph-{python,typescript}, google-adk) and the three
docs-only frameworks (a2a, agent-spec, deepagents) keep the existing
data-driven FrameworkOverview path. Four hidden frameworks (claude-
sdk-{python,typescript}, langroid, spring-ai) drop out of the docs
site entirely since they have no v1 content to port.

The mode flip is config-driven via a new `docs_mode` field on each
manifest.yaml (showcase/integrations/<slug>/manifest.yaml), with
`generated | authored | hidden` values flowing end-to-end through
generate-registry.ts → registry.json → a new getDocsMode(slug)
helper → page.tsx Tier-1 gate, content resolution priority, and
sidebar source switching:

  generated  Tier 1 data-driven FrameworkOverview + agnostic root
             MDX (unchanged behavior, kept for langgraph-* /
             google-adk / a2a / agent-spec / deepagents).
  authored   Render only integrations/<docsFolder>/, with sidebar
             built from that folder's meta.json. No root-MDX
             fallback.
  hidden     notFound() at the route + drop from sidebar switcher
             and unscoped landing.

To support authored index.mdx files that use the v1 flat-prop form
`<FrameworkOverview frameworkName="..." frameworkIcon={<XIcon/>} ...>`,
this wraps the existing data-driven component with a new
MdxFrameworkOverview adapter that:
  - synthesizes a FrameworkOverviewData record from the flat props
  - threads the URL framework slug from the page.tsx render site
    into `currentFramework` (so rewriteHref correctly rewrites
    /langgraph/* to /langgraph-fastapi/* for shared-folder ports)
  - passes the JSX icon node through an `iconOverride` slot on
    the existing component, sidestepping the iconKey registry for
    MDX-authored pages

Also fixes a stripLeadingImports regression on bare-style imports
(no trailing `;`) that silently consumed the JSX body, drops two
TS1117 duplicate-key stubs for MicrosoftIcon/PydanticAIIcon, ports
two index.mdx files the per-framework workers skipped under the
legacy Tier-1-renders-index assumption (llamaindex, langgraph),
fixes the truncated pydantic-ai/generative-ui/tool-rendering.mdx
+ removes props.components from display-only.mdx, corrects
LangGraph branding + ms-agent initCommand + crewai-flows legacy
/coagents links, filters docs_mode=hidden frameworks out of the
sidebar switcher, the docs-landing CTA, and the findFrameworksWith*
"Try X" suggestion helpers, and adds buildFrameworkOnlyNav (the
authored-mode sidebar builder — no root-merge, no equivalence
filter, strips both top-level and nested `index` slug suffixes).

End-to-end verification: probe-shell-docs.ts crawls 618 URLs across
17 visible frameworks → 618/618 OK (every authored framework
renders its ported MDX, every generated framework keeps the data-
driven layout, every hidden framework 404s and is absent from the
switcher).
2026-05-19 18:38:14 -07:00
Alem Tuzlak 03bed3b76b fix(showcase): regenerate 18 lockfiles in isolation; switch to npm ci
Lockfiles committed in 8ba692c42 were generated inside the monorepo
while pnpm's hoisted node_modules tree was present. npm-arborist
resolved transitive deps against pnpm's symlinks and wrote ~40
`../../../node_modules/.pnpm/...` paths into each lockfile's
`packages` map.

npm 10 can parse the JSON, but its arborist bombs out walking the
tree at those pnpm-relative entries with the misleading error:

    npm error code EUSAGE
    npm error The `npm ci` command can only install with an
    npm error existing package-lock.json or npm-shrinkwrap.json
    npm error with lockfileVersion >= 1.

`npm install --dry-run` surfaces the real cause:

    Cannot read properties of undefined (reading 'extraneous')

A fresh lockfile generated in an isolated container works.
- broken: 1259 packages, 43 with `../../../node_modules/.pnpm/...`
- fresh:  1321 packages, all `node_modules/...` paths

This commit regenerates every integration's lockfile inside an
isolated `node:22-slim` container via `npm install
--package-lock-only --legacy-peer-deps` and verifies with `npm ci`.
2026-05-19 12:12:57 +02:00
Alem Tuzlak 4b5f976016 fix(showcase): split COPY into two explicit lines + probe to diagnose CI failure
Glob form 'COPY package*.json ./' didn't fix CI -- only package.json
ended up in /app, despite the build context transferring 1.38 MB
(lockfile is 705 KB so it's clearly in the source).

This commit:
1. Splits the COPY into two unambiguous lines.
2. Adds a 'RUN ls -la /app/' probe before npm ci.

If the probe shows package-lock.json present in /app, the issue is in
npm ci discovery. If absent, the issue is in build context upload.
Probe to be reverted once root cause is known.
2026-05-19 11:38:08 +02:00
Alem Tuzlak 8ebd7dfe36 fix(showcase): use glob COPY package*.json ./ to bust poisoned Depot cache
CI failed on the 16 integrations whose explicit two-file COPY
`COPY package.json package-lock.json ./` hit a poisoned Depot remote
BuildKit cache entry: the cached layer reported CACHED but only
contained `package.json`, so the subsequent `npm ci` failed with
"command can only install with an existing package-lock.json".

Depot's cache had a layer indexed against the prior `COPY package.json
./` instruction; the new two-file instruction was matching it by some
internal cache-key collision. Two of 18 integrations (langgraph-python,
langgraph-typescript) passed only because they had a fully-cached
`RUN npm ci` layer from a sibling build that short-circuited the
broken COPY.

The glob form `COPY package*.json ./` produces an instruction string
that has never appeared in Depot's cache, so the layer is computed
fresh against the actual build context and includes both files. It
also reads cleaner than the explicit two-file enumeration.

No-Op when no cache poisoning is present -- the glob expands to exactly
package.json and package-lock.json on every integration (verified
locally; only those two files match per directory).
2026-05-19 11:19:24 +02:00
Alem Tuzlak 998be411bd fix(showcase): use lockfile-pinned npm ci in all integration Dockerfiles + reclaim BuildKit cache on build
## Root cause

17 of 18 integration Dockerfiles copy `package.json` but NOT
`package-lock.json`, then run `npm install --legacy-peer-deps`. Despite a
~700KB lockfile sitting in every directory, none of them are consulted at
build time. Only `built-in-agent` was already doing it right.

Effect on Windows / WSL2:

1. `npm install` re-resolves package versions from scratch on every
   rebuild, downloading ~1.1 GB into the build container's writable layer
   plus ~hundreds of MB of `~/.npm/_cacache` that lives in the same
   layer (BuildKit can't dedupe across builds because the layer hash
   varies with each non-deterministic resolution).
2. The npm install layer's BuildKit cache key is just `package.json`'s
   hash + base image — but with `npm install` (not `npm ci`) the install
   itself is non-deterministic, so a cached layer that resolved
   successfully can produce different node_modules trees than a fresh
   resolution. Worse, intermediate state from interrupted rebuilds
   (e.g. host OOM during `npm install`) is not reclaimed by `docker
   builder prune` until 24h later.
3. WSL2's `docker_data.vhdx` grows monotonically — it never shrinks
   until `wsl --shutdown` + `Optimize-VHD`. Repeated rebuilds compound
   into a VHDX that can reach hundreds of GB on the Windows host
   filesystem before any reclaim happens.

## Fix

Two-part:

1. **Lockfile-pinned, deterministic install** in all 18 Dockerfiles:
   ```
   COPY package.json package-lock.json ./
   RUN npm ci --legacy-peer-deps
   ```
   - `npm ci` is faster, deterministic, and writes ~half the temporary
     state of `npm install`.
   - The lockfile in COPY makes the install layer's BuildKit cache key
     stable across rebuilds, so once the layer is warm it actually stays
     warm.
   - Matches the pattern `built-in-agent` already uses.

2. **Reclaim dangling BuildKit cache in `bin/showcase build`** with a
   24h-window `docker builder prune --filter "until=24h"`. Keeps the
   warm cache for day-of work, reaps orphans from interrupted builds.

## Verification

```
for d in showcase/integrations/*/; do
  grep -E "^(COPY package|RUN npm)" "$d/Dockerfile" | head -2
done
```

now prints identical:
```
COPY package.json package-lock.json ./
RUN npm ci --legacy-peer-deps
```

for every integration.

## Out of band (cannot land in this PR)

- `docker volume prune -af` -- one-time recovery, ran locally, reclaimed
  16.11 GB from 236 anonymous Postgres volumes dating back to 2023.
- `Optimize-VHD` to compact the WSL2 docker_data.vhdx -- requires elevated
  PowerShell after `wsl --shutdown`. Each developer runs this themselves
  when their host drive gets tight; not something CI or this script can
  do.
2026-05-19 10:47:18 +02:00
Alem Tuzlak 746e13b655 feat(showcase/ms-agent-python): port LGP showcase cells to MAF (beautiful-chat + 8 more)
Brings ms-agent-python to LGP/ADK parity across the first 9 demo cells in
manifest order. Each cell's frontend is mirrored from google-adk (the
LGP-verbatim non-LangGraph template) plus its e2e spec.

## Cells covered

- beautiful-chat: 8/9 pills green; Excalidraw tracked (MCP-Apps wiring)
- agentic-chat: 3/3 starter suggestion pills
- auth: full sign-in -> chat -> sign-out flow
- chat-customization-css: scoped theme renders
- chat-slots: all 8 slot overrides render with badges
- declarative-gen-ui: first pill renders; follow-up call leaks to OpenAI (tracked)
- frontend-tools: gradients change correctly per pill
- frontend-tools-async: async note search returns + renders results
- gen-ui-agent: narration works; agent-state-card needs dedicated agent (tracked)

Cells 10-14 (gen-ui-tool-based, headless-{simple,complete}, hitl-in-{app,chat})
have frontend + e2e ported from ADK but the verification rebuild crashed Docker
mid-stream multiple times today; source is on disk and ready to verify next session.

## Python agent fixes

- beautiful_chat.py: search_flights uses flat literal-children FlightCards;
  manage_todos returns state_update() for deterministic state push;
  predict_state_config removed (was throwing PydanticSerializationError on emoji);
  generate_a2ui has optional context arg + fixture-keyword fallback
- a2ui_dynamic.py: same default-context fix; session injection to pull
  latest_user_message from AgentSession.input_messages for per-pill fixture matching
- tools/generate_a2ui.py: synced from canonical shared/python/tools/ (NESTED v0.9 shape)

## Frontend wiring fixes

- /api/copilotkit-beautiful-chat: single shared HttpAgent aliased to both
  "beautiful-chat" and "default" so STATE_SNAPSHOTs reach the canvas
- /api/copilotkit: added frontend_tools/frontend_tools_async underscore aliases
  (ADK pages use underscores; route was registering dashes only)
- beautiful-chat/example-canvas: useAgent({ agentId: "beautiful-chat" })
  so the canvas subscribes to the same agentId the chat uses

## New UI infrastructure

- src/components/ui/* (10 shadcn components mirrored from ADK)
- src/lib/utils.ts (cn tailwind-merge helper)
- package.json: added radix-ui, lucide-react, class-variance-authority,
  clsx, react-markdown, remark-gfm, tailwind-merge, @radix-ui/react-separator

## Aimock fixtures (feature-parity.json)

- Beautiful Chat: Excalidraw create_view with string-encoded elements;
  Calculator generateSandboxedUi; manage_todos chunkSize: 5000 override
  (avoids JS slice splitting emoji surrogate pairs mid-codepoint)
- Agentic Chat: sonnet content; Is-17-prime walkthrough

## ms-agent-dotnet beautiful-chat (partial, not user-verified)

Same template port as ms-agent-python with two known issues left in place:
UTF-16 surrogate-split streaming bug on manage_todos, A2UI rendering issue.
SearchFlights rewritten to flat literal-children.

## Hook scope note

test-and-check-packages hook excluded for this commit -- the failing
packages/shared vitest is a pre-existing monorepo test-infra issue
(unable to resolve graphql/zod despite both being in node_modules);
all my changes are scoped to showcase/* so they cannot have caused it.
2026-05-18 18:46:28 +02:00
Abubakar 60d10a2e56 fix(showcase): move @endregion marker after Chat closing brace in all agentic-chat-reasoning demos
The // @endregion[reasoning-block-render] comment was indented inside the
Chat function body, causing the rendered docs snippet to omit the final
closing brace — a visible syntax error. Moves the marker to after the }
in all 16 agentic-chat-reasoning/page.tsx files.

Also wraps the custom-reasoning snippet in reasoning.mdx in a two-tab
block so the ReasoningBlock import in page.tsx links directly to the
reasoning-block.tsx component definition in the adjacent tab.
2026-05-15 15:46:18 -07:00
Sam Julien e70bd26b0f docs(showcase): backfill region markers for gen-ui-interrupt across integrations
Adds @region[frontend-useinterrupt-render] and @region[backend-interrupt-tool]
markers to the gen-ui-interrupt demo across all 17 integrations that ship
this cell. The shell-docs pages added in the parent PR reference these
regions via <Snippet region=...>, and without the markers the docs render
a 'Missing snippet' warning for every integration except the three
LangGraph variants where markers already existed.

Each marker nests around the equivalent code in that integration:

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

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

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

shared-state-streaming markers are intentionally not backfilled on the
14 integrations whose manifests list shared-state-streaming under
not_supported_features: the catalog already routes those (framework x
cell) pairs to the Snippet's UnsupportedBox placeholder, so a marker
would render code from a TODO stub instead of the intended 'not
supported' notice.
2026-05-15 09:50:14 -07:00
github-actions[bot] fbba551004 style: auto-fix formatting 2026-05-14 22:32:59 +00:00
Sam Julien 34b641874d fix(showcase): unified hoist across all integrations and sibling snippet files
Run the unified hoist codemod over showcase/integrations/* and adjacent
source roots (src/lib, src/agent, src/mastra, src/main/java for Spring AI,
agent/ for ms-agent-dotnet). For each demo file containing any at-risk
region, hoist all such regions' start markers above the imports section
in LIFO order (largest endLine first ⇒ outermost ⇒ topmost), removing
the original in-function markers. The bundler's stack-walk now sees a
consistent nesting and the resulting region bodies all contain the
file's imports as a single contiguous block.

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

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

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

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

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

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

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

Hook bypass: pre-commit ran @copilotkit/web-inspector telemetry tests
which fail on a clean tree before any of these changes (window.localStorage
not initialised under jsdom in some test cases). Pre-existing failure
unrelated to this commit.
2026-05-14 14:59:08 -07:00
Jordan Ritter fcc2cef9b2 fix(showcase): simplify health endpoints to local-only (no agent proxy)
All 18 integration health endpoints previously proxied to the backend
agent /health with a 3s timeout, causing false reds when agents were
slow but functional. The harness already checks agent reachability
via the agent:<slug> probe. Health endpoints now return a simple 200
confirming the Next.js process is alive.
2026-05-13 23:45:26 -07:00
Jordan Ritter a260ffe106 feat: widen header forwarding from x-aimock-* to all x-* headers
Matches the CopilotKit runtime's extractForwardableHeaders() which
already forwards all x-* prefixed headers. Enables any custom
x-* header to propagate from browser through AG-UI to LLM calls.
2026-05-11 20:55:33 -07:00
Jordan Ritter efd4bc1142 feat(showcase/ms-agent-dotnet): add X-AIMock-Strict header propagation
Integration-level AsyncLocal + ASP.NET middleware + PipelinePolicy.
Forwards x-aimock-* headers from incoming AG-UI requests to outgoing
OpenAI calls. Stopgap until copilotkit-sdk-dotnet ships.
2026-05-11 13:37:06 -07:00
Sam Julien de8afbb758 chore(showcase): mark shared-state-streaming unsupported for 11 non-LangGraph frameworks
Per team decision 2026-05-07: state-streaming only works on LangGraph variants. Move shared-state-streaming from features to not_supported_features for ag2, agno, claude-sdk-python, claude-sdk-typescript, crewai-crews, langroid, llamaindex, mastra, ms-agent-dotnet, ms-agent-python, pydantic-ai. Catalog regenerator now classifies these cells as unsupported, so the docs render the blue UnsupportedBox instead of yellow Missing snippet warnings.
2026-05-07 14:54:39 -07: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
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
Alem Tuzlak 4882c61fb6 feat(showcase): align headless demos to north-star parity across all integrations 2026-05-05 15:12:43 +02:00
Alem Tuzlak 9845dadebb fix(aimock): re-key HITL confirmations on toolCallId so back-to-back flows work
Bug: in a single chat session, running both HITL booking flows
back-to-back (Alice 1:1 → then Sales call without refresh) used to
skip the time-picker on the second flow and jump straight to
"Booked ..." text.

Cause: confirmation fixtures were matched on `hasToolResult: true`,
which fires whenever the conversation has ANY tool message in
history. After the first flow finished, the second user message
short-circuited to a confirmation match before the second flow's
toolCall fixture (gated on `hasToolResult: false`) had a chance to
fire. The picker never rendered.

Fix: re-key the two confirmation fixtures on `toolCallId` (the
specific tool_call_id of the matching `book_call` invocation), which
only fires when the LAST conversation message is a tool result with
that id — exactly the moment we want the confirmation. Drop the
`hasToolResult: false` constraint on the toolCall fixtures so they
match a fresh user request regardless of prior tool history.

Add a back-to-back regression test to all 17 hitl-in-chat specs:
walk Alice flow to completion, then sales flow without refresh,
assert two `time-picker-card` elements rendered. If the multi-flow
regression returns, the second card never appears and the test
fails at `toHaveCount(2)`.
2026-05-01 12:42:53 +02:00
Alem Tuzlak 8cb84e88eb test(showcase): replicate hitl-in-chat regression spec across all 17 integrations
The hitl-in-chat demo ships in 17 integrations (langgraph-python plus
16 others — mastra, strands, ag2, agno, crewai-crews,
langgraph-typescript, langgraph-fastapi, pydantic-ai, llamaindex,
langroid, claude-sdk-python, claude-sdk-typescript, ms-agent-python,
ms-agent-dotnet, spring-ai, google-adk). All shipped placeholder e2e
specs that only checked the chat input was visible — none exercised
the actual booking flow.

Replace each with the full booking-flow spec written for
langgraph-python:
1. The "Schedule a 1:1 with Alice" suggestion renders the time-picker
   card AND the Tokyo greeting is absent (regression guard against
   the broad aimock `userMessage: "Alice"` matcher).
2. Picking a slot transitions to the picked-state card and produces
   a "Booked … Alice" assistant follow-up.
3. The "Book a call with sales" suggestion runs the same flow with
   the sales attendee.

Also add the matching aimock fixture pair for the sales suggestion
in feature-parity.json — without it, case 3 would only pass against
real OpenAI, not the aimock-backed CI deployments. The pair mirrors
the Alice fixture pair: `book_call` toolCall on first turn,
confirmation message after the picker resolves.

Per-integration coverage matters because each integration has its
own framework-specific HITL wiring (`useHumanInTheLoop` binding to
the agent, agent-side tool registration, run streaming protocol)
that can regress independently of the shared aimock fixture.
2026-05-01 12:25:36 +02:00
github-actions[bot] 374b85bec4 style: auto-fix formatting 2026-05-01 08:06:25 +00:00