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
Brings the 499-commit-stale foundations branch up to date with main so #5761
has a clean diff and no stale reverts (e.g. forwardHeaders). Conflicts:
- CopilotThreadsDrawer.tsx: took main's (main renamed CopilotDrawer -> ThreadsDrawer
+ added the collapse feature; the branch's edit was a no-op import-type split).
- pnpm-lock.yaml: regenerated with the pinned pnpm 10.33.4 (adds @copilotkit/bot-intelligence).
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 StateStore interface and the in-memory MemoryStore default remain;
durable backends can be reintroduced as a follow-up. Both adapter packages
were merged in #5613 but never published to npm, so removal is a clean
delete with no consumer impact.
- Delete packages/bot-store-redis and packages/bot-store-postgres.
- Revert the bot release scope and drift guard to bot + bot-ui.
- Strip the Redis dep, demo:restart script, restart demo, docker-compose,
and REDIS_URL env from examples/slack.
- Rewrite the bot persistence/transcripts docs around "MemoryStore default
+ implement the StateStore interface yourself for durability".
Adds a durable persistence layer for @copilotkit/bot, replacing the
in-memory-only ActionStore with a pluggable StateStore.
- StateStore interface (kv/list/lock/dedup/queue) with a shared
conformance suite; MemoryStore default plus @copilotkit/bot-store-redis
and @copilotkit/bot-store-postgres backends.
- createBot({ store }): typed per-thread state via Standard Schema,
action snapshots persisted through the store, per-conversation turn
lock (onLockConflict drop|force), and inbound-event dedup keyed on a
stable eventId. ActionStore is kept as a deprecated alias.
- Cross-platform transcripts (bot.transcripts + identity resolver) with
age-bounded retention (prune on append + filter on read), and
runAgent({ transcript: true }) to auto-inject history and capture the
reply.
- createBot({ components }) re-registers components so durable actions
re-fire after a restart; restart-durability demo in examples/slack.
- Dedup is marked seen only after the turn lock is acquired, so a turn
dropped on lock-conflict does not burn its eventId (no lost retries).
- Release lockstep: bot-store-redis/postgres version with bot + bot-ui.
Compares the workflow_dispatch scope choice dropdowns in
publish-release.yml, stable-release.yml, and canary.yml against the
authoritative .scopes keys in release.config.json, failing CI on drift.
Also validates that every explicitly-named arm in publish-release.yml's
notify-job npm-url case statement is a valid scope (catch-all makes
full coverage unnecessary). Parsers fail loud and distinct on shape
changes (anchored case detection, loose-vs-strict cross-check,
zero-options and zero-block guards) rather than silently passing.
Ported from ag-ui-protocol/ag-ui (PR #1914 wiring); config lives at
the repo root in CopilotKit.
Round-2 review fixes for the GITHUB_OUTPUT helper and the release scripts
that emit through it.
emitGithubOutputs (scripts/release/lib/github-output.ts):
- Replace the key newline/CR check with a full GitHub-Actions-safe charset
check: /^[A-Za-z_][A-Za-z0-9_-]*$/. A key containing "=" or whitespace
would silently corrupt the key=value line; rejecting up-front is
strictly safer. Value validation (single-line) is unchanged — "=" in
values is legal because GitHub splits on the first "=".
- Update the docblock accordingly.
prerelease.ts:
- Remove the dead `?? getCurrentVersion(scope)` fallback. The empty-list
guard above makes packages[0] guaranteed, and the fallback would have
masked a package.json missing its version field by emitting a version
divergent from what the loop publishes. Fail loudly with an explicit
exit instead.
- Drop the now-unused getCurrentVersion import.
- Add a comment above the dry-run emitGithubOutputs call explaining that
emitting in dry-run is safe — the publish workflow gates publish + the
verify guard on inputs.dry-run != true, so the dry-run emission only
serves local/e2e contract verification.
publish-release.ts:
- Hoist getPackagesForScope + empty-list guard above the prerelease-suffix
and registry checks. A misconfigured scope now fails with the clear
"no packages found" error instead of a misleading "not greater than
published" one. Loop is unchanged.
github-output.test.ts:
- Loosen the key-newline assertion from the JSON.stringify-coupled
/bad\\nkey/ to the stable /alphanumeric/ phrase from the new message.
- Add tests: "=" in key throws, space in key throws, empty key throws,
and "=" in value is accepted and written verbatim (note=a=b).
- Move vi.restoreAllMocks() to the top of afterEach so spies cannot leak
into env restore + rmSync cleanup.
Call sites audited:
- emitGithubOutputs: only ever called with {version, scope} (prerelease,
publish-release) — all valid under the new charset.
- publishVersion derivation: only used inside prerelease.ts main().
- getCurrentVersion: still imported by publish-release.ts, bump-prerelease.ts,
prepare-release.ts; only the prerelease.ts import was removed.
- getPackagesForScope hoist in publish-release.ts: `packages` was only
read inside the publish loop below; nothing earlier depended on it.
Hardens the new GITHUB_OUTPUT emission path so a malformed value can't smuggle
extra `key=value` lines into the workflow's step outputs, and so the workflow's
"Verify publish step emitted version" guard can't be fooled by a publish that
did nothing.
emitGithubOutputs now validates every key/value for `\n`/`\r` BEFORE the
GITHUB_OUTPUT early-return — a malformed value is a caller bug and should fail
loudly even when running locally. A multi-line value would need the heredoc
form, which this helper deliberately does not support.
prerelease.ts and publish-release.ts now fail loud when getPackagesForScope
returns an empty list. Without this, the new GITHUB_OUTPUT emission would make
the workflow's "Verify publish step emitted version" guard pass on a run that
published nothing — previously the missing output made such a run fail. The
guard runs BEFORE the dry-run branch in prerelease.ts. In publish-release.ts,
the inline iteration of getPackagesForScope(scope) is hoisted to a `packages`
const so the same guard fires before the publish loop.
The "no-op when GITHUB_OUTPUT is unset" test now spies on fs.appendFileSync
and asserts it wasn't called (the previous read of the unrelated temp file
was vacuously true). New tests cover newline/CR in value and newline in key.
The prerelease.ts usage string previously advertised `[--suffix <label>]`,
but the script never parses --suffix (suffix handling lives in
bump-prerelease.ts per the header comment). Removed.
Call sites enumerated:
- emitGithubOutputs: prerelease.ts (dry-run + post-publish), publish-release.ts
- getPackagesForScope: prerelease.ts, publish-release.ts (this commit);
bump-prerelease.ts, prepare-release.ts, versions.ts (not changed — out of
scope for this hardening)
Verification:
- npx vitest run --config scripts/release/vitest.config.mts → 91 passed
- Red-green for the newline validation: temporarily removed the validation,
the 3 new newline/CR tests failed (assertion: expected fn to throw); restored,
back to green.
- E2E: GITHUB_OUTPUT="$OUT" pnpm release:prerelease:dry succeeded and the
output file contained `version=1.59.5` and `scope=monorepo`.
Note: Fix 2's empty-list guard fires only on a misconfigured scope (no unit
test reachable — prerelease.ts is outside the vitest include glob and the
guard is boundary validation against a misconfigured scope, not a behavior
worth contriving a test harness for).
prerelease.ts published canaries successfully but never wrote the
version output the publish-release workflow's "Verify publish step
emitted version" guard reads, so every canary dispatch ended red after
a successful publish. Extract the GITHUB_OUTPUT append (previously
inline in publish-release.ts) into a shared lib/github-output.ts helper
and call it from both publish scripts.
Call-site enumeration:
- emitGithubOutputs: declared lib/github-output.ts; called from
prerelease.ts (dry-run path + after publish) and publish-release.ts
(replaces the inline appendFileSync block, same version=/scope= keys).
- No symbols removed; fs import in publish-release.ts still used (3
remaining call sites).
Add a pure builder that renders one concise #oss-alerts Slack message
per release from a unit-tested truth table: suppresses canary/dry-run
runs, gates npm/PyPI failure arms on event-derived release intent, and
pages on uncertain state. The CLI wrapper serializes env input to the
builder and writes the result to GITHUB_OUTPUT, failing loud on any
malformed or missing input.
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.
publish-release.ts now checks npm for each package before publishing
and skips versions that already exist. Makes publish idempotent —
safe to retry after partial failures. Removes the publish-remaining
one-shot workflow that's no longer needed.
Replace pnpm publish with pnpm pack + npx npm@11.15.0 publish to
enable OIDC authentication. Set NODE_AUTH_TOKEN='' to prevent the
expired secret from blocking OIDC. Removes test workflow.
Remove pnpm run build (and pnpm run test) calls from publish-release.ts
and prerelease.ts so that repository build code never executes with
NPM_TOKEN in the environment. The CI build job (contents: read, no
secrets) now handles all building and testing, uploading pre-built
artifacts for the publish job to consume.
For prerelease: extract version bumping into a new bump-prerelease.ts
script that runs in the build job before the build step, ensuring the
built artifacts contain the correct canary version numbers.
Also fix prerelease build job to use persist-credentials: false,
matching the publish-release build job pattern.
- Add tests for bumpPackages: verifies workspace:* protocol is
preserved and exact version deps are updated
- Add vitest config for scripts/release/
- Add release script test step to test_unit.yml so these run on
every PR and push to main
bumpPackages was overwriting internal dependency references like
"workspace:*" with the new version string, causing pnpm to try
resolving the version from the npm registry (which fails because
it hasn't been published yet). Now skips deps using workspace protocol.
Each release scope has its own packages, version source, and
independent version track:
- monorepo: 12 core @copilotkit/* packages (shared version)
- cli: copilotkit CLI (independent version)
- angular: @copilotkitnext/angular (independent version)
Branch pattern is now release/publish/<scope>/v<version> and git
tags use <scope>/v<version> for non-monorepo scopes.
- Replace import.meta.dirname (Node 21.2+) with fileURLToPath
workaround for Node 20 compatibility
- Rename workflows to release / pre, release / publish, release /
create-pr so they group together in the Actions UI
- Fix semver regex to allow hyphens in prerelease identifiers
- Add unit tests for parseSemver, computeNextStableVersion,
computePrereleaseVersion
Replace changesets with a simple, stateless release system:
Stable release (PR-gated):
Actions → "create release PR" → pick patch/minor/major → CI runs →
merge → publishes to npm, creates git tag + GitHub Release
Prerelease (ad-hoc):
Actions → "publish / prerelease" → publishes current version with
-canary.<suffix|timestamp> to npm under "canary" tag
Key features:
- All 12 core @copilotkit/* packages share a single version
- AI-generated release notes via Anthropic API
- Notion draft for team editing before merge
- Notion link commented on the release PR
- Guards: concurrent release PR check, version > npm check, clean
semver check, canary-only prerelease tag
- release/publish/v* branch pattern (hard to accidentally match)
- TypeScript throughout (tsx runner)
- release.config.json with versionedTogether/versionedIndependently
Replace eslint and prettier with oxlint and oxfmt for faster linting
and formatting across the monorepo. Remove all eslint and prettier
configs, dependencies, and related packages. Add .oxlintrc.json and
.oxfmtrc.json for the new tooling. Update CI workflows and lefthook
hooks accordingly. Reformat codebase with oxfmt.
https://claude.ai/code/session_01GMkSf29p78HuMR1mbXn8He
Flatten all packages from packages/v1/* and packages/v2/* into packages/* —
every package now lives directly under the @copilotkit/ scope with no v1/v2
subdirectories.
- Move all v1 packages (react-core, react-ui, runtime, shared, etc.) from
packages/v1/* to packages/*
- Absorb v2 react code into packages/react-core/src/v2/ (exported via /v2 subpath)
- Absorb v2 agent code into packages/runtime/src/agent/ (exported via /v2 subpath)
- Move v2 packages (core, angular, demo-agents, etc.) to packages/*
- Replace all @copilotkitnext/* imports with @copilotkit/* equivalents
- Keep @copilotkitnext/angular as the sole exception (angular remains on next)
- Update CI workflows, renovate config, release scripts for flat structure
- No public API surface changes — all exports fields are preserved
Co-authored-by: Alem Tuzlak <t.zlak@hotmail.com>
Signed-off-by: Tyler Slaton <tyler@copilotkit.ai>