Commit Graph

12629 Commits

Author SHA1 Message Date
Jordan Ritter 41ca3855c8 fix(harness): gate producer ticks on per-family pending backlog
Producers enqueued a fresh batch every scheduled tick regardless of
whether the family's previous batch had even been claimed — against 2
serial browser workers the queue compounded without bound (staging:
3,734 pending), feeding the claim-page starvation.

A scheduled tick now skips its family's batch when that family already
has pending (unclaimed) jobs, bounding the per-family backlog to one
batch, with a structured fleet.producer.skipped-for-backlog log
(family, pendingCount, skippedJobs) and a skippedForBacklog count on
TickResult. The check is per family, fails OPEN on a count blip (a PB
read failure must never stop production), and is BYPASSED by
operator-triggered ticks (explicit intent wins; the trigger CLI treats
0 enqueued as failure). Backed by a new
FleetQueueClient.countPendingForFamily (server-side totalItems count of
a family's pending rows).
2026-06-11 20:36:44 -07:00
Jordan Ritter 67da8ea245 fix(harness): family-fair claimNext so backlogged families cannot starve low-frequency jobs
claimNext listed ONE global oldest-50 pending page; with the d4+d5
producers ticking every 15min against 2 serial browser workers, a
persistent backlog permanently saturated that page and e2e-demos jobs
never entered the candidate set (prod: all 18 e2e-demos jobs pending
forever; staging: 3,734 pending, oldest 22h).

claimNext now discovers the distinct families present in pending
(oldest first, one perPage=1 query per family) and tries them in
round-robin rotation across calls, listing a per-family candidate page
for each. Every discovered family is attempted before giving up, so no
family starves while any of its jobs are claimable. The S0 CAS
exactly-one-winner semantics and the per-page anti-herd shuffle are
unchanged; only candidate SELECTION changed.
2026-06-11 20:36:44 -07:00
Jordan Ritter 10d3939a8e fix(showcase/shell): runtime-derived backend URLs, docs-host redirects, and middleware/builder hardening (SU) (#5401)
## Summary

End-to-end hardening of the showcase shell's URL plane:

- Carries `backendHostPattern` + `docsHost` in the shell runtime config
(no longer baked from `registry.json` at Docker build time). Derives
demo backend URLs at runtime from the pattern, so a new pattern via env
reconfigures every integration on the next deploy without a registry
rebuild.
- Issues docs-host 301/308 redirects from middleware with a runtime
`DOCS_HOST`; misconfigured values no longer 500 every docs route — they
fall back to a sentinel that disables the docs-redirect step.
- Hardens the redirect table builder + matcher: first-match-wins for
duplicate exact sources, deduped wildcard prefixes with warn, malformed
entries rejected at lookup-build time, case-insensitive matching parity,
trailing-slash normalization, structural `/integrations` namespace guard
above the docs-host redirect (closes R15/R17 hijack class).
- Hardens runtime-config + backend-url env readers:
scheme/whitespace/control-char normalization, query/fragment/userinfo
rejection on `DOCS_HOST` / `POSTHOG_HOST` / backend-host pattern /
local-override URLs, present-but-empty `posthogKey` rejection, prod
loopback `BASE_URL`/`DOCS_HOST` rejection (no silent `http://` prepend),
once-guarded FATAL logging (no per-request spam).
- Brings the build-time twin in `showcase/scripts/generate-registry.ts`
to parity with the runtime normalizer (scheme/trailing-slash strip,
degenerate fallback, `NEXT_PUBLIC` fallback, slug validation).
- Surfaces PostHog capture failures once per failure class; keeps
capture alive across the redirect via `event.waitUntil`; missing
`POSTHOG_KEY` is `console.error` in production and surfaces at
config-resolution time (not first redirect).
- Open-redirect hardening on `/shared//evil.com` (SU-18); `//` rejected
at both source and destination; root `/` exact-source and `/:path*`
wildcard sources rejected; non-printable-ASCII source/destination
rejected.

Stream: SU (shell-runtime-urls). Subject groups
SU-2/8/11/13/14/15/16/17/18/19/20 (initial), SU2-A/B (env-hardening),
CR2-C (test infra), SU5-A1..A7 (registry/builder/lint/matcher boundary),
SU6-A1..A6 (request-time normalization parity), SU6-B1..B7
(parsed-normalized return forms, SHOWCASE_LOCAL states, generator
`{slug}` validation), SU7-F1..F3 (final-round backend-pattern + POSTHOG
+ table + script-side parity).

## Test plan

- [x] `pnpm test` in `showcase/shell` — 7 files, 235/235 pass
- [x] `pnpm test` in `showcase/scripts` — 51 files, 1857/1857 pass (one
pre-existing flake in `generate-registry.test.ts` unrelated to this
diff; passes on subsequent runs, classic vitest fork-reuse cross-file
pollution)
- [x] `pnpm exec tsc --noEmit` in `showcase/shell` — clean
- [x] `oxlint` on every changed file — 0 warnings, 0 errors
- [x] `oxfmt --check` on every changed file — clean
- [x] `pnpm build` in `showcase/shell` (full Next 15.x build with
registry+demo-content+starter-content+search-index generation) — clean
- [ ] CI green on the PR — confirm via `gh pr checks` after push
2026-06-11 20:34:46 -07:00
Jordan Ritter 38eeebe11e feat(showcase): writer-identity namespacing on status writes (#5384)
## Summary

Anti-dual-writer defense for the showcase `status` collection — the
flap-comb incident class where the legacy monolith scheduler and the
fleet writer fight over the same rows.

- **Writer identity columns**: new `written_by` / `state_written_at`
columns on `status` (two PB migrations, idempotency-symmetric up/down
paths). Every write stamps a stable host-derived writer identity; the
legacy orchestrator wires `writtenBy: "legacy"` explicitly.
- **Flip / foreign-write detection**: the status writer detects
cross-writer state flips inside a validated window and warns
(TTL-deduped re-warns so sustained fighting stays visible; one-time warn
when the self-write memory cap starts evicting; same-identity replica
hint).
- **PB-safe date normalization**: `observedAt` is normalized to RFC-3339
PB-safe shapes before any date-field write (zone-less shapes, colonless
offsets rejected) — no PB 400 unlatch-retry hot loops.
- **Aggregator honesty**: padded/blank projected keys normalized or
skipped loudly; explicit outcome discriminators replace ambiguous
asserts (no consumer hot-loop); `droppedCommError` surfaced whenever a
comm error misses the aggregate row; trusted-negative duplicate handling
scoped to cell-vs-cell so no cell can impersonate an aggregate row.
- **CLI persistence honesty**: thrown driver errors are persisted to PB
in the `runDriverInputs` catch; the summary carries `WriteOutcome`
discriminators (dropped-write counts, correct pluralization); writer
error classification documented honestly (401 vs 403 split, new
`pb_not_found` reason).
- **Alert/fixture truthfulness**: the alert engine's synthesized cron
outcome is stamped `persisted: false`; alert/orchestrator/probe test
fixtures align with the real `StatusWriter` / `OverlayWriteOutcome`
contracts, with fail-loud fake-PB fixtures hardened against silent
divergence from real PocketBase.

Hardened over 10 CR rounds (~60 reviewer reports), converged to zero
findings.

## Test plan

- [x] Full harness vitest suite: 124 test files / 2378 tests passing
- [x] `tsc --noEmit` and build typecheck (`tsconfig.build.json`) clean
- [x] oxfmt clean on all touched files; oxlint 0 errors
- [x] Known flake note: `probe-invoker.test.ts` wall-clock assertion
(elapsed 101ms vs <100ms bound) fired once under full-suite load and
passes in isolation (67/67) — pre-existing timing sensitivity, unrelated
to this diff
2026-06-11 20:34:41 -07:00
GeneralJerel ceb4b48979 feat(showcase): sequence welcome chips for the self-learning demo arc
Rewire the before-first-message suggestion pills to drive the FOR-137
self-learning story: (1) the teachable over-limit ask, (2) surface the pending
charges so the officer can demonstrate the unlock, (3) recall on a different
over-limit charge on a fresh thread. Titles stay symptom-only so they do not
hint at the exception path the agent is meant to learn on its own.
2026-06-11 19:12:54 -07:00
GeneralJerel f04d9e992a fix(showcase): pass deps to HITL tools so their render uses loaded data
The banking demo's human-in-the-loop tools registered their render in a
mount-keyed effect (useFrontendTool), so without a deps array the render
closure froze on the EMPTY initial cards/policies/transactions. Those arrays
load async after mount, so the registered render kept filtering empty data:
showAndApproveTransactions painted a card with no rows (the agent-driven
approve flow appeared to do nothing), and assignPolicyToCard / setCardPin /
addNoteToTransaction showed raw ids instead of the resolved card/transaction.

Pass the data each render reads as the useHumanInTheLoop deps so it
re-registers when that data loads, mirroring the existing selectCard and
showTransactions (useComponent) deps. addNewCard / openPolicyException /
finalizePolicyException render their args only, so they are left as-is.

Verified against unmodified workspace react-core: the agent-driven approval
card now renders the Google Ads charge with its over-limit badge and the
file-exception action instead of a blank card.
2026-06-11 19:12:53 -07:00
Tyler Slaton 3a5a1a993d docs: add gated Microsoft Teams docs (#5403) 2026-06-11 18:26:17 -07:00
Tyler Slaton fd4c1cadc3 docs: add gated Microsoft Teams docs 2026-06-11 17:12:52 -07:00
Jordan Ritter 7f9b63b069 fix(showcase/shell): clamp profile-client file-list when collapsed 2026-06-11 16:15:13 -07:00
Austin Merrick 932bd73036 docs(skills): complete v2 API migration across CopilotKit skills (#5394)
## What

Completes the v2 API migration across the CopilotKit agent skills,
extending #5345 (which started it for `copilotkit-setup`). Docs only, no
runtime code changed.

## Why

The journey skills a new user reaches for were still teaching pre-v2
APIs, so copy-pasting their examples failed before anything ran:

- `copilotkit-develop` and `copilotkit-integrations` imported from
`@copilotkit/react`, which does not exist (the package is
`@copilotkit/react-core`, v2 surface at `/v2`).
- `copilotkit-setup` assets imported the phantom `@copilotkit/agent`
package and a non-existent `@copilotkit/runtime/express` subpath.
- `copilotkit-integrations` used the v1 route and an uncompilable
`useAgent` shape.
- The recommended multi-route provider snippet omitted
`useSingleEndpoint={false}`, so the chat rendered but never connected
(404).

## Changes

| Skill | Migration |
|-------|-----------|
| `copilotkit-setup` | assets + refs to `@copilotkit/runtime/v2` (and
`/v2/express`), `createCopilotHonoHandler` /
`createCopilotExpressHandler`, `@copilotkit/react-core/v2`; transport
fix (`useSingleEndpoint={false}`); PATCH/DELETE route exports |
| `copilotkit-develop` | hooks and components to `react-core/v2`,
runtime to `/v2`, `useThreads` signature, complete route example |
| `copilotkit-integrations` | `CopilotKit` provider, v2 catch-all Hono
route, per-framework agent classes matched to the shipped
`examples/integrations/*` |
| `runtime` skill | LangGraph to `@copilotkit/runtime/langgraph`, Agno
to `HttpAgent` from `@ag-ui/client` |
| `react-core` skill | `defaultOpen`, `onSubmitMessage`, headless
`CopilotChatView` render prop |

Standardized on the non-deprecated `createCopilotHonoHandler` /
`createCopilotExpressHandler` factories (matching #5345).

## Validation

- Reviewed across 5 unbiased review rounds (7 agents per round); the
final round found zero actionable findings in the changed code.
- Functional build test against the published `@copilotkit/*@1.60.0`
packages: `npm install` plus `tsc --noEmit` pass with zero errors, and
every `/v2` subpath and imported symbol resolves.

## Out of scope (tracked separately)

Pre-existing issues in files this PR did not change: integration example
Python bodies, `runtime`-skill citation paths into the retired `docs/`
tree, reference completeness gaps, `showDevConsole` doc accuracy, the
`copilotkit-upgrade` skill, the `publicApiKey` vs `publicLicenseKey`
source-of-truth decision, and skill eval modernization.
2026-06-11 15:09:27 -07:00
Austin Merrick 1ec63986ec chore(skills): sync plugin version to 1.60.0
Match the plugin and marketplace metadata to the released runtime 1.60.0
via sync:plugin-skills, clearing the check:plugin-skills version-drift gate.
2026-06-11 14:43:50 -07:00
Austin Merrick de9d46d1df docs(skills): migrate CopilotKit skills to the v2 API
Bring the agent skills in line with the shipped v2 API so their examples
install, compile, and connect. Extends #5345 (which migrated the
copilotkit-setup SKILL.md body) to the rest of the skills.

- Imports: drop the nonexistent @copilotkit/react and @copilotkit/agent
  packages and the bare @copilotkit/runtime/express subpath; use
  @copilotkit/react-core/v2 and @copilotkit/runtime/v2 (+ /v2/express),
  and createCopilotHonoHandler / createCopilotExpressHandler rather than
  the deprecated createCopilotEndpoint aliases.
- Provider: CopilotKit from @copilotkit/react-core/v2 with
  useSingleEndpoint={false} on multi-route setups (the v1-compat bridge
  defaults to single transport and would 404 a multi-route backend).
- Routes: v2 catch-all Hono handler exporting GET/POST/PATCH/DELETE via
  handle() from hono/vercel, replacing the v1
  copilotRuntimeNextJSAppRouterEndpoint + ExperimentalEmptyAdapter.
- Integrations: per-framework agent classes matched to the shipped
  examples (LangGraphAgent/LangGraphHttpAgent from @copilotkit/runtime/
  langgraph, CrewAIAgent, MastraAgent, LlamaIndexAgent, HttpAgent from
  @ag-ui/client; Agno via HttpAgent, not @ag-ui/agno).
- Hooks/props: correct useAgent, useThreads, useRenderTool, identifyUser,
  and the chat-component props (defaultOpen, onSubmitMessage, the headless
  CopilotChatView render prop).

Validated across review rounds and a build test against the published
@copilotkit/*@1.60.0 packages (tsc passes, every /v2 subpath resolves).
Regenerated the skills/runtime and skills/react-core mirrors.
2026-06-11 14:43:45 -07:00
Jordan Ritter 6dea8ad764 style(showcase): apply oxfmt to SU shell-runtime-urls follow-up files
Pure prettier-style rewrite (line-wrapping, single-line collapses, multi-
line callback indentation). No semantic changes — confirmed via tsc clean,
oxlint clean, vitest 235/235 pass in showcase/shell.

Touched files:
- showcase/scripts/__tests__/generate-registry-pattern.test.ts
- showcase/scripts/generate-registry.ts
- showcase/shell/src/lib/backend-url.ts
- showcase/shell/src/lib/backend-url.test.ts
- showcase/shell/src/lib/docs-redirects.test.ts
- showcase/shell/src/lib/local-backends-env.test.ts
- showcase/shell/src/lib/runtime-config.ts
- showcase/shell/src/lib/runtime-config.test.ts
- showcase/shell/src/lib/runtime-url-wiring.test.ts
- showcase/shell/src/middleware.ts
- showcase/shell/src/middleware.test.ts
- showcase/shell/vitest.global-setup.ts
2026-06-11 14:02:36 -07:00
Jordan Ritter 8e427bbc0a fix(showcase): final-round backend-pattern + POSTHOG + table + script-side parity (SU7-F1/F2/F3)
SU7-F1 — backend host pattern hardening:
- F1.1  Reject bare trailing ?/# in the backend host pattern
- F1.2  Strip internal tab/CR/LF from the backend host pattern
- F1.3  Warn when ignoring an empty-string local backend override
- F1.4  Reject empty-userinfo @ in the backend host pattern authority
- F1.5  Keep __proto__ keys as data in local-backend maps
- F1.6  Commit the local-backends memo key only after the value computes
- F1.7  Trim local backend overrides before validation and name the real
        rejection
- F1.8  Honest FATAL when the pattern host is a stray scheme fragment
- F1.9  Canonicalize the pattern authority for parity with the override
        path
- F1.10 Acknowledge the staging-to-prod fail-open in the pattern fallback
- F1.11 Harden backend-url/local-backends-env test hygiene

SU7-F2 — runtime-config & client-config edge cases:
- F2.1  Branch POSTHOG_HOST rejection reasons (scheme/degenerate/parse-
        failure) instead of the catch-all mislabel
- F2.2  Reject loopback BASE_URL/DOCS_HOST in production instead of the
        silent http:// prepend
- F2.3  Key the DOCS_HOST fallback once-guard on (mode, shellHost, value)
        and mode-prefix all value-only guard keys
- F2.4  Reject a present-but-empty posthogKey in the client config reader
- F2.5  Drop the trailing slash from SSR_PLACEHOLDER_URL for structural
        parity with server values
- F2.6  Attribute the DOCS_HOST slash-strip to readDocsHost itself
- F2.7  Normalize trailing-dot FQDN spellings in the docs self-host loop
        guard (both compare sides)
- F2.8  Harden console spies to capture all log args; pin the full all-env
        config shape; converge SSR simulation on vi.stubGlobal

SU7-F3 — script-side parity, table classification & test isolation:
- F3 #1  Handle a missing reference integration per the error contract
- F3 #2  Port the runtime backend-host-pattern normalization into the
         generator — scheme/trailing-slash strip, degenerate fallback,
         NEXT_PUBLIC fallback
- F3 #3  Treat non-mapping manifest parses (empty/null/scalar/array YAML)
         as validation errors, not TypeErrors
- F3 #4  Label a missing/unreadable constraints.yaml per the stderr+exit(1)
         error contract
- F3 #5  Align atomic-write tmp naming with the test harness straggler-
         sweep convention; guard main() on direct invocation
- F3 #6  Correct the determineCellStatus unshipped docstring; replace
         stale hardcoded cell counts with formulas
- F3 #7  Isolate the pattern suite on a per-suite tmpdir harness; snapshot
         the generator's full write set
- F3 #8  Classify discarded duplicate wildcards as duplicates — hoist the
         owner check above the destination warns
- F3 #9  Reject a root ("/") EXACT seo-redirect source — homepage-hijack
         twin of the root-wildcard guard
- F3 #10 Reject seo-redirect entries with non-printable-ASCII source/
         destination — close the silent-dead-entry class
- F3 #11 Strip trailing slashes in normalizePosthogHost before the scheme
         test
- F3 #12 Message-filter the empty-slug-set error count; pin the single
         matcher entry
2026-06-11 14:01:15 -07:00
Jordan Ritter 4f9f5dba4c fix(showcase/shell): docs-host robustness, builder & matcher hardening (SU2-stragglers + SU5 + SU6-A/B)
Round-by-round CR convergence covering the redirect builder, the middleware
matcher, the docs-host self-loop guard, and the runtime-config env readers.

Highlights:
- Clear module-load warns after fresh middleware import
- Validate SET BASE_URL values (scheme-less/degenerate/garbage) with
  sentinel fallback + once-guarded FATAL log
- Normalize path/query/fragment-bearing DOCS_HOST to origin; reject
  non-http(s) schemes; branch rejection reasons
- Harden POSTHOG_HOST (degenerate-host/scheme rejection); expose
  posthogKey via readEnvPair semantics
- Reject a DOCS_HOST equal to the shell's own host (redirect-loop guard,
  authority compare)
- Warn on missing local-ports.json under SHOWCASE_LOCAL=1 and validate
  TCP port range; extract helper for tests
- backend-url hardening — slug charset guard, frozen local-backends memo,
  pattern path-segment warn, local-override URL validation
- Client config fail-loud covers all four URL fields with type checks
- Make RuntimeConfig.posthogKey optional — absence is a valid state, not
  a wiring bug
- Drop R15/R17 and guard /integrations from SEO redirects
- Dedup duplicate wildcard prefixes with first-match-wins warn
- Validate malformed SEO entries at lookup-build time
- Restore case-insensitive redirect matching parity
- Normalize trailing slashes before redirect matching
- Keep the framework segment on F13, pin MG3 case fix
- Read posthogKey from runtime config in middleware, not raw process.env
- Fall back to the default backend host pattern for degenerate values
- Disable docs redirects when the default fallback collides with the
  shell host
- Bring validateBaseUrl to parity with its sibling readers
- Strip query/fragment from POSTHOG_HOST while keeping reverse-proxy paths
- Restrict local backend overrides to http(s) URLs
- Add server-only guard to runtime-config
- Harden localBackendsEnv failure posture
- Hoist /integrations namespace guard above the docs-host redirect
- Validate seo-redirect sources and cross-kind shadowing in
  buildRedirectLookup
- Unify slash normalization for middleware matching
- Lowercase-normalize REGISTRY_FRAMEWORK_SLUGS at construction
- Escalate missing POSTHOG_KEY to console.error in production
- Skip all redirect steps when docs redirects are disabled (sentinel
  consumer)
- Reject userinfo credentials in DOCS_HOST, POSTHOG_HOST, and the backend
  host pattern
- Branch dev-vs-prod logging in readDocsHost and fatalPatternOnce
- Prepend http:// (not https://) to scheme-less loopback hosts
- Round-5 micro-finding batch across the URL config libs

SU5-A1..A7 — registry safety, // reject, builder lint batch (case-
insensitive :path*, same-destination twin allowlist, original-case
divergence remainder), matcher api boundary, generator+vitest infra, test
hygiene + empty docs-host guard, comment batch.

SU6-A1..A6 — reject miscased :path* tokens, warn on tokenless wildcards,
normalize redirect-destination comparisons like request time, reject
destinations containing "//", surface missing POSTHOG_KEY at config-
resolution time, compile matcher harness like Next's runtime, type
parse/tokensToRegexp in the path-to-regexp shim, keep buildRedirectLookup
JSDoc attached.

SU6-B1..B7 — reject query/fragment/userinfo in pattern and local-override
URL gates, return parsed-normalized URL form from validation success
paths, distinguish unset/blank/padded SHOWCASE_LOCAL states, warn when
SHOWCASE_LOCAL is set to a value other than 1, validate {slug} placeholder
in generate-registry, mirror middleware drop semantics in the wiring
test's registry re-derivation, pin the noStore spy and calls to one fresh
module instance in the Edge-path test.
2026-06-11 14:00:50 -07:00
Jordan Ritter b28a1dc494 fix(showcase/shell): runtime-config + backend-url env-hardening; redirect builder safety (SU2-A/B + CR2-C)
SU2-B series — runtime-config / backend-url env robustness:
- Correct the Edge-safety story in runtime-config (SU2-B1)
- Stop per-request FATAL-CONFIG spam for unset BASE_URL (SU2-B2)
- Prepend https:// to a scheme-less POSTHOG_HOST (SU2-B3)
- Trim whitespace paste artifacts in env values and host patterns (SU2-B4)
- Memoize parseLocalBackends and warn once per value (SU2-B5)
- Make {slug} substitution immune to $-patterns (SU2-B6)
- Harden the client runtime-config reader (SU2-B7)
- runtime-config hardening batch (SU2-B8)
- Validate local-ports.json before baking NEXT_PUBLIC_LOCAL_BACKENDS (SU2-B9)
- test: warn-once assertions retry-safe; stop console leaks (SU2-B10)

CR2-C series — test infrastructure:
- Generate registry.json in a vitest globalSetup (CR2-C1)
- Stop ambient POSTHOG_KEY firing real fetches in middleware tests (CR2-C2)
- Assert the production slug set, not a re-derivation (CR2-C3)
- Make the registry generator subprocess robust (CR2-C4)
- Middleware/wiring test hygiene batch (CR2-C5)

SU2-A series — redirect-layer & PostHog capture:
- Stop $-pattern expansion in wildcard redirect substitution (SU2-A1)
- Surface PostHog capture failures once per failure class (SU2-A2)
- Duplicate exact redirect sources are first-match-wins (SU2-A3)
- Resolve runtime config once per redirected request (SU2-A4)
- Include destination host in seo_redirect capture (SU2-A5)
- Normalize scheme-less POSTHOG_HOST at the capture use site (SU2-A6)
- Correct redirect-layer comments and guard wildcard prefix boundary (SU2-A7)
- Cover docs-host hardening branches, compile matcher via path-to-regexp (SU2-A8)
2026-06-11 14:00:20 -07:00
Jordan Ritter 426ae3a8e1 fix(showcase/shell): SEO redirect table + middleware matcher hardening (SU-2/8/11/14/15/16/17/18/19/20)
Resolve SEO redirect destinations against the docs host (SU-17); forward
the query string on SEO redirects (SU-16); match bare paths on wildcard
SEO sources (SU-19). Collapse duplicate slashes in docs-host redirect
destinations (SU-13). Regression test for /shared//evil.com open redirect
(SU-18). Emit 308 for docs-host redirects to match next.config parity
(SU-2). Add a path boundary to the api matcher exclusion (SU-15). Loud
guard when registry yields zero framework slugs (SU-20). Keep PostHog
capture alive via event.waitUntil (SU-14). Note docs-host redirects are
untracked by design (SU-8). Cover docs-host redirects at the middleware
level (SU-11).

Squash of the SEO-table + matcher-hardening cluster.
2026-06-11 14:00:03 -07:00
Jordan Ritter febd8bc946 feat(showcase/shell): runtime-derived backend URLs and docs-host redirects (SU-13)
Carry backendHostPattern + docsHost in the shell runtime config (no longer
baked from registry.json at Docker build time). Derive demo backend URLs at
runtime from the pattern; issue docs-host 301s from middleware with a runtime
DOCS_HOST so a misconfigured value can no longer 500 every docs route.

Validate NEXT_PUBLIC_LOCAL_BACKENDS and empty overrides; guard the backend
host pattern against silent env misconfigs. Reword the stale demo-page
comment about backend URL derivation. Pin the registry slug set and SSR
placeholder URL composition; fix env/spy/global leaks in runtime-config
test cleanup.

Squash of the initial runtime-URL refactor cluster:
- feat(showcase): carry backendHostPattern + docsHost in shell runtime config
- fix(showcase): derive demo backend URLs at runtime instead of baked registry values
- fix(showcase): issue docs-host 301s from middleware with runtime DOCS_HOST
- fix(showcase): never let a misconfigured DOCS_HOST 500 every docs route
- fix(showcase): guard backend host pattern against silent env misconfigs
- fix(showcase): validate NEXT_PUBLIC_LOCAL_BACKENDS values and empty overrides
- docs(showcase): reword stale demo-page comment about backend URL derivation
- test(showcase): fix env/spy/global leaks in runtime-config test cleanup
- test(showcase): pin registry slug set and SSR placeholder URL composition
2026-06-11 13:59:46 -07:00
Ben Taylor f4df2c36fd chore(examples/integrations): Intelligence 0.5.0 + CopilotKit 1.60.0, drop demo-user provisioning (#5398)
## What

Across the **threads-enabled integration examples**
(`examples/integrations/*`, excluding the vestigial
`langgraph-python-threads`):

1. **Drop demo-user provisioning** — removes the `provision-user`
one-shot service from the shared `_intelligence/docker-compose.yml`.
2. **Bump Intelligence → 0.5.0** —
`ghcr.io/copilotkit/intelligence/composite` `0.2.0` → `0.5.0`.
3. **Bump CopilotKit → 1.60.0** — every `@copilotkit/*` pin
(`react-core`, `react-ui`, `runtime`, `a2ui-renderer`, `sdk-js`)
`1.59.5` → `1.60.0`, with regenerated `package-lock.json` files.

## Why

The `provision-user` service existed to seed `cpki.users` (a bare id
plus a per-project `<projectId>_<userId>` alias) so the runtime's
`demo-user` identity satisfied the `threads_user_id_fkey` constraint.
The **0.5.0 composite provisions thread users on demand**, so the manual
seed is obsolete and can be dropped from the local-dev overlay.

## Scope

18 threads-enabled examples (each renders the `ThreadsDrawer` panel):
a2a-a2ui, a2a-middleware, adk, agent-spec, agentcore, agno,
crewai-crews, crewai-flows, langgraph-fastapi, langgraph-js,
langgraph-python, llamaindex, mastra, mcp-apps,
ms-agent-framework-dotnet, ms-agent-framework-python, pydantic-ai,
strands-python.

`langgraph-python-threads` is intentionally untouched (vestigial, slated
for removal).

## Notes

- The `identifyUser` demo stub in each route handler is **kept** — it
selects the demo identity; provisioning that identity is now the
composite's job.
- `_intelligence/docker-compose.yml` is not parity-tracked;
`@copilotkit` pins are — `pnpm parity:check` passes (0 errors).
- The Intelligence `0.5.0` image + on-demand provisioning is validated
at runtime (needs the image + license token + Docker), not in this PR's
static checks.
2026-06-11 15:48:17 -05:00
Benjamin Taylor 717cfccedb chore(examples/integrations): bump CopilotKit to 1.60.0
Bumps every @copilotkit/* pin (react-core, react-ui, runtime, a2ui-renderer,
sdk-js) from 1.59.5 to 1.60.0 across the threads-enabled integration examples,
and regenerates each package-lock.json to the 1.60.0 dependency closure.
Excludes the vestigial langgraph-python-threads example.
2026-06-11 15:42:25 -05:00
Benjamin Taylor 05cbbae951 chore(examples/integrations): bump Intelligence to 0.5.0, drop demo-user provisioning
Updates the shared `_intelligence` activation overlay to the composite 0.5.0
image and removes the `provision-user` one-shot service. That service seeded
`cpki.users` (a bare id plus a per-project `<projectId>_<userId>` alias) so the
runtime's `demo-user` identity satisfied `threads_user_id_fkey`. The 0.5.0
composite provisions thread users on demand, so the manual seed is obsolete.
2026-06-11 15:42:25 -05:00
Tyler Slaton 570dd39336 feat(shell-docs): gate Slack docs behind early-access password (#5395)
## What does this PR do?

Puts the Slack docs behind a shared early-access password. Gated pages
render blurred and non-interactive with an unlock card floating above
them:

- **`/slack`** — the Slack guide, plus every framework-scoped variant
(`/<framework>/slack`), opted in via an `earlyAccess: slack` frontmatter
flag
- **`/reference/bot/**`** — the entire bot reference section
(`@copilotkit/bot*` packages, the Slack adapter), gated on `version ===
"bot"`

### The unlock card

- **"Slack is in early access"** headline, a short explanation of the
gate and of what CopilotKit for Slack is, and a product screenshot (a
Slack thread with a generative-UI bot reply — stored in **git LFS**,
rendered via `next/image`).
- **"Don't have the password? Reach out to request early access to
Slack"** linking to the [beyond-the-web early-access
form](https://go.copilotkit.ai/beyond-the-web-form).
- Password input + Unlock for folks who already have it.

### How it works

- `early-access-gate.tsx` (client) blurs the page content (`inert`,
unselectable, pointer-events off) and renders the unlock card in a
**sticky scrollport-height frame**, so the card stays centered in view
while the blurred page scrolls underneath — sidebar and top nav stay
crisp and usable. On very short viewports the card caps its height and
scrolls internally.
- `src/lib/early-access.ts` is the gate registry (password, copy, CTA,
image, storage key) shared by server routes and the client component.
Unlocking persists in `localStorage`, so one unlock covers the guide and
all reference pages.
- Ungated pages never mount the client component (server-side
conditional wrappers in `docs-page-view.tsx` and the reference route).
- Light/dark theme via existing tokens; responsive down to mobile (input
row stacks to a full-width button).

### Reviewer notes

- This is a deliberate **soft gate** (early-access friction, not a
security boundary): the password ships in the client bundle, and
raw-MDX/`llms.txt`/search-index routes still expose the content.
- Verified in the running app: scroll-following card, wrong-password
error state, unlock-in-place, cross-page persistence,
mobile/tablet/desktop, dark mode.
- Tests: 6 new vitest cases (config integrity incl. form URL, SSR
locked-state markup, unknown-id pass-through).
Format/lint/typecheck/test/build all green locally.

## Related PRs and Issues

- Gates the docs introduced in #5368 (`docs(shell-docs): Slack platform
quickstart + Bots API reference`)

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked (lets us help iterate on
your PR directly — faster turnaround for everyone)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-11 13:41:11 -07:00
Tyler Slaton a028b5fb91 feat(shell-docs): gate Slack docs behind early-access password
Blur the Slack guide (/slack and its framework-scoped variants) and the
entire bot reference section behind a client-side unlock card. The card
follows the scroll in a sticky scrollport-height frame, persists unlock
state in localStorage, and leaves the sidebar and top nav usable. Doc
pages opt in via earlyAccess frontmatter; the bot reference gates on
version === "bot". Visitors without the password get a product shot
(light/dark variants in git LFS, shown beside the form on wide cards
via container query) and a link to the beyond-the-web early-access
form.
2026-06-11 13:18:11 -07:00
Ben Taylor 71e2682790 chore: release monorepo v1.60.0 (#5390)
## Release monorepo v1.60.0

**Scope:** `monorepo` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.60.0`
   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.60.0`
   - Creates git tag `monorepo/v1.60.0`
   - 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.60.0
2026-06-11 11:40:35 -05:00
MikeRyanDev a6e8000c94 chore: release monorepo v1.60.0 2026-06-11 16:27:00 +00:00
Ben Taylor 8fbc8936f1 refactor(runtime): Update Intelligence API handlers to pass along user IDs as route params (#5389)
## Summary

- Pass the resolved runtime `userId` through Intelligence thread reads
and message-history lookups.
- Include `userId` and `agentId` in Intelligence thread delete requests.
- Update Runtime tests to assert the new REST wire contract.

## Why

The Intelligence REST API now requires explicit app-user ownership for
direct thread reads, message reads, and destructive thread mutations.
Older Runtime code still omitted `userId` on those calls, which breaks
against the updated API even though create/list/connect/lock already
send `userId`.

## Validation

- `pnpm nx run @copilotkit/runtime:test -- --run
src/v2/runtime/intelligence-platform/__tests__/client.test.ts
src/v2/runtime/__tests__/handle-threads.test.ts
src/v2/runtime/__tests__/handle-run.test.ts`
- `git diff --check`

Skipped local package typecheck; it is known to be unreliable locally
and hit Node heap/long-running behavior in this worktree. CI should
provide the final signal.
2026-06-11 11:23:12 -05:00
Mike Ryan 05cb21d325 fix(runtime): pass user ids to intelligence thread reads 2026-06-11 08:27:50 -07:00
Ran Shemtov 7f8c2dcf34 Merge branch 'main' into claude/a2ui-injection-config-9r2ve3 2026-06-11 16:38:10 +02:00
SeoyeonKim 8e440a9e7d fix(react-core): stabilize pin-to-send scrolling 2026-06-11 22:56:07 +09:00
GeneralJerel c310f4142c fix(showcase): present all pending approvals in one HITL call
The model answered 'show me the unapproved transactions' with one
showAndApproveTransactions call per pending transaction (parallel tool
calls). Parallel calls to the same useHumanInTheLoop tool wedge the
render at inProgress, nobody can respond, and the thread is then
poisoned — every later run fails with 'Tool results are missing for
tool calls …'. Make the tool take a comma-separated id list and
instruct the model to call it exactly once; the renderer's existing
string .includes() filter was already written for a combined call.
(An array schema renders an empty tool slot — react-core issue — so
the param stays a string.)

Verified live in OSS mode: single call streams complete args +
RUN_FINISHED, the approval card renders with per-row Approve/Deny,
deny fires the recording vignette (data-recording=true) and POSTs
/annotate; over-limit approve is rejected by the server gate as
designed. In Intelligence mode the BFF /annotate path records 200.
2026-06-11 06:41:29 -07:00
GeneralJerel bd0cf2a21d fix(showcase): neutral framing for the empty permissions deny-list context
The unavailable-actions agent context had an unconditional "the user does
not have permission to perform these actions" description. For Admins the
list is empty, and the model read the menacing description plus "[]" as a
blanket prohibition — refusing showAndApproveTransactions and every other
gated tool even though they were forwarded with the run. Reframe the
description so an empty list explicitly means no restrictions and refusals
are only allowed for listed actions.

Verified live in Intelligence mode: before, the agent answered "you don't
have permission" as Admin; after, it calls showAndApproveTransactions
(wire capture shows the corrected context and the tool call).
2026-06-11 06:13:06 -07:00
Ben Taylor 81ee31dd5a docs(packages): scrub Copilot Cloud / client license-key prop from SDK doc references (#5364)
## Why

Copilot Cloud is no longer promoted, but new users still find it through
stale links and code references — including the SDK's own JSDoc/console
messages. This scrubs the old Copilot Cloud framing **and** the client
`publicLicenseKey`/`publicApiKey` prop references from the SDK doc
surface.

Important distinction this PR is built around: the **client
`publicLicenseKey`/`publicApiKey` prop** is the header→cloud path (being
retired) and is **not** what activates the Intelligence runtime. The
Intelligence runtime license is the **server-side
`COPILOTKIT_LICENSE_TOKEN`** (Ed25519 JWT) → `licenseToken` on
`CopilotRuntime`. So the client prop is not documented here as the
premium/Intelligence enabler.

Follow-up to the link cleanup in #5258. Example-app + server-side
runtime documentation deferred ("Bucket B").

## What changed

Doc-comments / JSDoc / console strings / README prose — **no functional
code, no prop renames, no endpoint/header changes.**

- **Copilot Cloud → removed** from JSDoc/console/README across
react-core, react-ui, runtime, vue, shared, angular.
- **Client license-key prop references removed**, not reframed:
- `publicApiKey`/`publicLicenseKey` docstrings (react-core props + v2
provider) reverted to bare one-liners.
- "Requires a license key" / "premium feature" / `<CopilotKit
publicLicenseKey=…>` example notes dropped from the headless hook,
react-ui observability docs (`Chat`/`Popup`/`Sidebar`/`props`), and
runtime logging/`onError` JSDoc.
- No `npx copilotkit@latest license` guidance attached to client props
(that CLI yields the *server-side* token, not the client prop).
- **Angular**: all `licenseKey` mentions removed from the README — it's
no longer a premium feature (the license watermark is disabled) and the
key isn't needed to function.
- **Defunct features** (`guardrails_c`, `authConfig_c`,
`useCopilotAuthenticatedAction_c`) keep their code but lose their JSDoc
(`@internal Defunct`).

### Incidental (pre-commit lint-fix)

The repo's pre-commit hook auto-applied `import type` conversions on the
touched files (a pre-existing oxlint warning). Type-only, zero runtime
impact.

## Deliberately untouched

`api.cloud.copilotkit.ai` endpoint + `X-CopilotCloud-Public-Api-Key`
header (functional), prop names, gating logic, tests, CHANGELOGs, the
`#5351` skill files, and `CopilotCloudOptions`/`CopilotCloudConfig` type
identifiers.

## Out of scope (deferred — "Bucket B")

- Migrating example apps onto the
Intelligence/`COPILOTKIT_LICENSE_TOKEN` runtime model.
- Documenting the server-side `licenseToken` setup.
- Stale `CopilotCloud` watermark strings in `angular/config.ts`
(watermark is disabled; flagged for a separate cleanup).

## Verification

- `oxfmt --check` on changed files → pass
- `nx run-many build` (no cache) for
`@copilotkit/{shared,react-core,react-ui,runtime,vue}` → success
- `oxlint` on changed files → 0 errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-11 07:43:06 -05:00
Benjamin Taylor 8d68a95bc9 docs(packages): drop client license-key prop references; Angular no longer needs a key
Follow-up correction. The client publicLicenseKey/publicApiKey prop is the
header→cloud path and is NOT what activates the Intelligence runtime (that's
the server-side COPILOTKIT_LICENSE_TOKEN). So:

- Remove the `npx copilotkit@latest license` guidance from all client-prop
  contexts — that CLI yields the server-side license token, not the client
  prop value.
- Revert the client-prop docstrings (copilotkit-props, v2 CopilotKitProvider)
  to bare one-liners; drop the premium/"requires a license key" framing from
  the headless hook, react-ui observability docs, and runtime logging/onError
  JSDoc rather than reframing.
- Angular: remove all `licenseKey` mentions from the README — it is no longer
  a premium feature (the license watermark is disabled) and the key is not
  needed to function.

Server-side license-token documentation remains deferred to the example/runtime
setup pass (Bucket B).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 07:22:37 -05:00
Benjamin Taylor 8956c668bc docs(packages): retire Copilot Cloud framing in SDK doc references, point to the license key
Cloud is no longer promoted; the Intelligence license key is its replacement.
Scrub the old Copilot Cloud system from SDK JSDoc / doc-comments / console
messages / README prose so code references reflect how the license key is
obtained and used, mirroring examples/integrations/*:

- publicApiKey/publicLicenseKey docstrings (react-core props + v2 provider,
  vue legacy types, copilot-context) describe the CopilotKit public license
  key, acquired via `npx copilotkit@latest license` or the dashboard;
  publicApiKey framed as the legacy alias of publicLicenseKey.
- Premium-feature docs (headless hook, react-ui Chat/Popup/Sidebar
  observability, runtime logging/onError) drop "Copilot Cloud"/"requires a
  publicApiKey" wording and the publicApiKey examples in favor of the public
  license key + publicLicenseKey.
- console-styling messages and the angular README point at the license key
  and the `npx copilotkit@latest license` command.

Defunct features (guardrails_c, authConfig_c, useCopilotAuthenticatedAction_c)
keep their code but lose their JSDoc (marked @internal defunct).

Functional surfaces untouched: api.cloud.copilotkit.ai endpoint, the
X-CopilotCloud-Public-Api-Key header, prop names, gating logic, tests,
CHANGELOGs. Example-app migration (Bucket B) deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 07:22:37 -05:00
Ran Shemtov 73e19983b3 Merge remote-tracking branch 'origin/main' into claude/a2ui-injection-config-9r2ve3
# Conflicts:
#	packages/runtime/src/v2/runtime/handlers/get-runtime-info.ts
2026-06-11 12:12:56 +00:00
GeneralJerel 6a7f1187f7 test(showcase): add self-learning smoke script (record, distill, recall)
scripts/self-learning-smoke.mjs proves the banking demo's recording seam
end-to-end against a running Intelligence backend: posts four teaching
actions through the demo BFF /api/copilotkit/annotate (the platform
requires UUID clientEventIds), optionally runs one sl-worker sweep when
INTELLIGENCE_REPO is set, and asserts the distilled vendor policy reads
back through the platform /mcp knowledge tool. Wired as the
test:self-learning package script and documented in the README.

Verified live: PASS 6/6 against Intelligence @ mme/learn-from-user-activity
(records as rows 13-16, sweep editCount=0 steady-state, recall returns the
pre-cleared vendor policy).
2026-06-11 04:54:23 -07:00
Claude 924a78a2a7 fix(runtime): add a2ui enabled opt-out via shared isA2UIEnabled predicate
Route both the run path (agent-utils) and the /info response
(get-runtime-info) through a single isA2UIEnabled() predicate so the two
can no longer disagree on whether a2ui is on (the divergence behind #5369),
and add an optional `enabled` flag to the runtime a2ui config.

Backwards compatible: any existing a2ui config stays enabled; only an
explicit `a2ui: { enabled: false }` turns it off while keeping the rest
of the config (e.g. schema/catalog) in place.

https://claude.ai/code/session_01TYohiEJyhsU3mJS4jabdv6
2026-06-11 11:49:29 +00:00
GeneralJerel 3b06802423 fix(showcase): migrate banking demo lint to eslint cli (next 16 removed next lint)
next lint was removed in Next 16, so the demo's lint script failed before
linting anything. Switch to eslint . with a flat eslint.config.mjs built on
eslint-config-next's native flat exports (same shape as the other Next 16
example apps), and fix the findings the new react-hooks rules surfaced:

- actions.ts / team/actions.ts: wrap mount fetches in an async IIFE so
  set-state-in-effect can see the setState calls are asynchronous
- auth-context: derive currentUser from selection ?? team[0] instead of
  syncing state in an effect
- use-theme: lazy-init theme from localStorage (SSR-guarded) and apply the
  DOM class in an effect keyed on theme; hoist applyTheme to module scope
- threads-drawer: copy timeout maps to locals inside the effect so cleanup
  does not read refs that may have changed
2026-06-11 02:29:32 -07:00
Ran Shemtov e8f9c10dbe fix: respect per-agent A2UI scoping instead of injecting catalog context into every agent's runs (#5383) 2026-06-11 09:54:05 +02:00
Jordan Ritter e9bf2ac9d6 fix(harness): orchestrator writer wiring and alert/probe fixture alignment
Wire the legacy monolith scheduler's status writer with an explicit
writtenBy:"legacy" identity, correct the dual-writer dedupe comments
to describe the real upsert-collapse (and why it is not safe), stamp
the alert engine's synthesized cron outcome persisted:false honestly,
and align alert/orchestrator/probe test fixtures with the real
StatusWriter and OverlayWriteOutcome contracts.
2026-06-10 22:35:48 -07:00
Jordan Ritter d86c4fd2c2 fix(harness): CLI runner/results persistence honesty
Persist thrown driver errors to PB in the runDriverInputs catch,
carry WriteOutcome discriminators through the CLI summary (dropped
write counts with correct pluralization, no duplicate cause
clauses), and pin the runner/results behavior with StatusWriter
contract-typed stubs so writer contract drift is compile-checked
at the stub site.
2026-06-10 22:35:38 -07:00
Jordan Ritter daa122cdad fix(harness): result-aggregator trim/discriminator honesty
Normalize padded projected keys to trimmed canonical form, skip
blank keys loudly, and replace ambiguous outcomes with explicit
discriminators: honest outage-skip/empty-projection semantics,
droppedCommError surfaced whenever the comm error misses the
aggregate row, trusted-negative duplicate preference scoped to
cell-vs-cell (no aggregate-row impersonation), and comm-error
identity asserts converted to discriminators so the consumer
cannot hot-loop.
2026-06-10 22:35:37 -07:00
Jordan Ritter 28d3e76beb test(harness): status-writer writer-identity and hardening coverage
Pin the writer-identity stamping, flip/foreign-write warn paths
(TTL re-warns, self-write memory cap eviction), date normalization
shapes, overlay write outcomes, idempotency latches, and error
classification against fail-loud fake-PB fixtures hardened against
silent divergence from real PocketBase behavior.
2026-06-10 22:35:25 -07:00
Jordan Ritter 0de4843b68 feat(harness): writer-identity namespacing on status writes
Add written_by/state_written_at columns (PB migrations) and stamp every
status write with a stable host-derived writer identity. The status
writer now detects cross-writer state flips and foreign writes (the
anti-dual-writer flap-comb defense), normalizes observedAt to PB-safe
RFC-3339 shapes before date-field writes, and classifies writer errors
honestly (401 auth vs 403 permission split, new pb_not_found reason).
2026-06-10 22:35:16 -07:00
Mark 8ce66524f9 Merge branch 'main' into fix/5369-a2ui-context-scoping 2026-06-10 22:20:50 -07:00
Mark Fogle 326fcc77a8 chore(changeset): drop the a2ui scoping changeset (#5369) 2026-06-11 05:11:08 +00:00
Mark Fogle 66dfa753dd chore(changeset): add changeset for the a2ui context scoping fix (#5369) 2026-06-11 05:07:28 +00:00
Mark Fogle a6deb44926 fix(vue): scope the A2UI catalog context to the runtime's a2ui agents (#5369) 2026-06-11 05:07:14 +00:00
Mark Fogle c036a97efa fix(react-core): scope the A2UI catalog context to the runtime's a2ui agents (#5369) 2026-06-11 05:07:11 +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