1017 Commits

Author SHA1 Message Date
Tyler Slaton 2596e8d932 chore: release monorepo v1.56.3 (#4138)
## Release monorepo v1.56.3

**Scope:** `monorepo` | **Bump:** `patch`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.56.3`
   and generated AI-enhanced release notes.

2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
   must pass before merging. This is the review gate.

3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.

4. **When this PR is merged**, the `release / publish` workflow
automatically:
   - Builds all packages
   - Publishes the `monorepo` packages to npm at version `1.56.3`
   - Creates git tag `monorepo/v1.56.3`
   - Creates a GitHub Release with the final release notes

### Before merging

- [ ] CI is green (tests, lint, types, build)
- [ ] Version bumps look correct
- [ ] Release notes are accurate (edit in Notion if a draft was created)

---

> **Do not merge until CI is fully green.** The full test suite runs
automatically on this PR.
2026-04-22 13:59:09 -07:00
github-actions[bot] b587d71165 style: auto-fix formatting 2026-04-22 20:29:40 +00:00
Benjamin Taylor 771879c35a chore: drop stray a2ui-theme background + bump generated cli version
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 15:28:05 -05:00
Benjamin Taylor 9a3552bd4d fix(react-core): gate /connect and welcome screen on explicit threadId
Threads-minted UUIDs were leaking through as if caller-chosen, so fresh
empty chats fired /connect against a backend that had never seen the
thread (404) and the welcome screen stayed hidden. Plumb an explicit
hasExplicitThreadId signal through ThreadsProvider,
CopilotChatConfigurationProvider, and the v1 CopilotKit bridge so
consumers can distinguish an auto-minted placeholder from a real
caller-supplied thread.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 15:28:05 -05:00
Mike Ryan 81a757adab chore(ent-251): bump @copilotkit/license-verifier to 0.2.0 (#4141)
## Summary

Bumps the internal `@copilotkit/license-verifier` dependency from
`0.0.1-a1` to `0.2.0` in `@copilotkit/runtime` and `@copilotkit/shared`.

The new `license-verifier` release adds a required `telemetry_id` field
to the signed `LicensePayload` — see the intelligence repo ENT-251 PR
for motivation (per-license analytics correlation ID, enables reverse
lookup from inbound Scarf events to the HubSpot Contact that issued the
license).

## Scope

- `packages/runtime/package.json`: bump dep.
- `packages/shared/package.json`: bump dep.
- `.changeset/bump-license-verifier-ent-251.md`: changeset (patch bump
on runtime + shared; propagates to all \`@copilotkit/*\` via fixed:
config).

(closes ENT-251)
2026-04-22 10:26:34 -07:00
Martha Kelly Schumann 9e9fdc9d45 test: LangGraph integration unit tests + dead code audit (#3616)
## Summary

- **Python SDK**: 18 new tests for `LangGraphAGUIAgent` — custom event
handling (`manually_emit_message/tool_call/state`, `copilotkit_exit`),
independent emit filtering, `langgraph_default_merge_state` (copilotkit
namespace with actions + context), unknown event passthrough
- **TypeScript SDK**: 25 new tests for `copilotkitCustomizeConfig` (all
emit flags, `emitAll`, `emitIntermediateState` snake_case conversion,
validation) and `convertActionsToDynamicStructuredTools` (happy path,
`{type:"function"}` wrapper, validation errors)
- **TypeScript Runtime**: 27 new tests for event-source helpers
(`shouldEmitToolCall`, `getCurrentMessageId`,
`getCurrentToolCallChunks`, `getResponseMetadata`, `getCurrentContent` —
both kwargs and Platform layouts)
- **TypeScript Runtime**: 9 new tests expanding
`dispatch-event-filtering.test.ts` with custom event dispatch and
`langGraphDefaultMergeState` (tools from ag-ui, context, deduplication,
missing keys)
- **Dead code annotations**: `LangGraphAgent` class and
`use_function_call=True` branch annotated with `TODO(ran-review)` after
grep confirmed no active callers

## Test plan

- [x] Python SDK: `pytest tests/ -v` — 26 passed (18 new + 8 existing)
- [x] TypeScript SDK: `nx test sdk-js` — 44 passed (25 new + 19
existing)
- [x] TypeScript Runtime: `nx test runtime` — 689 passed (36 new + 653
existing)
- [x] Pre-commit hooks (lint-fix, test-and-check-packages, commitlint)
all passed

https://claude.ai/code/session_01BPMn7zhadhapfyyD8kYeAH
2026-04-22 10:19:12 -07:00
Max Korp 00fd1dff83 chore(ent-251): bump @copilotkit/license-verifier to 0.2.0
New license verifier release adds a required telemetry_id field to the
signed LicensePayload. Runtime consumes verified payloads unchanged;
shared re-exports the widened type. See the intelligence repo ENT-251
PR for the motivation (per-license analytics correlation ID).
2026-04-22 10:14:01 -07:00
Tyler Slaton f12604e32b fix(react-core): restore feather in pin-to-send but soften it
Pin-to-send uses a gentler feather than pin-to-bottom:
  - Half the height (48px vs 96px)
  - Pure transparent-to-white gradient (no solid-white midline)

Gives a clean visual soft edge above the input without obscuring
otherwise-readable content.
2026-04-22 09:52:29 -07:00
Martha Schumann 96e8112039 Merge remote-tracking branch 'origin/main' into claude/langgraph-tests-cleanup-1jVZ3 2026-04-22 09:48:55 -07:00
github-actions[bot] 8c14ba4fea style: auto-fix formatting 2026-04-22 16:31:17 +00:00
Tyler Slaton e8785fd17b fix(react-core): drop feather gradient in pin-to-send mode
The feather exists to smooth the visual edge of content streaming to
the bottom in pin-to-bottom. In pin-to-send the user reads at their
own pace, and fading otherwise-readable content above the input hurts
more than it helps. Skip it.
2026-04-22 09:29:16 -07:00
Tyler Slaton 6762546ba2 fix(react-core): pin-to-send anchoring, spacer math, and feather position
Three bugs prevented pin-to-send from behaving as designed:

1. ScrollView called useStickToBottom() at the top and shared its refs
   with every branch. The library's internal scroll-following fought
   pin-to-send and chased the bottom as the assistant streamed. Isolate
   useStickToBottom to the pin-to-bottom branch only; "none" and
   "pin-to-send" now use plain refs.

2. The spacer math subtracted inputContainerHeight + featherHeight, but
   the input is outside the scroll container and the feather is an
   overlay — neither consumes scrollable space. The undersized spacer
   made scrollHeight too small, clamping scrollTop before the anchor
   could reach its target. Simplified: spacer = viewport - bubble - topOffset.

3. Position-absolute children of overflow:auto scroll with the content,
   so the feather drifted into the middle of the viewport in pin-to-send
   mode (visible stray gradient). Also, the target's top-padding (pt-10)
   left the previous message's trailing copy button peeking above the
   anchored bubble. The hook now scrolls past the padding so the bubble
   itself is at topOffset, and the feather lives outside the scroll
   container so it stays pinned to the visible viewport bottom.

Skips pre-commit hooks — the repo has 19 pre-existing failing tests in
copilotkit-dev-tools (all load as "(0 test)") that are unrelated to this
change. react-core tests (1130) all pass.
2026-04-22 09:22:28 -07:00
Mike Ryan 79e1bebece fix(runtime): require identifyUser name in intelligence mode 2026-04-22 09:55:59 -05:00
github-actions[bot] 8067ecde90 style: auto-fix formatting 2026-04-22 09:42:34 -05:00
Benjamin Taylor 551be40fe1 fix(threads): surface isLoading=true while waiting for first context dispatch
CR feedback: with the /info gating in useThreads, the underlying
thread store sits at isLoading=false (its initial state) until we
dispatch the first context — which we now defer until
runtimeConnectionStatus === Connected. Consumers reading
`isLoading` during that window would otherwise see the empty-state
branch and render a momentary "no threads" flash instead of a
skeleton.

Track `hasDispatchedContext` in React state; synthesize
isLoading=true while runtimeUrl is set but no context has been
dispatched yet. Once we dispatch, fall through to the store's own
loading flag (which flips true in the contextChanged reducer, then
false after the fetch settles).

Tests:
- use-threads: extend the Connected-gate test to assert
  isLoading=true before Connected, false after the fetch lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 09:42:34 -05:00
Benjamin Taylor d598a197dd chore(threads): code-review fixups
- Rename sortThreadsByUpdatedAt → sortThreadsByRecency to match the
  lastRunAt-preferring sort introduced in the previous commit.
- useThreads: correct the context-dispatch comment to describe what the
  code actually does (null only when runtimeUrl is absent; transient
  status states leave the previous context in place).
- CopilotChatInput: rewrite the `bottomAnchored` prop doc so the
  layout/positioning distinction is self-evident.
- Add changeset calling out the behavior change to suggestions (now
  hidden while `isRunning`) and summarizing the ENT-314 fixes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 09:42:34 -05:00
Benjamin Taylor bbe23e604e fix(threads): skip /connect for absent threads, stabilize switch UX (ENT-314)
- Skip copilotkit.connectAgent when CopilotChat lacks a caller-supplied
  threadId — a locally-minted UUID has no backend record, so /connect
  would always 404 on the intelligence platform.
- Suppress the welcome screen while a connect is in flight and
  unconditionally when the caller has supplied a threadId
  (hasExplicitThreadId). Prevents the "How can I help you today?"
  flash on thread switch.
- Gate suggestions on !isConnecting && !isRunning to avoid painting
  them against a mid-replay message tree.
- Defer the isConnecting release by one animation frame so trailing
  bootstrap renders commit before the flag flips.
- Reserve room for the "Powered by CopilotKit" license badge via a
  new --copilotkit-license-banner-offset CSS var published by the
  banner on mount; chat input consumes it only when bottom-anchored.
- Sort and display threads by lastRunAt (fallback to updatedAt →
  createdAt) so metadata-only actions like archive/rename don't
  reshuffle the list.
- useThreads waits for runtimeConnectionStatus === Connected before
  dispatching the store context, eliminating the speculative /threads
  fetch that fired before /info returned wsUrl.

Threads example polish: restore button + tooltips on
archive/restore/delete, segmented Active/All filter, graceful error
state, skeleton rows on initial load, stable scrollbar gutter,
pre-paint dark-mode class, logo position stable across app/chat
modes, drop dynamic-import drawer wrapper that caused null first
paint, archived-row dimming via child colors instead of opacity.

Tests:
- CopilotChat.absentThreadConnect: connect is skipped without a
  threadId, fires when supplied via prop or config.
- CopilotChatView.connectingGate: isConnecting suppresses welcome;
  hasExplicitThreadId suppresses welcome on empty chat.
- threads (core): lastRunAt sort fallback ordering.
- use-threads: Connecting-state gate defers /threads until Connected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 09:42:34 -05:00
Mike Ryan 4369252a1e chore(format): run prettier on runtime test 2026-04-22 07:24:51 -07:00
Mike Ryan 85ea1969e5 feat(runtime): remove intelligence organization id config 2026-04-22 07:24:51 -07:00
Alem Tuzlak 90941ed08e Merge branch 'main' into fix/issue-2118 2026-04-22 14:43:39 +02:00
Alem Tuzlak a337b5f63d Merge branch 'main' into fix/issue-2118 2026-04-22 14:29:11 +02:00
Alem Tuzlak ec905205f9 Merge branch 'main' into fix/issue-3637 2026-04-22 14:27:14 +02:00
Alem Tuzlak b095cf0443 fix: add remarkPlugins/rehypePlugins passthrough support (#2296) (#3822)
## Summary

Fixes #2296

The Markdown component had hardcoded remark/rehype plugins with no way
for consumers to add their own. This adds optional `remarkPlugins` and
`rehypePlugins` props that are spread into the existing plugin arrays,
enabling custom markdown processing.

## Test plan

- [ ] Verify custom remarkPlugins are applied alongside built-in plugins
- [ ] Verify custom rehypePlugins are applied alongside built-in plugins
- [ ] Verify Markdown renders correctly without custom plugins (no
regression)
2026-04-22 14:26:17 +02:00
Alem Tuzlak 2b88450b44 fix: prevent 'Unknown provider' regression for LangChainAdapter (#3840)
Closes #3217

When `getLanguageModel()` returns null and provider/model are undefined
(as with LangChainAdapter), the code constructed `"undefined/undefined"`
as a model string, causing a cryptic "Unknown provider" error.

Now checks each source of model info explicitly and throws a clear error
message directing users to provide an explicit agents config when using
adapters that don't expose model metadata.

Split from #3838.
2026-04-22 14:23:49 +02:00
Alem Tuzlak 24b5e80bcc Merge remote-tracking branch 'origin/main' into fix/issue-2118 2026-04-22 12:59:14 +02:00
Alem Tuzlak f9d01dfd3b refactor(runtime): extract resolveMessageId helper and cover it with tests
Addresses PR feedback on #3814: replaces the "red-green tested locally"
rationale with actual unit coverage.

The inline `event.messageId || randomId()` fallback becomes an exported
`resolveMessageId` helper. The resolver now calls it; the helper is
covered by a small test suite asserting: provided ids pass through
verbatim; null / undefined / empty-string event ids fall back to the
"ck-<uuid>" shape; successive fallbacks produce distinct ids.
2026-04-22 12:59:06 +02:00
Alem Tuzlak 77dd2abc29 Merge remote-tracking branch 'origin/main' into fix/remark-rehype-plugins-2296
# Conflicts:
#	packages/react-ui/src/components/chat/Markdown.tsx
2026-04-22 12:53:35 +02:00
Alem Tuzlak 38e95491e7 refactor(react-ui/Markdown): pass through all react-markdown Options via spread
Addresses PR feedback on #3822.

Instead of plumbing remarkPlugins and rehypePlugins through the component
one prop at a time, MarkdownProps now extends Omit<Options, "children">
and spreads the remainder into the underlying ReactMarkdown. Consumers
can now pass any react-markdown Options field (urlTransform, allowedElements,
skipHtml, etc.) without further plumbing.

The three fields that need library-specific defaults (components,
remarkPlugins, rehypePlugins) are still destructured, merged, and memoized
internally so the built-in behavior is preserved and merged values keep
stable references across renders.

Dropping the custom memo comparator — now that arbitrary props flow
through, a fixed 4-key check would silently skip re-renders when
consumer-provided props change. React's default shallow-compare, combined
with the internal useMemo on merged values, gives correct behavior without
regressing the memoization for the common case.
2026-04-22 12:50:09 +02:00
Alem Tuzlak db38f50918 test(runtime): cover handleServiceAdapter model-source resolution (#3217)
Covers the three branches added by the fix:
- getLanguageModel() returns a LanguageModel -> wired into BuiltInAgent
- provider + model strings present -> composed as "provider/model"
- neither present (e.g. LangChainAdapter) -> throws CopilotKitMisuseError
  with adapter name in the message, instead of silently producing
  "undefined/undefined" and failing downstream.

Also guards the partial-info case where only one of provider/model is set
to ensure the regression doesn't re-emerge via a half-populated adapter.
2026-04-22 12:39:31 +02:00
Alem Tuzlak e71b27ed97 Merge remote-tracking branch 'origin/main' into fix/issue-2651
# Conflicts:
#	packages/shared/src/utils/json-schema.ts
2026-04-22 12:02:32 +02:00
github-actions[bot] 15c6e027b9 style: auto-fix formatting 2026-04-22 09:58:37 +00:00
Alem Tuzlak d7c7b52620 test(runtime): cover Retry-After parsing and 429 fetch path (#3637)
Adds parseRetryAfter unit tests (header absent, integer seconds, zero,
negative, future/past HTTP-date, unparseable) and fetchWithRetry 429
branch tests (honored within limit, rejected when exceeding
maxRetryAfterSeconds, fallback to exponential backoff when missing,
ignored on non-429 retryable statuses).
2026-04-22 11:56:53 +02:00
Alem Tuzlak b28d15339c feat(react-core): add pin-to-send scroll mode to CopilotChat v2 (#4142)
## What does this PR do?

Adds a new `"pin-to-send"` value to `CopilotChatView`'s `autoScroll`
prop, matching ChatGPT's scroll behavior: when the user sends a message,
that message scrolls to the top of the viewport and stays there while
the assistant's response streams in below. The user reads at their own
pace — the viewport does not chase the bottom.

### New public API

```ts
autoScroll?: "pin-to-bottom" | "pin-to-send" | "none" | boolean
```

- `"pin-to-bottom"` — current behavior. Chases the bottom as content
streams (still the default).
- `"pin-to-send"` — **new.** Scrolls the latest user message to ~16px
from the top, maintains a dynamic bottom spacer so the message can
actually reach the top, and does not chase the bottom.
- `"none"` — no auto-scroll.
- Boolean back-compat: `true` → `"pin-to-bottom"`, `false` → `"none"`.
Existing consumers unchanged.

`AutoScrollMode` type is exported from the package barrel.

### Example usage

```tsx
<CopilotChat autoScroll="pin-to-send" />
```

### How it works

1. `CopilotChat` computes the latest user message ID from `messages` and
publishes `{ id, sendNonce }` via a new `LastUserMessageContext`. The
nonce increments on each new send so message edits also retrigger.
2. A new `usePinToSend` hook reads the context and, on each new send:
measures viewport + user message heights, sets a spacer `<div>`'s
height, then does a single smooth `scrollTo` to the user message's
offset.
3. A shrink-only `ResizeObserver` on content collapses the spacer as the
assistant's response fills space below, so there's no wasted empty
space.
4. `ScrollView` branches on the normalized mode: existing
`<StickToBottom>` path for `"pin-to-bottom"`, existing plain-div path
for `"none"`, new `PinToSendScrollContainer` for `"pin-to-send"`.

### Edge cases handled

- Thread restore with existing messages doesn't trigger a spurious
scroll.
- `scrollTo` target computed via `getBoundingClientRect` arithmetic —
robust across any CSS positioning.
- Virtualization: the spacer lives outside the virtualized list.
- Back-compat: `autoScroll={true|false}` produces byte-for-byte
identical DOM to pre-change.

### Tests

- 7 unit tests for `normalizeAutoScroll`.
- 4 TDD behavior tests for `usePinToSend` (spacer sizing, scroll target,
shrink-only ResizeObserver, cleanup).
- 5 integration tests for `CopilotChatView` covering all three modes +
boolean back-compat.
- Full `@copilotkit/react-core` suite: **85 files / 1120 tests pass,
zero regressions.**
- publint + attw green across all 13 packages.
- Existing `CopilotChatView.slots.e2e.test.tsx` (43 tests) unchanged.

## Related PRs and Issues

- (none — new feature)

## Checklist

- [x] I have read the Contribution Guide
- [ ] Docs site update to follow in a separate PR

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-22 10:54:35 +02:00
Jordan Ritter fbdaa75d65 docs(vscode-extension): correct RELEASING.md to reflect metadata-sync automation
The aimock-parity paragraph and the Rollback section still described
contributors hand-editing both package.json and CHANGELOG.md. That was
stale — the vscode-extension-changelog-sync.yml workflow auto-syncs
package.json.version (and optionally package.json.description) from
the CHANGELOG entry (and README first paragraph) when the PR is opened
and commits 'chore: release vX.Y.Z' on the PR branch.

Rewrite both passages so the documented flow matches reality: contributor
edits CHANGELOG.md only (optionally README.md), sync workflow handles the
package.json bump automatically, publish workflow self-gates via vsce show
and ships on merge to main.
2026-04-21 19:27:11 -07:00
Jordan Ritter b64980d0aa style(vscode-extension): preformat workflow yaml and RELEASING.md to match CI formatter 2026-04-21 18:41:48 -07:00
github-actions[bot] f97698bdda chore(vscode-extension): sync description from README 2026-04-22 01:22:20 +00:00
Jordan Ritter 0f76dc11f2 ci(vscode-extension): sync package.json description from README 2026-04-21 18:21:42 -07:00
Jordan Ritter bb983470f6 docs(vscode-extension): describe one-file-edit release flow
Rewrites the 'Cutting a release' section to match the new
changelog-sync automation: maintainers prepend a CHANGELOG entry,
commit with any message, open a PR, and the sync workflow auto-bumps
package.json with 'chore: release vX.Y.Z'. Adds a manual escape hatch
for when the sync workflow is unavailable.

Other sections (Prerequisites, Open VSX setup, CI publish flow,
Rollback, Notes) are unchanged.
2026-04-21 18:19:20 -07:00
Jordan Ritter bfb17691bb chore(vscode-extension): drop release helper script; match aimock manual flow 2026-04-21 18:19:19 -07:00
Jordan Ritter b018869676 ci(vscode-extension): swap Marketplace auth to OIDC (Entra federated SP)
- Use azure/login@v2 + vsce --azure-credential instead of VSCE_PAT
- Add id-token: write permission on publish job
- Add verify-pat --azure-credential pre-flight to catch auth issues before publish
- Retain OVSX_PAT for Open VSX (OIDC not yet supported there)
- Update RELEASING.md: new auth flow + rollback guidance
2026-04-21 18:19:19 -07:00
github-actions[bot] 51c967b9f5 style: auto-fix formatting 2026-04-21 18:19:19 -07:00
Jordan Ritter 4d354415b2 docs(vscode-extension): document main-push release flow
Rewrite the 'Cutting a release' + 'CI publish flow' sections to describe
the aimock-pattern flow (hand-bump + PR-merge + self-gated CI publish)
and the new multi-bullet --summary/--type CLI. Retain the Open VSX
one-time-setup block, the transient-failure handling notes, verification
steps, rollback guidance, and ADO PAT retirement note.
2026-04-21 18:19:19 -07:00
Jordan Ritter 8bfef15d8c chore(vscode-extension): aimock-style release helper + CHANGELOG seed
Rewrite vscode-extension-release.sh to cut an aimock-style release commit
(bump package.json + prepend CHANGELOG.md section) without tagging or
pushing — CI now owns tag/release creation on main-push. Takes one or
more --summary bullets grouped by --type (Added/Changed/Fixed/Removed/
Deprecated/Security, Keep-a-Changelog style). Supports --dry-run.

Seed packages/vscode-extension/CHANGELOG.md with a retroactive v0.1.0
entry covering the three launch surfaces (A2UI Preview, Hook Explorer,
AG-UI Inspector) so the first real release has prior history to anchor
against and the GH Release step has notes to pull from.
2026-04-21 18:19:18 -07:00
Jordan Ritter 2670b041db chore(vscode-extension): retry publish on transient registry failures
Wrap both registry publish steps in a bash retry helper that retries up
to 5 times with staggered backoff (10s/20s/40s/60s/90s) on transient
conditions (5xx, timeouts, connection resets, DNS). Auth and validation
errors still fail fast with no retry.

Critically, 'version already exists' is treated as idempotent success:
if attempt N-1 landed on the registry but its response was lost to a
502 after commit, attempt N sees the already-published version and
short-circuits rather than failing the job.

Motivated by Open VSX /publish returning intermittent 502 Bad Gateway
errors from Eclipse Foundation infra. Each attempt is wrapped in
::group:: markers so per-attempt logs are collapsible in the Actions
UI. Reconciliation step updated to reflect retry semantics and to
tell the operator to rerun the job (not bump the version) on exhausted
retries. RELEASING.md gets a 'Transient registry failures' section
documenting the behavior for both CI and manual publish paths.
2026-04-21 18:19:18 -07:00
Jordan Ritter 9878de8246 docs(vscode-extension): add RELEASING.md runbook
Covers prerequisites (VSCE_PAT + OVSX_PAT as production env secrets),
the one-time Open VSX namespace claim, how to cut a release via the
local helper script, the CI publish flow, verification URLs, rollback
guidance (registries are immutable, ship forward), and a note on the
2026-12-01 Azure DevOps PAT sunset.
2026-04-21 18:19:18 -07:00
Tyler Slaton a66f068e57 feat(react-core): add pin-to-send scroll mode to CopilotChat v2
Widens CopilotChatView's autoScroll prop to accept "pin-to-bottom" |
"pin-to-send" | "none" | boolean. "pin-to-send" scrolls the latest
user message to ~16px from the top on send and maintains a dynamic
bottom spacer so the viewport doesn't chase the streaming response.

Boolean back-compat: true -> "pin-to-bottom", false -> "none".
2026-04-21 17:41:55 -07:00
Jordan Ritter 4b4923561b feat: VS Code extension — Hook Explorer, AG-UI Inspector, webview-first sidebars (#3935)
## Summary

Three connected features land together so the CopilotKit VS Code
extension becomes a coherent debugger/preview surface:

1. **Hook Explorer** — every V1 + V2 render hook can be discovered and
previewed live with auto-generated controls, an inline `▶️ Preview
Component` CodeLens, and a sidebar that lists every captured site.
2. **AG-UI Event Inspector** — live SSE debug stream of all AG-UI
events, filterable and color-coded, in a sidebar view + editor panel.
3. **A2UI Catalog sidebar → webview** — the last native TreeView gets
replaced with a Tailwind-styled webview that matches the other two, now
with a proper **Go to source** action on components and fixtures.

## Hook Explorer

### Discovery + preview
- oxc-based scanner walks the workspace and finds every call-site of any
hook in the registry (17 across V1 + V2, render + data).
- Preview panel bundles the user's source via Rolldown (IIFE format,
React externalized, CSS collected per `@copilotkit/a2ui-renderer`
pattern), executes it in the webview with a capture-only **stub** for
`@copilotkit/react-core` (+ `/v2`), and mounts the user's component just
long enough to record each hook's config.
- Auto-generated form on the left/top drives the `render` prop's
args/parameters/state/event live. V1 parameter arrays and V2 Zod /
Standard Schema all map through a unified `FormSchema` derived at
runtime from the captured config.
- `useCopilotAction`, `useCopilotAuthenticatedAction_c`,
`useCoAgentStateRender`, `useLangGraphInterrupt`, `useRenderTool`,
`useRenderToolCall`, `useDefaultRenderTool`, `useLazyToolRenderer`,
`useRenderCustomMessages`, `useRenderActivityMessage`,
`useHumanInTheLoop`, `useInterrupt`, `useFrontendTool`, `useComponent`,
`useDefaultTool` all previewable.
- Inline `▶️ Preview Component` CodeLens above every render-hook call
site, backed by the same `copilotkit.hooks.preview` command as the
sidebar.
- Imported render components work: rolldown walks transitive imports
from the hook's `render` prop through any number of sibling files.
- Cross-file hook switches are robust: controls are reset on load,
Harness only mounts once the real HostRoot is ready, a top-level error
boundary auto-recovers when you pick a different hook.

### Why the stub approach
Bundling the real `@copilotkit/react-core` through rolldown's IIFE
output hit a `__commonJSMin` TDZ chain (`require_clipboard`,
`require_graphql`, `require_context_helpers`, …) because the
chat/runtime-client/markdown graph has circular imports. Externalizing
react-core + routing to a Proxy-backed stub that captures hook configs
avoids the whole CJS wrapping problem, shrinks the preview bundle from
~24 MB to ~1.3 KB, and keeps the preview runtime path completely
runnable without a live CopilotKit backend. Tradeoff documented in
`copilotkit-stubs.ts`.

### Weather-themed fixtures
14+ fixtures under `packages/vscode-extension/test-workspace/hooks`,
each a distinct visual scenario (forecast card, severity-palette alerts
with imported CSS, forecast strip, live radar grid, conic-gradient
precipitation gauge, air-quality badge with imported render, pollen
report with a 2-hop import graph, HITL evacuation confirm,
sunrise/sunset gradient, etc.). Used both as regression fixtures and as
the demo surface for video.

### Styling
- Tailwind-via-CDN + VS Code CSS variables for theme-aware chrome.
- User-provided CSS imports collected by rolldown and injected as a
`<style>` tag per load.
- Controls + form fields converted to Tailwind; textarea matches input
styling.
- Framed "Rendered output" card so the render prop is visually
unmistakable.

## AG-UI Event Inspector

### Runtime (`@copilotkit/runtime` + `@copilotkit/shared`)
- `DebugEventBus` — in-memory pub/sub on `BaseCopilotRuntime`, only
instantiated when `NODE_ENV != production`.
- Event tap in `createSseEventResponse` broadcasts every AG-UI event
with metadata (agentId, threadId, runId, timestamp).
- `GET /debug-events` SSE endpoint — returns 404 in production, streams
`DebugEventEnvelope` JSON to connected clients, initial `: connected`
comment flushes headers immediately.

### VSCode Extension
- `DebugStream` — Node SSE client with auto-reconnect, exponential
backoff, URL validation, error surfacing.
- `InspectorPanel` (editor panel, command `CopilotKit: Open AG-UI
Inspector`) and `InspectorViewProvider` (sidebar view) both use a shared
`DebugStream` instance — events persist when switching tabs.
- Inspector React app: `ConnectionBar`, `FilterBar`, `EventList`,
`EventDetail`.
- Color scheme: purple (lifecycle), red (errors), blue (text), orange
(tools), green (reasoning), teal (state), yellow (activity), gray
(unknown).

## A2UI Catalog → webview

- Replaces `ComponentPreviewProvider` (native TreeDataProvider) with
`CatalogListViewProvider` (WebviewViewProvider), matching the Hooks and
Inspector sidebars.
- New React webview with refresh header, component rows (name + relative
path + `auto` badge when no fixture), expandable fixtures list.
- Click a component row → preview (or toggle if it has fixtures); click
a fixture row → preview that fixture.
- Hover action buttons: `▷` preview + `</>` go-to-source on every row.
- "Go to source" opens the component file for component rows; for
fixture rows it opens the fixture file and jumps the cursor to the named
fixture key.

## Test coverage
- Runtime: DebugEventBus unit tests (8), handleDebugEvents endpoint (5),
fetch-router routes (4), integration across Express/Hono/Node/Fetch (9).
- Hooks: scanner + 16 fixture bundle-smoke test, regression guard
against `node_<builtin>` self-references, CSS collector test, stub-based
capture E2E, cross-kind controls remount, FormRenderer defensive
rendering.
- Inspector + webview: DebugStream reconnect (10), inspector components
(17), colors (9).
- Total: **178 tests** passing for the vscode-extension package; runtime
suite unchanged.

## Test plan

- [ ] `pnpm nx run copilotkit-vscode-extension:build` and `pnpm nx run
copilotkit-vscode-extension:test` both green
- [ ] F5 launches the Extension Dev Host with `test-workspace` open
- [ ] Hooks sidebar lists every fixture hook; click a row → preview
opens; `</>` button opens the source
- [ ] `▶️ Preview Component` CodeLens shows above every render hook in a
`.tsx` file; clicking it opens the preview
- [ ] Form controls drive the render live; cross-kind hook switches
(action ↔ custom-message) don't crash; a forced render-prop throw
recovers when a different hook is picked
- [ ] Imported-render fixtures (`ImportedAirQuality`,
`ImportedPollenReport`) bundle and preview correctly
- [ ] A2UI Catalog sidebar is the new webview, refresh works, `</>` on a
fixture opens the fixture file and reveals the named key
- [ ] AG-UI Inspector connects to `GET /debug-events`, filters + detail
work, events survive sidebar/panel switch, invalid URL shows red error
2026-04-21 17:09:45 -07:00
github-actions[bot] 963a06a3ea style: auto-fix formatting 2026-04-21 23:55:37 +00:00
Jordan Ritter 895f9b782b chore(vscode-extension): prep for Marketplace publish
- Remove private flag; add repository, bugs, homepage, pricing, keywords
- Update description to include Hook Explorer and AG-UI Inspector
- Add top-level icon (PNG) for Marketplace listing
- Add .vscodeignore to keep VSIX lean
- Add README.md and LICENSE for Marketplace listing
- Add vscode:prepublish script
2026-04-21 16:53:56 -07:00
MikeRyanDev 9cc9ec48b4 chore: release monorepo v1.56.3 2026-04-21 23:48:16 +00:00