mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
angular/v0.2.0
13288 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
56c67a346f |
chore: release angular v0.2.0 (#6096)
## Release angular v0.2.0 **Scope:** `angular` | **Bump:** `minor` --- ### How this release process works 1. **This PR was created automatically** by the "release / create-pr" workflow. It bumped the `angular` packages to `0.2.0` and generated AI-enhanced release notes. 2. **CI runs on this PR** — the full test suite (unit tests, lint, type checks, build) must pass before merging. This is the review gate. 3. **Review the release notes** in `release-notes.md` in this PR. If a Notion draft was created, you can edit the release notes there before merging. 4. **When this PR is merged**, the `release / publish` workflow automatically: - Builds all packages - Publishes the `angular` packages to npm at version `0.2.0` - Creates git tag `angular/v0.2.0` - Creates a GitHub Release with the final release notes ### Before merging - [ ] CI is green (tests, lint, types, build) - [ ] Version bumps look correct - [ ] Release notes are accurate (edit in Notion if a draft was created) --- > **Do not merge until CI is fully green.** The full test suite runs automatically on this PR.angular/v0.2.0 |
||
|
|
a90ff38b46 | chore: release angular v0.2.0 | ||
|
|
3ac4b84fed |
chore(deps): update github actions (#6092)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [reviewdog/action-actionlint](https://redirect.github.com/reviewdog/action-actionlint) | action | patch | `v1.72.0` → `v1.72.1` | | [ruby/setup-ruby](https://redirect.github.com/ruby/setup-ruby) | action | minor | `v1.319.0` → `v1.320.0` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/592) for more information. --- ### Release Notes <details> <summary>reviewdog/action-actionlint (reviewdog/action-actionlint)</summary> ### [`v1.72.1`](https://redirect.github.com/reviewdog/action-actionlint/releases/tag/v1.72.1) [Compare Source](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.72.0...v1.72.1) v1.72.1: PR [#​211](https://redirect.github.com/reviewdog/action-actionlint/issues/211) - fix: include digest in Docker image reference for action.yml </details> <details> <summary>ruby/setup-ruby (ruby/setup-ruby)</summary> ### [`v1.320.0`](https://redirect.github.com/ruby/setup-ruby/compare/v1.319.0...v1.320.0) [Compare Source](https://redirect.github.com/ruby/setup-ruby/compare/v1.319.0...v1.320.0) </details> --- ### Configuration 📅 **Schedule**: (in timezone America/Los_Angeles) - Branch creation - "before 9am every weekday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/CopilotKit/CopilotKit). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzIuNCIsInVwZGF0ZWRJblZlciI6IjQzLjI3Mi40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> |
||
|
|
d0fc5d0050 | chore(deps): update github actions | ||
|
|
8f04764e9c |
fix(examples): upgrade slack bot's TanStack AI deps to fix OpenAI strict-schema 400 (#6088)
## Problem
The deployed Slack triage bot (`examples/slack`) started failing
**every** turn with:
```
400 Invalid schema for function 'save_diff_comment':
In context=('properties','anchor'), 'propertyNames' is not permitted.
```
No change on our side triggered it — Linear's hosted MCP server changed
the `save_diff_comment` tool schema. Its `anchor` param is now a
free-form map (open object declared with `propertyNames` + open
`additionalProperties`). The bot fetches Linear's tool list at runtime,
so it picked up the new schema automatically.
## Root cause
`@tanstack/ai-openai@0.15.2` (what the bot resolves to) forces `strict:
true` on every function tool. OpenAI's strict function-calling validator
only accepts a subset of JSON Schema and **rejects the entire request
(400, before the model runs)** for a free-form-map object like `anchor`.
One over-rich third-party tool takes down the whole turn.
## Fix — adopt the upstream fix via a dependency upgrade
Already fixed upstream: `@tanstack/openai-base@0.9.8`
([tanstack/ai#933](https://github.com/TanStack/ai/pull/933)) makes the
tool converter detect free-form-map schemas and emit those tools with
`strict: false` (so they stay callable) instead of forcing an invalid
strict schema. First ships in `@tanstack/ai-openai@0.17.0`.
The bot's `^0.15.2` range can't reach it, so this bumps the aligned set
and refreshes `pnpm-lock.yaml`:
| package | before | after |
|---|---|---|
| `@tanstack/ai` | `^0.32.0` | `^0.42.0` |
| `@tanstack/ai-openai` | `^0.15.2` | `^0.17.1` (→ `openai-base@0.9.9`)
|
| `@tanstack/ai-mcp` | `^0.1.3` | `^0.2.5` |
**zod stays at `^3.25.76`.** The repo pins zod to 3.x via a root
`pnpm.overrides` (`zod: ">=3.22.3"`), so the whole workspace resolves
zod 3 regardless. `ai-openai@0.17` peers `zod ^4` (unmet → advisory
warning only), but the strict-schema fix operates on plain JSON Schema,
not zod, so it's unaffected.
**No runtime code change** — the fix lives entirely in the upgraded
adapter (an earlier revision of this PR hand-rolled a schema sanitizer;
that's removed in favor of leaning on TanStack's built-in handling).
## Verification
⚠️ Not verifiable in this worktree (example deps aren't installed here).
Before merge, in an installed env:
- `pnpm --filter slack-example check-types` and `pnpm --filter
slack-example test`
- One live turn hitting Linear (previously-failing `save_diff_comment`
path)
- Sanity-check the bot runs on the workspace's pinned **zod 3** despite
`ai-openai@0.17`'s `zod ^4` peer (the fix path is zod-independent, but
confirm no other `@tanstack/ai` code the bot exercises needs a
zod-4-only API).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||
|
|
d4e68b133f |
fix(examples): upgrade slack bot's TanStack AI deps to fix OpenAI strict-schema 400
Linear's save_diff_comment.anchor started shipping as a free-form map (propertyNames + open additionalProperties). @tanstack/ai-openai@0.15.2 forced strict:true on every tool and 400d the whole turn on such schemas. @tanstack/openai-base@0.9.9 (via ai-openai@0.17) detects free-form-map schemas and emits those tools with strict:false instead, so they stay callable. Bump the aligned set and refresh the lockfile: @tanstack/ai ^0.32.0 -> ^0.42.0 @tanstack/ai-openai ^0.15.2 -> ^0.17.1 @tanstack/ai-mcp ^0.1.3 -> ^0.2.5 zod stays at ^3.25.76: the repo pins zod to 3.x via a root pnpm override, so the whole workspace resolves zod 3. ai-openai@0.17 peers zod ^4 (unmet, advisory) but the strict-schema fix operates on plain JSON Schema, not zod, so it is unaffected. No runtime code change. |
||
|
|
601754b177 |
test(showcase): derive D4 guard probed-route set from probe SSOT + align D4 probe naming (#6084)
## Summary
Three laser-surgical cleanups to the showcase D4 chat-roundtrip probe
and its `domDone` regression guard. Two are behavior-preserving
refactors; one is a test-coverage hardening. No probe control-flow /
outcome behavior changes.
## Changes
### GB2 — derive the guard's probed-route set from the probe SSOT
`d4-probe-domdone-guard.test.ts` hardcoded its probed-route set as a
literal `["agentic-chat","tool-rendering"]` parallel to the probe's own
inline `demo`/`demoPath` literals — a drift hazard if the probe ever
starts driving a new D4 route. Introduced `D4_DEMO_ROUTE_AGENTIC_CHAT`,
`D4_DEMO_ROUTE_TOOL_RENDERING`, and a `D4_PROBED_DEMO_ROUTES`
source-of-truth array in `d4-chat-roundtrip.ts`, wired the two
`runLevel` `demo`/`demoPath` call sites and `hasToolRendering` to them,
and had the guard derive `PROBED_ROUTES` from that export. A future D4
route is now covered automatically. Added a superset assertion so the
derived set can never narrow coverage below `{agentic-chat,
tool-rendering}`. Route strings unchanged → behavior-preserving.
### T2 — consolidate the completion FSM — DEFERRED
Not surgically achievable without behavior risk. The completion state
(`completeAtMs` / `everObserved` / `degraded` plus the per-poll
`observed` / `completed`) is progressively mutated across poll
iterations inside `runAttempt`'s loop and consumed jointly by the
grace/ceiling/floor deadline clamp (`Math.min(Math.max(baseBudgetEnd,
graceEnd), fastFailEnd, attemptCeiling)`) and three early-return sites.
There is no single read-site to redirect into one named source of truth;
a true consolidation would restructure the deadline arithmetic and risk
altering the clamp outcomes on this flap-critical probe. Left as-is per
proportionate-fix discipline.
### T3 — align complete/completed naming (behavior-preserving rename)
`readTurnComplete` returned `{ observed, complete }` while `runAttempt`
returned `{ text, completed, observed }` for the same concept. Renamed
the lower-churn side (`readTurnComplete`'s `complete` → `completed`, 5
refs vs 6) so both use `completed`. The fields are local to `runLevel`,
not exported and not referenced by any test → pure rename, zero behavior
change.
## Proof — behavior preserved
Baseline (origin/main state, before changes):
- `d4-chat-roundtrip.test.ts`: **84 passed**
- `d4-probe-domdone-guard.test.ts`: **41 passed**
- Total: **125 passed**
After changes:
- `d4-chat-roundtrip.test.ts`: **84 passed** (identical — behavior
preserved through T3 rename + GB2 wiring)
- `d4-probe-domdone-guard.test.ts`: **42 passed** (41 original + 1 new
GB2 superset test)
- Total: **126 passed**
The 125 baseline tests all still pass; the only delta is the added GB2
coverage test.
## GB2 guard red-green
On
`showcase/integrations/langgraph-python/src/app/demos/agentic-chat/page.tsx`:
- Mutated `<CopilotChat … />` → `<CopilotChat …>{null}</CopilotChat>`
(children/render-prop form) → guard **RED** (1 failed:
`langgraph-python/agentic-chat renders <CopilotChat/> in the
attribute-bearing self-closing form`).
- Reverted → guard **GREEN** (42 passed).
Mutation fully reverted; net change to the guard's scanned pages is
zero.
## Quality gates
- `oxfmt --check`: clean
- `oxlint`: 0 errors (2 warnings, both pre-existing on lines 954 / 1189,
untouched by this diff)
- `tsc --noEmit`: clean
- `tsc -p tsconfig.build.json` (full build): clean
|
||
|
|
e5e7fc8b96 |
refactor(showcase): align complete/completed naming in D4 probe (T3)
readTurnComplete returned { observed, complete } while runAttempt returned
{ text, completed, observed } for the same concept. Rename the lower-churn
side (readTurnComplete's 'complete' → 'completed') so both use 'completed'.
Pure internal rename — the fields are local to runLevel, not exported and
not referenced by any test. Zero behavior change.
|
||
|
|
041b4a0692 |
test(showcase): derive D4 guard probed-route set from probe SSOT (GB2)
The d4-probe-domdone-guard test hardcoded its probed-route set as a literal
["agentic-chat","tool-rendering"] parallel to the probe's own inline
route literals — a drift hazard if the probe starts driving a new D4 route.
Introduce D4_DEMO_ROUTE_AGENTIC_CHAT / D4_DEMO_ROUTE_TOOL_RENDERING and a
D4_PROBED_DEMO_ROUTES source-of-truth array in the probe, wire the two
runLevel demo/demoPath call sites (and hasToolRendering) to them, and have
the guard derive PROBED_ROUTES from that export. Add a superset assertion so
the derived set can never narrow coverage below {agentic-chat,tool-rendering}.
Behavior-preserving: the route strings are unchanged.
|
||
|
|
da4f99f325 |
showcase: harden notify jobs + bring prod autoUpdates under drift-gate management (#6083)
Follow-ups to #6082 (showcase deploy consolidation), applied after the live prod `autoUpdates` flip. 1. **fix** — the `notify-all-builds-failed` / `notify` jobs had the same cancelled-rollup blind spot as the redeploy guard: an all-legs-cancelled build (one leg cancelled under contention) that really produced **no** successful service sent **no** alert. They now fire on `any_success == 'false'` (guarded by a status function so a user-cancelled run stays silent). Red-green in `redeploy-guard.test.ts` (reads the live workflow guards). 2. **feat** — prod `autoUpdates` is now `"disabled"` (was `"unmanaged"`), bringing prod under drift-gate management now that its live Railway `autoUpdates` are disabled. Both envs are migrated; the gate enforces both. The live staging + prod Railway `autoUpdates` are already disabled, so the drift gate finds live == SSOT on both envs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
3dc43b9ca9 |
feat(showcase): bring prod autoUpdates under drift-gate management
Prod autoUpdates is now "disabled" (was "unmanaged") for every service, so the drift gate enforces prod as well as staging. Paired with disabling autoUpdates on the live prod Railway services. Regenerates the SSOT JSON. |
||
|
|
e0c7fd30ee |
fix(showcase): alert when an all-legs-cancelled build produced no successes
The notify-all-builds-failed and notify jobs keyed off a 'failure' rollup / bare failure(), so a build where every real service failed but one leg was cancelled (contention) rolled up to 'cancelled' and sent no alert — the same blind spot as the redeploy guard. Fire on any_success == 'false' (guarded by a status function so a user-cancelled run stays silent). Extends the guard test. |
||
|
|
bd000f973b |
showcase: consolidate deploy onto CI-explicit path (guard fix, autoUpdates SSOT, drift gate, reconcile) (#6082)
## Showcase deploy-mechanism consolidation Consolidates the showcase Railway deploy path onto a single **CI-explicit** mechanism, so we can safely retire Railway's registry auto-watch (the source of the surprise "Service aimock upgraded to latest" emails). Design proposal: [Notion — Showcase Deploy-Mechanism Consolidation](https://app.notion.com/p/3a33aa38185281e4b64cc5bebde92d91). ### What & why The "aimock upgraded to latest" email was never a per-service config choice — it was a **CI bug** letting Railway's watcher win a race: a Renovate PR that only touches `showcase_build.yml` forces a full-fleet rebuild; the LFS `shell` leg gets cancelled under runner contention; and the `redeploy-staging` guard (`needs.build.result != 'cancelled'`) then skipped the CI redeploy for the **whole fleet**, orphaning aimock's fresh digest for Railway's watcher to pick up. The `autoUpdates` setting itself had also silently drifted (24 services `minor` / 17 none) — tracked in no SSOT, gated by nothing. ### The four changes (one commit each) 1. **`fix(showcase)` — the P0 guard bug.** Relax the `redeploy-staging` **and** `redeploy-staging-starters` guards so a cancelled sibling leg no longer skips the fleet's staging redeploy; they now redeploy the already-computed successful-service list. A guard-evaluation test reads the live workflow `if:` strings and models GitHub's matrix rollup. 2. **`feat(showcase)` — autoUpdates SSOT (per-env, staging-first).** Add a **per-env** `autoUpdates` policy to every service in `railway-envs.ts` — **staging: `disabled`** (enforced), **prod: `unmanaged`** (left exactly as-is until a later migration). Regenerate `railway-envs.generated.json`. CI-explicit redeploy becomes the single deploy path on staging. 3. **`feat(showcase)` — drift gate.** New CI gate fails when a live Railway service's `autoUpdates` diverges from the SSOT. Reads `Environment.config` (autoUpdates isn't on the typed `ServiceSource` output), **enforces managed (`disabled`) envs and skips `unmanaged` ones** (so prod is untouched), **fails closed per-env** on zero-checked, and skips cleanly on fork PRs with no Railway token. 4. **`feat(showcase)` — scheduled reconcile.** CI-owned self-heal (every 15m) comparing each staging service's deployed digest against GHCR `:latest`, re-running the staging redeploy for lagging services and alerting Slack. Invariant: **green ⟺ every in-scope service confirmed current**; any unconfirmed service (lag, digest error, dropped redeploy, empty scope, thrown redeploy) alerts and exits non-zero. ### Verification - Every behavior change carries red-green tests; **230 tests pass**, `tsc` clean, `oxfmt`/`oxlint` clean, generated JSON in sync, workflows parse. - Reviewed via a full CR loop (Tier 3, 5 rounds to convergence); the reconcile's fail-loud invariant was hardened across rounds (silent-green holes, stale-digest ordering, expansion false-positives, test hygiene). ### Rollout (staging-first) - **Staging is flipped live as part of this change** — `autoUpdates` disabled on all staging services (snapshot-first, verified only `autoUpdates` changed). The drift gate now enforces staging. - **Prod is untouched** — its `autoUpdates` stay exactly as-is and the gate marks prod `unmanaged` (skipped). Migrating prod is a deliberate follow-up (flip prod live + change prod SSOT `unmanaged`→`disabled` together) once we're comfortable with staging on the new mechanism. No transition window where anything is unguarded. ### Follow-ups (from CR, non-blocking) - Dedup the reconcile alert's `unconfirmed` list by service key (cosmetic double-listing; exit code already correct). - Harden the sibling `notify-all-builds-failed`/`notify` jobs against the same all-legs-cancelled rollup (pre-existing, in a job this PR doesn't touch). - Minor: `postSlackAlert` try/catch belt; a few added test assertions; comment/doc accuracy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
6b4b1ee179 |
fix(showcase): gate D4 chat probe completion on domDone to close empty-response render race (#6081)
## Incident
At ~21:19Z on 2026-07-20 the prod showcase Feature Matrix showed the
`claude-sdk-python` column whole-column-red (✓0/✗37). It self-recovered
by ~21:30Z. Not infra, not staleness: `/api/health` was 200 throughout,
`commErrorKinds` was empty, and the image was current.
## Root cause
The shared D4 chat probe (`d4-chat-roundtrip.ts`) emitted ONE transient
red — `failureSummary: "empty assistant response"`, no
`errorClass`/`errorDesc`. Because the dashboard's `resolveD4` is
**slug-keyed**, that single `chat:<slug>` row gated all 37 feature cells
for the slug → the whole column went red off one flap.
The producer-side origin is a **render race**. `readTurnComplete()`
gated turn completion on `domDone || sseDone`. `sseDone` is the
transport-level `RUN_FINISHED` counter — a synchronous raw-byte SSE
parse that runs *outside* React and can fire at-or-before the React
commit that actually renders the assistant text. `domDone` (the
`data-copilot-running` true→false DOM edge) is coalesced into that
*same* React commit (`use-agent.tsx`
`batchedForceUpdate`/`queueMicrotask`). Under contention, gating on
`sseDone` let the fast-fail grace window elapse while the DOM was still
empty, redding a turn that was about to render correctly.
## The change
`complete: domDone || sseDone` → `complete: domDone`. The moment
`domDone` is true, the assistant text is already in the DOM (same
commit). `observed` still includes `sseDone`, so a turn whose attribute
never appears still gets the wider polling window rather than
fast-failing. `FIRST_TOKEN_GRACE_MS` and `NON_COMPLETION_RETRY_LIMIT`
are untouched. `domDone` is not a new signal — the probe already
observes that edge via `readTurnState`; this only changes which existing
signal `complete` trusts.
**Throughput-neutral:** `runAttempt` returns on a non-empty
`readAssistantText` *before* `readTurnComplete` is consulted, so the
happy path is unchanged. Only a completed-but-empty turn's
classification changes. A genuinely-empty completed turn still reds
(correct) — only the race false-positive is removed.
## Red → green proof (deterministic, on the real code path)
A new deterministic timing-sim regression (`sseLeadMs` fixture)
decouples `sseDone` from `domDone` *in time* and drives the real
`readTurnComplete`/`runAttempt`. Two cases: a TIMING SIM (sseDone at
send, text at 2500ms past the ~2000ms grace window) and a FORMULA PIN
(sseDone-only, token never arrives → asserts `sends === 2`, catching a
literal revert to `domDone || sseDone` via the retry-fired
discriminator, not a wall-clock threshold).
**RED — test hunks applied on top of UNFIXED probe code:**
```
FAIL src/probes/drivers/d4-chat-roundtrip.test.ts > d4 render-race: sseDone-leads / domDone-lags turn completion (Fix B) > TIMING SIM: sseDone fires EARLY, domDone+text land LATE together → GREEN (RED pre-fix)
AssertionError: expected 'red' to be 'green' // Object.is equality
Expected: "green"
Received: "red"
❯ src/probes/drivers/d4-chat-roundtrip.test.ts:3195:21
FAIL src/probes/drivers/d4-chat-roundtrip.test.ts > d4 render-race: sseDone-leads / domDone-lags turn completion (Fix B) > FORMULA PIN: sseDone alone must NOT flip `complete` — a turn that only ever fires sseDone stalls+retries (does NOT fast-fail as completed-empty)
AssertionError: expected 1 to be 2 // Object.is equality
- Expected 2
+ Received 1
❯ src/probes/drivers/d4-chat-roundtrip.test.ts:3229:19
Test Files 1 failed (1)
Tests 2 failed | 82 skipped (84)
```
**GREEN — probe fix hunk then applied, same tests re-run:**
```
✓ src/probes/drivers/d4-chat-roundtrip.test.ts (84 tests | 82 skipped) 9026ms
✓ d4 render-race: sseDone-leads / domDone-lags turn completion (Fix B) > TIMING SIM: sseDone fires EARLY, domDone+text land LATE together → GREEN (RED pre-fix) 5017ms
✓ d4 render-race: sseDone-leads / domDone-lags turn completion (Fix B) > FORMULA PIN: sseDone alone must NOT flip `complete` — a turn that only ever fires sseDone stalls+retries (does NOT fast-fail as completed-empty) 4007ms
Test Files 1 passed (1)
Tests 2 passed | 82 skipped (84)
```
Full `d4-chat-roundtrip.test.ts` suite after the fix: **84 passed (84)**
— no regression.
## Real-probe forcing (Part B) — honest disclosure
The live race is low-rate and non-deterministic. The `--direct`
(direct-LLM) live-probe forcing path could **not** be stood up within
reasonable effort in this environment: Docker is running, but `--direct`
requires a real Anthropic API key that is not present here, and forcing
a probabilistic React-commit-timing race across ~300 reps on a
freshly-built `claude-sdk-python` integration stack is beyond a
reasonable bound for the bonus real-surface proof. It was **not** faked.
The deterministic timing-sim regression above exercises the real
`readTurnComplete`/`runAttempt` code path and is the gating proof.
**Recommendation:** a multi-tick staging dashboard watch post-merge to
confirm the flap does not recur.
## Scope note
This PR fixes the **producer-side** root cause. The **render-layer
de-amplifier** (a single transient D4 flap should degrade a slug's cells
to *amber*, not whole-column-red via slug-keyed `resolveD4` fan-out) is
owned separately by the dashboard-ladder redesign.
## CR follow-ups (post-review hardening)
Three small follow-ups from the 7-agent CR + adversarial verify (which
found zero live bugs in the Fix B core). The `complete: domDone` core is
untouched.
- **Regression-guard test (hardening).** New
`d4-probe-domdone-guard.test.ts` (source-level, TS AST). It asserts
every D4-probed demo page — `/demos/agentic-chat` for every integration,
`/demos/tool-rendering` where present — renders `<CopilotChat/>` in the
attribute-bearing **self-closing** form, not the children render-prop /
slot form. Only the self-closing form hits the `CopilotChatView` branch
that emits `data-testid="copilot-chat"` + `data-copilot-running`, which
the probe's `domDone` gate reads; the `if (children)` branch returns a
`display:contents` wrapper with neither, which would silently regress
the cell to the ~60s / double-send fallback. That regression is
invisible to the probe's own fake-injected unit tests, so it is guarded
structurally at CI time. Chose the source/AST approach over full page
render because the pages are Next.js `"use client"` app-router
entrypoints mounting a live `<CopilotKit runtimeUrl=.../>` provider +
framework agents (impractical to render faithfully in a harness unit
test).
**Red-green proof.** Temporarily mutated
`langgraph-python/agentic-chat/page.tsx` to the children render-prop
form → guard **RED** (`langgraph-python/agentic-chat … expected 0 to be
greater than or equal to 1`, 1 failed | 40 passed). Reverted the
mutation → **GREEN** (41 passed). Mutation fully reverted; net change is
the test only.
- **Comment factual fix.** In `d4-chat-roundtrip.ts` near the `complete:
domDone` gate: the comment said `observed` still includes `sseDone`
"(below)", but `observed` is defined *above*. Corrected "(below)" →
"(above)".
- **Timing-sim robustness pin.** The `TIMING SIM` test's discriminating
power depended on `FIRST_TOKEN_GRACE_MS (2000) < firstTokenDelayMs
(2500) < ceiling (~4000)`, encoded only in prose. Now imports the actual
`FIRST_TOKEN_GRACE_MS` source constant (newly exported) and asserts that
ordering, so raising the grace constant later fails the test loudly
instead of silently ceasing to discriminate. No existing assertion
weakened.
Quality: harness `d4-chat-roundtrip.test.ts` + new guard test green (125
tests); `tsc --noEmit` clean; `tsc -p tsconfig.build.json` clean; `oxfmt
--check` clean; `oxlint` warnings-only (no errors).
|
||
|
|
eddfcc07e8 |
docs(showcase): fix stale cross-reference in D4 probe comment
The comment near the complete:domDone gate said `observed` still includes `sseDone` "(below)" — but `observed` is defined ABOVE the comment, not below. Correct "(below)" to "(above)". |
||
|
|
4bf796b713 |
test(showcase): guard D4 probe domDone gate + pin first-token grace ordering
Add a source-level (TS AST) regression guard asserting every D4-probed demo page (/demos/agentic-chat always; /demos/tool-rendering where present) renders <CopilotChat/> in the attribute-bearing self-closing form, not the children render-prop form. The self-closing form is the CopilotChatView branch that emits data-testid="copilot-chat" + data-copilot-running, which the probe's domDone completion gate reads; the render-prop branch omits it, which would silently regress the cell to the ~60s/double-send fallback path. Invisible to the probe's own fake-injected unit tests, so guarded structurally at CI time. Also pin the TIMING SIM test's discriminating window against the actual FIRST_TOKEN_GRACE_MS source constant (now exported): assert FIRST_TOKEN_GRACE_MS < firstTokenDelayMs < attempt-0 ceiling so that raising the grace constant later fails the test loudly instead of silently ceasing to discriminate pre-fix vs post-fix. |
||
|
|
a33e313df8 |
feat(showcase): make autoUpdates per-env for staging-first rollout
autoUpdates is now per-env: staging is enforced "disabled" while prod is "unmanaged" (the drift gate skips it) so prod stays untouched until a later migration. The gate enforces managed envs and skips unmanaged ones; the zero-checked floor applies only to managed envs. Regenerates the SSOT JSON. |
||
|
|
50805ab47d |
docs: fix stale quickstart/link references and add MCP Codex setup (#6079)
## What & why Three independent documentation-accuracy fixes, batched into one PR. ### 1. Dead spec links + gen-ui page gaps (Closes #3975) `generative-ui-specs-overview.mdx` (rendered at `/whats-new/generative-ui-spec-support`) linked to the retired `/generative-ui/specs/<spec>` subgroup. Repointed to canonical destinations and added the frameworks list the issue asked for. **Verified live (HTTP status against docs.copilotkit.ai):** | Link | Before | After | | --- | --- | --- | | A2UI | `/generative-ui/specs/a2ui` (301 hop) | `/generative-ui/a2ui` → **200** | | MCP Apps | `/generative-ui/specs/mcp-apps` (301 hop) | `/generative-ui/mcp-apps` → **200** | | Open Generative UI (new) | — | `/generative-ui/open-generative-ui` → **200** | - **Supported Frameworks** list added — all 12 `/<slug>/quickstart` targets return **200** live (LangGraph Py/TS, Google ADK, MS Agent, AWS Strands, Mastra, PydanticAI, CrewAI, Agno, AG2, LlamaIndex, Claude Agent SDK, Deep Agents). - **Open-JSON-UI is intentionally NOT linked:** `/generative-ui/open-json-ui` is a placeholder pulled from the nav and redirected to `/generative-ui` on purpose (`next.config.ts` — `// AI-slop placeholder pulled from nav until properly authored`). Linking only the two specs that have live detail pages avoids sending readers to a redirect. Open-JSON-UI is still described in the comparison table on the page. - Open Generative UI is a CopilotKit capability (not an external spec), so it sits under "related capabilities." > Note: the issue/support-bot suggested a `/learn/...` path — there is no `/learn/` tree in shell-docs; the canonical homes are the flat `/generative-ui/<spec>` pages. ### 2. CLI `init` vs. existing app (Closes #2525) Maintainer resolution was "fix the docs." The original "`init` bootstraps your existing Next.js app" claim was already removed in the shell-docs migration (the reported `/direct-to-llm/guides/quickstart` now resolves to the Built-in Agent quickstart, which is fully manual). To remove the remaining ambiguity: - **Built-in Agent quickstart:** added an "Already have an app?" callout — existing apps skip `create-next-app`. - **CLI guide (`cli.mdx`):** clarified that `create` (aliased `init`) scaffolds a brand-new project in its own directory and does not detect/bootstrap an existing app; points to the manual install in the Quickstart. Verified against `copilotkit@latest` (4.3.0): `init --help` → *"Initialize a **new** CopilotKit project … before scaffolding"*, `-n, --name` *"names the local app **and its directory**"*, and `init`/`create` are aliases. ### 3. Codex setup for the MCP guide (Closes #2526) Added a **Codex** section to `mcp-server-setup.mdx` using the stdio `mcp-remote` bridge in `~/.codex/config.toml`, matching the page's existing command-based pattern (Cursor / Windsurf / Claude Desktop), plus the `codex mcp add` shortcut. Verified against the installed Codex CLI: `codex mcp --help` lists `add`/`list`/`get`/`remove`, and the `[mcp_servers.<name>]` table with `command`/`args` matches OpenAI's Codex config reference. Per the issue thread, the macOS `mcp-remote` port-blocking concern is **not** claimed to be solved — only the Codex config is documented. ## Testing - **#3975 (links):** curled every added/changed URL against the live docs — A2UI, MCP Apps, Open Generative UI, and all 12 framework quickstarts return **200**; confirmed `/generative-ui/open-json-ui` is a deliberate redirect (hence unlinked). Pre-existing `/ag-ui-protocol` and `/generative-ui` links are stable 301→200 and left as-is. - **#2525 (CLI):** ran `npx copilotkit@latest init --help` on the published `latest` (4.3.0) — confirmed new-directory scaffolding, no existing-app detection; verified `[Quickstart](/quickstart)` serves the manual-install page live (`create-next-app` + "Install CopilotKit packages"). - **#2526 (Codex):** ran `codex mcp --help` to confirm subcommands; new section reuses the file's existing `<Steps>`/fenced-code structure. `<Callout>` is a registered global MDX component (`src/lib/mdx-registry.tsx`), already used unimported on the Built-in Agent quickstart. - Docs-only; no code paths affected. Closes #3975 Closes #2525 Closes #2526 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
077913e5b4 |
feat(showcase): scheduled staging reconcile with Slack self-heal
Adds a CI-owned reconcile (every 15m) that compares each staging service's deployed digest against GHCR :latest and re-runs the staging redeploy for lagging services, alerting Slack. The run is green only when every in-scope service is confirmed current; any unconfirmed service (lag, digest error, dropped redeploy, empty scope, or a thrown redeploy) alerts and exits non-zero. Exposes per-service redeploy records from redeploy-env for accurate per-service remediation confirmation. |
||
|
|
b34debc02b |
feat(showcase): add autoUpdates drift gate against live Railway config
New CI gate fails when a live Railway service's autoUpdates diverges from the SSOT (every service must be disabled). Reads Environment.config (autoUpdates is not on the typed ServiceSource output), fails closed per-env when it verifies zero services, and skips cleanly on fork PRs that lack a Railway token. |
||
|
|
2ecba43d2f |
feat(showcase): track autoUpdates in SSOT, disabled fleet-wide
autoUpdates was tracked nowhere and had drifted (24 services minor / 17 none). Add an explicit disabled autoUpdates policy to every service in railway-envs.ts and regenerate railway-envs.generated.json, making CI-explicit redeploy the single deploy path instead of Railway's registry auto-watch. |
||
|
|
2d6883568e |
fix(showcase): don't skip staging redeploy when a build leg is cancelled
The redeploy-staging and redeploy-staging-starters jobs guarded on needs.build.result != 'cancelled', so a single cancelled matrix leg (e.g. the Git-LFS shell build under runner contention) skipped the whole fleet's staging redeploy even when the other 27 services built fine. Relax both guards to redeploy the already-computed successful-service list. Adds a guard-evaluation test that reads the live workflow if: strings and models GitHub's matrix rollup. |
||
|
|
cae8e78ac8 |
fix(showcase): gate D4 chat probe completion on domDone to close empty-response render race
readTurnComplete() gated turn completion on `domDone || sseDone`. sseDone (the
transport-level RUN_FINISHED counter) is a synchronous raw-byte parse OUTSIDE
React and can fire at-or-before the React commit that renders the assistant
text; domDone is coalesced into that SAME commit (use-agent.tsx
batchedForceUpdate / queueMicrotask). Gating on sseDone let the fast-fail grace
window elapse with the DOM still empty under contention, redding a turn that was
about to render correctly ("empty assistant response").
Gate completion on domDone alone. observed still includes sseDone, so a turn
whose attribute never appears still gets the wider polling window. Throughput-
neutral: runAttempt returns on non-empty readAssistantText before
readTurnComplete is consulted, so the happy path is unchanged; a genuinely-empty
completed turn still reds.
|
||
|
|
45898bd1b6 |
test(showcase): pin D4 chat probe sseDone-leads/domDone-lags render race
Add a deterministic timing-sim regression for the D4 chat-roundtrip probe render race. The sseLeadMs fixture decouples the transport RUN_FINISHED counter (sseDone) from the DOM run-stop edge (domDone) in time, so a turn whose sseDone fires early while domDone + assistant-text land later in the same React commit is exercised on the real readTurnComplete/runAttempt path. Two cases: a TIMING SIM (sseDone at send, text at 2500ms past the grace window) that reds pre-fix, and a FORMULA PIN (sseDone-only, token never arrives) asserting sends===2, catching a literal revert to domDone||sseDone via the retry-fired discriminator rather than a wall-clock threshold. |
||
|
|
7869d31e64 |
docs: drop unpublished Open-JSON-UI link, move Open Generative UI to related
CR: /generative-ui/open-json-ui is a deliberately-unpublished placeholder (next.config.ts redirects it to /generative-ui, pulled from nav until authored), so link only the two specs with live detail pages (A2UI, MCP Apps). Open Generative UI is a CopilotKit capability rather than an external spec, so it moves under related capabilities. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c9511cf4f9 |
docs: fix stale quickstart/link references and add MCP Codex setup
Fixes three independent documentation-accuracy issues: - #3975: repoint the retired /generative-ui/specs/<spec> links to the canonical flat /generative-ui/<spec> paths, add an Open Generative UI entry, and add a Supported Frameworks list on the Generative UI Spec Support page. - #2525: clarify that the CLI `create`/`init` scaffolds a brand-new project in its own directory and does not bootstrap an existing app; point existing-app users to manual installation. - #2526: add a Codex setup section to the MCP server guide using the stdio `mcp-remote` bridge, matching the page's existing pattern. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
69e6be253a |
feat(showcase): add outcome reaction to promote-notify init Slack message (#6078)
## What & why The `showcase_promote_notify` workflow posts an init message to `#team-showcase`, then a threaded reply summarizing the run outcome. Operators wanted the *net* result visible at a glance on the original init message without clicking into the thread. This adds an emoji **reaction** to the original init message reflecting the run outcome via Slack's `reactions.add` API. ### Outcome → emoji mapping | `outcome` | reaction name | emoji | |-----------|---------------|-------| | `success` | `white_check_mark` | ✅ | | `partial` | `warning` | ⚠️ | | `total` | `x` | ❌ | ### Implementation notes - **`showcase_promote_notify.yml`** — after the thread reply, maps `outcome` → reaction name with a `case` and calls the existing `slack_api` helper with `reactions.add` (body `{channel, timestamp, name}` — note `timestamp`, not `ts`, for `reactions.add`). Guarded: only attempts when both `init_ts` and `init_channel_id` are non-empty (init post may have failed → skip with a `::warning::`). The reaction is informational, so a failed add is **warn-only** (`|| true`), mirroring the thread-reply idiom — NOT the fail-loud `#oss-alerts` page. - **`showcase_promote_notify.dry-run.sh`** — makes no real Slack calls, so it emits the reaction it *would* add as a `--- reactions.add ---` block. The `outcome`→reaction-name `case` is byte-identical to the `.yml`. - **`promote-notify.bats`** — new tests assert the emitted reaction name per fixture, plus a new anti-drift parity guard that the reaction mapping matches between the `.yml` and the `.sh` mirror (mirroring the existing `slack_alert_posted_ok` parity test). ## Red-Green Proof The real failure surface is the dry-run harness + bats suite. ### RED — before the change Dry-run on all three fixtures emits **no** `reactions.add` line (`grep -c` = 0 each): ``` ########## RED dry-run: success.json ########## -> grep reactions.add: 0 ########## RED dry-run: partial.json ########## -> grep reactions.add: 0 ########## RED dry-run: total-failure.json ##### -> grep reactions.add: 0 ``` New bats tests fail (existing 1–11 pass): ``` ok 11 call-site: both posts ok → zero exit, no warning not ok 12 reaction: success outcome adds white_check_mark to the init message not ok 13 reaction: partial outcome adds warning to the init message not ok 14 reaction: total-failure outcome adds x to the init message not ok 15 reaction: yml and sh reaction-name mapping is identical (anti-drift) ``` ### GREEN — after the change Dry-run emits the correct reaction per outcome: ``` ########## GREEN dry-run: success.json ########## --- reactions.add --- channel: #team-showcase (ts=<init_ts>) name: white_check_mark ########## GREEN dry-run: partial.json ########## --- reactions.add --- channel: #team-showcase (ts=<init_ts>) name: warning ########## GREEN dry-run: total-failure.json ########## --- reactions.add --- channel: #team-showcase (ts=<init_ts>) name: x ``` Full bats suite passes (15/15): ``` ok 1 slack_alert_posted_ok: ok:true response returns 0 and emits no warning ... ok 11 call-site: both posts ok → zero exit, no warning ok 12 reaction: success outcome adds white_check_mark to the init message ok 13 reaction: partial outcome adds warning to the init message ok 14 reaction: total-failure outcome adds x to the init message ok 15 reaction: yml and sh reaction-name mapping is identical (anti-drift) ``` `shellcheck .github/workflows/showcase_promote_notify.dry-run.sh` → clean (exit 0). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01F6rwtyRSUFtgiAY2dYuyU2 |
||
|
|
305cfd494b |
feat(showcase): add outcome reaction to promote-notify init Slack message
Add an emoji reaction to the original promote-notify init message reflecting the net run outcome, so operators can see success/failure at a glance without opening the thread reply: success -> white_check_mark (checkmark) partial -> warning total -> x The live workflow calls reactions.add on the init post (guarded on a successful init post, warn-only on failure to mirror the thread reply). The dry-run harness emits the reaction it would add, using a byte-identical case mapping enforced by a new anti-drift bats guard. Adds bats coverage asserting the emitted reaction name per fixture. |
||
|
|
999264f648 |
chore: bump aimock to 1.37.4 (multi-turn fixture matching fix) (#6071)
Bumps the showcase's `@copilotkit/aimock` dependency from `1.26.1` to **`1.37.4`** so the showcase's record/replay fixture stack picks up the multi-turn fixture-matching fix. **Why:** aimock v1.37.4 (aimock #319) fixes record/replay `hasToolResult` symmetry — recorded multi-turn fixtures now match on replay. The showcase records/replays LLM fixtures for its demo cells, so this pulls the fix into the showcase. **What changed** - `showcase/scripts/package.json`: `@copilotkit/aimock` `1.26.1` → `1.37.4` (exact pin, matching existing style) - `showcase/scripts/package-lock.json`: regenerated via `npm install --package-lock-only` (this lock is consumed by `npm ci` in the shell/shell-docs/shell-dashboard Dockerfiles) - `pnpm-lock.yaml`: regenerated via `pnpm install --lockfile-only` (showcase/scripts is a pnpm workspace member) The only version change is aimock (and its transitive tree in the npm lock). The minor eslint-config-next peer-resolution relabeling in `pnpm-lock.yaml` is benign normalization — no package version changes; both jiti variants already existed in the lock. **Validation gap:** this is a dependency bump only. Full validation (running the showcase multi-turn recording against 1.37.4 to confirm the recorded fixtures match on replay) requires the running showcase stack and is not exercised here. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
107a17e493 |
fix(showcase): wire langroid declarative-gen-ui via Option A (JS-injected A2UI) (#6070)
## Summary Supersedes #6058's two-stage approach (outer `generate_a2ui` → secondary Python LLM call → `render_a2ui`), which severed across the prod streaming boundary. **Option A** (mirroring crewai-crews #6067): `injectA2UITool` defaults to `true`, so CopilotKit's `A2UIMiddleware` injects `render_a2ui` into `RunAgentInput.tools`. The langroid `agui_adapter.py` now merges those injected tools into its OpenAI call, so the LLM calls `render_a2ui` directly. The middleware intercepts the tool call stream, builds `a2ui_operations`, and fires `RUN_FINISHED` — no secondary Python LLM pass needed. ## Changes - **`agent.py`**: Remove ~550 lines of two-stage A2UI infrastructure (`generate_a2ui_via_llm`, `_a2ui_error`, `_resolve_a2ui_model`, `_get_a2ui_llm`, `_RENDER_A2UI_FUNCTION_SPEC`, etc.). Replace `GenerateA2UITool.handle` with a stub that logs loudly on regression (middleware should always intercept before reaching Python). - **`agui_adapter.py`**: Merge `run_input.tools` (AG-UI-injected) into the OpenAI tools list so `render_a2ui` is visible to the LLM. Remove `set_last_user_message` call (ContextVar no longer needed). - **`route.ts`**: Remove `injectA2UITool: false`; keep `defaultCatalogId` pin. - **`gen-ui-declarative.json`**: Replace 9 two-stage fixtures with 4 single-stage fixtures matching `toolName: render_a2ui` + `context: langroid`. ## Root cause of prior RED The langroid adapter builds its OpenAI tool list from `ALL_TOOLS` (Python-side registry) via `_get_openai_tools()`, which does NOT include `render_a2ui`. The `A2UIMiddleware` injects `render_a2ui` into `RunAgentInput.tools` at the AG-UI protocol level, but `agui_adapter.py` ignored `run_input.tools` entirely — so the LLM never saw `render_a2ui` in its tool list, never called it, and the fixture never matched. ## Red-green proof **RED** (from main, before changes): ``` ✗ d6:langroid/gen-ui-declarative red (0.0s) state=red 0 passed, 1 failed ``` **GREEN** (after this PR's changes, rebuild from worktree): ``` ✓ d6:langroid/gen-ui-declarative green (0.0s) 1 passed ✓ Tests passed for langroid:declarative-gen-ui ``` Test command: `bin/showcase test langroid:declarative-gen-ui --d6 --isolate --rebuild` ## Related - Supersedes #6058 (two-stage approach, now reverted in this integration) - Mirrors #6067 (crewai-crews Option A fix, same pattern) |
||
|
|
683ce92c5b | chore: bump aimock to 1.37.4 (multi-turn fixture matching fix) | ||
|
|
1196c7b637 |
test(showcase): align langroid test_generate_a2ui with Option A (JS-injected A2UI)
Option A removed the two-stage server-side A2UI planner (generate_a2ui_via_llm, _get_a2ui_llm, _resolve_a2ui_model, _A2uiError, _A2uiErrorKind, _RENDER_A2UI_FUNCTION_SPEC, _RENDER_A2UI_TOOL_SPEC, _a2ui_error). The CopilotKit JS runtime A2UIMiddleware now intercepts generate_a2ui before it reaches Python and drives the render_a2ui LLM pass itself. test_generate_a2ui.py was importing the removed symbols at collection time, causing an ImportError that failed CI's "Run showcase package Python unit tests" step for Python 3.12. Fix: remove all tests for the deleted two-stage planner infra; rewrite GenerateA2UITool.handle() tests to the Option A contract (handle fires only on middleware regression, returns structured error JSON, logs ERROR); retain all tests that remain valid: _ToolErrorKind enum identity, backend tool handle() happy+error paths, create_agent wiring, module hygiene (no openai at load time, clean subprocess import). |
||
|
|
46f810779c |
fix(showcase): wire langroid declarative-gen-ui via Option A (JS-injected A2UI)
Supersedes #6058's two-stage approach (outer generate_a2ui → secondary Python LLM call → render_a2ui), which severed across the prod streaming boundary. Option A: `injectA2UITool` (default true) causes CopilotKit's A2UIMiddleware to inject `render_a2ui` into RunAgentInput.tools. The langroid agui_adapter now merges those injected tools into its OpenAI call so the LLM can call render_a2ui directly. The middleware intercepts the tool call stream, builds a2ui_operations, and fires RUN_FINISHED — no secondary Python LLM pass needed. Changes: - agent.py: remove ~550 lines of two-stage A2UI infrastructure (generate_a2ui_via_llm, _a2ui_error, _resolve_a2ui_model, _get_a2ui_llm, etc.); replace GenerateA2UITool.handle with a stub that logs loudly if middleware interception regresses - agui_adapter.py: merge run_input.tools (AG-UI-injected) into the OpenAI tools list so render_a2ui is visible to the LLM; remove set_last_user_message call - route.ts: remove injectA2UITool: false; keep defaultCatalogId pin - gen-ui-declarative.json: replace 9 two-stage fixtures with 4 single-stage fixtures matching toolName: render_a2ui + context: langroid (mirrors crewai-crews Option A) Mirrors the crewai-crews fix from #6067. |
||
|
|
54eea138b8 |
fix(showcase): wire ag2 declarative-gen-ui via Option A (JS-injected A2UI) (#6069)
## Summary - **Route**: Drop `injectA2UITool: false` from `copilotkit-declarative-gen-ui/route.ts` — default `true` enables JS middleware injection - **Backend**: Replace the complex inner-LLM two-stage body in `a2ui_dynamic.py` with a fail-loud stub matching the crewai-crews Option A pattern (no more openai/AsyncOpenAI, no `_request_context`, no `tools/RENDER_A2UI_TOOL_SCHEMA`) - **Fixture**: Update `_meta` note and `_comment` fields to reflect Option A; fixture structure was already correct for aimock two-stage matching (outer `generate_a2ui` matched by `context:ag2`; inner `render_a2ui` matched by `toolName:render_a2ui`) ## Why Option A works AG2's AG-UI adapter has no Python-side A2UI injection. Option A routes the secondary LLM pass through the JS CopilotKit runtime middleware, which intercepts the agent's `generate_a2ui` toolcall, drives `render_a2ui` itself, synthesises the tool result, and fires `RUN_FINISHED`. This is the same pattern as the merged crewai-crews fix (#6067) and mirrors the green langgraph-python sibling. The previous two-stage backend approach failed under aimock because the backend's inner `AsyncOpenAI` call to `render_a2ui` bypassed aimock entirely (aimock only intercepts the frontend→backend path). ## Red → Green evidence **RED** (pristine, before changes): ``` ▸ Testing ag2:declarative-gen-ui (--d6)... ▸ Isolation active: project=showcase-iso19 slot=19 ✗ d6:ag2/gen-ui-declarative red (0.0s) state=red 0 passed, 1 failed ⚠ Tests failed for ag2:declarative-gen-ui (exit 1) ``` **GREEN** (after Option A changes): ``` ▸ Testing ag2:declarative-gen-ui (--d6)... ▸ Isolation active: project=showcase-iso20 slot=20 ✓ d6:ag2/gen-ui-declarative green (0.0s) 1 passed ✓ Tests passed for ag2:declarative-gen-ui ``` ## Files changed - `showcase/integrations/ag2/src/app/api/copilotkit-declarative-gen-ui/route.ts` — drop `injectA2UITool: false`, update header comment - `showcase/integrations/ag2/src/agents/a2ui_dynamic.py` — replace inner-LLM body with fail-loud stub - `showcase/aimock/d6/ag2/gen-ui-declarative.json` — update `_meta`/`_comment` for Option A 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
5a35379906 |
docs: add Thread & History Lifecycle guide (#5988)
## What & why
Adds a new framework-agnostic guide — **Thread & History Lifecycle**
(`docs/threads-lifecycle.mdx`) — that walks the full client-side
lifecycle of a conversation thread as one narrative. It fills the gap
between the [Headless Threads](/threads) how-to and the [Threads &
Persistence Architecture](/premium/threads-explained) explanation, and
directly answers a recurring cluster of support questions.
## Sections
- **How the threadId is created** — UUID v4, client-minted at mount, the
resolution precedence, and the remount-stability caveat (auto-minted ids
re-mint on remount / StrictMode; pass an explicit `threadId` for
continuity).
- **How history is restored** — explicit-`threadId` `connect()` replay
vs. manual `agent.setMessages(...)`; clarifies there is **no v2
`initialMessages`** and no v2 `useCopilotChat` (read via
`useAgent().agent.messages`).
- **Switching / starting threads** — `setActiveThreadId(id, { explicit
})` and `startNewThread()`, plus the prop-controlled no-op guard.
- **Creating a thread with your own API on first message** —
mint-up-front + `setActiveThreadId`/`threadId` prop as the robust path;
the headless `CopilotChatInput.onSubmitMessage` seam for submit-time
interception (noting the built-in `<CopilotChat>` overrides it).
- **CopilotKit threads vs. your framework's checkpointer** — two layers
correlated only by `threadId`; a LangGraph checkpointer creates
checkpoint tables, not a CopilotKit "threads" table.
- **MCP Apps activity & history** — activity messages are
frontend/middleware constructs (no server store); re-synthesize on
hydration.
- **v1 vs v2** disambiguation (incl. the two different `useThreads`
hooks).
## Addresses
Recurring thread-lifecycle questions: #4790, #4778, #5434, #2242, #5931.
(I'll close those pointing here once this lands.)
## Testing / accuracy
All referenced APIs verified present on `main`: `useThreads` (v2),
`useCopilotChatConfiguration` (`setActiveThreadId`/`startNewThread`),
`useAgent().agent.setMessages/addMessage`,
`CopilotChatInput.onSubmitMessage`, `<CopilotChat threadId>`, and the
`mcp-apps` activity type. All five cross-doc links resolve. Added to the
"Threads" group in `docs/meta.json`.
Note: written against the current v2 APIs — three details were corrected
against source during authoring (`startNewThread` not `createThread`;
`onSubmitMessage` is headless-only; no v2
`useCopilotChat`/`initialMessages`).
|
||
|
|
0408f821a7 |
fix(showcase): wire ag2 declarative-gen-ui via Option A (JS-injected A2UI)
Remove the backend two-stage inner-LLM pattern (injectA2UITool:false + Python-side secondary openai call) in favour of Option A: the CopilotKit JS runtime middleware intercepts the agent's no-arg generate_a2ui toolcall and drives the render_a2ui secondary LLM pass itself, synthesising the tool result and firing RUN_FINISHED. Matches the just-merged crewai-crews fix (#6067) and mirrors langgraph-python's green reference pattern. Changes: - route.ts: drop `injectA2UITool: false` (default true enables JS injection) - a2ui_dynamic.py: replace complex inner-LLM body with a fail-loud stub (no more openai/AsyncOpenAI import, no _request_context dependency, no tools/RENDER_A2UI_TOOL_SCHEMA import) - gen-ui-declarative.json: update _meta note + _comment fields to reflect Option A (fixture structure was already correct for two-stage aimock matching; outer generate_a2ui matched by context:ag2, inner render_a2ui matched by toolName:render_a2ui) Red→Green: D6 control-plane harness confirmed red before (state=red, exit 1) and green after (1 passed, exit 0). |
||
|
|
8d9e077b63 |
fix(showcase): wire crewai-crews declarative-gen-ui via Option A (JS-injected A2UI) (#6067)
## Summary
- **route.ts**: remove `injectA2UITool: false` (enables JS middleware
injection); keep `defaultCatalogId: "declarative-gen-ui-catalog"` to
prevent "Catalog not found" render errors when models omit `catalogId`.
- **declarative_gen_ui.py**: replace `GenerateA2uiTool` (Python body
that would drive a secondary LLM pass — impossible in `ag_ui_crewai`,
which has no `CopilotKitMiddleware`) with a no-arg
`_GenerateA2uiNoArgTool` that raises loudly if called directly. The JS
`A2UIMiddleware` intercepts the `generate_a2ui` toolcall before Python
ever sees it and drives the secondary `render_a2ui` pass itself.
- **definitions.ts + renderers.tsx**: add `DataTable` component
(columns/rows schema + `declarative-data-table` testid); add missing
`declarative-info-row` testid to `InfoRow`. Both were present in the
`langgraph-python` reference catalog but absent from `crewai-crews`.
Required by D5 harness turns 2 and 4.
- **gen-ui-declarative.json**: rewrite D6 aimock fixtures from broken
two-stage pattern (`generate_a2ui` → inner `render_a2ui`) to correct
single-stage (LLM calls `render_a2ui` directly). `ag_ui_crewai` has no
Python-side injection; the middleware's `complete()` synthesizes the
tool result and fires `RUN_FINISHED` after streaming all
`TOOL_CALL_CHUNK` events through AG-UI.
## Architecture note
`langgraph-python` uses **two-stage A2UI**: outer `generate_a2ui` →
Python `CopilotKitMiddleware` drives inner `render_a2ui`. `crewai-crews`
uses **single-stage**: JS `A2UIMiddleware` intercepts `generate_a2ui`
(toolcall in the agent's tool list), fires a secondary LLM call itself
passing `render_a2ui` in the tools list, the LLM calls `render_a2ui`
directly, and `ag_ui_crewai` streams the `TOOL_CALL_CHUNK` events
through AG-UI to the middleware.
## RED → GREEN proof
**RED (main, `injectA2UITool: false`):**
```
[conversation-runner] turn 1/4 — FAILED {
error: 'waitForTurnComplete: turn 1 did not complete within 90000ms
(reason=surface-missing, runsFinished=1, ...)'
```
Every pill: "CrewAI flow failed; see server logs" — `render_a2ui` not in
the agent tool list, aimock fixture never fired, no surface painted.
**GREEN (this branch):**
```
[conversation-runner] turn 1/4 — assertions passed
[conversation-runner] turn 2/4 — assertions passed
[conversation-runner] turn 3/4 — assertions passed
[conversation-runner] turn 4/4 — assertions passed
[conversation-runner] conversation completed successfully { turnsCompleted: 4, totalDurationMs: 8524 }
✓ d6:crewai-crews/gen-ui-declarative green (0.0s)
1 passed
```
All 4 pills pass with full component-tree assertions
(Metric×4+PieChart+BarChart / DataTable+BarChart /
StatusBadge×3+Metric×3 / InfoRow×7+PieChart).
## Adapter-forwarding value-test
Turn 1 passing confirms the full Option A path end-to-end:
`generate_a2ui` in tool list → JS `A2UIMiddleware` fires secondary
`render_a2ui` LLM pass → aimock returns component tree → `ag_ui_crewai`
streams `TOOL_CALL_CHUNK` events → middleware builds `a2ui_operations` →
frontend catalog renders
`declarative-metric`/`declarative-pie-chart`/`declarative-bar-chart`
testids with correct counts.
|
||
|
|
73f7f88f22 |
fix(ci): deploy starter-only changes (showcase_build redeploy gap) (#6068)
## The incident PR #6061 (`fix(starters): add python-multipart to agno starter`) merged, its `starter-agno` image built to GHCR via `showcase_build.yml`'s `build-starters` job — and then was **never deployed to Railway**. `starter-agno` stayed crashed until someone manually redeployed. That is not a one-off: it is structural. Any change touching **only** starter files (`examples/integrations/<slug>/**`) hits the same hole. ## Root cause (job-graph) `showcase_build.yml` has two independent lanes: | Lane | Detect | Build | Aggregate | Redeploy | | --- | --- | --- | --- | --- | | **Showcase fleet** | `detect-changes` | `build` (matrix) | `aggregate-build-results` | `redeploy-staging` | | **Starters** | `detect-starter-changes` | `build-starters` (matrix) | — | **(none)** | `redeploy-staging` is scoped **entirely to the showcase fleet**: ``` redeploy-staging: needs: [detect-changes, build, aggregate-build-results] if: >- !cancelled() && needs.detect-changes.outputs.has_changes == 'true' && needs.build.result != 'skipped' && needs.build.result != 'cancelled' && needs.aggregate-build-results.outputs.any_success == 'true' ``` (`.github/workflows/showcase_build.yml:780-799`) On a **starter-only** push: - `detect-changes` filters are all `showcase/**` paths → none match `examples/integrations/**` → `has_changes=false` → `build` skips → `aggregate-build-results` skips → `redeploy-staging` skips (fails its `has_changes=='true'` and `build.result != 'skipped'` clauses). - `detect-starter-changes` matches → `build-starters` builds `starter-<slug>:latest` to GHCR — **and stops.** There is no aggregate and **no redeploy job for the starter lane at all.** Net: the starter image is built and pushed, but nothing ever calls Railway's `serviceInstanceRedeploy`, so the running container keeps the stale image. The `starter-build-result-*` per-slot artifacts already emitted by `build-starters` were **write-only** — nothing consumed them. ## The fix A new `redeploy-staging-starters` job that mirrors `redeploy-staging` for the starter lane, reusing existing mechanisms (no new script, no new aggregator): ``` redeploy-staging-starters: needs: [detect-starter-changes, build-starters] if: >- !cancelled() && needs.detect-starter-changes.outputs.has_changes == 'true' && needs.build-starters.result != 'skipped' && needs.build-starters.result != 'cancelled' ``` Steps: 1. Download the already-emitted `starter-build-result-*` artifacts (`pattern` download → succeeds with zero matches if the build crashed before writing any). 2. Compute `matrix ∩ build-success`: read each per-slot `{"service":"<raw slug>","status":...}`, keep `status:success` slugs, map each **raw slug → `starter-<slug>` SSOT key** via the starter matrix `.image` field. (The raw slug must NOT be passed to `redeploy-env.ts` — e.g. `"agno"` collides with the **showcase** `agno` dispatch_name.) 3. If the CSV is non-empty, `npx tsx showcase/scripts/redeploy-env.ts staging --services <csv>` — the exact same invocation `redeploy-staging` uses. `redeploy-env.ts` already resolves each `starter-<slug>` as an SSOT key (verified: all 12 starter `.image` values exist as keys in `railway-envs.ts`). **Deploy-on-failure is impossible:** the "don't deploy on build failure" guard is the per-slot success intersection, not the job `if:`. `build-starters` `result == 'failure'` still enters the job (fail-fast is false, so some slots may have succeeded), but only `status:success` slots are redeployed; an all-failed or crashed build yields an empty CSV → the redeploy step is skipped. This is the same net guarantee `redeploy-staging` gets from its `any_success` guard, computed inline to avoid standing up a second aggregator job. **No `redeploy-summary` artifact is written** by this job on purpose: that name is owned by `redeploy-staging` and downloaded by `showcase_deploy.yml` by exact name — a second same-named upload would collide on a combined push. Starter *staging verification* is intentionally out of scope for this deploy-gap fix (starters are already smoke-covered by `test_smoke-starter.yml` and the harness `starter_smoke` axis). `redeploy-staging-starters` was also added to the `notify` job's `needs` so a starter redeploy failure alerts. ## Before / after truth table | Scenario | `build` | `redeploy-staging` | `build-starters` | `redeploy-staging-starters` | | --- | --- | --- | --- | --- | | **(a) main-fleet-only change** | runs | **redeploys fleet** | skipped | skipped | | **(b) starter-only change** | skipped | skipped | runs | **redeploys starter (NEW)** | | **(c) both changed** | runs | **redeploys fleet** | runs | **redeploys starter (NEW)** | | **(d) starter build failure** | (n/a) | (n/a) | failure | runs, but CSV empty → **no redeploy** | - **(a)** unchanged — the showcase lane is untouched. - **(b)** is the fix: the starter now auto-deploys instead of sitting on GHCR. - **(c)** unchanged for the fleet; the starter additionally deploys. No artifact collision because `redeploy-staging-starters` uploads no `redeploy-summary`. - **(d)** partial failure redeploys only the slots that succeeded; a wholesale failure redeploys nothing. ## Fail-loud hardening (CR follow-up) A CR flagged that the new `redeploy-staging-starters` job could itself **silently under-deploy** — re-opening the very hole it exists to close. Two guards added to the `Compute successfully-built starter services` step, mirroring the sibling `redeploy-staging` job's empty-intersection guard: 1. **Empty deploy-set → fail loud.** When `build-starters.result == 'success'` (all slots built) but the `matrix ∩ success` CSV is **empty**, the job now `exit 1`s with an actionable `::error::` instead of silently skipping the redeploy at green CI (a slug↔`.image` contract skew, or a success set that maps to no matrix entry). Gated on `'success'` so a partial/total build **failure** keeps the legitimate no-deploy path and is not double-reported — that failure is already surfaced by `build-starters` itself. 2. **Missing/unreadable result artifact → fail loud.** Dropped `2>/dev/null` on the `result.json` read so a read error surfaces and trips `pipefail`, and added a parsed-record-count vs matrix-slot-count assertion (every slot writes a `result.json` via `if: always()`, so on a full-success build the counts must match). A missing/expired `starter-build-result-*` artifact — which would otherwise silently drop a built starter from the redeploy set — now fails the job. Also gated on `'success'` so a crashed slot's legitimately-absent artifact isn't double-reported on a build failure. Updated truth table with the new fail-loud row: | Scenario | `build-starters.result` | deploy CSV | `redeploy-staging-starters` | | --- | --- | --- | --- | | success + non-empty CSV | success | non-empty | **redeploys** | | success + **empty** CSV | success | empty | **exit 1 (NEW fail-loud)** | | build failure (partial) | failure | subset | redeploys successful subset, no spurious exit | | build failure (all/crash) | failure | empty | no deploy, failure surfaced, no spurious exit | | skipped (no starter changes) | skipped | (n/a) | job `if:` excludes it — never runs | Both guards were locally red→green exercised: pre-fix the empty-CSV and missing-artifact cases went **green with nothing/partial deployed**; post-fix they `exit 1`. actionlint still 9/9 (no new findings). ## actionlint Clean. Baseline (`origin/main`) = 9 findings; this branch = 9 findings, all at pre-existing lines (custom `depot-*` runner label + pre-existing SC2086 infos). **Zero new findings** from the added job. The `matrix ∩ success` jq mapping was locally exercised across the four scenarios above (success/partial/all-fail/ crash-before-artifacts) and produced the expected CSVs. ## Prod-promote path **Does NOT share the gap.** `showcase_promote.yml` is `workflow_dispatch`-only ("Humans trigger. No automatic prod promotes.") and already lists all 12 `starter-*` services in its choices with `resolve-targets` handling them. There is no push-driven prod path to fix. ## Residual verification (honest note) Workflows can't be safely dry-run end-to-end (the redeploy path hits live Railway). Static validation is complete (actionlint clean, jq logic exercised, all 12 starter SSOT keys confirmed, `redeploy-env.ts` reused unchanged), but the true end-to-end confirmation is the **next starter-only change auto-deploying to staging**. That first real starter-only merge after this lands should be watched to confirm `redeploy-staging-starters` fires and the Railway service picks up the new image. --- Draft — do not merge until reviewed. |
||
|
|
b79a561fd7 |
ci: fix zizmor ref-version-mismatch on starter-redeploy checkout pin
The new redeploy-staging-starters job pinned actions/checkout to 9c091bb (tag v7.0.0) but commented it # v7. zizmor's ref-version-mismatch flagged the discrepancy: the v7 moving tag points to 3d3c42e, not 9c091bb. Repin to 3d3c42e # v7 — the canonical checkout pin already used across every other job on main — so the comment matches the SHA's tag. |
||
|
|
6fba48faa9 |
docs(threads): reorder Threads nav and tighten lifecycle/architecture boundary
Addresses CR on the Thread & History Lifecycle guide (PR #5988): - Reorder the Threads navigation consistently across the root and all authored-framework meta.json files to: Overview, Threads Drawer, Headless Threads, Import Thread History, Threads & Persistence Architecture, Thread & History Lifecycle. Re-anchor the injected Architecture page before the Lifecycle page and update the nav-order test. - Tighten the two-page boundary: Architecture now owns platform behavior (persistence, replay, realtime sync, locks, failure modes) and defers client-side steps to Lifecycle; Lifecycle keeps only brief persistence context and links to Architecture for the deeper model. - Writing pass reducing heavy em-dash use in both pages, keeping em dashes only in link-gloss lists and table placeholders. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
29ce611db1 |
ci: fail loud on starter redeploy silent-under-deploy holes
The redeploy-staging-starters job could go green while deploying nothing (all starters built, empty deploy CSV) or silently drop a built-but-missing starter from the redeploy set. Both re-open the exact gap this job exists to close. - Finding 1: when build-starters.result == 'success' but the matrix ∩ success CSV is empty, fail the job (exit 1) instead of silently skipping the redeploy. Mirrors redeploy-staging's empty-intersection guard. Gated on 'success' so a partial/total build FAILURE keeps the legitimate no-deploy path and isn't double-reported. - Finding 2: drop 2>/dev/null on the result.json read (surface read errors via pipefail) and assert parsed-record count == matrix slot count when all slots built, so a missing/expired starter-build-result-* artifact fails loud instead of silently under-deploying. |
||
|
|
769cd9daf0 |
chore(deps): update github actions (#6065)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/checkout](https://redirect.github.com/actions/checkout) ([changelog](https://redirect.github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0..3d3c42e5aac5ba805825da76410c181273ba90b1)) | action | digest | `9c091bb` → `3d3c42e` | | [actions/setup-python](https://redirect.github.com/actions/setup-python) | action | major | `v6.3.0` → `v7.0.0` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/592) for more information. --- ### Release Notes <details> <summary>actions/setup-python (actions/setup-python)</summary> ### [`v7.0.0`](https://redirect.github.com/actions/setup-python/compare/v6.3.0...v7.0.0) [Compare Source](https://redirect.github.com/actions/setup-python/compare/v7.0.0...v7.0.0) ### [`v7`](https://redirect.github.com/actions/setup-python/compare/v6.3.0...v7.0.0) [Compare Source](https://redirect.github.com/actions/setup-python/compare/v6.3.0...v7.0.0) </details> --- ### Configuration 📅 **Schedule**: (in timezone America/Los_Angeles) - Branch creation - "before 9am every weekday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/CopilotKit/CopilotKit). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNjUuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI3Mi40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> |
||
|
|
1cc66e6dea |
fix(ci): deploy starter-only changes (showcase_build redeploy gap)
A push touching only starter files (examples/integrations/<slug>/**) built a fresh starter-<slug>:latest image to GHCR via build-starters but never redeployed it to Railway: the starter lane (detect-starter-changes -> build-starters) ended at the GHCR push, and redeploy-staging only covers the showcase build lane. Starter fixes sat undeployed until a manual redeploy (the #6061 agno incident). Add a redeploy-staging-starters job that mirrors redeploy-staging for the starter lane: it reads the already-emitted per-slot starter-build-result-* artifacts, intersects the build matrix with the build-success set (mapping raw slug -> starter-<slug> SSOT key), and redeploys only the successfully-built starters to staging. No deploy on build failure (empty success set -> redeploy step skipped). Reuses redeploy-env.ts unchanged. |
||
|
|
f44cb57669 |
fix(showcase): wire crewai-crews declarative-gen-ui via Option A (JS-injected A2UI)
Switch the crewai-crews gen-ui-declarative cell from a broken Option B (Python-side injection, which has no mechanism in the ag_ui_crewai adapter) to Option A (JS-runtime-injected A2UI): - route.ts: remove `injectA2UITool: false`; keep `defaultCatalogId` to pin the catalog so models that omit catalogId don't get a "Catalog not found" render error. - declarative_gen_ui.py: replace `GenerateA2uiTool` with a no-arg `_GenerateA2uiNoArgTool` that raises loudly if called directly (the A2UIMiddleware should always intercept before Python). - definitions.ts + renderers.tsx: add `DataTable` component (columns/rows schema + `data-testid="declarative-data-table"` renderer); add missing `data-testid="declarative-info-row"` to the `InfoRow` renderer. Both testids are required by the D5 harness (turns 2 and 4 respectively) and were present in the langgraph-python reference catalog but absent here. - gen-ui-declarative.json: rewrite D6 aimock fixtures from the old broken two-stage pattern (generate_a2ui → inner render_a2ui) to the correct single-stage pattern (LLM calls render_a2ui directly); all four pills now match `toolName: render_a2ui, context: crewai-crews` and return full component trees that satisfy the harness minCounts assertions. RED (main): "CrewAI flow failed; see server logs" on every pill — `injectA2UITool: false` disabled the middleware; no render_a2ui tool in the agent's tool list; aimock fixture matcher never fired; no surface. GREEN (this branch): all 4 turns pass with assertions, 1 passed (0.0s). |
||
|
|
cd76f12980 | chore(deps): update github actions | ||
|
|
7fb0abf60e |
fix(vue): keep attachment sources structuredClone-safe (#5933)
## What does this PR do? Fixes a Vue `DataCloneError` that occurred when uploaded attachment sources crossed the `structuredClone` boundary in core. Vue’s deep `ref()` conversion wrapped nested attachment sources in reactive proxies; `useAttachments` now keeps the attachment container shallow with `shallowRef()`, preserving externally supplied sources as raw cloneable values before they reach AG-UI/core payloads. The change is intentionally Vue-only: core and React are untouched because the defect is caused by Vue’s reactivity behavior at the framework boundary. Focused regressions cover both the attachment hook and `CopilotChat` submission path, including non-reactivity and successful `structuredClone` behavior. ## Related PRs and Issues - [CopilotKit issue #3](https://github.com/enekesabel/CopilotKit/issues/3) ## Verification - `pnpm nx run @copilotkit/vue:check-types` — passed. - `pnpm nx run @copilotkit/vue:test -- src/v2/hooks/__tests__/use-attachments.test.ts src/v2/components/chat/__tests__/CopilotChat.attachments.test.ts` — passed, 18 tests in 2 files. - `pnpm nx run @copilotkit/vue:build` — passed. - Pre-commit package gate (`test-and-check-packages`) — passed: 1073 tests, publint, and attw. - `pnpm nx run @copilotkit/vue:lint` — remains blocked by 171 pre-existing errors across unrelated Vue files; no lint errors were introduced in the changed files. - `git diff --check upstream/main...HEAD` — passed. ## Scope and exclusions - Changed files are limited to `packages/vue/src/v2/hooks/use-attachments.ts`, its focused hook and `CopilotChat` tests, and the related `packages/vue/PARITY.md` and `packages/vue/AGENTS.md` guidance. - No core, React, workflow, or package-wide lint cleanup is included. - The `PARITY.md` change removes accidental table-format churn and retains only the meaningful attachment parity note. ## Checklist - [x] I have read the [Contribution Guide](https://github.com/CopilotKit/CopilotKit/blob/main/CONTRIBUTING.md) - [x] If the PR changes or adds functionality, I have updated the relevant documentation - [x] "Allow edits by maintainers" is checked (lets us help iterate on your PR directly — faster turnaround for everyone) |
||
|
|
99ae28804b |
fix(vue-demo): use v2 entrypoint and BuiltInAgent (#5960)
## What does this PR do? Updates the Vue v2 demo to consistently use current v2 APIs: - imports all Vue demo pages, including the A2UI catalog page, from `@copilotkit/vue/v2`; - replaces the demo runtime's deprecated `BasicAgent` instances with `BuiltInAgent`. This is the focused, still-applicable demo correction recovered from #5176. It does not change package exports, public APIs, documentation, or unrelated demo behavior. ## Related PRs and Issues - Extracts the Vue demo portion of #5176. ## Verification - `pnpm nx run @copilotkit/vue-demo:lint` passed. - Manual Vue demo smoke testing passed using the branch's Nx dev server. - `pnpm nx run @copilotkit/vue-demo:build` completed Nuxt client and server compilation locally, but did not exit during Nitro finalization and was stopped after producing no further output. - Vue package suite: 1,069 tests passed; two unrelated existing 5-second timeout failures occurred in `CopilotChatMessageView` activity rendering and `CopilotSidebarView` measured-margin coverage. - `git diff --check` passed. ## Checklist - [x] I have read the [Contribution Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md) - [x] Documentation is not required because this only corrects the existing v2 demo's imports and deprecated runtime construction. - [x] "Allow edits by maintainers" is checked (lets us help iterate on the PR directly). |
||
|
|
30cc551a9b |
docs(langgraph,crewai-flows): remove broken useCopilotContext example (#5821)
## What does this PR do? Removes the "Using setThreadId" example from the LangGraph and CrewAI Flows persistence docs. That example calls `useCopilotContext()`, which is a v1-only hook not exported from `@copilotkit/react-core/v2` — following the example as written throws a module resolution error for v2 users. The preceding "Dynamically Switching Threads" section on the same page already documents the correct, working pattern (plain React state + the `threadId` prop on `<CopilotKit>`), so removing the broken section doesn't leave a gap. ## Related PRs and Issues Closes #3860 ## Files changed - `showcase/shell-docs/src/content/docs/integrations/langgraph/advanced/persistence/loading-message-history.mdx` - `showcase/shell-docs/src/content/docs/integrations/crewai-flows/persistence/loading-message-history.mdx` ## Checklist - [x] I have read the [Contribution Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md) - [x] Docs-only change; no functionality updated - [x] Allow edits by maintainers |
||
|
|
e91ae56372 |
docs(shell-docs): emit canonical versioned URLs for reference pages in llms-full.txt (#5486)
## What does this PR do? `getAllLlmPages()` in `llm-text.ts` previously walked `src/content/reference/` directly and emitted reference pages at `reference/<slug>` (e.g. `reference/hooks/useCopilotAction`). The live site serves those pages at their versioned canonical URL — `/reference/v2/hooks/useCopilotAction` for the current v2 API — so `llms-full.txt` contained non-canonical source URLs that diverged from what users see in the browser. **Root cause:** The v2 API reference lives at the _root_ of `src/content/reference/` (no `v2/` subfolder), so a bare filesystem walk cannot distinguish v2 from older SDK versions. It emits `reference/hooks/foo` instead of the correct `reference/v2/hooks/foo`. **Fix:** Replace step 3 with an enumeration via `loadReferenceVersionItems` (which already knows the canonical URL per version) and `resolveReferencePage` (which resolves the content file path). This matches the URL scheme used by the `/reference/[...slug]` route handler. **Result:** - v2 hooks/components now appear at `reference/v2/hooks/...` in `llms-full.txt` - v1, react-native, core, and bot pages appear at their correct versioned prefixes - Version root index pages (`reference/v2`, `reference/v1`, ...) are included - The migration guide (`migrate/v2`) was already included via the docs walk (step 1 unchanged) ## Related PRs and Issues - Closes #3385 ## Checklist - I have read the Contribution Guide - If the PR changes or adds functionality, I have updated the relevant documentation - "Allow edits by maintainers" is checked |
||
|
|
bc2916efaa |
fix(runtime-client-gql): guard abort errors without message (#5437)
Fixes #2596 ## Summary `@copilotkit/runtime-client-gql` was still assuming abort-shaped errors always expose a string `message`, which could turn an early-stop path into a secondary TypeError instead of a clean abort suppression or the original failure. This branch centralizes abort detection behind a null-safe helper and keeps the existing abort phrases unchanged. ## Changes - Replaced the duplicated abort checks in `packages/runtime-client-gql/src/client/CopilotRuntimeClient.ts` with a shared `isAbortError(unknown)` helper that only inspects string messages. - Added focused regression coverage in `packages/runtime-client-gql/src/client/__tests__/CopilotRuntimeClient.test.ts` for a string abort cause, an object without `message`, known abort suppression in the stream path, and non-abort stream errors surfacing normally. - Added `.changeset/guard-abort-error-message.md` for the patch release note. ## Scope Only `packages/runtime-client-gql` and its local changeset are touched. The abort phrases, caller-facing API, structured GraphQL error handling, and stream close behavior for known aborts are unchanged. ## Test Plan - [x] `npx nx run @copilotkit/runtime-client-gql:graphql-codegen` - regenerated the package GraphQL artifacts used by the client imports. - [x] `pnpm run build` - workspace build completed successfully. - [x] `pnpm -C packages/runtime-client-gql exec vitest run src/client/__tests__/CopilotRuntimeClient.test.ts` - 4/4 passed. Covers a string abort cause in the fetch path, an object with no `message` in the fetch path, known abort suppression in the stream path, and non-abort stream errors surfacing. - [x] `pnpm exec oxfmt --write packages/runtime-client-gql/src/client/CopilotRuntimeClient.ts packages/runtime-client-gql/src/client/__tests__/CopilotRuntimeClient.test.ts` - formatted the touched source and test files. - [x] `pnpm exec oxlint packages/runtime-client-gql/src/client/CopilotRuntimeClient.ts packages/runtime-client-gql/src/client/__tests__/CopilotRuntimeClient.test.ts` - 0 warnings, 0 errors. |