Commit Graph

318 Commits

Author SHA1 Message Date
Alem Tuzlak 7fc82c6061 fix(runtime): send SSE comment on connect to flush response headers immediately 2026-04-16 14:23:54 +02:00
Alem Tuzlak 0813cc390a test(runtime): add debug-events integration tests across all adapters
Tests the /debug-events SSE endpoint across Express, Hono, Node, and
Fetch Direct adapters. Verifies SSE response format, event flow through
the DebugEventBus, envelope structure (timestamp, agentId, threadId,
runId, event), full event sequence, HTTP method validation (405 for
POST), and NODE_ENV=production guard (404).

Key implementation detail: reader.cancel() must NOT be awaited on
tee'd ReadableStreams (created by response.clone() in the fetch
handler) because Node.js blocks until the other tee branch is also
consumed/cancelled.
2026-04-16 13:57:53 +02:00
Alem Tuzlak 7bde34a856 test(runtime): add handleDebugEvents endpoint tests 2026-04-16 13:03:32 +02:00
Alem Tuzlak 1848a161ee test(runtime): add DebugEventBus and debug-events route tests 2026-04-16 13:00:09 +02:00
Alem Tuzlak 417b58569c refactor(vscode-extension): consolidate types, fix any casts, extract getNonce, add useMemo 2026-04-16 12:41:34 +02:00
Alem Tuzlak 84d5c1676f fix: duck-type Request check for Hono polyfill compat (#3790)
## Summary
- Fixes #2986
- `reqOrRequest instanceof Request` fails when `@hono/node-server`
polyfills the Request class with a different prototype
- Replaced with a duck-type check (`isRequestLike`) that verifies `url`,
`method`, and `headers` properties exist
- The `!res` guard ensures IncomingMessage objects (which always come
with a ServerResponse) are still routed correctly

## Test plan
- [x] Added `request-duck-type.test.ts` covering native Request,
polyfilled Request, null/undefined, and missing properties
- [x] All 1225 existing runtime tests pass
- [x] Build passes
2026-04-16 12:32:38 +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 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 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 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
ranst91 cfb5921108 chore: release monorepo v1.56.0 2026-04-15 17:22:27 +00:00
Ran Shem Tov 6986a1c120 fix: use latest agui langgraph packages 2026-04-15 18:11:17 +02:00
Alem Tuzlak 9953b8a264 Merge branch 'main' into worktree-lucky-popping-wren 2026-04-15 17:12:55 +02:00
Markus Ecker d51140ebbc chore: bump @ag-ui/a2ui-middleware to 0.0.5 2026-04-15 14:56:51 +02:00
Jordan Ritter 92730856b5 fix: widen openai peer dep range to include v6.x
The compatibility layer correctly handles v6 (same API surface as v5),
but the version range ^5.0.0 excluded v6.x. Changed to >=5.0.0 so
users on the latest openai SDK don't get peer dependency warnings.
2026-04-15 13:10:34 +02:00
Jordan Ritter 614e4cf815 fix: replace unsafe type casts with proper type guards for OpenAI v4/v5 compat
- Remove all `as any`, `as Function`, and `as Record<string, unknown>` casts
  from production code in the OpenAI compatibility layer
- Introduce typed `OpenAIV4Beta` interface and `hasV4BetaChat` type guard
  for safe runtime detection of v4 vs v5 clients
- Extract `retrieveThreadRun` and `submitToolOutputsStream` helper functions
  into utils.ts with properly typed generic signatures, moving the v4/v5
  dispatch logic out of the assistant adapter
- Give `getChatCompletionsForStreaming` an explicit return type so callers
  no longer need secondary casts
- Update tests to exercise the new helpers directly instead of
  duplicating dispatch logic inline
2026-04-15 13:10:34 +02:00
Jordan Ritter 1a458d1dcf test: add OpenAI SDK v4/v5 compatibility tests (#1979)
Cover isOpenAIV5 detection, getChatCompletionsForStreaming dispatch,
and named-path-param calling conventions for runs.retrieve and
submitToolOutputsStream.
2026-04-15 13:10:32 +02:00
Jordan Ritter 020588e357 fix: support OpenAI SDK v5 in adapter and assistant adapter (#1979)
OpenAI SDK v5 removed beta.chat (promoted to chat.completions) and
changed multi-path-param methods to use named params (e.g.
runs.retrieve(runId, { thread_id }) instead of positional args).

- Add isOpenAIV5() detection and getChatCompletionsForStreaming() helper
- Migrate OpenAIAdapter to use helper for streaming completions
- Migrate OpenAIAssistantAdapter runs.retrieve() and
  submitToolOutputsStream() to branch on SDK version
- Add openai ^4.85.1 || ^5.0.0 to peerDependencies
2026-04-15 13:10:32 +02:00
Jordan Ritter 362a04e1cc fix: resolve agent factory functions in V1 CopilotRuntime constructor
The V1 CopilotRuntime constructor did `{...endpointAgents, ...agents}`
which silently spread a factory function to `{}`, losing all agents.
Anyone using the V1 API with a factory function got zero agents and no
error. This wraps factory functions so endpoint agents are merged at
resolution time instead of construction time.
2026-04-15 13:10:24 +02:00
Jordan Ritter 78c65a8a38 fix: ensure tool_result and tool_use messages stay paired after token trimming (#2450) 2026-04-14 16:23:34 -07:00
Jordan Ritter a7cf38211c fix: add configurable maxInputTokens to OpenAI and Anthropic adapters (#2405) 2026-04-14 16:11:39 -07:00
Jordan Ritter 0c4383d74c fix: add satisfies constraint and improve test coverage for onAfterRequest
- Add `satisfies OnAfterRequestOptions` for compile-time type safety (consistent with onBeforeRequest)
- Replace `(m: any)` casts with type predicates and explicit `as unknown as Message[]`
- Add TODO comment for hardcoded empty properties
- Expand test to verify all 6 fields of OnAfterRequestOptions
- Add edge case tests for undefined messages and missing threadId/runId
2026-04-14 15:48:12 -07:00
Jordan Ritter f403105ad9 fix: only set hasReceivedContent for processed content blocks
Move hasReceivedContent flag inside each content block type handler
so that skipped unknown tool_use blocks do not prevent the fallback
response mechanism from activating. Add tests for unknown tool
skipping behavior.
2026-04-14 15:47:27 -07:00
Jordan Ritter 4bd57af65d test: add tests for array content normalization in TOOL_CALL_RESULT
Cover the MCP adapter scenario where content arrives as an array of
{type:"text", text:string} objects, and verify non-text parts are
filtered out during normalization.
2026-04-14 15:41:25 -07:00
Jordan Ritter fde4e0b424 fix: cache pino debug logger on runtime instead of creating per-request
createLogger() was called on every request when debug was enabled,
instantiating a new pino + pino-pretty stream each time. Now creates
a single logger in the runtime constructor and passes it to handlers.
Added test verifying pre-created logger is reused.
2026-04-14 14:58:22 -07:00
Jordan Ritter 1e5c0ba9ec fix: support OpenAI SDK v5 by falling back from openai.beta to openai.chat.completions (#1979) (#3810)
Fixes #1979

## Summary

- Add `isOpenAIV5()` detection helper that checks whether `beta.chat`
was removed (v5 promoted it to `chat.completions`)
- Add `getChatCompletionsForStreaming()` helper that routes to the
correct completions namespace per SDK version
- Migrate `OpenAIAdapter` to use the new helper instead of direct
`beta.chat.completions` access
- Migrate `OpenAIAssistantAdapter` `runs.retrieve()` and
`submitToolOutputsStream()` to use v5 named path params (e.g.
`retrieve(runId, { thread_id })` instead of positional
`retrieve(threadId, runId)`)
- Add `openai` to peerDependencies with `^4.85.1 || ^5.0.0` range
- Add 11 unit tests covering v4/v5 detection, streaming dispatch, and
named path param calling conventions

## Notes

The remaining `openai.beta.threads.*` calls (`threads.create`,
`messages.create`, `runs.stream`) do NOT need migration because:
1. `beta.threads` still exists in v5 (only `beta.chat` was removed)
2. These methods have single path params, so their signatures are
unchanged

## Test plan

- [x] All 11 v5 compat tests pass (`nx run @copilotkit/runtime:test`)
- [x] Runtime package builds successfully (`nx run
@copilotkit/runtime:build`)
- [x] Pre-commit hooks pass (lint, format, publint, attw)
2026-04-14 14:26:05 -07:00
Jordan Ritter e1ef523a3e fix: resolve agent factory functions in V1 CopilotRuntime constructor (#3865)
## Summary

- The V1 `CopilotRuntime` constructor did `{...endpointAgents,
...agents}` which silently spread a factory function to `{}`, destroying
all agents with no error or warning
- Anyone using the V1 API with a factory function (introduced in #3854)
got zero agents — complete silent data loss
- This wraps factory functions so endpoint agents are merged at
resolution time instead of construction time, matching how V2 already
handles it via `resolveAgents()`

Fixes the V1 path regression from #3854 (per-request agent factory,
issue #2941).

## Test plan

- [x] New test: factory function is preserved through constructor (not
spread to `{}`)
- [x] New test: factory resolves different agents per-request based on
headers
- [x] New test: endpoint agents are correctly merged with
factory-resolved agents
- [x] New test: static agent records still work (backward compat)
- [x] New test: promised agent records still work (backward compat)
- [x] Red-green verified: 4/5 tests fail without the fix, all 5 pass
with it
- [x] Full runtime test suite passes (1234 tests)
- [x] Full build passes
2026-04-14 14:06:14 -07:00
Jordan Ritter b9748a6e0e fix: widen openai peer dep range to include v6.x
The compatibility layer correctly handles v6 (same API surface as v5),
but the version range ^5.0.0 excluded v6.x. Changed to >=5.0.0 so
users on the latest openai SDK don't get peer dependency warnings.
2026-04-14 13:57:49 -07:00
Jordan Ritter a8b224e935 fix: replace unsafe type casts with proper type guards for OpenAI v4/v5 compat
- Remove all `as any`, `as Function`, and `as Record<string, unknown>` casts
  from production code in the OpenAI compatibility layer
- Introduce typed `OpenAIV4Beta` interface and `hasV4BetaChat` type guard
  for safe runtime detection of v4 vs v5 clients
- Extract `retrieveThreadRun` and `submitToolOutputsStream` helper functions
  into utils.ts with properly typed generic signatures, moving the v4/v5
  dispatch logic out of the assistant adapter
- Give `getChatCompletionsForStreaming` an explicit return type so callers
  no longer need secondary casts
- Update tests to exercise the new helpers directly instead of
  duplicating dispatch logic inline
2026-04-14 13:50:23 -07:00
github-actions[bot] 8933ee82b5 style: auto-fix formatting 2026-04-14 16:39:04 +00:00
Alem Tuzlak 488c7d00e0 fix: address PR review feedback for debug mode
- Count all emitted events unconditionally (eventCount), track separately
  how many were logged (loggedEventCount) — completion log shows both
- Remove dead `?? undefined` on runtime.debug (non-optional type)
- Update test to verify eventCount reflects actual events; add test with
  events: true to verify loggedEventCount
2026-04-14 18:34:49 +02:00
Alem Tuzlak 7e0a632e64 test: add debug mode tests for shared, runtime, and core packages 2026-04-14 18:34:47 +02:00
Alem Tuzlak 99c3a39a29 style: fix prettier formatting 2026-04-14 18:34:47 +02:00
Alem Tuzlak 4ec0230cf8 fix(runtime): guard debug property access for backward compat with mock runtimes 2026-04-14 18:34:46 +02:00
Alem Tuzlak 0b2731e8da feat(runtime): add debug logging to SSE event pipeline 2026-04-14 18:34:08 +02:00
Alem Tuzlak b9127c18c1 feat(runtime): accept debug config on CopilotRuntime constructor 2026-04-14 18:34:07 +02:00
Alem Tuzlak 983274f7c3 Merge branch 'main' into worktree-nested-tinkering-quail 2026-04-14 14:11:42 +02:00
Alem Tuzlak 19b99dd2ae fix(runtime): widen TanStack message content type for adapter compat (#3747)
## Summary

- Widen `TanStackChatMessage.content` from `TanStackContentPart[]`
  to `any[]` so messages from `convertInputToTanStackAI` are directly
  passable to any TanStack AI adapter without `as any` casts
- Split `TanStackContentPart` into a proper discriminated union with
  separate variants per modality
- Add `env.d.ts` with `vite/client` reference for CSS import types
- Fix `onError` callback shape in the example

## Test plan

- [x] All 17 multimodal TanStack tests pass
- [x] All 294 agent tests pass
- [ ] Verify no TS errors in react-router example IDE

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-14 14:11:18 +02:00
Martha Schumann e814e91030 test: add unit tests for ThreadStoreRegistry, thread handlers, and hook lifecycle
- 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>
2026-04-13 15:43:28 -07:00
Martha Schumann 14ae28cfd1 feat(inspector): add thread store registry, runtime handlers, and useThreads hook
- 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>
2026-04-13 15:43:27 -07:00
Jordan Ritter b53844c8c3 test: add OpenAI SDK v4/v5 compatibility tests (#1979)
Cover isOpenAIV5 detection, getChatCompletionsForStreaming dispatch,
and named-path-param calling conventions for runs.retrieve and
submitToolOutputsStream.
2026-04-13 09:11:28 -07:00