Commit Graph

202 Commits

Author SHA1 Message Date
tylerslaton f8cb4d2447 chore: release channels v0.9.0 2026-08-14 20:42:01 +00:00
tylerslaton a7378e70eb chore: release channels v0.8.1 2026-08-10 18:53:10 +00:00
Maximiliano Korp 4f29570bd6 fix(channels-intelligence): recover from error-only websocket failures 2026-08-10 10:15:28 -07:00
Austin Merrick b32b5539cc feat: add Inspector navigation, usage, and locked Threads (refs ENT-1173) (#6275)
## What does this PR do?

Adds the CopilotKit consumer side of ENT-1173 across Shared, Runtime,
Core, Web Inspector, and the existing Shell Docs pages.

- Defines and parses optional trusted Inspector metadata for identity,
plan, license, action, usage, and expiry. Runtime proxies it through a
private, failure-isolated route, and Core refreshes it without changing
connection state.
- Groups Inspector navigation into Threads, Agents, and Learning.
Threads renders finite, unlimited, unknown, overage, and expiring usage
states plus matching trusted plan or license actions.
- Keeps explicit `threadEndpoints` as the only authority for Thread
requests. Locked or absent capability states make no list, subscription,
detail, message, event, or state calls.
- Keeps the zero-thread video, three example Threads, detail tabs, and
guided tour in empty and locked states. General Intelligence remains the
default onboarding path; only trusted `team_self_hosted` metadata uses
self-hosted onboarding.
- Gives an active license with missing Runtime routes a short **Finish
setting up Rich Threads** state. Users can copy a safe coding-agent
prompt or open the public Runtime setup guide. The same copy control
appears in that guide, and raw Markdown/LLM views include the full
prompt.
- Keeps finite usage green below 90%, orange from 90% to the limit, and
red at or above the limit. At 90%, a trusted plan action changes from
**Manage Your Plan** to a purple **Upgrade Your Plan** without changing
its trusted URL, action kind, or telemetry contract.
- Adds a deterministic 33-state loopback lab for CopilotKit developers.
It has no production route or export, is absent from public docs and
package metadata, and is excluded from the npm tarball.

`Expiring Soon` is display-only; this PR does not enable the thread
culler. Managed Enterprise receives no manage-plan action, and Team
Self-Hosted receives no hosted plan action. Optional metadata and the
additive expiry field remain compatible across mixed producer, Runtime,
Core, and Inspector versions.

A small Channels test-only change updates fetch mocks for current
TypeScript types. It changes no Slack or Teams docs or runtime behavior.

## Related PRs and issues

- Refs
[ENT-1173](https://linear.app/copilotkit/issue/ENT-1173/ship-plg-ready-inspector-navigation-metadata-and-locked-threads)
- Producer:
[CopilotKit/Intelligence#696](https://github.com/CopilotKit/Intelligence/pull/696)

## Validation

- `@copilotkit/web-inspector`: 20 files and 372 tests passed; typecheck
and production build passed.
- Shell Docs: 57 files and 383 tests passed; lint, typecheck, and
production build passed. The build generated all 222 static pages.
- Browser checks cover the copy-prompt flow, unchanged white **Manage
Your Plan**, purple **Upgrade Your Plan**, orange 4,500/5,000 usage, and
red 5,000/5,000 usage.
- Independent review found no Critical or Important issues.
- The broader Runtime, React Native, Channels, package-quality,
compatibility, and Node-version checks from the prior pushed head remain
green.

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] I updated the relevant documentation
- [ ] "Allow edits by maintainers" is checked
2026-08-07 14:08:23 -07:00
tylerslaton 289ae4a539 chore: release channels v0.8.0 2026-08-06 09:26:34 -07:00
Tyler Slaton 0cf899095b fix(channels): take the legacy path when a dropped stream start settles as applied
The gateway settles a direct-message slack.stream.start provider failure
as applied with capabilityError and no provider reference. Parse the
start result inside the fallback try so that shape reaches the legacy
create instead of hard-failing the stream body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 15:44:06 -07:00
Alem Tuzlak 85d30dd327 fix(channels): keep managed Slack DM replies visible 2026-08-05 15:44:06 -07:00
Ben Taylor 9a86e21d48 feat(runtime): split Channel status into transport and provider legs (refs OSS-739) (#6360)
**Half 2 of 2 for OSS-739.** Gateway half ships first:
CopilotKit/Intelligence#746.

## Why

`status().overall === "online"` proved only that the runtime reached the
Gateway with a valid project API key. It said nothing about whether a
Slack/Teams app was bound to the Channel, so **a Channel with no
provider at all reported `online`** — and every version of our Channels
onboarding guidance used that value to certify end-to-end success.

`setup_required` had **no producer**. The manager set it only when the
activation engine threw `SETUP_REQUIRED`, and the engine stopped doing
that at the 2026-07-29 realtime-boundary cutover (`8f166577ce`). In
published `@copilotkit/channels-intelligence@0.7.0` the string survives
in exactly one file — a shipped *test*. The 15 doc comments describing
the state outlived the mechanism, which is why nobody noticed for a
week.

## Change

- `connectRealtimeGateway` captures the control join reply (it was
**discarded**) and exposes `providerStates()`. Phoenix's `Push.resend`
preserves `recHooks`, so the hook re-fires on every auto-rejoin — a
Channel provisioned while the runtime was disconnected is picked up with
no extra plumbing.
- The launcher and the manager's handle view delegate it as a
**getter**, not a captured snapshot, for that same reason.
- `status()` gains `detail`, reporting `transport` and `provider`
separately so a caller can assert the leg it cares about:

```ts
status() → {
  overall: "setup_required",
  channels: { support: "setup_required" },
  detail: { support: { status: "setup_required", transport: "online", provider: "not_attached" } },
}
```

`channels` keeps its shape — turning its values into objects would break
the CLI's `channels-report` and the starter channel-host — but its
values are now the fold of the two legs, which is what makes `overall`
honest.

- The stale `setup_required` doc comments are corrected, with a note not
to describe the state again without a path that can emit it.

## Back-compat: `unknown` is load-bearing

An older Gateway, a Gateway whose lookup failed, a handle without the
seam, a Channel the Gateway did not mention, an unrecognised state, and
a throwing getter **all** yield `unknown`, which keeps the
transport-derived status — exactly today's behaviour. Only a *positively
reported* absence downgrades a Channel, so no existing deployment turns
amber on upgrade.

The **41 pre-existing channel-manager tests pass unchanged**, which is
that guarantee.

## Testing

- `channel-manager-provider-leg.test.ts` — 14, incl. the regression test
that never existed ("reports setup_required for a joined Channel with no
provider attached") and one case per degradation path
- `realtime-gateway-provider-states.test.ts` — 8 parser cases
- `realtime-gateway.test.ts` — +2 proving the wiring end-to-end through
real Phoenix framing, not just the parser
- Full suites: runtime **1874/1874**, channels-intelligence **192/192**;
`check-types` and `build` clean for both packages

**I mutation-tested the fold** — neutralising it fails 5 tests including
the linchpin — so these assert behaviour rather than passing vacuously.

Worth noting: two type errors (`ChannelsHandle` in `runtime.ts`, a
session mock) were invisible to vitest, which transpiles without
typechecking. The pre-commit build gate caught them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-05 16:06:40 -05:00
Benjamin Taylor 9280e71346 refactor(channels): trim redundant provider-leg tests and fix a wrong comment
Self-review of the previous commit.

Corrects a factual error I introduced: the `SETUP_REQUIRED` note claimed such a
Channel "has no transport at all (the launcher never returned a handle)". False
for the `hasDirectAdapter` branch, which starts the developer-owned transport and
assigns a synthetic handle — so there IS a running transport there. Dropped the
wrong reasoning and shortened the note to the part that holds: the misattribution
is cosmetic on a path with no producer, and a future producer should report
through the `providerStates` seam.

Removes three tests that did not earn their place:

- "calls the seam ON the session" — redundant. `ProviderStateGateway.providerStates`
  reads `this`, so the two remaining tests already fail if the launcher ever used
  a detached reference. It died on the same mutation as the first test, for the
  same reason.
- "omits providerStates for a session without the seam" — survived the mutation
  that removes the forward, so it guarded nothing.
- the channel-level-error rejoin case — same `Push.resend` hook as the transport
  drop, so it re-proved one mechanism at ~1s extra wall-clock. Kept the drop
  case: it asserts a genuinely fresh socket, which is the "provisioned while the
  runtime was disconnected" story the design claim is about.
- "keeps the last reported states while a rejoin has not yet succeeded" — pinned
  behaviour with no observable consequence, since the transport leg dominates the
  fold while offline.

Also trims the drift-guard comment: why a guard was NOT added belongs in the PR
discussion, not permanently in source.

Re-mutation-tested after trimming: removing the forward kills both remaining seam
tests; making `providerStates` a snapshot kills the rejoin test while the other
41 gateway tests pass.

Verified: channels-intelligence 195/195, runtime 1874/1874, build + oxfmt clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 15:27:46 -05:00
Benjamin Taylor c71d9ac58b fix(channels): forward the provider seam through the exported launcher helper
Addresses review on #6360.

`startChannelsWithGatewayControl` is public so callers can compose over a
session they manage themselves, but it forwarded only `onClose` and
`onStateChange` — not `providerStates`. A handle without the provider seam makes
`ChannelManager.providerLeg` fall back to `unknown`, which keeps the
transport-derived status and reports `online` for a Channel with no provider
bound: the exact false green OSS-739 removes, still reachable through a public
export. The guard is widened too, so a session exposing only `providerStates`
is no longer dropped on the fall-through path.

Tests the reconnect claim that makes `providerStates` a getter rather than a
snapshot. Nothing exercised it: the gateway tests covered only the initial join
reply, and the manager-side rejoin test proves the manager re-reads on each
`status()` call, not that the session's value ever changes. The fake socket's
join reply can now vary per join, so a drop -> rejoin carrying a different
`channels` map asserts the refresh over real Phoenix framing — via both rejoin
paths (channel-level error on a live socket, and a full transport drop onto a
fresh socket), plus the case where a rejoin has not yet succeeded and the last
known states must persist.

Mutation-tested both: removing the forward kills 3 of 4 seam tests, and making
`providerStates` a captured snapshot kills both rejoin tests while all 3
pre-existing provider-state tests still pass — which is the gap itself.

Docs corrected against their real mechanisms:

- `attached`/`unhealthy`/`not_attached` now state the gateway's actual rule
  (adapter `status == "active"` is part of the predicate; a configured adapter in
  `error` is `unhealthy` with no failed health check), plus the best-of adapter
  fold that keeps a Slack-only Channel `attached`.
- `ready()` no longer promises it rejects on `error`. It awaits activation, so
  it can resolve while `status().overall === "error"` from an `unhealthy`
  provider. Says that instead.
- Notes the legacy `SETUP_REQUIRED` path reports a provider condition on the
  transport leg (dead, cosmetic, left rather than guessed at), and why the
  provider-state set is duplicated across the duck-typed package seam.

Verified: channels-intelligence 199/199, runtime 1874/1874, both builds clean,
oxfmt/oxlint clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 15:16:31 -05:00
Austin Merrick 9b604378aa test(channels): update fetch mocks for current types 2026-08-05 11:55:50 -07:00
tylerslaton b95a43e254 chore: release channels v0.7.3 2026-08-04 21:51:00 +00:00
Tyler Slaton 7e30957976 fix(channels): reconnect after clean gateway close 2026-08-04 13:54:36 -07:00
Mike Ryan 80370b5ecb fix(channels): preserve provider diagnostics 2026-08-04 12:33:17 -07:00
tylerslaton 1f5c70da2e chore: release channels v0.7.2 2026-08-04 18:42:33 +00:00
Alem Tuzlak 7b5cc8ccf9 fix(channels): recover from transient gateway outages (#6347)
## What changed

- Mark initial gateway HTTP 5xx and transient transport failures as
retryable.
- Retry initial managed Channel activation with exponential backoff from
1 second to a 30-second cap until it connects or the manager stops.
- Preserve retry hints from `gateway_draining` join replies and retry
initial join timeouts.
- Keep HTTP 4xx and NXDOMAIN failures terminal.
- Back off established-session outage reminders from 30 seconds to a
15-minute cap while Phoenix continues reconnecting.

## Why

The OpenTag Railway runtime saw the gateway host return HTTP 502 during
an outage. Established Phoenix sessions keep retrying, but a runtime
that starts during the outage stops after its one initial connect
window. It cannot recover when the gateway comes back unless the process
restarts. Fixed 30-second reminder logs also flood long outages.

The gateway drain work now rejects new joins with a structured retryable
response. The client must preserve that response so the runtime can
retry instead of leaving the Channel in a terminal error state.

## Companion change

CopilotKit/OpenTag#25 keeps the Railway HTTP server alive while an
initial Channel retry is pending. OpenTag must consume a CopilotKit
release containing this PR before that companion change can recover by
itself.

## Validation

- `pnpm nx run-many -t test,check-types,build -p
@copilotkit/runtime,@copilotkit/channels-intelligence`
- `pnpm nx run-many -t publint,attw -p
@copilotkit/runtime,@copilotkit/channels-intelligence`
- pre-commit tests and package checks for all affected projects
- `pnpm exec oxfmt --check` on all five changed files
- `pnpm exec oxlint` on all five changed files
- `git diff --check`
2026-08-04 17:39:00 +02:00
tylerslaton f8f9e2a721 chore: release channels v0.7.1 2026-08-04 14:48:21 +00:00
Tyler Slaton dfe728d833 fix(channels): retry gateway drain joins 2026-08-04 07:34:36 -07:00
Tyler Slaton 82eaecdfda fix(channels): retry transient gateway activation 2026-08-04 07:34:36 -07:00
Benjamin Taylor ecbf51028f feat(runtime): split Channel status into transport and provider legs (refs OSS-739)
`status().overall === "online"` proved only that the runtime reached the Gateway
with a valid project API key. It said nothing about whether a Slack/Teams app was
bound to the Channel, so a Channel with no provider at all reported `online` —
and every version of our onboarding guidance used that value to certify
end-to-end success.

`setup_required` had no producer. The manager set it only when the activation
engine threw a `SETUP_REQUIRED` error, and the engine stopped doing that at the
2026-07-29 realtime-boundary cutover. In published
@copilotkit/channels-intelligence@0.7.0 the string survives in exactly one file,
a shipped test. The 15 doc comments describing the state outlived the mechanism,
which is why nobody noticed for a week; they are corrected here, with a note not
to describe the state again without a path that can emit it.

The Gateway now reports per-Channel provider attachment on the control join
reply. This half consumes it:

- `connectRealtimeGateway` captures the join reply (it was discarded) and exposes
  `providerStates()`. Phoenix's `Push.resend` preserves `recHooks`, so the hook
  re-fires on every auto-rejoin and a Channel provisioned while the runtime was
  disconnected is picked up with no extra plumbing.
- The launcher and the manager's handle view delegate it as a GETTER, not a
  captured snapshot, for that same reason.
- `status()` gains `detail`, reporting `transport` and `provider` separately so a
  caller can assert the leg it cares about. `channels` keeps its shape — turning
  its values into objects would break the CLI's channels-report and the starter
  channel-host — but its values are now the fold of the two legs, which is what
  makes `overall` honest.

`unknown` is the load-bearing case. An older Gateway, a Gateway whose lookup
failed, a handle without the seam, a Channel the Gateway did not mention, an
unrecognised state, and a throwing getter all yield `unknown`, which keeps the
transport-derived status — exactly today's behaviour. Only a positively reported
absence downgrades a Channel, so no existing deployment turns amber on upgrade.
The 41 pre-existing channel-manager tests pass unchanged, which is that
guarantee.

Verified the new tests fail without the fix by mutating the fold, not just that
they pass with it.
2026-08-04 08:21:30 -05:00
Maximiliano Korp 8e83dfa6db fix: downgrade in-flight Slack appends 2026-08-03 15:58:22 -07:00
Maximiliano Korp e6c740fd2e fix: preserve gateway delivery compatibility 2026-08-03 15:58:22 -07:00
Maximiliano Korp 5cc22a5a1f fix(runtime): preserve gateway handoff continuity 2026-08-03 15:58:19 -07:00
tylerslaton 53bf978904 chore: release channels v0.7.0 2026-08-03 19:52:48 +00:00
Mike Ryan 979a8ee990 feat(channels-slack): support data visualization blocks 2026-08-03 11:29:12 -07:00
Tyler Slaton 7f37c3395e fix(channels-intelligence): restore inbound trigger files (#6332)
## Problem

Channel agents lose inbound files whenever the current-trigger
transcript omits attachments. The currently deployed Intelligence path
always omits those files because normalized_payload never contains their
handles.

## Why

The delivery adapter seeds the current inbound turn from the transcript,
and core then deduplicates the explicit prepared input. Files present
only on the prepared delivery therefore never reach either the
agent-history consumer or channel.getMessages during version skew.

## Fix

Restore a missing current-trigger transcript file list from the prepared
delivery inside ClaimedChannelDelivery.getTranscript(), where the result
is shared and memoized for both consumers. Existing transcript files are
preserved, so the Intelligence fix and this fallback cannot duplicate
attachments.

Either PR independently repairs the agent path. Coverage proves both an
omitted transcript and an already-correct transcript hydrate the image
for getMessages and agent seeding.
2026-08-03 10:43:41 -07:00
Tyler Slaton 65150a683b fix(channels-intelligence): repair all transcript consumers 2026-08-03 09:26:04 -07:00
Mike Ryan b88f9b7e4f feat(channels): complete native JSX contracts 2026-08-03 09:23:15 -07:00
Mike Ryan f8145b05b7 feat(channels): add native Slack and Teams JSX 2026-08-03 09:23:15 -07:00
Tyler Slaton 6c2c289d85 fix(channels-intelligence): restore prepared trigger files 2026-08-03 08:52:57 -07:00
BenTaylorDev bdf054f8bd chore: release channels v0.6.1 2026-08-03 14:06:07 +00:00
BenTaylorDev 63c15ce445 chore: release channels v0.6.0 2026-08-02 20:24:17 +00:00
Tyler Slaton 42d25ade8a fix(channels): accept namespaced app user IDs 2026-08-01 19:19:42 -04:00
Mike Ryan 17e7f33876 fix(channels): reconcile identity stack integration 2026-08-01 09:26:39 -07:00
Mike Ryan 561bf19fa6 feat(channels): add explicit identity and memory grants 2026-08-01 09:19:13 -07:00
Tyler Slaton 5ceb53799b fix(channels): complete managed provider parity 2026-08-01 11:10:28 -04:00
Tyler Slaton a0e516d403 fix(channels): delegate Teams typing to Gateway 2026-08-01 00:00:04 -04:00
Tyler Slaton aaf9d61a66 fix(channels): enforce provider delivery semantics 2026-07-31 23:49:51 -04:00
Tyler Slaton 183e83ff58 fix(channels): preserve stream cleanup errors 2026-07-31 23:12:04 -04:00
Tyler Slaton 1712be5ae9 feat(channels): complete managed Teams SDK parity 2026-07-31 23:11:06 -04:00
Tyler Slaton 871cd20f2a feat(channels): add managed welcome lifecycle 2026-07-31 18:26:41 -04:00
Tyler Slaton d247050646 feat(channels): declare Slack and Teams together 2026-07-31 18:23:28 -04:00
tylerslaton db8ebf5f09 chore: release channels v0.5.0 2026-07-31 12:46:39 -07:00
Mike Ryan eb6c8df0ad fix(channels): start Slack streams with first text 2026-07-31 10:26:41 -07:00
Mike Ryan 29d2721775 fix(channels): contain terminal delivery failures 2026-07-30 23:20:48 -07:00
Mike Ryan 552268d47d fix: keep participant metadata out of assistant history 2026-07-30 22:50:27 -07:00
Mike Ryan 81d192ad22 fix(channels): suppress exact provider self output 2026-07-30 19:51:08 -07:00
Mike Ryan 7259bae438 feat(channels): bound pending delivery capacity 2026-07-30 19:51:08 -07:00
Mike Ryan 9dc343ddf8 feat(channels): confirm managed file delivery 2026-07-30 19:51:08 -07:00
Mike Ryan ddfa6f3453 feat(channels): supersede pre-output runs 2026-07-30 19:51:08 -07:00