Commit Graph

13442 Commits

Author SHA1 Message Date
tylerslaton 6c354037fc chore: release monorepo v1.63.0 2026-07-15 22:18:07 +00:00
Tyler Slaton 5fa4f2813d fix(release): unblock Channels umbrella publish (#5990)
## Problem

The Channels v0.2.0 release publishes its dependency packages, then
fails before publishing the umbrella package because pnpm rejects the
freshly published dependencies under the 24-hour minimum release age
policy.

## Why

The registry-backed verifier installs the packed umbrella in an isolated
temporary consumer without carrying a Channels-family release-age
exemption into that consumer.

## Fix

Generate a pnpm workspace config for the isolated consumer that exempts
every Channels package while retaining the maturity gate for unrelated
dependencies. Add regression coverage for the complete family. Verified
with all 109 release-script tests, the registry-backed Channels
verifier, explicit lint/typecheck/format checks, and the full Nx package
build.
channels/v0.2.0
2026-07-15 14:26:45 -07:00
Tyler Slaton a5387831c0 fix(release): exempt Channels verifier from maturity gate 2026-07-15 14:11:44 -07:00
Ran Shemtov a233fff69f Merge branch 'main' into claude/brave-kirch-8dbf00 2026-07-15 23:06:05 +02:00
Benjamin Taylor 7edb6dbf19 docs: address adversarial review of threads-lifecycle guide
- History section: "Platform replay (the default)" → "Server-side replay",
  state the precondition (needs a server-side store — platform or a
  persisting AgentRunner; a bare runtime replays nothing), and use the
  correct method name connectAgent() (there is no agent.connect()).
- First-message thread creation (headless): fix a race — the example set
  the thread via setActiveThreadId() (a deferred React state update) then
  sent immediately, which lands on the previous thread; and truly-headless
  has nothing syncing agent.threadId. Now set agent.threadId directly and
  add a caveat explaining the state-setter timing.
- v1 notes: correct the setThreadId throw attribution — the useThreads
  setter silently shadows under a prop; the throwing setThreadId is the
  one on the main <CopilotKit> hooks.
- MCP Apps: drop the unverified "not persisted server-side" assertion;
  reframe as client-side re-derivation that restores via normal history
  replay.
- LangGraph: don't imply the linked persistence page proves the Platform
  UUID rule; loosen the checkpointer shorthand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 15:55:57 -05:00
Tyler Slaton 45fa204843 chore: release channels v0.2.0 (#5989)
## Release channels v0.2.0

**Scope:** `channels` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `channels` 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 `channels` packages to npm at version `0.2.0`
   - Creates git tag `channels/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.
2026-07-15 13:38:33 -07:00
Ran Shem Tov 0440c58106 docs(showcase/mastra): document OM-as-background-activity (OSS-391)
Short how-to section in background-tasks.mdx: enable Observational Memory on
the agent's Memory + opt in on the adapter (observationalMemory: true on
getLocalAgents), render via renderActivityMessages with activityType
mastra-observational-memory. Mirrors the working /demos/observational-memory
wiring. (--no-verify: worktree commitlint binary still broken post-crash.)
2026-07-15 13:36:41 -07:00
tylerslaton add6539dcd chore: release channels v0.2.0 2026-07-15 20:29:29 +00:00
Sam Julien c72b94db4b docs(shell-docs): cover rich Threads history 2026-07-15 13:19:51 -07:00
Sam Julien f6e4c9f8ad docs(shell-docs): elevate Threads screenshot frame 2026-07-15 13:16:31 -07:00
Benjamin Taylor 47aa0b1725 docs: add Thread & History Lifecycle guide
Adds a framework-agnostic guide covering the full client-side thread
lifecycle, filling a gap between the Headless Threads how-to and the
Threads & Persistence Architecture explanation:

- how a threadId is minted (UUID v4, client-side at mount) + the
  resolution precedence and the remount-stability caveat
- how history is restored (explicit-threadId connect() replay vs.
  manual agent.setMessages); notes v2 has no initialMessages
- switching/starting threads (setActiveThreadId / startNewThread) and
  the prop-controlled no-op guard
- intercepting thread creation on first message (mint-up-front vs. the
  headless onSubmitMessage seam; built-in <CopilotChat> overrides it)
- CopilotKit threads vs. framework checkpointers (two layers correlated
  only by threadId; a checkpointer creates checkpoint tables, not a
  threads table)
- MCP Apps activity/history (frontend constructs; re-synthesize on hydration)
- v1 vs v2 disambiguation

Addresses the recurring thread-lifecycle support questions (#4790, #4778,
#5434, #2242, #5931). Added to the Threads nav group.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 15:13:25 -05:00
Tyler Slaton 9504e0666c refactor(channels): add batteries-included package architecture (#5948)
## Summary

- Extract the platform-neutral Channels foundation into
`@copilotkit/channels-core`.
- Make `@copilotkit/channels` the batteries-included consumer entry
point, with adapter and UI subpaths.
- Release the umbrella, core, UI, and all six adapters as one shared
`channels` version scope.
- Verify the packed consumer contract and migrate the Slack and Teams
examples to the umbrella.

## Why

Consumers should be able to install one Channels package without making
the runtime or selective integrations depend on every platform SDK.
Shipping the complete Channels family together prevents adapter/core
version drift and makes the umbrella's exact dependency set release as a
compatible unit.

## How

- Move shared bot/runtime primitives into `channels-core` and invert
adapter/runtime dependencies.
- Add exact workspace dependencies and export subpaths from the umbrella
package.
- Consolidate the existing release configuration and all three release
workflow selectors into one shared `channels` scope containing all nine
packages.
- Use `@copilotkit/channels` as the version source: the next minor
release resolves to `0.2.0` and bumps every Channels package together.
- Publish scoped packages in dependency order for both stable and canary
releases: UI, core, adapters, then the umbrella.
- For a stable Channels release, publish the UI/core/adapters first, run
the registry-backed packed-consumer verifier against those newly
published exact versions, then publish the umbrella.
- Generate Channels release notes from `channels/v*` tags rather than
the monorepo `v*` tags.
- Verify builds, type checks, tests, package artifacts, examples, and
release workflow scope synchronization locally.

### First stable release sequence

1. Bootstrap the currently unpublished `@copilotkit/channels-core`
package on npm and configure npm trusted publishing for every Channels
package against this repository's `release / publish` workflow and `npm`
environment.
2. Create and merge the `channels` minor release PR. The stable workflow
publishes the Channels family in the staged order above and validates
the packed umbrella from the registry before the umbrella is released.
3. Create and merge a subsequent `monorepo` release PR so the published
`@copilotkit/runtime` switches from the historical umbrella dependency
to `@copilotkit/channels-core`.
2026-07-15 13:12:16 -07:00
Sam Julien 59f15608ba docs(shell-docs): reduce Threads screenshot padding 2026-07-15 13:09:57 -07:00
Ran Shem Tov 4eed87c75b fix(showcase/mastra): correct cancel-path narration via aimock toolResultContains gate
Pick and cancel resume the native schedule_meeting suspend tool with the
SAME toolCallId; the requests differ only inside the tool-result payload,
so the cancel resume previously hit the pick-confirmation fixture and the
assistant replayed "Booked: ... confirmed" after the user cancelled. The
"__cancelled" toolCallId gates on the Denied fixtures were fictional and
never matched.

aimock 1.37.0 (CopilotKit/aimock#299) adds a JSON-expressible
match.toolResultContains substring gate on the last tool-result message.

- gen-ui-interrupt.json: cancelled legs now gate on the real toolCallId +
  toolResultContains "cancelled", ordered before the confirmation legs
- interrupt-headless.json: gained the same cancelled legs (the demo's
  Cancel button had no fixture at all)
- aimock-fixtures.test.ts: matchKey learns toolResultContains; duplicate
  ceiling 303 -> 305 (headless cancelled legs share exact keys AND
  response text with the gen-ui-interrupt ones, one pair per pill)
- e2e specs: cancel tests now assert the Denied narration and reject
  Booked/Scheduled, so the regression cannot silently return

Verified live against aimock built from source (fixture replay):
8/8 Playwright e2e across both demos, plus manual pick + cancel runs on
/demos/gen-ui-interrupt and /demos/interrupt-headless.

Commit uses --no-verify: this worktree's lefthook runner is broken
(pre-existing, see daa501daa); commitlint + prettier + the fixtures
vitest were run manually and pass.

Follow-up (blocked on aimock#299 npm publish): bump the vendored
@copilotkit/aimock pin in showcase/scripts/package.json and pull the
refreshed ghcr.io/copilotkit/aimock:latest.
2026-07-15 13:09:41 -07:00
Sam Julien 40c0401871 docs(shell-docs): tighten Threads screenshot frame 2026-07-15 13:04:21 -07:00
Ben Taylor 0777a26833 feat(channels-intelligence): realtime transport parity — kinds, identity, history/files, delete (#5983)
## What & why

The Realtime Gateway transport had drifted from the HTTP polling
transport, so managed channels running over the gateway behaved
differently from direct. This brings the realtime path to full parity.

Before, the realtime transport:
- built a **text-only** ingress envelope —
commands/reactions/interactions were coerced into empty turns;
- keyed conversations **per-turn** (`conversationKey = turn.id`), so
threaded follow-ups didn't share agent/session state;
- **dropped the provider actor** — `env.user` was never populated (on
*both* transports, in fact);
- implemented **none** of `fetchFile`/`getHistory`/`uploadFile`, so the
realtime path silently ran with no history and no file support;
- had **no `delete` render kind**, so `thread.delete` couldn't render
over the gateway.

## Changes

- **`claim-mapping.ts` (new, shared):** extract the claim→ingress
mapping — `ClaimedDelivery`, `conversationKeyFromReplyTarget`,
`mapDeliveryToEnvelope` — into one module both transports import, so
they can't drift again (drift *was* the bug). Adds the provider `actor`
to the claim turn and maps it to `env.user` — fixing identity on
**both** paths.
- **realtime transport:** builds the envelope via the shared mapper
(real kind discrimination, thread-stable `conversationKey`, actor→user)
instead of the inline text-only build. Fail-closed: an unmodeled
reply-target/kind is dropped+logged, not crashed.
- **`intelligence-file-history.ts` (new, shared):** extract
`fetchFile`/`getHistory`/`uploadFile` into
`IntelligenceFileHistoryClient`. These are **HTTP-only** — the gateway
relays the render-event stream but never file bytes or history. The
realtime transport gains them when configured with `appApiBaseUrl` +
`apiKey` (threaded through the launcher); without those, the methods
stay `undefined` and the adapter degrades exactly as before.
- **`delete` render kind:** add `{ kind: "delete"; ref }` to
`ChannelRenderEvent` (mirrors the frozen Intelligence contract) and
route `thread.delete` through a render frame when a render sink is
wired, like post/update/file.

## Tests

- `claim-mapping.test.ts`: actor→user, kind discrimination
(command/reaction/interaction/text), thread-stable conversationKey
(slack/teams), unmodeled-adapter throw.
- `render-events.test.ts`: realtime non-text kind + identity +
thread-stable key; file/history capability toggling on config; a
delete-render-frame test.
- Full suite (160) + `check-types` + `build` green.

## Companion

This is the CopilotKit SDK half of the managed-transport parity work;
the Intelligence-side half (gateway `render_event/1` validator for
file/delete, DB CHECK, Connector Outbox `chat.delete`, actor on the
claim) landed separately. Together they close the direct-vs-managed
parity matrix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-15 14:41:41 -05:00
github-actions[bot] 36cad9530e style: auto-fix formatting 2026-07-15 19:18:05 +00:00
Jordan Ritter 9299533bfd fix(showcase): self-activate CVDIAG routing + guard public $PORT with alerting watchdog (claude-sdk-python)
Self-activate CVDIAG_LOG_STDOUT=0 when CVDIAG_PB_URL is wired (safe: only silences stdout when PB is receiving; explicit override preserved). Extend the watchdog to poll the public $PORT /api/health and, on sustained failure, POST a loud #oss-alerts Slack alert BEFORE kill-restart; add the same alert to the agent-\:8000 branch (no silent recovery). Add uvicorn --no-access-log to cut the access-log flood. Together these keep the shared log stream under the 500/sec cap so the pipe never backs up.
2026-07-15 12:15:10 -07:00
Jordan Ritter 50f119b459 fix(showcase): route CVDIAG stdout emission behind CVDIAG_LOG_STDOUT gate (default ON)
Shared cvdiag_bootstrap: gate the per-LLM-call breadcrumb capture handler and the emit_cvdiag stdout write behind CVDIAG_LOG_STDOUT (default ON so every other integration is byte-for-byte unchanged; opt-out per service). Enqueue to the non-blocking PocketBase sink BEFORE the stdout write so a wedged fd1 cannot cost the durable breadcrumb. No sampling; full fidelity to PB. Red-green unit tests incl. a hostile-stdout durability test.
2026-07-15 12:15:09 -07:00
Jordan Ritter 50245bb4dd test(showcase): reproduce stdout-backpressure event-loop wedge (docker RED+GREEN harness)
Faithful node:22-slim repro: fd1 through the same awk process-substitution as entrypoint.sh, a Railway-capped drain reader, a uvicorn+CVDIAG-shaped flood, and the static no-log /api/health as victim. RED wedges (200->502, CPU->0, heartbeat frozen); the FIXED lane stays 200 throughout. run.sh asserts the outcome (exit 3/4/5 on a false result, proven). watchdog.sh runs the entrypoint public-guard loop verbatim and needle-anchors it against entrypoint.sh.
2026-07-15 12:15:07 -07:00
Sam Julien 402646ff32 docs(shell-docs): update Threads overview screenshot 2026-07-15 12:14:44 -07:00
Ran Shem Tov cb9696fc57 Merge remote-tracking branch 'origin/main' into claude/brave-kirch-8dbf00 2026-07-15 11:45:56 -07:00
Ran Shem Tov daa501daa2 fix(showcase/mastra): interrupt resume-loop, browse_web card, reasoning replay order
Playwright-verified fixes for the Mastra demo validation round:

- aimock interrupt fixtures (gen-ui-interrupt, interrupt-headless): add
  hasToolResult:false to the schedule_meeting suspend legs so the resume
  request falls through to the toolCallId confirmation fixture instead of
  re-matching the suspend leg (picker loop, duplicated intro). Mirrors
  hitl-in-chat.json.
- aimock-fixtures test: ceiling 301 -> 303; the two suspend keys now
  intentionally collide across the three mastra interrupt cells
  (runtime-disambiguated by route/fixtureFile like existing aliases).
- browse-web tool: return the result OBJECT instead of JSON.stringify;
  the bridge encodes once more so stringifying double-encoded the result
  and BrowseResultsCard showed "0 results" despite a successful browse.
- reasoning-chain pill: "Roll a d20 ..." instead of "Roll a 20-sided die
  ..." — the d4 agentic-chat fixture shadowed the first leg under replay
  (d4 loads before d6) and pushed reasoning a step late. Real-LLM order
  verified correct.
- header-forwarding shim: default x-aimock-context to "mastra" when absent
  so browser-driven demos replay against aimock instead of 404ing. Harness
  header wins when present; real providers ignore it.
- docker-compose.local: make OPENAI_BASE_URL overridable via .env (default
  aimock unchanged) so real-LLM cells like browser-use can be tested live.

(--no-verify: commitlint binary missing in this worktree after the session
crash — ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL, infra not message)
2026-07-15 11:45:36 -07:00
Sam Julien dfe5532280 docs(shell-docs): add themed Threads diagrams 2026-07-15 11:37:11 -07:00
Benjamin Taylor a8407f84fd fix(channels): address Tyler CR — wire app-api URL through runtime activation + map user name (OSS-476)
- [P1] History/files were absent on the NORMAL managed path: defaultActivateChannel
  never forwarded the app-api HTTP URL, so the transport (which installs
  fetchFile/getHistory/uploadFile only when appApiBaseUrl is set) ran without
  them for Channels started by the CopilotRuntime handler — only manual
  low-level launcher callers got file/history. Thread intelligence.ɵgetApiUrl()
  through ChannelActivationConfig.apiUrl → defaultActivateChannel →
  startChannelsOverRealtimeGateway({ appApiBaseUrl }). The launcher + transport
  already accepted it.
- [P2] Managed turns exposed the provider profile under a non-public `displayName`
  field, leaving PlatformUser.name undefined. Map env.user.displayName -> name
  (parity with the direct Slack adapter, which populates `name`).

Tests: deriver returns apiUrl; defaultActivateChannel forwards appApiBaseUrl to
the launcher opts; onMessage sees message.user.name. channel-activation-config +
channels-intelligence (170) green; runtime build type-checks. (channel-manager.test
executes in CI — local vitest hits the known optional-peer-dep resolution flake.)
2026-07-15 13:36:36 -05:00
Sam Julien cc107b776a docs: refresh stale contributing commands, langgraph RunnableConfig imports, and Anthropic model IDs (#5982)
## What & why

Consolidates three community docs fixes that were each opened against
the retired `docs/content/docs/` tree (now just a symlink to
`showcase/shell-docs/`), so none of them could merge as-is even though
the underlying doc bugs are still live. This re-applies them against the
current shell-docs source and, where the original proposals had drifted,
uses commands verified against the current repo.

### 1. Contributing / package-linking guides — supersedes #3509
Turborepo has been **fully removed** from the repo (no `turbo`
dependency, no `turbo.json`), but every contributing guide still
instructs `turbo run …`. Across the root guide, all per-integration
copies, and the shared snippets:
- Drop the "Turborepo v2.x installed globally" prerequisite; bump pnpm
to **v10.x** to match the root `packageManager` (`pnpm@10.33.4`).
- Reframe the monorepo as a pnpm workspace orchestrated by **Nx**.
- Replace commands with equivalents verified against the current root
`package.json` / Nx targets:
  - `turbo run build|dev|format|lint` → `pnpm run build|dev|format|lint`
- `turbo run link:global` / `unlink:global` → `pnpm exec nx run-many -t
link:global` / `unlink:global`
- per-package dev (`turbo run dev --filter=…`) → `pnpm exec nx watch
--projects=packages/<name> -- pnpm run build`
- also fixed a pre-existing stale reference: `pnpm run example-dev` →
`pnpm run dev:examples` (the real script)

### 2. Anthropic model IDs — supersedes #3656
`built-in-agent/model-selection` listed dotted IDs that aren't valid;
hyphenate `claude-3-7-sonnet`, `claude-opus-4-1`, `claude-3-5-haiku`.

### 3. LangGraph `RunnableConfig` imports — supersedes #4069
Twelve langgraph reference pages annotate `config: RunnableConfig` in
Python snippets without importing it. Add `from langchain_core.runnables
import RunnableConfig` to each such block. (Tutorial pages were
intentionally left out to avoid disrupting their step-by-step
narrative.)

## Credit
Thanks to the original authors whose fixes this incorporates:
@electricalen (#3509), @Abubakar-01 (#3656), and @Koushik-Salammagari
(#4069). Those PRs can be closed in favor of this one once merged.

## Testing
- `grep` confirms **0** remaining `turbo run` / `Turborepo` / `turbo@2`
references and **0** remaining `example-dev` references across the docs
content.
- All replacement scripts/targets verified present in the root
`package.json` (`build`, `dev`, `format`, `lint`, `dev:examples`) and as
per-package Nx targets (`link:global`, `unlink:global`).
- Confirmed **0** langgraph Python blocks remain that use
`RunnableConfig` without importing it (excluding the
intentionally-skipped tutorial pages).
- Spot-checked insertion placement/indentation in both deeply-nested
(`interrupt-flow.mdx`) and flat (`auth.mdx`) code blocks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-15 11:11:54 -07:00
Benjamin Taylor 237cbf4cf9 chore(channels): CR hygiene — real test coverage + doc/log cleanups (OSS-476)
Trivial items from the CR confirmation rounds (no behavior change to production
paths):

- intelligence-adapter.test.ts: `delete source.getHistory` was inert (getHistory
  is a prototype method; delete only removes own props), so the "no getHistory"
  branch was never actually exercised. Shadow with an own `undefined` instead so
  the `source?.getHistory?.()` short-circuit is genuinely tested.
- in-memory-transports.ts: mirror the production `limit <= 0 -> []` guard in
  InMemoryDeliverySource.getHistory (was `slice(-limit)` → returns ALL for 0).
- realtime ack(): log the empty-turn (no accepted frames) drop so the OSS-491
  redelivery pile-up is diagnosable (every other drop path here logs).
- http-transports.ts: remove two orphaned JSDoc comments dangling over
  ClaimResponse (leftovers from the file/history extraction).
- intelligence-adapter.ts: correct an inaccurate op-id comment (mintOp is the
  ${turnId}:${seq} source; the render path keys on ${turnId}:${slot}:${seq}).

channels-intelligence 170 tests + check-types green.
2026-07-15 12:58:53 -05:00
Tyler Slaton 5811cab177 fix(channels): align rebase with channel API 2026-07-15 10:29:21 -07:00
Benjamin Taylor 2718474229 fix(channels): second CR round — graceful realtime stop() + parity/hygiene (OSS-476)
From the 7-agent CR confirmation round:

- RealtimeGatewayTransport.stop() now halts intake (a `stopped` guard in
  handleDeliveryAvailable — the session exposes no `off` to detach the
  DELIVERY_AVAILABLE listener) and DRAINS the in-flight delivery (awaits the
  serial `processing` chain) before clearing state, so a turn settling at stop
  time still sends its terminal signal instead of silently no-oping and
  redelivering. Mirrors HttpDeliverySource.stop().
- Realtime nack() truncates the reason to 500 chars (parity with HTTP).
- getMessages drops empty content parts before join(" ") so a read_thread
  transcript isn't corrupted with doubled/leading/trailing spaces (a test had
  enshrined "part one  part two").
- Removed dead imports (buildContentParts, AgentContentPart, ChannelFileRef)
  left in http-transports.ts after the file/history extraction.

Deferred (delivery-contract / design; need coordination — folded into OSS-491):
timeout-nack can redeliver a still-running turnId (overlap); realtime push()
no-state fallback vs HTTP fail-loud (documented intentional — parity Q); the
empty-turn completion signal.

Tests: stop() drains in-flight + ignores post-stop deliveries; getMessages
assertion corrected. channels-intelligence 170 tests + check-types green.
2026-07-15 12:21:53 -05:00
Tyler Slaton eed52e13c7 refactor(release): preserve configured publish order 2026-07-15 10:13:19 -07:00
Tyler Slaton 3b22abbbd1 fix(release): stage channels publishing 2026-07-15 10:13:18 -07:00
Tyler Slaton 17213998a1 chore(release): unify channels version scope 2026-07-15 10:13:18 -07:00
Tyler Slaton 02a93c3b8a docs(channels): clarify umbrella release availability 2026-07-15 10:13:18 -07:00
Tyler Slaton fad2aed6c2 test(channels): verify packed umbrella consumers 2026-07-15 10:13:17 -07:00
Tyler Slaton 8f6f97f231 docs(channels): dogfood the umbrella in channel examples 2026-07-15 10:13:17 -07:00
Tyler Slaton 163d0e99b8 chore(release): add channels core and umbrella scopes 2026-07-15 10:12:23 -07:00
Tyler Slaton 3dba09b7c7 feat(channels): add the batteries-included umbrella 2026-07-15 10:12:23 -07:00
Tyler Slaton 06fb2ed34a refactor(channels): extract the platform-neutral core 2026-07-15 10:11:55 -07:00
Benjamin Taylor f126acfb43 docs: address review — real example dev path/script, root auth imports, pnpm 10, langgraph self-contained fences
Addresses @samjulien's review on #5982:

1. Contributing example command: the guide changed into a nonexistent
   `examples/next-openai` and ran `dev:examples` (a workspace build/watch
   script that never starts a server). Point it at the real
   `examples/v1/next-openai` package and its `example-dev` (`next dev`)
   script, which actually serves http://localhost:3000/presentation.
   Fixed in the shared snippet + all per-integration copies.

2. LangGraph auth: langgraph variants are docs_mode: generated, so the
   `/auth` route renders the root `docs/auth.mdx`, not the framework copy.
   Add the missing `from langchain_core.runnables import RunnableConfig`
   to the two Python blocks in the root source that route renders.

3. Self-contained fences: add the import to the non-tutorial
   `langgraph/shared-state/predictive-state-updates.mdx` Python fence and
   the `snippets/integrations/langgraph/frontend-tools.mdx` fence, so the
   zero-missing-import claim holds for every non-tutorial langgraph block.

4. Contributor prerequisites: bump the `docs-contributions` guides from
   pnpm 9 to pnpm 10 to match the code-contributions requirement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 12:08:29 -05:00
github-actions[bot] c2e2b4c0fd style: auto-fix formatting 2026-07-15 17:08:16 +00:00
Benjamin Taylor 54fa303477 fix(channels): address adversarial CR findings on the realtime transport (OSS-476)
Pre-merge 7-agent CR of #5983 surfaced several realtime-transport defects (all
in channels-intelligence). Fixes:

- Poison-payload re-lease loop: an unmappable delivery (unmodeled reply-target
  adapter / unknown input.kind) with a valid lease was logged + dropped, so
  app-api re-leased the identical payload forever. It now fails NON-retryable
  (dead-letter), mirroring the HTTP path. nack() gains a `retryable` param.
- Double-terminal-signal race: realtime ack()/nack() deleted delivery state
  AFTER the wire push, so a per-turn-timeout nack could race a late dispatch ack
  and emit BOTH fail + complete_requested. Now delete-before-push (XOR).
- Concurrent dispatch: deliveries were handled fire-and-forget; now processed
  serially (parity with the HTTP runLoop) so an in-flight redelivery can't reset
  the shared per-turn seq counter or run two turns of one conversation at once.
- actor.displayName was carried through the claim mapper then dropped in
  dispatchTo (`{ id }` only) — now forwarded to handlers (OSS-476 identity).
- fetchFile enforced MAX_INBOUND_FILE_BYTES only against declared content-length;
  the actual read was unbounded. Now streams and aborts past the cap.
- getHistory returned the FULL history for limit<=0 (slice(-0)) and hydrated file
  bytes for over-returned messages it then discarded. Now caps to the most recent
  `limit` BEFORE hydrating; limit<=0 -> [].
- stream() posted an empty text frame for an empty stream; now skips the post.
- HTTP withTimeout/defaultSleep timers now unref() (parity with realtime).
- Corrected the inaccurate thread_started comment in claim-mapping.ts.

Deferred to OSS-491 (delivery-terminal-signal contract, needs app-api
coordination): an empty turn (reaction/command that posts nothing) has no valid
completion signal (acceptedThrough requires >=1) and redelivers; and the
run_error swallow on the HTTP-fallback render path.

Tests: poison non-retryable, single-terminal XOR, serial dispatch, displayName
forwarding, getHistory limit<=0 + cap. channels-intelligence 169 tests + check-types green.
2026-07-15 12:06:50 -05:00
Benjamin Taylor bc883e89c0 feat(channels-intelligence): realtime transport parity — kinds, identity, history/files, delete (OSS-476)
The realtime-gateway transport had drifted from the HTTP transport: it built a
text-only ingress envelope that coerced commands/reactions/interactions into
empty turns, keyed conversations per-turn (breaking threaded follow-ups),
dropped the provider actor identity, and implemented none of
fetchFile/getHistory/uploadFile (so the realtime path silently ran with no
history and no file support). It also had no `delete` render kind. This brings
the realtime path to full parity with direct.

- claim-mapping: extract the claim→ingress mapping (ClaimedDelivery,
  conversationKeyFromReplyTarget, mapDeliveryToEnvelope) into a shared module
  both transports use, so they cannot drift again. Add the provider `actor` to
  the claim turn and map it to `env.user` (fixes identity on BOTH paths).
- realtime transport: build the envelope via the shared mapper — real kind
  discrimination, thread-stable conversationKey, actor→user — instead of the
  text-only inline build. Fail-closed: an unmodeled reply-target/kind is
  dropped+logged, not crashed.
- file/history: extract fetchFile/getHistory/uploadFile into a shared
  IntelligenceFileHistoryClient (HTTP-only — the gateway never relays bytes or
  history). The realtime transport gains them when configured with
  `appApiBaseUrl` + `apiKey` (threaded through the launcher); absent that, the
  methods stay undefined and the adapter degrades exactly as before.
- delete render kind: add `{ kind: "delete"; ref }` to ChannelRenderEvent
  (mirrors the frozen Intelligence contract) and route thread.delete through a
  render frame when a render sink is wired (OSS-420), like post/update/file.

Tests: shared-mapper unit tests (actor→user, kind discrimination,
conversationKey, unmodeled-adapter throw); realtime tests for non-text kind +
identity + thread-stable key and file/history capability toggling; a
delete-render-frame test. Full suite + check-types + build green.
2026-07-15 11:41:01 -05:00
Ben Taylor 183b0d9dc9 fix(channels): realtime-transport reliability hardening + residual bot-naming scrub (closes OSS-485, OSS-482) (#5972)
Combines the two OSS-473 follow-ups (originally #5972 + #5973, now
folded here) into one PR for a single review/merge. Base is `main`
(OSS-473/#5963 has merged). Reviewable **commit-by-commit** — the
mechanical rename is isolated in commit 1; the behavior changes are
commits 2–4.

## Commit 1 — `refactor(channels)`: scrub residual internal "bot" naming
(closes OSS-485)

Mechanical, naming-only, **no behavior change** — the last internal
"bot" vestiges left out of 473's atomic telemetry-surface commit.

- `bot` local variable → `channel` in `create-channel.ts` internals +
the ~15 tests that exercise it.
- `BotNode` type → `ChannelNode` in `@copilotkit/channels-ui` and
**every** importer (channels,
slack/teams/discord/telegram/whatsapp/intelligence adapters, slack/teams
examples — 256 refs).
- `botName` adapter-SPI option → `channelName` on `AdapterStartContext`
+ its `create-channel` caller + the one consumer
(`IntelligenceAdapter.start` ctx), in one change so the SPI can't drift.
(Phoenix wire contract was already `channelName` as of 473.)
- Stale `bot-ui`/`bot-slack` comment refs →
`channels-ui`/`channels-slack`; `Symbol.for("copilotkit.bot-ui.*")` →
`"copilotkit.channels-ui.*"`.
- **Kept** (out of scope): the platform `isBot?` author flag (unrelated
semantic) and example `bot` instance vars / "demo bot" prose
(user-facing).

## Commits 2–4 — `fix`: realtime-transport reliability & parity
hardening (closes OSS-482)

The self-contained observability/robustness subset of the OSS-473 CR
follow-ups (`packages/channels-intelligence` transport +
`packages/runtime` manager). Each hardening ships with a test that fails
without the fix.

- **`emit()` fail-loud** (`intelligence-adapter.ts`) — returned a
synthetic `MessageRef` on `{ ok: false }`, acking a failed
post/update/delete as success (silent egress drop). Now throws → the
delivery is nacked/retried.
- **Realtime delivery dispatch** (`realtime-gateway-transport.ts`) — the
`void handleDeliveryAvailable(...)` fire-and-forget had no error
boundary and no deadline. Replaced with a `.catch` + a bounded per-turn
timeout that nacks + logs on failure/timeout (parity with the HTTP
`runLoop`).
- **`ChannelManager.stop()` per-handle timeout** — a wedged
`handle.stop()` hung teardown/SIGTERM forever. Each is now bounded by
`stopHandleTimeoutMs` (default 5000); on timeout it's logged and
abandoned so other entries still stop.
- **`ChannelManager.ready({ timeoutMs })`** — a set-wide timeout
discarded an erroring channel's reason when a sibling hung. The deadline
is now **per channel**, so the `AggregateError` carries both the real
activation error **and** a named timeout for each hanging channel.
- **Forward `ChannelManager` `log` down** to the launcher/transport so
transport-level drop diagnostics (e.g. a version-skew
missing-`leaseToken` outage) aren't silent in the managed path.
- **`examples/slack/.env.example`** — OpenAI-only `AGENT_MODEL`
guidance; removed never-read `ANTHROPIC_API_KEY`/`GOOGLE_API_KEY`;
blanked the presence-gated `LINEAR_API_KEY`/`NOTION_*` placeholders (a
non-blank value wires a broken MCP); documented `NOTION_MCP_PORT`; added
WhatsApp to the adapter list.

### Already landed in OSS-473 (not re-done here)
The reconnect **"gave-up → error" escalation** is fully implemented on
`main`: `realtime-gateway.ts` bounds the reconnect window
(`reconnectGiveUpMs`, default 60s) and emits a terminal `gave_up`; the
launcher exposes `onStateChange`;
`ChannelManager.registerConnectionObserver` maps `gave_up → error`
(covered by `realtime-gateway.test.ts` +
`channel-manager-reconnect.test.ts`).

### Explicitly EXCLUDED — owned by OSS-474 / OSS-476
Left untouched (overlap in-flight work): no cross-turn history on the
realtime path (per-turn `conversationKey`) → OSS-474/476; empty-turn
`ack()` redelivery livelock → OSS-474/475/476; non-text parity
(command/interaction/reaction) → OSS-476; `thread.delete()` render frame
→ OSS-476 (PR #554); durable StateStore on the managed realtime path →
OSS-474/476.

## Testing
- **DoD grep** — `grep -rn "\bbot\b\|botName\|BotNode" packages/channels
packages/channels-ui` (`.ts`/`.tsx`, excl. `dist/`) → **0**; `BotNode`
gone repo-wide.
- **check-types** green across all 8 channels packages +
`@copilotkit/runtime`.
- **tests** green: channels 155, channels-ui 23, slack 277, teams 88,
discord 193, telegram 149, whatsapp 73, channels-intelligence 144,
runtime `channel-manager` 40; slack-example 63, teams-example 2. Full CI
matrix (incl. `unit` 20.x/22.x/24.x) green on this branch.
- Each 482 hardening has a test that fails pre-fix (no silent ack;
dispatch nacks on throw/timeout; `stop()` resolves + logs on a wedged
handle; `ready()` aggregate preserves the real reason;
`defaultActivateChannel` forwards `log`).

Closes OSS-485. Closes OSS-482.
2026-07-15 11:29:09 -05:00
Benjamin Taylor a758faa19d fix(channels): CR follow-ups — honest stopped status + correct .env WS port (OSS-482)
Two fixes from the pre-merge adversarial CR of this PR (both pre-existing,
flagged as in-subject):

- ChannelManager.status() reported overall "online" for a manager stopped
  BEFORE activate() (e.g. SIGTERM during startup): `entries` is empty, so the
  empty-set fold returned "online" — a torn-down manager reading healthy. Now
  short-circuits to "stopped" when `this.stopped`, matching the documented
  status() contract. New red-green test covers the stop()-before-activate() case.

- examples/slack/.env.example: COPILOTKIT_INTELLIGENCE_WS_URL example was
  ws://localhost:4401, but derivation is a scheme-only swap of the :4201 API URL
  (→ ws://localhost:4201) and 4401 is used nowhere — a user uncommenting it hit a
  dead port. Corrected to :4201 and clarified the derivation note.
2026-07-15 10:50:20 -05:00
Benjamin Taylor 07c1ad7ef1 docs: refresh stale contributing commands, langgraph RunnableConfig imports, and Anthropic model IDs
Consolidates three stale-docs fixes that were opened against the retired
`docs/content/docs/` tree (now a symlink) and so could no longer merge:

- Contributing/package-linking guides (root + all integration copies +
  shared snippets): Turborepo is fully removed from the repo (no dep, no
  turbo.json). Drop the Turborepo prerequisite, bump pnpm to v10.x to match
  `packageManager`, describe the monorepo as a pnpm workspace orchestrated by
  Nx, and replace `turbo run <task>` with verified equivalents:
  `pnpm run build|dev|format|lint`, `pnpm exec nx run-many -t (un)link:global`,
  `pnpm exec nx watch` for a single package, and `pnpm run dev:examples`
  (the real script; `example-dev` did not exist). Supersedes #3509.
- built-in-agent/model-selection: hyphenate the Anthropic model IDs
  (`claude-3-7-sonnet`, `claude-opus-4-1`, `claude-3-5-haiku`). Supersedes #3656.
- langgraph reference docs: add the missing
  `from langchain_core.runnables import RunnableConfig` import to Python code
  blocks that annotate `config: RunnableConfig`. Supersedes #4069.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 09:18:02 -05:00
renovate[bot] afcd74a587 chore(deps): update zizmorcore/zizmor-action action to v0.6.0 (#5981)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[zizmorcore/zizmor-action](https://redirect.github.com/zizmorcore/zizmor-action)
| action | minor | `v0.5.7` → `v0.6.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/592) for more information.

---

### Release Notes

<details>
<summary>zizmorcore/zizmor-action (zizmorcore/zizmor-action)</summary>

###
[`v0.6.0`](https://redirect.github.com/zizmorcore/zizmor-action/compare/v0.5.7...v0.6.0)

[Compare
Source](https://redirect.github.com/zizmorcore/zizmor-action/compare/v0.5.7...v0.6.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.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI1OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2026-07-15 12:55:38 +00:00
Benjamin Taylor 8eda1d64aa docs(examples): correct slack .env.example env accuracy (OSS-482)
Pre-existing .env.example issues noted in the OSS-473 CR:

- AGENT_MODEL example was `anthropic/claude-sonnet-4.5`, but runtime.ts is
  OpenAI-only (web search is an OpenAI hosted tool; it strips a leading
  `openai/` and passes the rest to `openaiText`). Use an OpenAI example and say
  so.
- Removed ANTHROPIC_API_KEY / GOOGLE_API_KEY — never read by this runtime.
- LINEAR_API_KEY, NOTION_TOKEN and NOTION_MCP_AUTH_TOKEN were non-blank
  placeholders, but runtime.ts turns the Linear/Notion MCPs ON purely on the
  presence of LINEAR_API_KEY / NOTION_MCP_AUTH_TOKEN — a placeholder wires a
  broken MCP. Blanked them (they're optional integrations, like the commented
  Discord/Telegram/WhatsApp creds).
- Documented NOTION_MCP_PORT (the `pnpm notion-mcp` sidecar port, default 3001;
  must match NOTION_MCP_URL).
- Added WhatsApp to the header list of supported adapters.
2026-07-15 07:44:35 -05:00
Benjamin Taylor ed37e418ca fix(runtime): bound ChannelManager.stop(), surface ready() AggregateError on hang, forward log to transport (OSS-482)
Three ChannelManager observability/robustness hardenings from the OSS-473 CR.

stop() per-handle timeout: stopEntry awaited handle.stop() unbounded, so a
wedged stop() (e.g. a socket.disconnect that never returns) hung teardown — and
thus SIGTERM shutdown — forever. Each handle.stop() is now bounded by
stopHandleTimeoutMs (default 5000); on timeout it is logged and abandoned so
every other entry still reaches `stopped`.

ready() surfaces the real reason on hang: ready({ timeoutMs }) wrapped the whole
`allSettled` in one timeout, so when one channel settled to `error` while a
sibling hung, it rejected with only a generic timeout and DISCARDED the erroring
channel's reason. The deadline is now applied PER CHANNEL, so the AggregateError
carries both each failed channel's real reason AND a named timeout for each
still-hanging channel.

Log forwarding: the manager's `log` reached activation-level events only; the
default engine (defaultActivateChannel → startChannelsOverRealtimeGateway) never
passed it down, so transport-level drop diagnostics (e.g. a version-skew
missing-leaseToken outage) were silent in the managed path. `log` is now
forwarded down to the launcher/transport.

Note: the reconnect "gave-up → error" escalation from the same CR is already
implemented end-to-end in OSS-473 (realtime-gateway.ts reconnectGiveUpMs +
ChannelManager.registerConnectionObserver) and is not re-done here.

Tests: stop() resolves + logs a timeout when handle.stop() never settles;
ready() aggregate contains both a real activation error and the hung sibling's
named timeout; defaultActivateChannel forwards its log sink to the launcher opts.
2026-07-15 07:44:35 -05:00
Benjamin Taylor 2b4b19cf3b fix(channels): fail loud on egress failure + bound realtime delivery dispatch (OSS-482)
Two transport reliability hardenings on the managed realtime path, from the
OSS-473 CR.

emit() fail-loud: IntelligenceAdapter.emit() returned a synthetic MessageRef on
`{ ok: false }`, acking a failed post/update/delete as success (silent egress
drop on the HTTP-fallback path). It now throws with the failure code so the
failure propagates up the render/run path and the delivery is nacked/retried.

Realtime delivery dispatch: `session.on(delivery.available)` fired
`void this.handleDeliveryAvailable(...)` with no error boundary and no per-turn
deadline — an onDelivery rejection became an unhandled rejection (silent drop)
and a hung handler pinned the delivery forever. Replaced the `void` with a
`.catch` and wrapped the turn in a bounded per-turn timeout that nacks + logs on
failure/timeout (parity with the HTTP runLoop's turnTimeoutMs).

Tests: egress `{ ok: false }` makes thread.post throw (no silent ack); an
onDelivery throw and an onDelivery that exceeds deliveryTimeoutMs both nack
(channel.delivery.fail.v1) and log.
2026-07-15 07:41:17 -05:00
renovate[bot] 9ab25acda1 chore(deps): update zizmorcore/zizmor-action action to v0.6.0 2026-07-15 12:40:42 +00:00