Commit Graph

6971 Commits

Author SHA1 Message Date
Alem Tuzlak c9a304ec4e fix(showcase/langgraph-python): force JSON mode for byoc-json-render agent
Root cause: gpt-4o-mini occasionally answered "Show me the sales
dashboard with metrics and a revenue chart" with a prose preamble
or clarifying question instead of the JSON spec the `@json-render`
renderer expects, which made the frontend fall back to
CopilotChatAssistantMessage (plain text) rather than a MetricCard +
BarChart tree. The single-component prompts (Revenue by category,
Expense trend) were terse enough that the model usually complied,
but the multi-component Sales Dashboard prompt was where it drifted.

Fix:

- Pass response_format={"type": "json_object"} via model_kwargs so
  the OpenAI response is guaranteed to be a single JSON object,
  removing any possibility of a plain-text fallback.
- Tighten the system prompt so every user turn is answered with JSON
  (no clarifying questions, no prose) and components are referenced
  by their exact case-sensitive names.
- Extend the Sales Dashboard worked example to include two MetricCards
  plus a BarChart so the model has a concrete multi-component pattern
  to mirror - the round-1 children forwarding in the registry wrapper
  already supports arbitrarily many siblings under the root MetricCard.
2026-04-24 19:22:19 +02:00
Alem Tuzlak ed9982ada3 Merge remote-tracking branch 'origin/fix/langgraph-python-auth' into fix/langgraph-python-demo-runtime-bugs 2026-04-24 17:40:24 +02:00
Alem Tuzlak acc543f3c4 Merge remote-tracking branch 'origin/fix/langgraph-python-agent-config' into fix/langgraph-python-demo-runtime-bugs 2026-04-24 17:40:21 +02:00
Alem Tuzlak 2c19d30d1e Merge remote-tracking branch 'origin/fix/langgraph-python-voice' into fix/langgraph-python-demo-runtime-bugs 2026-04-24 17:40:21 +02:00
Alem Tuzlak c4a45d3d62 Merge remote-tracking branch 'origin/fix/langgraph-python-multimodal' into fix/langgraph-python-demo-runtime-bugs 2026-04-24 17:40:19 +02:00
Alem Tuzlak 623f1a2deb Merge remote-tracking branch 'origin/fix/langgraph-python-byoc-hashbrown' into fix/langgraph-python-demo-runtime-bugs 2026-04-24 17:40:18 +02:00
Alem Tuzlak c242ff3dea Merge remote-tracking branch 'origin/fix/langgraph-python-byoc-json-render' into fix/langgraph-python-demo-runtime-bugs 2026-04-24 17:39:48 +02:00
Alem Tuzlak 5f222b00ee fix(showcase/langgraph-python): emit hashbrown JSON envelope from byoc-hashbrown agent
The agent system prompt instructed the LLM to return <ui>...</ui> XML markup,
but the frontend renderer uses useJsonParser(message.content, kit.schema)
which expects a JSON object matching createUiKit(...).schema:

  {
    "ui": [
      { "metric":   { "props": { "label": "...", "value": "..." } } },
      { "pieChart": { "props": { "title": "...", "data": "[{...}]" } } },
      ...
    ]
  }

The XML syntax in useUiKit({ examples }) is hashbrowns prompt DSL for when
hashbrown drives the LLM directly (e.g. useUiChat); because this demo drives
the LLM via langgraph, the agent itself must emit the JSON wire format. With
XML content, useJsonParser returned { value: undefined } and the renderer
bailed to null, leaving the chat with only a loading indicator.

Rewrote the system prompt to produce the JSON envelope and updated the
renderer top-of-file docstring to match. Prop schemas tracked from the
current kit (metric: label+value, pieChart/barChart: title+data-as-JSON-string,
dealCard: title+stage+value, Markdown: children).
2026-04-24 17:10:29 +02:00
Alem Tuzlak 606656eeb4 fix(showcase): wire multimodal demo attachments to LangGraph agent
The multimodal demo failed three ways:

1. Try-with-sample-image rendered a broken thumbnail because the sample
   PNG on disk is a Git LFS pointer stub when LFS is not pulled at build
   time. The browser base64-encoded the 130-byte text stub, fed it into
   the chat as a valid-looking image/png, and CopilotChat rendered it
   as a broken <img>.

2. Try-with-sample-pdf attached in the composer but the agent said
   "no image/document attached". Same broken-image pipeline also hid the
   real symptom: the published @ag-ui/langgraph converter (0.0.x) only
   understands the legacy { type: binary, mimeType, data | url }
   AG-UI content-part shape. The modern { type: image | document,
   source: {...} } parts CopilotChat emits are silently filtered out of
   the LangChain message stream, so the LangGraph agent never saw them.

3. Manual drag-and-drop of an image failed for the same reason as #2.

Fixes:

- sample-attachment-buttons.tsx: reject Git LFS pointer stubs and
  validate PNG/PDF magic bytes on the client before feeding them to the
  attachment queue. Surfaces an actionable error pointing at
  git-lfs-pull instead of silently producing a broken thumbnail.

- page.tsx: install an onRunInitialized subscriber on the active agent
  that rewrites outgoing user-message image / document / audio / video
  parts to the legacy binary shape the runtime converter preserves.
  Everything else (CopilotChat UI, useAttachments upload pipeline,
  paperclip + drag-drop + paste paths) is untouched; we only retarget
  the wire format so the LangGraph side receives the attachment.

- multimodal_agent.py: after the rewrite, attachments arrive in the
  agent as LangChain image_url content parts (data URLs) regardless of
  upstream modality. Route on MIME instead of the AG-UI part type:
  image/* forwards to GPT-4o natively, application/pdf is flattened to
  text via pypdf. The modern document shape is still handled for
  forward-compat when the runtime is upgraded.

Verified: classifier helpers pass inline unit checks; tsc --noEmit
introduces no new type errors relative to HEAD (module-resolution
errors for @copilotkit/shared and lucide-react are pre-existing on this
branch and unrelated to the multimodal demo).
2026-04-24 17:01:35 +02:00
Alem Tuzlak 23dc888c3b fix(showcase): bridge forwardedProps to LangGraph configurable.properties 2026-04-24 16:03:22 +02:00
Alem Tuzlak 96a9386dce fix(showcase-shell): separate CLI init command from live demos (#4196)
## Summary

On integration profile pages (e.g. `/integrations/langgraph-python`),
the `cli-start` demo entry — which has a `command` field instead of a
`route` — was being rendered inside the Live Demos grid. Clicking it
opened `DemoDrawer` with an undefined `demoRoute`, so the iframe tried
to load `${backend_url}undefined`.

This PR:
- Splits `integration.demos` into `liveDemos` (runnable, have `route`)
and `commandDemos` (CLI-only, have `command`).
- Filters command-only entries out of the Live Demos grid.
- Adds a new **Get Started** section above Live Demos that renders each
`commandDemos` entry as a description + copy-able `<code>` block
(mirrors how `shell-dashboard` already handles these via `CommandCell`).
- Makes `Demo.route` optional and adds `Demo.command?: string` on the
`Demo` type.

Only `langgraph-python` currently has a command-only demo, so this is
the only profile page that changes visibly.

## Test plan

- [x] Ran `showcase/shell` dev server, visited
`/integrations/langgraph-python`, confirmed:
- New "Get Started" card shows `npx copilotkit@latest init --framework
langgraph-python` with a working Copy button.
- "Live Demos" grid no longer contains the broken "CLI Start Command"
tile.
- Other integrations (no `command` demos) render unchanged — Live Demos
still present, no empty "Get Started" section.
- [x] Pre-commit hooks (lint-fix, check-binaries,
test-and-check-packages — 1149 tests, commitlint) all pass.
2026-04-24 16:00:03 +02:00
Alem Tuzlak 67df4e0137 fix(showcase): invert auth demo default to authenticated + guard against 401 crash
Starting the /demos/auth cell unauthenticated meant the initial `/info`
handshake from CopilotKit returned 401 before any React error handler
could attach, crashing the page on load. Flip the default so the demo
mounts already signed in — the chat is immediately usable — and expose
Sign out / Sign in as the toggle for exercising the 401 path.

- use-demo-auth: default state flipped from unauthed to authed so the
  page mounts with a valid Bearer header.
- page.tsx: add a ChatErrorBoundary around <CopilotChat /> that catches
  any render-time throw from chat internals after signing out and shows
  a friendly in-page message instead of white-screening. The boundary
  resets on auth transitions so signing back in restores a live chat.
- auth-banner: rename Authenticate -> Sign in; status copy updated to
  Signed in / Signed out to match the inverted default.
- tests/e2e/auth.spec.ts: flip assertions — page loads authenticated,
  sign out triggers 401 on next send with banner still mounted, and
  sign in clears the error and restores successful sends.
- qa/auth.md: refreshed checklist for the authenticated-default flow.
2026-04-24 15:55:45 +02:00
Alem Tuzlak 1037e02d9d fix(showcase/langgraph-python): voice route advertises transcription + returns clear 4xx when key missing
V1 CopilotRuntime wrapper silently drops `transcriptionService`, so the
composer never saw the mic button on /voice. Write it onto the V2 runtime
instance directly, and wrap the OpenAI service with a guard that throws an
"api key missing" error when OPENAI_API_KEY is absent (mapped by the
runtime error categorizer to AUTH_FAILED / 401) instead of the opaque 503
users were hitting.
2026-04-24 15:45:04 +02:00
Alem Tuzlak 74aaa4ad84 fix(showcase): forward children through byoc-json-render MetricCard wrapper 2026-04-24 15:11:00 +02:00
Alem Tuzlak 61e5976815 fix(showcase): wrap byoc-json-render Renderer in JSONUIProvider
Clicking any suggestion in the byoc-json-render demo crashed with
"useVisibility must be used within a VisibilityProvider". Renderer from
@json-render/react relies on StateProvider, VisibilityProvider,
ValidationProvider, and ActionProvider contexts that its internal
ElementRenderer consumes, but the assistant-message slot was rendering
Renderer bare.

Wrap it in JSONUIProvider (which composes all four required providers)
so streamed spec output renders without a context crash.

Also pass children through the MetricCard catalog wrapper. The agent's
Sales Dashboard worked example uses a MetricCard as the root with a
BarChart nested in its children array; previously that chart was
silently dropped by the registry wrapper, which only rendered the
MetricCard itself.
2026-04-24 15:00:10 +02:00
Alem Tuzlak 7b074be36b fix(showcase/langgraph-python): align byoc-hashbrown example with strict hashbrown schema (#4252)
## Problem

Follow-up to #4251 (voice route lazy-init). The voice fix unblocked the
build far enough to hit the **next** failure:

\`\`\`
Error occurred prerendering page "/demos/byoc-hashbrown"
Error: Example prompt has 5 errors:
  Prop 'trend' is not defined on <metric>
  Prop 'data' on <pieChart>: Expected an array at: <root>
  Prop 'data' on <barChart>: Expected an array at: <root>
  Prop 'assignee' is not defined on <dealCard>
  Prop 'dueDate' is not defined on <dealCard>
\`\`\`

Wave 4a was ported from the starter, which used an older
\`@hashbrownai/core\` where:
- Optional props used \`.optional()\`.
- Array props accepted stringified JSON in example JSX attributes.

\`@hashbrownai/core@0.5.0-beta.4\` dropped \`.optional()\` (props
omitted from the schema are treated as not-present) **and** tightened
example-prompt validation to reject strings against array schemas. Wave
4a already adapted the schema for \`.optional()\` removal (see the
comment on MetricCard in hashbrown-renderer.tsx) but the \`examples\`
prompt still carried the old-style attributes.

## Fix

- Wrap \`PieChart\` + \`BarChart\` with \`PieChartWithStringData\` /
\`BarChartWithStringData\` that accept \`data: string\`, JSON-parse it,
and render the real chart. Defensive: renders nothing if the parse fails
mid-stream (hashbrown feeds partial tokens during \`useJsonParser\`
streaming).
- Change the hashbrown schema on chart \`data\` from
\`s.streaming.array(...)\` to \`s.string(...)\`.
- Drop the non-schema example props (\`trend\` on \`<metric>\`,
\`assignee\` + \`dueDate\` on \`<dealCard>\`).

This unblocks Railway deploys once more. Modeling \`data\` as a string
also matches how the LLM streams it (JSON tokens through
\`useJsonParser\`).

## Why this blocks everything

Same as #4251: while \`npm run build\` fails on the langgraph-python
container, no new image can be pushed to Railway, and the full showcase
deploy pipeline stalls.

## Test plan

- [ ] Validate Showcase CI passes
- [ ] Container builds locally (or in \`showcase_deploy.yml\`) with
schema-validated examples
- [ ] Post-merge: \`showcase_deploy.yml\` run for langgraph-python
succeeds
- [ ] Post-deploy: \`/demos/byoc-hashbrown\` prompt streams JSON that
hits the new string-\`data\` schema; charts render via the wrapper
2026-04-24 13:33:08 +02:00
Alem Tuzlak 698bf85bbb fix(showcase/langgraph-python): align byoc-hashbrown example with strict schema
Wrap PieChart + BarChart with string-accepting wrappers that JSON-parse the
data prop, and change the hashbrown schema from s.streaming.array(...) to
s.string(). Drop the non-schema example props (trend on metric, assignee
+ dueDate on dealCard).

Wave 4a was ported from the starter, which used an older hashbrown where:
  - optional props were declared via .optional()
  - array props accepted stringified JSON in example JSX attributes

@hashbrownai/core@0.5.0-beta.4 dropped .optional() (props omitted from the
schema are treated as not-present) AND tightened example-prompt validation
to reject strings against array schemas. The build failed at prerender:

  Error: Example prompt has 5 errors:
  Prop 'trend' is not defined on <metric>
  Prop 'data' on <pieChart>: Expected an array at: <root>
  Prop 'data' on <barChart>: Expected an array at: <root>
  Prop 'assignee' is not defined on <dealCard>
  Prop 'dueDate' is not defined on <dealCard>

Modeling data as a string matches how the LLM streams it anyway (JSON
tokens through useJsonParser), and the wrappers are defensive about
partial tokens — they render nothing if the parse fails mid-stream.
2026-04-24 13:20:46 +02:00
Alem Tuzlak 6f9f3f220e Merge remote-tracking branch 'origin/main' into fix/showcase-shell-cli-start-not-live-demo
# Conflicts:
#	showcase/shell/src/data/registry.json
2026-04-24 13:16:45 +02:00
Alem Tuzlak f75d901342 fix(showcase/langgraph-python): lazy-init voice runtime to unblock Railway deploys (#4251)
## Problem

Every \`showcase-langgraph-python\` deploy has been **failing** since
#4224 (voice demo) merged:

\`\`\`
[Error: Failed to collect page data for /api/copilotkit-voice]
Missing credentials. Please pass an \`apiKey\`, or set the
\`OPENAI_API_KEY\` environment variable.
Error: failed to solve: process "/bin/sh -c npm run build" did not
complete successfully: exit code: 1
\`\`\`

Root cause: the voice route was instantiating \`new OpenAI({ apiKey:
process.env.OPENAI_API_KEY })\` at module scope. Next.js runs route
modules at build time to collect page/route data, and the Docker build
context does **not** have \`OPENAI_API_KEY\` set (only the running
container does), so the SDK's constructor throws and the build fails.

## Fix

Wrap the \`OpenAI\` + \`TranscriptionServiceOpenAI\` +
\`CopilotRuntime\` construction in a \`getRuntime()\` function that runs
on the first request. Cached after first call so there's no per-request
cost.

Affects only \`/api/copilotkit-voice\`. Runtime behavior is unchanged;
this is a pure build-time-safety fix. The comment on the original code
already said "construct lazily" — the code just didn't match the
comment.

## Why this blocks everything

Railway auto-deploys on every push to \`main\` under \`showcase/**\`.
While this route fails \`npm run build\`, the langgraph-python container
can't be pushed to Railway, which means:

- Voice, multimodal, auth, agent-config, byoc-hashbrown,
byoc-json-render demos all ship nothing new to Railway — every merge
since #4224 has been failing the deploy.
- The dashboard at \`dashboard.showcase.copilotkit.ai\` won't reflect
any of Waves 2b-4b until this lands.

## Test plan

- [ ] Validate Showcase CI passes
- [ ] Container builds locally with \`docker build\` (or CI build job)
when \`OPENAI_API_KEY\` is unset in the build context
- [ ] Post-merge: \`showcase_deploy.yml\` run for \`langgraph-python\`
succeeds
- [ ] Post-deploy: \`/api/copilotkit-voice\` responds normally
(first-request init still works)
2026-04-24 13:11:40 +02:00
Alem Tuzlak d936bc726d fix(showcase-shell): guard demo.route in viewer + preview, share Demo type
Review feedback from #4196:

- `[slug]/[demo]/page.tsx` constructed `${backend_url}${demo.route}`
  without a null check, so command-only demos (which have no `route`)
  rendered an iframe pointing at `${backend_url}undefined`. Now builds
  the src only when `demo.route` exists and renders a 'no live preview'
  panel otherwise, mirroring the Get Started section on the profile
  page. Also replaces the `any`-typed state with proper `Demo` and
  `Integration` types imported from `@/lib/registry`.
- `[slug]/[demo]/preview/page.tsx` had the same bug — already typed
  but TypeScript doesn't catch template-literal coercion of undefined.
  Now bails with a command-focused message before concatenating.
- `profile-client.tsx` no longer duplicates `Demo`/`Integration`
  interfaces — deleted the local copies and imports from
  `@/lib/registry`. copyDemoCommand's catch now logs the failure so a
  double-failure (no clipboard API + blocked prompt) is diagnosable.
  Comment above the live-demos section updated from 'Demos' to
  'Live Demos' to match the rendered heading.
2026-04-24 13:06:45 +02:00
Alem Tuzlak 015bab3054 fix(showcase/langgraph-python): lazy-init voice runtime to unblock build
The voice route was instantiating OpenAI() at module scope, which Next.js
triggers during 'collect page data' at build time. The Docker build context
does NOT have OPENAI_API_KEY set — only the running container does — so
every showcase-langgraph-python deploy has been failing since the voice
demo merged (#4224):

  Error: Missing credentials. Please pass an `apiKey`, or set the
  `OPENAI_API_KEY` environment variable.
  [Error: Failed to collect page data for /api/copilotkit-voice]

Wrap the OpenAI + TranscriptionService + CopilotRuntime construction in
a getRuntime() function that runs on first request. Cached after first
call so there's no per-request cost in production.

This unblocks the full showcase deploy pipeline, not just voice.
2026-04-24 13:03:35 +02:00
Alem Tuzlak d3aa63aa66 chore(showcase/langgraph-python): add sample binaries for voice + multimodal demos (#4250)
## Summary

Follow-up to #4249 (langgraph-python waves 2b–4b consolidation). Adds
the three bundled sample assets that the voice and multimodal demos
reference but had left as placeholders:

| Path | Size | Notes |
|---|---:|---|
| `showcase/packages/langgraph-python/public/demo-audio/sample.wav` | 87
KB | 16 kHz mono, ~2.7 s. Windows TTS clip saying "What is the weather
in Tokyo?" — pairs with the existing `weather` aimock fixture so the
voice demo's "Play sample" → transcribe → send → WeatherCard flow works
end-to-end. |
| `showcase/packages/langgraph-python/public/demo-files/sample.png` | 10
KB | CopilotKit logo (lifted from
`examples/showcases/mcp-demo/public/copilotkit-logo-light.png`). |
| `showcase/packages/langgraph-python/public/demo-files/sample.pdf` |
2.4 KB | One-page CopilotKit quickstart excerpt. Contains the word
"CopilotKit" nine times, matching the multimodal E2E spec's
case-insensitive substring assertion on the agent's PDF summary. |

## Why it's a separate PR

The wave PRs shipped placeholders in those directories (README stubs) so
CI could pass without binaries committed alongside 6 feature branches
running in parallel. This PR lands the three binaries in one tiny
commit, no other code changes.

## Test plan

- [ ] `check-binaries` pre-commit hook passes (all three files are well
under the 1 MB cap)
- [ ] Post-deploy: voice demo's "Play sample" button populates the input
with a transcript containing "weather" / "Tokyo"
- [ ] Post-deploy: multimodal demo's "Try with sample image" and "Try
with sample PDF" buttons produce the expected attachment chips + agent
responses referencing CopilotKit
2026-04-24 12:58:47 +02:00
Alem Tuzlak eada8b1dbe chore: track *.wav via Git LFS and migrate sample.wav
Add *.wav to .gitattributes so audio assets follow the same LFS policy
as the existing *.png / *.pdf / *.gif / *.jpg / *.jpeg / *.mp4 / *.webm
rules. Re-stage sample.wav so the committed object becomes an LFS
pointer instead of a raw 87 KB blob.
2026-04-24 12:52:06 +02:00
Alem Tuzlak 8d14aef816 chore(showcase/langgraph-python): add sample binaries for voice + multimodal demos
- public/demo-audio/sample.wav (87KB, 16kHz mono, ~2.7s) — TTS "What is the weather in Tokyo?" for the voice demo's "Play sample" button
- public/demo-files/sample.png (10KB) — CopilotKit logo for the multimodal demo's "Try with sample image"
- public/demo-files/sample.pdf (2.4KB, one page, contains "CopilotKit" 9x) — quickstart excerpt for the multimodal demo's "Try with sample PDF"

Makes both demos fully self-contained end-to-end; the "Try with sample X" buttons now work without the user providing their own files.
2026-04-24 12:39:48 +02:00
Alem Tuzlak 59e3482743 feat(showcase): consolidate langgraph-python waves 2b–4b (multimodal, auth, agent-config, byoc-hashbrown, byoc-json-render) (#4249)
## Summary

Consolidates 5 independent langgraph-python wave PRs into one branch to
avoid a sequential rebase chain. Wave 2a (voice) already merged via
#4224; this PR carries the remaining five:

- **Wave 2b — multimodal** (supersedes #4225): `<CopilotChat
attachments>` with image + PDF (inline base64), dedicated vision-capable
`multimodal_agent`
- **Wave 3a — auth** (supersedes #4226): `onRequest` bearer-token gate
with an error-first UX showing both 401 and authenticated states
- **Wave 3b — agent-config** (supersedes #4230): forward typed `{tone,
expertise, responseLength}` via `<CopilotKit properties>` to a
dynamic-system-prompt agent
- **Wave 4a — byoc-hashbrown** (supersedes #4229): port starter's
hashbrown renderer into a single-mode demo with
`@hashbrownai/{core,react}`
- **Wave 4b — byoc-json-render** (supersedes #4227): integrate
`@json-render/{core,react}` with a Zod-validated catalog

One consolidated PR means one rebase, one CI wait, one review, one merge
— rather than 5 sequential rebase-fests on shared files (manifest.yaml /
constraints.yaml / docs-links.json / regenerated catalog + registry +
test counts).

## Merge structure

Sequential merge commits from `origin/main` (post-#4224), branches
merged in order: 2b → 3a → 3b → 4a → 4b. Each conflict
(manifest/constraints/docs-links appends, agent-id appends in
langgraph.json, test-count bumps) resolved with union semantics. Final
test counts bumped once to 38 features/demos and 37/1/0
wired/stub/unshipped for LGP, 182/1/480 overall.

## Closes

Once this lands, the following PRs can be closed as superseded:
- #4225
- #4226
- #4227
- #4229
- #4230

## Test plan

- [ ] `nx run showcase-scripts:test` passes (generate-registry +
generate-catalog counts match 38 LGP demos)
- [ ] `nx run showcase-ops:test` passes
- [ ] `pnpm exec tsc --noEmit` clean in `packages/langgraph-python`
- [ ] `python -m pytest src/agents/test_agent_config_agent.py -v` passes
(from Wave 3b)
- [ ] Post-deploy: run each wave's Playwright spec 3× against Railway
- [ ] Post-deploy: walk the langgraph-python column on
dashboard.showcase.copilotkit.ai — all 5 new cells green

## Outstanding (post-merge)

- Sample binaries for voice + multimodal demos — see the voice PR for
voice's `sample.wav` expectation; multimodal needs `sample.png`
(CopilotKit logo) + `sample.pdf` (one-page CopilotKit doc excerpt).
Drop-in commands documented in the team thread on Slack.
- Python `forwardedProps` → `config.configurable` mapping for Wave 3b —
flagged in that wave's PR; agent falls through to defaults cleanly
today, but the dropdowns won't visibly change agent behavior until a
middleware lands.
- V1 NextJS adapter gap surfaced by Wave 3a —
`copilotRuntimeNextJSAppRouterEndpoint` silently drops the `hooks`
option. Wave 3a works around by calling `createCopilotRuntimeHandler`
directly. Worth a core fix.
2026-04-24 12:37:39 +02:00
Alem Tuzlak 4ba79746ae Merge branch 'feat/wave4b-byoc-json-render-demo' into consolidation 2026-04-24 12:28:28 +02:00
Alem Tuzlak 4ef8df8028 Merge branch 'feat/wave4a-byoc-hashbrown-demo' into consolidation 2026-04-24 12:25:02 +02:00
Alem Tuzlak 102f680bc1 Merge branch 'feat/wave3b-agent-config-demo' into consolidation 2026-04-24 12:21:51 +02:00
Alem Tuzlak 1a78be938b Merge branch 'feat/wave3a-auth-demo' into consolidation 2026-04-24 12:19:14 +02:00
Alem Tuzlak 11da7248f0 Merge branch 'feat/wave2b-multimodal-demo' into consolidation 2026-04-24 12:17:14 +02:00
Alem Tuzlak 5bac0a3e47 feat(showcase/langgraph-python): voice demo (Wave 2a) (#4224)
## Summary

Wave 2a — wire the existing `@copilotkit/voice` package into a
`langgraph-python` `/demos/voice` route with a dedicated runtime that
mounts `TranscriptionServiceOpenAI`.

- Dedicated runtime route `/api/copilotkit-voice` with
`transcriptionService: new TranscriptionServiceOpenAI(...)` — the only
route in this showcase that advertises `audioFileTranscriptionEnabled:
true`, so the mic button only appears in this demo.
- Demo page at `/demos/voice` with `<CopilotChat />` plus a
`<SampleAudioButton />` that bypasses the mic: fetches a bundled
`/demo-audio/sample.wav`, POSTs the single-route transcribe envelope to
`/api/copilotkit-voice`, and writes the transcribed text into the chat
textarea (native setter + synthetic input event keeps React state in
sync).
- Sample audio file path wired (`public/demo-audio/sample.wav` — binary
to be added by user, see Concerns).
- QA checklist (`qa/voice.md`) + Playwright E2E spec
(`tests/e2e/voice.spec.ts`) authored.
- `manifest.yaml` + per-shell `registry.json` / `demo-content.json` +
`docs-links.json` wired.
- `voice` was already allowlisted in `showcase/shared/constraints.yaml`
— no change there.
- Small pre-existing pre-commit hook tidy:
`showcase/shell-docs/src/data/demo-content.json` and
`showcase/shell-dojo/src/data/demo-content.json` are already >1 MB on
main; added them to `check-binaries.sh`'s allowlist alongside the
existing `shell` one so any commit that regenerates the bundle (like
this one) can land.

Out of scope (per spec): realtime voice, TTS, continuous dialog, custom
mic UI. Those are later waves.

## Test plan

- [x] `pnpm exec tsc --noEmit` — new files clean (pre-existing errors in
beautiful-chat / headless-complete are untouched baseline).
- [x] `showcase-scripts:test` — no new failures vs. main. Remaining
Windows-specific CLI-subprocess failures are a baseline (same count on
origin/main detached HEAD run); CI on Linux is the source of truth.
- [ ] Sample audio binary added by user (pending —
`public/demo-audio/.gitkeep` + README placeholder committed; path is
wired).
- [ ] Playwright `voice.spec.ts` runs green 3x against Railway
(post-deploy verification).
- [ ] Dashboard walk — `voice` row green for `langgraph-python`
(post-deploy).

## Concerns

- `public/demo-audio/sample.wav` binary must be produced and committed
by the user before the demo works end-to-end. The path is wired (demo
page, sample button, QA, E2E); the file is currently a placeholder
directory.
- E2E stabilization deferred to post-deploy. The new `/demos/voice`
doesn't exist on Railway yet, so the spec was authored (structural
selectors, permissive weather/tokyo regex on transcription) but not
executed — "3x green against Railway" happens once the service redeploys
with this PR.
2026-04-24 11:51:56 +02:00
Alem Tuzlak e5d2612ca9 fix(showcase): sync counts and regen langgraph-python starter after merge
- Bump generate-catalog.test counts for LGP multimodal (wired 31->32,
  unshipped 6->5; metadata wired 176->177, unshipped 486->485).
- Regenerate langgraph-python starter: add multimodal_agent.py, langgraph.json
  graph entry, and pypdf requirement.
2026-04-24 11:09:06 +02:00
Alem Tuzlak 36222515c8 fix(showcase/langgraph-python): regenerate starter + bump catalog test counts
Re-run `generate-starters.ts` for langgraph-python to emit the
byoc_json_render_agent.py starter agent and register it in langgraph.json
(post-merge drift-check was failing because the starter hadn't been
regenerated after adding the byoc-json-render demo).

Bump generate-catalog.test LGP-feature-count assertions 32->33 and
wired-totals 176->177 / 31->32, unshipped 486->485 / 6->5 to match the
new manifest.
2026-04-24 11:06:59 +02:00
Alem Tuzlak 860dfb7187 test(showcase): bump generate-catalog LGP counts for voice demo (32 wired, 1 stub, 5 unshipped) 2026-04-24 11:03:26 +02:00
Alem Tuzlak 825c5404a9 fix(showcase): regen langgraph-python starter + bump catalog counts
Regenerate langgraph-python starter so agent_config_agent is included
(drift-check fails without this). Bump generate-catalog.test.ts counts
to match wiring of agent-config: LGP wired 31→32, LGP unshipped 6→5,
total wired 176→177, total unshipped 486→485.
2026-04-24 11:03:22 +02:00
Alem Tuzlak 03ebe81863 test(showcase-scripts): bump generate-catalog counts for auth demo (Wave 3a) 2026-04-24 10:59:02 +02:00
github-actions[bot] 0d25d1f187 style: auto-fix formatting 2026-04-24 08:56:43 +00:00
Alem Tuzlak 72e94bba29 fix(showcase): regen langgraph-python starter + bump catalog test counts 31/176 -> 32/177 for byoc-hashbrown 2026-04-24 10:56:02 +02:00
github-actions[bot] 355b51c144 style: auto-fix formatting 2026-04-24 08:56:01 +00:00
Alem Tuzlak 9bbc5eb62e Merge branch 'main' into feat/wave4b-byoc-json-render-demo
Resolves conflicts:
- manifest.yaml / constraints.yaml / docs-links.json: keep both byoc-json-render
  and main's re-wired open-gen-ui + open-gen-ui-advanced entries
- scripts/hooks/check-binaries.sh: keep both shell-docs and shell-dojo
  demo-content exclusions (identical lines, different ordering)
- pnpm-lock.yaml (langgraph-python): regenerated via pnpm install
- shell/shell-dojo/shell-docs data JSONs: accept main's deletion (now
  regenerated by nx targets), then regenerate via scripts/generate-registry.ts
  and scripts/bundle-demo-content.ts

Bump generate-registry.test expected feature/demo count 32 -> 33 to account
for the new byoc-json-render demo.
2026-04-24 10:53:56 +02:00
Alem Tuzlak 7c66420a9f Merge remote-tracking branch 'origin/main' into feat/wave2b-multimodal-demo
# Conflicts:
#	showcase/aimock/feature-parity.json
#	showcase/packages/langgraph-python/docs-links.json
#	showcase/packages/langgraph-python/manifest.yaml
#	showcase/shell-docs/src/data/demo-content.json
#	showcase/shell-docs/src/data/registry.json
#	showcase/shell-dojo/src/data/demo-content.json
#	showcase/shell-dojo/src/data/registry.json
#	showcase/shell/src/data/constraints.json
#	showcase/shell/src/data/demo-content.json
#	showcase/shell/src/data/docs-status.json
#	showcase/shell/src/data/registry.json
2026-04-24 10:51:23 +02:00
github-actions[bot] e0190fd25d style: auto-fix formatting 2026-04-24 08:47:16 +00:00
github-actions[bot] d8fddba4de style: auto-fix formatting 2026-04-24 08:46:55 +00:00
github-actions[bot] ec80ac367b style: auto-fix formatting 2026-04-24 08:46:45 +00:00
Alem Tuzlak 5e3004be9c Merge remote-tracking branch 'origin/main' into feat/wave2a-voice-demo
# Conflicts:
#	showcase/shell-docs/src/data/demo-content.json
#	showcase/shell-docs/src/data/registry.json
#	showcase/shell-dojo/src/data/demo-content.json
#	showcase/shell-dojo/src/data/registry.json
#	showcase/shell/src/data/demo-content.json
#	showcase/shell/src/data/docs-status.json
#	showcase/shell/src/data/registry.json
2026-04-24 10:46:20 +02:00
Alem Tuzlak 022db41164 chore: merge origin/main into feat/wave4a-byoc-hashbrown-demo
Resolves conflicts in:
- showcase/packages/langgraph-python/manifest.yaml (byoc-hashbrown + open-gen-ui demos/features coexist)
- showcase/packages/langgraph-python/docs-links.json (subagents path from main + byoc-hashbrown entry)
- showcase/shared/constraints.yaml (merge both feature additions)
- Regenerated shell/*/data JSONs now gitignored on main; deletions accepted.

Bumps generate-registry.test.ts langgraph counts 32 -> 33 (byoc-hashbrown added).
2026-04-24 10:45:53 +02:00
Alem Tuzlak c12426b69e chore: merge origin/main into feat/wave3b-agent-config-demo
Resolves textual conflicts in manifest.yaml and docs-links.json (keeps
both open-gen-ui* from main and agent-config from this branch). Accepts
main's deletion of generated shell*/src/data/*.json (now gitignored).
Bumps langgraph-python feature/demo count test from 32 to 33.
2026-04-24 10:45:17 +02:00
Alem Tuzlak c2db5e706f chore: merge origin/main into feat/wave3a-auth-demo
Resolved conflicts:
- showcase/packages/langgraph-python/manifest.yaml: kept auth (HEAD) +
  open-gen-ui / open-gen-ui-advanced (main) in both features and demos.
- showcase/packages/langgraph-python/docs-links.json: kept auth entry
  from HEAD alongside updated subagents shell_docs_path.
- showcase/shared/constraints.yaml: kept auth + open-gen-ui* entries.
- Deleted shell/shell-dojo/shell-docs generated JSONs per main (now
  generated at build, no longer committed).

Bumped langgraph-python feature/demo count 32 -> 33 in generate-registry
test to reflect the added auth demo.
2026-04-24 10:45:05 +02:00
Jordan Ritter 415e371c87 fix(ci): generate registry.json before starter deployed smoke tests (#4247)
## Summary

Fixes the repeating "Starter Deployed Smoke Test Failed — 0 failure(s) —
job-level error" alerts in #oss-alerts.

**Root cause:** `integration-smoke.spec.ts` imports `registry.json`,
which is now gitignored (generated at build time, removed from tracking
in PR #4236). The CI workflow didn't run the generator before tests, so
the import fails with "Cannot find module."

**Fix:** Add a `generate-registry` step before the Playwright test run.

## Test plan
- [ ] Next scheduled run (or manual dispatch) passes without "Cannot
find module" error
- [ ] #oss-alerts stops receiving "job-level error" messages
2026-04-24 01:21:41 -07:00
Jordan Ritter 1baf168a95 fix(ci): generate registry.json before starter deployed smoke tests
The test at integration-smoke.spec.ts:21 imports registry.json, which
is gitignored (generated at build time). After PR #4236 removed it
from tracking, every CI run fails with "Cannot find module
'../../shell/src/data/registry.json'" — producing the repeating
"Starter Deployed Smoke Test Failed — 0 failure(s) — job-level error"
Slack alerts in #oss-alerts.

Adds a generate-registry step before the Playwright test run.
2026-04-24 01:19:58 -07:00