Commit Graph

15424 Commits

Author SHA1 Message Date
copilotkit-qa-bot[bot] ad5454b1a3 Merge remote-tracking branch 'origin/main' into codex/fac-129-review-feedback 2026-08-17 15:48:36 -07:00
copilotkit-qa-bot[bot] ecaa5c5fd8 fix(docs): validate Claude run input before streaming 2026-08-17 15:47:46 -07:00
Benjamin Taylor 21ab0c6eb6 docs(auth): add agent/stop to the unscoped routes, demote identifyUser
The previous commit claimed every route resolves the caller through
identifyUser. It does not. handleStopAgent never resolves a user at all:
it calls runtime.runner.stop({ threadId }) directly, and
IntelligenceAgentRunner.stop looks the run up by threadId alone. Any
caller who learns an active threadId can abort that run mid-flight, and
an application relying on identifyUser as its authentication backstop is
not covered on this route because the callback is never invoked.

Audited every route on the Intelligence path rather than patching the one
that was reported. agent/stop is the only additional gap: agent/suggest
deliberately skips thread persistence, and threads/clear is a no-op off
the in-memory runner, which is the only runner exposing local thread
endpoints.

Drop the false universal-resolution claim, add agent/stop to the No row
and the targeted guard, and state plainly that onRequest is the
authentication gate while identifyUser only names an already
authenticated caller. The guard uses a switch rather than an array
membership test so route narrows and route.threadId type-checks; the
includes form fails with TS2339, verified against the real RouteInfo.

Refs OSS-851

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:29:17 -05:00
Benjamin Taylor 383c3f697c docs(auth): flag threads/events and threads/state as unscoped
The revised thread-authorization section claimed the Intelligence runtime
scopes every thread-bearing route to the resolved user. It does not.

handleGetThreadEvents and handleGetThreadState resolve the caller through
identifyUser and then discard the result, calling getThreadEvents({
threadId }) / getThreadState({ threadId }). The platform client takes no
userId on either method — both hit project-authenticated _inspect
endpoints — so any caller identifyUser accepts can read the event log and
agent state of any thread in the project given its id.

Replace the blanket guarantee with a per-route table, and document the
onBeforeHandler guard narrowed to those two routes so the Intelligence
path is not told there is nothing to build.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 9ea276b740 docs: correct API Gateway streaming and Intelligence thread scoping
Two review corrections.

API Gateway REST APIs gained Lambda response streaming in November 2025
via responseTransferMode: STREAM, which also lifts the 10 MB payload cap
and the 29-second integration timeout. The guide claimed no API Gateway
type can stream and steered readers to a buffered serverless-http setup.
Split REST from HTTP, document the REST streaming path (payload format
1.0 adapter, AWS_PROXY integration on the response-streaming-invocations
URI, CLI/CDK/SAM config), and scope the buffered fallback to HTTP APIs
and ALB, which still have no streaming path.

The thread-authorization section told every reader to build an ownership
table and enforce it in onBeforeHandler. On the Intelligence path the
runtime already resolves identifyUser(request) server-side and passes
that user id to run, connect, the thread reads, the mutations, and the
subscription token; listThreads is scoped by user and filtered by
agentId. Document identifyUser as the platform binding and scope the DIY
pattern to SSE runtimes, custom stores, and the local in-memory runner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 6548d59f40 docs(mcp): distinguish when an MCP App is and is not needed
mcp.mdx treated all non-App MCP servers generically, leaving #5991's
question unanswered: readers could not tell whether their server needed a
UI resource at all.

Separates the three cases — read-only context servers (no renderer needed),
action servers (renderer plus human-in-the-loop approval), and interactive
MCP Apps — with the test for choosing between them.

Closes #5991

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 98e02e9a4c docs(langgraph): add a guardrails and DLP how-to
Only adjacent coverage existed — the AG-UI middleware guide and a
third-party governance cookbook — so #3414's question about input/output
screening had no first-class answer.

Covers the built-in PIIMiddleware first, then custom AgentMiddleware for
input screening (before_model + jump_to), output and DLP screening
(wrap_model_call), and tool-call screening, plus why guardrails must be
ordered ahead of CopilotKitMiddleware.

Closes #3414

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor e996328f15 docs(threads): answer the bring-your-own-thread-backend question
#6090 asked how to point CopilotKit threads at a different database. There
is no such extension point, and nothing said so — the honest answer is that
Rich Threads are an Enterprise Intelligence Platform capability, and the DIY
path is own-the-threadId plus framework-layer persistence.

Documents that path and what it costs relative to Rich Threads. Body lives
in a shared snippet with the usual per-framework wrappers, since the nav
parity contract requires every authored framework to publish the page and
every React destination to map to an Angular one.

Closes #6090

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 0e724231ec docs(auth): document per-user thread authorization
auth.mdx covered token forwarding and the onRequest gate but stopped at
authentication. Nothing tied a threadId to a user, so a caller who learned
another user's thread id could reach it through every thread route.

Adds the ownership-table pattern and the onBeforeHandler enforcement point,
including which routes carry threadId on `route` versus in the request body,
and why the thread list has to be filtered server-side.

Closes #2241

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 2e1b125049 docs(deploy): add an AWS Lambda self-hosting guide
The generic adapter guide covers Lambda only by implication, and the part
that actually bites is undocumented: API Gateway and ALB buffer responses,
so a chat runtime behind either appears to hang for the whole agent run and
then dumps the reply at once.

Documents the Function URL + RESPONSE_STREAM path as the default, with the
awslambda.streamifyResponse wiring that bridges the runtime's Fetch Response
into the Lambda response stream, and keeps the serverless-http/API Gateway
path for the cases that genuinely do not stream.

Closes #1151

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor cb11f6fb93 fix(runtime): warn when message content parts are dropped
normalizeMessageContent maps array content and handles only "text" and
"binary" parts. Any other part -- the {"type": "image", ...} case from
#1748 -- maps to "" and is filtered out with no signal at all, so an
agent emitting structured content sees its output silently vanish.

Carrying those parts through needs an AssistantMessage schema change and
is tracked separately in OSS-767. This makes the current drop visible in
the meantime, once per unrecognised part type so streaming does not flood
the log.

Refs #1748

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor ffd15801d6 fix(react-core): re-render consumers when the agent node changes
useAgentNodeName tracked the current node in a ref and returned
nodeNameRef.current. Mutating a ref schedules no render, so a component
reading useCoAgent().nodeName kept showing whichever node was current at
its last render and never updated on its own -- it only appeared to work
when something unrelated happened to re-render it.

Backing the value with state fixes that. Adds the coverage the hook never
had: transitions, run-start reset, run-error, and unsubscribe on unmount.

Note this does NOT explain GH #1426 (interrupt agentMetadata.nodeName
reporting the previous node). useInterrupt only evaluates the `enabled`
predicate from a useEffect/useMemo keyed on its `pending` state, so the
interrupt's own state update always forces a render before the predicate
runs -- and the pre-fix code reads the ref correctly at that point. That
report needs a different explanation; it is left open.

Refs #1426

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor c94032f3fa feat(react-ui): report feedback state to onThumbsUp/onThumbsDown
The thumbs callbacks only received the message, so a consumer could not
tell whether a click applied feedback or retracted it. Custom
AssistantMessage implementations that track their own toggle state had
no way to pass that value through, and the built-in feedback state was
write-only: clicking an active button re-applied the same value.

Add an optional second argument reporting the state the click
transitions to. The built-in AssistantMessage derives it from the
message's current feedback, which also makes the built-in buttons
toggle; a custom AssistantMessage may pass its own value. The argument
is optional, so existing one-argument handlers are unaffected.

The toggle logic is extracted to ./feedback so it can be unit tested —
this package's vitest project runs in a node environment and has no
component-rendering harness.

Closes #2615
2026-08-17 17:22:24 -05:00
Benjamin Taylor 1ea18ca864 fix(react-ui): pad the chat header on mobile viewports
The `.copilotKitHeader` rule declared `padding-right` only inside
`@media (min-width: 640px)`, so below that breakpoint the header's
`space-between` children ran flush to the viewport edge and the close
button had no gutter.

Move the horizontal padding into the unconditional rule so it applies at
every viewport. The value matches the 24px the sm breakpoint already
used, so wide layouts are unchanged.

Fixes #2493
2026-08-17 17:22:21 -05:00
Tyler Slaton 69bb0a9814 fix(ci): stop enabling LangSmith tracing in the dojo e2e run (#6534) 2026-08-17 15:19:48 -07:00
copilotkit-qa-bot[bot] e8aa97649c fix(docs): parse Claude request before streaming 2026-08-17 15:12:58 -07:00
Martha Kelly Schumann d429f5d577 Fix Strands TypeScript sub-agent doc snippets (#6537)
## Summary

- include the Strands TypeScript sub-agent tools source in the demo
bundle
- define the canonical setup and supervisor delegation documentation
regions
- add a focused bundler regression for both regions and their boundaries

Linear:
[FAC-142](https://linear.app/copilotkit/issue/FAC-142/aws-strands-ts-sub-agents-docs-show-missing-snippets-in-two-sections)

## Validation

- `npm test -- __tests__/bundle-demo-content.test.ts` in
`showcase/scripts`
- `npm run typecheck` in `showcase/shell-docs`
- `npm run build` in `showcase/shell-docs`
- built `/strands-typescript/multi-agent/subagents` route contains both
snippets and zero `Missing snippet` warnings
- built Strands Python sub-agents route remains healthy as a control
2026-08-17 15:05:40 -07:00
copilotkit-qa-bot[bot] 61fd3c3828 Fix Strands TypeScript sub-agent doc snippets 2026-08-17 14:50:05 -07:00
Mark 23e4709718 chore(showcase): upgrade CopilotKit to 1.68.1 (#6510)
## Summary

- advance the canonical Showcase CopilotKit pin to `1.68.1`
- apply the release consistently across all 21 integrations and the
Showcase shell
- regenerate the affected npm lockfiles, including the LangGraph
TypeScript agent lockfile and the Shell's strict peer-dependency entries

This picks up
[#5837](https://github.com/CopilotKit/CopilotKit/pull/5837), which
bounds the in-memory agent runner to prevent unbounded thread retention
and OOMs.

## Verification

- Showcase pin ratchet passes at the existing 26-failure baseline/hash
- `@copilotkit/showcase-scripts`: 2,511 tests pass
- strict Shell `npm ci --ignore-scripts` succeeds, matching the Showcase
validation workflow
- Shell unit tests pass (241/241) and its production build succeeds
- clean installs and production builds pass for Ag2, Langroid, and
Mastra
- comparison with `origin/main` found no pin-induced TypeScript
diagnostics; the standalone TypeScript failures are pre-existing and
outside the current production build gate
2026-08-17 14:27:57 -07:00
Mark 89993e2d74 feat(showcase): deploy CrewAI conversational flows to staging (#6493)
## Summary

- provision and register the staging-only Railway service for CrewAI
Conversational Flows
- add the integration to the showcase build and redeploy workflow,
matching the existing service fleet
- enable Railway image-reference validation for the service while
validating only its declared staging environment
- keep full-fleet promotion compatible with intentional
single-environment services without weakening drift detection
- update the Railway SSOT, generated artifacts, fixtures, documentation,
and regression coverage

## Railway

- service: `showcase-crewai-conversational-flows`
- staging domain:
https://showcase-crewai-conversational-flows-staging.up.railway.app
- production intentionally not provisioned in this step

## Reviewer follow-up

- set `gateValidated: true` and removed the `gateIgnore` exemption; a
missing staging instance or incorrect GHCR repository/tag now fails
validation
- emit explicit `onlyEnvironment` metadata for SSOT-declared
single-environment services
- exempt only SSOT-declared environment asymmetry during no-argument
full-fleet promotion
- retain fail-closed behavior for unknown live Railway asymmetry and
explicitly targeted staging-only promotion
- add regression tests for staging-only image validation, full-fleet
parity, unknown services, targeted promotion, and generated metadata

## Conflict resolution against current `main`

- merged current `main`, including #6515 and #6516, instead of choosing
either side wholesale
- preserved #6515's canonical attachment fixtures, multimodal probe, and
global ownership regression test byte-for-byte from `main`
- preserved #6516's scripts typecheck fixes in `equivalence-gate.ts` and
`generate-search-index.ts` byte-for-byte from `main`
- reconciled the service registration introduced by #6504 with this PR's
build-matrix changes: there is exactly one SSOT entry, `ciBuilt: true`,
`gateValidated: true`, staging-only metadata, and no borrowed production
domain
- regenerated `railway-envs.generated.json`; it emits `onlyEnvironment:
"staging"` and an empty legacy production domain
- exclude that intentionally empty legacy domain from Ruby's
public-domain preflight set, preventing a permanent blank production
advisory
- the final PR diff against `main` contains only the intended 13
Railway/build/validation files and does not modify attachment fixtures
or probes

## Test plan

- `@copilotkit/showcase-scripts:test` through Nx: 77 files / 2,515 tests
passed
- `@copilotkit/showcase-harness:test` through Nx: 177 files / 3,712
tests passed; 2 files / 18 tests skipped
- focused multimodal harness regression: 11 tests passed
- showcase scripts TypeScript check passed
- showcase harness typecheck and build passed through Nx
- full Railway Ruby 3.2 suite passed: 188 tests / 723 assertions
- generated Railway JSON and promote-dropdown drift checks passed
- formatter and diff checks passed
- pre-commit affected-package checks passed, including Angular
build/package validation and 303 tests
2026-08-17 13:59:40 -07:00
Benjamin Taylor f07a7910d5 fix(ci): mock weather in the dojo e2e run, matching upstream
ag-ui's dojo-e2e sets AG_UI_MOCK_WEATHER=1 because the backend
tool-rendering demos call the live open-meteo API, which rate-limits CI's
shared egress IPs and hangs the suites. Our copy of the workflow drifted
and never picked it up, so those suites hit the live API — a latent flake
source, and a trace-divergence source now that the dojo asserts golden
event traces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 15:12:58 -05:00
Benjamin Taylor f6f6ed1872 fix(ci): stop enabling LangSmith tracing in the dojo e2e run
The dojo's new golden event-trace assertions (ag-ui #2392) compare
STATE_SNAPSHOT metadata exactly, and our e2e run was polluting it.

Injecting LANGSMITH_API_KEY makes langgraph-api force tracing on
(LANGSMITH_CONTROL_PLANE_API_KEY defaults to LANGSMITH_API_KEY, which
sets LANGSMITH_TRACING). The LangSmith client then merges every
LANGSMITH_*/LANGCHAIN_* env var into each run's metadata dict, and
langchain_core hands the tracer the same dict object the run config
streams out — so `langgraph dev`'s LANGSMITH_LANGGRAPH_API_VARIANT=local_dev
leaks into STATE_SNAPSHOT and every same-repo PR fails langgraph-python.

Upstream ag-ui runs these suites keyless against LLMock, which is why its
own CI is green on the same commit. Drop the key to restore parity; the
dojo never needed it, since OPENAI_BASE_URL already points at LLMock.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 15:11:38 -05:00
Ben Taylor fb0e2af897 docs(contributing): fix documentation typo (#6525)
## What does this PR do?

Fixes a typo in the contributor resources section: `documentatation` is
corrected to `documentation`.

This is a documentation-only change and does not affect runtime
behavior.

## Related PRs and Issues

- No related issue; checked the open pull requests for the same typo and
found no duplicate.

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation (not applicable; no functionality changes)
- [x] "Allow edits by maintainers" is checked
2026-08-17 15:10:26 -05:00
Ben Taylor 06eb9a9de0 chore(examples): update CLI starter package versions (#6532)
## Summary

- update all 17 first-party starter sources used by the Intelligence CLI
to the current npm `latest` tags for CopilotKit and AG-UI packages
- refresh each affected npm lockfile and keep shared AG-UI/CopilotKit
types deduplicated with targeted overrides
- move the Mastra starter to `@ag-ui/mastra@1.1.2` and remove its
obsolete legacy peer-dependency workaround
- update the LangGraph FastAPI parity sibling so the integration parity
contract remains green

## Why

The CLI checks out these directories directly from this repository.
Several templates still pinned older CopilotKit, Channels, Angular, and
AG-UI releases, which meant newly generated projects started behind the
current published packages.

## Validation

- verified 146 CopilotKit and AG-UI manifest references across 17 CLI
starters against npm `latest` tags
- ran standalone `npm ci --ignore-scripts` for every affected package
manifest
- built every affected frontend plus the nested AgentCore runtime
Lambda, Claude agent, LangGraph agent, and MCP server
- ran all 14 starter channel typechecks
- ran `pnpm parity:check`
- ran targeted `oxfmt`, `oxlint`, and `git diff --check`

One unrelated existing AgentCore CDK root build error remains at
`lib/backend-stack.ts` (`gatewayTarget` and `toolLambda` are undefined);
the changed runtime Lambda itself builds cleanly.
2026-08-17 14:57:34 -05:00
Mike Ryan 5b9776a1a0 chore(examples): update CLI starter package versions 2026-08-17 12:31:41 -07:00
Ben Taylor e6d3629445 fix(sdk-python): emit tool call events for middleware-intercepted SDK Actions (#5372)
## Summary

Frontend SDK Actions intercepted by `CopilotKitMiddleware` could
disappear before the client received a tool-call lifecycle, leaving the
handler uncalled and the conversation without a tool result or follow-up
answer. The bridge now consumes the middleware's authoritative
intercepted-call state and publishes each call through the AG-UI adapter
at most once. The focused intercepted file has 8 tests and the manual
AG-UI file has 30 tests; the combined run is 38 tests, with the
supported-version matrix remaining CI-owned.

## Root cause

`CopilotKitMiddleware.after_model()` removes frontend calls before
LangChain's backend tool node and records those exact calls for
final-message restoration. The previous adapter fallback ignored that
state and reconstructed frontend ownership from `on_chat_model_end` plus
the run's action catalog. That duplicated classification, failed when an
action carried `function: None`, and never ran on Python 3.10 because
the async LangChain path emitted no model callbacks there.

## Changes

- `sdk-python/copilotkit/langgraph_agui_agent.py`
- publish middleware-classified calls from the existing chain-state
event path
- reuse one lifecycle materializer and the parent adapter's per-run ID
ledger
- remove raw model-end/action-schema reconstruction and the duplicate
logger assignment
- `sdk-python/tests/test_intercepted_tool_call_events.py`
- exercise the real `create_agent(..., tools=[])` middleware and AG-UI
path in streaming and non-streaming modes
- cover exactly-once identity, Python 3.10 restoration, multiple IDs,
metadata opt-out, backend negative space, and malformed action/state
shapes

## What is not changed

- backend tools still use LangChain's normal tool node
- `after_agent` still restores intercepted calls into the final
assistant snapshot
- tool-call emission metadata still controls streamed lifecycle
visibility
- explicit `copilotkit_emit_tool_call()` calls keep their existing
caller-controlled semantics

## Related PRs and Issues

Closes #4342.

## Test plan

- [x] Focused intercepted SDK Action regression file, 8 passed on Python
3.12. Covers the real `create_agent(..., tools=[])` path, streaming,
restoration, mixed ownership, chain metadata suppression, malformed
state, and action-shape isolation.
- [x] Existing manual tool-call materialization file, 30 passed on
Python 3.12.
- [x] Combined focused selection, 38 passed on Python 3.12, counted once
rather than adding a second 38-test total.
- [x] Ruff check and format check on both changed files, both passed.
- [ ] Python SDK CI matrix green on Python 3.10, 3.11, 3.12, 3.13, and
3.14
2026-08-17 12:58:37 -05:00
Ben Taylor cd0d38a073 fix(sdk-python): restore frontend tool history faithfully in LangGraph middleware (#5308)
## Description

Fixes the LangGraph middleware "lying" to the agent about frontend tool
execution (#4759). When a model turn calls a `useFrontendTool` handler,
the middleware strips the FE tool calls so the backend `ToolNode` only
runs calls it actually made, then rehydrates them afterward. Previously
the rehydration could leave the restored AI message and its tool history
inconsistent, so providers that require every tool call to have a
matching result would break, and the agent saw an incorrect picture of
what executed.

## Changes

- `_restore_intercepted_tool_call_history` rebuilds the intercepted FE
tool calls with synthetic `ToolMessage` results only for the restored
model history (so providers that require every `tool_call` to have a
result stay valid), and preserves the original AI message's `name`,
`additional_kwargs`, and `response_metadata` on restore.
- Tracks `original_tool_calls` in the CopilotKit private state so the
original call set is restored exactly.

## Testing

`uv run pytest tests/test_copilotkit_lg_middleware.py` — 68 passed,
including new cases asserting the restored AI message keeps its
tool-call ids, name, `additional_kwargs`, and `response_metadata`, and
that tool results line up with their calls.

Closes #4759

AI was used for assistance.
2026-08-17 12:54:26 -05:00
Jordan Ritter 52ce3ef47d Railway cost reduction: langgraph memory caps + harness worker recycle (#6505)
## What & why

Railway **memory** is the showcase project's largest cost line
(~$1.2k/mo; egress was already fixed by the July internal-URL flip).
This PR attacks it two ways:

1. **Cap langgraph integration backend memory.** The three `langgraph-*`
showcase backends run the in-memory `langgraph dev` server and were
drifting to 6–13 GB RSS each. Set `MALLOC_ARENA_MAX=2` +
`MALLOC_TRIM_THRESHOLD_` on the python/fastapi entrypoints (glibc arena
fragmentation on the many-core Railway host) and
`NODE_OPTIONS=--max-old-space-size=1536` scoped to the
langgraph-typescript **agent** process (not the sibling Next.js server)
to cap the V8 heap. All values use `${VAR:-default}` so explicit Railway
overrides win.

2. **Recycle harness workers** after `WORKER_MAX_JOBS` settled jobs
(default 100, per-replica jitter via `WORKER_MAX_JOBS_JITTER`) to
pre-empt slow Chromium/heap growth — the Gunicorn `--max-requests` /
Celery `max-tasks-per-child` pattern. The recycle exits non-zero
(`WORKER_RECYCLE_EXIT_CODE=42`) so Railway's `ON_FAILURE` policy
restarts a fresh container, and routes teardown through the **same
deregister-first `gracefulTeardown` → `drainFleetWorker`** SIGTERM uses
(made idempotent via a once-latch) so a recycling worker deletes its
roster row instead of stranding it ~180s (a transient dashboard
false-red).

## Commits (by area of concern)

- `perf(showcase): cap langgraph integration backend memory`
- `feat(showcase/harness): recycle workers after WORKER_MAX_JOBS to
pre-empt leaks`
- `feat(showcase/harness): deregister workers cleanly on recycle exit`

## Validation

- **207/207** harness tests pass (recycle counter/threshold/jitter,
disabled-when-0, deterministic jitter, idempotent teardown, recycle-exit
deregister — all red-green + mutation-checked).
- oxfmt clean, oxlint 0 errors, typecheck clean (the only `tsc` errors
are 4 pre-existing `frontend-matrix.test.ts` errors from a missing
generated catalog, unrelated to this diff).
- Reviewed via a 4-round code-review loop (converged: 0 mandatory
findings; Procedure-3 promotion audit `PROMOTE_TO_A: 0`).

## ⚠️ Deploy / rollout notes

- **`WORKER_MAX_JOBS` defaults to 100 (recycle ON).** Set
`WORKER_MAX_JOBS=0` to disable if you want a staged rollout. Recommend
enabling on **staging first**.
- **The langgraph memory savings are not yet empirically measured.**
`MALLOC_ARENA_MAX` reclaims glibc fragmentation on the many-core host
but the GB delta must be confirmed by a **staging A/B** (deploy, compare
RSS with/without) before quoting a dollar figure. The change itself is
safe/standard; only the magnitude is unverified.
- Precondition confirmed: harness-workers restart policy is `ON_FAILURE`
(in-repo docs) — the non-zero recycle exit will restart. Recommend
pinning `restartPolicyType: ON_FAILURE` explicitly in IaC as
defense-in-depth (follow-up).

## Follow-up (out of scope — pre-existing, surfaced by review)

The review surfaced a large pre-existing debt backlog in touched files,
none load-bearing on this PR's subject (all deferred). Notable
candidates for a separate PR:
- **Recycle-teardown hardening:** bound `pool.shutdown` in the recycle
path with a timeout so a hard-wedged Chromium can't delay the voluntary
exit (currently backstopped by the `/health` 503 healthcheck); make the
recycle-vs-SIGTERM exit-code deterministic; `latchOnce` sync-throw
guard.
- **Monitor write-only-red:** `onPidSaturation` writes RED with no clear
path (permanent false-red once tripped).
- **Entrypoint robustness:** `wait -n` under `set -e` making the
exit-code/diagnostic block dead code; `kill` of wrapper PIDs orphaning
node children; TS watchdog probing the `:8124` sidecar not `:8123`.
- **Control-plane parity:** `runControlPlane` missing the S3 backup cron
/ `hydrateProbeLastRuns` / `probe_runs` metric wiring that `boot()` has.
- Assorted test-hygiene (afterEach `doUnmock` leaks, a few vacuous
assertions, fixed-timer flakes).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-17 09:42:52 -07:00
CRDong233 58e049b58e docs(contributing): fix documentation typo 2026-08-17 22:46:18 +08:00
Lukas Moschitz d45a478a83 fix(channels-slack): rename decimal_allowed to Slack's is_decimal_allowed
`SlackNativeProps` declared `decimal_allowed`. Slack's `number_input` field is
`is_decimal_allowed`. Slack accepts a message whole or not at all, so the
unrecognised key refused the entire `chat.postMessage` call with
`invalid_blocks: invalid field at /blocks/N/element` and ended the Channels
delivery that carried it — no exception reached the caller and nothing arrived
in the channel.

The typed path was therefore the broken one: a developer who bypassed our types
and hand-wrote `is_decimal_allowed` got it right, while everyone using
`Slack.Element.NumberInput` silently lost the message.

Verified live against Slack, one delivery per case:

- `decimal_allowed` alone — refused, `invalid_blocks: invalid field at
  /blocks/0/element`
- `is_decimal_allowed` alone — delivered
- both names present — refused with the same error, which isolates the unknown
  key as the cause: Slack's required field is satisfied and the payload is
  otherwise identical to the one that delivers

Not treated as a breaking change and no alias is kept. The old name never
worked, so no caller can depend on its behaviour, and keeping it would preserve
the trap. Removing it converts a silent message loss into a compile error that
names the right field.

Also adds a test comparing every field name `native.ts` declares against
Slack's own Block Kit declarations in `@slack/types` (already a dependency),
parsed with the TypeScript parser rather than matched as text. Names
`@slack/types` does not cover — `container`'s `blocks`, `rich_text_list`'s
`offset`, `card`'s `slack_icon` and `subtext`, and the whole
`data_visualization` vocabulary — are listed individually with the reason, so
the check states its coverage instead of implying completeness. Floors on the
vocabulary size and on the number of names actually compared keep a collapsed
comparison from passing as success.

Sweeping the remaining names turned up no other mismatch.
2026-08-17 12:49:10 +02:00
Ran Shem Tov 4ed613a599 fix(showcase): ignore blank expected Railway domains 2026-08-17 10:37:58 +02:00
Ran Shem Tov b81a11bf0c Merge remote-tracking branch 'origin/main' into codex/fix-crewai-conversational-flows-deploy
# Conflicts:
#	showcase/scripts/__tests__/verify-railway-image-refs.test.ts
#	showcase/scripts/railway-envs.generated.json
#	showcase/scripts/railway-envs.test.ts
2026-08-17 10:25:36 +02:00
Ran Shemtov 4526bb00d2 fix(showcase): canonicalize multimodal fixtures (#6515)
## Summary

- delete obsolete D4 multimodal fixtures instead of disguising them with
the unrecognized `_d4_unused_multimodal_image` field
- make each D6 `multimodal.json` the sole owner of the exact image and
PDF prompts by removing duplicate `agentic-chat.json` entries and broad
fallback aliases
- align the canonical D5 fixture, all D6 canned responses, and probe
assertions with the real CopilotKit logo and CopilotKit Quickstart
assets, with ownership/semantics ratchets

## Root cause

`_d4_unused_multimodal_image` was introduced as a fixture tombstone, but
AIMock does not interpret that field. D4 does not run a multimodal turn,
so retaining those fixtures did not preserve D4 coverage.

The D6 fixture tree also had the same multimodal prompts in both
`agentic-chat.json` and `multimodal.json`. Because fixtures are loaded
recursively and matching is first-match-wins, the file named
`multimodal.json` was not reliably the fixture that answered the probe.
Four integrations additionally had broad aliases such as `image` and
`document`.

Both the D6 responses and the canonical harness D5 fixture described
assets that do not exist and claimed the canned response proved upload
transport. The actual checked-in assets are the CopilotKit logo and
CopilotKit Quickstart PDF, and prompt matching cannot prove that their
bytes reached the model boundary.

This revision removes those ambiguities rather than renaming them: one
exact owner per prompt and integration, no D4 tombstones, and factual
expected content.

## Verification

- regression coverage was run red against the prior layout, then green
after canonicalizing ownership and semantics, including the canonical
harness D5 fixture
- `nx format:check --uncommitted`
- changed TypeScript files: oxlint found 0 warnings and 0 errors
- `@copilotkit/showcase-scripts:test`: 2,512 passed
- `@copilotkit/showcase-harness:test`: 3,712 passed, 18 skipped
- `@copilotkit/showcase-harness:typecheck`: passed
- `@copilotkit/showcase-harness:build`: passed
- fresh isolated D6 cells:
  - `google-adk:multimodal` — green
  - `langgraph-python:multimodal` — green
  - `crewai-crews:multimodal` — green

## Scope boundary

The current fixture schema still matches these cases by prompt. This PR
proves deterministic fixture ownership and truthful assertions; it does
not prove that attachment bytes reached the model boundary.
[OSS-845](https://linear.app/copilotkit/issue/OSS-845) tracks
attachment-aware normalization, matching, journal evidence, and
prompt-without-attachment negative tests.
2026-08-17 10:13:09 +02:00
Ran Shemtov 181854cd03 Merge branch 'main' into investigate-google-adk-staging 2026-08-17 10:12:19 +02:00
Mark ad890b21d1 fix(showcase): restore scripts typecheck (#6516)
## Summary

- narrow promotion gate cells to the feature-bearing contract their
consumers already require
- widen frontend search page metadata to its declared interface without
changing runtime entries
- restore the Showcase scripts TypeScript gate before rebuilding #6493

## Root cause

Two independent type contracts on `main` drifted after their data models
changed: promotion `GateCell` inherited a nullable `featureId` even
though the closure contains only feature-bearing cells, while the
frontend search table retained an overly narrow tuple-derived union
after Slack and Teams stopped defining `guidanceTitle`.

## Verification

- reproduced the baseline: 8 TypeScript diagnostics on `origin/main`
- `pnpm exec tsc --noEmit --project showcase/scripts/tsconfig.json`
- focused gate tests: 32/32
- search contract: 7/7
- full uncached Showcase scripts suite: 2511/2511 across 77 files
- generated search indexes unchanged and byte-identical
- scoped formatter and lint clean

Prerequisite for reconciling #6493.
2026-08-17 01:08:55 -07:00
Mark 81ea8e8b6f test(showcase): keep canonical multimodal fixture factual 2026-08-16 20:43:35 -07:00
Mark 23cb3987fc fix(showcase): make multimodal fixtures factual and canonical 2026-08-16 20:33:11 -07:00
Mark ed295a1184 fix(showcase): stop D4 fixtures shadowing multimodal D6 2026-08-16 19:22:18 -07:00
Mark de2d3b67da fix(showcase): restore scripts typecheck 2026-08-16 19:16:04 -07:00
Murat Sari ea9ccff81f feat(angular): expose agent capabilities (#6513)
## Summary

Closes another React–Angular parity gap by adding the Angular equivalent
of React’s `useCapabilities`.

- Add `injectCapabilities` as a readonly signal
- Support the configured or explicitly selected agent
- Add React-parity tests
- Document the new Angular API

## Testing

- Angular tests, typecheck, build, publint, and API checks pass
- Angular docs tests pass
- Full workspace tests executed; unrelated Vue and React Native failures
remain
2026-08-16 22:26:06 +02:00
Murat Sari 703944880d feat(angular): expose agent capabilities 2026-08-16 22:11:36 +02:00
Murat Sari a4fb56e186 feat(angular): support fetch credentials (#6512)
## Summary

This closes an Angular parity gap with React by adding Fetch
`credentials` support.

- Forwards credentials through the runtime and provisional agents.
- Keeps cached provisional agents synchronized with credential changes.
- Documents cross-origin cookie authentication and CORS requirements.

## Testing

- Angular tests, typecheck, and build passed.
- Full workspace suite executed; unrelated React Native configuration
failures remain.
2026-08-16 21:23:28 +02:00
Murat Sari 5720cd7fdc feat(angular): support fetch credentials 2026-08-16 21:03:52 +02:00
Cursor Agent 49bf4535a9 test(sdk-python): add checkpoint roundtrip coverage for orphan-handoff contract
Adds tests that exercise the full checkpoint roundtrip path:
- test_checkpoint_roundtrip_placeholder_replaced_by_real_result: Verifies
  _fix_messages_for_bedrock correctly replaces patch_orphan_tool_calls
  placeholder with real FE result
- test_checkpoint_roundtrip_multiple_fe_calls_with_placeholders: Multiple
  FE calls with placeholders all correctly resolved
- test_after_agent_leaves_fe_call_orphaned_for_checkpoint: Confirms
  after_agent does not persist synthetic ToolMessages, leaving FE calls
  as orphans for the real result to fill

These tests address reviewer feedback requesting coverage for the checkpoint
persist → add_messages merge → patch_orphan_tool_calls → real FE result path.

Co-authored-by: Matt Van Horn <mvanhorn@users.noreply.github.com>
2026-08-16 18:12:11 +00:00
Mark 1232f71495 fix(showcase): sync shell lockfile for strict npm install 2026-08-15 21:27:04 -07:00
Mark db22a686cc chore(showcase): upgrade CopilotKit to 1.68.1 2026-08-15 18:46:53 -07:00
Mark 82cd5e007a fix(showcase): clear probe thread state after runs (#6506)
## Summary

- add best-effort remote thread cleanup for showcase probe runs
- clear the process-wide in-memory runner store through the ungated
`copilotkit-voice` catch-all after D3, D4, and D6 browser teardown
- keep cleanup failures non-fatal while warning with the probe slug
- cover per-invocation cleanup, rejected/timed-out requests, unchanged
probe results, and backend URL selection

## Verification

- Nx format check for the seven changed files
- Nx showcase harness typecheck
- D3, D4, and D6 sibling test suites (175 tests)
- Nx showcase harness build
python-sdk/v0.1.95
2026-08-15 11:52:23 -07:00
Mark 6e9e119b2e fix(showcase): clear probe thread state after runs 2026-08-15 11:35:57 -07:00
Jordan Ritter b2f9d2fe7e feat(showcase/harness): deregister workers cleanly on recycle exit
Wire the recycle exit through the same deregister-first graceful teardown as
SIGTERM (a shared, latch-once gracefulTeardown -> drainFleetWorker), so a
recycling worker deletes its roster row instead of stranding it ~180s for
fleet-health to reclaim (a transient false-red on every recycle). The latch
makes the shared teardown run at most once even if a recycle races a SIGTERM.
2026-08-15 11:10:30 -07:00
Jordan Ritter c59e158a74 feat(showcase/harness): recycle workers after WORKER_MAX_JOBS to pre-empt leaks
A worker stops claiming after WORKER_MAX_JOBS settled jobs (default 100,
staggered per replica via WORKER_MAX_JOBS_JITTER so replicas do not recycle in
lockstep), then exits non-zero (WORKER_RECYCLE_EXIT_CODE=42) so Railway restarts
a fresh container. Mirrors Gunicorn --max-requests / Celery max-tasks-per-child;
0/unset disables. Caps slow Chromium/heap growth on long-lived harness workers.
2026-08-15 11:10:30 -07:00