Commit Graph

1601 Commits

Author SHA1 Message Date
Alem Tuzlak a7c2e32d06 feat(vscode-extension): add FilterBar, EventList, and EventDetail inspector components
Three React components for the AG-UI event inspector webview:
- FilterBar: category toggles, text search, agent/run dropdowns
- EventList: scrollable event stream with sticky auto-scroll and event summaries
- EventDetail: side panel with metadata display and collapsible JSON tree viewer
2026-04-16 12:30:13 +02:00
Alem Tuzlak 3621d26918 fix: handle void return from sendFunction in usePushToTalk (#3783)
## Summary
- `sendMessage` returns `Promise<void>` but `usePushToTalk` accessed
`.id` on the result, causing a `TypeError` crash during push-to-talk
transcription
- Added guard to check if `sendFunction` returns a message before
accessing `.id`
- Updated `SendFunction` type to accept `Promise<Message | void>`

Fixes #3011

## Test plan
- [x] Added unit tests verifying void return handling
- [x] Added unit tests verifying message-with-id return handling
- [x] All react-ui tests pass
2026-04-16 12:27:57 +02:00
Alem Tuzlak 97d413d0af fix: replace hardcoded width 97% with 100% on messages footer (#3786)
## Summary
- `.copilotKitMessagesFooter` used `width: 97%` which caused horizontal
overflow in constrained containers
- Changed to `width: 100%` with `box-sizing: border-box` so padding is
included in the width calculation

Fixes #2325

## Test plan
- [x] All react-ui tests pass
- [ ] Visual verification: render CopilotKit chat in a constrained
container (e.g. 300px sidebar) and confirm no horizontal scrollbar
appears
2026-04-16 12:27:38 +02:00
Alem Tuzlak 51bfcf85b9 feat(vscode-extension): add inspector webview entry point, App shell, and ConnectionBar 2026-04-16 12:27:31 +02:00
Alem Tuzlak 0726b99621 fix: configurable audio mediaType and release mic tracks on stop (#2049, #2050) (#3811)
Fixes #2049
Fixes #2050

Red-green tested locally.
2026-04-16 12:27:04 +02:00
Alem Tuzlak d4aca6664b fix: export CopilotModal and CopilotModalProps from react-ui (#2194) (#3817)
## Summary

Fixes #2194

`CopilotModal` and `CopilotModalProps` were not exported from
`@copilotkit/react-ui`, making them inaccessible to consumers. Adds both
exports to the chat barrel file.

## Test plan

- [ ] Verify `CopilotModal` and `CopilotModalProps` are importable from
`@copilotkit/react-ui`
2026-04-16 12:26:08 +02:00
Alem Tuzlak f896cb0e54 feat(vscode-extension): add InspectorPanel host, register command, update build config 2026-04-16 12:25:08 +02:00
Alem Tuzlak b8ff382fe3 fix: wrap Button with forwardRef for Radix DropdownMenuTrigger (#3830)
## Summary

- `Button` component wrapped with `React.forwardRef` to fix ref warning
from Radix UI's `DropdownMenuTrigger asChild` pattern

Closes #2947

## Test plan

- [x] All affected packages build successfully

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-16 12:23:35 +02:00
Alem Tuzlak e9148b6e92 fix: show loading indicator during tool execution (#3833)
## Summary
- The loading spinner only appeared when the last message had role
"user"
- During tool execution the last message can have role "tool", hiding
the indicator
- Now also show it when the trailing message is a tool result

Closes #3055
2026-04-16 12:22:41 +02:00
Alem Tuzlak 2c56e8a8ec feat(vscode-extension): add SSE debug stream client with auto-reconnect 2026-04-16 12:22:19 +02:00
Alem Tuzlak c3e5582d11 fix: add IME composition guard in CopilotChatInput (#3835)
## Summary
- Skips keydown handling during IME composition (e.g. CJK input) by
checking `isComposing`/`keyCode 229`
- Guards textarea measurement from resetting value mid-composition,
which would break the composition session

Closes #3318
2026-04-16 12:22:12 +02:00
Alem Tuzlak 5add12346b fix: call onChange("") after send in controlled input mode (#3836)
## Summary
- Always calls `onChange("")` after send in controlled mode so the
parent component is notified to clear its state
- Previously `onChange` was only called inside the `!isControlled`
branch, leaving controlled parents unaware the input was submitted

Closes #3593
2026-04-16 12:20:51 +02:00
Alem Tuzlak 0ac05e1373 feat(vscode-extension): add inspector message types and event color mapping 2026-04-16 12:20:48 +02:00
Alem Tuzlak a7e7fbeef6 fix: pass urlTransform prop through to ReactMarkdown (#3845)
Closes #1921

The Markdown component accepted `components` but not `urlTransform`,
preventing users from customizing URL sanitization. Added `urlTransform`
as an optional prop with passthrough to `MemoizedReactMarkdown`.

Split from #3838.
2026-04-16 12:20:18 +02:00
Alem Tuzlak 0bc0405043 fix: exclude tools with available:"disabled" from buildFrontendTools (#3020) (#3793)
## Summary
- `buildFrontendTools` only checked `tool.available !== false` but the
`available` field can also be the string `"disabled"`, which is truthy
- Added `tool.available !== "disabled"` to the filter so disabled tools
are properly excluded
- Added test verifying tools with `available: "disabled"` are filtered
out

## Test plan
- [x] New test: tool with `available: "disabled"` is excluded from
`buildFrontendTools`
- [x] All existing available-filtering tests still pass
- [x] Full core test suite passes (338 tests)
2026-04-16 12:19:44 +02:00
Alem Tuzlak 38c6642a97 feat(runtime): add GET /debug-events SSE endpoint for live event inspection 2026-04-16 12:18:34 +02:00
Alem Tuzlak dc96155d77 feat(runtime): broadcast AG-UI events to DebugEventBus from SSE handlers 2026-04-16 12:15:16 +02:00
Alem Tuzlak 70cb4d002a feat(runtime): wire DebugEventBus into BaseCopilotRuntime 2026-04-16 12:12:14 +02:00
Alem Tuzlak ada147ef84 feat(runtime): add DebugEventBus and DebugEventEnvelope type 2026-04-16 12:09:25 +02:00
Alem Tuzlak f624ee1fb7 fix: pass AssistantMessage to onThumbsUp/Down callbacks (#3457) (#3796)
## Summary
- onThumbsUp/onThumbsDown/onReadAloud/onRegenerate callbacks on
CopilotChatAssistantMessage were receiving the browser SyntheticEvent
instead of the AssistantMessage object
- Wrapped the onClick handlers to pass the message explicitly:
`onClick={() => onThumbsUp(message)}`
- Same fix applied to onReadAloud and onRegenerate for consistency

## Test plan
- [x] Red-green verified: test confirms callback arg has `id`, `role`,
`content` and NOT `nativeEvent`/`target`
- [x] Full react-core test suite passes (1071 tests)
- [x] Build passes

Closes #3457
2026-04-16 12:07:26 +02:00
Alem Tuzlak c38d0db229 fix: return null instead of throwing in useRenderCustomMessages (#3497) (#3797)
## Summary
- useRenderCustomMessages threw "Agent not found" when the agent was
undefined during the connecting state
- Changed the throw to return null, allowing the component to render
gracefully while the agent is being resolved

## Test plan
- [x] Red-green verified: test calls hook with nonexistent agent,
asserts returns null not throws
- [x] Full react-core test suite passes (1071 tests)
- [x] Build passes

Closes #3497
2026-04-16 12:03:39 +02:00
Alem Tuzlak 3bda9d28bc fix: guard CopilotListeners against empty agents map (#3249) (#3798)
## Summary
- CopilotListeners called useAgent() unconditionally, which throws when
no agents are registered and no runtimeUrl is configured
- Split into CopilotListeners (outer, handles error subscription) and
CopilotListenersAgentSubscription (inner, uses useAgent)
- Inner component only renders when agents exist or a runtime is
configured

## Test plan
- [x] Red-green verified: render CopilotListeners with no agents, assert
no throw
- [x] Full react-core test suite passes (1071 tests)
- [x] Build passes

Closes #3249
2026-04-16 12:02:54 +02:00
Alem Tuzlak 057f159db0 fix: skip version check when showDevConsole is false (#3827)
## Summary

- `checkForUpdates()` in dev console is now gated on `showDevConsole`,
preventing unnecessary network requests when the console is disabled

Closes #2751

## Test plan

- [x] `@copilotkit/react-core` tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-16 12:00:23 +02:00
Alem Tuzlak c38f8d3477 fix: always generate unique message IDs in LangChain adapter (#3829)
## Summary

- LangChain adapter now always uses `randomId()` for message stream IDs
instead of relying on `lc_kwargs.id` (which GoogleGenerativeAI sets to
`"0"` for all messages)

Closes #2929

## Test plan

- [x] `@copilotkit/runtime` tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-16 11:59:22 +02:00
Alem Tuzlak bddf0a0189 fix: add Zod v4 compatibility for schema-to-JSON conversion (#3837)
## Summary
- Detects Zod v4 schemas by checking for `toJSONSchema()` method on the
schema object
- Calls `schema.toJSONSchema()` directly for Zod v4 (avoids
`zod-to-json-schema` v3, which can't handle Zod v4 internals)
- Preserves existing Zod v3 path via injected `zodToJsonSchema` fallback
- Removes dead `vendor === "zod4"` check (Zod v4 reports vendor as
`"zod"`, not `"zod4"`)
- Removes `_def` duck-typing fallback (unnecessary with `toJSONSchema`
detection)

### Priority order:
1. Standard JSON Schema V1 (`~standard.jsonSchema.input`)
2. Zod v4 native (`schema.toJSONSchema()`)
3. Zod v3 fallback (injected `zodToJsonSchema`)

### Tests added:
- Verifies `toJSONSchema()` is called when present
- Verifies it works without `zodToJsonSchema` option
- Verifies it takes priority over `zodToJsonSchema` fallback
- Verifies `~standard.jsonSchema` still takes top priority over
`toJSONSchema()`

Closes #3636
2026-04-16 11:58:56 +02:00
Alem Tuzlak 1ec1b864a6 fix: increase Anthropic adapter default max_tokens to 4096 (#3785)
## Summary
- Default `max_tokens` was hardcoded to 1024, causing truncated
responses for most use cases
- Increased default from 1024 to 4096 while still respecting
user-provided `maxTokens`

Fixes #2354

## Test plan
- [x] Added test verifying default max_tokens is 4096 when not specified
- [x] Added test verifying user-provided maxTokens is passed through
- [x] All existing anthropic adapter tests pass
2026-04-16 11:58:34 +02:00
Alem Tuzlak fbf67ce128 fix: replace non-unique provider IDs like txt-0 with UUIDs (#3410, #3623) (#3800)
## Summary

- Providers like `@ai-sdk/openai-compatible` emit sequential IDs
(`txt-0`, `reasoning-0`, `msg-0`) that are treated as unique but collide
across requests
- The existing check only caught the literal `"0"` — expanded to match
the `^(txt|reasoning|msg)-0$` pattern
- Both `text-start` and `reasoning-start` event handlers now use
`randomUUID()` for these non-unique IDs

## Test plan

- [x] Added `provider-id-collision.test.ts` with 4 tests covering txt-0,
reasoning-0, msg-0, and legitimate ID preservation
- [x] All 1226 runtime tests pass (including existing
config-tools-execution tests)

Fixes #3410, #3623
2026-04-16 11:58:13 +02:00
Alem Tuzlak 078b840d3d fix: pass hookParams to onAfterRequest instead of empty object (#2124) (#3801)
## Summary

- `onAfterRequest` middleware callback was called with `{}` instead of
actual hook parameters
- Now forwards `threadId`, `runId`, `inputMessages`, `outputMessages`,
and `url` from the v2 runtime's `hookParams`
- The `onBeforeRequest` handler at line 566 already did this correctly;
this fix makes `onAfterRequest` consistent

## Test plan

- [x] Added `on-after-request.test.ts` verifying the callback receives
threadId and runId (not empty object)
- [x] All 1226 runtime tests pass

Fixes #2124
2026-04-16 11:55:42 +02:00
Alem Tuzlak 8b1bc3aa49 fix: ensure tool_result messages have matching tool_use after token trimming (#2450) (#3820)
## Summary

Fixes #2450

Token trimming in the Anthropic adapter could remove assistant messages
containing `tool_use` blocks while keeping the corresponding user
messages with `tool_result` blocks. Anthropic's API rejects orphaned
`tool_result` messages. This adds a post-processing step that removes
orphaned `tool_result` blocks after trimming.

## Test plan

- [ ] Verify token trimming preserves tool_use/tool_result pairing
- [ ] Verify orphaned tool_result blocks are removed
- [ ] Verify messages with mixed content (tool_result + text) retain
non-orphaned content
2026-04-16 11:54:58 +02:00
Alem Tuzlak 2b8a426f1b fix: add configurable maxInputTokens to OpenAI and Anthropic adapters (#2405) (#3823)
## Summary

Fixes #2405

Both OpenAI and Anthropic adapters used a hardcoded token limit for
message trimming. This adds an optional `maxInputTokens` constructor
parameter to both adapter classes, allowing consumers to override the
default context window limit.

## Test plan

- [ ] Verify default behavior unchanged when `maxInputTokens` not
provided
- [ ] Verify custom `maxInputTokens` is passed through to
`limitMessagesToTokenCount`
2026-04-16 11:52:28 +02:00
Alem Tuzlak 98d0683fa3 fix: skip unknown tool_use blocks in Anthropic adapter (#2504) (#3824)
## Summary

Fixes #2504

When Anthropic returns a `tool_use` block for a tool not registered in
the current action set, the adapter would crash trying to process it.
This adds a check against known action names and skips unknown tool_use
blocks gracefully.

## Test plan

- [ ] Verify known tools are still processed normally
- [ ] Verify unknown tool_use blocks are skipped without crashing
2026-04-16 11:51:31 +02:00
Alem Tuzlak 3378773606 fix: normalize array content in TOOL_CALL_RESULT for MCP adapters (#3832)
## Summary
- langchain-mcp-adapters sends tool call result content as an array of
`{type:"text", text:string}` objects
- Extracts and joins text parts so downstream consumers always receive a
plain string

Closes #2922
2026-04-16 11:46:12 +02:00
Alem Tuzlak cb4189acdf fix: forward credentials on all agent registration paths (#3839)
Closes #3141

`applyCredentialsToAgents`/`applyCredentialsToAgent` were defined but
never called from `initialize()`, `setAgents__unsafe_dev_only()`, or
`addAgent__unsafe_dev_only()`. Only remote agents received credentials
via constructor. Local agents now receive credentials alongside headers.

Split from #3838.
2026-04-16 11:45:32 +02:00
Alem Tuzlak 9641933e13 fix: pass toolCallId to useRenderTool render components (#3843)
Closes #3741

Add `toolCallId` prop to all three status branches (InProgress,
Executing, Complete) of the ToolCallRenderer, and update the
`ReactToolCallRenderer` type to include it in the discriminated union.

Split from #3838.
2026-04-16 11:42:45 +02:00
Alem Tuzlak 12dda2dc51 fix: preserve jsonSchema structure in MCP tool parameter extraction (#3846)
Closes #1936

`extractParametersFromSchema` now preserves enum values as structured
data on string parameters, recursively extracts nested object
attributes, and converts object arrays to `object[]` type with
attributes. This ensures complex MCP tool schemas survive the
`Parameter[]` -> Zod conversion without losing nested structure.

Split from #3838.
2026-04-16 11:42:24 +02:00
Alem Tuzlak 26ac5460aa feat(vscode-extension): extract real component schema from catalog via extractCatalogComponentSchemas for authoritative prop validation 2026-04-16 10:43:29 +02:00
Alem Tuzlak 42d8eb84ac feat(vscode-extension): fixture re-render on change, deep prop validation with typo detection from dynamic schema registry 2026-04-16 10:27:06 +02:00
Alem Tuzlak 83a89bdfab fix(vscode-extension): detect catalog by shape instead of hardcoded export name 2026-04-16 10:09:22 +02:00
Maxim b8d6e14138 fix(tests): improve test hygiene — remove type casts, reduce duplication
Core test (core-subscribe-to-agent.test.ts):
- Replace `as any` on RunErrorEvent with proper EventType.RUN_ERROR type
- Consolidate 4 identical lifecycle tests into one `it.each` block
- Extract silenceConsoleError() helper used across 10 error-path tests
- Document the remaining intentional `as any` in guardAll JS-consumer test

Angular test (agent.spec.ts):
- Make MockAgent extend AbstractAgent, removing all 4 `as unknown as AbstractAgent` double casts
- Replace all `any` types with proper AG-UI types (Message, State, AgentSubscriber, etc.)
- Emit helpers now pass correct AgentSubscriberParams instead of empty objects
- Use userMsg() factory for properly typed test data
- Simplify ProxiedCopilotRuntimeAgent assertion with single narrowing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 01:02:36 +02:00
Maxim bb6f02c62a fix(core,react-core): handle onRunErrorEvent in useAgent and document in subscribeToAgentWithOptions
React's useAgent was missing onRunErrorEvent under OnRunStatusChanged,
causing isRunning to stay true after protocol-level RUN_ERROR events
(infinite spinner). Angular already handled this via PR #3749.

Also updates SubscribeToAgentSubscriber JSDoc to accurately document
onRunErrorEvent as the sixth allowed callback with rationale for its
inclusion despite having stopPropagation in its return type, and adds
a core-level test for onRunErrorEvent firing immediately during
throttle windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:08:25 +02:00
Maxim 96f230c7cc fix: resolve rebase conflicts — active flag, onRunErrorEvent, async tests
- Restore `let active` guard in useAgent subscription effect (removed
  during refactor, causing ReferenceError in batchedForceUpdate)
- Add onRunErrorEvent to SubscribeToAgentSubscriber allowed keys
  (added on main for Angular AgentStore)
- Fix throttle tests to use async act() for onStateChanged assertions
  (batchedForceUpdate uses queueMicrotask, needs await to flush)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 23:15:45 +02:00
Maxim b8f4a8faa0 refactor: replace custom throttle with @tanstack/pacer Throttler
Replace the hand-rolled leading+trailing throttle (scheduleOrFlush,
setTimeout, throttleActive state machine) with TanStack Pacer's
Throttler class. Clean up comments to describe the method generically
rather than only in terms of throttling.

No public API changes — throttleMs / defaultThrottleMs stay as-is.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:14:50 +02:00
Maxim 47b46e456e fix: make guardAll type-safe, remove any casts
Address review feedback: replace Object.entries loop in guardAll
with explicit per-key wrapping so TypeScript can verify all
callback signatures without any casts. Also replace Promise
duck-typing in safeCall with instanceof Promise, and use
Record<string, unknown> instead of any in the unsupported keys check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:09:17 +02:00
Maxim 18a9ad6e58 fix: rename subscribeToAgent to subscribeToAgentWithOptions on CopilotKitCore
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:09:16 +02:00
Maxim 0ae5e4606c fix: warn about unsupported callback keys in both throttled and unthrottled paths
Move the unsupported-key scan from guardAll into a pre-scan that runs
before the throttled/unthrottled branch, so JS consumers passing
unsupported callbacks (e.g. onEvent via `as any`) get a console.warn
regardless of whether throttling is active. Previously, guardAll only
ran on lifecycleOnly in the throttled path, silently dropping
unsupported keys without any diagnostic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:09:15 +02:00
Maxim d8b60f5a1c fix: address PR review — error monitoring, Angular Error state, type safety
- Add Error state handling in Angular CopilotkitAgentFactory (parity with React)
- Add emitError to guardAll for dropped callbacks (structured monitoring)
- Add emitError to setDefaultThrottleMs for monitoring parity
- Replace empty .catch(() => {}) with logging pattern on emitError
- Add generic typing to safeCall for call-site parameter safety
- Clarify flushPending comment re: sync-only unsubscribe guard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:09:15 +02:00
Maxim 1f74c59eca fix: address review findings — type safety, JSDoc accuracy, and test coverage
- 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>
2026-04-15 22:09:14 +02:00
Maxim 7b94afd862 fix: address code review findings for subscribeToAgent
- Add .catch() to emitError() in reportError to prevent unhandled
  promise rejections if the error reporting infrastructure itself fails
- Add console.warn in guardAll when unsupported callback keys are
  dropped, so JS consumers discover they need agent.subscribe() directly
- Hoist ALLOWED_KEYS Set to module scope to avoid per-call allocation
- Fix SubscribeToAgentSubscriber JSDoc: explicitly list the 5 supported
  callbacks and mention onNewMessage/onNewToolCall as excluded
- DRY subscribeToAgent() method JSDoc by referencing the type instead
  of duplicating the AG-UI exclusion rationale
- Fix safeCall comment: async error path returns Promise<undefined>,
  not undefined
- Add JSDoc to setDefaultThrottleMs setter; simplify getter JSDoc
- Fix use-agent.tsx: consistent camelCase callback names, fix @default
  tag format, replace unresolvable {@link} with plain text reference
- Add test: emitError/onError integration for SUBSCRIBER_CALLBACK_FAILED
- Add test: unsubscribe + throw combination in onMessagesChanged
- Add test: unsupported callback keys dropped with console.warn

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:09:14 +02:00
Maxim a35dc88f96 fix: decouple AgentStore from CopilotKitCore concrete class
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>
2026-04-15 22:09:13 +02:00
Maxim b9f5679937 fix: add emitError integration, safeCall docs, and single-source ALLOWED_KEYS
- Add SUBSCRIBER_CALLBACK_FAILED error code and call emitError() in
  safeCall so subscriber failures are visible to monitoring systems
  and onError handlers, not just console.error
- Document that safeCall intentionally discards return values on the
  error path (including lifecycle AgentStateMutation)
- Extract SUBSCRIBE_TO_AGENT_KEYS tuple as single source of truth for
  both the SubscribeToAgentSubscriber type and the runtime ALLOWED_KEYS
  set, eliminating the one-directional sync risk from the satisfies pattern

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:09:13 +02:00