Addresses review feedback on #4215 / OSS-192.
- Thread an explicit `data-testid` prop through `AutoResizingTextarea` so it
reaches the rendered <textarea>. The component destructures a fixed prop set
with no `{...rest}` spread, so the id passed from Input.tsx was silently
dropped and never landed in the DOM.
- Align selector names with the V2 components in @copilotkit/react-core:
`copilot-chat-textarea` on the textarea and `copilot-send-button` on the send
control. The legacy `data-test-id` values are preserved for back-compat.
- Add a source-level test asserting the Input wiring and that Textarea forwards
the prop (the dropped-prop guard); the package's vitest runs in a node env
with no DOM harness, matching the existing testids.test.ts convention.
Stable selectors let tests locate the controls; the headless input-driving
issue in #4215 remains a separate follow-up and should stay open.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ports the usePinToSend half of #5386 to the Vue package, which is a
documented 1:1 parity port and retained the shrink-only ResizeObserver.
When content below the anchored user message loses height (suggestions
swap, input resize), the spacer now grows back so total scrollable space
below the bubble stays constant and the message stays pinned (#5355).
Vue has no scroll-to-bottom button, so the listener half of #5386 does
not apply.
## What does this PR do?
Fixes `pin-to-send` scrolling in the v2 chat view.
- Re-attaches the non-autoscroll scroll listener after the real scroll
element mounts by depending on `nonAutoScrollEl`, not the stable
`scrollRef` object.
- Lets the `usePinToSend` spacer adjust in both directions as content
below the pinned user message changes, so the user message stays
anchored after streaming finishes and layout height changes.
- Adds regression coverage for the scroll-to-bottom button and spacer
adjustment behavior.
## Related PRs and Issues
Fixes#5355
## Tests
- `corepack pnpm -C packages/react-core exec vitest run
src/v2/hooks/__tests__/use-pin-to-send.test.tsx
src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.tsx`
- `corepack pnpm exec oxfmt --check
packages/react-core/src/v2/components/chat/CopilotChatView.tsx
packages/react-core/src/v2/hooks/use-pin-to-send.ts
packages/react-core/src/v2/hooks/__tests__/use-pin-to-send.test.tsx
packages/react-core/src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.tsx`
- `git diff --check`
Attempted:
- `corepack pnpm -C packages/react-core run check-types`
- This failed in the local workspace on existing/type-resolution issues
outside this diff, including `react-markdown` JSX namespace errors,
missing `@copilotkit/runtime-client-gql` declarations, and existing e2e
mock `AbstractAgent` private member mismatches.
## Checklist
- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation (N/A: bug fix only, no API/docs change)
- [x] "Allow edits by maintainers" is checked (lets us help iterate on
your PR directly — faster turnaround for everyone)
Fixes#5416
## Problem
`AgentStore` mirrored the agent's messages into a signal via
`this.#messages.set(abstractAgent.messages)`. `AbstractAgent.addMessage`
pushes **in place** and notifies with the **same array reference**.
Angular signals compare with `Object.is`, so `set(sameRef)` is a no-op:
the signal never notifies, the OnPush `<copilot-chat>` view is never
marked dirty, and a freshly added message — including the user's own
bubble on submit — does not render until the run pipeline reassigns
`messages` to a new array at run completion.
## Fix
```ts
this.#messages.set([...abstractAgent.messages]);
```
A shallow copy gives the array a new identity, so the signal notifies
and OnPush views re-render immediately. The `Message` objects stay
referentially stable, so `trackBy` still avoids re-creating existing
bubbles.
`onStateChanged` is intentionally left unchanged: `AbstractAgent`
reassigns `this.state` to a freshly cloned reference on every change
(`setState(e) { this.state = clone(e) }`) and never mutates state in
place, so that signal already notifies correctly. Scoping the fix to
messages keeps it minimal.
## Tests
Added two regression tests in `agent.spec.ts`, both exercising the
in-place mutation path that the existing tests never hit (they assign a
fresh array each emit):
1. **Reference guard** — the store must not hand back the agent's live
`messages` array.
2. **OnPush re-render** — a count rendered in an OnPush *descendant* (a
root `detectChanges()` would force-check the root and hide the bug; only
a child whose dirty flag depends on the signal exposes it). Two in-place
pushes; the second is the same-reference no-op the fix repairs.
Both tests fail without the fix (`'1' to be '2' // Object.is equality`)
and pass with it.
## Verification
- `agent.spec.ts`: 6/6 pass
- full `@copilotkitnext/angular` suite: 50/50 pass
- `tsc --noEmit`: clean
## Summary
- export the telemetry lambda client as a named binding instead of
default-reexporting it through the shared barrel
- update shared telemetry internals/tests to consume the named binding
- add a built-package smoke check to ensure both CommonJS and ESM expose
`lambdaClient.send`
## Root Cause
`@copilotkit/shared` re-exported `lambdaClient` from a default export.
The unbundled CommonJS build emitted `exports.lambdaClient =
require_lambda_client`, so CommonJS consumers received the module
namespace object instead of the `{ send }` client. `@copilotkit/runtime`
then called `lambdaClient.send(...)` and crashed because `send` was
nested under `lambdaClient.default`.
## Validation
- `pnpm nx run @copilotkit/shared:build --skip-nx-cache`
- `node packages/shared/scripts/verify-cjs-exports.cjs`
- `pnpm nx run @copilotkit/shared:test --skip-nx-cache`
- `pnpm nx run @copilotkit/shared:check-types --skip-nx-cache`
- `pnpm nx run @copilotkit/shared:publint --skip-nx-cache`
- `pnpm nx run @copilotkit/runtime:build --skip-nx-cache`
- runtime CJS telemetry capture smoke test
- `pnpm nx run @copilotkit/runtime:test --skip-nx-cache --
src/v2/runtime/__tests__/telemetry.test.ts`
- pre-commit hook: `pnpm run test && pnpm run check:packages`
AgentStore mirrored the agent's messages into a signal via
`this.#messages.set(abstractAgent.messages)`. AbstractAgent.addMessage
pushes in place and notifies with the same array reference, so the
signal's Object.is equality check treats set(sameRef) as a no-op: it
never notifies, the OnPush <copilot-chat> view is never marked dirty,
and a freshly added message (including the user's own on submit) does
not render until the run pipeline reassigns messages to a new array at
run completion.
Copy into a fresh array so the reference changes and the signal
notifies. Message objects stay referentially stable, so trackBy still
avoids re-creating existing bubbles. State is unaffected: AbstractAgent
reassigns this.state to a cloned reference on every change, so its
signal already notifies.
Adds regression tests covering the in-place mutation path: a reference
guard and an OnPush descendant re-render check. Both fail without the
fix.
Fixes#5416
Bring the agent skills in line with the shipped v2 API so their examples
install, compile, and connect. Extends #5345 (which migrated the
copilotkit-setup SKILL.md body) to the rest of the skills.
- Imports: drop the nonexistent @copilotkit/react and @copilotkit/agent
packages and the bare @copilotkit/runtime/express subpath; use
@copilotkit/react-core/v2 and @copilotkit/runtime/v2 (+ /v2/express),
and createCopilotHonoHandler / createCopilotExpressHandler rather than
the deprecated createCopilotEndpoint aliases.
- Provider: CopilotKit from @copilotkit/react-core/v2 with
useSingleEndpoint={false} on multi-route setups (the v1-compat bridge
defaults to single transport and would 404 a multi-route backend).
- Routes: v2 catch-all Hono handler exporting GET/POST/PATCH/DELETE via
handle() from hono/vercel, replacing the v1
copilotRuntimeNextJSAppRouterEndpoint + ExperimentalEmptyAdapter.
- Integrations: per-framework agent classes matched to the shipped
examples (LangGraphAgent/LangGraphHttpAgent from @copilotkit/runtime/
langgraph, CrewAIAgent, MastraAgent, LlamaIndexAgent, HttpAgent from
@ag-ui/client; Agno via HttpAgent, not @ag-ui/agno).
- Hooks/props: correct useAgent, useThreads, useRenderTool, identifyUser,
and the chat-component props (defaultOpen, onSubmitMessage, the headless
CopilotChatView render prop).
Validated across review rounds and a build test against the published
@copilotkit/*@1.60.0 packages (tsc passes, every /v2 subpath resolves).
Regenerated the skills/runtime and skills/react-core mirrors.
Follow-up correction. The client publicLicenseKey/publicApiKey prop is the
header→cloud path and is NOT what activates the Intelligence runtime (that's
the server-side COPILOTKIT_LICENSE_TOKEN). So:
- Remove the `npx copilotkit@latest license` guidance from all client-prop
contexts — that CLI yields the server-side license token, not the client
prop value.
- Revert the client-prop docstrings (copilotkit-props, v2 CopilotKitProvider)
to bare one-liners; drop the premium/"requires a license key" framing from
the headless hook, react-ui observability docs, and runtime logging/onError
JSDoc rather than reframing.
- Angular: remove all `licenseKey` mentions from the README — it is no longer
a premium feature (the license watermark is disabled) and the key is not
needed to function.
Server-side license-token documentation remains deferred to the example/runtime
setup pass (Bucket B).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cloud is no longer promoted; the Intelligence license key is its replacement.
Scrub the old Copilot Cloud system from SDK JSDoc / doc-comments / console
messages / README prose so code references reflect how the license key is
obtained and used, mirroring examples/integrations/*:
- publicApiKey/publicLicenseKey docstrings (react-core props + v2 provider,
vue legacy types, copilot-context) describe the CopilotKit public license
key, acquired via `npx copilotkit@latest license` or the dashboard;
publicApiKey framed as the legacy alias of publicLicenseKey.
- Premium-feature docs (headless hook, react-ui Chat/Popup/Sidebar
observability, runtime logging/onError) drop "Copilot Cloud"/"requires a
publicApiKey" wording and the publicApiKey examples in favor of the public
license key + publicLicenseKey.
- console-styling messages and the angular README point at the license key
and the `npx copilotkit@latest license` command.
Defunct features (guardrails_c, authConfig_c, useCopilotAuthenticatedAction_c)
keep their code but lose their JSDoc (marked @internal defunct).
Functional surfaces untouched: api.cloud.copilotkit.ai endpoint, the
X-CopilotCloud-Public-Api-Key header, prop names, gating logic, tests,
CHANGELOGs. Example-app migration (Bucket B) deferred.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Route both the run path (agent-utils) and the /info response
(get-runtime-info) through a single isA2UIEnabled() predicate so the two
can no longer disagree on whether a2ui is on (the divergence behind #5369),
and add an optional `enabled` flag to the runtime a2ui config.
Backwards compatible: any existing a2ui config stays enabled; only an
explicit `a2ui: { enabled: false }` turns it off while keeping the rest
of the config (e.g. schema/catalog) in place.
https://claude.ai/code/session_01TYohiEJyhsU3mJS4jabdv6
Bolt's App constructor schedules a background auth.test that can't be
awaited or error-handled - in unit tests it phoned home to api.slack.com
with dummy tokens, leaving ~15 unhandled invalid_auth rejections racing
the run's end (the unit (20.x) flake). deferInitialization: true makes
construction genuinely side-effect-free; start() runs app.init() first,
so auth/config errors surface to the caller, followed by the existing
awaited auth.test. Test fake App grows the matching init() stub.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LicenseMode was removed from license-verifier 0.3.0 and has no consumers
anywhere in the repo; the prior re-export was already uncompilable, so no
external consumer could exist either.
The paths entries pointed at sibling package sources, so the Angular
package's tsc run typechecked core and shared sources under Angular's
compiler settings — surfacing errors in files outside any Angular
change (reported on #5321). Resolve to the built declarations first,
same pattern as the Vue package; the src fallback remains for cold
checkouts.
@copilotkit/license-verifier dropped LicenseContextValue and
LicenseMode from its public API in 0.3.0, leaving shared re-exporting
two nonexistent members. tsdown's dts rollup never validated the
re-export, so the broken types shipped silently and check-types fails
on main. Define both types here — shared already owns the context
shape via createLicenseContextValue — using the definitions from
license-verifier 0.2.0. Also annotate the merged telemetry properties
record so string indexing typechecks.
A2UIViewer.tsx and theme/viewer-theme.ts were left behind by the
0.8 -> 0.9 migration: nothing imports them, they import @a2ui/lit
(no longer a dependency) and files that no longer exist, so
check-types fails on files no PR touches. Remove them along with the
now-inert @a2ui/lit external/global entries in tsdown.config.ts, and
underscore the unused type params kept on deprecated aliases for
call-site compatibility.
The reusable mechanics (streaming, chunking, markdown-to-mrkdwn,
conversation store) live on in @copilotkit/bot-slack; UI authoring
moved from A2UI/defineSlackComponent to JSX -> IR -> Block Kit.
JSX -> Block Kit rendering with per-element budgets and degradation,
Socket Mode ingress, opaque-id interactions (ack within 3s, run async),
chat.update message streaming with chunking, accent attachments, and
sender-profile resolution. Preserves the PoC's streaming, chunking,
and mrkdwn mechanics behind the PlatformAdapter boundary.
createBot with handler registration (onMention/onMessage/onInterrupt/
onCommand), the agent run/tool/interrupt loop, content-stable JSX
action binding with cold-path rehydration from a pluggable ActionStore,
the PlatformAdapter boundary, capability-gated thread methods, one
shared BotToolContext, defineBotTool / defineBotCommand, and typed
interaction/interrupt handlers. Includes fake-adapter/fake-agent
testing utilities.
Pure JSX runtime (no React, no Slack) producing a BotNode IR tree.
Statically typed component props via a package-owned JSX namespace:
unknown attributes, bad values, and bad children are compile errors.
Components: Message, Header, Section, Markdown, Field, Context,
Actions, Button, Select, Input, Image, Divider; bind() escape hatch
for non-serializable handler captures.
Node 25 unflagged the experimental Web Storage API; vitest's jsdom env
does not replace the method-less stub, so localStorage-touching tests
crash. Install a functional stub before the environment boots.
A single unavailable MCP server (down, 5xx, timeout, bad auth) no longer
fails the whole run - it is skipped with an error log and the run
continues with healthy servers and the agent's own tools.