Updated JSDoc and troubleshooting docs to accurately describe that
the client-side debug prop forwards config to the AG-UI transport
layer, not CopilotKit's own logging. Removed fabricated console.debug
output examples that don't exist.
debug was only read at construction time. Added setDebug() to
CopilotKitCore and added it to the provider's prop-sync useEffect
so runtime changes to the debug prop take effect.
- 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>
- 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>
- 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
- 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
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).
Skip keydown handling during IME composition (e.g. CJK input) by
checking isComposing/keyCode 229, and guard textarea measurement
from resetting value mid-composition.
Radix UI's asChild pattern requires the child component to forward
refs. The Button component was a plain function, causing a React
warning when nested inside DropdownMenuTrigger. Converted to
React.forwardRef so the ref is properly passed through to the
underlying DOM element.
When the backend emits RunErrorEvent via the AG-UI protocol, several
components did not handle it:
- ProxiedCopilotRuntimeAgent: isRunning stayed true, causing
data-copilot-running to never transition to false (infinite spinner)
- StateManager: activeRun entries were never cleaned up, runFinished
flag never set (stale state on subsequent runs)
- Angular CopilotKitAgent: same isRunning bug as the proxy agent
- useAgentNodeName: node name stuck at last step instead of "end"
onRunErrorEvent is distinct from onRunFailed — the former handles
protocol-level RUN_ERROR events from the backend, the latter handles
local exceptions (network errors, deserialization failures).
The ui/message handler added messages to the chat but never called
runAgent(), so the agent never processed MCP-sent messages.
- Use copilotkit.runAgent({ agent }) through RunHandler for frontend
tools, context, tool execution, and abort support
- Send JSON-RPC response immediately after addMessage, before agent run
- Agent run is fire-and-forget with error logging
- followUp parameter: true=always, false=skip, default=user messages only
Fixes#3216
- Fix JSDoc: "while keeping the latest toolCalls" was wrong for the ?? case;
now says "recovers toolCalls from earlier occurrences if the latest is
undefined" and notes that [] is treated as intentional
- Add @internal annotation to signal export is for testing only
- Remove redundant AssistantMessage casts inside the role-narrowed branch
- Add missing content assertion to "uses latest content" render test
- Add test: [] toolCalls from later chunk is kept (not fallen back from)
- Add test: undefined content on both sides is handled without error
- Add changeset for @copilotkit/react-core patch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Keep both defaultThrottleMs (our branch) and inspectorDefaultAnchor +
design-skill context registration (main) in CopilotKitProvider.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Core setter rejects invalid values (NaN, Infinity, negative) instead of
storing them, preventing garbage from reaching downstream consumers.
- Provider initializes defaultThrottleMs synchronously during instance
creation so child hooks see the correct value on their first render.
- Remove phantom notificationThrottle JSDoc reference (API does not exist).
- Remove dead "default" branch in error source detection.
- Fix misleading @default comments re: 0-vs-undefined semantics and
cascade direction.
- Replace React-specific "re-renders" language in framework-agnostic core.
- Add test for dynamic provider defaultThrottleMs changes.
- Add tests for core setter validation behavior.
- Add defaultThrottleMs to renderWithCopilotKit test helper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses Tyler's review comment on #3657 — defaultThrottleMs is configuration
that belongs on the copilotkit instance, not as a sibling field in the React
context value.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract renderAndWarmCache() and installBoundingRectSpy() helpers to
eliminate duplicated setup across 4 tests. Add justifying comments on
all necessary type casts (MockResizeObserver, CSSStyleDeclaration,
TextMetrics, canvas getContext overloads).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>