Commit Graph

2368 Commits

Author SHA1 Message Date
Alem Tuzlak bda691bd30 fix(showcase/harness): dwell-and-recheck d5-subagents chain to catch critic loop regressions
The probe returned at the first snapshot with critic count == 1, so a
regression that briefly shows 1 critic card before the supervisor
re-invokes critique_agent (count grows to 2) would silently pass.

After the validator passes, hold for CHAIN_SETTLE_DWELL_MS (3s) and
re-snapshot. If the second snapshot fails validation, including a
critic count > 1 or the new sub-agent-empty sentinel appearing in
the page text, throw with a clear destabilised-during-dwell message
that surfaces both initial and post-dwell counts.

Adds the empty-sub-agent sentinel from subagents.py to the probe
BOILERPLATE_MARKERS so an empty sub-agent result fails the test
instead of rendering as an empty card.
2026-05-07 20:55:49 +02:00
Alem Tuzlak ac9ff8affd fix(showcase/harness): use numeric comparator when sorting status codes
[first.status, second.status].sort() defaults to lexicographic
ordering — it returned [200, 429] correctly only by accident and
would mis-order [200, 1000]. Pass an explicit (a,b)=>a-b comparator
so the assertion holds for any future status-code pair.
2026-05-07 20:55:24 +02:00
Alem Tuzlak b7ac944315 fix(showcase/langgraph-python): surface explicit sentinel for empty sub-agent results
_invoke_sub_agent's last-resort branch silently returned '' or a
Python repr like \"[{'type': 'text', ...}]\" for block-list content,
which the UI would render as a blank/garbled card. Return a stable
SUB_AGENT_EMPTY_SENTINEL ('<sub-agent produced no output>') instead
so the d5-subagents probe can match it against its boilerplate-marker
list and fail the genuine-pass test loudly when a sub-agent produces
no usable output.
2026-05-07 20:55:13 +02:00
Alem Tuzlak 447c3d415f fix(showcase/langgraph-python): make get_stock_price deterministic via optional args
The get_stock_price tool returned randint-based price/change every
call, so e2e specs asserting $338.37 / -2.96% would only pass when
aimock short-circuited the entire call. The Python tool body still
runs server-side under aimock — only the LLM call is mocked.

Mirror the deterministic-`value` pattern on roll_d20: accept optional
price_usd / change_pct arguments and echo them back when present.
Defaults to random mock data when the args are omitted, preserving
the legacy live-LLM behaviour.
2026-05-07 20:54:49 +02:00
Alem Tuzlak 17d98f5386 fix(showcase/harness): drop reasoning-display keyword fallback
The probe sent "show your reasoning step by step" and accepted any
assistant transcript containing "reasoning", "step", or "thinking".
Those tokens are typical assistant acknowledgements of the prompt
itself, so the keyword fallback always matched regardless of
whether the framework actually surfaced REASONING_MESSAGE_* events
to the frontend — making the assertion non-genuine.

Strict-only behavior now: the assertion requires one of the four
stable role/testid markers (reasoning-block / reasoning-content /
reasoning-default / [data-message-role="reasoning"]) to render
within the timeout. Integrations that rely on CopilotKit's default
reasoning slot without a stable testid will fail this probe — by
design.

Replace REASONING_KEYWORDS export with REASONING_SELECTORS, drop
the readAssistantTranscript helper (no longer needed), and update
the test to exercise the testid-presence success path and the
timeout failure path.
2026-05-07 20:54:39 +02:00
Alem Tuzlak abfbb803b8 fix(showcase): assert non-boilerplate hello in headless-simple spec
The HELLO_LEADING phrase was the showcase-assistant catch-all
boilerplate ('I can help you with weather lookups...') that other
tests in this PR explicitly guard AGAINST. The dedicated d5-all.json
fixture for 'Say hello in one short sentence' now returns a distinct
non-boilerplate greeting; the spec asserts that distinct phrase, so a
fixture-priority misroute fails loudly instead of passing by accident.
2026-05-07 20:54:36 +02:00
Alem Tuzlak 82bd7857e6 fix(showcase/harness): tighten frontend-tools gradient hints
PILL_GRADIENT_HINTS contained naked hex prefixes (e.g. "#0", "#1",
"#2", "#ff", "#fb", "#3"-"#9") that accidentally cross-matched
across families — cosmic's #1e3a8a matches forest's "#1", so a
regression returning the same gradient for every pill could have
silently passed.

Drop ALL naked-hex prefix hints. Keep only color-name keywords:
  - sunset: sunset, orange, red, rose, pink, amber, coral, peach
  - forest: forest, green, emerald, lime, olive, teal
  - cosmic: cosmic, space, navy, magenta, purple, violet, indigo,
            fuchsia
If full-hex matching is ever needed, use full 6-digit codes from
the actual fixture rather than 1-2 character prefixes.

Also fix the broken "background did not change off baseline" test:
the previous assertion built a baseline-only page mock and then
discarded it via `void page`. Replaced with a fake-timer-driven
invocation that actually triggers the timeout branch, plus a
separate test for the wrong-family path.
2026-05-07 20:54:24 +02:00
Alem Tuzlak 9039716f65 fix(showcase/harness): correct agent-config knob delta math
The length-mode (responseLength) assertion compared the value-B
delta against the FULL CUMULATIVE pre-A transcript, so on the third
knob pair the math was strongly negative and the threshold check
always failed. Same shape mismatch existed on text-mode.

Thread a per-knob snapshot through each pair so both sides of the
comparison are per-turn deltas:
  - Capture priorCumulative BEFORE turn A (chained from the previous
    pair's value-B assertion via chainPriorCapture; pair 0 starts
    with empty since the page is blank pre-run).
  - Snapshot assertion stores aOnly = postA - priorCumulative and
    postACumulative for the next subtraction.
  - Diff assertion isolates onlyB = postB - postACumulative and
    compares aOnly vs onlyB (text equality or length delta).

Tests updated to construct KnobSnapshot bundles via a snapshotFor
helper and exercise the cumulative-prior third-pair scenario for
length-mode.
2026-05-07 20:54:04 +02:00
Alem Tuzlak ad228453b4 fix(showcase/harness): align tool-rendering catchall probes with production testids
The default-catchall probe queried `tool-status-{pending,executing,complete}`
but `DefaultToolCallRenderer` emits a single `copilot-tool-render-status`
pill with the lifecycle state on the container's `data-status` attribute.
Collapse the testid array to that single id and update the selector.

The custom-catchall probe queried `custom-catchall-render`, but the
production `CustomCatchallRenderer` emits `custom-wildcard-card`. Update
the constant + selector. Also swap the unmatched `"AAPL stock price"`
prompt for `"What's the current price of AAPL?"`, the verbatim key
already wired in `showcase/aimock/d5-all.json`, so the fixture
deterministically resolves instead of falling through to the live model.

Tests in both .test.ts files updated to match the new constants and
prompt; both files green locally.
2026-05-07 20:50:18 +02:00
Alem Tuzlak ddb248034d fix(showcase/langgraph-python): restore useDefaultRenderTool() in default catchall cell
The blitz removed the explicit useDefaultRenderTool() call expecting a
framework-level fallback to handle zero-hook registrations, but the
integration uses the published @copilotkit/react-core@1.56.5 which does
not yet ship that fallback. Without the call, useRenderToolCall has no
'*' renderer and tool calls render invisibly — the user only sees the
agent's final text summary instead of the OOTB tool card.

Restore the explicit useDefaultRenderTool() invocation. The framework
fallback (committed in this PR but inert until react-core publishes a
release that includes it) becomes a no-op once that ships.
2026-05-07 19:57:48 +02:00
Sam Julien 1b0ffc0dd8 test(harness): refresh seo-redirects snapshot for retargeted catalog 2026-05-07 10:55:06 -07:00
Sam Julien 3a2eb01ebf fix(shell-docs): restore /v2 subpath on V2 canonical-form imports
The earlier V2 canonical sweep misread the brand-name guidance ("always
CopilotKit") as a directive on import paths and stripped /v2 from
@copilotkit/react-core specifiers. Inline review feedback clarified that
guidance applied only to the component name. This restores
"@copilotkit/react-core/v2" and "@copilotkit/react-core/v2/styles.css"
across the docs sweep scope (now including 8 framework quickstarts
inherited via rebase onto main); the <CopilotKit> rename and the drop
of @copilotkit/react-ui from install commands are kept.
2026-05-07 10:15:03 -07:00
Sam Julien 942ace0072 fix(shell-docs): translate InlineDemo slug to underscore form for code iframe
Registry demo slugs are dash-form (`agentic-chat`); feature-viewer.copilotkit.ai
serves them at underscore-form (`agentic_chat`). The Code tab iframe was
404'ing because the slug was passed through verbatim. Replace `-` with `_`
when building the code URL.
2026-05-07 10:13:30 -07:00
Sam Julien f3ae6680fa feat(shell-docs): render demo + code tabs on InlineDemo
Wraps the InlineDemo iframe in a Demo / Code tab strip mirroring the
IframeSwitcher component, so pages using <InlineDemo demo="..." /> now
expose both the live demo (integration backend) and a code view. The
code iframe points at feature-viewer.copilotkit.ai/<framework>/feature/
<demo>?view=code&sidebar=false&codeLayout=tabs, where <framework> is
translated through getDocsFolder() to map registry slugs like
langgraph-python down to their upstream folder name (langgraph) used by
the feature viewer.
2026-05-07 10:13:30 -07:00
Sam Julien ab684602f4 fix(shell-docs): wire IframeSwitcher to the real component
The mdx-registry shipped a stub IframeSwitcher that took `src`/`title`
props and rendered a single iframe. MDX consumers actually pass
`exampleUrl`/`codeUrl`/`exampleLabel`/`codeLabel`, so the stub was
silently dropping those props and rendering an empty container. The
result: pages using `<IframeSwitcher>` showed no demo+code tabs.

Replace the stub with the real component from `@/components/content`,
which matches the props shape consumers actually use.
2026-05-07 10:13:30 -07:00
Sam Julien 4bbceea08f docs(shell-docs): IframeSwitcher id forwarding + V2 SDK prose fix
IframeSwitcher: forward the `id` prop to a wrapping `<div id={id}>` so MDX
authors can deep-link to a specific switcher instance. The prop was
declared but never consumed.

oss-vs-enterprise.mdx: fix the Frontend SDK bullet to reflect canonical
V2 — both hooks and prebuilt components ship from `@copilotkit/react-core`
(the standalone `@copilotkit/react-ui` package is V1-era).
2026-05-07 10:13:30 -07:00
Sam Julien 646a058fc2 feat(shell-docs): add IframeSwitcher component for demo+code tabs
Several MDX files import `IframeSwitcher` from `@/components/content`
(prebuilt-components, frontend-tools, interactive, tool-rendering, plus
integration overrides), but the component file was missing. This adds it
as a thin wrapper around the existing `<Tabs>` component, rendering a
demo iframe and a code iframe in a Tabs strip.

Props: `exampleUrl`, `codeUrl`, `exampleLabel` (default "Demo"),
`codeLabel` (default "Code"), `height` (default "600px"). Both iframes
are sandboxed and lazy-loaded.

Matches the upstream IframeSwitcher pattern used on docs.copilotkit.ai
to render embedded feature-viewer demos alongside their backing code.
2026-05-07 10:13:30 -07:00
Sam Julien 1de9052af8 docs(shell-docs): consolidate custom-agent onto backend/custom-agent.mdx
backend/custom-agent.mdx (508 lines, structurally complete) is the canonical
Factory Mode page. The integrations/built-in-agent/custom-agent.mdx copy
(240 lines, missing 5 sections) was retired:

- Add 301 redirects in next.config.ts for the two historical paths
  (/built-in-agent/custom-agent and /integrations/built-in-agent/custom-agent
  → /backend/custom-agent).
- Inbound link retargets to /backend/custom-agent landed in the previous
  V2 normalization commit (5 files).
- Delete the divergent 240-line copy.
2026-05-07 10:13:29 -07:00
Sam Julien f4231b7d3b docs(shell-docs): normalize V2 canonical form across docs
Apply the canonical V2 import form across all V2 docs:
- `<CopilotKit>` (not `<CopilotKitProvider>`)
- imports from `@copilotkit/react-core` (root, not `/v2`)
- styles from `@copilotkit/react-core/styles.css` (not `react-ui/v2/styles.css`)
- drop `@copilotkit/react-ui` from npm install commands

Fix V2 leaks in canonical pages: replace stale `useCopilotAction` and
`useCopilotReadable` references in agentic-protocols/a2a.mdx and
backend/custom-agent.mdx with their V2 equivalents (`useFrontendTool`,
`useAgentContext`).

Excludes intentional V1 references in migrate guides, V1 reference tree,
migration callouts, and V1 release notes.
2026-05-07 10:13:29 -07:00
Sam Julien 091790cc5d docs(shell-docs): cutover content batch (quickstart CLI two-choice, AG-UI tab removal, BIA voice region) (#4687)
## Summary

Six commits, batched into one PR for the May 12 docs cutover.

- `2c10c735d` Port upstream CLI walkthrough verbatim onto 8 framework
quickstarts (adk, agno, aws-strands, langgraph, llamaindex, mastra,
microsoft-agent-framework, pydantic-ai). Initial byte-perfect import
from upstream `docs/content/docs/integrations/<fw>/quickstart.mdx`.
- `f17c86867` Add `sample-audio-button` region marker on the
built-in-agent voice demo. Closes a B-cell snippet gap; the bundler now
reports 4 regions on `built-in-agent::voice`.
- `cebca9216` Remove AG-UI brand tab from desktop header for visual
parity with `docs.copilotkit.ai` (canonical has zero AG-UI elements in
the header).
- `abeb2792b` Also remove AG-UI link from mobile slide-out menu and drop
now-unused helpers (`AgUiIcon`, `AG_UI_LINKS`, `AG_UI_PREFIXES`, `Brand`
type, `activeBrandFromPath`, `usePathname`). Net 82-line cleanup of
`brand-nav.tsx`.
- `99d8ac7a5` Intermediate rewrite of the 8 quickstarts to use `npx
copilotkit@latest create --framework <id>` (after CLI accuracy audit
found `--intelligence` and `--framework` are mutually exclusive in
`copilotkit@2.0.3`). Also applies V2 canonical imports to the same 8
files: `<CopilotKit>` from `@copilotkit/react-core` (root), styles from
`@copilotkit/react-core/styles.css`, drop `@copilotkit/react-ui` from
npm install.
- `59a8a71a6` Final CLI-section shape: each quickstart now leads with
the upstream interactive walkthrough (`npx copilotkit@latest create`
plus a bulleted explanation of Project name / Enterprise Intelligence
Platform with sign-up link / Framework picker), followed by an "Or skip
the prompts and pin a framework directly" `--framework <id>` block.
LangGraph and Microsoft Agent Framework show both language variants in
the flag block.

## Test plan

- [ ] Visit each of the 8 framework quickstarts on the dev server.
Verify the CLI section shows the interactive walkthrough with the
EIP/sign-up bullet AND the `--framework <id>` flag block below it.
- [ ] LangGraph quickstart shows both `langgraph-py` and `langgraph-js`
flag commands. Microsoft Agent Framework shows both
`microsoft-agent-framework-dotnet` and `microsoft-agent-framework-py`.
- [ ] All 8 quickstarts: imports show `@copilotkit/react-core` (root),
styles from `@copilotkit/react-core/styles.css`. No `/v2` paths.
- [ ] Inspect shell-docs header at desktop and mobile (narrow viewport).
No AG-UI brand tab anywhere.
- [ ] Visit a built-in-agent voice page that consumes the
`sample-audio-button` region. The snippet renders.
2026-05-07 10:08:02 -07:00
Sam Julien 24101fbfc1 chore(harness): sync seo-redirects intentional copy with retargeted shell catalogue
The harness driver `showcase/harness/src/probes/drivers/seo-redirects.ts` is
an intentional inlined copy of `showcase/shell/src/lib/seo-redirects.ts`
(the harness runtime image is built hermetic from harness's own src/, so
the shell package's src/ isn't reachable at runtime). Both copies must
stay in sync per the file's own header — without this update the monthly
redirect-decommission report would surface ~480 phantom candidates after
the shell catalogue retargeting in the previous commits.

Body content is byte-identical to the new shell + shell-docs catalogue.
The "INTENTIONAL COPY" header comment block is preserved unchanged.
2026-05-07 10:01:27 -07:00
Sam Julien aa65c89213 feat(shell-docs): add sitemap, robots, and per-framework self-canonical metadata
Phase 3 of the docs.copilotkit.ai cutover: surface a complete sitemap,
basic robots config, and per-framework self-canonical metadata so each
URL variant (bare /quickstart, /langgraph-python/quickstart,
/agno/quickstart, etc.) is indexed under its own canonical rather than
collapsing onto a single root.

- src/app/sitemap.ts: emit one entry per (root URL, framework variant)
  pair plus reference and AG-UI sections. lastModified resolves from
  MDX frontmatter `lastmod`, then file mtime, then now. Strips Next.js
  route-group `(name)` segments and trailing `/index` so URLs match
  what the routers actually serve.
- src/app/robots.ts: allow all, disallow /api/, sitemap pointer at
  ${NEXT_PUBLIC_BASE_URL}/sitemap.xml.
- src/lib/sitemap-helpers.ts: shared MDX walking + base-URL resolution
  used by both metadata routes.
- generateMetadata() on the four catch-all docs routes
  ([[...slug]], [framework]/[[...slug]], reference/[...slug],
  ag-ui/[[...slug]]) sets `alternates.canonical` to the page's own
  full URL. Per-framework self-canonical, NOT root canonical.
- .env.example: document NEXT_PUBLIC_BASE_URL and NEXT_PUBLIC_SHELL_URL.
- next.config.ts: extend the existing NEXT_PUBLIC_BASE_URL doc comment
  with the new sitemap/robots/canonical consumers.
2026-05-07 09:55:33 -07:00
github-actions[bot] a2bfa49b9a style: auto-fix formatting 2026-05-07 16:53:44 +00:00
Sam Julien f5a611f20f feat(shell-docs): port redirect middleware + retarget destinations to shell-docs slugs
Part 1 — Retarget seo-redirects.ts destinations:

- Drop the legacy /docs/integrations/ prefix everywhere; shell-docs
  serves canonical framework docs at /<fw-slug>/<...> from the host
  root.
- Apply registry-slug renames in destinations:
    langgraph                  → langgraph-python
    adk                        → google-adk
    aws-strands                → strands
    microsoft-agent-framework  → ms-agent-dotnet
    crewai-flows               → crewai-crews
    unselected                 → built-in-agent (BIA canonical re-flip)
- Add slug-rename catch-alls for the bare /<old-slug>/* form so legacy
  upstream URLs (e.g. /langgraph/quickstart) 301 to the new slug.
- Add /docs/integrations/* and /docs/* catch-alls so any URL still
  carrying the legacy SHELL routing prefix lands at the shell-docs
  equivalent.
- Add /migration-guides/* → /migrate/* (4 URLs).
- Add folder-index redirects for shell-docs folders without an
  index.mdx (/troubleshooting, /migrate, /premium, /concepts,
  /reference) so bare folder URLs land on a representative inner page.

Part 2 — Port the redirect middleware to shell-docs:

- Copy the retargeted seo-redirects.ts to shell-docs/src/lib/.
- Merge the SHELL redirect-middleware logic into shell-docs's existing
  pageview-tracking middleware: redirects fire first (with seo_redirect
  PostHog event), and non-redirected requests still get the
  docs_pageview capture and distinct_id cookie.
- Preserve the framework-scoped short-circuit so canonical
  /<fw-slug>/<...> URLs are never hijacked by legacy patterns.
- Leave the SHELL versions in place — the SHELL still serves
  docs.showcase.copilotkit.ai until DNS flips.

Verified shell-docs and SHELL builds clean. Spot-checked redirects on a
local shell-docs server: /docs/integrations/langgraph/quickstart →
/langgraph-python/quickstart, /langgraph/quickstart →
/langgraph-python/quickstart, /migration-guides/v2 → /migrate/v2,
/troubleshooting → /troubleshooting/common-issues, /coagents →
/langgraph-python, /aws-strands/quickstart → /strands/quickstart.
2026-05-07 09:52:02 -07:00
Sam Julien 3d4b594e96 chore(reference): update autogen pipeline for langgraph_agent rename
Upstream renamed sdk-python/copilotkit/langgraph_agent.py to
langgraph_agui_agent.py and the class to LangGraphAGUIAgent. Update the V1
reference autogen entry in scripts/docs/lib/files.ts to point at the new
source and class name, and regenerate the shell-docs MDX. Pipeline now
reports 26/26 entries succeeding (was 25/26).
2026-05-07 09:50:28 -07:00
Alem Tuzlak 6ad6dfbbd1 Merge slot B8 into blitz/lgp-genuine-pass/integration
Resolved conflicts:
- d5-all.json: appended B8's 26 new fixture entries to the existing 131
- gen-ui-open.json: kept ours (B3's verbatim pill messages match the suggestions.ts pills); dropped B8's paraphrased fixtures
- d5-gen-ui-open.ts: kept B7's basic-only routing + B8's iframe-presence assertion logic; updated PILL_PROMPT_PREFIX to '3D axis visualization (model airplane)' so it matches the actual pill message
2026-05-07 18:22:52 +02:00
Alem Tuzlak 2b085f22d2 Merge slot B7 into blitz/lgp-genuine-pass/integration 2026-05-07 18:20:29 +02:00
Alem Tuzlak 06989b977b Merge slot B6 into blitz/lgp-genuine-pass/integration
Resolved d5-all.json conflict by appending B6's headless-simple/complete fixtures (Say hello, joke, fun fact, Highlight, chart) before the tool-rendering and open-gen-ui entries already on integration.
2026-05-07 18:20:15 +02:00
Alem Tuzlak e8eaacee14 Merge slot B5 into blitz/lgp-genuine-pass/integration 2026-05-07 18:18:23 +02:00
Alem Tuzlak 4097b166eb Merge slot B4 into blitz/lgp-genuine-pass/integration 2026-05-07 18:18:22 +02:00
Alem Tuzlak d5615fed90 Merge slot B3 into blitz/lgp-genuine-pass/integration 2026-05-07 18:17:58 +02:00
Alem Tuzlak 92e405946d Merge slot B2 into blitz/lgp-genuine-pass/integration
Resolved d5-all.json conflict by appending B2's readonly-state-agent-context fixtures after B1's hitl-in-app and frontend-tools-async fixtures.
2026-05-07 18:17:42 +02:00
Alem Tuzlak 83fd617f94 feat(showcase/harness): rewrite d5 smoke probes to genuine assertions
Rewrites 10 D5 smoke probes from keyword-match-on-transcript checks
to side-effect / DOM-mount / network-payload assertions per
Phase-2B of .claude/specs/lgp-test-genuine-pass.md:

- d5-frontend-tools: 3 per-pill turns (Sunset/Forest/Cosmic) asserting
  the page background data-attribute mutated to the pill's family-
  specific gradient and differs from the prior pill's gradient.
- d5-frontend-tools-async: notes-card testid mount + settled-state
  detection (list items OR empty-state copy).
- d5-agent-config: 3 knob pairs (tone/expertise/responseLength) sent
  as 6 turns; assertion compares value-A vs value-B response text or
  character-count delta. Aimock fixtures key on prompt-encoded knob
  tokens since JSON fixtures don't expose context-keyed predicates.
- d5-gen-ui-agent: 3 per-pill turns asserting agent-state-card mounts
  with ≥ 2 agent-step rows whose text fingerprint differs across
  pills (catches a regression where fixtures stop differentiating).
- d5-gen-ui-declarative: 4 per-pill turns asserting at least one
  catalog testid (declarative-card / metric / status-badge /
  pie-chart / bar-chart) mounted.
- d5-gen-ui-a2ui-fixed: pill prompt + a2ui-fixed-card testid mount
  assertion.
- d5-gen-ui-interrupt: 2 per-pill turns; click first time-picker-slot
  after time-picker-card mounts; assert time-picker-picked appears.
- d5-gen-ui-open: pill prompt; iframe[srcdoc] mounts with srcdoc
  length ≥ 100 chars.
- d5-shared-state-streaming: 3 per-pill turns asserting
  document-content text length ≥ STREAMING_MIN_FINAL_CHARS.
- d5-readonly-state-context: seeds [data-testid=ctx-name] with a
  sentinel; installs page.route() interceptor on /api/copilotkit;
  asserts the captured outgoing request body contains the sentinel.

Adds _genuine-shared.ts with the structural Page extension
(GenuinePage), pill-click helper, testid waiter, and runtime guard
that mirrors the _beautiful-chat-shared.ts pattern.

All 10 *.test.ts files updated with focused assertions over fakes —
none rely on the production page being live, all 63 unit tests pass.
2026-05-07 18:15:02 +02:00
Alem Tuzlak 7b1f43fd9f chore(showcase/aimock): add d5 probe fixtures keyed on context values
Adds per-pill aimock fixtures backing the Phase-2B genuine D5 probes:

- agent-config: 6 fixtures (3 knob pairs) so concise vs detailed
  responses differ deterministically; satisfies the new probe's
  text-diff + length-diff assertions.
- frontend-tools: 3 per-pill fixtures (sunset/forest/cosmic) emitting
  change_background tool calls with family-specific gradient hexes.
- frontend-tools-async: query_notes tool call so the NotesCard mounts.
- gen-ui-agent: 3 per-pill set_steps tool calls with distinct step
  content so the per-pill content-fingerprint assertion catches
  fixture-drift.
- gen-ui-declarative: 4 per-pill generate_a2ui calls + render_a2ui
  fixture for the secondary LLM call that paints the catalog.
- gen-ui-a2ui-fixed: SFO/JFK display_flight tool call.
- gen-ui-interrupt: 2 per-pill schedule_meeting tool calls with
  distinct time-slot payloads.
- gen-ui-open: generateSandboxedUi tool call with a non-trivial
  HTML payload so the iframe[srcdoc]-mount assertion has ≥ 100 chars
  to observe.
- shared-state-streaming: 3 per-pill write_document tool calls with
  substantive content payloads (≥ 100 chars each).
- readonly-state-context: pill-prompt fixture; the probe's network-
  payload assertion checks the request body, not the response.

d5-all.json is updated with the new entries prepended so first-match
precedence routes specific pill prompts to their per-pill fixtures
ahead of the generic adjacent matches.
2026-05-07 18:14:35 +02:00
Alem Tuzlak 63aef191ff feat(showcase/langgraph-python): add testids and pills required by d5 probes
Adds production-code testids needed by the Phase-2B genuine D5 probes:

- frontend-tools/background.tsx: data-testid='frontend-tools-background'
  + data-background-value mirror so the probe can read the live gradient
  off the DOM without computing styles.
- declarative-gen-ui/a2ui/renderers.tsx: data-testid for Card,
  StatusBadge, Metric, PieChart, BarChart so per-pill probes can assert
  the expected catalog component painted.
- a2ui-fixed-schema/a2ui/renderers.tsx: data-testid='a2ui-fixed-card'
  on the Card override so the fixed-schema component-tree mount is
  observable without keyword-matching the transcript.

Each cell's Layer 1 spec is already green; this is purely additive — no
spec rewrites.
2026-05-07 18:14:13 +02:00
Alem Tuzlak 05395937fe test(showcase/langgraph-python): rewrite tool-rendering trio to pill-driven 6-test plans
All three tool-rendering cells now drive the suggestion pills directly
instead of typing free-form prompts that race fixture matchers:

- tool-rendering: 6 tests (page loads + 5 pills) — Weather in SF
  asserts SF city + deterministic temp/humidity/wind; Find flights
  asserts >=2 flight rows from the dedicated fixture; Stock price
  asserts AAPL $338.37 / -2.96%; Roll a d20 asserts exactly 5 d20
  cards with the 5th=20; Chain tools asserts weather+flights+d20
  cards mount from a single pill click.
- tool-rendering-default-catchall: 6 tests asserting the OOTB default
  tool-call renderer paints every tool call with data-testid=
  copilot-tool-render plus data-tool-name. Branded sibling-cell
  testids stay at zero. Test 6 asserts every card matches the
  built-in renderer DOM signature.
- tool-rendering-custom-catchall: 6 tests asserting the same
  custom-wildcard-card testid renders for every tool. Test 6 is the
  cross-tool snapshot — every tool kind paints via the same shell.
2026-05-07 17:55:20 +02:00
Alem Tuzlak ba60df5d33 feat(showcase/langgraph-python): add per-tool testids
Add stable testids and rendering surfaces for the three tool-rendering
cells so the e2e suite can distinguish each cell's strategy:

- tool-rendering: register useRenderTool for get_stock_price and
  roll_d20; new StockCard / D20Card components with testids
  stock-card / d20-card / stock-price / stock-change / d20-value.
  Rename FlightListCard testid flight-list-card -> flights-card.
- tool-rendering-default-catchall: drop the custom shadcn
  useDefaultRenderTool registration so the cell is truly zero
  custom-render-hooks. The framework's built-in
  DefaultToolCallRenderer now paints every tool call, with stable
  data-testid='copilot-tool-render' wrapper plus data-tool-name,
  data-args, and data-result attributes for inspection without
  expanding the card.
- tool-rendering-custom-catchall: rename the wildcard renderer's
  testids from custom-catchall-* to custom-wildcard-* so the cell
  is distinguishable from the (now-OOTB) default-catchall demo.
- packages/react-core: when no per-tool / wildcard renderer is
  registered, useRenderToolCall now falls back to the built-in
  DefaultToolCallRenderer instead of returning null.
2026-05-07 17:55:02 +02:00
Alem Tuzlak b0f0947ae3 chore(showcase/aimock): add tool-rendering pill fixtures with priority
Add 14 fixtures at the top of d5-all.json so they win precedence over
the existing 'weather in Tokyo' / 'd5 beautiful-chat probe: search
flights' substring matches:

- Chain tools: 3 toolCalls in one assistant turn (get_weather Tokyo +
  search_flights SFO->Tokyo + roll_d20=11) plus follow-up text.
- Weather in SF: get_weather(San Francisco) + text (deterministic).
- Find flights: dedicated search_flights(SFO,JFK) fixture, no longer
  leaks the a2ui beautiful-chat shape.
- Stock price: get_stock_price(AAPL) returning $338.37 / -2.96%.
- Roll a 20-sided die: 5 sequential roll_d20 fixtures with
  turnIndex 0..4 (stateless across runs), values [7,14,3,19,20].
2026-05-07 17:54:43 +02:00
Alem Tuzlak 7747033d68 fix(showcase/langgraph-python): mock d20 as 5 deterministic rolls
Replace the random roll_dice tool with roll_d20(value), which echoes
the LLM-supplied value back as the result. Aimock fixtures script the
five sequential calls returning [7, 14, 3, 19, 20] so the e2e suite can
assert exact values rather than rolling until 20 lands.

Update SYSTEM_PROMPT to allow multi-tool chaining when the user
explicitly asks for it (Chain tools pill emits 3 tool calls in one
turn).
2026-05-07 17:54:26 +02:00
Sam Julien 59a8a71a61 docs(shell-docs): give quickstart CLI section two clear paths (interactive vs flag)
Restructure the "Run our CLI" step in all eight framework quickstarts to surface
two paths: the upstream interactive flow (which now covers the Enterprise
Intelligence Platform prompt and sign-up) and the `--framework <id>` flag fast
path. LangGraph and Microsoft Agent Framework keep both language variants in the
flag block.
2026-05-07 08:52:31 -07:00
Alem Tuzlak e67fcfbf84 feat(showcase/harness): add d5-gen-ui-open-advanced probe
Phase-2A wrong-target split. The old d5-gen-ui-open probe claimed BOTH
open-gen-ui and open-gen-ui-advanced via the same gen-ui-open literal,
which meant a regression on the advanced demo's iframe sandbox would
never surface (the basic-tier assertion didn't read iframe state). The
advanced demo now owns its own probe asserting iframe presence as the
distinguishing signal:

- d5-gen-ui-open-advanced: drives /demos/open-gen-ui-advanced, asserts
  the [data-testid="gen-ui-open-advanced-iframe"] testid (with a
  generic iframe fallback).

d5-gen-ui-open: scoped to the basic /demos/open-gen-ui route only;
preNavigateRoute no longer branches on the demos[] context.

d5-feature-mapping.ts: open-gen-ui-advanced now points at the new
gen-ui-open-advanced literal; d5-registry.ts adds the literal.
2026-05-07 17:52:31 +02:00
Alem Tuzlak 6ce43eeaf6 test(showcase/langgraph-python): rewrite hitl-in-app and frontend-tools-async to genuine assertions
hitl-in-app — 7 explicit tests (1 skip):

- Page-load and pill-render tests retained.
- New refund #12345 approve/reject pair asserts the deterministic
  fixture leading phrases ("I am processing the $50 refund" vs
  "refund request was not approved").
- New escalate #12347 approve/reject pair asserts "Escalated ticket
  #12347" vs "Not escalated".
- The describe block runs in serial mode so the approve test
  (sequenceIndex 0 in the fixture) always runs before the reject test
  (sequenceIndex 1) for each pill.
- Downgrade #12346 stays skipped per spec (broken upstream as of
  2026-05-07).

frontend-tools-async — 4 explicit tests:

- Page-load test asserts composer + 3 pills.
- Project-planning, auth, and reading pills each click and assert the
  Notes DB card renders with the correct keyword heading and the
  per-note testid rows that the async handler returned. Anti-regression
  assertions catch the previous fixture-priority bugs (generic-plan
  boilerplate, showcase-assistant catch-all).
- Reading pill locks the full canonical shape per spec test #4: keyword,
  match count, note title, content lines, tag chip, and the assistant
  narration leading phrase.

No production-code testid changes — the existing dialog and notes-card
testids cover every assertion. Fixture work lives in d5-all.json (prior
commit).
2026-05-07 17:52:30 +02:00
Alem Tuzlak e6644338d5 feat(showcase/harness): add d5-tool-rendering-default-catchall and d5-tool-rendering-custom-catchall probes
Phase-2A wrong-target split. Both registry IDs previously pointed at
d5-tool-rendering, which asserts a per-tool WeatherCard — the wrong
signal for catchall renderers. Each catchall surface now owns a probe
that asserts its own testid contract:

- d5-tool-rendering-default-catchall: drives the built-in default
  catchall renderer, asserts [data-testid="copilot-tool-render"] +
  [data-tool-name="get_weather"] + a tool-status-* lifecycle pill.
- d5-tool-rendering-custom-catchall: drives the user-supplied wildcard
  renderer, sends 2 distinct prompts (get_weather + get_stock_price)
  and asserts BOTH render through the same [data-testid="custom-catchall-render"]
  testid (cross-tool signature snapshot — the wildcard truly catches
  all tools, not just one).

Mapping in d5-feature-mapping.ts now points each registry ID at its
own probe; d5-registry.ts adds the two new D5FeatureType literals.
2026-05-07 17:52:16 +02:00
Alem Tuzlak 276161d0bd chore(showcase/aimock): add fixtures for hitl-in-app and frontend-tools-async pills
Adds deterministic fixtures to d5-all.json (loaded before feature-parity.json
so it wins match precedence) for the Phase 1A genuine-pass cells:

- hitl-in-app refund #12345 and escalate #12347 pills: each emits a
  request_user_approval tool call on the first turn, then branches via
  sequenceIndex on the second turn (0 = approve response, 1 = reject
  response). Test ordering (serial mode in the spec) drives which branch
  is claimed first per pill pair.

- frontend-tools-async project-planning, auth, and reading pills: each
  emits a query_notes tool call so the async client-side handler runs
  against NOTES_DB and renders project-planning / auth / reading-tagged
  matches. The reading pill's 2nd-turn narration locks the canonical
  leading phrase per spec test #4.

Replaces nothing — purely additive. The dedicated pill-prompt entries
beat the broad 'plan' and showcase-assistant catch-all entries that were
silently winning before.
2026-05-07 17:52:09 +02:00
Alem Tuzlak 390ab6fbbc test(showcase/langgraph-python): rewrite subagents to 5 deterministic 3-card tests
- Drop the 8 stale tests that asserted travel-planner shapes
  (Current Itinerary / supervisor-indicator / .bg-gray-50). They
  predated the supervisor + 3-subagent rewrite and could not catch
  the 3 production bugs.
- New suite (5 tests, 0 skipped):
    1) page loads with composer + 3 verbatim suggestion pills + 3
       subagent role indicators (testid-based).
    2-4) one test per pill (Write a blog post / Explain a topic /
       Summarize a topic). Each clicks the pill, waits for all
       three role-scoped subagent cards to reach data-status=
       "complete", then asserts each card's subagent-result is
       non-empty AND does not contain the showcase-assistant
       boilerplate fragments. Test 4 also serves as a regression
       gate on the delegations reducer fix — without it, that pill
       returns HTTP 400 and the cards never reach complete.
    5) clicks any pill, waits for terminal state, then asserts the
       critic-card count is exactly 1 and stays at 1 with status
       complete across a 5s dwell — catches any return of the
       supervisor -> critic loop.
- Aimock fixtures: 3 verbatim pill chains (cold exposure training,
  LLM tool calling, reusable rockets) added to both d5-all.json and
  the harness source d5/mcp-subagents.json. Each chain drives the
  full supervisor flow (turnIndex 0..3) plus three nested sub-agent
  fixtures so every Researcher/Writer/Critic card surfaces real
  prose instead of showcase boilerplate.
2026-05-07 17:52:02 +02:00
Alem Tuzlak a6f1076cf5 test(showcase/langgraph-python): rewrite open-gen-ui and open-gen-ui-advanced to iframe-presence assertions
Drop the 5 cross-origin contentFrame() / page.on('console', ...) skipped
assertions across the two specs — sandbox=allow-scripts only blocks host
introspection of the iframe DOM, and console-spying on the host page
catches no inner-iframe logs. Replace with iframe-presence assertions:
each pill click must produce iframe[sandbox*='allow-scripts'] with a
non-empty srcdoc (or src) attribute. That is the load-bearing signal
that the open-generative-ui pipeline mounted SOMETHING.

Rewrite each suggestion message string as a short verbatim label that
doubles as a deterministic aimock fixture key (paired with the new
fixtures in showcase/aimock/d5-all.json). Drop pill-title parentheticals
per the cosmetic note in lgp-test-genuine-pass.md so titles read as
natural human prompts; keep the message field aligned with the fixture
key.

Final test counts: 5 minimal (page-load + 4 pill-iframe), 4 advanced
(page-load + 3 pill-iframe). All .skip() removed. The sandbox-function
round-trip (evaluateExpression / notifyHost) is intentionally not
asserted here — that requires a same-origin sandbox option or a
host-side spy on the runtime's sandbox-function-call event, both
deferred to a follow-up.
2026-05-07 17:51:44 +02:00
Alem Tuzlak 9b3d64dda4 feat(showcase/langgraph-python): add subagent-card and subagent-result testids
- subagent-activity-card: emit data-testid="subagent-card-<role>" on
  each card wrapper (researcher | writer | critic), data-testid=
  "subagent-result" on the Result content div, and data-testid=
  "subagent-status" on the status pill. The previous testids
  (subagent-activity-card, subagent-activity-result) collapsed across
  roles, so the e2e suite couldn't count or content-assert per role.
- delegation-log: render a fixed row of 3 always-visible role
  indicators (data-testid="subagent-indicator-<role>") so the page
  exposes a stable hook for the load-state assertion regardless of
  whether the supervisor has delegated yet.
2026-05-07 17:51:40 +02:00
Alem Tuzlak 2b7d93a157 feat(showcase/harness): split d5-mcp-subagents into d5-mcp-apps and d5-subagents
Phase-2A wrong-target split. The old d5-mcp-subagents probe claimed both
mcp-apps and subagents feature types but routed both to /demos/subagents,
leaving mcp-apps wrong-targeted. Each feature now has its own probe:
- d5-mcp-apps: drives /demos/mcp-apps, asserts iframe presence via the
  [data-testid="mcp-app-iframe"] testid (with iframe[sandbox] fallback).
- d5-subagents: drives /demos/subagents, asserts the 3 Phase-1D
  subagent-card testids (researcher, writer, critic), enforces the
  one-critic invariant, and rejects boilerplate placeholder text.

d5-feature-mapping.ts: comment block updated to reflect the split.
d5-registry.ts: no new literals needed (mcp-apps + subagents already
existed).
2026-05-07 17:51:36 +02:00
Alem Tuzlak 527e46c5d9 fix(showcase/langgraph-python): fix subagents delegations reducer, single-critic cap, and Result-echo boilerplate
- Annotate AgentState.delegations with operator.add reducer so concurrent
  sub-agent emissions in one supervisor step accumulate instead of
  raising INVALID_CONCURRENT_GRAPH_UPDATE (HTTP 400 on the Summarize pill).
- Update _delegation_update to return only the new entry (the reducer
  concatenates) instead of echoing the full prior list, which would
  duplicate entries each step under operator.add.
- Cap supervisor -> critique_agent loop at _MAX_CRITIQUE_ITERATIONS
  (default 1). Re-entrant critique calls short-circuit with a finish-now
  ToolMessage and do not append a second delegation, so the UI shows
  exactly one critic card per supervisor run.
- _invoke_sub_agent now walks messages newest-first and returns the
  first non-empty AIMessage content (handles list-of-content-blocks
  shape too). Prevents the previous failure mode where a final empty
  AIMessage made the card Result blank or echoed the showcase-assistant
  intro.
- Strengthen supervisor system prompt: each sub-agent must be called
  exactly once, with no further calls after critique returns.
2026-05-07 17:51:19 +02:00
Alem Tuzlak 72342e1543 chore(showcase/aimock): add open-gen-ui pill fixtures with priority over showcase-assistant catch-all
The 5 of 7 open-gen-ui pill prompts (3D axis, neural network, quicksort,
calculator, ping-the-host) currently match the broad userMessage: 'hi'
catch-all in feature-parity.json (substring match on 'hi' inside 'Say hi
to the host', 'this', etc.) and resolve to the showcase-assistant
boilerplate greeting instead of emitting the generateSandboxedUi tool
call. That kills the iframe path on 5/7 of the pills.

Add 7 high-priority verbatim-prompt fixtures in d5-all.json (and the
source-of-truth showcase/harness/fixtures/d5/gen-ui-open.json) that emit
deterministic generateSandboxedUi tool calls with inline HTML + CSS in
the tool result. d5-all.json loads BEFORE feature-parity.json so the
first-match-wins ordering naturally beats the catch-all. Pill fixtures
appear at the top of the file so they also win against intra-bundle
specifics. Inline HTML is intentionally minimal — the assertion bar is
iframe presence + non-empty srcdoc, not iframe DOM introspection
(cross-origin blocked under sandbox=allow-scripts only).
2026-05-07 17:50:53 +02:00