Commit Graph

8565 Commits

Author SHA1 Message Date
Mike Ryan 0139ebb0e7 chore: remove CopilotKit CLI (don't worry! It's just moving homes 🏠) (#4588)
<!--
Thank you for sending the PR! We appreciate you spending the time to
work on these changes.

Help us understand your motivation by explaining why you decided to make
this change.


**Please PLEASE reach out to us first before starting any significant
work on new or existing features.**

By the time you've gotten here, you're looking at creating a pull
request so hopefully we're not too late.

We love community contributions! That said, we want to make sure we're
all on the same page before you start.
Investing a lot of time and effort just to find out it doesn't align
with the upstream project feels awful, and we don't want that to happen.
It also helps to make sure the work you're planning isn't already in
progress.

As described in our contributing guide, please file an issue first:
https://github.com/ag-ui-protocol/ag-ui/issues
Or, reach out to us on Discord: https://discord.com/invite/6dffbvGU3D


You can learn more about contributing to copilotkit here:
https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md

Happy contributing!

-->

## What does this PR do?

(Describe the changes introduced in this PR)

## Related PRs and Issues

- (Direct link to related PR or issue, if relevant)

## Checklist

- [ ] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [ ] If the PR changes or adds functionality, I have updated the
relevant documentation
- [ ] "Allow edits by maintainers" is checked (lets us help iterate on
your PR directly — faster turnaround for everyone)
2026-05-01 13:35:25 -07:00
Mike Ryan 8648e4a838 chore: remove CopilotKit CLI 2026-05-01 13:16:49 -07:00
Tyler Slaton df3c961276 Merge branch 'main' into feat/CPK-7193-inspector-threads-clean 2026-05-01 12:40:38 -07:00
Jordan Ritter e7391e2c88 feat(showcase): skip D5 probes for recently deployed services (#4571)
## Summary

- When a Railway service deployed within the last 2 minutes, the D5
probe driver skips all features with green side rows instead of
launching a browser and producing false reds from deploy churn
- Discovery source now threads `deployedAt` (from
`latestDeployment.createdAt`) through to drivers via
`RailwayServiceInfo`
- Skip fires before script loader and browser launch so recently
deployed services cost zero probe resources

## Changes

**`showcase/harness/src/probes/discovery/railway-services.ts`**
- Added `deployedAt: string` to `RailwayServiceInfo` interface
- Added `createdAt` to the Zod schema for `latestDeployment` and the
GraphQL query
- Extracts `createdAt` in the enrichment loop and passes it through

**`showcase/harness/src/probes/drivers/e2e-deep.ts`**
- Added `DEPLOY_CHURN_GRACE_MS` constant (120,000ms = 2 minutes)
- Added `deployedAt` to the driver's input Zod schema
- Deploy-churn skip logic inserted after feature resolution, before
script loading and browser launch
- When `deployedAt` is within the grace window: emits green side rows
with `note: "skipped: deploy in progress (Ns ago)"` and returns
aggregate green with all features in `skipped[]`

**`showcase/harness/src/probes/drivers/e2e-deep.test.ts`**
- 8 new tests covering: skip path, normal execution when outside grace
window, backwards compat (absent/empty/unparseable `deployedAt`),
boundary at exactly `DEPLOY_CHURN_GRACE_MS`, and 0s-age edge case

## Test plan

- [x] `npx tsc --noEmit -p showcase/harness/tsconfig.json` passes
cleanly
- [x] All 40 e2e-deep driver tests pass (8 new + 32 existing)
- [x] All 58 railway-services discovery tests pass unchanged
- [ ] CI green
2026-05-01 10:42:08 -07:00
GeneralJerel 15bf868cb8 feat(showcase-finance-erp): polish demo chat UX
- Persistent follow-up suggestion chips above the input; the third chip
  rotates based on the currently loaded dashboard so we never suggest
  switching to the dashboard the user is already viewing.
- Hide the assistant message toolbar except on hover and only on the
  latest turn — drops the floating copy icon that previously appeared
  mid-conversation between tool cards.
- Replace the raw markdown preview under do_research/do_projections
  tool cards with a clean "Completed data gathering" status caption.
- Expand the orchestrator prompt with natural-language intent mapping
  so spending / cash-flow / revenue / executive-overview questions
  route to load_dashboard against the matching template (no save +
  reset + update churn), and approval-context invoice queries route
  to request_approval instead of just charting.
2026-05-01 10:27:18 -07:00
Alem Tuzlak 86acef1a1b fix(showcase): loosen reasoning-display probe to OR(testid, keyword) (#4580)
## Summary

PR #4579 tightened the d5-reasoning-display probe to require BOTH a
reasoning-role testid AND a keyword in the transcript. That flipped most
integrations from D5 to D4 because the strong selector check is only
valid for cells whose AG-UI bridge emits role-reasoning messages with a
stable testid. Cells that surface reasoning inline as assistant text —
`llamaindex`, `crewai-crews`, several variants that use CopilotKit's
default `CopilotChatReasoningMessage` slot which has no `data-testid` —
were always green via the keyword check and shouldn't have been
regressed.

This PR loosens the probe to pass on **either** signal:

- A known reasoning testid (`reasoning-block`, `reasoning-content`,
`reasoning-default`) or `[data-message-role="reasoning"]` — strong
signal that AG-UI REASONING_MESSAGE_* events reached the frontend.
- OR a reasoning keyword in the assistant transcript — looser fallback
for cells that surface reasoning inline as text, or use the default
reasoning slot.

It also broadens the testid list to cover `reasoning-content` and
`reasoning-default`, which are used in several showcase ReasoningBlock
components but were missing from the original tightening.

The strict path is preserved where it works: `langgraph-python` and
`langgraph-fastapi` still emit role-reasoning messages with
`data-testid="reasoning-block"` and pass the strong check first. The
strict end-to-end assertions live in `langgraph-python`'s e2e specs from
PR #4579 and continue to enforce it for that integration specifically.

`claude-sdk-typescript`'s "assistant did not respond within 30000ms"
failure is a separate backend-timeout issue, not addressed here.

## Notes

Committed with `--no-verify` (worktree has no node_modules, lefthook
can't run nx; CI runs the same checks).

## Test plan

- [ ] CI fixture-validation passes
- [ ] `showcase test crewai-crews --d5 --verbose` — reasoning-display
green again
- [ ] `showcase test pydantic-ai --d5 --verbose` — reasoning-display
green again
- [ ] `showcase test langgraph-python --d5 --verbose` — still green via
strict selector path
- [ ] Production D4 → D5 reverts on most integrations after deploy
2026-05-01 14:37:28 +02:00
Alem Tuzlak 028ebf3157 fix(showcase): revert reasoning field on aimock d5 reasoning fixture (hot-fix) (#4581)
## Hot fix

PR #4579 added a `reasoning` field to the `show your reasoning step by
step` fixture in `showcase/aimock/d5-all.json` (and
`showcase/harness/fixtures/d5/reasoning-display.json`). Intent: make
aimock emit `response.reasoning_summary_text.delta` events for the
OpenAI Responses API path so the langgraph-python reasoning demo renders
deterministically against aimock.

**Side effect:** aimock also injects non-standard `reasoning_content`
deltas into the OpenAI **Chat Completions** SSE stream (DeepSeek / Qwen
convention) when `reasoning` is set. Verified against the production
aimock — every `chat.completion.chunk` now starts with `delta: {
reasoning_content: "..." }` chunks before the role/content chunks. Most
integration OpenAI client adapters do not expect those leading deltas
and either fail to parse the stream or hang waiting for a proper first
chunk — surfacing in the dashboard as "assistant did not respond within
30000ms" across most reasoning cells.

This PR reverts both fixture entries to their pre-#4579 content-only
form. Production heals immediately on the next aimock fixture reload.

## What's still working

- The langgraph-python / langgraph-fastapi agent fixes from #4579
(gpt-5-mini + Responses API + reasoning summary) remain in place — when
the real OpenAI deployment runs, reasoning streams as before.
- Every other integration that was D5 before #4579 returns to D5 —
aimock now emits the original plain-text response and the d5 probe's
keyword check passes.

## What's lost (acceptable trade-off)

- The langgraph-python / langgraph-fastapi e2e specs that assert
`[data-testid="reasoning-block"]` against aimock will fail until either
(a) aimock is taught to suppress `reasoning_content` deltas on Chat
Completions when other integrations need a clean stream, or (b) the e2e
tests are split to run only against real OpenAI. Filed as follow-up —
out of scope for the production hot-fix.

## Notes

Committed with `--no-verify` (worktree has no node_modules; CI runs the
same checks). Stacks on top of #4580 conceptually but neither depends on
the other.

## Test plan

- [ ] Production reasoning cells flip back from D4 → D5 on next probe
run after deploy
- [ ] `curl
https://showcase-aimock-production.up.railway.app/v1/chat/completions
...` no longer returns leading `reasoning_content` deltas
- [ ] `showcase test claude-sdk-typescript --d5` no longer times out
2026-05-01 14:37:18 +02:00
Alem Tuzlak a3586fb62a fix(showcase): revert reasoning field on aimock d5 reasoning fixture
PR #4579 added a `reasoning` field to the "show your reasoning step by
step" fixture so aimock would emit response.reasoning_summary_* deltas
for the OpenAI Responses API path. Side effect: aimock's Chat
Completions handler also emits non-standard `reasoning_content` deltas
(DeepSeek/Qwen-style) ahead of the role/content chunks. Many
integrations' OpenAI client adapters don't expect those deltas and
either hang or fail to parse the stream — manifesting as "assistant
did not respond within 30000ms" across most reasoning cells in
production.

Restore the original content-only fixture. The langgraph-python /
langgraph-fastapi agent fixes from #4579 still work against real
OpenAI (gpt-5-mini + Responses API streams real reasoning summaries),
but the aimock-driven path no longer exercises the role-reasoning
render — keyword-only assertion in the d5 probe handles that.
2026-05-01 14:07:21 +02:00
Alem Tuzlak 2e18d07d5e fix(showcase): loosen reasoning-display probe to OR(testid, keyword)
Tightening the probe to require BOTH a reasoning-role testid AND a
keyword match flipped most integrations from D5 to D4 in production.
The strong selector check is only valid for cells whose AG-UI bridge
emits role-reasoning messages with a stable testid; cells that surface
reasoning inline as assistant text (llamaindex, crewai-crews, several
default-slot variants whose CopilotChatReasoningMessage has no testid)
were always green via the keyword check and shouldn't have been
regressed.

Pass on either signal: a known reasoning testid OR a reasoning keyword
in the transcript. Also broaden the testid list to cover the
reasoning-content and reasoning-default variants used in showcase.

Doesn't change the langgraph-python / langgraph-fastapi outcome — those
cells still emit role-reasoning messages with data-testid="reasoning-block"
and pass the strong check first. The integration-specific assertions in
langgraph-python's e2e specs continue to enforce the strict path.
2026-05-01 14:02:13 +02:00
Alem Tuzlak 51db05f666 fix(showcase): emit reasoning events in langgraph-python and langgraph-fastapi (#4579)
## Summary

The `agentic-chat-reasoning` and `reasoning-default-render` cells in
`langgraph-python` and `langgraph-fastapi` never rendered any reasoning
content. Root cause: both agents were configured with `gpt-4o-mini` +
`use_responses_api=False`, so the underlying model produced no reasoning
content blocks and the Chat Completions API has no reasoning summary
surface in the first place. The frontend's `reasoningMessage` slot
stayed empty even though the cells are billed as reasoning demos.

This PR:

- Switches both agents (and their `tool_rendering_reasoning_chain`
siblings) to `gpt-5-mini` through the Responses API with
`reasoning={"effort":"medium","summary":"detailed"}`, mirroring the
`langgraph-typescript` and `pydantic-ai` agents that already worked.
Model is overridable via `OPENAI_REASONING_MODEL`.
- Updates the aimock `d5-all.json` fixture (and the matching harness
`reasoning-display.json`) to set the `reasoning` field on the `show your
reasoning step by step` match. Aimock now emits
`response.reasoning_summary_text.delta` events so the demo renders
deterministically without a real LLM call.
- Adds a `Show reasoning` `useConfigureSuggestions` pill on both
reasoning pages in both integrations so the demo is one click to
exercise.
- Tightens the `d5-reasoning-display` probe to also assert that a
reasoning-role message rendered (`[data-testid="reasoning-block"]` or
`[data-message-role="reasoning"]`), not just that the word "reasoning"
appears in the transcript.
- Un-skips the three streaming reasoning-block tests in
`agentic-chat-reasoning.spec.ts`, adds a suggestion-pill test, and
extends `reasoning-default-render.spec.ts` to cover the default
reasoning slot.
- Updates the `langgraph-python` QA doc to describe the new model +
Responses API setup and the pill flow.

Verified locally end-to-end: clicking the pill at
`/demos/agentic-chat-reasoning` renders the amber `ReasoningBlock` with
the fixture's reasoning text above the final answer bubble.

## Out of scope

Other integrations were audited and intentionally left alone:

- `langgraph-typescript`, `pydantic-ai` already use a reasoning model +
Responses API and work today.
- `agno`, `claude-sdk-python`, `ms-agent-python` use deliberate
workarounds (XML-tag reasoning + custom AGUI handler, Claude
extended-thinking deltas, `think` tool respectively) because their AG-UI
bridges either don't translate Responses-API reasoning items, run a
multi-call CoT loop incompatible with fixture replay, or don't emit
reasoning events at all.
- `llamaindex` uses `gpt-4.1` and surfaces reasoning inline as assistant
text. Its bridge (`llama-index-protocols-ag-ui`) does not translate
Responses-API reasoning items into AG-UI events; fixing that needs an
upstream patch and is out of scope here.

## Notes

Committed with `--no-verify` (explicit user request) — this worktree has
no `node_modules`, so the lefthook `test-and-check-packages` step
couldn't run locally. Changes are entirely under `showcase/` and CI runs
the same checks.

## Test plan

- [ ] CI fixture-validation passes on `showcase/aimock/d5-all.json`
- [ ] `showcase test langgraph-python --d5 --verbose` —
`reasoning-display` probe green (asserts `reasoning-block` selector +
keyword)
- [ ] `showcase test langgraph-fastapi --d5 --verbose` — same
- [ ] `nx run @copilotkit/showcase-langgraph-python:test:e2e -- --grep
reasoning` — un-skipped specs pass against the deployed Railway image
- [ ] Manual: visit `/demos/agentic-chat-reasoning` on a deployed
langgraph-python, click `Show reasoning`, confirm amber `REASONING —
Agent reasoning` block renders with italic step text above the final
answer bubble
- [ ] Manual: same on `/demos/reasoning-default-render`, confirm
CopilotKit's default `CopilotChatReasoningMessage` card renders
2026-05-01 13:40:10 +02:00
Ran Shemtov 17745c36b0 chore: upgrade langgraph integration demos (#4320) 2026-05-01 13:35:29 +02:00
Ran Shemtov 41b7fa1cb3 Merge branch 'main' into chore/upgrade-langgraph-integration-demos 2026-05-01 13:35:10 +02:00
Alem Tuzlak 7f9da6919b fix(aimock): unbreak beautiful-chat suggestions + e2e regression (#4578)
## Summary

The 6 beautiful-chat demos (spring-ai, strands, langroid, agno,
claude-sdk-typescript, claude-sdk-python) ship three identical
suggestion chips. Against the deployed aimock-backed showcase, all three
were broken:

| Suggestion | Symptom | Cause |
|---|---|---|
| Plan a 3-day Tokyo trip | Returned a generic "Hi there! I'm your
showcase assistant…" greeting | Substring `"hi"` matches inside
**arc*hi*tecture**, hijacked by the broad `userMessage: "hi"` fixture |
| Explain RAG like I'm 12 | aimock 4xx — `"No fixture matched"` | No
fixture |
| Draft a launch email | aimock 4xx — `"No fixture matched"` | No
fixture |

Verified locally against `showcase up spring-ai` in a headed browser —
all three now return on-topic content.

## Fix

Add three full-sentence fixtures before the broad `"hi"` matcher in
`feature-parity.json`. Aimock's matcher is substring + first-match-wins
by file order, so the long sentence matchers win first and the `"hi"`
fixture is never reached for these prompts. Each returns a plausible
markdown response (3-day Tokyo itinerary, open-book-test analogy,
3-paragraph launch email).

## Regression coverage

Replaced the 1-line beautiful-chat placeholders with a 4-test suite for
all 6 integrations:

- Page loads with heading + chat input
- Each suggestion's reply contains the expected keywords (`Day 1|Day
2|Day 3`, `open-book|retrieval|RAG`, `Subject:|co-pilot|launch`)
- Each test ALSO asserts `toHaveCount(0)` against `/I'm your showcase
assistant/i` — if the broad "hi" fixture re-broadens or the new fixtures
are reordered/removed, the tests fail with a useful message.

## Test plan

- [x] `validate-fixture-tool-surface` clean: 141 fixtures × 628 demos,
no drift
- [x] Manual headed-browser verification on `showcase up spring-ai` —
all 3 suggestions return their on-topic responses
- [ ] CI's `Validate Showcase` job stays green
- [ ] On-demand E2E (`/test-aimock <slug>`) passes for any of the 6
integrations
2026-05-01 13:34:47 +02:00
github-actions[bot] 6032b374c4 style: auto-fix formatting 2026-05-01 11:32:58 +00:00
Alem Tuzlak dca1b9894d fix(showcase): emit reasoning events in langgraph-python and langgraph-fastapi
The agentic-chat-reasoning and reasoning-default-render cells in
langgraph-python and langgraph-fastapi were configured with
gpt-4o-mini + use_responses_api=False, which never produces AG-UI
REASONING_MESSAGE_* events: gpt-4o-mini is not a reasoning model and
the Chat Completions API does not surface reasoning summary items at
all. The frontend's reasoningMessage slot was rendering nothing,
even though the cells were billed as "reasoning" demos.

- Switch both reasoning agents to gpt-5-mini (override via
  OPENAI_REASONING_MODEL) routed through the Responses API with
  reasoning={"effort":"medium","summary":"detailed"} so the model's
  chain of thought streams as content blocks that @ag-ui/langgraph
  translates into REASONING_MESSAGE_* events.
- Update the aimock d5-all.json and harness reasoning-display.json
  fixtures to include a "reasoning" field so aimock emits
  response.reasoning_summary_text.delta SSE events deterministically
  in CI without hitting a real LLM.
- Add a "Show reasoning" useConfigureSuggestions pill on both
  reasoning demo pages so the user can trigger the fixture-matched
  prompt with one click.
- Tighten the d5-reasoning-display probe: it now also asserts a
  reasoning-role message rendered via [data-testid="reasoning-block"]
  or [data-message-role="reasoning"], so a plain text response
  containing the word "reasoning" no longer falsely passes.
- Un-skip the three streaming reasoning-block tests in
  langgraph-python's agentic-chat-reasoning.spec.ts and add a
  suggestion-pill test; expand the reasoning-default-render spec to
  cover the default reasoning slot.
- Update the langgraph-python QA doc to describe the new model +
  Responses API setup and the suggestion-pill flow.
2026-05-01 13:30:28 +02:00
Alem Tuzlak a549de3a41 fix(aimock): add fixtures for beautiful-chat suggestions + e2e regression
The 6 beautiful-chat demos (spring-ai, strands, langroid, agno,
claude-sdk-typescript, claude-sdk-python) ship three identical
suggestion chips: "Plan a 3-day Tokyo trip", "Explain RAG like I'm
12", and "Draft a launch email". Against the deployed aimock-backed
showcase, all three were broken:

- Tokyo trip: hijacked by the broad `userMessage: "hi"` fixture,
  because the substring "hi" appears inside "arc**hi**tecture" in
  the prompt. Returned a generic "Hi there! I'm your showcase
  assistant..." greeting with nothing about Tokyo.
- RAG explain: no fixture matched, aimock returned an error.
- Launch email: same — no fixture, error.

Add three on-topic fixtures with the full suggestion sentence as
`userMessage` (effectively-exact substring match). Place them
before the broad "hi" fixture in the file so first-match-wins
routes each suggestion to the right response.

Add a `beautiful-chat.spec.ts` regression suite to all 6
integrations: send each suggestion, assert the right keywords
appear in the assistant reply ("Day 1/2/3" for Tokyo,
"open-book/RAG" for RAG, "Subject:/co-pilot" for email), AND
assert the hijacked greeting is absent. If the broad "hi" fixture
re-broadens or the new fixtures are reordered/removed, these
tests fail loudly.
2026-05-01 13:17:44 +02:00
Ran Shem Tov d1e2aeef35 chore: enable hasAppMode for langgraph-js smoke test 2026-05-01 13:08:49 +02:00
Ran Shem Tov 2358034310 chore: ratchet showcase pin baseline to 97 2026-05-01 13:01:30 +02:00
Alem Tuzlak f13c49f92f fix(showcase): drop hardcoded white chat background that broke dark mode (#4577)
## Summary

-
`showcase/integrations/{langgraph-python,langgraph-typescript,mastra,built-in-agent}/src/app/copilotkit-overrides.css`
(and the starter template that seeds new integrations) all forced
`.copilotKitChat { background-color: #fff !important; }`. The
`!important` won over the per-demo `ThemeProvider`, so the
`beautiful-chat` demo rendered a white chat panel in dark mode.
- `langgraph-fastapi` has no overrides file and was already correct —
this PR brings the other four to parity by deleting just the offending
rule (the `.copilotKitInput` border styles are kept).
- Updated `showcase/STYLING-GUIDE.md` with a warning so the example
block doesn't get pasted back in.

## Test plan

- [ ] Open `/demos/beautiful-chat` in `langgraph-python` with the OS in
dark mode — chat background follows the dark theme (no white panel).
- [ ] Same check for `langgraph-typescript`, `mastra`, and
`built-in-agent`.
- [ ] `langgraph-fastapi` unchanged (regression check on the working
baseline).
- [ ] Light mode in all four still renders correctly (chat picks up the
v2 light tokens).
2026-05-01 12:56:02 +02:00
Alem Tuzlak f396638c32 fix(aimock): add HITL 1:1-with-Alice fixture before broad Alice match (#4576)
## Summary

The hitl-in-chat demo's **"Schedule a 1:1 with Alice next week to review
Q2 goals."** suggestion was being intercepted by the broad `userMessage:
"Alice"` matcher used by the memory/context demo, which returns a
generic "Nice to meet you, Alice! I see you're in Tokyo — wonderful
city..." greeting. The HITL flow never fired and the user saw a
nonsensical reply.

Aimock's matcher uses `text.includes(match.userMessage)` (substring) +
first-fixture-wins by file order, so any message containing "Alice"
hijacked the suggestion before the HITL flow could trigger.

## Fix

Added a fixture pair earlier in `showcase/aimock/feature-parity.json`
with the **full suggestion sentence** as the matcher:

- `hasToolResult: false` → returns a `book_call` toolCall, letting the
frontend `useHumanInTheLoop` render the time-picker.
- `hasToolResult: true` → returns the booking confirmation message.

The substring-match-on-full-sentence is effectively exact — no other
realistic user message will contain that whole sentence — so the broad
`Alice` / `alice` fixtures stay scoped to the memory demo where the user
actually says "I'm Alice" or similar.

## Test plan

- [ ] Click "Schedule a 1:1 with Alice next week to review Q2 goals." in
the langgraph-python hitl-in-chat demo against an aimock-backed
deployment → expect the time-picker card to render and a booking
confirmation after picking a slot.
- [ ] The memory/context demo (where users type "I'm Alice") still gets
the Tokyo greeting — broad fixtures unchanged.
- [x] Pre-commit hooks pass (test, check-packages, commitlint).
2026-05-01 12:55:46 +02:00
Ran Shem Tov fa01c3510a chore: sync example-layout to north-star 2026-05-01 12:54:09 +02:00
Alem Tuzlak 3bb798c4ee fix(showcase): switch langgraph-python gen-ui-agent to v2 useAgent (#4574)
## Summary

The langgraph-python `gen-ui-agent` demo was the only one of 18
integrations still using the V1 `useCoAgentStateRender` hook. That hook
binds renders to messages via per-message claims, so each state-changing
`set_steps` tool call produced its own card snapshot in the chat — a
3-step plan run pushed ~7+ stacked, near-duplicate cards instead of one
updating card.

This PR migrates the demo to the canonical V2 pattern already used by
every other gen-ui-agent demo (mastra, strands, ag2, agno, crewai-crews,
langgraph-typescript, pydantic-ai, ...): subscribe to live state via
`useAgent` and render a single `InlineAgentStateCard` inside
`messageView.children`. The card now re-renders in place as state
streams.

Also tightens the agent system prompt with an explicit numbered tool
sequence (1 plan + 6 transitions + final message) to reduce the "step 3
stuck in_progress" tail-of-run failure with `gpt-4o-mini`. The UI is
robust to a missed final transition either way: when `agent.isRunning`
flips to false, the card headlines "All N steps complete" regardless of
step.status.

## Regression coverage

The previous e2e spec targeted a long-removed `task-progress` test id
and silently never matched the current UI. Replaced with assertions that
pin the contract:

- **exactly one** `[data-testid="agent-state-card"]` is rendered,
including after the run finishes
- every `[data-testid="agent-step"]` ends in `data-status="completed"`

These will fail if either bug regresses.

## Test plan

- [ ] Run the langgraph-python integration locally + click "Plan a
product launch" → confirm a single card updates in place from "Step 1 of
3" → "All 3 steps complete"
- [ ] `npx playwright test gen-ui-agent.spec.ts` against the running
stack
- [x] Pre-commit hooks pass (lint-fix, test, check-packages, commitlint)
- [x] Format / oxlint clean on all touched files
2026-05-01 12:52:04 +02:00
Alem Tuzlak e83915ac94 fix(aimock): scope HITL toolCall fixtures with toolName so they don't drift
The previous commit dropped `hasToolResult: false` from the two HITL
toolCall fixtures so they could fire on a second user turn (after
prior tool history). That made them too broad: validate-fixture-tool-
surface.ts flagged 34 drift violations because the same Alice/sales
suggestion strings also appear in the gen-ui-interrupt and
interrupt-headless demos, whose agents do NOT register `book_call`.
Aimock would have returned a dangling book_call toolCall to those
demos at runtime.

Add `toolName: "book_call"` to both toolCall fixture matchers. At
runtime aimock filters by request.tools — the fixture now only fires
for agents that actually register `book_call` (hitl-in-chat). The
drift validator has matching logic (line 83) that skips demos
without the named tool, so it goes from 34 violations → clean.
2026-05-01 12:46:39 +02:00
Alem Tuzlak 25e03ef0e8 fix(showcase): drop hardcoded white chat background that broke dark mode
The shared `copilotkit-overrides.css` files in langgraph-python,
langgraph-typescript, mastra, built-in-agent, and the starter template
forced `.copilotKitChat { background-color: #fff !important; }`, which
won over the demo-level `ThemeProvider` and made the beautiful-chat
demo render a white panel in dark mode. langgraph-fastapi has no
overrides file and was unaffected — same fix gets the others to parity.

Also add a warning in showcase/STYLING-GUIDE.md so the example block
isn't pasted back in by the next contributor.
2026-05-01 12:43:15 +02:00
Alem Tuzlak 9845dadebb fix(aimock): re-key HITL confirmations on toolCallId so back-to-back flows work
Bug: in a single chat session, running both HITL booking flows
back-to-back (Alice 1:1 → then Sales call without refresh) used to
skip the time-picker on the second flow and jump straight to
"Booked ..." text.

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

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

Add a back-to-back regression test to all 17 hitl-in-chat specs:
walk Alice flow to completion, then sales flow without refresh,
assert two `time-picker-card` elements rendered. If the multi-flow
regression returns, the second card never appears and the test
fails at `toHaveCount(2)`.
2026-05-01 12:42:53 +02:00
Ran Shem Tov 67d22d88ec chore: fix smoke tests on lg-js 2026-05-01 12:31:05 +02:00
Ran Shem Tov 84af438694 chore: use latest cpk 2026-05-01 12:31:05 +02:00
Ran Shem Tov e40add8f7a chore: fix parity with showcase 2026-05-01 12:31:05 +02:00
Ran Shem Tov 2143b9666d chore: use latest js sdk 2026-05-01 12:31:04 +02:00
Ran Shem Tov 50498fe6e7 chore: fix peripherals for smoke tests and parity 2026-05-01 12:31:04 +02:00
Ran Shem Tov 8bae258b84 chore: fix peripherals for smoke tests and parity 2026-05-01 12:31:04 +02:00
Ran Shem Tov 73e5e2cb54 chore: fix dockerfile for langgraph fastapi demo 2026-05-01 12:31:04 +02:00
Ran Shem Tov 0b41bebe23 chore: fix showcase drift 2026-05-01 12:31:04 +02:00
github-actions[bot] 3f814cf602 style: auto-fix formatting 2026-05-01 12:31:04 +02:00
Ran Shem Tov a79481439a chore(integrations/langgraph-fastapi): sync to langgraph-python reference demo 2026-05-01 12:31:04 +02:00
Ran Shem Tov efb37668b3 chore(integrations/langgraph-js): use latest packages 2026-05-01 12:31:04 +02:00
Ran Shem Tov e77df6d16b chore(integrations/langgraph-js): fix state streaming 2026-05-01 12:31:04 +02:00
Ran Shem Tov f13f8865a8 feat(sdk-js/langgraph): zodState helper for agent state schemas
Add a zodState() helper that attaches a lazy `~standard.jsonSchema.input`
to a zod schema so LangGraph's StateSchema.getJsonSchema() emits the
field into the graph's output_schema. Without it, zod v4 fields carry
`~standard.validate` + `vendor` only, `isStandardJSONSchema` returns
false, and the field is silently dropped from output_schema — which in
turn causes the AG-UI LangGraphAgent proxy to filter the value out of
STATE_SNAPSHOT events on the wire, so the frontend never sees it even
though the underlying thread state has the data.

Apply zodState to the middleware's own `copilotkit` state field so it
surfaces in output_schema and export it for demos to use on custom
state fields (todos, documents, etc.).

Uses `z.toJSONSchema` when available (zod v4 subpath) and falls back to
an empty object, which is sufficient to make langgraph-api include the
key in output_schema.
2026-05-01 12:31:04 +02:00
Ran Shem Tov 091eb86f16 chore(integrations/langgraph-js): port agent to createAgent + fix Docker
Rewrite the langgraph-js agent to use `createAgent` from `langchain`
(matching langgraph-python) with `copilotkitMiddleware` and
`stateStreamingMiddleware` from `@copilotkit/sdk-js/langgraph-middlewares`.
Tools now use `ToolRuntime` for state and tool-call-id access. System
prompt inlined in `agent.ts`; drop the file-based `PROMPT.md`.

Replace the legacy single-stage Dockerfile with a Node-only two-stage
build that mirrors the langgraph-python Dockerfile (frontend build →
runner, HttpAgent route override for Docker, Turbopack→webpack).

Add JS-specific `entrypoint.sh` (launches `@langchain/langgraph-cli dev`
+ Next.js standalone) and `docker-compose.test.yml` (wget healthcheck
for the alpine-based agent image, STARTER=langgraph-js default). Both
added to the instance's `allowedDivergence` in the parity manifest.

Rewrite the README to drop Python/uv prerequisites and list the correct
TypeScript tool paths.
2026-05-01 12:31:04 +02:00
Ran Shem Tov 09501b43ed chore(integrations/_parity): inline-prompt contract + track Dockerfile
Two small changes to the parity tooling, surfaced while validating it on
the langgraph-fastapi port.

1. Drop the per-instance PROMPT.md file. The reference demo
   (langgraph-python) does not load agent/PROMPT.md at runtime — it inlines
   the prompt as a triple-string literal in agent/main.py. Syncing a
   cosmetic PROMPT.md file to every instance created a contract the code
   did not follow. Now:
   - sync.ts no longer writes agent/PROMPT.md per instance.
   - verify.ts greps the first non-blank line of _parity/canonical/PROMPT.md
     against each instance's agent source. Inline the prompt string in
     source; verifier passes.
   - Deleted the now-orphaned PROMPT.md copy under langgraph-js/agent/.

2. Track Dockerfile, docker/Dockerfile.agent, and serve.py in the shared
   verbatim-files list. These were previously silent "allowed divergence"
   across all instances — any Docker or runtime-adapter drift shipped
   unflagged. Now:
   - Added to tracked.verbatimFiles in manifest.json.
   - langgraph-js keeps them in allowedDivergence (Node-only stack, legit
     difference from the Python-based reference).
   - langgraph-fastapi drops them from allowedDivergence (same language
     stack as the reference; Docker/serve.py should match).

README and the copilotkit-demo-parity skill updated to match the new
prompt contract. Verifier still supports `--target` and exits non-zero on
unexpected drift.
2026-05-01 12:31:04 +02:00
Ran Shem Tov c9793b5e6e chore(integrations/langgraph-js): sync to langgraph-python reference demo
Align langgraph-js with examples/integrations/langgraph-python via the
parity tooling. Remove legacy app/ layout, adopt src/ layout, rewrite
the TS agent to expose the tracked tool surface (manage_todos,
get_todos, query_data, generate_a2ui, search_flights) and todos state,
and write the canonical PROMPT.md. Keeps LangGraphAgent + stategraph
runtime (allowed divergence per the manifest); brings deps,
Dockerfile.app, entrypoint, showcase metadata, and shared UI into
lockstep. Parity verifier: 88 ok / 0 error.
2026-05-01 12:31:04 +02:00
Ran Shem Tov 2bb9f3fdf4 chore(integrations): add _parity tooling + copilotkit-demo-parity skill
Introduce machinery for keeping examples/integrations/* demos aligned to a
single north-star (langgraph-python). Built first so the upcoming
langgraph-js and langgraph-fastapi alignment PRs have a mechanical baseline
to work against instead of manual copy-paste.

- examples/integrations/_parity/manifest.json declares verbatim files,
  tracked package.json keys, and expected agent surface (tool names,
  state keys) per instance plus allowed-divergence lists.
- _parity/sync.ts copies verbatim files + rewrites tracked package.json
  keys from north-star to a target instance. Dry-run supported.
- _parity/verify.ts diffs each instance vs north-star and exits non-zero
  on unexpected drift. Checks verbatim content, tracked keys, canonical
  prompt equality, and agent-surface grep-level presence.
- Canonical prompt at _parity/canonical/PROMPT.md — synced into each
  instance's agent/PROMPT.md on parity:sync.
- Root package.json: pnpm parity:sync, parity:verify, parity:check.
- CI: .github/workflows/integrations_parity.yml runs parity:check on PRs
  touching examples/integrations/**.
- Skill: .claude/skills/copilotkit-demo-parity/SKILL.md teaches agents
  how to drive sync/verify and handle manual-merge zones (agent code,
  api route, Dockerfile).

Does NOT touch the existing instance demos yet. Those alignment commits
follow in the same PR.
2026-05-01 12:31:04 +02:00
Alem Tuzlak 8cb84e88eb test(showcase): replicate hitl-in-chat regression spec across all 17 integrations
The hitl-in-chat demo ships in 17 integrations (langgraph-python plus
16 others — mastra, strands, ag2, agno, crewai-crews,
langgraph-typescript, langgraph-fastapi, pydantic-ai, llamaindex,
langroid, claude-sdk-python, claude-sdk-typescript, ms-agent-python,
ms-agent-dotnet, spring-ai, google-adk). All shipped placeholder e2e
specs that only checked the chat input was visible — none exercised
the actual booking flow.

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

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

Per-integration coverage matters because each integration has its
own framework-specific HITL wiring (`useHumanInTheLoop` binding to
the agent, agent-side tool registration, run streaming protocol)
that can regress independently of the shared aimock fixture.
2026-05-01 12:25:36 +02:00
Alem Tuzlak 846a8a8938 test(showcase): add hitl-in-chat regression spec for Alice 1:1 suggestion
Pins the contract that the new full-sentence aimock fixture pair beats
the broad `userMessage: "Alice"` matcher:

1. Sending the suggestion `"Schedule a 1:1 with Alice next week to
   review Q2 goals."` renders `[data-testid="time-picker-card"]`,
   not the Tokyo greeting. The test explicitly asserts the Tokyo
   greeting is absent — `toHaveCount(0)` against
   `/Nice to meet you, Alice/i` — so any future broad-match
   regression fails here loudly.
2. Clicking a slot transitions to `[data-testid="time-picker-picked"]`
   and the assistant follow-up message contains "Booked ... Alice",
   verifying the `hasToolResult: true` branch of the fixture pair
   also wires through.
2026-05-01 12:17:24 +02:00
Alem Tuzlak 7661a72ead fix(aimock): add HITL 1:1-with-Alice fixture before broad Alice match
The hitl-in-chat demo's "Schedule a 1:1 with Alice next week to review
Q2 goals." suggestion was being intercepted by the broad
`userMessage: "Alice"` matcher used by the memory/context demo, which
returns a generic "Nice to meet you, Alice! I see you're in Tokyo --
wonderful city..." greeting. Aimock matches `userMessage` via
`text.includes(...)` substring + first-fixture-wins, so any message
containing "Alice" hijacked the suggestion before the HITL flow could
fire.

Add a fixture pair earlier in the file with the full suggestion text
as the matcher: returns a `book_call` toolCall on the first turn
(letting the frontend `useHumanInTheLoop` render the time-picker), and
a confirmation message after the user picks a slot (`hasToolResult:
true`). The substring-match-on-full-sentence is effectively exact —
no other realistic message will contain that whole sentence — so the
broad Alice/alice fixtures stay scoped to the memory demo where the
user actually says something like "I'm Alice".
2026-05-01 12:06:56 +02:00
Alem Tuzlak 06785a064c fix(showcase): allow microphone in demo iframe so voice demos work (#4573)
## Summary

- Voice demos across all 18 integrations were throwing
`AudioRecorderError: Microphone permission denied` the moment a user
clicked the mic button — no permission prompt, no transcription,
nothing.
- Root cause: the showcase shell embeds each demo in a cross-origin
iframe whose `allow` attribute only granted `clipboard-read;
clipboard-write`. Browsers default cross-origin iframe access to
`microphone=()` and reject `getUserMedia({ audio: true })` at the
Permissions Policy layer before any user prompt is shown. The voice
package itself catches that as a permission denied error.
- Fix: add `microphone` to the iframe `allow` in all three places that
embed demo previews — the per-demo viewer, the standalone preview route,
and the demo drawer — so voice demos work uniformly across every
integration.

No other demo type uses `getUserMedia` / `getDisplayMedia` /
`geolocation`, so no further Permissions Policy features are needed.

## Test plan

- [x] Run shell locally, open
`localhost:3000/integrations/langgraph-python/voice` in a headed
Chromium with `microphone` granted to the context. Confirm the mic
records and transcription returns successfully (verified manually — no
Permissions Policy violation in the console).
- [ ] Smoke any one of the other integrations' voice demo (mastra, agno,
crewai-crews, etc.) through the same iframe — change is generic across
all 18 integrations.
- [ ] Verify the demo drawer (homepage demo browser) also lets the mic
work.
2026-05-01 11:50:31 +02:00
Alem Tuzlak e79cac1208 fix(showcase): unblock gen-ui-agent recursion + drop deepagents wrapper
Verified end-to-end against a local langgraph-python stack: agent now
walks plan → step1 in_progress → step1 completed → ... → final summary,
and the frontend renders a single inline progress card that updates in
place all the way to "All 3 steps complete".

Two real changes pulled out from the verification round:

1. agent.py: drop the `deepagents.create_deep_agent` wrapper for the
   plain `langchain.agents.create_agent` ReAct loop. The deepagents
   planner / sub-agent / write_todos middleware ate enough supersteps
   per turn that the run regularly tripped LangGraph's recursion
   limit before the agent could publish all three step transitions.
   The plain ReAct loop is one superstep per LLM/tool call, and
   `state_schema=GenUiAgentState` is supported directly so the
   middleware-only state-extension hack is gone.

2. route.ts: bake `recursion_limit: 100` into every LangGraphAgent
   via `assistantConfig`. `with_config({"recursion_limit": ...})` on
   the compiled Python graph does NOT propagate when the graph is
   served via the langgraph runs API — the wrapper is invisible to
   the assistant config the server hands to Pregel, which then falls
   through to langchain_core's hard-coded default of 25. Setting
   `assistantConfig.recursion_limit` on the JS side makes the limit
   travel with every run kicked off through this route, regardless
   of what the Python graph thinks its config is.
2026-05-01 11:47:40 +02:00
Ran Shemtov 0f28ff0e49 Bump version to 0.1.88 (#4575) 2026-05-01 11:36:17 +02:00
Ran Shemtov 5aaca65485 chore: release sdk-python 0.1.88 2026-05-01 09:33:19 +00:00
Alem Tuzlak 0fcf904978 fix(showcase): switch langgraph-python gen-ui-agent to v2 useAgent
The langgraph-python gen-ui-agent demo was the only one of 18
integrations using the V1 `useCoAgentStateRender` hook. That hook
binds renders to messages via per-message claims, so each
state-changing tool call (each `set_steps` invocation) produced its
own card snapshot in the chat — a typical 3-step plan run pushed
~7+ stacked cards instead of one updating card.

Migrate the page to the canonical V2 pattern already used by every
other gen-ui-agent demo (mastra, strands, ag2, agno, crewai-crews,
langgraph-typescript, pydantic-ai, ...): subscribe to live state via
`useAgent` and render a single `InlineAgentStateCard` inside
`messageView.children`. The card now re-renders in place as state
streams — no per-message claims, no duplicates.

Also tighten the agent system prompt with an explicit numbered tool
sequence (1 plan + 6 transitions + final message) to make the
"step 3 stuck in_progress" tail-of-run failure less likely with
gpt-4o-mini. The UI is robust to a missed final transition either
way: when `agent.isRunning` flips to false, the card headlines
"All N steps complete" regardless of step.status.

Replace the stale e2e spec (which targeted a long-removed
`task-progress` test id) with one that pins the contract:
- exactly one `agent-state-card` rendered, even after the run
  finishes
- every `agent-step` ends in `data-status="completed"`
2026-05-01 11:11:17 +02:00