Wave-1 widened the catch list in BeautifulChatAgent.GenerateA2ui from
specific upstream exceptions to a blanket catch (Exception ex). That
inadvertently swallowed InvalidOperationException thrown by
ApiKeyResolver.ResolveApiKey, which is the intentional fail-fast contract
for misconfigured deployments. With the blanket catch in place, a missing
or invalid API key produced a generic "unexpected_error" structured
response to end users while the operator received no clear startup-level
signal — exactly the silent-degradation failure mode the fail-fast was
designed to prevent.
Replace the blanket catch with specific catches for the two
runtime-recoverable exception types the secondary tool caller can throw
after the transport/SDK/cancellation handlers:
- JsonException — upstream returned malformed JSON
- KeyNotFoundException — upstream JSON missing required fields
(defensive; TryGetProperty guards most paths after wave-1)
Both map to the existing "upstream_malformed" structured-error taxonomy.
All other exceptions, including configuration errors like
ApiKeyResolver's InvalidOperationException, now propagate so a
misconfigured deployment fails loudly at the operator layer instead of
limping along behind a generic user-facing message.
ASP.NET Core hands control back to the middleware once the endpoint handler
completes via `await _next(context)`, but for streaming endpoints (AG-UI uses
`IAsyncEnumerable`/SSE) the response delegate continues writing to the response
body — and may issue downstream OpenAI calls — AFTER `_next` returns. The
previous `finally` clause reset `AimockHeaderContext` to an empty dictionary at
that point, which caused `AimockHeaderPolicy` to silently drop aimock headers
on those streaming-tail calls. That defeated the entire purpose of the
middleware for the exact codepath it was built to serve.
The `finally`-clear was also unnecessary for isolation: `AsyncLocal<T>` is
scoped to the current execution context, so each ASP.NET request gets its own
slot automatically. There is no cross-request leakage to defend against.
Remove the `try`/`finally` and just call `AimockHeaderContext.Set(headers)`
followed by `await _next(context)`. Add a comment documenting why no reset is
performed.
ApiKeyResolver.IsMockEndpoint compared Uri.Host against "[::1]", but
System.Uri.Host strips the surrounding brackets and returns "::1" for
inputs like http://[::1]:8000/. The bracketed comparison was therefore
dead code: developers running aimock on IPv6 loopback got the fail-fast
error instead of the intended mock-key fallback.
Change the literal to "::1" and update the inline + docstring comments
to reflect the bracket-less form.
- BeautifulChatStateSnapshotAgent.RunCoreAsync now coalesces a null
response.Messages to an empty array before constructing the new
List<ChatMessage>. Previously, an inner agent that returned no
messages would cause `new List<ChatMessage>(null)` to throw
ArgumentNullException, masking the real upstream behaviour.
- GenerateA2ui's empty-content branch now returns the canonical
BeautifulChatA2ui.StructuredError shape (error / message /
remediation / errorId) like every other error path in the method,
instead of an ad-hoc { error, errorId } object. The frontend
expects the structured shape with remediation guidance.
Program.cs#CreateOpenAiClient previously read the OpenAI endpoint solely from
the OPENAI_BASE_URL environment variable and fell back to
ApiKeyResolver.DefaultOpenAiEndpoint. The secondary tool-calling HTTP client
(A2uiSecondaryToolCaller) instead routes through ApiKeyResolver.ResolveEndpoint,
which checks env, then configuration[OPENAI_BASE_URL] (appsettings.json /
user-secrets), then the default.
When OPENAI_BASE_URL was supplied only via configuration (e.g. user-secrets in
local dev), the primary client silently dialed the public Azure-hosted models
endpoint while the secondary client dialed the configured aimock. The two
endpoints diverged with no visible signal, breaking aimock-routed flows and
masking misconfigurations.
Switch CreateOpenAiClient to call ApiKeyResolver.ResolveEndpoint so both
clients share a single source of truth. Logging is preserved and now reports
which source supplied the endpoint (env, configuration, or default).
When iterating IHeaderDictionary's underlying store yields case-variant
duplicates (e.g., a misbehaving proxy injecting both `X-Foo` and `x-foo`),
the previous GroupBy + ToDictionary path silently kept only the first value
and discarded the rest. For aimock context routing — where header semantics
drive fixture selection — silent drops are a debugging nightmare.
We still keep `.First()` because HTTP defines no canonical merge for
case-variant collisions across distinct keys (the comma-join rule only
applies when keys are ASCII-equal). Instead, when a group has more than
one entry, we emit a structured warning naming the key, the kept value,
and the number of dropped variants, so operators can spot the upstream
misbehavior in logs.
Constructor now takes `ILogger<AimockHeaderMiddleware>` — ASP.NET's
middleware activator injects it automatically via `UseMiddleware<T>()`.
Two surgical hardening fixes to ApiKeyResolver:
1. IsMockEndpoint: drop host.StartsWith("aimock.", ...) and
host.EndsWith(".aimock", ...). The StartsWith match is exploitable
— an attacker-registered domain like aimock.attacker.example.com
would be classified as a mock endpoint and bypass the fail-fast,
silently returning the mock key. The EndsWith match is unused
noise (no .aimock TLD exists). Only exact, well-known mock hosts
("localhost", "127.0.0.1", "0.0.0.0", "[::1]", "aimock") are
accepted. IPv6 loopback [::1] is added so dual-stack dev paths
are still covered.
2. ResolveApiKey: change !string.IsNullOrEmpty(apiKey) to
!string.IsNullOrWhiteSpace(apiKey). A whitespace-only key such as
" " would otherwise be accepted as valid, bypassing the mock-key
/fail-fast logic entirely and sending a bogus key upstream.
- RunCoreAsync: avoid mutating AgentResponse.Messages in place. Reassign
Messages to a fresh List<ChatMessage> so the path is safe regardless of
whether the inner agent returns a mutable list or an immutable
IReadOnlyList wrapper. Prevents NotSupportedException at runtime; all
other response metadata (AgentId, ResponseId, Usage, RawRepresentation,
...) is preserved via the property setter.
- RunCoreStreamingAsync: only emit the trailing todos snapshot if the
inner stream completed normally. Wrap the inner enumerator in
try/finally with a streamCompletedNormally flag; on early exit
(throw or cancellation) log a warning and skip the snapshot rather
than emitting potentially stale state to the frontend. The trailing
yield lives outside the try block (idiomatic C# pattern since `yield`
cannot live inside `try { } catch { }`).
The previous implementation used Contains() substring matching against the
full endpoint URL, which is exploitable. An attacker-controlled endpoint
such as https://attacker.example.com/aimock-decoy or
https://api.openai.com/?env=localhost would be classified as a mock and
bypass the fail-fast guard, silently returning the sk-mock-local key for
what is actually a non-mock destination.
Parse the URL and inspect only the host component, matching exact dev
hosts (localhost, 127.0.0.1, 0.0.0.0, aimock) plus aimock subdomains.
Path, query, and arbitrary subdomain segments containing "aimock" or
"localhost" no longer trigger the mock fallback.
The header propagation chain (middleware -> context -> policy) had two bugs
that combined to threaten D5/D6 header-forwarding:
1. AimockHeaderMiddleware.ToDictionary used the default ORDINAL case-sensitive
comparer. ASP.NET's IHeaderDictionary is case-insensitive, but iterating
the underlying store can yield case-variant duplicates (e.g., a misbehaving
proxy injecting both `X-Foo` and `x-foo`). Default-comparer ToDictionary
throws ArgumentException on duplicates and fails the request.
2. AimockHeaderContext.Set lowercased all keys via ToLowerInvariant.
AimockHeaderMiddleware captured original case; the context then mutated
the casing; AimockHeaderPolicy.TryGetValue then matched against whatever
case the OpenAI SDK happened to use. This is inconsistent and aimock
fixture matching can be case-sensitive depending on configuration.
Canonical strategy: preserve original header casing as captured by the
middleware, but compare case-insensitively throughout via
StringComparer.OrdinalIgnoreCase. The middleware now also groups variants
defensively so duplicate keys cannot blow up the dictionary build.
AimockHeaderPolicy's add-if-absent TryGetValue then works correctly under
case-insensitive comparison without any further changes.
The GitHubToken line shipped `ghp_...` as a literal placeholder VALUE. When
a developer runs `cp .env.example .env` and forgets to edit, the entrypoint's
`-z "$GitHubToken"` check sees a non-empty string and skips the "key missing"
warning. The literal `ghp_...` is then sent upstream, producing a confusing
401 that looks like an OpenAI/GitHub Models bug rather than a setup issue.
Move the format example into a comment above the line and leave the value
empty so the empty-value check in entrypoint.sh fires the clear warning.
OPENAI_API_KEY was already empty (prior fix); verified still empty.
- entrypoint.sh: replace `sleep 3 && kill -0` agent-startup gate with a curl
retry loop against /health on :8000 (up to 30s). The bare PID check only
proved the process existed; if Kestrel hadn't finished binding, Next.js
would proxy to a dead backend for ~90s until the watchdog killed the
container.
- entrypoint.sh: watchdog now also supervises Next.js. If Next.js dies while
the agent stays healthy the watchdog breaks out so wait -n can return and
Railway can restart the container instead of serving a broken page.
- entrypoint.sh + .env.example: align the env-var contract with what
agent/Program.cs actually reads. The .NET agent uses OPENAI_API_KEY,
GitHubToken (fallback), and optional OPENAI_BASE_URL — it never reads
AZURE_OPENAI_API_KEY. The startup warning and .env.example now document
the real key precedence plus every Next.js-side var (AGENT_URL,
NEXT_PUBLIC_BASE_URL, MCP_SERVER_URL, SHOWCASE_DEBUG_TOKEN).
- Replace silent `return null` paths in A2uiSecondaryToolCaller with
TryGetProperty guards that each emit a structured LogWarning naming
the exact missing/unexpected field (choices, message, tool_calls,
function, name mismatch, arguments). Callers can now tell why a
design-tool call produced no content.
- Add ILogger parameter to GetDesignToolArgumentsAsync and pass
BeautifulChatAgent._logger from the single call site so warnings
flow into the existing log stream.
- Log the response body (truncated to 1 KB) at LogWarning before
EnsureSuccessStatusCode throws, so upstream error payloads survive
the throw and reach operators.
- Extract the OPENAI_API_KEY/GitHubToken/sk-mock-local fallback chain
from Program.cs and A2uiSecondaryToolCaller.cs into a new
ApiKeyResolver helper. Both call sites now share one implementation.
- ApiKeyResolver fails fast with InvalidOperationException + LogCritical
when no real key is present and OPENAI_BASE_URL is not an
aimock/localhost endpoint, so misconfigured prod deploys cannot
silently send sk-mock-local to a real LLM provider. The silent
mock-key fallback is preserved for aimock/localhost dev endpoints.
- RunCoreAsync: append todos snapshot DataContent to AgentResponse so non-streaming
callers receive the same state mirror that RunCoreStreamingAsync already emits.
- ManageTodos: defensive-copy each incoming todo before storing (mirrors the
symmetry of GetTodosSnapshot) so callers cannot mutate our backing list by
retaining input references.
- ManageTodos: validate Status against the documented "pending" | "completed" set;
coerce out-of-range values to "pending" with a LogWarning instead of letting
arbitrary LLM-supplied strings into shared state.
- GenerateA2ui: add a final catch (Exception) returning a StructuredError
("unexpected_error", ...) matching the existing taxonomy, and log an info-level
entry when OperationCanceledException flows through (was previously silent).
AimockHeaderPolicy previously called message.Request.Headers.Set(...)
unconditionally for every key returned by AimockHeaderContext, which
silently clobbered any header already set by an earlier pipeline policy
or the SDK itself (e.g. x-request-id, x-correlation-id).
Switch both Process and ProcessAsync to add-if-absent semantics, using
PipelineRequestHeaders.TryGetValue to skip keys that already have a value
on the outbound request. New aimock x-* headers still propagate; existing
correlation/SDK headers are preserved.
Aligned everything to npm to match what the Dockerfile already uses
(`npm ci --legacy-peer-deps`) and the committed `package-lock.json`.
The sibling `ms-agent-dotnet` integration uses the same npm-based
setup, so npm is the established convention.
Changes:
- playwright.config.ts: webServer.command now `npm run dev` (was `pnpm dev`),
so local E2E works in environments without pnpm installed.
- package.json: removed the redundant top-level `pnpm.overrides` block.
The equivalent override is already declared under npm's `overrides`
field, so the pnpm block was dead weight given that npm is canonical.
- package.json: `scripts.dev` now uses `concurrently -k --success first`
so a crashing .NET agent surfaces during local dev instead of leaving
Next running headlessly.
Add a prominent warning banner above the aimock service block in
showcase/docker-compose.local.yml documenting that --proxy-only lets
unmatched fixture requests fall through to real OpenAI/Anthropic/Gemini.
That behavior is fine for interactive local dev (you can capture new
fixtures from real responses) but dangerous in any automated context:
a missing fixture produces a real LLM response, and tests/CI see a
green check that is actually a false positive while burning real
provider tokens. Comment-only change; no behavior change.
main added its own CANONICAL_FRAMEWORKS const after this branch was cut.
CI tests the merge commit, so the duplicate declaration caused a build
error. Replace with an inline derivation from FRAMEWORKS so the variable
is self-contained and never conflicts with whatever main defines.
The root /build-with-agents page had 290 lines of inline content that had
drifted from the canonical mcp-server-setup.mdx snippet: wrong MCP endpoint
paths (/mcp vs /sse), and missing Tadata attribution Callout that every
per-framework build-with-agents page renders.
Replace with <MCPSetup /> to use the same shared snippet as the langgraph
integration page, ensuring the root page and all framework pages render
identical, authoritative content from a single source of truth.
S16 in SUBPATH_RENAMES already generates /<fw>/coding-agents → /<fw>/build-with-agents
for all 13 legacy frameworks including unchanged-slug ones (agno, ag2, pydantic-ai,
llamaindex, mastra, agent-spec, a2a). Including them in CANONICAL_FRAMEWORKS created
7 duplicate source entries in the redirect table, corrupting PostHog decommission
attribution (the CA×<fw> IDs would never get traffic).
Restrict CANONICAL_FRAMEWORKS to frameworks whose canonical slug differs from their
legacy slug (langgraph-python, google-adk, crewai-crews, ms-agent-dotnet, strands,
built-in-agent) — these are the ones S16 can't cover since S16 sources use legacy slugs.
CANONICAL_FRAMEWORKS was referenced in CODING_AGENTS_RENAMES but never
defined, causing a TypeScript error. Derive it from FRAMEWORKS.map(canonicalSlug)
so all 13 canonical slugs (langgraph-python, google-adk, strands, etc.) get
/coding-agents → /build-with-agents redirects.
## Summary
Lands the per-framework fixture reorg + D6 probe driver + harness
scoping work that was parked behind the ag-ui header-forwarding chain
(now shipped via #4984, #4951, #5015, #5016).
This is the foundational data layer the D6 dashboard needs to populate.
Slice 1 (#5018) shipped the rendering plumbing earlier today; this PR
makes d6:<slug>/<featureId> PB rows start flowing.
## What ships
- 477 per-integration aimock fixtures organized under `d4/`, `d6/`,
`shared/` directories (flat `d5-all.json` / `feature-parity.json`
deprecated)
- Every fixture keyed by `match.context` to enforce per-integration
isolation (server-side routing already merged in aimock #226)
- D6 all-pills probe driver + per-integration scoping in
showcase-harness
- X-AIMock-Context header propagation in 18 integration Playwright
configs
- D6-ceiling chip color algorithm (D6 is integration-scoped aggregate,
maxPossible raised from 5 to 6)
- Docker-compose updates for the new fixture dir layout
- 12 HITL fixtures migrated from main's d5-all.json additions into
shared/_migrated-from-d5-all-hitl.json
## Why this is safe to ship now
- ag-ui/LangGraph configurable+context HTTP 400 blocker is fixed (#5015
+ #5016)
- sdk-python 0.1.91 with `_extract_forwarded_headers_from_config` is on
PyPI and pinned across showcase
- aimock server-side context routing is already live (aimock #226)
- The SDK overlay hacks the branch carried locally are now redundant —
discarded before rebase
## Pre-existing CI note
`@copilotkit/web-inspector:test` has a pre-existing failure
(`window.localStorage.clear is not a function` in telemetry tests) —
verified on clean main checkout. Not introduced by this PR.
## Follow-ups
- Distribute migrated HITL fixtures from shared/_migrated-from-*.json
into per-integration d6/<slug>/ files
- Slice 2: D6 drilldown DIMENSIONS + AdaptiveStatsBar rollup section
- LGP gen-ui-interrupt second-pill framework bug (Hypothesis B in
useInterrupt hook)
PR #4927 landed this rename in the legacy `docs/` tree, but `showcase/shell-docs`
has its own content directory that was never updated.
Changes:
- Rename 11 `coding-agents.mdx` → `build-with-agents.mdx` (root + 10 integrations)
- Update frontmatter title "Coding Agents" → "Build with agents" in all 11 files
- Update `"coding-agents"` → `"build-with-agents"` in 9 integration meta.json nav files
- Update root meta.json: rename entry + add React Native under new ---Platforms--- section
- seo-redirects.ts: update S4/S15 subpath destinations; add S16 (coding-agents→build-with-agents)
subpath rename for all legacy framework slugs; add CODING_AGENTS_RENAMES for root + all
canonical framework slugs; fix stale destinations in F20, R12, R18, R19
- docs-render.tsx: update SUBPATH_TO_COMPONENT key "coding-agents" → "build-with-agents"
The four fixture routing regression tests still referenced the old
monolithic d5-all.json / smoke.json / feature-parity.json files that
were reorganized into per-integration d4/ d6/ shared/ directories.
Changes:
- Load fixtures via glob from d6/langgraph-python/ (reference
integration) instead of deleted monolithic files
- Add _context to test requests (aimock 1.26.1 checks req._context
against match.context for per-integration scoping)
- Adapt subagents test from toolCallId-based chaining to
turnIndex-based chaining (matches new D6 fixture structure)
- Adapt state-context test to D6 context-scoping model (no
systemMessage matching; routing happens via X-AIMock-Context)
- Remove _migrated-from-*.json shared files (all fixtures already
exist in per-integration D6 dirs; the migration files caused
620 shared-vs-scoped collisions)
- Add KNOWN_DUPLICATE_CEILING=11 ratchet for pre-existing D6
intra-feature duplicate match keys
Add fixture analysis/split/merge scripts for the D6 restructure,
update aimock fixture collision detection tests for the new directory
layout, update GOTCHAS.md and QA-COVERAGE.md with D6 notes, and
add --d6 flag support to the showcase test CLI.
Update depth-utils to treat D6 as an integration-scoped aggregate
(d6:<slug> not d6:<slug>/<featureId>), raise maxPossible from 5 to 6
when D5 mapping exists, and adjust chipColor derivation so D5-green
without D6 yields amber instead of green. Update composed-cell memo
comparator and cell-drilldown dimensions. Comprehensive test updates
across cell-model, depth-utils, compute-tally-detail, unified-cell,
and status-tab.
Replace single-file volume mounts with directory mounts (shared/, d4/,
d6/) so new fixture files are picked up without editing compose files.
Remove --proxy-only flag to catch fixture gaps instead of silently
falling through to real API. Add LANGGRAPH_HTTP env var from main.
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.
Add d6-all-pills driver that exercises every pill on every integration
behind aimock context routing. Rename e2e-chat-tools/e2e-deep to
d4-chat-roundtrip/d5-single-pill to match depth convention. Wire
D5 representative map, D6 scoping helpers, dimension types, and
the orchestrator config for the new probe IDs.
## Summary
Adds a D6 overlay section to the dashboard, showing green/gray/red
counts across all wired cells based on parity-vs-reference probe
results. Pairs with #5018 (CellModel D6 field) and #5020 (D6 drilldown
dimension).
## Files
- **overlay-types.ts**: add `"d6"` to the `Overlay` union and
`ALL_OVERLAYS` array
- **adaptive-stats-bar.tsx**: new `D6Section` component + `D6Stats`
interface + `d6Stats` prop
- **overlay-toggle-bar.tsx**: add D6 to `ALL_OVERLAYS` and
`OVERLAY_LABELS` for the toggle pill
- **page.tsx**: compute D6 stats via `resolveCell` and pass to
`AdaptiveStatsBar`
- **overlay-toggle-bar.test.tsx**: update pill count assertion (5 -> 6)
- **overlay-selector-integration.test.tsx**: add `"d6"` to the
all-overlays test case
## Test plan
- [x] 44 existing overlay tests pass (overlay-toggle-bar,
overlay-selector-integration, useOverlays)
- [ ] Dashboard shows D6 toggle pill; toggling it shows "X green / Y
gray / Z red" tally
Move monolithic d5-all.json + feature-parity.json + smoke.json into
per-integration directories under d4/<slug>/, d6/<slug>/, and shared/.
Every fixture file is now context-scoped to enable server-side aimock
routing via match.context. Migrated 12 HITL fixtures from main's
d5-all.json additions into shared/_migrated-from-d5-all-hitl.json
for follow-up distribution into per-integration files.
## Summary
- **6 prebuilt-components pages** were missing their
`PrebuiltComponents` import, causing the `inlineSnippets()` regex to
skip them and the `framework` prop to be dropped (iframe URLs defaulted
to `langgraph` instead of the correct integration)
- **8 HITL pages** had copy-pasted code examples using the deprecated v1
`parameters: [{ name, type }]` array format instead of `parameters:
z.object({...})` Zod schemas
- Added a `checkComponentImports()` validation to `verify-shell-docs.ts`
to catch missing snippet imports going forward
### Affected pages
**Prebuilt-components** (missing import): agno, aws-strands,
crewai-flows, llamaindex, microsoft-agent-framework, pydantic-ai
**HITL code examples** (deprecated params format): adk, ag2, agent-spec,
agno, llamaindex, mastra, microsoft-agent-framework, pydantic-ai
## Test plan
- [ ] Serve shell-docs locally (`cd showcase/shell-docs && npx next
dev`) and verify prebuilt-components pages render with correct iframe
content
- [ ] Verify HITL pages show `parameters: z.object({...})` in code
blocks
- [ ] Run `npx tsx showcase/scripts/verify-shell-docs.ts --skip-build`
and confirm no component-import warnings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
Adds D6 (Parity / Reference) to the cell-drilldown DIMENSIONS array so
clicking any cell chip shows D6 status alongside d5/e2e/d2/health/smoke.
CellModel already has the d6 field (#5018); this is the one-line missing
piece to surface it.
## Test plan
- [ ] Click a cell chip -> drilldown panel shows D6 row
## Summary
Extends the showcase dashboard's active cell rendering path with D6
support so D6 chips can display on every cell. Today D6 was only
referenced in the chips-explainer legend; CellModel capped at
ceilingDepth: 0 | 3 | 4 | 5 with no D6 in UnifiedCell.
## What this PR changes
- `cell-model.ts`: adds `d6: TestLevel | null` field, `resolveD6()`,
extends `achievedDepth`/`ceilingDepth` to `| 6`, D6-ceiling algorithm
for chip color
- `unified-cell.tsx`: renders the D6 chip
- `feature-grid.tsx`: small wiring to surface the new field
- `live-status.ts`: delta from the branch (Dimension/BadgeRender
extensions)
## State after merge
Every cell renders a D6 chip. Until `d6:<slug>/<featureId>` PB rows flow
(follow-up PR for the D6 probe driver + per-framework fixtures), every
D6 chip is gray ("no data — probe pending"). This is the accurate state.
## Why this is safe to ship now
No data layer changes. No probe driver changes. Zero functional risk to
existing cells (they keep their D5-ceiling chip colors). Pure additive
rendering plumbing.
## Follow-up
The d6-all-pills probe driver + d4/d6/shared per-framework fixture reorg
lands in a separate PR (rebased from `feat-d6-everything-works`). That's
what starts populating real D6 state.
Extends the active rendering path with D6 support so dashboard cells
can display D6 ("parity vs reference") state. cell-model.ts gains
ceilingDepth | 6 + d6 TestLevel field + resolveD6() + D6-ceiling
chip-color algorithm. unified-cell.tsx + feature-grid.tsx render the
new D6 chip. live-status.ts gets the small Dimension/BadgeRender delta
the branch needed.
Until d6:<slug>/<featureId> PB rows start flowing (separate PR for the
D6 probe driver + per-framework fixtures), every cell renders D6 gray
("no data -- probe pending"). This is the accurate state -- visibility
without functional risk.
Cherry-picked from feat-d6-everything-works (the per-framework fixtures
branch). The remainder of that branch -- d6-all-pills driver, fixture
reorg, harness config -- lands in a follow-up PR now that the ag-ui
header-forwarding prerequisites (#4984, #4951, #5015, #5016) are in.
## Summary
- Switches `packages/angular` from a proprietary "Commercial" license to
MIT, aligning it with the rest of the CopilotKit packages.
- Updates `packages/angular/LICENSE` to the MIT text (Copyright (c)
Tawkit Inc.) and sets `"license": "MIT"` in
`packages/angular/package.json`.
## Test plan
- [ ] CI passes
## Summary
Bumps two showcase-level `@ag-ui/langgraph` override pins from `0.0.32`
to `0.0.33`:
- `showcase/integrations/langgraph-typescript/package.json`
- `showcase/integrations/langgraph-typescript/src/agent/package.json`
Regenerates both `package-lock.json` files.
## Why this is needed (after R3b already shipped)
R3b (#5015) bumped `packages/runtime` and `packages/sdk-js` to consume
`@ag-ui/langgraph@0.0.33`. But the langgraph-typescript showcase
integration pins `@ag-ui/langgraph` directly in its own `package.json`
files via `overrides`, which overrides whatever the runtime transitively
pulls. Without this PR, the LGT Docker image bakes 0.0.32 and the D6 LGT
probe stays RED.
This is the final ag-ui-side bump needed to complete the LGT
header-forwarding chain end-to-end.
## What's in @ag-ui/langgraph 0.0.33
(Same as documented in #5015.) Per-request `onRequest` hook,
prepareStream configurable+context partition fix for langgraph-api 0.7+,
mergeConfigs context_schema allowlist.
## Test plan
- [ ] CI green
- [ ] After merge, `showcase_build.yml` auto-fires (path filter
`showcase/**` matches)
- [ ] langgraph-typescript Docker image rebuilds + pushes to GHCR
- [ ] Railway redeploys langgraph-typescript service
- [ ] D6 LGT probe flips GREEN
Derive snippet component names from SNIPPET_MAP in docs-render.tsx at
runtime instead of maintaining a hardcoded 35-entry set that was already
13 entries behind. Replace name-level handledByInline gate with per-match
inline pattern check to fix a false-negative path. Align function
signature with sibling check functions. Add 3 unit tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>