Commit Graph

1601 Commits

Author SHA1 Message Date
Jordan Ritter 9e5b458612 fix: use div instead of p tag in Markdown to prevent hydration errors (#2234) (#3821)
## Summary

Fixes #2234

React's hydration fails when block-level elements (like `<div>`) are
nested inside `<p>` tags in the Markdown component. Replaces the `<p>`
wrapper with `<div>` (adding `copilotKitParagraph` class for styling) to
prevent SSR hydration mismatches.

## Test plan

- [ ] Verify Markdown rendering in SSR context has no hydration errors
- [ ] Verify paragraph styling is preserved via `copilotKitParagraph`
class
2026-04-14 14:26:02 -07:00
Jordan Ritter 14eef93d20 fix: scope .dark CSS selectors to CopilotKit elements (#3850)
## Summary

- **console.css + input.css:** Scope `.dark` CSS selectors to CopilotKit
container elements (`.copilotKitDevConsole
.copilotKitDebugMenuTriggerButton` and `.poweredBy` respectively). The
original selectors had bare `.dark,` as standalone entries in
comma-separated selector lists, which applied styles to *any* element
with class `.dark` instead of scoping to CopilotKit elements.
- **colors.css:** Remove broken `:root` pseudo-element from
`body[style*="color-scheme: dark"] :root` — `:root` is `<html>`, which
cannot be a descendant of `<body>`, so this selector never matched
anything.
- **E2E tests:** 4 Playwright regression tests verifying dark mode
styles don't leak into host application elements.

Prevents CopilotKit dark-mode styles from leaking into the host
application.

Closes #2920

---
*Split from #3847*
2026-04-14 14:25:57 -07:00
Jordan Ritter e1ef523a3e fix: resolve agent factory functions in V1 CopilotRuntime constructor (#3865)
## Summary

- The V1 `CopilotRuntime` constructor did `{...endpointAgents,
...agents}` which silently spread a factory function to `{}`, destroying
all agents with no error or warning
- Anyone using the V1 API with a factory function (introduced in #3854)
got zero agents — complete silent data loss
- This wraps factory functions so endpoint agents are merged at
resolution time instead of construction time, matching how V2 already
handles it via `resolveAgents()`

Fixes the V1 path regression from #3854 (per-request agent factory,
issue #2941).

## Test plan

- [x] New test: factory function is preserved through constructor (not
spread to `{}`)
- [x] New test: factory resolves different agents per-request based on
headers
- [x] New test: endpoint agents are correctly merged with
factory-resolved agents
- [x] New test: static agent records still work (backward compat)
- [x] New test: promised agent records still work (backward compat)
- [x] Red-green verified: 4/5 tests fail without the fix, all 5 pass
with it
- [x] Full runtime test suite passes (1234 tests)
- [x] Full build passes
2026-04-14 14:06:14 -07:00
Jordan Ritter b9748a6e0e fix: widen openai peer dep range to include v6.x
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.
2026-04-14 13:57:49 -07:00
Jordan Ritter a8b224e935 fix: replace unsafe type casts with proper type guards for OpenAI v4/v5 compat
- 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
2026-04-14 13:50:23 -07:00
Jordan Ritter fbf1af2419 fix: propagate copyToClipboard success result to CopyButton UI state
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>.
2026-04-14 13:47:44 -07:00
Jordan Ritter 093f41907a fix: extract shared copyToClipboard utility to eliminate clipboard duplication
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.
2026-04-14 13:39:42 -07:00
Jordan Ritter b7b885e086 fix: scope dark theme CSS variables in colors.css
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.
2026-04-14 13:33:59 -07:00
Jordan Ritter 3d0873cc1e test: add userToggledRef behavior tests for reasoning message
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
2026-04-14 13:12:28 -07:00
Jordan Ritter 93547c933e test: wrap fireEvent.click in act() for deterministic reasoning toggle test
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.
2026-04-14 12:42:06 -07:00
Jordan Ritter 8cf8f03a57 fix: respect user expand/collapse intent in reasoning message
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.
2026-04-14 12:41:22 -07:00
Jordan Ritter b63708490d fix: apply oxfmt formatting 2026-04-14 11:53:31 -07:00
github-actions[bot] 8933ee82b5 style: auto-fix formatting 2026-04-14 16:39:04 +00:00
Alem Tuzlak e977a49972 fix: address CR findings for debug mode feature
- Fix clone() dropping debug config on ProxiedCopilotRuntimeAgent
- Pass raw DebugConfig to agents instead of collapsing to boolean
- Clamp verbose to false when enabled is false
- Fix pino-pretty log format in docs (parentheses, timestamps, levels)
- Add loggedEventCount to doc example
- Fix "Agent run started/finished" → actual log messages in arch docs
2026-04-14 18:35:32 +02:00
Alem Tuzlak 488c7d00e0 fix: address PR review feedback for debug mode
- Count all emitted events unconditionally (eventCount), track separately
  how many were logged (loggedEventCount) — completion log shows both
- Remove dead `?? undefined` on runtime.debug (non-optional type)
- Update test to verify eventCount reflects actual events; add test with
  events: true to verify loggedEventCount
2026-04-14 18:34:49 +02:00
Alem Tuzlak 7e0a632e64 test: add debug mode tests for shared, runtime, and core packages 2026-04-14 18:34:47 +02:00
Alem Tuzlak 99c3a39a29 style: fix prettier formatting 2026-04-14 18:34:47 +02:00
Alem Tuzlak 4ec0230cf8 fix(runtime): guard debug property access for backward compat with mock runtimes 2026-04-14 18:34:46 +02:00
Alem Tuzlak 7b9abc142c feat(react-core): add debug prop to CopilotKit provider, thread to AG-UI agent 2026-04-14 18:34:45 +02:00
Alem Tuzlak 0b2731e8da feat(runtime): add debug logging to SSE event pipeline 2026-04-14 18:34:08 +02:00
Alem Tuzlak b9127c18c1 feat(runtime): accept debug config on CopilotRuntime constructor 2026-04-14 18:34:07 +02:00
Alem Tuzlak cc5410dc4f feat(shared): add DebugConfig type and resolveDebugConfig utility 2026-04-14 18:34:07 +02:00
Alem Tuzlak 983274f7c3 Merge branch 'main' into worktree-nested-tinkering-quail 2026-04-14 14:11:42 +02:00
Alem Tuzlak 19b99dd2ae fix(runtime): widen TanStack message content type for adapter compat (#3747)
## Summary

- Widen `TanStackChatMessage.content` from `TanStackContentPart[]`
  to `any[]` so messages from `convertInputToTanStackAI` are directly
  passable to any TanStack AI adapter without `as any` casts
- Split `TanStackContentPart` into a proper discriminated union with
  separate variants per modality
- Add `env.d.ts` with `vite/client` reference for CSS import types
- Fix `onError` callback shape in the example

## Test plan

- [x] All 17 multimodal TanStack tests pass
- [x] All 294 agent tests pass
- [ ] Verify no TS errors in react-router example IDE

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-14 14:11:18 +02:00
Martha Schumann e814e91030 test: add unit tests for ThreadStoreRegistry, thread handlers, and hook lifecycle
- New ThreadStoreRegistry suite (8 tests) covers register/get round-trip,
  replacement on duplicate id, unregister no-op, and subscriber events for
  both register and unregister
- handle-threads suite gains handleClearThreads (InMemory path + intelligence
  path) and handleGetThreadMessages (InMemory, unknown thread, intelligence
  delegation, 422 fallback) describe blocks
- in-memory-runner suite: clearThreads() in beforeEach fixes GLOBAL_STORE
  isolation; vacuous empty-array test replaced with a meaningful post-clear
  assertion
- use-threads suite: new test asserts registerThreadStore is called on mount
  and unregisterThreadStore is called on unmount

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 15:43:28 -07:00
Martha Schumann 0ee11987e3 feat(web-inspector): add Threads tab with early-access gate and thread store integration
Wires the new Angular Custom Elements into the web inspector's Threads tab.
The tab is hidden behind an early-access gate (isEarlyAccessUser check);
_demoMode defaults to false. The inspector registers its own per-agentId
thread store unless one is already registered by useThreads(), preventing
accidental overwrites for apps that use both.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 15:43:28 -07:00
Martha Schumann 0e913ea33e feat(web-inspector-angular): new Angular Custom Elements package for thread UI
Exports cpk-thread-list, cpk-thread-details, and cpk-empty-events as
Custom Elements so the thread panel UI works in any framework (Angular,
React, plain HTML). Components use RxJS observables and Angular signals
internally, then render via defineElements() to register as standard
Web Components.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 15:43:28 -07:00
Martha Schumann 14ae28cfd1 feat(inspector): add thread store registry, runtime handlers, and useThreads hook
- CopilotKitCore gains a ThreadStoreRegistry (register/unregister by agentId)
  and a new onAgentRunStarted subscriber event so the inspector can subscribe
  before agent.runAgent() snapshots the subscriber list
- Runtime gains handleListThreads, handleUpdateThread, handleArchiveThread,
  handleDeleteThread, handleSubscribeToThreads, and handleGetThreadMessages
  handlers; all mutations are authenticated via identifyUser (request body
  userId is ignored)
- InMemoryAgentRunner now stores thread history for the local-dev fallback
  path; debug console.log removed; InMemoryThread uses literal types for
  constant-value fields (organizationId: "", createdById: "", archived: false)
- useThreads hook registers its store with CopilotKitCore on mount and
  unregisters on unmount so the inspector can read thread state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 15:43:27 -07:00
Nathan 🔶 Tarbert 8a651db6d9 fix: inspector not receiving AG-UI events from per-thread agent clones
useAgent() returns per-thread clones that are not in the agent registry.
The inspector only subscribed to registry agents via onAgentsChanged, so
it never received events from clones — resulting in an empty event panel.

Add onAgentRunStarted subscriber event that fires before connectAgent()
and runAgent(), passing the actual agent instance (which may be a clone).
The inspector subscribes to that agent, matching the existing StateManager
pattern (subscribeAgentToStateManager).
2026-04-13 17:58:10 -04:00
Jordan Ritter 5e9fec77ba fix: update blockquote nested paragraph selector after p-to-div change
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.
2026-04-13 14:38:22 -07:00
Jordan Ritter 8244b0f31f fix: guard clipboard calls and only show copied state on success (#2114)
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.
2026-04-13 09:16:11 -07:00
Jordan Ritter b53844c8c3 test: add OpenAI SDK v4/v5 compatibility tests (#1979)
Cover isOpenAIV5 detection, getChatCompletionsForStreaming dispatch,
and named-path-param calling conventions for runs.retrieve and
submitToolOutputsStream.
2026-04-13 09:11:28 -07:00
Jordan Ritter 0b26088586 fix: clone visited-refs set to prevent false circular-ref detection across sibling branches
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.
2026-04-13 09:08:54 -07:00
Jordan Ritter 6bf84f3cec fix: support OpenAI SDK v5 in adapter and assistant adapter (#1979)
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
2026-04-13 09:07:38 -07:00
Jordan Ritter ac0ceda748 fix: replace tautological test with real unit tests for error visibility
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.
2026-04-13 09:05:38 -07:00
Jordan Ritter 18552b561f fix: add circular $ref cycle detection in JSON schema to Zod conversion
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.
2026-04-13 08:30:33 -07:00
Jordan Ritter 23ea810c5a fix: remove unstable key on CodeBlock to prevent flickering during streaming
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
2026-04-13 08:28:28 -07:00
Jordan Ritter 4e10f1344a fix: resolve agent factory functions in V1 CopilotRuntime constructor
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.
2026-04-13 08:27:19 -07:00
Jordan Ritter 7998a46659 fix: update CSS selectors to match div-based paragraph component
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.
2026-04-13 08:25:22 -07:00
Alem Tuzlak f55cd5f7e2 Merge remote-tracking branch 'origin/main' into worktree-nested-tinkering-quail
# Conflicts:
#	packages/runtime/src/v2/runtime/handlers/get-runtime-info.ts
2026-04-13 15:03:54 +02:00
Ran Shemtov 9788c07dcc Merge branch 'main' into fix/issue-1921 2026-04-13 15:01:32 +02:00
Ran Shemtov 454ba9b17a Merge branch 'main' into fix/issue-1936 2026-04-13 14:58:03 +02:00
Ran Shemtov ced35df1b2 Merge branch 'main' into fix/issue-1921 2026-04-13 14:56:05 +02:00
Ran Shemtov 7a7955a440 Merge branch 'main' into fix/issue-2941 2026-04-13 14:50:24 +02:00
Alem Tuzlak 4b279cee64 fix: address code review findings on capabilities
- Restore getCapabilities() return type to Promise<AgentCapabilities>
  with ?? {} fallback, honoring AbstractAgent base class contract
- Simplify type annotation in get-runtime-info.ts to explicit
  AgentCapabilities | undefined instead of complex Awaited<ReturnType<...>>
- Add console.warn logging to per-agent capabilities error catch block
- Fix useCapabilities JSDoc to accurately describe behavior during
  runtime handshake
- Add test for empty capabilities object {} (truthy, included in response)
- Update error isolation test to verify warning is logged
2026-04-13 14:49:50 +02:00
Ran Shemtov dcfd7da220 Merge branch 'main' into fix/issue-3499 2026-04-13 14:43:42 +02:00
github-actions[bot] a6fb46b555 style: auto-fix formatting 2026-04-13 09:23:53 +00:00
Alem Tuzlak ee926b8628 fix: address capabilities review feedback
- Add per-agent error isolation in /info handler so a single
  getCapabilities() failure doesn't 500 the whole endpoint
- Normalize getCapabilities() to return undefined (not {}) when no
  capabilities are set, matching the sync getter
- Replace instanceof ProxiedCopilotRuntimeAgent with duck-type check
  in useCapabilities hook for extensibility
- Add JSDoc warning about shallow-merge behavior on capabilities config
- Add useCapabilities hook tests (5 cases covering both branches)
- Add per-agent error isolation test for get-runtime-info
2026-04-13 11:22:22 +02:00
Alem Tuzlak 327d134ecd Merge remote-tracking branch 'origin/main' into worktree-nested-tinkering-quail
# Conflicts:
#	packages/angular/package.json
#	packages/core/package.json
#	packages/demo-agents/package.json
#	packages/react-core/package.json
#	packages/runtime/package.json
#	packages/shared/package.json
#	packages/sqlite-runner/package.json
#	packages/web-inspector/package.json
#	pnpm-lock.yaml
2026-04-13 11:12:25 +02:00
Jordan Ritter d1c3708050 fix: batch useAgent forceUpdate calls via microtask to prevent scroll jumping (#3499)
When useAgent subscribes to multiple update types (OnMessagesChanged,
OnStateChanged, OnRunStatusChanged), each event fires forceUpdate()
independently. During streaming this causes dozens of re-renders per
second, leading to brief content height fluctuations that trigger
scroll jumping in use-stick-to-bottom.

Coalesce OnStateChanged and OnRunStatusChanged notifications using
queueMicrotask so multiple synchronous events within the same tick
produce a single React re-render. OnMessagesChanged retains its
existing behavior (direct or throttled).
2026-04-12 16:19:55 -07:00