Commit Graph

10887 Commits

Author SHA1 Message Date
Mark fd0ea4aaee Merge branch 'main' into release/publish/monorepo/v1.59.5 2026-06-04 22:30:06 -07:00
Jordan Ritter dc76bb4220 fix(showcase): render absent-starter columns as 🚫 unsupported, not grey/red ✗
A STARTER-row column for an integration that has NO starter (the 7 columns
absent from STARTER_TO_COLUMN) was rendering a grey "✗" with a "no starter
for this integration" tooltip. That mis-communicates the truth: a grey/red
✗ reads as "we expected data and got none" or "a probe ran and failed",
when the reality is "this integration is architecturally unsupported in the
starter row".

buildStarterBadge's mapping-derived !isSupported branch now returns the same
🚫 "Not supported by this framework" treatment depth-chip/unified-cell
already use for unsupported cells. Columns that DO have a starter keep
surfacing their real probe status — a genuinely-red starter still renders
red ✗ and is never masked as 🚫.
2026-06-04 22:26:36 -07:00
contextablemark 9bfeb74bc9 chore: release monorepo v1.59.5 2026-06-05 05:21:08 +00:00
Mark dd1dcb3078 feat(react-core): A2UI error-recovery status renderer (OSS-162) (#5228)
## What does this PR do?

Adds the **client-side renderer for the A2UI error-recovery status**
(OSS-162) — the third of the three A2UI "shipped" gaps from the recon
(robust error recovery).

The A2UI middleware emits an `a2ui_recovery` activity as a pure **data
contract** over the AG-UI event stream — `{ status: "retrying" |
"failed" | "resolved", attempt?, errors?, attempts?, error? }`. This PR
turns that into UX in `@copilotkit/react-core`, with no coupling to
`@ag-ui/a2ui-toolkit`:

- **`createA2UIRecoveryRenderer(options)`** (new —
`packages/react-core/src/v2/a2ui/A2UIRecoveryRenderer.tsx`), a
`ReactActivityMessageRenderer` for `activityType: "a2ui_recovery"`:
- **`retrying`** → a non-disruptive, collapsed *"Retrying UI
generation…"* hint that only appears once it would be perceptible (after
`showAfterMs`, or once `attempt` ≥ `showAfterAttempts`) — so a fast
first retry never flashes. It never replaces the surface or shows noisy
errors inline.
- **`failed`** → a clean, tasteful hard-failure message for the end
user, with structured developer detail (per-attempt errors) tucked into
an expandable `<details>`.
- **`resolved`** / anything else → renders nothing (the A2UI surface
renderer owns the UI on success).
- **Auto-registered** in `CopilotKitProvider`
(`builtInActivityRenderers`, gated on `runtimeA2UIEnabled`), alongside
the existing A2UI surface / skeleton / tool-call renderers — so apps
don't wire it up.
- **Configurable** via the provider's `a2ui.recovery` option
(`A2UIRecoveryRendererOptions`): `showAfterMs` (default 2000),
`showAfterAttempts` (default 2), `debugExposure` (`"hidden" |
"collapsed" | "verbose"`, default `"collapsed"`).

Timing and how much debug detail to surface are intentionally **client**
concerns, keeping react-core decoupled from the toolkit (the contract is
plain data).

Scope is deliberately small — 4 files, all in `react-core`: the new
renderer + 7 unit tests, the provider registration, and the export. The
recovery loop, the server-side validation gate, and the framework
adapters live in the **ag-ui** repo (separate PR — see below).

## Related PRs and Issues

- Linear: **OSS-162** — [Google] Add A2UI recovery / error-handling loop
- Server-side counterpart (shared `@ag-ui/a2ui-toolkit` validate +
retry, the `@ag-ui/a2ui-middleware` paint gate, the LangGraph TS/Python
adapters, and the dojo showcase + e2e): **ag-ui-protocol/ag-ui#1858**

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [ ] If the PR changes or adds functionality, I have updated the
relevant documentation _(docs to follow once the cross-repo feature
lands)_
- [x] "Allow edits by maintainers" is checked

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-04 22:16:07 -07:00
Mark Fogle 9696bf5ec0 chore(react-core): drop the OSS-162 changeset (OSS-162)
Removing the changeset added for the A2UI recovery renderer — not wanted here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 05:02:11 +00:00
Mark 9fda7e634d Merge branch 'main' into mark/oss-162-a2ui-recovery-client-ux 2026-06-04 17:58:58 -07:00
Mark Fogle 943c1421fe fix(react-core): hold the A2UI loader until the surface can paint a card (OSS-162)
onReady fired after the first processMessages, but a data-bound list paints
nothing until its data model arrives — so at high stream latency the skeleton
dropped ~1s before the first card (blankness). Gate onReady on the surface
actually being renderable: for data-bound surfaces (components reference data via
`path`), wait for the first non-empty updateDataModel; static surfaces are
renderable from components alone. Latency-independent — fires exactly when the
first card can exist. Fallback timer bumped to 8s (backstop only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 00:57:43 +00:00
Mark Fogle 195de1fc6a fix(react-core): swap the A2UI loader on actual paint, not a fixed delay (OSS-162)
A fixed cross-over delay can't be right — the time from ops-arrive to first card
varies with stream latency, payload size, and machine speed. Instead, the surface
processor fires onReady the moment it has processed its first operations; the
renderer swaps one animation frame later. The timer is demoted to a 1.5s safety
fallback. Latency-independent true replacement, no magic number to tune.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 00:45:04 +00:00
Tyler Slaton fb278c6baf Merge branch 'main' into tyler/format-only-on-pr 2026-06-04 17:18:36 -07:00
Tyler Slaton d193d18d9e Run formatter only on PRs 2026-06-04 17:18:03 -07:00
Jordan Ritter e508508aff fix(showcase): validate every Railway mutation result + harden fleet snapshot
Close the recurring "mutation result not validated" defect class in the
starter-fleet provisioner and make the existing-services snapshot fail loud
instead of silently feeding erroneous create decisions.

- Add a uniform assertMutationOk guard and route EVERY mutation through it:
  serviceCreate (assert .id), serviceInstanceUpdate (was DISCARDED — a false
  Boolean! return meant sleep/healthcheck/image/creds were never applied while
  the script reported success; now asserted and "configured" is logged only
  after verification), serviceDomainCreate (assert .domain on the create path),
  and serviceInstanceRedeploy (routed through the same guard for consistency).
- Absorb a serviceCreate "already exists" rejection: on a snapshot-miss the
  create path now re-fetches the service id by name and falls through to UPDATE
  instead of aborting the whole fleet. Predicate renamed ALREADY_EXISTS_RE and
  reused by the domain-create path.
- fetchExistingServices fails loud on page-drain truncation (hasNextPage still
  true at the defensive bound) rather than returning a partial byName map.
- fetchExistingServices coalesces null serviceInstances/.edges (transitional
  service nodes) so an unguarded .find can't TypeError and abort the fetch;
  interface fields marked optional/nullable.
- TRANSIENT_ERROR_RE made single-line ([^\n]*? not [\s\S]*?) so a newline-joined
  multi-error blob can't bridge "Service" and "not found" across lines.
- withRetry wraps the schedule-exhaustion rethrow with context and { cause }.
2026-06-04 16:43:31 -07:00
Jordan Ritter 3fef03d794 fix(showcase): paginate fleet snapshot, match interpolated not-found, harden missing-token
Three functional fixes to the starter-fleet provisioner found in CR:

- fetchExistingServices now drains the Relay ServiceConnection via
  pageInfo.hasNextPage/endCursor. A single un-paginated query truncated the
  snapshot (~27 SSOT + 12 starter services span >1 page), making an existing
  starter look absent → CREATE path → serviceCreate "already exists" →
  non-transient abort of the whole run.

- TRANSIENT_ERROR_RE now matches Railway's INTERPOLATED "Service <id> not
  found" (id embedded), not just the contiguous "Service not found", so the
  post-create eventual-consistency retry actually fires.

- serviceInstanceRedeploy result check: documented the verified Boolean!
  contract (sources: redeploy-env.ts, bin/railway RestoreCommand) and now
  gates on truthiness (rejects false/null, accepts truthy defensively).

Hardening: ABORT on the live path when GITHUB_TOKEN is unset (private GHCR
images would image-pull-backoff while reporting success); warn-and-continue
only under --dry-run. Benign domain "already exists" no-op now logs the actual
matched Railway message for a forensic trail.
2026-06-04 16:43:31 -07:00
Jordan Ritter 5b643ff3ae fix(showcase): make starter-fleet provisioner converge on re-run, deploy images, validate argv
Harden the committed starter-fleet Railway provisioner against the
partial-failure / mistyped-flag / un-deployed-image failure modes
surfaced in CR:

- Domain idempotency: a serviceDomainCreate that Railway rejects with an
  "already exists" error (start-of-run snapshot missed the domain due to
  eventual consistency, or a prior run died mid-fleet) is now caught as a
  benign no-op (marked "existing", logged) so a re-run converges instead
  of aborting the entire remaining fleet. A genuine non-transient error
  still aborts.

- Explicit redeploy: serviceCreate + serviceInstanceUpdate(source.image)
  only PINS the image; it does not start a deployment, and Railway's image
  auto-updates fire only on a NEW digest push. Added serviceInstanceRedeploy
  after the instance update on BOTH the create and update paths so the
  pinned image actually runs (and starter_smoke can find the service up).
  Mirrors the documented update+redeploy pattern in bin/railway and the
  explicit redeploy showcase_deploy.yml issues after each GHCR push.

- argv validation: parseArgs() now rejects any unrecognized argument
  (e.g. a mistyped --dry-rn) with a usage hint before any provisioning,
  instead of silently ignoring it and proceeding to REAL live provisioning.

- Fail-fast safety: validate the Railway token AND registry credentials
  up front in main() (token resolution no longer process.exit()s deep in
  the GraphQL boundary; main().catch owns the exit). Broadened the
  withRetry transient predicate to the domain/instance eventual-consistency
  class via an overridable per-call predicate. Dry-run now reports a new
  service's domain as "would-create" for a faithful preview.
2026-06-04 16:43:31 -07:00
Jordan Ritter a04d734393 feat(showcase): add committed starter-fleet Railway provisioner for staging
Adds showcase/scripts/provision-starter-fleet.ts — a committed, idempotent
provisioner for the SSOT-decoupled "starter container fleet". It creates (or
updates) one sleepable Railway service per starter template in the STAGING
environment, deriving the 12 targets from STARTER_TO_COLUMN (the smoke-matrix
SSOT) so the fleet can never drift from the build matrix.

Per service: serviceCreate scoped to the STAGING env (environmentId on
ServiceCreateInput, so NO production instance is ever materialized) with
source.image=ghcr.io/copilotkit/starter-<slug>:latest (RAW starter slug) and
GHCR registryCredentials; then serviceInstanceUpdate against staging with
sleepApplication:true + healthcheckPath="/" + region=us-west1; then
serviceDomainCreate for a generated staging domain. A bounded retry absorbs
Railway's eventual-consistency "ServiceInstance not found" right after create.

Healthcheck is "/" not "/api/health": the starters' single deployable image
EXPOSEs 3000 running the Next.js frontend, which serves "/" and
"/api/copilotkit" but has no "/api/health" route; the agent's "/health" is on
the internal 8123 port Railway does not expose. region read-back is null on the
serviceInstance for ALL existing showcase services too — that is normal Railway
behavior, so the fleet matches the existing services.

The fleet is decoupled from the 27-service railway-envs SSOT (starter-* services
are auto-discovered by the starter_smoke probe). #5254 already made
verify-railway-image-refs.ts tolerate starter-* names, so provisioning does not
trip the image-ref gate / skip the showcase build.

Red-green tested against an injected Railway GraphQL mock: target derivation
(raw vs remapped slug), GHCR credential resolution, sleepApplication:true,
staging-env scoping on BOTH create and update (never prod), idempotent
update-vs-create, domain de-duplication, and transient-error retry.
2026-06-04 16:43:31 -07:00
Mark Fogle 5977a58836 fix(react-core): keep the A2UI surface mounted across the cross-over swap (OSS-162)
The prior cross-over returned a different tree shape once ready (top-level
`surfaces` vs the held wrapper), so React unmounted+remounted ReactSurfaceHost at
the swap — throwing away the offscreen-painted surface and reintroducing the gap
at the swap point. Keep ReactSurfaceHost in ONE stable position and only toggle
its wrapper styling (offscreen→in-flow) + the loader overlay, so the painted
surface is preserved. Also track the last pre-paint snapshot from content (not the
lagging operations state) so the paint snapshot can't clobber it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 23:43:12 +00:00
Mark Fogle 33cbb4183d fix(react-core): cross-over the A2UI skeleton into the painted surface (OSS-162)
The skeleton unmounted the instant a2ui_operations arrived, but the A2UIProvider
needs a couple ticks to process the ops and paint — leaving a visible empty gap
between skeleton and first card. Hold the loader in-flow while the surface mounts
and paints OFFSCREEN (absolute, opacity 0), then swap, so the first card truly
replaces the skeleton. Keep showing the last pre-paint snapshot during the
hand-off so the building count / retry status carries through without a flicker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 23:34:43 +00:00
Ben Taylor 6c0ab3e0c5 Intelligence threads in examples rollout (#5236)
## Summary

Lands CopilotKit Intelligence **threads** across ALL integration
examples — an activation-gated, per-example-themed threads drawer with
shared underpinnings. [ENT-679 / ENT-734]

**Migrated examples (18 — complete coverage of
`examples/integrations/*`):** langgraph-python (north-star),
langgraph-js, langgraph-fastapi, strands-python, mastra, adk, agno,
ms-agent-framework-python, ms-agent-framework-dotnet, crewai-flows,
crewai-crews, llamaindex, pydantic-ai, a2a-middleware, a2a-a2ui,
mcp-apps, agent-spec, agentcore.
**Held out:** ag2 (#5206) — showcase surface, pending team discussion.

### What each example gets
- A themed **threads drawer** (list/create/select/archive/restore,
realtime) gated behind `COPILOTKIT_LICENSE_TOKEN` — without a license it
renders a locked tease pointing at `copilotkit add-intelligence`; the
demo otherwise works unchanged on its fallback runner.
- Env-gated `CopilotKitIntelligence` block in the runtime route,
client-safe threads gate (`NEXT_PUBLIC_…` for Next, `VITE_…` for
agentcore's Vite frontend), `.env.example` documenting the local
Intelligence stack, REST transport (`useSingleEndpoint={false}`).
- Coverage in the migration contract test
(`scripts/__tests__/integration-intelligence-migration.test.ts`) — **66
tests**, parameterized + bespoke blocks for the non-standard shapes
(a2a-middleware, a2a-a2ui, agentcore).

### Reconciliation with current main
Rebuilt on top of main's current baseline (not the pre-revert tree):
**1.59.3** pins everywhere (lockfiles regenerated), `default` agent
keys, AGENT_URL normalization, `useConfigureSuggestions`,
`useRenderTool` `status`/`parameters` API, call-time `agent.state`
reads, jpr5's rebuilt crewai-crews page (threads shell grafted around
it). Also rides: a react-core `A2UIMessageRenderer` test flake fix (act
→ waitFor).

### Verification
- Migration contract test: **66/66** passing
- Parity verify: langgraph-js 82 / langgraph-fastapi 91 / strands-python
88 — zero drift (strands + fastapi now fully tracked, shields removed)
- All examples uniform on @copilotkit **1.59.3** (a2ui-renderer stays at
the family-wide 1.56.5 pin)
- oxfmt clean; no stale agent keys

### Provenance
Mechanically: reverts of #5215/#5216/#5217 + reconciliation, then merges
of #5201 (a2a-a2ui), #5207 (agentcore), #5202 (strands-python), #5198
(crewai-crews). Full review history: #5151, #5189, #5196, #5197, #5198,
#5199, #5201, #5202, #5205, #5207, #5209, #5211.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-04 17:32:43 -05:00
Benjamin Taylor 348bed226d Merge remote-tracking branch 'origin/main' into ben1/intelligence-threads-examples-rollout 2026-06-04 17:23:02 -05:00
github-actions[bot] 0002d4f9a6 style: auto-fix formatting 2026-06-04 15:15:48 -07:00
Jordan Ritter 3627b74d90 fix(showcase): tolerate starter-* services in railway image-ref drift gate
The starter container fleet (starter-<slug>) is decoupled from the
27-service railway-envs SSOT: each starter-* service is auto-discovered
at runtime by the starter_smoke probe (railway-services discovery,
namePrefix "starter-") and is never read from railway-envs.ts.

verify-railway-image-refs.ts is a hard needs: of the build job and runs a
bidirectional live-Railway drift check. Before this change, provisioning
a starter-* service made it untracked in the SSOT, so findUntrackedServices
failed and the showcase build was SKIPPED (the canary regression).

Scope both drift checks (findUntrackedServices and, defensively,
findMissingServices) to exclude services matched by a single, well-named
predicate isStarterFleetService(name) => name.startsWith("starter-"),
mirroring the harness discovery filter convention. Real showcase-*/infra
services are still drift-checked exactly as before.

This is the prerequisite for Phase-3 starter provisioning — provisioning
must happen AFTER this merges.
2026-06-04 15:15:48 -07:00
Jordan Ritter a9bc7a2d6c fix(showcase/harness): add starter_smoke to DIMENSIONS so the probe loads
The starter_smoke probe registers its driver under kind `starter_smoke`
(starterSmokeDriver, orchestrator.ts) and config/probes/starter_smoke.yml
declares `kind: starter_smoke`, but the probe-config Zod `kind` enum is
built from DIMENSIONS, which only listed the `starter` emit-prefix and not
the `starter_smoke` probe kind. The enum therefore rejected the YAML at
parse time; because `kind` is shared across all three union variants the
failure surfaced as the misleading "Unrecognized key(s) in object:
'discovery'" union error, the probe never loaded, AND probe-loader.test.ts's
shipped-config assertion failed (the lone recurring failure).

Add `starter_smoke` alongside `starter`, mirroring the existing kind/emit
pairs (e2e_d6/d6, e2e_deep/d5, e2e_demos/e2e). `discovery` was a red herring
— it is a valid key the DiscoveryBlockSchema already accepts; the working
d6-all-pills-e2e.yml uses the identical discovery shape.
2026-06-04 15:08:39 -07:00
Jordan Ritter 88911e04da fix(showcase/pocketbase): make probe_runs.triggered optional so scheduled run-history works
probe_runs.triggered was `required: true`, and PocketBase rejects the
boolean `false` as empty (validation_required). The fleet aggregator opens
every run-history row with `triggered: false` (scheduled, not ad-hoc), so
run-history start() failed on every non-triggered run. Add an idempotent
migration that ALTERs the existing collection's field to optional (the
create migration already ran on staging/prod volumes, so we alter rather
than recreate).
2026-06-04 15:08:34 -07:00
Benjamin Taylor f20157aa88 Merge remote-tracking branch 'origin/main' into ben1/intelligence-threads-examples-rollout 2026-06-04 16:46:57 -05:00
github-actions[bot] 6d24d630e1 style: auto-fix formatting 2026-06-04 21:46:32 +00:00
Mark Fogle a3d46c72b8 feat(react-core): unify A2UI generation lifecycle into the surface renderer (OSS-162)
The pre-paint A2UI experience was split across three uncoordinated render
paths: a per-tool-call skeleton (render_a2ui), the a2ui-surface activity, and a
separate a2ui_recovery activity. That caused a duplicate "Building interface…"
skeleton (one per tool call / retry) and a skeleton that lingered after the
surface painted, and left retry/failure UI floating beside the loader.

Collapse the whole lifecycle onto the a2ui-surface activity as the single
owner, swapped in place on one stable messageId:
  building -> retrying -> failed -> (painted card)

- New A2UIRecoveryStates.tsx: shared building/retrying/failed subcomponents +
  the animated skeleton (ported from the retired tool-call renderer) + the
  threshold-gated retry label + debugExposure resolution.
- A2UIMessageRenderer now branches: a2ui_operations present -> paint surfaces;
  else status failed/retrying/building. Recovery options (showAfterMs,
  showAfterAttempts, debugExposure) flow in via `a2ui.recovery`. Server-stamped
  content.debugExposure still wins. Lifecycle metadata lives on the AG-UI
  activity-content wrapper, never inside an A2UI envelope (op elements stay
  {version, <one op>}, per v0.9).
- Retire the render_a2ui tool-call skeleton: it now renders nothing (still
  registered, so raw args are suppressed). Kills the duplication at the root.
- Drop createA2UIRecoveryRenderer + the separate a2ui_recovery registration;
  the surface renderer owns it. Tests moved to A2UIRecoveryStates.test.tsx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 21:45:49 +00:00
Austin Merrick 809eb8e058 fix(ci): remove Claude settings and MCP config from checked-out PR code before running Claude (#4975)
## Summary

- Removes three project-level Claude Code config files from the
checked-out PR code immediately after checkout, before any other step
runs
- Closes three pre-model-load code execution vectors that a malicious PR
could exploit when a maintainer triggers the social copy generator

## What's removed and why

| File | Vector |
|------|--------|
| `.claude/settings.json` | `SessionStart` hooks execute as shell
commands before the model loads |
| `.claude/settings.local.json` | Same hook vector — gitignored but can
be force-committed to a branch |
| `.mcp.json` | MCP servers are launched as subprocesses before the
model loads in non-`--bare` mode |

All three fire before the model processes any prompt, so
`--allowedTools` restrictions don't protect against them.

## Context

The social copy generator checks out the PR's HEAD SHA and then runs
`claude -p` with `ANTHROPIC_API_KEY` in scope. An existing write-access
permission gate (a maintainer must manually check a checkbox to trigger
generation) limits who can pull the trigger — but doesn't prevent a
social-engineering attack where a seemingly legitimate PR contains a
malicious config file.

The step is placed immediately after `actions/checkout` so nothing in
the checked-out workspace can influence Claude Code before the
sanitization runs.

## Test plan

- [ ] Trigger the social copy generator on a normal PR and confirm it
still produces output
2026-06-04 14:08:22 -07:00
Max Korp 355418edd4 fix(runtime): drop spurious "agents" license warning on agent run (#5251)
The v2 `agent/run` handler
(`packages/runtime/src/v2/runtime/handlers/handle-run.ts`) logged:

```
[CopilotKit Runtime] Warning: "agents" feature is not licensed. Visit copilotkit.ai/pricing
```

on **every** agent run whenever a `licenseChecker` was present.

## Why remove it

- **It can never pass.** `checkFeature("agents")` resolves against
`@copilotkit/license-verifier`, whose license catalog defines no
`"agents"` feature id. `isFeatureEnabled` returns `false` for any
unknown feature before it ever consults the license, so the warning
fires for every customer regardless of plan (free, dev, or enterprise).

## Scope

- Removes only the warning block.
- `runtime.licenseChecker` remains wired (`createLicenseChecker` in
`core/runtime.ts`) and is still consumed by `get-runtime-info` for
license status reporting — so this does not touch any actual
licensing/status behavior.
- No tests asserted this warning.
2026-06-04 13:35:29 -07:00
Maximiliano Korp d13f944c3c fix(runtime): drop spurious "agents" license warning on agent run
The agent/run handler logged `[CopilotKit Runtime] Warning: "agents"
feature is not licensed.` on every run whenever a licenseChecker was
present. The check is purely cosmetic (it never gated execution) and
fires for every customer because no license catalog defines an "agents"
feature id, so checkFeature("agents") can never return true. This
removes the misleading warning. The licenseChecker remains wired and is
still consumed by get-runtime-info for status reporting.
2026-06-04 13:29:25 -07:00
Benjamin Taylor e2cb8e3d1c Merge remote-tracking branch 'origin/main' into ben1/intelligence-threads-examples-rollout
# Conflicts:
#	examples/integrations/crewai-crews/package-lock.json
#	examples/integrations/crewai-crews/package.json
2026-06-04 15:27:53 -05:00
Jordan Ritter 64fb3432fe fix(examples/integrations/crewai-crews): pin Next to 16.2.7
The smoke Dockerfile previously relied on a floating `npm install
next@latest` to upgrade crewai-crews from its pinned Next ^15.5.15 to
Next 16. PR #5250 removed that floating line for all starters, which was
correct for the other five but broke crewai-crews: Next 15 cannot
compile @copilotkit/react-core's `export *` re-exports, so the app build
failed.

Pin `next` to 16.2.7 (current latest, the patched build that compiles
react-core and is free of the 16.0.x security advisory) instead of
restoring the floating dependency. Locally, a clean no-cache
docker-compose smoke build compiles, boots, and passes all 4 starter
smoke tests.
2026-06-04 13:08:37 -07:00
Jordan Ritter fce4a83d1f fix(examples): remove floating next@latest from starter smoke Dockerfiles
The smoke-test app Dockerfiles ran `RUN npm install next@latest` right after
installing the pinned deps from package.json. This overrode the deliberate
`next` pin with a floating version (non-deterministic builds) and added a
flaky network round-trip that broke the agno smoke build with ECONNRESET on
2026-06-04 (run 26972381969). Every affected starter already pins `next` in
package.json (agno 16.0.7, adk 16.1.1, crewai ^15.5.15, llamaindex 16.0.8,
ms-agent-framework-python 16.0.8, pydantic-ai 16.0.7), so the extra install
is pure harm. Removing it makes builds deterministic and removes the network
fragility.
2026-06-04 13:08:37 -07:00
Jordan Ritter 293b981464 fix(ci): render real newlines in showcase build & validate Slack alerts
GitHub Actions expression string literals don't interpret `\n`, so
`toJSON(format('...\n...'))` emits literal `\\n` and Slack renders the
two characters backslash-n instead of a line break. Inject real newlines
via a `fromJSON('"\n"')` placeholder, matching the starter-smoke fix.

Fixes the "all builds failed" and "Showcase Build Failed" alerts in
showcase_build.yml and the multi-line "showcase_validate failed" alert
in showcase_validate.yml. showcase_promote.yml already used the
fromJSON placeholder; the single-line validate alert has no newlines
and was left untouched.
2026-06-04 12:44:51 -07:00
Jordan Ritter 6dc92e2822 fix(ci): render real newlines in starter smoke Slack alert
The starter smoke failure alert built its message with literal `\n`
inside a GitHub Actions `format()` call. GHA expression string literals
do not interpret `\n` as an escape, so `format()` emitted the two
characters backslash+n, which `toJSON()` then encoded as `\\n` — Slack
rendered a literal "\n" and the triple-backtick fence as plain text
instead of a line break and a code block.

Inject real newlines via `fromJSON('"\n"')` so `toJSON` encodes them as
a single `\n` Slack honors, and place the code-fence delimiters on their
own lines so the failure summary renders as a proper code block.
2026-06-04 12:44:51 -07:00
github-actions[bot] 5b2852c5b5 style: auto-fix formatting 2026-06-04 12:23:05 -07:00
Jordan Ritter 3c138ec450 ci(showcase): build & push the PocketBase image from main
PocketBase had no CI build path: `ghcr.io/copilotkit/showcase-pocketbase`
was a stale April `:latest`, and there was no way to ship pb_migrations /
pb_hooks changes without an ad-hoc manual build. Add a `pocketbase` slot to
showcase_build.yml's build matrix, mirroring the harness/aimock entries:
  - dispatch_name `showcase-pocketbase`, context `showcase/pocketbase`, its
    own Dockerfile, health `/api/health`, railway_id from the SSOT.
  - a paths-filter key gated to `showcase/pocketbase/**` so the slot only
    rebuilds when PB's own files change (the image is self-contained — no
    shared-module copy), not on every showcase push.
  - the workflow_dispatch service choice so PB is human-targetable.

Flip the SSOT entry (railway-envs.ts) to `ciBuilt: true` with
`dispatchName: "showcase-pocketbase"` so it is built+pushed (`:sha` +
`:latest`) and joins the default staging-redeploy scope; the build's
redeploy step only touches the matrix-intersect-success set, so PB still
only redeploys when its own files change. Regenerate
railway-envs.generated.json and the showcase_promote.yml service dropdown,
and update the SSOT/redeploy tests that pinned PB as out-of-band
(CI_BUILT_SERVICES 25 -> 26; webhooks stays the only non-CI-built service).
2026-06-04 12:23:05 -07:00
Jordan Ritter 928793c07b fix(showcase/pocketbase): make image bootable on an existing staging volume
A PB image freshly built from main crash-loops staging PocketBase (502s)
because of two latent defects, both verified by booting the built image
against a real PB 0.22.21 binary on a volume that already has the
collections but has NOT recorded their migrations in `_migrations`.

1. Hook API. `pb_hooks/main.pb.js` registered its CORS middleware via the
   bare global `onBeforeServe(...)`, which is undefined in PB 0.22.x JSVM
   (only the `$app.onBeforeServe()` Go method exists) — it throws
   `ReferenceError: onBeforeServe is not defined` at hook load and crashes
   the server. Switch to the documented global `routerUse((next) => (c) =>
   …)` entry point. Separately, the per-request closure runs in PB's pooled
   goja runtime where top-level helpers/consts are out of scope, so calling
   them throws per request and the router returns HTTP 400 on EVERY route;
   inline the entire allowlist/env/match logic into the closure to fix that
   second regression. Verified: health 200, collection reads 200, the
   allowlisted origin is echoed on `Access-Control-Allow-Origin`, a
   non-allowlisted origin is not, and OPTIONS preflight returns 204.

2. Migration idempotency. `1777700000_create_baseline.js` and the three
   original `1745193*` creators (status, status_history, alert_state) called
   `saveCollection(new Collection(...))` unconditionally, so on a volume
   where the collection already exists they throw
   `UNIQUE constraint failed: _collections.name`, aborting the ENTIRE
   migration chain before later migrations (resource_snapshots, future fleet
   collections) can run. Guard each with the proven find-or-skip pattern
   already used by probe_runs / resource_snapshots, and harden their down
   arms to tolerate an already-absent collection. Verified end to end:
   deleting those migrations' `_migrations` rows while leaving the
   collections in place (the exact staging state), then rebooting the built
   image — boots healthy, re-records the migrations cleanly with no UNIQUE
   abort and no duplicate collections, and a brand-new collection migration
   still applies through the now-clean chain (the pool-fleet path).
2026-06-04 12:23:05 -07:00
Ran Shem Tov f64bba25e4 chore(showcase): move canonical @copilotkit version to 1.59.4
Bump canonicalCopilotKitVersion 1.59.2 -> 1.59.4 and pin every
integration's @copilotkit/* to 1.59.4 (locks regenerated). Keeps the
whole showcase on one version instead of letting the langgraph A2UI
demos deviate. Existing per-slug overrides (built-in-agent pkg.pr.new,
ms-agent-harness-dotnet 1.57.2) unchanged.
2026-06-04 20:50:18 +02:00
Mark c8094de0e5 Merge branch 'main' into mark/oss-162-a2ui-recovery-client-ux 2026-06-04 11:41:42 -07:00
Mark Fogle dce8fe85cc feat(react-core): honor server-stamped debugExposure on recovery activity (OSS-162)
The A2UI middleware now stamps recovery.debugExposure onto every a2ui_recovery
activity, so the server (covering Python and TS agents alike, since the middleware
is the single emitter) can drive how much retry/error detail the renderer surfaces.

Resolve debugExposure per-activity inside render() with precedence
content > client option > "collapsed" default, and declare it on
RecoveryContentSchema. Adds a test asserting the server value wins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 18:37:14 +00:00
Ran Shem Tov 2d733d0094 docs(a2ui): rewrite dynamic-schema for the middleware flow
Drop the hand-rolled render_a2ui/generate_a2ui + a2ui_prompt framing.
Document the two real paths: prebuilt agent (add CopilotKitMiddleware)
and graph agent (wire get_a2ui_tools). injectA2UITool stays the single
on/off switch. Fixes langgraph + deepagents + the generic page;
corrects the streamed op names (createSurface/updateComponents/
updateDataModel).
2026-06-04 20:31:32 +02:00
Ran Shem Tov 57f1f99faa chore(showcase): pin langgraph integrations to stable releases
copilotkit 0.1.94a3->0.1.94 (py), @copilotkit/* 1.59.2->1.59.4 +
sdk-js alpha.3->1.59.4 (ts). Drop the @ag-ui/langgraph override —
runtime 1.59.4 now carries @ag-ui/a2ui-middleware 0.0.6 (the
injectA2UITool forward) + @ag-ui/langgraph 0.0.37. Locks regenerated.
2026-06-04 20:25:25 +02:00
Ran Shemtov d59a035656 chore: release python sdk 0.1.94 (#5244) 2026-06-04 19:41:15 +02:00
Ran Shemtov 4b6904d1d3 Merge branch 'main' into chore/release-python-sdk 2026-06-04 19:40:31 +02:00
Ran Shem Tov 2b5d2e0113 chore: release python sdk 0.1.94 2026-06-04 19:39:44 +02:00
Jordan Ritter 9e7c2cd1e6 fix(showcase): harden promote rollback, env-diff, verify-prod & deploy-poll (#5241)
## Summary

Hardens a set of pre-existing `showcase` promote/`bin/railway` bugs
surfaced during review of the GHCR bearer fix (#5239) and the
#team-showcase notification (#5240). Each is an independent, real
defect; all changes are covered by tests (Ruby `bin/spec` **127 runs / 0
failures**, TS `verify-deploy` drivers **82 passing**, `actionlint`
clean).

## Fixes

1. **`rollback` could roll back to the wrong deployment.**
`find_previous_deployment` selected the second-newest SUCCESS from an
*unsorted* GraphQL result, and assumed the head deploy was always
SUCCESS — so when the latest deploy FAILED/CRASHED (the exact case
rollback is for) it rolled back one good deploy too far. Now sorts by
`createdAt` desc, selects the newest SUCCESS strictly older than the
current head (`sorted.drop(1).find { SUCCESS }`), and **fails loud**
(rather than silently mis-rolling) when the `first: N` window is
saturated with no valid target — telling the operator to pass `--to`.
2. **`env-diff` was dishonest.** It advertised custom-domain comparison
it never performed, and exposed a `--ignore-env-scoped` flag that was
parsed but never read. Now actually diffs `custom_domains` (the snapshot
already carried them), removes the dead flag/helper, and nil-guards
**every** accessor in `diff_services` (`services`, `env_keys`,
`custom_domains`) consistent with the rest of the file.
3. **`verify-prod` could vacuously pass.** Its empty-`succeeded_csv`
branch `exit 0`'d unconditionally. Now fails loud if `promote` reported
success but produced no succeeded set (contract violation), while still
skipping cleanly when promote genuinely failed.
4. **`verify-prod` raced the prod rollout.** It failed instantly when
the just-promoted deploy was still `DEPLOYING` (observed live: promote
succeeded, verify-prod failed ~17s later mid-rollout). `verify-deploy`
now polls in-progress statuses
(`DEPLOYING`/`BUILDING`/`INITIALIZING`/`WAITING`/`QUEUED`/`NEEDS_APPROVAL`)
until terminal (~150s budget), still failing fast on
`FAILED`/`CRASHED`/`REMOVED`.
5. **`npx tsx` ran from the wrong cwd** in the verify jobs (deps
installed in `showcase/scripts`, invoked from repo root → could fetch
`tsx` from the network). Now runs with `working-directory:
showcase/scripts`, matching the resolve/promote jobs.
6. **Slack payloads rendered literal `\n`.** Both promote Slack posts
used `toJSON(format('...\n...'))`, where the literal `\n` survives as
backslash-n (verified live in #team-showcase). Now uses the
`fromJSON('"\n"')` idiom for real line breaks.

## Test plan
- [x] `showcase/bin/spec` — 127 runs, 0 failures (new: rollback
head-FAILED + saturated-window, env-diff custom-domain + nil-guard
cases)
- [x] `showcase/scripts` `tsc --noEmit` clean; `verify-deploy` driver
tests 82 passing (in-progress→SUCCESS, →timeout, fast-fail-on-terminal)
- [x] `actionlint` clean
- [ ] CI green

## Out of scope (separate follow-up)
Review surfaced further pre-existing items intentionally NOT fixed here
(no diff overlap): `run_staging_probe`'s `IO.popen` nests its options
hash inside the argv array (stderr redirect verified working; the
`child_env` hash isn't applied but the probe inherits the parent env in
CI); `image_shape`/`parse_image_ref`/`PinCommand` colon-splitting for
registry-port refs (latent — portless `ghcr.io` only); the deeper
`DEPLOYMENTS_QUERY first:10` truncation beyond the new fail-loud guard;
`succeeded_csv` integrity under a 20-min promote-job timeout; and a few
comment/test-coverage nits.
2026-06-04 10:39:27 -07:00
Ran Shemtov 852cb293a2 chore: release monorepo v1.59.4 (#5243)
## Release monorepo v1.59.4

**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.59.4`
   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.59.4`
   - Creates git tag `monorepo/v1.59.4`
   - 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.
v1.59.4
2026-06-04 19:37:19 +02:00
ranst91 47fcb30d0f chore: release monorepo v1.59.4 2026-06-04 17:26:49 +00:00
Markus Ecker 804b2e2475 feat: useRecordUserAction hook + runtime wiring (CPK-7587) (#4839)
## Summary

Three-tier wiring on the CopilotKit side, mirroring `useThreads`, to
surface user UI signals into CopilotKit Intelligence's self-learning
loop. Companion change in `CopilotKit/Intelligence` (PR #192) lands the
connector + schema.

- **Runtime client** — `CopilotKitIntelligence.recordUserAction(...)`
hits the idempotent platform endpoint
`${apiUrl}/connector/user-actions/record/:clientEventId`. Auth via the
deployment-level Intel API key (Bearer); the Intel key never reaches the
browser.
- **Runtime handler** — `handleRecordUserAction` resolves the Intel user
via `resolveIntelligenceUser`, forwards to the platform client, returns
`{ id, duplicate }`.
- **Fetch router** — `POST /user-actions` wired in
(`user-actions/record` `RouteInfo` variant + dispatch case).
- **React hook** — `useRecordUserAction()` and
`useRecordUserActionInCurrentThread()` in `@copilotkit/react-core/v2`.
Auto-generates a UUID `clientEventId` per call so retries are idempotent
by default. Throws when `runtimeUrl` is absent.

Linear: CPK-7587

## Test plan

- [ ] CI green on this PR
- [ ] Companion Intelligence PR #192 merged or coordinated

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-04 19:23:32 +02:00
Ran Shemtov 7d537fa98b feat(sdk): auto-inject A2UI tool in CopilotKitMiddleware (#5161)
Prebuilt agents get dynamic A2UI with no extra wiring — adding the
middleware is enough. When the frontend registers an A2UI catalog
(surfaced by the runtime into state["ag-ui"].a2ui_schema), the
middleware infers the agent's own model, advertises the generate_a2ui
tool in the model-call hook, and executes it in the tool-call hook. No
catalog → the tool is never advertised.

Covers both @copilotkit/sdk-js and the copilotkit Python SDK. Bumps the
A2UI tool-factory dependency to where get_a2ui_tools ships
(@ag-ui/langgraph 0.0.35, ag-ui-langgraph >=0.0.37).
2026-06-04 19:17:04 +02:00
Ran Shemtov 37577a20c1 Merge branch 'main' into feat/copilotkit-middleware-auto-a2ui 2026-06-04 19:16:50 +02:00