Commit Graph

226 Commits

Author SHA1 Message Date
Benjamin Taylor f90231f4fd feat(core,react-core): add unarchiveThread to thread store and useThreads
Restores an archived thread via the existing generic PATCH /threads/:id
update path with { archived: false } — the same mechanism example apps
already use for restore — so no new runtime route is required. Mirrors
archiveThread across the core thread store and the v2 useThreads hook.
2026-06-24 08:44:40 -05:00
Markus Ecker b0f2a6fbf3 feat(core): memory store registry on CopilotKitCore
Adds MemoryStoreRegistry (mirroring ThreadStoreRegistry) plus
register/unregister/get/getMemoryStores on CopilotKitCore and
onMemoryStoreRegistered/onMemoryStoreUnregistered subscriber hooks, so a
binding can register a per-agent memory store for sharing/lookup and react to
its lifecycle. Memory stores auto-unregister on agent removal, symmetric with
thread stores. Full core suite green (477 tests).
2026-06-24 13:10:11 +02:00
Markus Ecker be13e02d0c fix(core): memory REST path is runtime-relative /memories (not /api/memories)
runtimeUrl is the CopilotKit runtime mount (e.g. /api/copilotkit); the thread
store uses the relative suffix /threads, which the runtime maps to app-api's
/api/threads. Memory mirrors that with /memories -> /api/memories. /api/memories
would have wrongly produced /api/copilotkit/api/memories.
2026-06-24 13:04:40 +02:00
Markus Ecker 6d96bcdfff feat(core): export the memory store from the package barrel
Surfaces the ɵMemory* types, ɵcreateMemoryStore, selectors, and event groups
from @copilotkit/core, mirroring how ./threads is re-exported.
2026-06-24 12:50:32 +02:00
Markus Ecker dbcf64ee04 feat(core): memory store mutations (server-authoritative add/update/remove)
addMemory POSTs, updateMemory PATCHes (supersede — the id changes), removeMemory
DELETEs against /api/memories. The REST response is applied to local state on
resolve (server-authoritative) and the realtime event reconciles idempotently;
mutation promises resolve to the stored memory (add/update) or void (remove).
Adds isMutating state + mutationFinished tracking via a trackMutation helper
mirroring the thread store.
2026-06-24 12:48:54 +02:00
Markus Ecker 6aef784151 feat(core): memory store REST snapshot + context + selectors
setContext bumps a session and triggers GET /api/memories; the snapshot keeps
only user-scoped memories (v1 surfaces user scope only, matching the realtime
stream). Adds listRequested/listFailed + isLoading/error state, refresh(), and
ɵselectMemories/IsLoading/Error selectors, mirroring the thread store's
bootstrap+fetch effects. Note: REST path is /api/memories — reconcile with how
runtimeUrl is configured if it differs from the thread store's /threads base.
2026-06-24 12:43:34 +02:00
Markus Ecker 3426d8c702 feat(core): wire memory realtime — createMemoryStore consumes memory_metadata
Adds the memory_metadata event type + mapper (created/updated -> upsert,
invalidated -> remove, projecting to the public Memory shape) and a
createMemoryStore that reduces those deltas into observable state. The store
rides an injected user_meta event source (the thread store's
ɵobserveUserMetaEvent in production) — one socket, no lifecycle code on the
memory side. select() re-emits on every change, so React/Angular bindings
re-render when a memory arrives. REST snapshot + mutations land next.
2026-06-24 12:34:56 +02:00
Markus Ecker 4492cb1fdc feat(core): expose ɵobserveUserMetaEvent on the thread store
Lets sibling per-user stores (e.g. the upcoming memory store) ride the
single user_meta socket/channel the thread store already owns, instead of
opening a second socket. The socket effect publishes the live channel session
into a BehaviorSubject; observeUserMetaEvent memoizes a shared, per-event
stream over it (one channel.on(event) fanned out to all subscribers, cleared
on teardown). Phoenix stays fully encapsulated — callers get plain payloads.
Scoped to the user_meta channel only. Additive; socket/reconnect/teardown
flow unchanged.
2026-06-24 12:29:31 +02:00
Markus Ecker 8482743484 feat(core): add memory store reducer (snapshot + realtime upsert/invalidate)
First slice of the framework-agnostic MemoryStore, mirroring the thread
store's micro-redux patterns: session-guarded MemoryState, listSucceeded
snapshot population, and memoryUpserted/memoryInvalidated domain reducers
(prepend-new / replace-in-place / remove). Public kind vocabulary
(topical/episodic/operational). Reducer covered by unit tests.
2026-06-24 12:16:23 +02:00
Tyler Slaton a13c3ee663 chore: merge main into PR 5480 2026-06-23 20:50:16 -07:00
Tyler Slaton 75611b272c chore: merge main into PR 5480 2026-06-23 15:32:09 -07:00
Austin Merrick 4ba201b5c4 fix: repair check-types across all packages and gate it in CI
Repairs TypeScript check-types across the monorepo and adds a CI gate so
regressions are caught going forward:

- core: bundler module resolution and strict-mode fixes
- sdk-js: bundler module resolution; keep codegen, formatter, packaging working
- react-core: fixes across components, hooks, and tests
- react-native: restore catch binding referenced by TypeError cause
- runtime: repair check-types and bound AI SDK schema inference
- web-inspector: nodenext import extensions, export Anchor
- remaining packages and node example: assorted check-types repairs
- deps: add missing type-only devDependencies
- license context driven from /info licenseStatus
- ci: run check-types in the static quality workflow

Squashed from 12 commits for a single, easily-revertable change.
2026-06-23 15:26:47 -07:00
Austin Merrick 30bd6d8f0e test(core): pin remove/re-add baseline; doc + assertion polish
CR round 2 follow-ups (no behavior change):
- Add a core-headers regression test proving the agentOwnHeaders baseline
  stays pristine across remove + re-add (the WeakMap is intentionally not
  cleared on removal; clearing would re-capture polluted headers).
- Correct the stale `headers` config doc ("appended" -> merged on top of each
  HttpAgent's own headers, core wins).
- Tighten the e2e no-provider-headers assertion to toEqual.
2026-06-23 15:22:11 -07:00
tylerslaton 410d34001d chore: release monorepo v1.61.1 2026-06-23 21:00:28 +00:00
Austin Merrick 6bfb12267f docs(core): document header merge/clear contract; pin clear-baseline test
CR round 1 follow-ups (no behavior change):
- Document on setHeaders + applyHeadersToAgent that the merge baseline is the
  agent's construction-time headers, so setHeaders can override but cannot
  remove a per-agent header (the agent's own value re-surfaces on clear), and
  that dynamic updates go through setHeaders, not direct agent.headers mutation.
- Tighten the agentOwnHeaders field comment (captured on first apply, never
  re-captured) and the applyHeadersToAgent method doc.
- Add a core-headers test pinning the clear-reveals-baseline contract.
- Soften the two useAgent test-mock comments: they are an additive stand-in,
  not a faithful model of core's frozen baseline.
2026-06-23 11:43:21 -07:00
Mike Ryan db09796809 fix: gate thread endpoints by runtime capability 2026-06-23 11:32:30 -07:00
Alem Tuzlak 43fdba74aa feat: AG-UI standard interrupt support in useInterrupt + BuiltInAgent
Adds the AG-UI standard interrupt flow (RUN_FINISHED outcome:interrupt + resume array) alongside the legacy on_interrupt path.

- core: forward the standard resume array through runAgent.
- react-core / vue / react-native: useInterrupt handles standard interrupts with resolve()/cancel(), surfaces the primary + full interrupt set, and persists each resolved tool-backed interrupt as a tool-result message so multi-turn conversations stay well-formed (no dangling tool call -> no tool-call loop).
- runtime BuiltInAgent: native interrupts for the aisdk + tanstack factory paths via each SDK's needsApproval primitive (tool-approval-request / CUSTOM approval-requested -> outcome:interrupt); classic interrupt-tool emission + ctx.interrupt() factory primitive; idempotent resume injection mapped to each SDK's native tool-result; getCapabilities advertises humanInTheLoop.interrupts.
- docs: document standard interrupt support.

Verified across core/react-core/runtime unit suites and a real-model multi-turn run on both aisdk and tanstack.
2026-06-23 20:14:17 +02:00
Austin Merrick 59f96620bb fix(core): preserve agent-level headers instead of overwriting them (#5635)
HttpAgent headers configured directly on an agent registered via
agents__unsafe_dev_only were silently replaced by core headers, dropping
per-agent auth headers and causing 401s against self-hosted backends.

Core headers are now merged ON TOP of each agent's construction-time
headers (captured once in a WeakMap before the first apply), with the
core-level value winning on a key conflict. Header application is
centralized in CopilotKitCore.applyHeadersToAgent so the run handler and
the react-core useAgent hook share one merge path and never clobber
per-agent headers.
2026-06-23 10:33:32 -07:00
Jordan Ritter b9311f94b9 fix(core): preserve runtime agent instance across re-connection
`updateRuntimeConnection` unconditionally rebuilt the `remoteAgents` map
with a fresh `ProxiedCopilotRuntimeAgent` for every id on each connect,
discarding the already-registered live instance along with its
accumulated `messages`, `threadId`, and subscriptions. A re-connection
(an `/info` re-settle, or a header/config/transport change) therefore
swapped the live instance for an empty one. Downstream the `use-agent`
memo keys on the instance identity returned by `getAgent(id)`, so the
swap unmounted an already-rendered conversation — the source of the
showcase auth `dom-missing` flap.

Reuse the existing instance for ids still advertised by the runtime
(re-applying only registry-owned headers/credentials in place); mint a
new proxy only for genuinely-new ids; drop ids no longer present. The
disconnect/no-runtime and error paths still clear `remoteAgents`.
2026-06-22 23:16:35 -07:00
Austin Merrick 4c71ea1138 fix(core): allow clearing headers via setHeaders with null/undefined
setHeaders typed headers as Record<string, string>, so there was no
type-safe way to clear a header (e.g. Authorization on logout) — passing
an empty string left the header present with a blank value.

Widen the signature to Record<string, string | null | undefined> and drop
any entry whose value is null/undefined. setHeaders remains a full overwrite,
so clearing one header while keeping the rest is the spread pattern:
setHeaders({ ...copilotkit.headers, Authorization: null }). A shared
normalizeHeaders helper enforces the same string-only invariant at both
write paths (constructor and setHeaders).

Update the react-core AuthTokenSync skill example to show the logout/clear
path and warn that a header must not be managed via both the headers prop and
imperative setHeaders (the provider re-applies prop-derived headers as a full
overwrite when its inputs change). Also update the setHeaders reference
signature docs. Tests cover null/undefined stripping, empty-string
preservation, overwrite-not-merge semantics, single-header clear via spread,
subscriber notification, and propagation to local and remote
(ProxiedCopilotRuntimeAgent) agents.

Fixes #5535
2026-06-19 14:13:02 -07:00
Mike Ryan b094156537 chore: release monorepo v1.61.0 2026-06-18 15:00:19 -07:00
davidmckayv 692e52244c chore: release monorepo v1.60.2 2026-06-17 16:59:44 +00:00
ranst91 02c3a8aef0 chore: release monorepo v1.60.1 2026-06-12 13:03:45 +00:00
Ran Shem Tov 7805a9a57b fix: update cpk to use latest agui core packages 2026-06-12 11:16:19 +02:00
MikeRyanDev a6e8000c94 chore: release monorepo v1.60.0 2026-06-11 16:27:00 +00:00
Mark Fogle 47c993ccbb fix(core): scope context entries per agent and preserve the a2ui agent list (#5369) 2026-06-11 05:06:15 +00:00
Ran Shem Tov e5d3963db6 fix(core): bump @ag-ui core packages to 0.0.56 and adapt runHttpRequest
Bump @ag-ui/core, @ag-ui/client, @ag-ui/encoder from 0.0.53 to 0.0.56
across all packages.

@ag-ui/client 0.0.56 changed runHttpRequest from (url, requestInit) to a
fetch-thunk signature (() => Promise<Response>). Update the single-route
and connect transport paths in ProxiedCopilotRuntimeAgent to wrap the
request in () => this.fetch(url, init), restoring the broken envelope
transports.

Add @ag-ui/core, client, encoder, proto to minimum-release-age-exclude
in .npmrc so the freshly published 0.0.56 (under the 24h release-age
gate) installs in CI.
2026-06-09 17:47:43 +02:00
contextablemark 9bfeb74bc9 chore: release monorepo v1.59.5 2026-06-05 05:21:08 +00:00
ranst91 47fcb30d0f chore: release monorepo v1.59.4 2026-06-04 17:26:49 +00:00
lukasmoschitz 5de391fa27 fix(core): make setRuntimeTransport idempotent on the requested transport mode (#5179)
## Summary

`setRuntimeTransport` was not idempotent on the **requested** transport
mode. Auto-detect resolves the requested `"auto"` to a concrete
transport (`"rest"`/`"single"`) and writes that back to
`_runtimeTransport`; the guard then compared against that **resolved**
value. So re-applying the same requested mode — which the provider
effect does on **every render** — compared unequal and **re-ran the
entire `/info` handshake**, rebuilding the runtime agents mid-session.

When that re-sync lands during a turn, `useAgent` hands the UI a
freshly-rebuilt (empty) agent for a render, **blanking the whole
transcript** (and any per-message UI bound to it — e.g. the intelligence
indicator) until it replays.

## Fix

Track the **requested** mode separately (`_requestedTransport`) and
guard on it. Re-applying an unchanged requested transport — including
`"auto"` after auto-detect has resolved it — is now a no-op, so no
redundant `/info` re-sync fires.

## Tests

`packages/core/src/__tests__/agent-registry-resync.test.ts`: re-applying
`"auto"` after auto-detect resolves it does **not** refetch `/info`.

## Scope / risk

Touches only `packages/core` (`core/agent-registry.ts` + the test). **No
public API change.** Genuine transport *changes* still re-sync exactly
as before; only redundant re-applications of the same requested mode are
skipped.

> **Verified live:** this idempotency guard *alone* eliminates the
mid-turn re-sync in the e-commerce intelligence demo — instrumentation
shows no `/info` handshake fires during a turn, and the
transcript/indicator no longer flickers. (An earlier draft also made the
re-sync itself non-destructive as defense-in-depth; that was dropped
because, with this guard, no mid-turn re-sync occurs for it to protect
against.)
2026-06-04 11:56:47 +02:00
Jordan Ritter 32551f2bdb fix(react-core): type the active-run completion contract and serialize the suggestion send path
Replace the brittle `"activeRunCompletionPromise" in agent` probe + double
`as unknown as` casts in CopilotChat with a typed `RunCompletionAware`
contract plus an `isRunCompletionAware` type guard, both exported from core.
IntelligenceAgent now declares the property and implements the interface, so
the in-flight-run await is reachable without a cast and non-Intelligence
agents still degrade safely. Cast sites in the attachments/e2e tests and the
MockStepwiseAgent helper are updated to the typed accessor.

Factor the await-then-send logic into a shared `waitForActiveRunToSettle`
helper and call it from BOTH onSubmitInput and handleSelectSuggestion. This
closes the suggestion-path in-flight gap: selecting a suggestion mid-run no
longer pre-empts/aborts the active run (e.g. an interrupt RESUME) — the same
regression PR #5195 fixed for the typed-Enter path. Adds a red-green
regression test that parks the suggestion send on the in-flight promise.
2026-06-03 19:47:38 -07:00
jpr5 be20a389cf chore: release monorepo v1.59.3 2026-06-03 14:53:22 -07:00
Lukas Moschitz 8a79dca3b4 fix(core): make setRuntimeTransport idempotent on the requested transport mode (RD-4)
Auto-detect resolves the requested transport ("auto") to a concrete value
("rest"/"single") and writes it back to _runtimeTransport. setRuntimeTransport
then compared against that resolved value, so re-applying the same requested
mode — which the provider effect does on every render — compared unequal and
re-ran the entire /info handshake, rebuilding the runtime agents mid-session
and blanking the transcript (and any per-message UI bound to it).

Track the requested mode separately (_requestedTransport) and guard on it, so
re-applying an unchanged requested transport is a no-op.

Adds coverage: re-applying "auto" after auto-detect resolves it does not
refetch /info.
2026-06-03 16:28:35 +02:00
jpr5 3b78ae7551 chore: release monorepo v1.59.2 2026-05-30 17:34:06 +00:00
Tyler Slaton 8eb339e3e6 feat(ci): bundle-size tracking + ES-compat checks (OSS-123, OSS-121) (#5051) 2026-05-30 09:21:25 -07:00
David McKay c6ca283e96 feat(ci): bundle-size tracking + ES-compat checks (OSS-123, OSS-121)
Adds two CI signals for keeping the published packages small and broadly compatible:

- Bundle size: size-limit file-mode config across packages plus a
  CopilotChat import-size regression signal (gzip) so growth in the
  headline consumer entrypoint is visible on every PR. A bundle-size
  workflow comments results on the PR (Phase 1: no hard-fail).
- ES compatibility: a compat-check (es-check) script across 9 packages
  with a root .browserslistrc, validating built .mjs/.cjs against the
  es2022 build target.

The measure script is importable (measureBundle) and unit-tested. Dev
docs live under dev-docs/ (bundle-size.md, browser-compat.md). All
action refs are pinned to full commit SHAs for supply-chain safety.
2026-05-29 16:44:35 -07:00
BenTaylorDev 28f6264dd4 chore: release monorepo v1.59.1 2026-05-29 15:19:08 +00:00
BenTaylorDev 94b1f61cc3 chore: release monorepo v1.59.0 2026-05-27 22:31:30 +00:00
BenTaylorDev ebc09ea5c0 chore: release monorepo v1.58.0 2026-05-26 15:40:57 +00:00
github-actions[bot] 47d3a0d442 style: auto-fix formatting 2026-05-21 22:14:54 +00:00
Jordan Ritter 56f3477e09 fix(ci): add repository.url to packages missing it + one-shot publish workflow
Packages without repository.url fail npm OIDC provenance verification.
Adds the field to agentcore-runner, core, sqlite-runner, voice, and
web-inspector. Includes a one-shot workflow to publish the 14 remaining
v1.57.4 packages (a2ui-renderer already published via OIDC).
2026-05-21 15:14:02 -07:00
tylerslaton 938803e6f4 chore: release monorepo v1.57.4 2026-05-21 14:25:58 +00:00
tylerslaton efae3dfb5b chore: release monorepo v1.57.3 2026-05-19 15:59:44 +00:00
tylerslaton 1b14504788 chore: release monorepo v1.57.2 2026-05-13 00:40:27 +00:00
Martha Schumann ce35cba85e feat(inspector/telemetry): propagate telemetryDisabled from runtime env var through inspector
- Add telemetryDisabled to RuntimeInfo from COPILOTKIT_TELEMETRY_DISABLED/DO_NOT_TRACK env vars
- Mirror through AgentRegistry and expose via CopilotKitCore getter
- Guard track calls, URL param appending, and console disclosure on core.telemetryDisabled
- Move maybeShowDisclosure() to onRuntimeConnectionStatusChanged (fires after core attaches)
- Update docs to replace localStorage toggle description with env var approach
- Add telemetryDisabled test suite to get-runtime-info tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 15:43:17 -05:00
Dusty aa08743c7e fix(core): only reset agent state on actual thread switch (supersedes #4720)
When the chat's connect effect re-fires due to React effect-dep churn, it
calls copilotkit.connectAgent({ agent }) on the same thread again. The
RunHandler previously called agent.setMessages([]), agent.setState({}),
and (transitively) clearReconnectCursor on every such call. That forced
the realtime gateway to replay the topic's full event history on every
churn re-connect — sending the same persisted cpki_event_ids 2-3 times
per thread switch — and produced both halves of Tyler's bug: duplicate
rows in the inspector AG-UI Events tab plus "Message not found" toasts
when the next runAgent fired with an empty agent.messages.

This change makes the orchestrator detect actual thread switches:

- RunHandler tracks _lastConnectedThreadId across connectAgent calls.
  On a fresh restore (different threadId from last call) it does the
  reset and clears the replay cursor. On churn (same threadId) it
  skips the reset entirely so local messages/state are preserved and
  the gateway resumes from lastSeenEventId instead of replaying.

- IntelligenceAgent.connect() no longer auto-clears the cursor;
  cursor management is the caller's decision now. clearReconnectCursor
  is made public so RunHandler (and tests) can call it explicitly.

- ProxiedCopilotRuntimeAgent exposes a clearReplayCursor(threadId)
  method that delegates to the IntelligenceAgent. Non-Intelligence
  runtime modes are a safe no-op.

This supersedes #4720, which attempted to solve only the inspector
duplicate-row symptom by adding a dispatcher dedup. That approach
introduced a blocking regression in the A → B → A restore path: the
dedup persisted across thread switches and suppressed the gateway's
restore replay, leaving agent.messages at [] and triggering the very
"Message not found" toast we were trying to prevent. Mike's review
caught it. The dispatcher dedup is removed entirely; the
orchestrator-level gate is sufficient and a smaller surface change.

Tests:
- intelligence-agent.test.ts: updated 4 tests that codified the old
  "always clear cursor" semantics. Added an explicit test that
  clearReconnectCursor() empties the cursor for the next connect, and
  Mike's regression — replay the same cpki_event_id after A → B → A
  and verify the rehydrate still produces the user message.
- core-connect-thread-switch.test.ts (new): four tests for the
  RunHandler gate covering churn, single switch, A → B → A, and the
  no-clearReplayCursor non-Intelligence path.

All 430 core tests pass.
2026-05-08 14:31:49 -06:00
tylerslaton 5164ae303f chore: release monorepo v1.57.1 2026-05-07 16:41:22 +00:00
Markus Ecker 79fb5af452 Merge remote-tracking branch 'origin/main' into mme/register-proxied-agent
# Conflicts:
#	packages/react-core/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx
#	packages/react-core/src/v2/hooks/use-agent.tsx
#	packages/web-inspector/src/styles/generated.css
2026-05-07 14:20:55 +02:00
Markus Ecker 77dab3766a refactor(core,docs): rename ProxiedCopilotRuntimeAgent.remoteAgentId → runtimeAgentId
Renames the proxy-config field, the field on the agent instance, and
all matching references in tests and the useCopilotKit reference page.
"runtime" reads more naturally now that the proxy concept is documented
as "a local agent that delegates to a runtime agent" rather than
"remote agent" — the latter conflates with `remoteAgents` (the
registry of agents fetched from the runtime), which keeps its name.

No behavioral change; the field still controls the outbound REST URL
used by the proxy.
2026-05-06 11:46:44 +02:00
tylerslaton 490440a0e4 chore: release monorepo v1.57.0 2026-05-04 17:33:59 +00:00