Commit Graph

12612 Commits

Author SHA1 Message Date
Jordan Ritter ec646bbf4f Merge remote-tracking branch 'origin/main' into chore/remove-harness-legacy-ssot
# Conflicts:
#	showcase/scripts/railway-envs.generated.json
#	showcase/scripts/railway-envs.ts
2026-06-23 17:56:18 -07:00
Mark Fogle 06e6de87c7 feat(showcase/google-adk): add ADK-only a2ui-recovery demo (OSS-158 recovery made visible)
A new demo that surfaces the ag_ui_adk >= 0.7.0 validate->retry recovery loop
+ recovery-exhausted hard-fail envelope, rendered as the building/retrying/
failed lifecycle by @ag-ui/a2ui-middleware >= 0.0.10. Two pills, driven by
aimock fixtures that key the inner render_a2ui call by recovery attempt
(sequenceIndex):
- HEAL: attempt 0 structurally-invalid (unresolved child) -> heals to valid
- EXHAUST: invalid on every attempt -> a2ui_recovery_exhausted fallback

Backend-owned (get_a2ui_tool, recovery.maxAttempts=3, injectA2UITool=false),
reusing the declarative-gen-ui catalog + sales context. ADK-only by design:
the recovery loop lives in the ADK middleware; langgraph-python's runtime A2UI
path (@ag-ui/a2ui-middleware single-pass) has no equivalent, so there is no LP
parity reference (exempt from LP e2e-parity). Ported from ag-ui
examples/.../a2ui_recovery.py.

Wires: recovery_agent.py + registry; copilotkit-a2ui-recovery route;
demos/a2ui-recovery page/chat/suggestions; manifest demo+feature; qa spec;
aimock fixture; feature-registry + constraints (constrained-explicit) entries.

Verified in-sandbox: import-smoke (41 agents, recovery cfg), generate-registry +
validate-constraints + validate-parity (20/20 pass) + aimock-fixtures (818) +
python suite (62) all green. Browser e2e (lifecycle render + sequenceIndex
routing) + e2e spec are the documented outside-sandbox steps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 00:49:18 +00:00
Jordan Ritter eaa3a0a3fd fix(showcase): honest promote-notify message + durable healthcheckPath tracking (#5657)
## Summary

Two related fixes to the showcase promote pipeline:

**Promote-notify Slack message — say what actually happened.**
Previously a partial promote rendered a message that read as if
*everything* failed, with no indication of which services promoted vs.
failed. Now the message:
- announces `🚂 Promoting showcase → prod (N): <names>` with a legible
count
- on a partial/failed outcome leads with `Promoted:` / `Failed:` (one
header each, then bullets) so you can see exactly which services
succeeded and which didn't
- reports real wall-clock elapsed (integer-coerced; degrades to omitting
the phrase if metadata is unparseable)
- drops the constant `verify-prod:` legend line that preceded the
meaningful data

**Durable healthcheckPath tracking — stop the silent prod drift.** The
promote pin path and the provisioning path could leave a service's
Railway `healthcheckPath` diverged from intent (this is what left aimock
answering on the wrong path in prod). Now:
- `healthcheckPath` is tracked per-service/per-env in the SSOT
(`railway-envs`)
- the promote pin re-asserts it (omit-when-absent — never sends `null`)
- `deploy-to-railway` provisioning routes through `isTrackedService` /
`resolveProvisionHealthcheck`, so a tracked-null service correctly
*omits* the healthcheck while an untracked one keeps the `/api/health`
default

## Test plan
- [x] `test_promote_healthcheck_reassert.rb` — pin re-asserts SSOT
healthcheck, omits when absent, never null (3 runs / 11 assertions)
- [x] `deploy-to-railway.healthcheck.test.ts` + `railway-envs.test.ts` +
`emit-railway-envs-json.test.ts` (121 tests)
- [x] snapshot-ivar lint green (2 runs / 32 assertions)
- [x] notify renderer dry-run mirrors success / partial / total-failure
shapes
2026-06-23 17:44:44 -07:00
Mark Fogle 0e7b803c3e chore(showcase/google-adk): remove dead hand-rolled A2UI planner + SalesPipelineAgent
The hand-rolled google.genai generate_a2ui planner (and the orphaned
SalesPipelineAgent that consumed it) in main.py are superseded by the
ag_ui_adk 0.7.0 middleware (get_a2ui_tool), now wired backend-owned in
declarative_gen_ui_agent.py / beautiful_chat_agent.py. main.py is reduced to
the shared tool wrappers + before_model/before_agent callbacks still covered
by tests; dead A2UI imports pruned.

- delete tests/python/test_generate_a2ui.py (tested the removed planner)
- manifest declarative-gen-ui: drop stale src/agents/main.py highlight + fix description

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 00:32:32 +00:00
Jordan Ritter 5859ae4057 docs(showcase): sync promote-notify README counts after harness-legacy removal
PR #5658 dropped harness-legacy from the fixtures but the README still
showed pre-removal counts, contradicting the edited fixtures.
2026-06-23 17:19:29 -07:00
Jordan Ritter 0809c25dac chore(showcase): remove redundant harness-legacy service from SSOT and fixtures
The pool-fleet migration is complete: the control-plane harness plus the
prod workers (deployed 2026-06-19, HARNESS_ROLE=worker, pool count 2) now
cover every probe dimension the interim `harness-legacy` fleet-migration
bridge was holding live, so `harness-legacy` is dead config.

This is the code-side cleanup only:
- Remove the `harness-legacy` entry from the railway-envs SSOT and the
  now-dead `key === "harness-legacy"` special-case in computePromoteClosure.
- Regenerate railway-envs.generated.json (41 -> 40 services).
- Drop harness-legacy from the golden snapshot, the gateIgnore expectation
  sets, the promote-notify fixtures, and the redeploy-env doc comments;
  update the service-count assertions (41 -> 40).
- Fix the stale "STAGING-ONLY" harness-workers comment: prod workers are
  live on Railway, though this SSOT entry still models the staging
  instance only (no prod env backfilled here yet).

The live Railway `harness-legacy` service is torn down separately as a
follow-up infra step.
2026-06-23 17:05:26 -07:00
Jordan Ritter 59e18693eb feat(showcase): honest promote-notify message + durable healthcheckPath SSOT tracking
Promote-notify Slack message: name the promoted AND failed services (one
Failed: header + bullets), legible "(N): <names>" count, real wall-clock
elapsed (integer-coerced), and drop the constant verify-prod legend line.

Durable healthcheckPath: track it per-service/env in the SSOT (railway-envs),
re-assert it on the promote pin path (omit-when-absent, never null), and route
deploy-to-railway provisioning through isTrackedService/resolveProvisionHealthcheck
so a tracked-null service omits the healthcheck while an untracked one keeps the
/api/health default — fixing the silent prod-healthcheck drift that refused aimock.

Tests: ruby pin-reassert spec + deploy-to-railway healthcheck spec + emit/golden/accessor.
2026-06-23 16:56:16 -07:00
Mark Fogle 55f4f43afd feat(showcase/google-adk): surface 0.7.0 A2UI middleware (backend-owned) in declarative-gen-ui + beautiful-chat
Replace the hand-rolled google.genai A2UI planners (in main.py and
beautiful_chat_agent.py) with the published ag-ui-adk >= 0.7.0 middleware
sub-agent via get_a2ui_tool(), surfacing OSS-158 (forced render_a2ui
sub-agent + toolkit validate->retry recovery loop + recovery-exhausted
hard-fail envelope + render_as_llm_instructions / parse_and_fix healing).

Wiring is BACKEND-OWNED (injectA2UITool: false), matching the AWS Strands /
ag2 external-framework convention rather than langgraph-python's
runtime-driven injectA2UITool: true. Backend-owned is required: the planner
now lives in the ADK middleware, so letting the runtime also inject would
double-bind the tool slot. The explicit  is load-bearing post
CopilotKit#5611 (a provider catalog otherwise defaults injectA2UITool to true).

- declarative_gen_ui_agent / beautiful_chat_agent: tools include
  get_a2ui_tool({model, default_catalog_id}); beautiful keeps its other tools.
- shared_chat: add get_a2ui_model() to resolve a concrete Gemini BaseLlm for
  the sub-agent (mirrors get_model's aimock-proxy wiring).
- routes: injectA2UITool stays false (declarative + beautiful-chat).
- registry/agent_server: no spec-level a2ui config needed (tool is agent-owned).

Verified vs published 0.7.0 + real Gemini: backend-wired generate_a2ui emits
a2ui_operations; OSS-158 gate (subagent + recovery invalid->valid + hard-fail
a2ui_recovery_exhausted) all retained through this exact wiring.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 23:19:45 +00:00
Mark Fogle ebd87a23f3 chore(showcase): bump google-adk to ag-ui-adk 0.7.0 (OSS-158 A2UI middleware)
Pins the published middleware that ships the A2UI auto-inject + toolkit
recovery + render_as_llm_instructions/parse_and_fix path. Foundational
step; the A2UI agent re-wire onto that path follows under verification
once 0.7.0 is on PyPI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 23:19:45 +00:00
Sam Julien e8c2cd5005 docs(shell-docs): show threads in authored framework nav 2026-06-23 15:42:01 -07:00
Sam Julien 7e54dbe746 docs(shell-docs): place threads with chat UI guides 2026-06-23 15:42:01 -07:00
Tyler Slaton 2ea3e66702 fix: repair check-types across all packages and gate it in CI (#5365)
## What this does

Follow-up to #5356. CI never ran `check-types`, so type errors piled up
silently across the monorepo. #5356 fixed shared, a2ui-renderer, and
angular. This PR fixes every remaining package and adds a CI gate so it
cannot happen again.

Almost all of the diff is mechanical type repair: type annotations,
`import type` splits, casts, ambient declarations, and tsconfig
module-resolution bumps. The sections below call out the parts that are
not purely mechanical so review can focus there.

## Where to focus your review

These are the only changes with runtime or public-API impact. Everything
else is type-level and behavior-preserving.

1. **License gating wired to /info** (shared, react-core, vue,
react-native). Behavioral change, details below.
2. **react-native bug fix**: a `catch` binding referenced by
`TypeError.cause` had been lint-stripped and is restored, plus a `{
cause }` is now attached to a parse error.
3. **runtime `Schema` passthrough**: a type-only cap on `tool()` schema
inference. Runtime behavior is unchanged; it only stops tsc from blowing
past 8 GB.
4. **New public type export**: `Anchor` from web-inspector, consumed by
react-core's `inspectorDefaultAnchor`.
5. **New CI job**, see the CI section.

## License context wired to /info

Follow-up to @MikeRyanDev's review on #5356 (wire the inert license
machinery to /info). `createLicenseContextValue` now takes the
server-reported license status instead of a hardwired null.
`checkFeature()` returns false only when the runtime reports `expired`
or `invalid`, and fails open otherwise (null, none, expiring, and valid
all keep features on). The React, Vue, and React Native providers feed
the status they already track from /info. New tests cover the gating in
shared and react-core. Per-feature data is not in /info yet, so gating
is uniform across features.

## Type fixes by package

- **core** (392 errors): bundler module resolution (matches the tsdown
build and the vue package), strict-mode and AG-UI drift in sources and
tests, added `@types/phoenix`.
- **react-core** (255): component, hook, and test drift (now-private
`activeRunCompletionPromise`, RunFinished outcome union, slot prop
types, StandardSchema variance), ambient declarations for `katex` CSS
and the react-markdown JSX namespace, plus the `Anchor` export.
- **runtime** (393, previously hidden behind an OOM crash):
BuiltInAgentConfiguration narrowing, AI SDK v6 and AG-UI drift, the
UserMessage attachment migration, OpenAI v4/v5 surface changes, and the
`Schema` passthrough noted above.
- **react-native** (23): provider/core bridge types, RN 0.85 drift, and
the `catch`/`cause` bug fix noted above.
- **smaller fixes**: runtime-client-gql (UserMessage image narrowing,
pinned `types`), web-inspector (nodenext import extensions, RunFinished
narrowing), react-textarea (es2023 lib for `toReversed`), react-ui,
voice, agentcore-runner, sqlite-runner (one-liners), sdk-js (bundler
resolution plus the missing `@standard-schema/spec` dev dep),
examples/v2/node (drop stale node10 resolution overrides).

## CI

New `check-types` job in `static_quality.yml`: run graphql codegen, then
`nx run-many -t check-types --parallel=1` with a 12 GB heap. The runtime
typecheck alone peaks near 10 GB and takes about 5 minutes on a 16 GB
runner, so it runs serially.

## Testing

- `nx run-many -t check-types` passes for all 24 projects locally and in
CI.
- All package test suites pass: core 431, react-core 1271, runtime 1523,
vue 1001, react-native 246, runtime-client-gql 129, plus the smaller
packages.
- Lockfile diff is only the two added type-only dev dependencies
(`@types/phoenix`, `@standard-schema/spec`).

## Follow-ups (not in this PR)

- react-core's built `.d.mts` files emit extensionless relative imports,
which silently degrade consumer types to `any` under `skipLibCheck`
(found while fixing react-native).
- The AI SDK x zod type-instantiation cost in runtime deserves a real
fix (40M instantiations); trace data available.
- `@ai-sdk/anthropic`'s new `authToken` setting is not forwarded by the
Anthropic adapter.
- `MCPClientProvider.tools()` has diverged from AI SDK v6's `ToolSet`
typing.
2026-06-23 15:41:18 -07:00
github-actions[bot] 3284bc863f style: auto-fix formatting 2026-06-23 22:34:58 +00:00
Tyler Slaton 75611b272c chore: merge main into PR 5480 2026-06-23 15:32:09 -07:00
Tyler Slaton 6d9397c42e Preserve quickstart CTA styling in shell docs reference pages (#5654)
## Summary
- Add a dedicated `shell-docs-primary-cta` style for the hero quickstart
link so it keeps the primary CTA color inside reference content.
- Cover the new class usage in the hero and framework overview tests.

## Testing
- Updated unit tests to verify the quickstart CTA class and the matching
global CSS override.
- Updated unit tests to verify the framework overview markup includes
the primary CTA class.
2026-06-23 15:27:06 -07:00
Austin Merrick 4ba201b5c4 fix: repair check-types across all packages and gate it in CI
Repairs TypeScript check-types across the monorepo and adds a CI gate so
regressions are caught going forward:

- core: bundler module resolution and strict-mode fixes
- sdk-js: bundler module resolution; keep codegen, formatter, packaging working
- react-core: fixes across components, hooks, and tests
- react-native: restore catch binding referenced by TypeError cause
- runtime: repair check-types and bound AI SDK schema inference
- web-inspector: nodenext import extensions, export Anchor
- remaining packages and node example: assorted check-types repairs
- deps: add missing type-only devDependencies
- license context driven from /info licenseStatus
- ci: run check-types in the static quality workflow

Squashed from 12 commits for a single, easily-revertable change.
2026-06-23 15:26:47 -07:00
Tyler Slaton 307a52c8eb Preserve quickstart CTA styling in reference content 2026-06-23 15:26:36 -07:00
Austin Merrick 30bd6d8f0e test(core): pin remove/re-add baseline; doc + assertion polish
CR round 2 follow-ups (no behavior change):
- Add a core-headers regression test proving the agentOwnHeaders baseline
  stays pristine across remove + re-add (the WeakMap is intentionally not
  cleared on removal; clearing would re-capture polluted headers).
- Correct the stale `headers` config doc ("appended" -> merged on top of each
  HttpAgent's own headers, core wins).
- Tighten the e2e no-provider-headers assertion to toEqual.
2026-06-23 15:22:11 -07:00
Jordan Ritter 3b9696265d fix(showcase): recover ag2 + llamaindex staging from crash-loops (#5642)
## Summary

Both the **AG2** and **LlamaIndex** showcase integrations were 100% red
on the staging matrix (every cell `BE ×`, 0 green all day). Root cause
was **not** per-cell logic — each framework's Next.js frontend was
crash-looping under matrix load, driven by an agent-side hot loop. This
PR fixes both root-cause loops.

### LlamaIndex — `sse-missing` (commit forwarding request-time tools)
- **Root cause:** the llama-index AG-UI adapter never forwarded
`RunAgentInput.tools`, so page-injected tools (`toggleTheme`,
`pieChart`, `barChart`, `scheduleTime`, MCP, `generateSandboxedUi`) were
invisible to the LLM → `RUN_ERROR` (404 `no_fixture_match` →
`openai.NotFoundError`) → no `RUN_FINISHED` → `sse-missing`. The retry
storm OOM-crashed the frontend (Node fatal, `next-server` v15.5.18).
- **Fix:** new `RequestAwareAGUIChatWorkflow` (`_request_tools.py`) that
forwards request tools, re-roles the tool-result on an LLM-bound copy
only, and skips duplicate frontend-tool chunk emission (bare snapshot
already carries them). Applied to beautiful_chat / mcp_apps /
open_gen_ui / open_gen_ui_advanced routers; added the `search_flights`
backend tool to beautiful_chat for langgraph-python parity.
- **Red→green:** beautiful-chat **0/5 → 5/5** (toggle-theme,
schedule-meeting, search-flights, pie-chart, bar-chart), freshly
re-confirmed via `--d6 --rebuild`; `mcp-apps` red→green.

### AG2 — `generate_a2ui` empty-arg validation loop
- **Root cause:** the declarative route pointed `HttpAgent` at the root
catch-all agent instead of the dedicated `/declarative-gen-ui` mount,
and `generate_a2ui` required a `context` arg the model emits as `{}` →
pydantic `context Field required` → infinite retry. **630 loop
iterations** observed; the flood starved the ag2 frontend (502s).
- **Fix:** dedicated mount + `injectA2UITool:false` + no-arg
`generate_a2ui` (matches langgraph-python / google-adk) + regenerated
aimock fixture to 4-pill parity + ported the stale ag2
renderers/definitions.
- **Red→green:** **630 → 0** validation errors, `runsFinished=1`, clean
`generate_a2ui → TOOL_CALL_RESULT → RUN_FINISHED`.

## Known remaining (pre-existing, separate, NOT regressions)
- **ag2 `gen-ui-declarative`:** run completes but the a2ui surface
components don't paint (autogen↔AG-UI bridge `TOOL_CALL_RESULT` →
A2UIMiddleware surface-conversion gap). Tracked separately.
- **llamaindex `open-gen-ui`:** `sse-missing` resolved; residual
sandboxed-UI iframe render gap is **pre-existing** (red since
2026-06-01, fc=509 — predates this crash).

## Test plan
- [x] LlamaIndex beautiful-chat `--d6 --rebuild`: 5/5 green (fresh,
isolated)
- [x] LlamaIndex mcp-apps: red→green
- [x] AG2 declarative hot-loop: 630→0 validation errors, runsFinished=1
- [x] Pyright clean on both integrations (verified in-Docker with real
deps)
- [x] oxfmt clean
- [ ] Post-deploy: re-run D6 matrix on staging to confirm ag2 +
llamaindex column recovery

## Deploy note
Staging is **image-sourced, main-only** (the "Showcase: Build & Push"
workflow builds GHCR images and redeploys on push to `main`). This
branch will NOT auto-deploy. To validate on staging before merge: `gh
workflow run showcase_build.yml --ref fix/llamaindex-sse-request-tools
-f service=ag2` (and `service=llamaindex`).
2026-06-23 15:21:11 -07:00
Jordan Ritter 9f2b859450 fix(showcase): stop ag2 generate_a2ui empty-arg validation loop
The ag2 declarative-gen-ui route pointed its HttpAgent at the root
catch-all mount (agents/agent.py) instead of the dedicated
/declarative-gen-ui mount (a2ui_dynamic.py), and generate_a2ui declared
a required context arg that the model emits as {}. pydantic rejected
every call with "context Field required" and AG2 retried without bound —
a 630-iteration hot loop per pill that flooded logs and starved the
frontend.

Fix: route to the dedicated mount with injectA2UITool:false (the
dedicated agent owns generate_a2ui and emits a2ui_operations itself);
make generate_a2ui a no-arg tool matching the D6 fixtures and the
langgraph-python gold standard, with a constant inner system prompt
(per-pill distinctness comes from the captured user message). Regenerated
the gen-ui-declarative fixture and ported the LP definitions/renderers
catalog (all 7 driver testids) for parity. Eliminates the validation
loop: runsFinished=1, zero validation errors.
2026-06-23 15:12:09 -07:00
Jordan Ritter 7cb43581aa fix(showcase): forward request-time tools in llamaindex AG-UI adapter
The LlamaIndex AG-UI adapter never forwarded RunAgentInput.tools, so
page-injected frontend tools (useFrontendTool / useComponent /
useHumanInTheLoop) were invisible to the LLM — runs the model couldn't
satisfy ended in RUN_ERROR (no RUN_FINISHED), which the harness reported
as sse-missing.

New RequestAwareAGUIChatWorkflow re-implements the chat step as the
upstream body plus three additions: forward RunAgentInput.tools as no-op
FunctionTool stubs carrying the verbatim injected JSON schema; re-role
tool-result messages to role="tool" on the LLM-bound message copy only
(so the hasToolResult second-leg fixture matches) without mutating
stored/snapshot history; and for frontend tool calls dispatch the
ToolCallEvent but skip the duplicate TOOL_CALL_CHUNK (the bare snapshot
already delivers the call). beautiful-chat 0/5 -> 5/5; mcp-apps fixed.
2026-06-23 15:12:09 -07:00
Jordan Ritter eded5f5325 fix(showcase): skip non-probe-eligible services in staging precondition instead of crashing (#5650)
## Summary

A `service=all` promote runs `verify-staging-precondition` →
`verify-deploy.ts --env staging --services <all>`, which
**hard-crashes** (exit 2) the moment it's handed a service with
`probe.staging=false` (`resolveProbeTargets` throws `not
probe-eligible`). That failed the whole-fleet precondition. This adds an
opt-in `--skip-ineligible` flag (wired into the
`verify-staging-precondition` step **only**) that skips a
non-probe-eligible service with a clear status line instead of throwing;
eligible services are still probed normally, and an explicit
single-service probe / unknown name still hard-fails (strict default
preserved; `verify-prod` untouched).

After #5641 (starters always-on), the only remaining
`probe.staging=false` services are **`harness-workers`** and
**`harness-legacy`** — empirically confirmed to still crash a
`service=all` precondition, so this fix is still needed (the starters
that originally triggered it are now eligible and probed normally).

## Verification
- Red-green (vitest, real surface): a service list containing
`harness-workers` crashes WITHOUT the flag, and is SKIPPED
(`harness-workers (skipped — not probe-eligible for staging,
probe.staging=false)`) WITH it.
- verify-deploy suite: 124/124 pass. `tsc --noEmit` clean on changed
files. `actionlint` on the workflow: exit 0.

## Test plan
- [x] vitest verify-deploy suite green (124)
- [ ] CI green

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-23 15:09:20 -07:00
Sam Julien 81c716a4aa docs(shell-docs): add framework-scoped threads callouts 2026-06-23 15:07:13 -07:00
Jordan Ritter 160ba5a4aa fix(showcase): skip non-probe-eligible services in staging precondition instead of crashing 2026-06-23 14:51:16 -07:00
Jordan Ritter 7a00e2373d feat(showcase): make starter fleet always-on + verify-deploy starter driver (#5641)
## Summary

The 12 `starter-*` services were deliberately `sleepApplication=true`
(sleepable), `probe.staging=false` (held out of the verify-deploy
staging matrix). That class-difference is the root of three recurring
symptoms: the `service=all` promote false-fails them (SLEEPING / no
running-digest), the deployed-starter smoke test 404s a cold container,
and they're excluded from staging validation. Decision: **bring them
into the normal managed-fleet flow — always-on + staging-probed.**

- **`verify-deploy.drivers.starter.ts` (new)** — real `probeStarter`
baseline driver (deployment SUCCESS + HTTP 200 on `/`, mirroring
`probeShell`); replaces the fail-loud `case "starter"` stub.
- **`railway-envs.ts`** — `staging.probe: false→true` for all 12
starters (prod already true); stale "staging probe OFF" comments
rewritten. `railway-envs.generated.json` regenerated (in-sync via
`--check`).
- **`provision-starter-fleet.ts`** — `sleepApplication: true→false` +
comments/logs; test updated.

## ⚠️ Deploy ordering (must hold)
This PR flips `probe.staging=true`, which routes starters into the
staging matrix. It must **not** merge until the live services are
flipped always-on, or a `service=all` promote would probe still-sleeping
starters and fail. Sequence: **(1) live-flip 24 instances
`sleepApplication=false` + redeploy (12 staging + 12 prod), (2) verify
awake + serving `/`, (3) merge this PR.**

## Verification
- Red-green: starter driver (stub→probe `/`), SSOT golden (probe.staging
true), provisioner (sleep false) — all RED→GREEN.
- `showcase/scripts`: 2092 tests pass; `tsc --noEmit` clean on changed
files.

## Test plan
- [x] vitest suites green (2092)
- [ ] CR
- [ ] live 24-instance always-on flip + redeploy (staging + prod)
- [ ] CI green
- [ ] post-flip: `service=all` dry-run shows starters pass staging probe

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-23 14:43:55 -07:00
Tyler Slaton b07647eede fix(showcase): built-in-agent shared-state demo now re-renders on UI writes (#5643)
## Summary

The built-in-agent `shared-state-read-write` demo wrote agent state via
**direct property assignment** (`agent.state = {...}`). That sets the
value but does **not** fire `onStateChanged`, so components subscribed
via `useAgent` never re-render off a UI write. Switched the seed + title
write to **`agent.setState(...)`**, which updates state *and* notifies
subscribers.

This was the lone divergence: every other framework demo — including the
`langgraph-python` gold standard — already uses `agent.setState(...)`,
and `docs/shared-state.mdx` documents writes going through `setState`.

```diff
-    agent.state = { ...defaultRecipe } as unknown as typeof agent.state;
+    agent.setState({ ...defaultRecipe } as unknown as typeof agent.state);
...
-    agent.state = { ...(agent.state as object), title: next } as unknown as typeof agent.state;
+    agent.setState({ ...(agent.state as object), title: next } as unknown as typeof agent.state);
```

## Why

`@ag-ui/client`'s `AbstractAgent.setState()` both assigns `this.state`
and notifies all subscribers (`onStateChanged`), which is what drives
the `useAgent` re-render. Direct `agent.state = {...}` is a plain
property write — it skips the notification, so any component relying on
the hook to reflect the change silently goes stale.

## Test plan

- `showcase/bin/showcase test built-in-agent --d5 --verbose --cycle
--isolate` → green after rebuild from the changed source.
- lefthook pre-commit (lint-fix, package checks) + commitlint pass.

## Follow-up (not in this PR)

The built-in-agent demo is recipe-shaped (title/ingredients/steps) while
the other read-write demos are preferences/notes + `DemoLayout`. Per the
showcase 1:1 convention it should mirror `langgraph-python` — larger
change (+ fixture realignment), flagging separately.
2026-06-23 14:42:18 -07:00
Sam Julien 7e4284d35f docs(git): require branching from up-to-date origin/main (#5648)
## Summary

Adds a rule to `.claude/docs/git.md`: fetch and branch off `origin/main`
before starting work, rather than whatever the local `main` happens to
be.

```sh
git fetch origin && git switch -c <branch-name> origin/main
# worktree equivalent:
git fetch origin && git worktree add -b <branch-name> ../<dir> origin/main
```

Branching off a stale local `main` ("behind origin/main by N commits")
bases the PR on an old commit and invites avoidable merge conflicts. The
rule also documents the recovery path for an already-stale branch: `git
fetch origin && git rebase origin/main`.

Docs-only change to agent guidance; no code impact.
2026-06-23 14:32:27 -07:00
Jordan Ritter d0497649c7 test(showcase/harness): turn-done signal completion/backstop matrix
Cover the data-copilot-running turn-done signal in waitForTurnComplete:
true->false transition completion, stayed-stopped quiescence, the
attr-gated early backstop, pre-send run-start baseline, and the
integration wait-for-turn-complete behavior.
2026-06-23 14:32:05 -07:00
Jordan Ritter 494d836005 feat(showcase/harness): reliable data-copilot-running turn-done signal in waitForTurnComplete
Make waitForTurnComplete use the page-side data-copilot-running attribute
as the primary turn-done signal: detect the running true->false transition,
require stayed-stopped quiescence, and gate the early backstop on
attrPresent + runningNow to avoid headless false-RED. Capture a pre-send
run-start baseline so fast turns keep the primary signal alive, read
surfaceReady once per poll, and add computeMaxTurnDurationMs.
2026-06-23 14:31:59 -07:00
Jordan Ritter 1696445da3 feat(showcase/harness): page-side data-copilot-running MutationObserver
Add buildCopilotRunningObserverScript to sse-interceptor.ts and wire it
via addInitScript so the page exposes a data-copilot-running attribute
that the harness can observe for turn-completion signaling.
2026-06-23 14:31:50 -07:00
Nathan 🔶 Tarbert c84e2166bc docs(git): require branching from up-to-date origin/main
Add a rule to .claude/docs/git.md to fetch and branch off origin/main
(not stale local main) before starting work, with the worktree
equivalent and the rebase recovery command for an already-stale branch.
Prevents PRs from being based on an old commit.
2026-06-23 17:22:07 -04:00
Nathan 🔶 Tarbert 97d1de4682 fix(showcase): use agent.setState in built-in-agent shared-state demo
The built-in-agent shared-state-read-write demo wrote agent state via
direct property assignment (`agent.state = {...}`), which sets the value
but does not fire `onStateChanged` — so subscribed components never
re-render off a UI write. Every other framework demo (including the
langgraph-python gold standard) already uses `agent.setState(...)`, which
both updates state and notifies subscribers. This was the lone divergence.

Switch the seed and the title write to `agent.setState(...)` so the demo
matches the documented pattern (docs/shared-state.mdx says writes go
through `setState`) and the rest of the showcase.

Verified: built-in-agent D5 e2e-deep suite green after rebuild.
2026-06-23 17:21:49 -04:00
Tyler Slaton 006c62592e chore: release monorepo v1.61.1 (#5645)
## Release monorepo v1.61.1

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

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.61.1`
   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.61.1`
   - Creates git tag `monorepo/v1.61.1`
   - 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.61.1
2026-06-23 14:21:47 -07:00
Ben Taylor f52960d279 fix(runtime): set telemetry license token for v2 SSE runtimes (#5640)
## Problem

Self-hosted users on the v2 SSE runtime never get a `telemetry_id` on
their runtime telemetry events — even with a license token configured.
The root cause is in `packages/runtime/src/v2/runtime/core/runtime.ts`:

- `CopilotIntelligenceRuntime` **did** call
`telemetry.setLicenseToken(...)` in its constructor.
- `BaseCopilotRuntime` and `CopilotSseRuntime` **did not**.

`telemetry_id` is derived only inside `setLicenseToken`
(`parseAndWarnTelemetryId`). If it's never called, every event the
runtime emits is sent anonymously. SSE-mode handlers (`handle-connect`,
`handle-run`, `sse-response`) all emit `oss.runtime.*` events through
the shared telemetry singleton, so all of them went out unattributed for
SSE users.

## Fix

Hoist the license-token resolution (`options.licenseToken ??
COPILOTKIT_LICENSE_TOKEN`) and the `telemetry.setLicenseToken` call
**into `BaseCopilotRuntime`'s constructor**, so SSE and Intelligence
runtimes attribute telemetry identically. The now-redundant duplicate is
removed from `CopilotIntelligenceRuntime` (its `licenseChecker` stays).
The v1 `CopilotRuntime` already set the token and is unchanged.

## Test coverage — every construction path into the endpoints

The token is set at construction time and all endpoints share one
telemetry singleton, so covering every runtime construction path covers
every endpoint.

- **`runtime-license-telemetry.test.ts`** — `CopilotSseRuntime` and
`CopilotIntelligenceRuntime` (direct) + the `CopilotRuntime` shim (both
SSE and Intelligence delegates), each across `{explicit option,
COPILOTKIT_LICENSE_TOKEN fallback, none}`. Asserts the token is set
**exactly once** (guards against a double-set after the hoist).
- **`sse-license-telemetry.integration.test.ts`** — end-to-end: an SSE
runtime built with a license token forwards it all the way to
`lambdaClient.send` on a real Express endpoint request.
- **`copilot-runtime-license-telemetry.test.ts`** — regression guard for
the v1 `CopilotRuntime` path (already worked, previously untested —
exactly the kind of untested path that let this gap appear).

The new tests are **red before the fix** (the SSE-path assertions fail)
and green after.

## Verification

- New + existing v2 runtime suite: **770/770 pass**, no regressions.
- Lint: 0 new warnings. Build: green (types clean). Format: clean
(oxfmt).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-23 16:19:36 -05:00
Benjamin Taylor c2d38f4b6a refactor(runtime): resolve license token once in base; add env-fallback integration test
Addresses PR review feedback:
- Resolve the license token once (option ?? COPILOTKIT_LICENSE_TOKEN) into a
  protected readonly field on BaseCopilotRuntime, and have
  CopilotIntelligenceRuntime's licenseChecker reuse it. Collapses the duplicated
  resolution and structurally enforces that telemetry attribution and feature
  gating can never disagree, instead of relying on a "keep in sync" comment.
- Add an integration test for the env-var-only path (no licenseToken option) —
  the exact self-hosted scenario this PR targets — proving the env-resolved
  token reaches lambdaClient.send through a real request. Kept in its own file
  so the process-wide telemetry singleton (last-write-wins) can't false-pass it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:11:26 -05:00
Benjamin Taylor 7fb1600da5 test(runtime): integration-cover license token → sink for all endpoints/modes
Adds genuine end-to-end coverage beyond the SSE-via-Express case:
- SSE via the Hono adapter
- SSE via the framework-agnostic fetch handler (what node + custom adapters wrap)
- Intelligence mode end-to-end (real CopilotIntelligenceRuntime, WS runner stubbed)

Each constructs a real runtime (so the base-class setLicenseToken runs), drives a
real request through the adapter, and asserts the token reaches lambdaClient.send
on oss.runtime.copilot_request_created.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:11:26 -05:00
Benjamin Taylor b5a435f0c4 fix(runtime): set telemetry license token for v2 SSE runtimes
Only CopilotIntelligenceRuntime called telemetry.setLicenseToken in its
constructor; BaseCopilotRuntime and CopilotSseRuntime did not. As a result,
self-hosted SSE users got anonymous runtime telemetry (no telemetry_id) even
with a license token configured — and those events were additionally throttled
to the 5% anonymous sample rate, leaving runtime telemetry_id stuck at ~1%.

Hoist the licenseToken resolution (option ?? COPILOTKIT_LICENSE_TOKEN env
fallback) and telemetry.setLicenseToken call into BaseCopilotRuntime so SSE and
Intelligence runtimes attribute telemetry identically. Remove the now-redundant
duplicate from CopilotIntelligenceRuntime (its licenseChecker stays).

Tests cover every construction path into the endpoints:
- runtime-license-telemetry.test.ts: SSE/Intelligence direct + CopilotRuntime
  shim (both delegates) x {explicit option, env fallback, none}; asserts the
  token is set exactly once (guards against a double-set after the hoist).
- sse-license-telemetry.integration.test.ts: end-to-end proof the token rides
  to lambdaClient.send through a real Express endpoint request.
- copilot-runtime-license-telemetry.test.ts: regression guard for the v1
  CopilotRuntime path (already worked, previously untested).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:11:26 -05:00
tylerslaton 410d34001d chore: release monorepo v1.61.1 2026-06-23 21:00:28 +00:00
Tyler Slaton 56615da485 ci: reduce release delay, fix flakey test, use devops bot token (#5644)
## Summary
- Mint a GitHub App token for the stable release workflow and reuse it
for PR creation and follow-up API calls
- Disable lefthook during automation commits so release PR generation
does not depend on local developer hooks
- Relax the CopilotChat perf regression test to assert correctness
without a hard 5s wall-clock check

## Testing
- Unit/UI test updated to allow longer async rendering while still
verifying 100 messages render successfully
- Not run (not requested)
2026-06-23 13:56:33 -07:00
Tyler Slaton 83b21df925 Stabilize release PR token and chat perf test 2026-06-23 13:51:35 -07:00
Mark f7cddc7651 fix(examples): route stack analyzer through end node (#5634)
## What does this PR do?

Routes the Gemini canvas stack analyzer through its registered `end`
node instead of directly to LangGraph's `END` sentinel.

This keeps the workflow wiring consistent with
`workflow.set_finish_point("end")` and ensures the cleanup/final state
emission in `end_node` is reachable.

## Related PRs and Issues

- Fixes #5605

## Tests

- `python3.12 -m py_compile examples/canvas/gemini/agent/stack_agent.py`
- `python3.12 - <<'PY' ... PY` (AST check that
`workflow.add_edge("analyze", "end")` exists and
`workflow.add_edge("analyze", END)` does not)
- `. /tmp/oss-pr-pipeline/langgraph-venv/bin/activate && python - <<'PY'
... PY` (LangGraph topology reproduction asserts `analyze -> end ->
__end__` and that `end_node` runs)
- `. /tmp/oss-pr-pipeline/langgraph-venv/bin/activate && python - <<'PY'
... PY` (imports `stack_agent.py` with CopilotKit/Gemini stubs and
asserts compiled `stack_analysis_graph` edges include `analyze -> end`
and not `analyze -> __end__`)
- `git diff --check`

## 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 (not applicable: example graph wiring bug fix)
- [x] "Allow edits by maintainers" is checked (lets us help iterate on
your PR directly — faster turnaround for everyone)
2026-06-23 13:41:29 -07:00
Sam Julien c45f3ce63a fix: gate thread requests on runtime capabilities (#4971)
## Root cause

`useThreads` and the web inspector treated a connected runtime as if
thread list/inspect endpoints were always available. In non-Intelligence
setups, that could trigger `/threads` and inspector requests against
runtimes that did not expose compatible thread endpoints, producing
noisy benign 404s.

## Behavior change

- Adds `threadEndpoints` capability metadata to runtime info and carries
it through shared/core types.
- Reports thread list/inspect support only for multi-route runtimes
backed by Intelligence or the local `InMemoryAgentRunner`; single-route
runtime info reports thread endpoints as unavailable.
- Gates `useThreads` so it does not fetch when the runtime does not
advertise thread list support, and returns an explicit
unavailable-endpoints error instead.
- Gates web inspector owned thread stores and thread detail fetches on
advertised list/inspect support.

## Docs

- Clarifies managed Intelligence thread metadata/history versus
self-managed runner persistence.
- Documents that `AgentRunner`, `SqliteAgentRunner`, or a custom runner
can persist and replay chat history, but does not automatically provide
the managed `useThreads` list/mutation/realtime contract unless
compatible REST thread endpoints are exposed.
- Updates inspector/event-inspector messaging to avoid implying thread
browsing is Intelligence-only while still distinguishing durable managed
history from local in-memory development support.

## Verification

Publish-pass checks:

- `gh --version`
- `gh auth status`
- `git diff --check`
- `git diff --cached --check`
- Commit hook ran `lint-fix` with warnings only, then package checks via
Nx:
  - `nx run-many -t test --projects=packages/**`
  - `nx run-many -t publint,attw --projects=packages/**`

Implementation-agent reported checks:

- web-inspector tests passed
- core tests passed
- react-core tests passed
- runtime tests passed
- sqlite-runner tests passed
- `git diff --check` passed

Known limitation:

- Full `run-many check-types` was attempted by the implementation agent
and failed due pre-existing dependency/typecheck issues and runtime OOM,
not this FAC-1 change.
2026-06-23 12:50:00 -07:00
Mike Ryan 3e4c515252 fix: preserve legacy thread endpoint behavior 2026-06-23 12:10:01 -07:00
Jordan Ritter bc784a1412 feat(showcase): make starter fleet always-on (sleepApplication=false, staging probe on)
Flip the 12 starter-* services to behave like every other managed
showcase service: always-on and staging-probed.

- railway-envs SSOT: staging probe false -> true for all 12 starters
  (prod was already on); refresh the stale "staging probe OFF" /
  fail-loud-placeholder doc-comments to reflect baseline-driver verification.
- provision-starter-fleet: sleepApplication true -> false so the
  provisioner creates always-on (not sleepable) Railway instances; update
  the "the whole point — sleepable" header/inline comments + log lines.
- Regenerate railway-envs.generated.json (emit-railway-envs-json.ts) and
  the golden fixture; update the SSOT probe + provisioner sleep assertions.
2026-06-23 12:00:53 -07:00
Jordan Ritter cb8f9ebea2 feat(showcase): add verify-deploy baseline driver for the starter fleet
Replace the fail-loud `case "starter"` stub in verify-deploy's dispatch
switch with a real baseline liveness driver. The starter-template fleet
EXPOSEs only its Next.js frontend (serving `/` and `/api/copilotkit`,
NO `/api/health`), so the driver healthchecks `/` via probeBaseline,
exactly like the Next.js shells: deployment-SUCCESS + HTTP 200 on `/`.
2026-06-23 12:00:37 -07:00
Alem Tuzlak 107cdad5af feat(slack-example): reaction/ephemeral/modal feature demos
Add per-feature demos to examples/slack that narrate per-platform degradation
explicitly rather than failing silently:
- emoji triage — 🐛/🔥/✅ reactions file/escalate/ack via the agent
- /preview — ephemeral draft issue (native only-you on Slack, DM fallback on
  Discord/Telegram)
- /file-issue — modal form (Slack rich, Discord text-only, Telegram
  conversational fallback)

Also updates the Slack frontend guide (slack.mdx) with the capability matrix.
2026-06-23 20:49:38 +02:00
Alem Tuzlak 268b39e3e0 feat(bot): cross-platform surface parity — reactions, ephemeral, modals
Add capability-gated surface methods across the bot packages so one handler
degrades gracefully per platform:
- thread.react / thread.unreact — emoji reactions (Slack, Discord, Telegram)
- thread.postEphemeral — only-you messages with a required DM fallback
- openModal (interaction/command-scoped) — structured forms (Slack rich,
  Discord text-only), omitted on surfaces with no live interaction trigger

Spans @copilotkit/bot-ui, bot, bot-slack, bot-discord, bot-telegram with
per-adapter capability flags. Discord: open modals from slash-command
interactions, and never clear registered commands on an empty publish.
2026-06-23 20:49:07 +02:00
Austin Merrick 6bfb12267f docs(core): document header merge/clear contract; pin clear-baseline test
CR round 1 follow-ups (no behavior change):
- Document on setHeaders + applyHeadersToAgent that the merge baseline is the
  agent's construction-time headers, so setHeaders can override but cannot
  remove a per-agent header (the agent's own value re-surfaces on clear), and
  that dynamic updates go through setHeaders, not direct agent.headers mutation.
- Tighten the agentOwnHeaders field comment (captured on first apply, never
  re-captured) and the applyHeadersToAgent method doc.
- Add a core-headers test pinning the clear-reveals-baseline contract.
- Soften the two useAgent test-mock comments: they are an additive stand-in,
  not a faithful model of core's frozen baseline.
2026-06-23 11:43:21 -07:00
Mike Ryan 3452657416 fix: update thread capability test fixtures 2026-06-23 11:36:58 -07:00
Mike Ryan 0187ec250a fix: address thread capability review feedback 2026-06-23 11:33:48 -07:00