<!--
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?
This PR adds an initial scaffolding of the CopilotKit Intelligence agent
runner and React agent classes.
Both will be part of the new threads-enabled feature set, and will be
iterated upon in subsequent PRs.
For this PR, the React agent is not tied into `useAgent`, so it cannot
currently be interacted with.
Also, in this PR, docs that describe the agent and runner architecture
are not updated, as it is assumed that these classes may change
substantially and rapidly in the very near term.
A big part of this PR is the integration of the Phoenix JS client SDK to
enable the IntelligenceAgent and IntelligenceAgentRunner to connect to
the Intelligence platform's Phoenix server. That allows threaded AG-UI
messages to be streamed from to and from the platform, instead of
directly from agent runner to client agent hook.
The message structure for the Phoenix connection is still in flux.
Note: while the SQLite-backed agent runner is in a separate package, the
IntelligenceAgentRunner was intentionally placed along side the
`ProxiedCopilotRuntimeAgent` to make it that much easier to switch from
the latter to the former if desired.
## Related PRs and Issues
- https://linear.app/copilotkit/issue/ENT-59
- https://linear.app/copilotkit/issue/ENT-54
## Checklist
- [x] 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
## Summary
- During streaming, `AbstractAgent.addMessage()` can push messages with
the same `id` into the messages array, causing React duplicate key
warnings in `CopilotChatMessageView`
- Added Map-based deduplication in the message rendering pipeline —
last-write-wins for duplicate IDs
- Includes dev-mode `console.warn` when duplicates are detected, to
surface the upstream cause without breaking the UI
Fixes#3258
## Test plan
- [x] Unit tests added verifying deduplication behavior
- [x] Warning logged in development when duplicates detected
- [x] Full package test suite passes
- [x] Build passes
🤖 Generated with [Claude Code](https://claude.ai/code)
Reverts the resolveAgent extraction from the previous commit — the
original useMemo + ref cache already provides referential stability.
All 4 stability tests pass without the refactor.
runtime-client-gql's graphql-codegen needs the schema file generated
by @copilotkit/runtime's build. After removing the package.json
dependency (to fix bundle size), Nx no longer orders the builds
correctly. implicitDependencies restores build ordering without
reintroducing the runtime dependency.
The @copilotkit/runtime-client-gql package listed @copilotkit/runtime as
a dependency, but none of its source files actually import from it. This
caused the entire server-side runtime (graphql-yoga, hono, openai, shiki,
reflect-metadata, etc.) to be pulled into client bundles, exploding
bundle size from ~600kb to 4.3mb+.
Remove the unused dependency from package.json, the UMD externals list,
and the UMD globals map in tsdown.config.ts.
Move V1 test file to __tests__/ directory and add test verifying that
string enum constraints round-trip through convertJsonSchemaToZodSchema.
Add equivalent test for V2's copy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The string case in convertJsonSchemaToZodSchema produced z.string() and
silently discarded the enum field. When useCopilotAction defines a
parameter with enum: ["todo", "done"], the constraint was lost during
the V1→V2 bridge and never reached the runtime payload.
Add an enum check before falling through to z.string() in both V1
(shared/json-schema.ts) and V2 (agent/index.ts) copies of the function.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The afterRequestMiddleware receives a cloned Response (via c.res.clone()),
whose internal stream controller functions have different names across
Node versions. Using expect.any(Response) avoids brittle deep equality
on Response internals.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>