The canary flow took ~11.5 min steady-state (and 20 min in an observed
run). Measured from run 30473499191, the time went to five avoidable
places rather than to real work.
1. `npx --yes npm@11.15.0 publish` ran per package, and npx re-resolves
the spec against the registry on EVERY invocation: ~16s of each
package's ~21s. A 9-package channels canary paid ~2.4 min of pure npx
overhead; a 16-package monorepo release paid over 4 min. Hoist the
pinned npm into lib/npm-cli.ts, install it once into a throwaway
prefix, and reuse the binary.
2. publish-release.yml was the only workflow in the repo with no pnpm
store cache, so all three jobs installed 4608 packages cold every
time. Usually ~45s each, but registry-bandwidth bound and heavy
tailed: the observed run spent 9m08s here on tarballs arriving at
2-49 KiB/s. Add the same node-version-keyed cache the rest of CI uses.
3. The notify job ran for canaries only to compute "post nothing" — the
builder already returns should_post=false for mode=prerelease and the
self-watchdog is already gated off. ~85s of dead work on the critical
path, since canary.yml waits for the whole run. Skip the job, keeping
it reachable for a python_publish dispatch.
4. The build job fetched full history for canaries, which need none (no
tag, no GH Release, no release-note commit range, and `nx run-many`
resolves no merge base). That rode along in the 837 MiB workspace
artifact too. Shallow-fetch prereleases; stable keeps depth 0 because
its publish job pushes tags out of that artifact's .git.
5. Two smaller ones: the artifact was gzipped and then re-deflated into
the artifact zip (compression-level: 0), and the orchestrator's
run-discovery loop slept 6s before its first poll.
Verified: 143 release-script tests pass (6 new for the npm-cli helper),
actionlint + shellcheck + the scope-dropdown guard are clean, the
prerelease dry-run path still enumerates all 9 channels packages, and a
live probe confirms the helper installs npm 11.15.0 once (3.2s) and
memoizes thereafter (0ms).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two release-tooling defects turned a pair of canary publishes into a broken
combination for consumers (a canary runtime resolving the last STABLE
channels-intelligence, which still called the removed `channel.addAdapter`).
1. Canary versions were prereleases of an ALREADY-PUBLISHED version. A stable
release leaves the working tree on the version it just published, and
computePrereleaseVersion appended `-canary.<id>` to exactly that, so the
canary sorted BELOW its own release (`0.2.1-canary.x < 0.2.1`): the `canary`
dist-tag pointed behind `latest`, and no dependent range could ever resolve
it. Base the canary on the next unreleased version instead (patch bump,
reusing computeNextStableVersion's prerelease rule).
2. A canary published one scope at a time, but the scopes are only independent
on the version axis. `@copilotkit/runtime` carries
`"@copilotkit/channels-intelligence": "workspace:*"`, and `pnpm pack`
resolves that against the working tree — so a `monorepo` canary pinned the
channels family to its last stable release even when the commit changed both
sides of the contract. Add a prerelease-only `all` selector that bumps and
publishes every scope from one commit under one shared canary id, and warn
loudly when a single-scope canary leaves a cross-scope pin behind.
`all` is a selector, never a scope: stable releases stay single-scope (their
tag, release branch, and npm/Slack links all derive from one scope name), which
publish-release.yml enforces in both jobs and the dropdown guard enforces per
workflow.
Renames the Bots SDK to the Channels SDK. Names only — no behavior change.
- 8 packages @copilotkit/bot* -> @copilotkit/channels* (git mv dirs, names,
workspace: cross-deps). Now includes @copilotkit/bot-intelligence ->
@copilotkit/channels-intelligence (landed on main via #5761; unpublished, so
renamed fresh with the family).
- release.config.json scope keys + versionSource; ReleaseScope union;
canary/stable-release/publish-release scope dropdowns; verify script
- examples/slack (Kite) + examples/teams: deps, jsxImportSource, imports
- showcase/shell-docs: content dirs docs/bots->docs/channels and
reference/bot->reference/channels, nav registry, redirects
createBot and other API names unchanged. Old @copilotkit/bot* to be deprecated
after the new packages publish (bot-intelligence was never published).
Re-derived onto latest main (was conflicting after #5761 landed).
Refs OSS-438
Move the Intelligence-delivered managed-bot surface out of @copilotkit/bot into
its own package so the adapter, transports, contracts, and lifecycle ship
independently of bot core.
- New @copilotkit/bot-intelligence: intelligenceAdapter + DeliverySource/EgressSink
(+ in-memory impls) + placeholder contracts + startManagedBots/validation/
activation metadata. Production code imports only types from @copilotkit/bot
and @copilotkit/bot-ui.
- @copilotkit/bot keeps the generic PlatformCodec seam (moved to src/codec.ts) and
all core createBot changes (addAdapter, deferred store, id fields,
__managed/skipIngressDedup, exclusive guard). It now also exports the
FakeAdapter/FakeAgent test utilities for downstream adapter-package tests.
- Registered the new release scope: release.config.json, scripts/release/lib/
config.ts, and the canary/publish/stable release workflows.
Tests preserved: bot 150 + bot-intelligence 19 (= the prior 169); bot-slack 261.
Builds typecheck across bot/bot-intelligence/bot-slack/runtime; publint/attw/
oxlint/oxfmt clean.
The stable-release (create-pr), publish-release, and canary workflows all
used a target-agnostic concurrency group, so releasing one scope (e.g.
`monorepo`) would queue behind an unrelated scope's run (e.g. `angular`)
despite touching disjoint packages and tags. Fold the release target into
each concurrency key so different scopes run in independent lanes while
same-scope runs stay serialized (cancel-in-progress: false), preserving the
version-bump / tag-push / npm-publish race protection.
publish-release also fires on merged release PRs where `inputs.scope` is
empty; the PR branch `release/publish/<scope>/v<version>` carries the scope
via `github.head_ref`, so the key stays scope-distinct on that path too.
ENT-950
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a bot-whatsapp release scope to release.config.json and the matching
workflow_dispatch scope dropdowns in publish-release / stable-release / canary,
so the package can be released via the manual CI trigger like bot-slack.
canary / publish: a workflow_dispatch orchestrator that mirrors the
dispatched ref to a unique short-lived canary/<slug>-<run_id>-<attempt>
branch via the GitHub API (devops-bot App token, app-id 1108748),
dispatches publish-release.yml on that ref with mode=prerelease, waits
for the delegated run (gh run watch + explicit conclusion check), and
deletes the ref afterward.
It does NOT publish to npm itself — publish-release.yml holds the
single npm OIDC trusted-publisher binding. Failure paths covered:
suffix validated before any side effect, ref kept when a dispatched
run was never located, ref deleted when the dispatch itself failed,
status-gated deletion + fresh cleanup token for cancellation/timeout
(90-min ceiling exceeds the 1h App-token TTL and queueing behind
publish-release's global concurrency group).
Ported from ag-ui-protocol/ag-ui PR #1914 with cpk adaptations
(scopes from release.config.json; dry_run -> dry-run input mapping).