- Add `satisfies readonly (keyof AgentSubscriber)[]` to SUBSCRIBE_TO_AGENT_KEYS
so upstream AG-UI renames are caught at compile time
- Fix SubscribeToAgentSubscriber JSDoc: separate AG-UI event handlers (mutation
semantics) from per-item callbacks (void return, excluded for surface area),
note that included lifecycle callbacks also return AgentStateMutation
- Emit invalid throttleMs through emitError so monitoring systems see
misconfiguration, not just console.error
- Add flushPending comment explaining the re-checked `active` flag between
onMessagesChanged and onStateChanged dispatch
- Derive SubscribeToAgentFn from CopilotKitCore['subscribeToAgent'] instead
of manually duplicating the signature (eliminates desync risk)
- Derive StubCore from Pick<CopilotKitCore, ...> in Angular tests
- Add test: async rejection during throttled trailing-edge flush
- Add test: clearing defaultThrottleMs(undefined) makes new subs unthrottled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AgentStore now receives a SubscribeToAgentFn function instead of a
CopilotKitCore instance. The factory binds core.subscribeToAgent once
and passes the bound function, keeping AgentStore decoupled from the
core class while preserving all throttle and error-protection behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace `as any` cast in notifyLifecycle with type-safe branching,
type the re-entrant test callback params via SubscribeToAgentSubscriber,
and replace `Record<string, any>` on Angular stub's core with a
typed StubCore interface.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add ALLOWED_KEYS filter in guardAll to prevent runtime leakage of
extra properties from JS consumers or `as any` casts
- Check `active` flag between flushPending dispatches so unsubscribing
inside onMessagesChanged prevents onStateChanged from firing
- Use real CopilotKitCore instance in Angular test stub instead of
passthrough that bypasses throttle and safeCall logic
- Reword SubscribeToAgentSubscriber and subscribeToAgent JSDoc to
accurately explain why AG-UI event handlers are excluded (mutation
return values silently discarded) rather than implying a clean
return-type split
- Add leading+trailing pattern summary to useAgent throttleMs JSDoc
- Fix setDefaultThrottleMs JSDoc: "logged as errors and ignored"
instead of ambiguous "rejected by the setter"
- Add tests: re-entrant notifications during flush, multiple
simultaneous subscriptions with independent throttle windows,
unsubscribe isolation, unsubscribe-during-flush prevents sibling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review findings from PR #3734:
- Wrap flushPending callback invocations in try-catch so a thrown
exception in onMessagesChanged/onStateChanged does not permanently
deadlock the throttle state machine or skip the sibling flush
- Add 21 dedicated unit tests for CopilotKitCore.subscribeToAgent
covering leading/trailing edge, shared window (bidirectional),
burst coalescing, run lifecycle passthrough, unsubscribe cleanup,
resolution cascade, invalid values, and exception safety
- Use named CopilotKitCoreSubscription return type
- Fix Angular test stub to accept the options parameter and document
that it bypasses throttle logic
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moves the leading+trailing throttle algorithm from the React-specific
useAgent hook into a framework-agnostic subscribeToAgent method on
CopilotKitCore. This consolidates throttle cascade resolution
(throttleMs ?? defaultThrottleMs ?? 0), validation, and the throttle
algorithm into a single location.
Key changes:
- Add subscribeToAgent() to CopilotKitCore with shared throttle gate
for onMessagesChanged and onStateChanged (run lifecycle events are
never throttled)
- Fix setDefaultThrottleMs to log errors and preserve previous value
on invalid input instead of silently erasing
- Simplify useAgent by removing ~60 lines of inline throttle logic
- Angular AgentStore now uses subscribeToAgent, getting throttle
support via provider-level defaultThrottleMs for free
- Remove duplicate validation from CopilotKitProvider useEffect
- Add direct unit tests for CopilotKitCore.setDefaultThrottleMs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
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).
Attachment queue & previews:
- Image lightbox with View Transition API morph animation
- Video lightbox with native controls and play button overlay
- Document lightbox (PDF via blob URL, text inline, info card fallback)
- Drop zone overlay with upload icon
- Filename preservation via InputContent metadata
- Proper video thumbnail sizing and play/pause indicator
- Fix attachment queue positioning (max-w-3xl constraint)
- Padding between X button and content for audio/document cards
- Document filenames wrap instead of truncating
Attachments config:
- onUploadFailed callback for validation/upload errors (file-too-large, invalid-type, upload-failed)
- onUpload accepts sync or async returns
- AttachmentUploadResult discriminated union with explicit interfaces
- Metadata field on Attachment and onUpload return type
AG-UI version bump:
- Bump @ag-ui/client, @ag-ui/core, @ag-ui/encoder, @ag-ui/proto to 0.0.51
- Remove process.env Vite workaround (fixed upstream in 0.0.51)
Deprecation lifecycle:
- @deprecated JSDoc on all legacy image upload APIs
- ImageRenderer, ImageRendererProps, ImageUpload type, imageUploadsEnabled prop,
inputFileAccept prop, ImageRenderer prop, AIMessage.image, ImageData
- Codemod at codemods/migrate-attachments.ts (15 tests)
- Migration guide updated with codemod instructions and new type shapes
Docs:
- New guide: docs/(root)/multimodal-attachments.mdx
- Updated migration guide with onUpload return type, metadata, codemod section
- Cross-links from prebuilt-components and migration guide
- Label change: "Add photos or files" → "Add attachments"
Tests:
- CopilotChat.attachments.test.tsx — 5 tests for onUploadFailed
- migrate-attachments codemod — 15 tests
- Fix fetchRuntimeInfoAutoDetect in agent.ts to use 2xx-only check
(was checking only 404/405, now aligns with agent-registry.ts)
- Remove duplicate JSDoc block on fetchRuntimeInfoAutoDetect
- Add 7 edge case tests: 500/403/405/network-error/both-fail scenarios
- Add 4 tests for useSingleEndpoint->runtimeTransport ternary mapping
- Update Angular test stubs to use "auto" default (was "rest")
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Instead of requiring users to explicitly set transport: "single", the
client now auto-detects the transport mode by trying REST (GET /info)
first and falling back to single-endpoint (POST with { method: "info" })
if the REST probe returns 404/405 or fails. The explicit flag is kept
for backward compatibility.
https://claude.ai/code/session_016xtYN15TY2BaBviryTcVyY
Replace eslint and prettier with oxlint and oxfmt for faster linting
and formatting across the monorepo. Remove all eslint and prettier
configs, dependencies, and related packages. Add .oxlintrc.json and
.oxfmtrc.json for the new tooling. Update CI workflows and lefthook
hooks accordingly. Reformat codebase with oxfmt.
https://claude.ai/code/session_01GMkSf29p78HuMR1mbXn8He
The previous publish workflow released 1.55.0-next.8 to npm but the
post-release commit failed to push to main (blocked by branch
protection). This applies the version bumps and pre.json updates that
the workflow would have committed, unblocking future releases.
https://claude.ai/code/session_01N8sLK9h9p6FdRjyHqzKzVV
After the V1/V2 consolidation merge, several changesets still referenced
old @copilotkitnext/* package names that no longer exist. Fixed package
references and ran changeset version to apply pending version bumps.
https://claude.ai/code/session_01A5aahBWFTmLPR3xZSeh4SD
Flatten all packages from packages/v1/* and packages/v2/* into packages/* —
every package now lives directly under the @copilotkit/ scope with no v1/v2
subdirectories.
- Move all v1 packages (react-core, react-ui, runtime, shared, etc.) from
packages/v1/* to packages/*
- Absorb v2 react code into packages/react-core/src/v2/ (exported via /v2 subpath)
- Absorb v2 agent code into packages/runtime/src/agent/ (exported via /v2 subpath)
- Move v2 packages (core, angular, demo-agents, etc.) to packages/*
- Replace all @copilotkitnext/* imports with @copilotkit/* equivalents
- Keep @copilotkitnext/angular as the sole exception (angular remains on next)
- Update CI workflows, renovate config, release scripts for flat structure
- No public API surface changes — all exports fields are preserved
Co-authored-by: Alem Tuzlak <t.zlak@hotmail.com>
Signed-off-by: Tyler Slaton <tyler@copilotkit.ai>