Commit Graph

12110 Commits

Author SHA1 Message Date
github-actions[bot] 283b1f8473 style: auto-fix formatting 2026-06-03 11:30:58 -07:00
Jordan Ritter 6d2f5885d2 test(showcase/harness): cover browser-pool crash-recovery, self-heal, and serve-retry paths
- STAGING-OUTAGE regressions: degraded alarm fires (not silent) when the
  set empties from a relaunch storm; self-heal re-inits a fresh set once the
  kernel relaxes; a waiter queued during the dead window is served by
  self-heal; a transient relaunch EAGAIN is retried and the entry survives
  (no eviction, no alarm).
- Bounded serveNextWaiter transient re-drive + FIX#7 dead-vs-alive gate
  propagation to the serve path.
- orchestrator: degraded/recovered signal wiring covered.
- BUG3 (orphan-by-recycle waiter drain) adapted to the crash-recovery
  acquire path: an acquire whose in-flight open is orphaned re-enqueues as a
  waiter; with cap=1 the freed slot goes to the other waiter, so the orphaned
  acquire settles via its own (now bounded) timeout. The invariant it
  verifies (freed capacity immediately serves the queued waiter) is unchanged.
2026-06-03 11:30:58 -07:00
Jordan Ritter 2b3e18bb78 fix(showcase/harness): raise container PID/thread ulimit for the chromium pool
Lift the soft nproc limit to the hard ceiling (`ulimit -u $(ulimit -Hu)`)
before exec'ing the orchestrator so the legitimate 40-context chromium
workload (several hundred OS threads at steady state) has ample thread
headroom instead of running near the default ~1024 soft ceiling, where
`chromium.launch()` tripped `pthread_create: Resource temporarily
unavailable`. `exec` keeps node as PID 1 for correct signal handling; the
`|| true` fallback keeps boot resilient when the runtime forbids raising
the soft limit (the cgroup pids limit then remains the dominant control).
2026-06-03 11:30:58 -07:00
Jordan Ritter 098909992e fix(showcase/harness): harden browser-pool crash recovery, self-heal, and bounded serve retry
Make the long-lived chromium pool survive a pthread/PID-ceiling
(`pthread_create: Resource temporarily unavailable`, errno 11) thread-
exhaustion storm instead of draining to an empty, permanently-wedged set.

- Crash-recovery relaunch backpressure: a transient EAGAIN on relaunch is
  retried with bounded linear backoff before the entry is evicted, so a
  thread-exhaustion window that relaxes within seconds recovers in place
  rather than splicing the entry out of the set.
- Self-heal + degraded/recovered alarm: when the set empties mid-life the
  pool fires an `onDegraded` red alarm (previously only emitted on init()
  failure — mid-life death was silent) and kicks a background self-heal
  loop that relaunches a fresh set the moment a launch succeeds, firing
  `onRecovered`. No manual redeploy required.
- Bounded serveNextWaiter transient re-drive: a persistently-transient
  newContext() on a still-connected browser no longer hot-loops the event
  loop; it self-reschedules up to a ceiling then leaves the waiter queued
  for a later release/recovery handoff (mirrors acquire()'s retry-once
  semantics).
- Accounting hardening: generation-token guard on in-flight opens across a
  recycle, clamped servedContexts rollback on orphan-close, deferred-recycle
  re-check on non-release teardown paths, and waiter-drain on orphan-by-
  recycle rollback so freed capacity is served immediately.
- orchestrator wires the pool's onDegraded/onRecovered hooks to the shared
  `system:browser-pool-degraded` red/green capacity-loss signal.

Fixes the 2026-06-03 staging incident: the browser pool died from thread
exhaustion, the relaunch storm emptied the set, and the harness wedged with
no alarm -> 626 D0-red cells until a manual redeploy.
2026-06-03 11:30:58 -07:00
Austin Merrick 179242cd82 fix(skills): remove internal-only skills from public repo
Removes the three internal-only skills (copilotkit-demo-parity, git-hooks,
showcase-demo-debugging) from .claude/skills/ and .agents/skills/. These are
staff-only and now live in the internal-skills plugin. Removing them at the
source means root skill discovery no longer sweeps internal skills into a
user's install.
2026-06-03 11:26:24 -07:00
Martha Schumann a736b29306 feat(integrations): add Intelligence threads to crewai-flows 2026-06-03 11:26:24 -07:00
Sam Julien 74e95684c8 docs: route all documentation authoring to shell-docs (#5184)
## Problem

The top-level `docs/` app is retired, but nothing in the repo said so,
and contributors (and agents) kept editing it. Two parallel docs trees
plus a one-directional legacy sync script made it ambiguous where
documentation should be authored:

- `docs/content/docs/` — the old Fumadocs app, no longer publishing
- `showcase/shell-docs/src/content/docs/` — the live source for
docs.copilotkit.ai

Two instruction surfaces actively pointed the wrong way: `CLAUDE.md`
said nothing about docs at all, and `.claude/docs/hooks.md` told
contributors to "add a docs page under `/docs`" (the retired location).

## Change

Establish one canonical rule and reduce the other surfaces to pointers:

- **`.claude/docs/documentation.md`** (new) — source of truth.
CopilotKit docs are authored in `showcase/shell-docs/src/content/`
(`docs/`, `reference/`, `snippets/`, `framework-overviews/`); the
top-level `docs/` folder is retired; AG-UI protocol docs are authored
upstream in `ag-ui-protocol/ag-ui` (publishing to docs.ag-ui.com) and
mirrored into `content/ag-ui/`.
- **`CLAUDE.md`** — adds an Essentials hard-rule and a Reference link.
- **`docs/README.md`** — replaces boilerplate with a retired/STOP
banner; legacy README retained under a `<details>`.
- **`.claude/docs/hooks.md`** — fixes the stale `/docs` pointer and
clarifies that a hook's API reference page lives in
`reference/hooks/<hookName>.mdx`, where v2 reference navigation is
generated automatically from frontmatter (no `meta.json`); conceptual
guide pages under `docs/` still use `meta.json`.
- **`CONTRIBUTING.md`** — adds a two-domain documentation section for
human contributors.

## Notes

- Two docs domains: **CopilotKit docs** → shell-docs; **AG-UI protocol
docs** → upstream `ag-ui-protocol/ag-ui`, then synced into the in-repo
mirror.
- Instructions-only change; no enforcement hook or sync-process change.
- Markdown only; no package code touched.
2026-06-03 11:03:32 -07:00
Austin Merrick c77624f14c docs(shell-docs): drop verbose install explanation paragraph 2026-06-03 10:31:35 -07:00
Austin Merrick 2beb091441 docs(shell-docs): scope skills install to /skills subpath, project scope
Use `CopilotKit/CopilotKit/skills -y` instead of the repo root: root
discovery sweeps in the internal `showcase-demo-debugging` skill
(metadata.internal, lives in .claude/.agents, not skills/), so users got
12 skills incl. one internal. The /skills subpath yields exactly the 11
published skills. Drop -g so install defaults to project scope, letting each
project pin the skills version matching its CopilotKit dependencies.
2026-06-03 10:27:18 -07:00
Austin Merrick 9ef80f787a docs(shell-docs): make skills install one-shot with -g -y
The build-with-agents guide recommended a bare `npx skills add` that drops
human users into a multi-step interactive flow (skill multiselect, agent
selection, scope, install method, confirm). Recommend `-g -y` so all skills
install globally in one shot, with a Callout pointing to the flag-less command
for users who want to choose interactively.
2026-06-03 10:21:45 -07:00
github-actions[bot] 43c448b5d4 style: auto-fix formatting 2026-06-03 17:06:19 +00:00
Sam Julien 69673f2ea7 docs: route all documentation authoring to shell-docs
The top-level docs/ app is retired but nothing said so, and two
instruction surfaces still pointed contributors there. Establish a
single canonical rule and reduce the other surfaces to pointers.

- Add .claude/docs/documentation.md as the source of truth: CopilotKit
  docs are authored in showcase/shell-docs/src/content/; the top-level
  docs/ folder is retired; AG-UI protocol docs are authored upstream in
  ag-ui-protocol/ag-ui and mirrored here.
- CLAUDE.md: add an Essentials rule and a Reference link.
- docs/README.md: replace boilerplate with a retired/STOP banner.
- .claude/docs/hooks.md: fix the stale /docs pointer; document that a
  hook's API reference page lives in reference/hooks/ and that v2
  reference nav is generated from frontmatter (no meta.json).
- CONTRIBUTING.md: add a two-domain documentation section.
2026-06-03 10:04:56 -07:00
Benjamin Taylor 074e3881f3 fix(examples/ms-agent-framework-dotnet): correct stale doc links + panel comment
The .NET example's page.tsx pointed its Shared State and Generative UI doc
links at /pydantic-ai/ (copy-paste leftovers) instead of
/microsoft-agent-framework/. Also fix the threads-drawer CSS header comment
that still referenced 'mastra's CopilotSidebar'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor df2236d91e fix(examples/threads): hide the locked threads panel on mobile
The no-license locked panel is a fixed-width (w-80 / 18-20rem) block. In the
single-column mobile grid it left a dead background strip beside it and pushed
the app content down. Hide it below 1024px (max-lg:hidden / .lockedPanel
display:none) — consistent with the real drawer + first-paint placeholder,
which also reserve no column on mobile. Content now gets the full width.

Applied across all 7 migrated examples.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 0c962fe9a9 fix(examples/threads): locked card — one-line command + clearer runnable hint
On the no-license locked threads panel:
- widen the panel slightly (w-72 -> w-80 / lockedPanel 18rem -> 20rem) and
  add white-space: nowrap so `copilotkit add-intelligence` stays on one line
  instead of wrapping mid-command
- add a 'with:' lead-in above the command box so it reads as a runnable command
  rather than loose text

Applied across all 7 migrated examples (Card-based locked state in adk/agno/
langgraph-js/langgraph-python; themed .lockedPanel in mastra/ms-agent-*).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 34906417be fix(examples/threads): surface the locked threads panel (no bare/black column)
The disabled-state ThreadsPanelGate (shown when no Intelligence license is
present) rendered its locked card in a bare `w-72` container with no
background, so the threads column showed the page background (a black column in
dark-themed examples, white in light) instead of the drawer surface.

Give that container the drawer surface (bg + hairline right border) so the
locked card sits in a panel that matches the drawer, consistent with the
already-surfaced .lockedPanel examples (mastra, ms-agent-framework-*).

Affects adk, agno, langgraph-js, langgraph-python (the Card-based locked state).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 3875b22f71 fix(examples/threads): kill threads-panel mount flash + content shift on load
The ThreadsPanelGate renders a first-paint placeholder while the client-only
drawer mounts. It was either a bare `w-72` div (no surface → a black/white
column flash in the page bg) or a fixed 18rem inline-styled div (correct color
but, on mobile where the mounted drawer floats, the reserved 18rem collapsed on
mount → content shifted left).

Replace both with a shared `.drawerPlaceholder` class that matches the open
drawer's footprint + surface (18rem, drawer bg, hairline border) on desktop and
`display: none` below 1024px (the mobile drawer floats, so reserve no column).
Result: no color flash and no content shift on load. Applied across all 7
migrated examples (themed vs raw surface tokens per example).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 0f6842495a fix(examples/langgraph-js): align mobile header with the threads launcher
Port the langgraph-python mobile-header fix to langgraph-js (same shared
canvas/header demo). Below 1024px the threads drawer's floating launcher is
fixed top-left and collided with the top-left CopilotKit header:

- max-lg:pl-24 on the header so the logo clears the launcher pill
- max-lg:pt-2.5 + pb-0 (and drop the logo span's pb-1.5 on mobile) so the
  logo is vertically centered with the launcher + the Chat/App toggle
- trim the collapsed launcher's icon buttons (2rem -> 1.75rem) + tighter
  padding so the pill height lines up with the toggle

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor a6586e68e0 fix(examples/langgraph-python): align mobile header with the threads launcher
On phones/tablets (≤1024px) the threads drawer's floating launcher is fixed
at the top-left corner, and it collided with this example's top-left
CopilotKit header. Three small fixes so the header reads as one tidy row:

- max-lg:pl-24 on the header so the logo clears the launcher pill
- max-lg:pt-2.5 + pb-0 (and drop the logo span's pb-1.5 on mobile) so the
  logo is vertically centered with the launcher + the Chat/App toggle
  (was sitting ~7px low)
- trim the collapsed launcher's icon buttons (2rem -> 1.75rem) + tighter
  padding so the pill height (~36px) lines up with the toggle instead of
  towering over it

Local to langgraph-python (the only rollout example with a top-left header).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor aca92a6fe0 fix(examples/threads): off-canvas threads panel on tablet + phone (≤1024px)
Below 1024px the in-flow threads column squeezed the demo content and the
(full-screen) CopilotSidebar chat into slivers. Raise the responsive
breakpoint from 900→1024 and make the panel a true off-canvas overlay:

- collapsed → a small floating launcher pill pinned top-left (z-1300),
  above the full-screen mobile chat, so threads stay reachable
- open → a fixed full-height panel sliding in from the left (z-1300),
  content + chat use the full width behind it
- default the drawer to collapsed when innerWidth ≤ 1024 on mount

Applied across all 7 integration examples' shared threads-drawer, each
adapted to its own theme tokens (themed examples use --threads-drawer-*,
raw examples use --card/--border for the launcher surface).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor ad03efefc4 fix(integrations/threads): default the threads drawer collapsed on narrow screens
Below 900px the drawer already overlays the content when open (existing media
query), but it defaulted to open — so on phones the 16rem panel covered the
content + chat on load. Default isOpen from window.innerWidth (> 900) so narrow
screens start at the 3.5rem rail; the user expands to the overlay on demand.
The drawer is client-mounted, so reading window in the initializer is safe.

Applied to the shared threads-drawer.tsx across all examples + north-star.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 21c59f9941 fix(integrations/threads): New thread starts a fresh thread + un-clip collapsed tooltips
- New thread (header + collapsed rail) now switches to a fresh threadId
  (crypto.randomUUID()) instead of setting it to undefined. Setting threadId
  undefined after a thread was selected did not reset the V2 chat — it kept
  showing the previous conversation. A new id forces the configuration provider
  to re-thread to an empty conversation.
- Collapsed-rail buttons use a native title tooltip instead of the styled
  ::after one, which clipped horizontally against the viewport's left edge in
  the narrow rail. The wider expanded row keeps the styled tooltip.

Applied to the shared threads-drawer.tsx across all examples + north-star.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 3ed9c58f7d fix(integrations/threads): unify threads-drawer base + propagate review fixes across examples
The threads-drawer had drifted into two near-identical .tsx variants (a 1-char
encoding diff) during the bespoke passes. Unify all examples onto a single
shared threads-drawer.tsx, which also propagates the mastra review fixes:
- collapsed rail: hover tooltips on the expand + new-thread buttons, and the
  non-interactive decorative icon (read as a dead button) removed;
- tooltip renders below the trigger in each example's themed module.css (the
  styled ::after tooltip was clipped when shown above the trigger).

Per-example theming (the module.css token values) is unchanged — only the
shared logic + the tooltip positioning rule are reconciled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 64233e1330 fix(integrations/threads): export PATCH/DELETE on runtime route (all examples) + mastra drawer review fixes
The Next route handlers only declared GET/POST, so the threads REST API's
DELETE (delete thread) and PATCH (archive/restore) were 405'd by Next before
reaching the runtime — thread deletion and archive were broken in every
example. Export PATCH + DELETE → handle(app) across all 7 routes.

mastra threads-drawer review fixes:
- tooltip renders below the trigger (the styled ::after tooltip was clipped by
  the drawer's overflow containers when shown above);
- collapsed rail drops a non-interactive decorative icon (read as a dead button)
  and adds hover tooltips to the expand + new-thread buttons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 94130333c6 feat(examples/integrations): Intelligence threads (batch 1) on @copilotkit 1.59.1
Activation-gated Intelligence/threads added to the batch-1 integration
examples (langgraph-js, mastra, adk, agno, ms-agent-framework-python,
ms-agent-framework-dotnet) and standardized — with the langgraph-python
north-star — on @copilotkit 1.59.1.

Per-example:
- env-gated CopilotKitIntelligence route branch (multi-route endpoint +
  `useSingleEndpoint={false}` REST transport; no organizationId);
- bespoke themed threads-drawer panel + locked-state tease;
- next.config `NEXT_PUBLIC_COPILOTKIT_THREADS_ENABLED` gate; demo-user identity.

Demo migration to v2 hooks (the 1.59.1 bump broke the V1-era demos):
- `useAgent({ agentId })` -> `{ agent }` with `agent.state`/`setState`;
- `useFrontendTool` params as Zod schemas; CopilotSidebar content as a sibling
  (v2 slot model), not children; guarded card state.

Shared `_intelligence/` overlay: composite image 0.2.0, idempotent
`provision-user` one-shot (demo-user), and `CHECK_ORIGIN=false` so the local
realtime-gateway accepts the app's websocket origin.

Verified end-to-end on mastra (threads CRUD create/list/auto-name + agent run +
live updates, clean console); the other five build clean and await per-example
visual review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor afb39fe04e refactor(integrations/langgraph-python): make threads-drawer a token-driven themeable base
Tokenize the last hardcoded literals in threads-drawer.module.css into --threads-*
CSS variables (with fallbacks to the existing design tokens / prior literals, so
the north-star is visually unchanged). Add THEME.md documenting the token contract
so each example can theme the drawer by defining tokens — no per-example CSS edits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor cdc8e36a0f chore(integrations/parity): track threads-drawer; stage instances for batched rollout
Add src/components/threads-drawer/** to verbatimFiles (north-star is canonical).
Stage langgraph-js / langgraph-fastapi / strands-python in allowedDivergence for
the threads files (threads-drawer/**, src/app/page.tsx, next.config.ts) so parity
stays green while the frontend rolls out per batch; entries are removed as each
instance is synced. Verified: adds zero new parity failures (pre-existing
example-layout / docker-route-override / next-env.d.ts drift is unrelated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor 2ee3e618aa feat(integrations/langgraph-python): scaffold Threads frontend (locked without license)
Restore the threads-drawer components + locked-state gate, page.tsx wiring
(threadId state + CopilotChatConfigurationProvider + two-column shell), and the
next.config build-time derivation of NEXT_PUBLIC_COPILOTKIT_THREADS_ENABLED from
the license token. Without a license the gate renders the locked panel; the
drawer is client-mounted (SSR-safe). This is the canonical north-star frontend
that parity:sync distributes to instances per batch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor b00d36b6bb feat(integrations): framework-agnostic _intelligence activation overlay
docker-compose (postgres + redis + intelligence/composite) with its load-bearing
init-db SQL, a .env.intelligence fragment (appended on activation), and a README.
Framework-agnostic; consumed by copilotkit init -i / add-intelligence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Benjamin Taylor e66e652a3c feat(integrations/langgraph-python): dormant env-gated Intelligence runtime wiring
When COPILOTKIT_LICENSE_TOKEN is set, wire CopilotKitIntelligence + identifyUser +
licenseToken (marker-fenced for opt-out); otherwise InMemoryAgentRunner — today's
behavior, unchanged. Document the optional Intelligence env keys (commented) in
.env.example. No visible change to the example until a license is provided.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:03:24 -05:00
Lukas Moschitz 8a79dca3b4 fix(core): make setRuntimeTransport idempotent on the requested transport mode (RD-4)
Auto-detect resolves the requested transport ("auto") to a concrete value
("rest"/"single") and writes it back to _runtimeTransport. setRuntimeTransport
then compared against that resolved value, so re-applying the same requested
mode — which the provider effect does on every render — compared unequal and
re-ran the entire /info handshake, rebuilding the runtime agents mid-session
and blanking the transcript (and any per-message UI bound to it).

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

Adds coverage: re-applying "auto" after auto-detect resolves it does not
refetch /info.
2026-06-03 16:28:35 +02:00
Ben Taylor 6c834f83d8 fix(runtime): Properly derive thread names from agents when generating them (fix ENT-732) (#5156)
## Summary
- Select generated thread titles only from assistant text messages
returned by the naming run.
- Reject JSON-shaped title output unless it parses to an object with a
string title.
- Add Runtime regression coverage for tool-result suffixes and invalid
JSON title payloads.

## Validation
- pnpm nx run @copilotkit/runtime:test --
src/v2/runtime/__tests__/thread-names.test.ts
src/v2/runtime/__tests__/handle-run.test.ts (passed, 56 tests)
- pnpm nx run @copilotkit/runtime:build (passed)
- Pre-commit package checks passed
- pnpm nx run @copilotkit/runtime:check-types (blocked in dependency
task @copilotkit/shared:check-types: missing
LicenseContextValue/LicenseMode exports from
@copilotkit/license-verifier and telemetry index error)
- NODE_OPTIONS=--max-old-space-size=8192 pnpm nx run
@copilotkit/runtime:check-types --excludeTaskDependencies (failed: tsc
heap out of memory near 8 GB)
2026-06-03 09:05:59 -05:00
Maxim d5f11c1dfe fix(saas-demo): render showTransactions via useComponent with stable deps
Display-only generative UI must use useComponent (not useFrontendTool): its
render is unconditional so the card persists after the tool call completes.
Also pass [transactions, cards] as deps so the renderer re-registers when the
data loads -- otherwise the closure captures the initial empty transactions
and the list renders empty.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 15:25:17 +02:00
Maxim 6d455e71ca fix(saas-demo): use CopilotKit provider + REST transport so chat renders
The migration mounted the low-level CopilotKitProvider, which omits the
ThreadsProvider that holds the rendered message thread, so the agent ran but
the transcript stayed empty. Use the full CopilotKit provider, and set
useSingleEndpoint={false} to match the multi-endpoint Hono route (the default
single-endpoint transport 404s against it).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 15:25:13 +02:00
Maxim 982f9e5378 docs(saas-demo): correct README REST/team/store details
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 13:08:30 +02:00
Maxim 2859f12377 fix(saas-demo): minor reference-demo cleanups
- cards PUT handler: stop console.info'ing the request body, which
  included the plaintext PIN on every PIN-change request.
- wrapper.tsx: drop the duplicate ./globals.css import (already
  imported in app/layout.tsx, which is the canonical place).
- copilot-context.tsx: replace window.location.pathname read during
  render with usePathname() from next/navigation, matching how
  components/layout.tsx already derives the current route.
- next.config.mjs: remove the eslint.ignoreDuringBuilds block — Next 16
  no longer runs ESLint at build, and the key now produces an
  "Unrecognized key(s): 'eslint'" warning. Confirmed warning is gone.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 12:50:13 +02:00
Maxim 0a70125d86 build(saas-demo): align next/react versions with actual runtime + drop stale lockfile
package.json was pinning next@14 / react@18, but the root pnpm.overrides
were already forcing next@16 / react@19 at install time and the code uses
Next 16 async params. Bump the declared ranges to ^16.0.10 / ^19 (and
@types/react{,-dom} to ^19) so the manifest matches reality and matches
the v2 reference demos (mcp-apps, generative-ui-playground).

Also drop examples/showcases/banking/pnpm-lock.yaml: the demo is a
workspace package (listed in root pnpm-workspace.yaml and resolved in the
root pnpm-lock.yaml), so the per-demo lockfile was vestigial v1 cruft
that contradicted the v2 migration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 12:49:53 +02:00
Maxim 1d2b5db575 docs(saas-demo): rewrite README for v2 architecture
Replace v1-era hooks/data references with the actual v2 surface:
useAgentContext / useFrontendTool / useHumanInTheLoop from
@copilotkit/react-core/v2, the Hono runtime route, the seed.json + store
data layer, and the Northwind identity. Drop mentions of removed
SQL/MSA/ServiceNow/RAG features.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 12:49:34 +02:00
Maxim 5263ac2e59 test(saas-demo): fail smoke test on hydration + uncaught errors
Remove the /Hydration/i pattern from the ignored-console-errors filter so
Next.js hydration mismatches surface as real failures, and add a
page.on("pageerror", ...) listener that records uncaught exceptions and
asserts none occurred. pageerrors are not filtered — any uncaught
exception fails the smoke test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:54:02 +02:00
Maxim 8efd6ecb33 test(saas-demo): Playwright smoke test for golden path
Adds a CI-safe Playwright smoke test that verifies the banking showcase
boots and the CopilotKit v2 popup opens with its configured suggestion
pills, without invoking the agent (so it runs in CI without secrets).

Covers:
  - Document title shows the Northwind Finance brand
  - Credit-cards dashboard renders ("Credit Cards" heading)
  - CopilotPopup launcher opens the dialog (Northwind Copilot)
  - Three suggestion pills render: View transactions, Add a card,
    Assign a policy

The dev server gets a dummy OPENAI_API_KEY so the runtime route boots,
but the test never sends a chat message or clicks a suggestion.

.gitignore: ignore test-results/, playwright-report/, and
tsconfig.tsbuildinfo so they don't become clutter.
2026-06-03 11:27:25 +02:00
Maxim 77c96acc4f refactor(saas-demo): migrate to Tailwind v4 and import v2 styles normally
Banking was on Tailwind v3, which made the pre-compiled v2 stylesheet
(`@copilotkit/react-core/v2/styles.css`, built as Tailwind v4 output)
incompatible with the PostCSS pipeline. A temporary inline-CSS hack in
`layout.tsx` worked around this. Migrate to Tailwind v4 to match the
canonical v2 demos and remove the hack.

- package.json: tailwindcss ^4, add @tailwindcss/postcss ^4, replace
  tailwindcss-animate with tw-animate-css (v4 drop-in)
- postcss.config.mjs: switch plugin to @tailwindcss/postcss
- globals.css: use @import "tailwindcss" + @import "tw-animate-css";
  add @custom-variant dark for the existing .dark/.light class toggle;
  move shadcn color/radius mapping into @theme inline (preserves
  bg-background/text-foreground/rounded-{lg,md,sm} semantics)
- tailwind.config.ts: deleted; theme now lives in CSS
- components.json: clear stale tailwind.config reference
- layout.tsx: drop the readFileSync/dangerouslySetInnerHTML inline-CSS
  workaround; import "@copilotkit/react-core/v2/styles.css" the normal
  way alongside ./globals.css

Verified: tsc clean, next build clean, Playwright-rendered all four
pages (/, /dashboard, /cards, /team) with computed-style checks
(sidebar bg-gray-900 dark, rounded-lg=8px, .border=1px) and opened
the copilot popup which renders fully styled with the v2 stylesheet.
2026-06-03 11:10:28 +02:00
Jordan Ritter dfc72f1a7b fix(showcase/harness): harden browser-pool non-release teardown paths (#5174)
## Summary

Follow-up to #5173 (bucket-(d)) closing three **pre-existing**
browser-pool concurrency defects on the non-release teardown paths. The
browser-pool is a context-pool over a fixed set of long-lived Chromium
processes; these defects biased the hygiene-recycle cadence and could
strand waiters / leak deferred recycles.

## Fixes (each red-green proven)

1. **`serveNextWaiter` orphan-close leaked `servedContexts`.** A waiter
timing out mid-`openContextOn` cleaned up the reservation/context but
never decremented `servedContexts` (which `openContextOn` had already
`++`'d) → every orphaned-by-timeout serve permanently inflated the count
→ premature hygiene recycles. Fix: decrement `servedContexts` in the
orphan-close block.
2. **Deferred `recyclePending` honored only on `release()`.** A recycle
deferred because `pendingOpens > 0` set `recyclePending`, but the
non-release teardown paths (orphan-by-recycle rollback, orphan-close)
returned the entry to idle without re-checking it → the deferred recycle
was dropped and the browser exceeded `recycleAfter` indefinitely. Fix:
shared `maybeFireDeferredRecycle(entry)` helper called on both
non-release teardown paths.
3. **`openContextOn` rollback didn't drain waiters.** The
orphan-by-recycle rollback freed a reservation but never
`scheduleServeNextWaiter()` → queued waiters could stall with free
capacity until an unrelated release. Fix: `scheduleServeNextWaiter()`
after the rollback.

## Verification
- Red-green for all three (reproduced each bug, then green).
- Full harness vitest: **1702–1705 passed**; browser-pool suite
**27/27** (mutation-tested — reverting fix #3 fails its guard). `tsc
--noEmit` exit 0.
- Public API + `BROWSER_POOL_MAX_CONTEXTS` default untouched.

## Reviewed
7-agent unbiased CR (cr-loop): the three fixes confirmed sound; one
ordering concern on the new code investigated and **refuted**
(sole-browser relaunch-failure rejects the waiter rather than stranding
it).

## Known further hardening (separate effort — NOT in this PR)
The CR surfaced additional **pre-existing** browser-pool reliability
bugs that warrant a dedicated hardening pass, independently flagged by
multiple reviewers:
- `shutdown()` vs in-flight `openContextOn` → leaked context (no
`isShutdown` re-check post-`newContext`); recycles added to
`inFlightRecycles` after shutdown's snapshot not awaited.
- crash-reason `recycleBrowser` abandons live contexts without
`.close()` — leaks on the non-dead `acquire`-retry path.
- `acquire` retry treats a transient `newContext` failure as a full
crash → recycles the whole browser, tearing down unrelated live contexts
(correlated flakiness).
- `launchChain` launch gate has no timeout → a single hung
`chromium.launch()` permanently deadlocks all relaunches.
- `parseInt` env parsing silently accepts trailing garbage
(`MAX_CONTEXTS=24x` → 24); no warning.
- context-close failures swallowed via bare `.catch(() => {})`
(inconsistent with `closeBrowser`'s logged path).
- relaunch-failure eviction only rejects waiters when the pool is fully
empty (doesn't redistribute onto surviving browsers); `pickLeastLoaded`
tie-break concentrates load on browser 0.
2026-06-02 20:56:33 -07:00
github-actions[bot] e032c514de style: auto-fix formatting 2026-06-03 02:43:19 +00:00
Jordan Ritter 57ff0d332f fix(showcase/harness): close three browser-pool non-release teardown concurrency defects
Bug 1: serveNextWaiter orphan-close (timed-out waiter mid-open) now mirrors
openContextOn's servedContexts++ with a decrement, so an orphaned serve no
longer permanently inflates servedContexts and biases the hygiene recycle to
fire early.

Bug 2: a hygiene recycle deferred via the release-path shouldRecycle&&hadWaiter
guard is now re-checked on the NON-release teardown paths (openContextOn
orphan-by-recycle rollback and serveNextWaiter orphan-close) via a shared
maybeFireDeferredRecycle helper, so the deferred recycle still fires when the
entry's last activity ends without a release() — previously it was dropped and
the browser exceeded recycleAfter indefinitely.

Bug 3: openContextOn's orphan-by-recycle rollback now calls
scheduleServeNextWaiter() so freed capacity immediately drains queued waiters
instead of stalling them until the next unrelated release/recycle handoff.

Adds three red-green regression tests (BUG1/BUG2/BUG3) to the browser-pool
suite. Public API and MAX_CONTEXTS default unchanged.
2026-06-02 19:32:26 -07:00
Jordan Ritter 90894901a2 fix(showcase): regression campaign — tool-rendering/calc fixtures, dashboard links, deploy guard, D6 ladder-gating, browser-pool cap (#5173)
## Fixes

- **Gate LGP tool-rendering AAPL + Find-flights fixtures on `toolName`**
(not `hasToolResult`): the AAPL tool-rendering and Find-flights
first-leg fixtures now key off `toolName` so the right tool renders.
Local proof: tool-rendering AAPL + Find-flights run **local D6 green**.
- **Restore sandboxed-UI `jsFunctions` in `gen-ui-open-advanced`
fixtures** (agno, crewai-crews, langgraph-fastapi, langgraph-python,
mastra): the sandboxed Calculator/Ping `jsFunctions` were missing, so
the calculator never computed. Local proof: calc **`=` → 4
browser-verified**.
- **Resolve dashboard links to the real shell host via server-threaded
`shellUrl`**: the dashboard tree was entirely `"use client"`, so
`getRuntimeConfig()` returned the `ssr-placeholder.invalid` SSR sentinel
and baked dead hrefs into every Demo/Code link. `page.tsx` is now a
server component that reads the real host server-side and threads it
into the client `DashboardPage`. Local proof: **SSR links click → real
demo, verified**.
- **Fail `verify-deploy` on env-unset config sentinel + robust config
extractor**: when `SHELL_URL` is unset the server config returns the
`about:blank#shell-url-missing` sentinel; the deploy guard now fails
loud on it rather than shipping dead links, with a hardened config
extractor. Local proof: **deploy-guard red-green**.
- **Gate Coverage D6 badge + stats by the depth ladder; gated indicator
only on genuine lower-rung failure**: D6 is the top of the verification
ladder, so a green D6 claim is only valid when the ladder through D5 is
intact. New `d6Effective` collapses to gated (`—`) when a lower rung
genuinely fails (never on no-data), keeping the badge, stat, regression
flag, and chip in agreement. Local proof: **D6-gating full-suite 790
green incl dashboard-color-matrix 54/54**.
- **Raise browser-pool default `MAX_CONTEXTS` to 40 + correct pool
docs**: contexts (not chromium processes) are the scaling knob since the
PID ceiling of 1000 is the binding constraint; D6 peak 32 + D5 peak 8 =
40. Probe cadence/docs corrected to match. Local proof: **pool
MAX_CONTEXTS=40 locally proven, 50 PIDs ≪ 1000**.

## CR

Converged via 4 unbiased 7-agent cr-loop rounds + 2 fix rounds.

## Known follow-ups (not in this PR)

- **(d) browser-pool concurrency hardening** — `servedContexts`
inflation on `serveNextWaiter` orphan-close, `recyclePending` deferral
on non-release teardown, and waiter-drain on `openContextOn` rollback.
These are pre-existing pool internals; separate PR.
- **(b/c) minor cosmetic / naming items** — `DocsRow` unused `shellUrl`
prop; `computeColumnTallyDetail` labels a D6-absent amber as `"e2e"`;
the agno `gen-ui-open-advanced` `_meta` note is misleading but is the
SOLE source of agno Calculator/Ping fixtures (do NOT delete); `API=d3`
vs `d2` naming; `resolveD3` has no effective stale row (pre-existing);
`e2e-deep.yml` stale primary-key comment.
- **react-core consecutive-interrupt run-state fix** — a SEPARATE
pending branch; the `gen-ui-interrupt` cell needs it.
2026-06-02 19:26:06 -07:00
github-actions[bot] 33d7eef4e4 style: auto-fix formatting 2026-06-03 00:58:59 +00:00
Jordan Ritter 07d230ae9c fix(showcase): raise browser-pool MAX_CONTEXTS default to 40 + correct pool docs 2026-06-02 17:57:48 -07:00
Jordan Ritter 9125ec5b81 fix(showcase): gate Coverage D6 badge + stats by depth ladder; gated indicator only on genuine lower-rung failure 2026-06-02 17:57:48 -07:00
Jordan Ritter 64461e1704 fix(showcase): fail verify-deploy on env-unset config sentinel + robust config extractor 2026-06-02 17:57:48 -07:00
Jordan Ritter 7d097feabc fix(showcase): resolve dashboard links to real shell host via server-threaded shellUrl 2026-06-02 17:57:47 -07:00