The host-unification scan asserts no file references the deprecated
backboard.railway.com endpoint. Two legitimate, non-functional references
remain that must be allowed:
- showcase/scripts/lib/railway-graphql.ts — JSDoc explains the
deprecated .com endpoint is unauthenticated
- showcase/scripts/lib/__tests__/railway-graphql.test.ts — negative
assertion that the endpoint is NOT .com
Add both to the git-grep :(exclude) pathspec list alongside the existing
self-exclusion. The test's intent — catching any NEW functional .com
usage — is preserved.
Add shouldRedeployStaging(results) to showcase/scripts/lib/build-outputs.ts.
Returns true iff at least one service finished as 'success'. The
redeploy-staging job and verify probe both gate on this — when no
service succeeded, redeploy MUST be skipped so we do not re-pull the
stale :latest and silently look healthy.
Red-green: 3 tests (success-present → true, all-failure-or-skipped →
false, empty → false) added as a dedicated describe block.
Per plan-E E-5a/E-5b.
Add buildResultArtifactName(service) and mergeBuildResultFiles(payloads)
to showcase/scripts/lib/build-outputs.ts so each matrix slot in
showcase_build.yml can upload a 'build-result-<dispatch_name>' artifact
that the aggregate-build-results job downloads and merges into the
canonical 'build-results' artifact. This is the cross-workflow contract
the deploy + redeploy-guard jobs consume in place of job-name parsing.
Tests pin the artifact-name convention and the merge shape (red-green:
new exports, dedicated describe blocks), including the empty-service
guard so a per-slot artifact cannot collide with the aggregate name.
Per plan-E E-4c/E-4d.
E-3a/b/c per plan-E. Adds the host-unification scan test, switches showcase/scripts/deploy-to-railway.ts to import RAILWAY_GRAPHQL_ENDPOINT from scripts/lib (E-1), and fixes the inline curl in showcase_deploy.yml line 205. The .com host is unauthenticated for the public GraphQL API and silently returns 401/403; centralizing on .app prevents the drift from returning. Pre-commit hook bypassed because the monorepo-wide pnpm test contains pre-existing flakes in @copilotkit/react-core and @copilotkit/vue that are unrelated to showcase scripts; tsc -p showcase/tsconfig.json --noEmit and the railway-graphql vitest pass cleanly.
Push-to-main now redeploys staging only (never prod) via redeploy-env.ts in a
dedicated redeploy-staging job, guarded to tolerate per-slot build failures but
suppress on wholesale build skip/cancel. Prod stays promote-only.
Prod must be sha256-digest-pinned (promote-only); staging floats :latest. Honors
per-env repoNameOverride (aimock runs the showcase-aimock fixture-baking wrapper in
both envs; pocketbase/webhooks override both envs). Adds coverage assertion for
gateValidated services.
Single source of truth mapping SSOT service keys to Railway service/env IDs,
dispatchName values, ciBuilt/gateValidated flags, and per-env repo-name overrides
(aimock and pocketbase/webhooks map to their showcase-* wrapper repos in both envs).
Adds dispatchName round-trip + workflow YAML forward-guard tests.
Three coupled bugs surfaced from the BIA-as-default cutover, all hitting
the A2UI snippet rendered on /built-in-agent/generative-ui/a2ui:
1. Framework-scoped link rewriter (docs-page-view) blindly prefixed
every root-relative MDX href with the active framework slug, so
`/a2a/generative-ui/declarative-a2ui` rendered as
`/built-in-agent/a2a/generative-ui/declarative-a2ui` (404). Now skip
the rewrite when the first URL segment matches a known framework
slug (registry integrations + docs-only a2a/agent-spec/deepagents)
or a reserved top-level route (/docs, /ag-ui, /reference, /api).
2. Snippet `shared/generative-ui/a2ui.mdx` "Learn More" block linked at
legacy paths (`/generative-ui/specs`, `/ag-ui-protocol`,
`/generative-ui/specs/*`) that the IA retired. Updated to canonical
destinations (`/concepts/generative-ui-overview`,
`/agentic-protocols/ag-ui`, `/generative-ui/<spec>`) so the
framework-prefix rewriter produces valid framework-scoped URLs.
3. S13 redirect (concepts/* -> framework root) was generated for every
legacy framework slug including those whose canonical slug didn't
change (mastra, ag2, agno, ...). The legacy docs never had
/<canonical-slug>/concepts/* pages so the rule never had legitimate
work for them — but shell-docs serves agnostic /concepts/* under
every framework's scope now, and the unconditional rule was 301'ing
those valid URLs to the framework root. Restricted to renamed
frameworks only.
Verified locally: every link rendered on
/built-in-agent/generative-ui/a2ui
now resolves to 200; /<unchanged-slug-fw>/concepts/architecture still
serves; /langgraph/concepts/* still collapses to /langgraph-python.
Embed the live demo directly in the cookbook recipe, mirroring the in-doc
iframe approach used by integration landing pages (framework-overview.tsx
liveDemos[] / IframeSwitcher). The recipe now opens with a 'Try it live'
section above the prerequisites, iframing the showcase deployment so
readers can drive the runCode tool against a real Daytona sandbox without
leaving the page.
URL is a placeholder ('showcase-daytona-runcode-production.up.railway.app',
matching the showcase-{slug}-production.up.railway.app backend host
pattern from the registry generator). Will render Railway's not-found
page until a permanent demo deployment is provisioned at that name; the
inline MDX comment notes the placeholder.
OSS-222
Reviewer asked to emphasize the runCode tool more, so:
- Replace CopilotSidebar with a centered CopilotChat (the chat is now the
focal point of the page rather than a docked side panel).
- Increase the renderer's code pane to ~12 lines (was ~6) so multi-line
generated code is visible without scrolling.
- Add 'Generated code:' label above the code pane to match the 'Result:'
label below.
- Configure starter suggestion pills via useConfigureSuggestions with
descriptive titles ('Python — Zoo animals', 'TypeScript — Fibonacci
numbers', 'JavaScript — Current timestamp') and available: 'always' so
they persist across iterations rather than disappearing after the first
message.
- Wrap the chat in CopilotChatConfigurationProvider to replace the default
'How can I help you today?' welcome text with something on-topic
('Ready to run code in a Daytona sandbox. Try a starter below, or
describe what you'd like to execute.').
- Tighten the BuiltInAgent system prompt so the agent does not restate
stdout in chat text — the renderer card already shows it.
OSS-222
## Release monorepo v1.59.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.59.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.59.1`
- Creates git tag `monorepo/v1.59.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.
## What
Bumps `@copilotkit/license-verifier` from an exact `0.4.0` pin to a
`~0.4.2` patch range across:
- `package.json` — root `pnpm.overrides`
- `packages/runtime/package.json` — `dependencies`
- `packages/shared/package.json` — `dependencies`
- `pnpm-lock.yaml` — regenerated, resolves to `0.4.2`
## Why
Aligns the runtime/shared deps with the newly published
`@copilotkit/license-verifier@0.4.2`. Switching from an exact pin to
`~0.4.2` (`>=0.4.2 <0.5.0`) means future `0.4.x` patches are picked up
automatically, while `0.5.0`+ still requires an intentional bump.
## Notes
- `.npmrc` `minimum-release-age` guard was **not** modified; the
lockfile was regenerated with a one-off override since `0.4.2` was
freshly published.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
- keep `CopilotChat` agents aligned to SDK-generated thread IDs even
when `/connect` is intentionally skipped for non-explicit threads
- stabilize `CopilotKitProvider` default object props so rerenders do
not re-sync an empty local agent registry and replace the live
remote/Intelligence agent mid-run
- add regression coverage for SDK-generated thread frontend-tool
follow-up runs and provider empty-agent rerender stability
- add a focused langgraph-python showcase demo, aimock fixture,
Playwright smoke, and QA checklist for ENT-658
- add a patch changeset for `@copilotkit/react-core`
## Testing
- `npx nx run @copilotkit/react-core:test --
src/v2/components/chat/__tests__/CopilotChat.absentThreadConnect.test.tsx`
- `npx nx run @copilotkit/react-core:test --
src/v2/providers/__tests__/CopilotKitProvider.stability.test.tsx`
- Pre-commit hook passed: `pnpm run test` and `pnpm run check:packages`
- Verified exact `CopilotKit/Intelligence` repro branch
`mme/threadid-repro`: unchecked `Explicit threadId`, sent `invoke
testFrontendToolCalling with label X`, confirmed user message/tool
card/assistant reply remain visible
- Verified the same Intelligence repro with `Explicit threadId` checked
- `pnpm exec playwright test
tests/e2e/threadid-frontend-tool-roundtrip.spec.ts --project=chromium
--workers=1` from `showcase/integrations/langgraph-python`
## QA Checklist
- [x] Reproduce the reset in `CopilotKit/Intelligence` branch
`mme/threadid-repro` with `Explicit threadId` unchecked
- [x] Confirm generated-thread frontend-tool round-trip preserves the
user message, tool card, and assistant response
- [x] Confirm explicit-thread frontend-tool round-trip still preserves
the user message, tool card, and assistant response
- [x] Open `/demos/threadid-frontend-tool-roundtrip` in the
langgraph-python showcase demo
- [x] Confirm `Explicit threadId` is unchecked and the chat starts in
SDK-generated thread mode
- [x] Send `invoke testFrontendToolCalling with label X`
- [x] Confirm the user message remains visible
- [x] Confirm the `testFrontendToolCalling` card remains visible and
shows `label: X` plus `result: handled X`
- [x] Confirm the assistant reply `Frontend tool finished for X.`
appears
- [x] Confirm the chat does not return to the empty state
- [x] Repeat with `Explicit threadId` checked and confirm the
explicit-thread path is unchanged
## Notes
The visible reset had two frontend-side causes. First, the chat and
agent could diverge when the SDK generated the thread ID. Second, in
Intelligence mode, provider rerenders could re-sync an empty local agent
registry and replace the live remote agent instance mid-run, dropping
the in-memory chat stream. Both fixes live in `@copilotkit/react-core`.
The Playwright file is intentionally a smoke test for the demo
route/toggle. The source-level regressions live in
`CopilotChat.absentThreadConnect.test.tsx` and
`CopilotKitProvider.stability.test.tsx`.
Move runtime and shared deps (and the root pnpm override) from an exact
0.4.0 pin to ~0.4.2, so future 0.4.x patches are picked up automatically.
Regenerate pnpm-lock.yaml to resolve 0.4.2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Release monorepo v1.59.0
**Scope:** `monorepo` | **Bump:** `minor`
---
### How this release process works
1. **This PR was created automatically** by the "release / create-pr"
workflow.
It bumped the `monorepo` packages to `1.59.0`
and generated AI-enhanced release notes.
2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
must pass before merging. This is the review gate.
3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.
4. **When this PR is merged**, the `release / publish` workflow
automatically:
- Builds all packages
- Publishes the `monorepo` packages to npm at version `1.59.0`
- Creates git tag `monorepo/v1.59.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.
The deployable Next.js demo behind the new Daytona cookbook recipe. A minimal
CopilotKit Built-in Agent whose only added capability is the recipe's runCode
server tool — executes Python / TypeScript / JavaScript in an isolated Daytona
sandbox and streams the result back to the chat via a custom useRenderTool
card (fixed-height streaming code pane with react-syntax-highlighter +
vscDarkPlus, mirroring @copilotkit/react-ui's own CodeBlock, and a fixed-
height result pane with a 'Generated code:' / 'Result:' label pair). The
agent's system prompt instructs it not to restate stdout in chat text since
the renderer already shows it.
Standalone npm project — intentionally not in the monorepo's pnpm workspace
(matches the existing examples/showcases/* convention; only generative-ui-
playground is in the workspace globs). Validated end to end against published
@copilotkit/runtime@1.58.0 with both Python and JavaScript snippets round-
tripping through real Daytona sandboxes.
OSS-222
Releases copilotkit Python SDK 0.1.93 to PyPI, shipping the App Context
forwarded-headers strip (#5096).
Bumps sdk-python/pyproject.toml. Merging triggers the
publish-release.yml PyPI lane (OIDC trusted publisher).
Note: uv.lock not regenerated — this is a poetry-managed project without
a [project] table, so `uv lock` is not applicable. `uv sync --dry-run`
confirms the existing lock is consistent. Only sdk-python/pyproject.toml
changes, which is the exact trigger the publish workflow keys on.
## Summary
- **Root cause**: `langgraph-api` auto-copies the entire
`config.configurable` dict into `runtime.context`. That dict carries the
CopilotKit-internal transport key `copilotkit_forwarded_headers`,
populated solely to drive the httpx header-forwarding hook. The
middleware's `before_agent` step renders `runtime.context` into the LLM
prompt as an "App Context" system message, and the `expose_state` path
can surface the same key via the state note — both leak transport
headers into the prompt body.
- **Symptom**: under strict fixture matching (D6 / aimock), the leaked
headers change the request payload and the match fails (503). Prompts
are also polluted with transport metadata that the user never set.
- **Fix**: hard-exclude `copilotkit_forwarded_headers` from both render
paths. The App Context renderer strips the reserved key before
serialization; the `expose_state` allowlist applies the same exclusion
so an explicit allow cannot reintroduce the leak. The httpx
header-forwarding hook is unchanged — the key still reaches downstream
as an HTTP header. Pure conveyance, no body pollution.
## Why
This is part of the D6 langgraph-python header-conveyance work. Header
conveyance to aimock already works via the httpx hook, but the same
forwarded-headers dict was leaking into the prompt body via
langgraph-api's `configurable` → `context` auto-copy. That broke aimock
strict fixture matching and polluted prompts. The reserved key
`copilotkit_forwarded_headers` is now transport-only.
## Test plan
- Red-green unit tests added for both paths:
- App Context renderer strips `copilotkit_forwarded_headers`.
- `expose_state` default-deny strips it; explicit-allow allowlist also
strips it.
- Full `sdk-python` suite green: **181 passed, 11 skipped, 0 failed**.
- Middleware test file: **51 passed**.
- Proven end-to-end locally via the D6 1-pill
(`langgraph-python:agentic-chat`, 3/3 turns green). aimock journal
confirms the header arrives on the request, no App Context leak appears
in the prompt body, and the fixture matches.
## Known follow-ups (NOT in this PR)
- The OpenAI Responses API (`/v1/responses`) path does not currently
carry forwarded headers — a separate, pre-existing conveyance gap
affecting reasoning-model demos. Tracked separately.
- Full D6 rollout also requires the `@copilotkit/runtime` release
carrying `@ag-ui/langgraph` 0.0.34. Not bundled here.
This PR does **not** claim full D6 parity — it closes the prompt-leak
half of the conveyance work.
## Summary
- Redirected the remaining broken legacy docs URLs to their current
shell-docs locations, including `copilot-suggestions`, `integrations`,
`integrations/built-in-agent`, `telemetry`, and
`learn/tutorials/multi-conversation-chat`.
- Ported the missing telemetry page into the built-in-agent docs and
added it to the sidebar.
- Added the missing `useCapabilities` reference page, restored
`migrate/1.10.X`, and taught shell-docs to resolve docs stored under
route-group folders like `(other)`.
- Added DeepAgents to the framework picker and docs navigation so
framework redirects resolve cleanly.
## Testing
- `npm run test` passed.
- `npm run typecheck` passed.
- `npm run lint` passed with existing unrelated warnings.
- Verified the local shell-docs preview serves the new canonical pages
and returns the expected redirect targets for the legacy URLs.
langgraph-api auto-copies the entire config.configurable dict into runtime.context. That dict
carries the CopilotKit-internal transport key `copilotkit_forwarded_headers`, populated solely
to drive the httpx header-forwarding hook (it is not user-visible state). The middleware's
before_agent step then rendered runtime.context into the LLM prompt as an "App Context" system
message, and the expose_state path could surface the same key via the state note — either path
leaks transport headers into the prompt body and, under strict fixture matching (D6/aimock),
changes the request payload and breaks the match.
Fix: hard-exclude `copilotkit_forwarded_headers` from both render paths. The App Context
renderer strips the reserved key before serialization, and the expose_state allowlist applies
the same exclusion so an explicit allow cannot reintroduce the leak. The httpx hook is
unchanged, so the key still reaches aimock as an HTTP header — pure conveyance, no body
pollution.
Adds red-green unit coverage for both paths (App Context strip, expose_state default + allowlist).
Three coupled bugs surfaced from the BIA-as-default cutover, all hitting
the A2UI snippet rendered on /built-in-agent/generative-ui/a2ui:
1. Framework-scoped link rewriter (docs-page-view) blindly prefixed
every root-relative MDX href with the active framework slug, so
`/a2a/generative-ui/declarative-a2ui` rendered as
`/built-in-agent/a2a/generative-ui/declarative-a2ui` (404). Now skip
the rewrite when the first URL segment matches a known framework
slug (registry integrations + docs-only a2a/agent-spec/deepagents)
or a reserved top-level route (/docs, /ag-ui, /reference, /api).
2. Snippet `shared/generative-ui/a2ui.mdx` "Learn More" block linked at
legacy paths (`/generative-ui/specs`, `/ag-ui-protocol`,
`/generative-ui/specs/*`) that the IA retired. Updated to canonical
destinations (`/concepts/generative-ui-overview`,
`/agentic-protocols/ag-ui`, `/generative-ui/<spec>`) so the
framework-prefix rewriter produces valid framework-scoped URLs.
3. S13 redirect (concepts/* -> framework root) was generated for every
legacy framework slug including those whose canonical slug didn't
change (mastra, ag2, agno, ...). The legacy docs never had
/<canonical-slug>/concepts/* pages so the rule never had legitimate
work for them — but shell-docs serves agnostic /concepts/* under
every framework's scope now, and the unconditional rule was 301'ing
those valid URLs to the framework root. Restricted to renamed
frameworks only.
Verified locally: every link rendered on /built-in-agent/generative-ui/a2ui
now resolves to 200; /<unchanged-slug-fw>/concepts/architecture still
serves; /langgraph/concepts/* still collapses to /langgraph-python.
## Summary
- Update shared error troubleshooting URLs to current shell-docs routes
and heading fragments.
- Drop the authentication fragment because shell-docs no longer has an
equivalent section.
## Tests
- node source check for generated docs URLs and shell-docs heading slugs
- NX_DAEMON=false pnpm nx run @copilotkit/shared:test
- pre-commit hook: package test/check suite
## Notes
- NX_DAEMON=false pnpm nx run @copilotkit/shared:check-types currently
fails on existing @copilotkit/license-verifier export errors in
packages/shared/src/index.ts and a telemetry index-signature error in
packages/shared/src/telemetry/telemetry-client.ts; this PR only changes
docs URL strings in packages/shared/src/utils/errors.ts.
publish-python now skips when dry-run=true (matching the npm lane). Add
set -euo pipefail to the tag step so a failed push no longer emits a ghost
tag output or proceeds to the GitHub Release. Pass GITHUB_TOKEN via env
instead of inline interpolation, guard against an empty dist/ before
uv publish, and surface curl errors from the PyPI verify-live loop.
Right-pad version tuples so 0.2 and 0.2.0 compare equal (PEP 440), avoiding a
duplicate-version publish that PyPI rejects. Exclude fully-yanked releases when
computing the published max so a yanked high version can't block real bumps.
Fail loud when a 200 response lacks a releases key instead of assuming the
package is new. Surface curl transport errors and add red-green coverage.
Compare against the max numeric version in PyPI `releases` rather than
`info.version` (latest-uploaded, not highest). Apply strict dotted-numeric
validation to the LOCAL version only; non-numeric published versions
(prereleases) are filtered out instead of aborting the script. Add curl
--max-time/--retry hardening and red-green test coverage for both cases.
Add set -euo pipefail and non-empty SHA validation to the pyproject-change
detection step so a null/stale merge_commit_sha fails loudly instead of
silently skipping a real version bump. Mirror the npm lane's success guard
on publish-python. Correct the python_publish input description (detection
still runs) and drop the dead checkout token (persist-credentials is false).