Commit Graph

10887 Commits

Author SHA1 Message Date
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
Jordan Ritter b6b35bd406 fix(showcase): restore sandboxed-UI jsFunctions in gen-ui-open-advanced fixtures 2026-06-02 17:57:47 -07:00
Jordan Ritter 3ca0a26f11 fix(showcase): gate LGP tool-rendering AAPL + Find-flights fixtures on toolName 2026-06-02 17:57:47 -07:00
Jordan Ritter a835b41e3e fix(showcase): bump @ag-ui/langgraph to 0.0.36 in langgraph integrations (#5171)
## Summary

Carries [ag-ui PR
#1784](https://github.com/ag-ui-protocol/ag-ui/pull/1784)
("fix(langgraph): skip regeneration check when `command.resume` is set")
into the three langgraph showcase stacks, greening the
`gen-ui-interrupt` D6 cell.

- ag-ui `@ag-ui/langgraph` 0.0.35 (and earlier) incorrectly ran the
regenerate path on a **resumed** run, tripping the regeneration trap and
breaking gen-ui-interrupt. `0.0.36` adds the `command.resume` guard so a
resume skips the regeneration check.
- Pins `@ag-ui/langgraph` `0.0.36` via npm `overrides` (it is a
**transitive** dep of `@copilotkit/runtime`) in `langgraph-python`,
`langgraph-typescript`, and `langgraph-fastapi`.
- Regenerates each integration's `package-lock.json` (python/fastapi
regenerated with `--legacy-peer-deps`, matching their Dockerfile `npm ci
--legacy-peer-deps`).

## Files changed

-
`showcase/integrations/langgraph-typescript/{package.json,package-lock.json}`
-
`showcase/integrations/langgraph-python/{package.json,package-lock.json}`
-
`showcase/integrations/langgraph-fastapi/{package.json,package-lock.json}`

Lockfiles flip `@ag-ui/langgraph` 0.0.34 → 0.0.36 and pull in 0.0.36's
new transitive dep `@ag-ui/a2ui-toolkit@0.0.1-alpha.3`.

## Verification

- `@ag-ui/langgraph@0.0.36` is published to npm `latest`; its
`dist/index.js` contains the `!command?.resume` regeneration guard from
#1784.
- All three regenerated lockfiles resolve
`node_modules/@ag-ui/langgraph` to `0.0.36`.

## Test plan

- [ ] CI green
- [ ] gen-ui-interrupt D6 cell green for langgraph-python,
langgraph-typescript, langgraph-fastapi after showcase rebuild + re-run
2026-06-02 16:54:50 -07:00
Maxim 78492cc1c5 fix(saas-demo): remove dead react-ui styles import and inline v2 css
The banking showcase was migrated to CopilotKit v2 but `src/app/layout.tsx`
still imported the removed `@copilotkit/react-ui/styles.css`, causing every
route to 500 with "Module not found". Drop the dead import.

Banking is still on Tailwind v3, while the v2 stylesheet
(`@copilotkit/react-core/v2/styles.css`) is pre-compiled Tailwind v4 output
containing bare `@layer base { ... }` rules. Tailwind v3's PostCSS plugin
rejects `@layer base` without a matching `@tailwind base` directive, so any
CSS import routed through the JS/TSX pipeline fails the build. Move the v2
stylesheet load to a server-side `fs.readFileSync` + inline `<style>` tag in
the root layout so the CSS reaches the browser without passing through
PostCSS / Tailwind v3. This avoids a full Tailwind v4 migration of the app.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 01:21:38 +02:00
Maxim 3edcab4759 fix(saas-demo): await dynamic route params for Next 16 compatibility 2026-06-03 00:39:59 +02:00
Jordan Ritter 72156dbb83 fix(showcase): bump @ag-ui/langgraph to 0.0.36 in langgraph integrations
Carries ag-ui PR #1784 (skip regeneration check when command.resume is
set) into the three langgraph showcase stacks. ag-ui 0.0.35 incorrectly
ran the regenerate path on a resumed run, breaking the gen-ui-interrupt
D6 cell. 0.0.36 adds the command.resume guard.

Pins @ag-ui/langgraph 0.0.36 via npm overrides (transitive dep of
@copilotkit/runtime) in langgraph-python, langgraph-typescript, and
langgraph-fastapi, and regenerates each per-integration package-lock.json.
2026-06-02 15:17:41 -07:00
Tyler Slaton f878892761 docs(shell-docs): recommend v2 CopilotKit provider import (#5163)
## Problem

Shell-docs had conflicting v2 guidance around the provider import path.
Some migration/reference/quickstart pages either recommended
`CopilotKitProvider` or kept `CopilotKit` examples on the root
`@copilotkit/react-core` package even though v2 docs should import the
`CopilotKit` component from `@copilotkit/react-core/v2`.

## Why

The correct recommendation is the `CopilotKit` component name, imported
from the v2 entrypoint. Leaving root-package imports in v2-facing docs
makes the migration and reference guidance contradict the v2 package
layout.

## Fix

- Recommend `CopilotKit` from `@copilotkit/react-core/v2`, not
`CopilotKitProvider`.
- Update v2 migration, reference, and quickstart examples to use the v2
provider/style entrypoints.
- Leave root `@copilotkit/react-core` imports only in v1 docs and
explicit migration “Before” examples.
- Add regression coverage for stale provider/style package paths.
- Fix the shell-docs SignupLink SSR test typing exposed by typecheck.

Closes #5153
2026-06-02 15:17:09 -07:00
Jordan Ritter 982b0b3d1e fix(showcase): gate LGP AAPL tool-rendering fixture on toolName not hasToolResult
The D6 cell tool-rendering-custom-catchall for langgraph-python timed out
(deterministic 30s no-response). The probe sends two turns in one thread:
turn 1 "weather in Tokyo" -> get_weather, turn 2 "What's the current price
of AAPL?" -> get_stock_price. The AAPL first-leg fixture was gated on
hasToolResult:false, but aimock implements that gate as
messages.some(m => m.role === "tool") -- i.e. ANY tool message anywhere in
the thread. Turn 1's get_weather leaves a tool result in the thread, so on
turn 2 hasToolResult is permanently true and the false gate can never match
-> no_fixture_match -> 503 -> 30s timeout.

Replace the broken hasToolResult:false gate with toolName:"get_stock_price"
(the same pattern the sibling weather/chain first-leg fixtures already use).
A toolName gate fires whenever the tool is registered, regardless of prior
tool results; the toolCallId follow-up fixture still wins on iteration 2.

Fixture-only change. Verified locally via the D6 Docker path:
tool-rendering-custom-catchall now green (turn 1 get_weather + turn 2
get_stock_price both render, no 503/timeout); tool-rendering-default-catchall
still green (no regression).
2026-06-02 15:14:19 -07:00
Jordan Ritter ea87e6f06f fix(showcase): restore sandboxed-UI jsFunctions in D6 gen-ui-open-advanced fixtures
The generateSandboxedUi calculator (and the ping-host / inline-evaluator
pills) rendered static HTML with no interactivity — the = and keypad
buttons were no-ops — because the affected per-integration fixtures
omitted the jsFunctions key that the OpenGenerativeUIRenderer injects
into the iframe to wire click handlers to the host bridge
(Websandbox.connection.remote.evaluateExpression / notifyHost).

Copy the jsFunctions VERBATIM from the canonical langgraph-typescript
fixture (apples-to-apples) into agno, crewai-crews, langgraph-fastapi,
and mastra, and create the missing langgraph-python advanced fixture
(Calculator + Ping pills; the inline evaluator already lives in
gen-ui-open.json). Fixture-only change; the renderer is correct.
2026-06-02 14:54:38 -07:00
Maxim e1f12dcd4d feat(saas-demo): credible identity + consistent currency formatting
- Replace toy team names and @example.com emails with credible
  professional names and @northwind.example addresses (preserve ids,
  roles, team assignments). Default Admin is Alex Morgan.
- Set <title> metadata to IDENTITY.brand (Northwind Finance).
- Add formatCurrency helper in lib/utils.ts and route all money
  rendering (transactions list, credit-card details, dashboard +
  cards summary tiles) through it so amounts always render as
  $10,000.00 / -$1,000.00.
- Instruct the Northwind Copilot prompt to treat the rendered
  showTransactions list as the single source of truth so prose no
  longer restates counts/totals and contradicts the rendered list.
- Remove stray console.log and tighten == to === in components/layout.tsx.
2026-06-02 23:54:14 +02:00
Maxim 6bfac07de3 feat(saas-demo): file-backed JSON data store for tool state
Replace the in-memory `data` literal in `api/v1/data.ts` with a
file-seeded, module-singleton store:

- `src/data/seed.json` holds the seed (cards, team, policies,
  transactions) with refreshed dates (within ~60 days of 2026-06-02)
  and valid future card expiries.
- `src/lib/store.ts` deep-clones the seed at module init and exposes
  typed read accessors (cards/team/policies/transactions, findCard,
  findPolicy, findTransaction) plus the exact mutator set the routes
  use (addCard, updateCardPin, assignPolicyToCard, addPolicy,
  updateTransaction, addMember, updateMember, removeMember).
- All `src/app/api/v1/**/route.ts` files now read/write through the
  store. `data.ts` retains the shared interfaces/enums/CARD_COLORS/
  generateUniqueId and drops the literal `data` constant.
- Mutations persist for the running server process and reset to seed
  on restart (intentional demo behavior; no disk write-back).
- Domain-data only — conversation threads/memory live in a separate
  ticket (FOR-137).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 23:30:28 +02:00
Jordan Ritter fa5a84cdba Fix OPS_BASE_URL so dashboard Ops tab resolves the harness probe endpoint (#5168)
## Summary

The showcase dashboard's Ops tab fetches `/api/ops/*` as a same-origin
path, which the Route Handler at
`shell-dashboard/src/app/api/ops/[...path]/route.ts` forwards at request
time to `${OPS_BASE_URL}/api/*` on the showcase-harness HTTP origin (the
service that serves `/api/probes`).

In the local compose stack, `OPS_BASE_URL` was set to
`http://localhost:3200` — the dashboard's own host. The proxy therefore
looped back into the dashboard instead of reaching the harness, so the
probe-trigger endpoint failed (self-referential 500/503) and the Ops
live-probe grid could not resolve.

This points `OPS_BASE_URL` at the harness origin over the compose
network: `http://showcase-harness:8080`. The harness `Dockerfile`
EXPOSEs `8080` and `orchestrator.ts` binds `PORT ?? 8080`, so the
dashboard reaches `/api/probes` by container name on the internal port.
This mirrors staging, where the dashboard's `OPS_BASE_URL` likewise
points at the harness origin rather than at itself.

Scope: a single build-arg value in `showcase/docker-compose.local.yml`
(plus an updated explanatory comment). `OPS_BASE_URL` is read at request
time by the Route Handler, so this only seeds the runtime default — no
build-time resolution required.

## Test plan

- [ ] Dashboard Ops tab loads without a 500/503 from the ops proxy
- [ ] Probe-trigger endpoint (`/api/ops/probes` POST) returns 2xx,
forwarded to the harness `/api/probes`
- [ ] Ops live-probe grid renders harness data (harness running on the
compose network as `showcase-harness`)
2026-06-02 14:29:36 -07:00
Jordan Ritter b4a396c831 Env-gate LOCAL_SERVICES_JSON injection in harness service discovery (#5167)
## Summary

Adds a permanent, env-gated injection seam to the showcase harness
service discovery
(`showcase/harness/src/probes/discovery/railway-services.ts`). When
`LOCAL_SERVICES_JSON` is set, the harness (especially the
d6-all-pills-e2e driver) runs against **LOCAL** backend services instead
of performing Railway discovery — enabling apples-to-apples LOCAL D6
verification without Railway credentials.

- **Zero behavior change when unset/empty.** An unset or empty
`LOCAL_SERVICES_JSON` takes the byte-identical Railway discovery path —
the seam is fully transparent in the default configuration.
- **`demos` plumbed end-to-end (load-bearing).** The injected service
records carry `demos` all the way through. This matters: empty `demos`
would short-circuit the D6 driver into a false 15ms zero-cell "green,"
masking real failures. Plumbing `demos` end-to-end is what makes the
LOCAL path a faithful stand-in for Railway discovery.
- **Enables apples-to-apples LOCAL D6 verification** — run the full pill
suite against local services with the same code path shape as staging.

## Notes

- 8 new tests covering the `LOCAL_SERVICES_JSON injection` path (66
tests total in `railway-services.test.ts`, all passing).
- Env-gated: no Railway credentials required when services are injected.
- The injection seam executes the real discovery code (not mocked).

## Test plan

- [ ] `tsc --noEmit` (typecheck) exits 0
- [ ] `railway-services.test.ts` passes (66 tests, incl. all 8
`LOCAL_SERVICES_JSON injection` tests)
- [ ] Injection seam executes against the real code path (verified via
`discovery.railway-services.local-injection` log emission, not a mock)
- [ ] Unset/empty `LOCAL_SERVICES_JSON` produces a byte-identical
Railway discovery path (zero behavior change)
- [ ] `demos` plumbed end-to-end through injected service records
(guards against false zero-cell D6 green)
2026-06-02 14:29:31 -07:00
Maxim 9373aa167c feat(saas-demo): v2 agent context in layout + actions
- Switch imports from @copilotkit/react-core to /v2 in layout.tsx and actions.ts
- Replace useCopilotReadable with useAgentContext
- Stringify the credit cards/policies/transactions context value to satisfy
  the JsonSerializable type
2026-06-02 23:06:07 +02:00
Maxim 5a97ebc2b3 feat(saas-demo): v2 hooks + useReducer fix in team page
- Switch imports from @copilotkit/react-core to /v2
- Replace useCopilotReadable with useAgentContext (stringify team)
- Convert removeMember, changeMemberRole, changeMemberTeam parameters
  to Zod schemas
- Fix React 19 useReducer typing by extracting dialogStateReducer and
  dropping explicit generics
2026-06-02 23:05:53 +02:00
Maxim e044a4c5b9 feat(saas-demo): v2 hooks + useReducer fix in cards page
- Switch imports from @copilotkit/react-core to /v2
- Replace useCopilotReadable with useAgentContext
- Convert all useHumanInTheLoop and useFrontendTool parameters to Zod schemas
  (addNewCard, assignPolicyToCard, addNoteToTransaction, showTransactions,
  setCardPin, showAndApproveTransactions)
- Convert v1 available: "enabled"/"disabled" to v2 boolean
- Fix React 19 useReducer typing by extracting changePinReducer and dropping
  explicit generics
2026-06-02 23:05:44 +02:00
Maxim 41ae4fab9c feat(saas-demo): v2 hooks in copilot-context
- Switch imports from @copilotkit/react-core to /v2
- Replace useCopilotReadable with useAgentContext (stringify object value)
- Convert navigateToPageAndPerform parameters array to a Zod object schema
2026-06-02 23:05:28 +02:00
Jordan Ritter 6cc06209c9 Resolve dashboard D6 per-cell via enum keys + correct depth/D6 stats (#5170)
## Summary
- **Fix per-cell D6 resolution**: the dashboard's `resolveD6` now reads
per-cell ENUM keys (`d6:<slug>/<featureType>` via `CATALOG_TO_D5_KEY`
fan-out) instead of the integration aggregate — D6 cells render real
per-cell green/red instead of all-gray.
- **Depth + D6 surfaced by default**: `DEFAULT_OVERLAYS = [links,
health, depth]` (the per-cell D6 badge rides on the Health layer; the
depth chip folds D6).
- **Correct the aggregate stats bar** (`page-stats.ts` extraction): D6
cells were dropped from the depth distribution (`dist["d6"]++` → `NaN`,
masked by an `as` cast); gray/no-data cells were counted as green;
`d6Stats` swallowed amber into gray. Now renders the reachable buckets
**D0/D3/D4/D5/D6** (dropped permanently-zero D1/D2), tracks `noData` and
`degraded` distinctly, and validates `parity_tier` fail-loud.
- **Test coverage**: new table-driven cell color/rollup matrix
(`dashboard-color-matrix.test.tsx`) + `page-stats.test.ts` +
order-independence/comment hardening.
- **CR fixes**: effective (stale-downgraded) `.row` from cell-model
resolvers, `WORST_STATE_RANK` rename, composed-cell memo keys,
overlay-types re-export dedup, `setTab` persistence + `window.location`
test stub, `page.tsx` shared-`now` threading + 60s staleness re-render.

## Verification
- **776 tests pass / 1 skip**, `tsc --noEmit` clean, Next.js production
build OK.
- **Local visual proof**: seeded enum D6 rows (30✓/8✗/0 gray) into a
local PocketBase, rebuilt this branch, screenshotted bare `#matrix` —
per-cell D6 green/red renders, and the depth distribution shows `D6:30
D5:8 D4:0 D3:0 D0:588`.
- **7-agent code review converged** over 3 confirmation cycles.

## Notes
- The **#5152 `d6-all-pills` driver must stay on enum keys** (matches
this dashboard's `resolveD6` + the `d5-mapping-drift` test). Do not
revert it to raw catalog keys.
- **Follow-up (separate PR)**: stats-bar single-source-of-truth
hardening (`computeD6Stats`→`buildCellModel`; reconcile
`resolveD6Row`/`resolveD5Row` to the effective row; thread `connection`
into stats for SSE-offline; docs-only stats exclusion); delete
deprecated `composed-cell.tsx` + `deriveDepth`; `useOverlays` mount-hash
deep-link clobber; Notion visualization-doc sync to per-cell
`resolveD6`.

## Test plan
- [ ] CI green
- [ ] After staging deploy, dashboard renders per-cell D6 green/red (not
all-gray) for LangGraph-Python
2026-06-02 13:55:16 -07:00
Maxim 3966baa879 feat(saas-demo): migrate provider to v2 CopilotKitProvider + identity 2026-06-02 22:54:44 +02:00
github-actions[bot] a8f1544286 style: auto-fix formatting 2026-06-02 20:51:16 +00:00