Python starters were trying to run uvicorn with agent.<module>:app but
those modules don't export a FastAPI app. The demo packages use
agent_server.py as the FastAPI wrapper, so starters need it too.
Changes:
- Copy agent_server.py from each demo package into starter root,
rewriting "from agents." to "from agent." for the starter layout
- Update all non-langgraph Python devScripts to use agent_server:app
- Update Dockerfile.python to COPY agent_server.py for non-langgraph
- Update getEntrypointBlock() generic Python to use agent_server:app
- Make langgraph-fastapi use langgraph_cli dev like langgraph-python
(it was incorrectly configured as a uvicorn-based starter)
- Regenerate all starters
Use jq to build JSON payloads safely and payload-file-path to avoid
inline multiline content. Limits error context to 3 lines, strips ANSI
codes, and caps field length at 200 chars.
- drift-detection: split payload build from post, sanitize playwright output
- starter-smoke: replace toJSON(format(...)) double-encoding with jq
- showcase_deploy: replace 300-char inline ternary with readable shell conditional
The langgraph-python starter crashes on Railway because of a directory
structure mismatch: agents were in agent/ with langgraph.json inside
agent/, causing langgraph_cli to fail resolving module paths.
Match the demo package's working layout:
- Move agents from agent/ to src/agents/ (same as demo)
- Put langgraph.json at project root (same as demo)
- Point entrypoint at root langgraph.json instead of agent/langgraph.json
- Templatize Dockerfile.python with AGENT_DIR and DOCKER_EXTRA_COPY vars
- Skip langgraph.json path rewriting when agentDir matches agentSourceDir
- Update tests to use framework agentDir instead of hardcoding "agent"
Regenerate all 17 starters.
Two new test cases covering the core behavioral fix:
- User collapses during streaming → panel stays collapsed after stream ends
- User collapses then re-expands during streaming → panel stays open after stream ends
Without act(), React 18 defers the state update through its scheduler,
which can race with waitFor polling on slow CI runners (Node 20.x/22.x).
Wrapping in act() forces synchronous flush.
The auto-collapse useEffect unconditionally called setIsOpen(false) when
streaming ended, overriding any manual expand/collapse the user had
performed. Add a userToggledRef that tracks explicit clicks so the
effect only auto-collapses when the user hasn't interacted.
The CopyButton in react-core was showing the "copied" checkmark based on
an independent clipboard availability check rather than the actual copy
result. This meant a failed copy (e.g. permission denied) would still
show the success indicator. Now the onClick handler returns the boolean
from copyToClipboard, and handleClick uses that to drive the UI state.
Also removes unsafe type casts of onClick to Promise<void>.
Address review feedback: extract the repeated clipboard availability check +
writeText + error handling pattern into a shared copyToClipboard() utility in
@copilotkit/shared. All 9 call sites across angular, react-core, and react-ui
now use the shared utility instead of duplicating the same code block.
Add null checks for navigator.clipboard across all copy-to-clipboard
calls to prevent TypeError in non-localhost environments where the
Clipboard API is unavailable. The copied indicator now only appears
after a confirmed successful write, preventing false positive UX
feedback when the clipboard API is missing or the write fails.
Extract getErrorSuppression as a pure testable function from the
routeError closure. Replace the mock-only test that only proved mock
wiring with 12 real assertions covering all visibility x isDev
combinations against the actual logic.
The routeError function returned early for ALL errors when
showDevConsole was false, suppressing user-visible errors
(TOAST and BANNER visibility) in production.
Now only DEV_ONLY and SILENT errors are suppressed in production.
TOAST and BANNER errors are always surfaced to the chat UI.
The original Math.random() key caused React to remount the CodeBlock on
every render. The PR's content-based key (language + content prefix) still
changed every streaming token, causing the same flickering. Removing the
key entirely lets React use positional identity, which is stable across
re-renders while content streams in.
Closes#2669
The shared visitedRefs Set was mutated in place, so when two sibling
properties referenced the same $def (e.g. billing and shipping both
referencing Address), the second resolution was incorrectly flagged as
circular. Clone the set before recursing so each branch has its own
ancestry path. Added regression test that fails without this fix.
Recursive JSON schemas that reference themselves via $ref would cause
infinite recursion and stack overflow. This adds a visited set that
tracks which $ref paths have been seen during resolution. When a cycle
is detected, it breaks with z.any() and logs a console.warn so users
get feedback. Also adds console.warn for the generic z.any() fallback
on unsupported schema types.
Adds tests for circular refs, non-circular $ref resolution, anyOf with
$ref variants, integer type, null type, and unsupported type warning.
The compatibility layer correctly handles v6 (same API surface as v5),
but the version range ^5.0.0 excluded v6.x. Changed to >=5.0.0 so
users on the latest openai SDK don't get peer dependency warnings.
- Remove all `as any`, `as Function`, and `as Record<string, unknown>` casts
from production code in the OpenAI compatibility layer
- Introduce typed `OpenAIV4Beta` interface and `hasV4BetaChat` type guard
for safe runtime detection of v4 vs v5 clients
- Extract `retrieveThreadRun` and `submitToolOutputsStream` helper functions
into utils.ts with properly typed generic signatures, moving the v4/v5
dispatch logic out of the assistant adapter
- Give `getChatCompletionsForStreaming` an explicit return type so callers
no longer need secondary casts
- Update tests to exercise the new helpers directly instead of
duplicating dispatch logic inline
The openai specifier in package.json was updated to ^4.85.1 || ^5.0.0
but the lockfile was not regenerated, causing all CI jobs to fail with
frozen-lockfile mismatch errors.
Cover isOpenAIV5 detection, getChatCompletionsForStreaming dispatch,
and named-path-param calling conventions for runs.retrieve and
submitToolOutputsStream.
OpenAI SDK v5 removed beta.chat (promoted to chat.completions) and
changed multi-path-param methods to use named params (e.g.
runs.retrieve(runId, { thread_id }) instead of positional args).
- Add isOpenAIV5() detection and getChatCompletionsForStreaming() helper
- Migrate OpenAIAdapter to use helper for streaming completions
- Migrate OpenAIAssistantAdapter runs.retrieve() and
submitToolOutputsStream() to branch on SDK version
- Add openai ^4.85.1 || ^5.0.0 to peerDependencies
The blockquote.copilotKitMarkdownElement p selector targeted literal <p>
elements inside blockquotes, but paragraphs now render as <div> after
the hydration fix. Updated to target .copilotKitParagraph class instead.
Also removes unused import and adds a regression test for this selector.
The p tag was changed to div to fix hydration errors, but CSS selectors
still targeted p.copilotKitMarkdownElement. Updated to use the
.copilotKitParagraph class selector so paragraph styling (line-height,
font-size, margin) applies correctly to the new div element.
Same bug pattern as console.css and input.css: bare `.dark,` was a
standalone selector leaking all --copilot-kit-* CSS custom properties
onto any element with a .dark class. Also removed broken `:root`
pseudo-element from `body[style*="color-scheme: dark"] :root` — :root
cannot be a descendant of body, so this selector never matched.
Fix: drop standalone `.dark,` (redundant with `html.dark` and
`body.dark`) and remove the non-functional `:root` descendant.
Remove captured-but-never-asserted colorBefore and markerColorLight
variables. Replace silent if-guard in poweredBy test with explicit
test.skip so missing elements surface in test reports instead of
silently passing.
Verifies that .dark CSS selectors in console.css and input.css are
properly scoped to CopilotKit elements and do not leak into the host
application. Tests detect the specific rgb(69, 69, 69) color leak that
occurred when .dark was used as a standalone selector.
The langgraph.json in the starter was copied verbatim from the demo package
with path ./src/agents/main.py:graph, but the starter flattens agents into
the agent/ dir so the correct path is ./main.py:graph.
Also wraps A2UI agent imports in try/except so the starter starts cleanly
even if copilotkit's ToolRuntime patch isn't available — these are optional
features that shouldn't prevent the core agent from running.
Fixes the generate-starters.ts script to rewrite langgraph.json graph paths
when copying from packages to starters, preventing this drift in the future.
The com.ag-ui.community artifacts aren't published to Maven Central,
so the Docker build fails when resolving dependencies. The demo package
Dockerfile already handles this by cloning the ag-ui repo and running
mvn install before building the agent — mirror that in the template
and regenerate the starter.
The V1 CopilotRuntime constructor did `{...endpointAgents, ...agents}`
which silently spread a factory function to `{}`, losing all agents.
Anyone using the V1 API with a factory function got zero agents and no
error. This wraps factory functions so endpoint agents are merged at
resolution time instead of construction time.
The _sanitize_for_json function was applied to state sync events and
get_state responses but not to the raw event stream yielded at line 507.
Events with NaN/Infinity float values in their data payloads would
produce invalid JSON (literal NaN) that downstream parsers cannot handle.
Verifies langchain_messages_to_copilotkit correctly concatenates all text
parts from list-style content blocks (Anthropic models). Includes
regression tests for the exact scenario from #1748 (text + image blocks)
and tests for string lists, mixed content, empty lists, and edge cases.
When Anthropic models return multi-part content lists, only the first
element was used and the rest discarded. Now iterates all parts and
concatenates text blocks, preserving the full message content.