Commit Graph

15742 Commits

Author SHA1 Message Date
Ben Taylor 0d0ea901e9 chore: release angular v0.5.0 (#6828)
## Release angular v0.5.0

**Scope:** `angular` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `angular` packages to `0.5.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 `angular` packages to npm at version `0.5.0`
   - Creates git tag `angular/v0.5.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.
angular/v0.5.0
2026-09-01 13:31:01 -05:00
Maxim c9d1dd95d0 feat(channels-core): forward the turn's actor to the agent (#6826)
## Why

An agent has no trustworthy way to learn who is speaking.

Today the actor reaches the agent in exactly one place: a context entry,
which
is prose in the prompt ("Requesting slack user Ada (slack id U…)").
Nothing on
the agent side parses it. So an agent that wants to act *as* that person
— read
their calendar, open their mailbox, use a third-party account connected
under
their name — has to read that sentence and copy the id into a tool
argument.
That makes the model the source of an identity, and message text is free
to
influence it.

This adds a structured, trusted path for that fact.

## What

The actor now travels in `forwardedProps.channelActor` on every agent
run of a
turn:

```ts
{ id: "U0AE1TJ9BV3", kind: "human", platform: "slack", name: "Ada" }
```

- The `Thread` supplies it from its own ingress event, so a caller
cannot pass
  an identity of its own choosing.
- Resumes carry it too, and a resume's actor is whoever pressed the
button —
not necessarily whoever started the turn. A card clicked twenty minutes
later
  attributes to the clicker.
- `id` is provider-scoped, so `platform` travels with it. Anything keyed
per
person keys on both; two platforms can hand out the same string for
different
  people.
- A turn that named nobody carries no `channelActor` key at all, rather
than one
holding an empty string. Ingress reports `id: ""` in that case, and an
agent
should not have to string-compare a sentinel to tell "nobody" from
"somebody".
- `kind` and the display fields are provider-reported metadata: useful
for
  addressing someone, useless for deciding what they may do.

No credential travels here. This is identity only — who is asking. A
backend
holding that person's connected accounts (Composio, or anything
equivalent)
keys them by user id server-side, so the agent says "act as this person"
and
never handles a token.

## Why not a request header

Headers are the obvious first idea, and `HttpAgent` already accepts them
— that
is how a deployment-wide `Authorization` gets to a self-hosted agent
today.

They are the wrong granularity. Headers are fixed when the agent
connection is
built, and that happens once per conversation: the factory receives a
thread id
and nothing else. A header would therefore name the conversation, not
whoever
just spoke — wrong for most turns in any thread with more than one
participant.
Making it per-person would mean rebuilding the connection every turn,
and
nothing exposes that object mid-turn to mutate it either.

`forwardedProps` is already per-run, which is exactly the granularity
"who is
asking" needs.

## Why not the message author

AG-UI user messages carry an optional `name`, and putting the actor
there would
have been a smaller change — it already round-trips through the
langgraph
adapter in both directions.

It is the wrong field. `name` is part of the message list handed to a
model
provider, and providers validate it. OpenAI accepts only `[A-Za-z0-9_-]`
in a
message author. Teams actor ids contain a colon, and adapters bound an
actor id
at 512 characters and nothing else — so an id that happens to satisfy
one
provider today is not a contract, and it can tighten under us at any
time.

Sanitizing the id to fit is worse than failing: a mangled id still reads
as an
identity, and the agent then answers confidently as the wrong person.

`forwardedProps` never enters the conversation. No provider inspects it,
and the
value stays exactly what the adapter reported.

The message author still has a legitimate, separate use — letting a
model see
who said what in a multi-person thread. That one is cosmetic, so a
mangled
display name there costs nothing. Different change.

## Nothing reads it yet

This is deliberately the enabling half. The consumer is an OpenTag
change that
moves its Composio integration out of the channel and into the agent,
keying
each person's connected accounts on `platform` + `id`. That work is
blocked on
this field existing, which is why it lands first and alone.

## Verification

- 8 new tests in `channels-core`: normal run, resume, absent actor, and
an id
containing a character a model provider would reject surviving verbatim.
- `nx run channels-core:check-types` clean.
- `nx run-many -t test -p channels-core channels-slack
channels-intelligence channels` — all green except two pre-existing
failures in `sanitize-agent-events.test.ts`, confirmed failing on the
base commit (`ddae645054`) before this branch.
- Mutation-checked: forcing the identity helper to return `{}` fails 3
of the 4 new run-loop tests.
- Confirmed the managed delivery path populates a real platform user id
(`externalUserId`), so this is live on the path OpenTag actually uses
rather than only on directly-connected adapters.
2026-09-01 20:29:59 +02:00
Maxim 9fef16090e Merge branch 'main' into feat/channels-message-author 2026-09-01 20:29:37 +02:00
Martha Kelly Schumann 6dab592b30 docs(ag-ui): fix applications quickstart route (#6829)
## Summary

- sync the AG-UI applications quickstart with the corrected root route
- add coverage that rejects the stale `/copilotkit` URL

## Testing

- `npm test -- src/lib/__tests__/ag-ui-content-links.test.ts`
- `npm run typecheck`
- `git diff --check origin/main...HEAD`

Linear: FAC-123
2026-09-01 11:29:03 -07:00
Maxim a875e2b901 Merge branch 'main' into feat/channels-message-author 2026-09-01 20:13:40 +02:00
Martha Kelly Schumann f0fd5f045c docs: clarify LangGraph configuration channels (#6805)
## Summary
- replace the unsupported browser-to-RunnableConfig example with
supported configuration channels
- route model-visible preferences through frontend-correct Agent Config
APIs and framework-scoped links
- document trusted Python and TypeScript backend execution configuration
- add rendered docs coverage across React, Angular, Python, and
TypeScript
- add repeated-request runtime coverage for request-local authorization
without raw token output

## Testing
- `npm --prefix showcase/shell-docs test --
src/lib/__tests__/langgraph-configurable-channels.test.ts`
- `npm --prefix showcase/shell-docs run typecheck`
- `pnpm --filter @copilotkit/runtime exec vitest run
src/v2/runtime/__tests__/handle-run.test.ts`
- `pnpm --filter @copilotkit/runtime check-types`
- `pnpm exec nx run @copilotkit/runtime:build`

Linear: FAC-121
2026-09-01 11:11:23 -07:00
copilotkit-qa-bot[bot] 84dd92485b docs: sync corrected AG-UI quickstart route 2026-09-01 11:07:34 -07:00
BenTaylorDev 948f64f4c5 chore: release angular v0.5.0 2026-09-01 17:59:58 +00:00
Ben Taylor 03a649871d feat(react-core): migrate MCP Apps host to @modelcontextprotocol/ext-apps (AppBridge) (#6707)
## What

Migrate the MCP Apps host (`MCPAppsActivityRenderer`, react-core) from a
hand-rolled protocol to the `@modelcontextprotocol/ext-apps` host
library (`AppBridge` + `PostMessageTransport`).

Today the renderer reimplements the whole app↔host protocol by hand:
method names as string literals, `PROTOCOL_VERSION = "2025-06-18"`
hardcoded, hand-written types, a manual `postMessage` + `switch` router,
and a custom sandbox proxy. There is no compile-time tie to the spec,
which is the root cause of recurring drift (e.g. widgets sending
`ui/notifications/size-change` vs the host/spec `size-changed`, and the
stale protocol version).

## Changes

- Add `@modelcontextprotocol/ext-apps` (^1.7.5) to `react-core`.
`@modelcontextprotocol/sdk` (^1.29.0) is a `peerDependency` (mirroring
how ext-apps declares it) plus a `devDependency`, not a direct
dependency: react-core does not use the SDK directly (type import only),
the runtime use is inside ext-apps.
- Per widget instance, connect an `AppBridge` over a
`PostMessageTransport` to the sandboxed iframe (the existing sandbox
proxy is kept as the transport relay). The bridge owns:
- `ui/initialize` + capability/protocol-version negotiation — now
advertises `LATEST_PROTOCOL_VERSION` (`2026-01-26`).
- host context (`setHostContext`), tool input/result (`sendToolInput` /
`sendToolResult`), and the sandbox handshake (`onsandboxready` →
`sendSandboxResourceReady`).
- App→host requests/notifications are mapped to the existing CopilotKit
behavior via bridge handlers: `open-link` (window.open), `tools/call`
(runAgent proxy), `size-changed` (iframe sizing), `initialized`,
logging. The runAgent queue and the issue #5819 thread-capture semantics
are preserved.
- Remove the hand-rolled `PROTOCOL_VERSION`, the send/response helpers,
and the JSON-RPC `switch` now owned by the bridge.

### ui/message: CopilotKit extensions preserved

The ext-apps `ui/message` schema only allows `role: "user"` and has no
`followUp`, but CopilotKit intentionally extends `ui/message` with
`role` ("user" | "assistant") and `followUp` (documented behavior,
dedicated tests). To stay behavior-preserving for widgets in the wild,
`ui/message` uses a custom request handler instead of the bridge's
strict `onmessage`:

- Extensions are read from `params._meta.copilotkit` first (the
forward-looking, spec-friendly channel), then from the legacy top-level
`params.role` / `params.followUp` (kept for backward compatibility,
slated for deprecation).

### Behavior changes to note

- `ui/open-link` **without** a `url` now fails with JSON-RPC `-32603`
(InternalError) instead of the previous hand-rolled `-32602`
(InvalidParams). The bridge validates the request against the spec
schema ahead of the handler, so a missing `url` surfaces as the bridge's
validation error rather than a params error we raise ourselves. Widgets
that read JSON-RPC error codes for this case will see the new code. A
well-formed `ui/open-link` is unaffected.
- `ui/open-link` now enforces a scheme **denylist** before
`window.open`: `javascript:`, `data:`, `vbscript:`, `blob:`, and `file:`
are refused (they can execute script / render attacker HTML). Everything
else is allowed, including `https:` universal links and custom-scheme
deep links (`myapp:`, `whatsapp:`, ...), which hand off to an OS handler
rather than executing in the page. A denylist on purpose: an allowlist
could never enumerate app-defined deep-link schemes, and it matches the
Anthropic Software Directory policy (https origins + owned custom URI
schemes).
- `ui/initialize` is now validated against the spec schema by the
bridge. A widget that omits the required fields (e.g. `appCapabilities`,
or empty/absent params) fails initialize with JSON-RPC `-32603` instead
of the lenient response the hand-rolled host gave; a compliant widget
(including any built with the ext-apps `App` class, which always sends
`appInfo` + `appCapabilities` + `protocolVersion`) is unaffected.
- Protocol-version negotiation: the host now advertises the **MCP Apps**
protocol version `2026-01-26` (`LATEST_PROTOCOL_VERSION`) and returns it
rather than echoing whatever a widget sends. Note this is the MCP
**Apps** protocol version, which is independent from the base MCP
protocol version — the old hand-rolled host confusingly hardcoded
`2025-06-18`, which is a base-MCP-protocol version, not an MCP Apps one.
Covered both ways by new e2e tests.

### Review round (addressing @BenTaylorDev)

- **Lazy-load the bridge.** `AppBridge` / `PostMessageTransport` are now
a dynamic `import()` inside Effect 1 (type-only import at the top), so a
`<CopilotKit>` app only pays the ~40-50 kB gzipped ext-apps cost when it
actually renders an MCP App. The built output has no static ext-apps
import, only `import("@modelcontextprotocol/ext-apps/app-bridge")`.
- **`@modelcontextprotocol/sdk` is no longer a direct dependency** (see
Changes above): optional `peerDependency` + `devDependency`.
- **zod peer floor raised to `>=3.25`.** The ext-apps/sdk schema slice
imports `zod/v4` and `zod/v4-mini`, which only exist in zod `>= 3.25`;
the old `>=3.0.0` peer let a consumer on zod 3.24 hit an unresolvable
import at build time.
- **Deterministic host context.** It is now seeded at `AppBridge`
construction (the `hostContext` option) rather than via `setHostContext`
after `connect`, so it is in place when the widget's `ui/initialize` is
handled instead of winning that race by luck. This is the seam #6689
needs to advertise `displayMode` / `availableDisplayModes` at
initialize.
- Restored the full cross-frontend testid surface-contract comment, and
split the `oncalltool` guard so "no server hash" and "no agent" report
distinctly.

## Testing

- `react-core` type-check green; MCP Apps e2e green (34 tests), incl.
the `_meta.copilotkit` extension-channel test, `ui/open-link` scheme
allow/deny (deep link vs `javascript:`), and `ui/initialize` negotiation
(well-formed success, missing-fields `-32603`, version returned).
- One e2e assertion updated: `ui/open-link` without `url` is now a
schema-validation error surfaced by the bridge (JSON-RPC `-32603`)
rather than the previous hand-rolled `-32602` (see "Behavior changes to
note" above).
- Validated end-to-end in a browser against a live MCP server + LLM: the
widget renders, `ui/initialize` negotiates `2026-01-26`, tool-result is
delivered, and `ui/message` works; console clean.

## Scope / follow-ups

- React-first (pilot). Vue and Angular ship their own hand-rolled
renderers with the same drift; a shared, framework-agnostic extraction
consumed by all three is the natural follow-up.
- Display-mode / update-model-context / theme host-context work layers
on top of this bridge.

This PR is intentionally not adding more features (like
requestDisplayMode from #6689 ), if we validate the approach to use
ext-app instead of reimplementing the ext-app specs, I will continue
ext-apps support to align as much as possible.



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Enhanced MCP app integration with streamlined initialization and
secure message/tool handling (including logging, sizing, and sandbox
delivery).
* Preserved role and follow-up behavior from app messages, with support
for safe custom deep links.
* Improved link handling with stricter URL validation and safer scheme
rules.
* **Bug Fixes**
* Prevented unsafe/malformed links and rejected script/HTML-executing
schemes.
  * Dropped queued follow-ups when the active conversation changes.
* **Dependency Updates**
* Updated MCP runtime/dev dependencies and tightened `zod` peer
dependency requirements.
* **Tests**
* Expanded e2e coverage for initialization negotiation, schema
validation errors, metadata-driven behavior, and link safety.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-01 11:51:36 -05:00
Maxim 0674200c33 chore(channels-core): drop the changeset this repo no longer reads 2026-09-01 18:49:59 +02:00
yannj-fr 8e68a624a0 chore(release): regenerate public API manifest for react-core peer deps
react-core's peerDependencies changed in this PR (added @modelcontextprotocol/sdk
and raised the zod floor to >=3.25), but the committed public API manifest still
reflected the old declarations, failing scripts/release/lib/public-api-manifest.test.ts.
Regenerate the manifest so it matches package.json.
2026-09-01 18:11:03 +02:00
Yann Jouanin 0558c16af5 Merge branch 'main' into feat/migrate-ext-app-package 2026-09-01 17:44:45 +02:00
copilotkit-qa-bot[bot] f236329630 test(runtime): harden request auth isolation coverage 2026-09-01 08:39:00 -07:00
copilotkit-qa-bot[bot] 45d8603ee2 Merge remote-tracking branch 'origin/main' into codex/fac-121-configurable-channels 2026-09-01 08:35:55 -07:00
Maxim 34f0728ba7 feat(channels-intelligence): post a Slack message only the turn recipient can see (closes OSS-988) (#6719)
The managed adapter declared `supportsEphemeral: false` and implemented
no private post, so `Thread.postEphemeral` had nothing behind it on the
managed path.

That is a real hole rather than a missing nicety. An app that needs one
message for one person has to abandon managed delivery for it: the one
that found this ended up holding its own Slack tokens and running a
direct adapter, purely so a Composio connect link could reach a single
person. A connect link binds whoever opens it to the identity it was
minted for, so posting it in a channel lets a colleague attach their own
account to somebody else's identity.

`postEphemeral` now emits the `slack.message.ephemeral` delivery effect,
and the capability says true.

## Who receives it is not the caller's choice

The delivery boundary posts to the turn's own fenced recipient, and
rejects an effect whose asserted user disagrees with it. So a request
naming somebody else is refused here rather than sent — the boundary
would refuse it anyway, and failing locally can say which user was
expected. A turn Intelligence could not attribute to a person is refused
the same way.

Teams returns `null`, the contract's "native unsupported" answer, so a
caller's DM fallback still engages rather than a private message quietly
becoming a public one.

No `MessageRef` comes back: Slack answers an ephemeral post with
`message_ts`, which no API accepts, so there is nothing to update or
delete afterwards. `usedFallback` is always false, since the managed
path has no DM route of its own.

## Verification

`packages/channels-intelligence`: 218 tests pass, four of them new — the
happy path asserts the exact effect payload, and the rest cover a
mismatched recipient, an unattributed turn, and Teams declining.

## Sequencing

Needs `slack.message.ephemeral` on the Intelligence side —
CopilotKit/Intelligence#1008 — which must merge first. Until it does,
the effect is rejected at the boundary rather than silently dropped, so
nothing is delivered wrongly in the meantime.

Once both are out, the app carrying the direct-adapter workaround can
drop its Slack tokens and go back to managed delivery.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for sending ephemeral Slack messages visible only to the
intended recipient.
* Messages follow standard Slack formatting and do not create persistent
message references.
* **Bug Fixes**
* Prevented delivery when recipients are missing, anonymous, or do not
match the conversation recipient.
* Prevented unsupported ephemeral delivery attempts on Microsoft Teams
from triggering transport actions.
* Added validation to ensure ephemeral message content meets delivery
requirements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-01 17:23:42 +02:00
Maxim ddde68d5cf Merge branch 'main' into feat/managed-ephemeral-post 2026-09-01 17:09:46 +02:00
copilotkit-qa-bot[bot] 15f80f880e docs: clarify browser-controlled LangGraph config 2026-09-01 07:49:58 -07:00
copilotkit-qa-bot[bot] 9c5a3ead46 Merge remote-tracking branch 'origin/main' into codex/fac-121-configurable-channels 2026-09-01 07:47:35 -07:00
renovate[bot] c0d9d14195 chore(deps): update reviewdog/action-actionlint action to v1.73.3 (#6820)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[reviewdog/action-actionlint](https://redirect.github.com/reviewdog/action-actionlint)
| action | patch | `v1.73.2` → `v1.73.3` |

---

### Release Notes

<details>
<summary>reviewdog/action-actionlint
(reviewdog/action-actionlint)</summary>

###
[`v1.73.3`](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.73.2...v1.73.3)

[Compare
Source](https://redirect.github.com/reviewdog/action-actionlint/compare/v1.73.2...v1.73.3)

</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:eyJjcmVhdGVkSW5WZXIiOiI0NC40OS4wIiwidXBkYXRlZEluVmVyIjoiNDQuNDkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
2026-09-01 14:22:42 +00:00
Maxim e17d6230d5 chore(channels-core): add changeset for the forwarded channel actor 2026-09-01 16:22:08 +02:00
Maxim f698a0e373 feat(channels-core): forward the turn's actor to the agent
An agent had no trustworthy way to learn who was speaking. The actor reaches
it only inside a context entry — prose in the prompt — so an agent that needs
to act as that person has to read the sentence and copy the id into a tool
argument, which makes the model the source of an identity and lets message
text influence whose account gets used.

The actor now travels in `forwardedProps.channelActor` on every run of a turn,
including a resume, where a resume carries whoever pressed the button rather
than whoever started the turn. The Thread supplies it from its own ingress, so
a caller cannot pass an identity of its own choosing.

AG-UI messages carry an optional author and putting it there would have been
the smaller change, but that field is part of the message list handed to a
model provider and providers validate it: OpenAI accepts only `[A-Za-z0-9_-]`
in a message author, Teams actor ids contain a colon, and adapters bound an
actor id at 512 characters and nothing else. Sanitizing an id to fit is worse
than failing, because a mangled id still reads as an identity and answers as
the wrong person. `forwardedProps` never enters the conversation, so no
provider inspects it and the value stays what the adapter reported.

`id` is provider-scoped, so `platform` travels with it — a consumer keying
anything per person keys on both. A turn that named nobody carries no
`channelActor` key at all rather than one holding an empty string.
2026-09-01 16:17:45 +02:00
Maxim c76697a5db fix(channels-intelligence): refuse an ephemeral post that names no recipient
An empty user id passed the truthiness guard, so the post went out to this
turn's own recipient and reported success for a recipient the caller never
identified. Comparing the requested id with the recipient directly refuses it
alongside a request naming somebody else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 16:06:21 +02:00
yannj-fr 82c2ffbfc6 test(react-core): fix stale allowlist wording in the open-link scheme test
The comment described an http/https/mailto/tel allowlist, but ui/open-link uses a
denylist (javascript:/data:/vbscript:/blob:/file:). Align the comment with the
actual contract so it does not mislead a future change to the scheme policy.
2026-09-01 16:03:14 +02:00
Yann Jouanin b12ba3e3a5 Merge branch 'main' into feat/migrate-ext-app-package 2026-09-01 15:40:55 +02:00
yannj-fr 2544f1ff4c test(react-core): cover ui/initialize negotiation + address round-three nits
- Add e2e tests pinning the ui/initialize contract (the compile-time tie to the
  spec): a well-formed initialize returns the host context and the negotiated MCP
  Apps protocol version; an initialize missing required fields (e.g.
  appCapabilities) is rejected with -32603; a widget sending a different
  protocol-version string gets the host's MCP Apps version back, not its own
  echoed. (2025-06-18 is a base-MCP-protocol version, independent from the MCP
  Apps protocol 2026-01-26; it is what the old hand-rolled host hardcoded.)
- Nit: load the bridge via `import(...).catch(rethrow)` with inferred types
  instead of `typeof import(...)` annotations, removing three
  consistent-type-imports warnings.
- Nit: restore the "ui/message: No agent available" warning log on the no-agent
  path, for parity with the hand-rolled host and the oncalltool guard.
2026-09-01 15:40:09 +02:00
renovate[bot] 0dfd6be6d9 chore(deps): update reviewdog/action-actionlint action to v1.73.3 2026-09-01 13:32:42 +00:00
Alem Tuzlak 2eaf683a87 docs hero: lead with the onboarding prompt (OSS-1072) (#6815)
Closes OSS-1072.

## What changed

The docs hero offered three competing entry points: a Quickstart picker,
a CLI command menu behind "Start using agents", and — below the fold —
the onboarding prompt a developer hands to their coding agent. The
prompt is the path we want people on, so it moves into the hero:

- **Primary, left:** `Copy onboarding prompt` — mints a fresh
12-character run id per click and copies the canonical prompt from
`lib/intelligence-onboarding-prompt.ts`
- **Secondary, right:** Quickstart, stepped down to the bordered
treatment
- **Removed:** the CLI command menu, and with it `npx copilotkit@latest
create` and the "Build with agents" link

The `Build agents that get smarter with every use.` section below the
hero is unchanged.

## Scope — this also touches the framework landing pages

`HeroStartActions` is shared verbatim by the home hero and the framework
landing heroes, and we kept it that way rather than forking it. So the
home page and most partner landings get the same row.

Measured against the running app, of the 21 registry integrations: 2
have no landing page (`langroid`, `spring-ai` 404), `built-in-agent`
redirects to `/` (its landing *is* the home page), and
`crewai-conversational-flows` redirects into a content page. Of the 17
remaining landing surfaces, **15 now render the prompt button**. The 2
that do not are `claude-sdk-python` and `claude-sdk-typescript`: their
init command is `npx copilotkit@latest init --framework claude-sdk-*`
rather than the generic one, so they take a different branch that keeps
its own command chip. `QuickstartLinkButton` gained a `variant` prop
defaulting to `primary` so those two keep their only hero button looking
unchanged.

That means this PR delivers most of OSS-1073's landing-page work as a
side effect. The two remaining pages are handled in #6816, which is
stacked on this branch.

## Decisions worth flagging to reviewers

**The prompt is identical on every surface.** OSS-1072 and its siblings
ask for an outcome "specific to the user's selected options in the top
left". That isn't possible as written: `copilotkit onboard start` takes
only `--run` and `--coding-agent`, and the onboarding graph inspects the
repository and picks its own path. A framework-scoped prompt would be a
promise the CLI does not keep. The prompt text is also required to stay
byte-identical to Intelligence's `intelligence-home.tsx` and the
Inspector, so it cannot carry a framework hint either. Giving the CLI a
real `--framework` option is a separate change in the Intelligence repo.

**Telemetry.** Both placements send the existing
`docs.intelligence_onboarding_prompt_copied` event with the same
property names, under new `surface` values (`docs_landing_hero`,
`docs_framework_hero`). One gap: the in-page section also sends
`feature: "learning" | "threads"`, which the hero button has no
equivalent for and therefore omits — funnel queries filtering on
`feature` will not see hero copies. Removing the CLI menu also ends
`hero_command_copied` (750 copies / 409 people in the last 90 days). No
saved insight referenced it. For contrast, the prompt it replaces was
copied 46 times by 40 people in the same window, across the landing page
and all 16 quickstarts — the bet here is that placement was the reason.

**`cliFrameworkForDocsSlug`** in `framework-overview.tsx` now has no
production caller (only its own test). Left in place because it holds
the docs-slug to CLI-framework mapping that a future `--framework`
option would need.

## Verification

- `npm run typecheck`, `npm run lint`, `npm run build` clean
- 512 tests pass; 19 new or reworked across the three touched test files
- Verified in a browser on the dev server: the copied text is the
canonical prompt (329 chars) with a run id matching the CLI's
`/^[A-Za-z0-9_-]{12}$/`, in light and dark mode, and stacked at 375px
- Clipboard write confirmed by hand in a normal browser (the automated
browser blocks `navigator.clipboard.writeText`, so the content assertion
above was made through a spy)
- The button reserves the width of its longest label so switching to
`Copied` no longer shunts Quickstart sideways
- Three test files fail on this branch — `public-assets`,
`angular-docs-content`, `llm-text`. All three fail identically on
unmodified `main` in the same environment; `public-assets` is unfetched
Git LFS pointers.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added a “Copy onboarding prompt” action to documentation landing pages
and framework overview pages.
* Users can copy a personalized onboarding prompt and receive clear
copied or error feedback.
  * Added accessible status announcements for copy results.

* **Improvements**
* Simplified hero actions by replacing the CLI command menu with the
onboarding prompt and Quickstart actions.
* Updated Quickstart styling to use a secondary treatment with accent
hover states.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-01 15:31:46 +02:00
Lukas Moschitz 1a5af3890c Merge remote-tracking branch 'origin/main' into lukas/oss-1072-overview-incorporate-agent-onboarding-prominently 2026-09-01 15:10:08 +02:00
Alem Tuzlak 88745255e8 docs: serve the Intelligence docs at /intelligence instead of /premium (#6818)
Closes OSS-1078.

## Why

The product is Intelligence; the docs served it under `/premium/`,
including a `premium/` folder inside twelve integrations. Readers and
coding agents both landed on a URL naming a tier that no longer exists.

## What changed

**Content.** The folder is now `intelligence/` — at the root, in the
twelve integration trees, and in the shared snippets — and every inbound
link is rewritten. Page slugs are deliberately unchanged, so the
redirect surface is a pure prefix rename.

Two cleanups fell out of it: `premium: true` is gone from fourteen pages
(nothing reads that frontmatter key), and the last piece of tier prose,
a `Premium UI capabilities` table cell, is now `Platform-gated UI
capabilities`.

**Redirects.** `/premium/*` is indexed, so every old path 301s to its
new home — at the root and under all 22 canonical plus 14 legacy
framework slugs. A wildcard covers the tree, including future pages and
the `.md`/`.mdx` LLM variants; exact entries cover the bare folder URLs,
which no wildcard prefix matches. Entries that pointed *into* the tree
are repointed (retired observability pages, the folder index, four
`next.config` destinations); sources are untouched, since a source
describes a URL that must keep resolving.

The shell host and the harness probe carry their own copies of the table
— the harness header requires them to stay in sync or the decommission
report reports phantom zero-hit entries — so both are updated too.

## Verification

Measured against the running dev server, not inferred:

- every legacy `/premium/*` path resolves `200`, one hop, including all
22 framework slugs and the `.mdx` variants
- the 7 root pages and the per-framework variants serve `200`
- sitemap, search index and `llms.txt` contain zero `premium` entries
(177 / 949 / 49 `intelligence` entries)
- `tsc --noEmit` and `next build` (226 pages) both exit 0
- no browser console errors

`npm run test` is 504 passed / 6 failed. Those 6 also fail on
`origin/main` in an identical environment — three missing PNG assets,
two Angular content assertions, one Mastra example — so this change adds
no failures.

## Deliberately not in scope

Six analytics surface identifiers still read `docs_premium_*`. Renaming
them would silently break the PostHog dashboards that key on them. They
are internal event names rather than docs content, so they want their
own change with a look at the dashboards first.

`/intelligence/intelligence-platform` reads repetitively. Renaming page
slugs would widen both this diff and the redirect table well past the
prefix rename this ticket asks for.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added dedicated Intelligence documentation sections and guides,
including overviews, self-hosting, headless UI, Inspector, and thread
architecture content.
* Added updated integration documentation for multiple agent frameworks.

* **Bug Fixes**
* Updated redirects so existing Premium documentation links continue to
reach the corresponding Intelligence pages.
* Corrected navigation, sitemap, and cross-reference links throughout
the documentation.

* **Tests**
* Updated documentation, navigation, SEO redirect, and sitemap checks
for the new Intelligence paths.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-01 15:05:04 +02:00
Lukas Moschitz 8bad102f16 test(showcase/harness): refresh the decommission report snapshots
The report is rendered from the live redirect table, and these two
fixtures pin it byte-for-byte. Adding INTEL-observability-root and
P7-intelligence to the shell table moves the entry count from 388 to
390 and lists both new ids among the zero-hit candidates.

Regenerated with the same inputs the test uses, so the diff is only the
two counters and the two new id lines.

Refs OSS-1078
2026-09-01 14:55:05 +02:00
Lukas Moschitz d776097afa test(showcase/shell-docs): expect the renamed Intelligence paths
Eight suites assert on the old paths — sitemap URLs, file existence,
loadDoc slugs and the Angular canonical-slug mapping. In the redirect
suite only the destinations move; the /premium/observability sources
stay, since a redirect source describes a URL that must keep resolving.

Refs OSS-1078
2026-09-01 14:00:51 +02:00
Lukas Moschitz 91ee5aa764 fix(showcase): 301 the legacy premium URLs onto the renamed Intelligence tree
/premium/* is an indexed URL surface, so the folder rename needs a
redirect for every old path — at the root and under each of the 22
canonical and 14 legacy framework slugs. A wildcard covers the tree
(including future pages and the .md/.mdx LLM variants); exact entries
cover the bare folder URLs, which no wildcard prefix can match.

Existing entries that pointed INTO the tree are repointed: the retired
observability pages, the premium folder index, and four next.config
destinations. Sources are left untouched — they describe URLs that must
keep resolving.

Two entries in next.config keep the built-in-agent surface at one hop:
its generic prefix-stripping catch-all runs before the middleware and
would otherwise hand the middleware a /premium/ path to rename in a
second hop.

The shell host and the harness probe carry their own copies of the
table, and the harness header requires them to stay in sync or the
decommission report surfaces phantom zero-hit entries. Both updated.

Refs OSS-1078
2026-09-01 14:00:37 +02:00
Lukas Moschitz eadc026341 fix(showcase/shell-docs): point the docs renderer at the renamed Intelligence tree
Three maps key off the content path or the URL slug: the shared-snippet
registries in docs-render and mdx-registry, the slug-to-component maps,
and the Angular canonical-slug map. All of them still named premium, so
after the folder rename the shared Overview, SelfHosting, Inspector and
HeadlessUI snippets would resolve to a path that no longer exists.

Refs OSS-1078
2026-09-01 14:00:21 +02:00
Lukas Moschitz e250256789 docs(showcase/shell-docs): move the Intelligence docs tree off the premium path
The product is called Intelligence, but the docs served it under
/premium/ — including a per-integration premium/ folder in twelve
integrations. Readers and coding agents both hit a URL naming a tier
that no longer exists.

Renames the folder to intelligence/ at the root, in the twelve
integration trees, and in the shared snippets, and rewrites every
inbound link. Page slugs are deliberately unchanged so the redirect
surface stays a pure prefix rename.

Also drops the premium: true frontmatter key from fourteen pages: no
code reads it, so it was dead. The one remaining piece of tier prose,
a "Premium UI capabilities" table cell, becomes "Platform-gated UI
capabilities".

Analytics surface identifiers (docs_premium_*) are left verbatim —
renaming them would silently break the PostHog dashboards that read
them. They are internal event names, not docs content, and belong in
their own change.

Refs OSS-1078
2026-09-01 14:00:03 +02:00
Lukas Moschitz 5cd54dbc90 fix(docs): match the hero prompt button to the ticket wording (refs OSS-1072)
The label is now "Copy onboarding prompt", the wording OSS-1072 asks for, and
the hint line under the action row is gone — the label already names what gets
copied, so the second line only repeated it. With nothing below the row,
HeroStartActions collapses to the row itself instead of wrapping it.
2026-09-01 13:05:37 +02:00
Lukas Moschitz 8bfcfc02ce feat(docs): lead the hero with the coding-agent prompt (refs OSS-1072)
The docs hero offered three competing entry points: a Quickstart picker, a
CLI command menu, and — buried below the fold — the onboarding prompt a
developer hands to their coding agent. The prompt is the path we want people
on, so it moves into the hero and takes the accent, Quickstart steps down to
the bordered treatment beside it, and the CLI command menu goes away with the
`create` command and the "Build with agents" link it carried. A muted hint
line names where the copied prompt is meant to go, which the removed menu
used to make obvious by showing its command inline.

The prompt is identical on every surface: the CLI's onboarding graph inspects
the repository and picks its own path, so a framework-scoped variant would be
a promise the CLI does not keep. HeroStartActions stays shared verbatim, so
the eleven framework landing pages using it get the same row. The four
frameworks with bespoke init commands render a different branch and are
untouched.

QuickstartLinkButton gains a `variant` prop defaulting to primary, so those
bespoke landing pages keep their only hero button looking unchanged.
2026-09-01 12:53:19 +02:00
lukasmoschitz 5195118345 showcase: rename byoc-* QA docs to declarative-* in 7 integrations (#6800)
## Why

`showcase/scripts/validate-parity.ts` keys spec and QA filenames to the
demo id. Seven integrations still carried the pre-rename `byoc-*` names
for the hashbrown / json-render demos, so the validator emitted spurious
`demo 'declarative-hashbrown' has no qa/declarative-hashbrown.md` style
warnings.

**454 → 446 warnings, still 21/21 pass.**

## What changed

**QA docs (14 files, all 7 integrations)** — renamed `qa/byoc-*.md` →
`qa/declarative-*.md` and reconciled against the `langgraph-python`
north star. Test Steps and Expected Results are now identical per demo
across every integration; genuinely per-integration facts (agent mount
path, env var, prompt module, preserved regression guards) live in an
`Integration notes` section. Every fact was verified against source —
pill labels, `data-testid`s, header text, package pins, API route →
`AGENT_URL` mappings — rather than carried over from the old doc.

**E2E specs (10 files, 5 integrations) — deleted, not renamed.** Those
integrations already ship `declarative-hashbrown.spec.ts` /
`declarative-json-render.spec.ts` byte-identical to the north star (md5
`57eee13d…` / `638e2ac4…`). The `byoc-*` copies point at `/demos/byoc-*`
routes that no longer exist and assert little beyond "page loads", so
renaming them would have clobbered the good specs. Spec counts stay
above demo count in all five packages, so no under-coverage warning
appears.

Python backend modules keep their `byoc_` prefix
(`byoc_hashbrown_agent.py`, `byoc_json_render_agent.py`) — the north
star uses those names too and integration `manifest.yaml` files
reference them under `highlight:`.

`claude-sdk-python` is deliberately untouched (handled in OSS-578 /
#6235).

## Found along the way, NOT fixed here

1. **`declarative-json-render` is broken in both crewai packages.** The
demo page (a north-star copy) mounts
`runtimeUrl="/api/copilotkit-declarative-json-render"`, but those
packages only ship `src/app/api/copilotkit-byoc-json-render/route.ts`,
and `next.config.ts` has no covering rewrite — the runtime URL 404s. The
rename was only half applied: page renamed, API route not. Documented as
a known break in the affected QA docs; fixing it is a runtime change, so
it wants its own PR.
2. **`langgraph-python/qa/declarative-json-render.md` still has the
stale title** `# QA: BYOC json-render — LangGraph (Python)`. Left alone
so as not to collide with #6235.

Minor, also left as-is: `crewai-*/src/app/demos/byoc-hashbrown/page.tsx`
are one-line alias re-exports of the declarative page, and the
`crewai-*` / `llamaindex` manifests still list `byoc-hashbrown` /
`byoc-json-render` under `features:` (a separate id namespace the
validator does not read).

## Verification

```
cd showcase/scripts && npx tsx validate-parity.ts
# 21 package(s) checked, 21 pass, 0 fail, 446 warning(s)
```

Diff of validator output before/after shows exactly the 8 target
warnings removed and nothing new. `showcase/scripts` suite: 78 files /
2539 tests pass. No dangling references to the deleted paths anywhere in
`showcase/` or `.github/`.
2026-09-01 11:05:59 +02:00
lukasmoschitz 199988566c chore(showcase/harness): remove stray npm lockfile (#6799)
## What

Removes `showcase/harness/package-lock.json` (3948 lines) and records in
`pnpm-workspace.yaml` why no npm lockfile belongs there.

## Why

`showcase/harness` is a **pnpm workspace member** (listed in
`pnpm-workspace.yaml`), so its only install path is pnpm from the root
`pnpm-lock.yaml`. Both consumers run exactly that:

- `showcase/harness/Dockerfile` → `pnpm install --frozen-lockfile
--filter @copilotkit/showcase-harness...`
- the `harness unit suite` job in `test_unit-showcase.yml` → `pnpm
install --frozen-lockfile`

Nothing anywhere ran `npm ci` in this directory — no Dockerfile,
workflow, or script referenced the file.

Because no gate ever read it, it rotted unobserved. Against a fresh
regeneration it was **106 package versions stale**, carried 51 packages
no longer required, and was missing `axe-core` outright. That is how it
surfaced:

```
npm error `npm ci` can only install packages when your package.json and package-lock.json are in sync.
npm error Missing: axe-core@4.11.1 from lock file
```

…for anyone who saw the file and reasonably concluded this package
installs with npm.

## Why not just regenerate it

Regenerating makes `npm ci` pass, but produces a tree that materially
differs from what CI and prod run — **9 direct deps diverge**:

| dep | pnpm (real build) | regenerated npm lock |
|---|---|---|
| `@hono/node-server` | 2.0.0 | 1.19.17 (**different major**) |
| `playwright` | 1.59.1 | 1.62.1 |
| `hono` | 4.12.15 | 4.13.5 |
| `vitest` / `@vitest/coverage-v8` | 3.2.4 | 3.2.7 |
| `@aws-sdk/client-s3` | 3.1014.0 | 3.1121.0 |

The root cause is that npm cannot see the root `pnpm.overrides` block —
**73 minimum-version floors**, several of them security patches. That
field is pnpm-only. Today those floors happen to be satisfied by luck of
"latest-in-range"; a floor raised above a `package.json` caret range
would have `npm ci` silently install *below* the intended minimum.

So a working `npm ci` here would hand a developer a green install
against versions that never ship. The stale file was a signpost pointing
the wrong way — removed rather than maintained.

## Verification

- `pnpm install --frozen-lockfile --ignore-scripts` succeeds (the real
gate is unaffected by the `pnpm-workspace.yaml` edit).
- Root `pnpm-lock.yaml` already resolves `axe-core` at `4.11.1`;
confirmed installed in the harness tree with no npm lockfile present.
- `showcase/harness` typechecks clean via `tsc --noEmit`, after
generating the gitignored showcase fixtures the way
`test_unit-showcase.yml` does (`showcase/scripts` → `tsx
generate-registry.ts`). Without that step it reports 4 pre-existing
errors, documented in that workflow.
- `pnpm-workspace.yaml` still parses; 17 `packages` entries unchanged,
`showcase/harness` still a member.
- lefthook pre-commit and commitlint pass.

## Notes for reviewers

- `showcase/scripts` is also a workspace member and legitimately
**does** ship a `package-lock.json` — it is read by `npm ci` in the
harness Dockerfile and six `showcase_*` workflows. The note in
`pnpm-workspace.yaml` calls this out so the two do not read as
contradictory.
- Related, **not** in this PR: `showcase/eval-webhook` is in the same
situation as the harness — it ships a lockfile its own Dockerfile never
copies (it uses `npm install` on `package.json` alone, so its container
builds are not reproducible). Worth a separate cleanup.
- The pre-existing CI step named "Verify lockfile is up to date" in
`showcase_validate.yml` is `pnpm install --frozen-lockfile` at the repo
root. It never ran `npm ci` in `showcase/harness` — which is correct,
since that is the path actually used; the gap was coverage of a file
with no function.
2026-09-01 11:05:46 +02:00
Lukas Moschitz 1559be1ff1 chore(showcase/harness): remove stray npm lockfile
`showcase/harness` is a pnpm workspace member (pnpm-workspace.yaml), so its
only install path is pnpm from the root `pnpm-lock.yaml`. Both consumers run
exactly that: `showcase/harness/Dockerfile` (`pnpm install --frozen-lockfile
--filter @copilotkit/showcase-harness...`) and the `harness unit suite` job
in `test_unit-showcase.yml`. Nothing anywhere ran `npm ci` in this directory
— no Dockerfile, workflow, or script referenced the lockfile.

Because no gate ever read it, it rotted unobserved. Against a fresh
regeneration it was 106 package versions stale, carried 51 packages no longer
required, and was missing `axe-core` outright — which is how it surfaced:
`npm ci` here failed with "Missing: axe-core@4.11.1 from lock file" for
anyone who saw the file and reasonably concluded this package installs with
npm.

Regenerating it was the wrong fix. npm resolves a materially different tree
than the one CI and prod actually run — 9 direct deps diverged, with
`@hono/node-server` off by a whole major (pnpm 2.0.0 vs npm 1.19.17) — and
npm cannot see the root `pnpm.overrides` block, 73 minimum-version floors
with several security patches among them, because that field is pnpm-only.
A working `npm ci` here would hand a developer a green install against
versions that never ship, and could silently resolve below an intended
security floor. The stale file was a signpost pointing the wrong way, so it
is removed rather than maintained.

The root `pnpm-lock.yaml` already resolves `axe-core` at 4.11.1 correctly;
verified that `pnpm install --frozen-lockfile --ignore-scripts` succeeds and
that axe-core 4.11.1 is present in the harness tree with no npm lockfile,
and that the harness typechecks clean once the gitignored showcase fixtures
are generated the way CI generates them.

Adds a NOTE in pnpm-workspace.yaml recording why no npm lockfile belongs
here, so the file is not re-added in good faith as it was in 671cc6ae1d.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 09:51:54 +02:00
Max Korp 163731bb83 feat(integrations): align managed Intelligence starters (#6188)
## What changed

- Move managed starter templates to `CPK_INTELLIGENCE_API_KEY`.
- Remove `COPILOTKIT_LICENSE_TOKEN` from the AgentCore managed setup.
- Store only the managed project key in AWS Secrets Manager.
- Bind AgentCore Runtime requests to the verified Cognito subject.
- Let frontend-only AgentCore deploys skip backend secrets and endpoint
setup.

## Why

Managed CopilotKit Intelligence projects issue a project API key. They
do not
issue a self-hosted license token. AgentCore must deploy with the
managed key
alone.

Self-hosted license setup belongs to the Intelligence Helm chart. It is
not part
of this managed AgentCore template.

## Landing order

1. Merge #6098.
2. Publish `@copilotkit/runtime` and `@copilotkit/react-core` with
managed entitlement support.
3. Update the two AgentCore pins from `1.68.1` to that release.
4. Merge this PR.

Do not merge this PR before step 3. The current `1.68.1` pins do not
include the
managed entitlement path.

## Companion PRs

- Core SDK: #6098
- CopilotKit/Intelligence#628
- CopilotKit/oss-path-to-production#226

## Validation

- Intelligence migration and AgentCore security contracts: 163 passed.
- AgentCore CDK tests: 2 passed.
- AgentCore CDK, Runtime Lambda, and frontend builds passed.
- Integration parity checks passed with 0 errors.
- Formatter, changed-file lint, shell syntax, shellcheck, commit hooks,
and `git diff --check` passed.
- The AgentCore frontend test target has no test files and exits with
code 1.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added authenticated AgentCore Runtime access with Cognito-based
identity verification.
- Added managed Intelligence credential handling and secure secret
storage for AgentCore deployments.
- Added local-development support and frontend ID-token authentication.

- **Documentation**
- Updated setup guides, examples, and quickstarts to use
`CPK_INTELLIGENCE_API_KEY`.
- Clarified managed project API keys, self-hosted configuration, and
AgentCore deployment options.

- **Bug Fixes**
- Prevented caller-supplied identity headers from overriding verified
identities.

- **Tests**
- Expanded coverage for deployment flows, credential naming,
authentication, and runtime security.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-31 21:01:35 -07:00
Benjamin Taylor 2d44d3ff00 fix(agentcore): collapse the duplicate @copilotkit/shared in the lambda lock (refs OSS-1029)
The 1.70.0 repin left two copies of @copilotkit/shared in the AgentCore lambda: 1.70.0
nested under runtime, and 1.68.1 still hoisted at the top level, alongside a stale
@copilotkit/core 1.68.1.

runtime@1.70.0 pins shared to exactly 1.70.0, but the transitive @copilotkit/channels-*
0.9.0 packages ask for ^1.68.0, which the existing 1.68.1 resolution already satisfies.
A --package-lock-only bump has no reason to move a range that is already satisfied, so
npm hoists 1.68.1 for the channels packages and nests 1.70.0 under runtime. npm dedupe
does not collapse it; npm update on shared and core does.

Regenerating the lock from scratch also yields one clean copy, but sweeps 89 unrelated
packages with it -- @graphql-tools/executor 1.5.1 -> 2.0.0, @graphql-tools/utils 10 -> 11,
debug 2 -> 4, and a @types/express 5 -> 4 downgrade -- so it was rejected.

Verified: one copy of every @copilotkit and @ag-ui package in the lock afterwards, none
left on a 1.6x line, and npm install + tsc -p tsconfig.json exits 0.

Refs OSS-1029.
2026-08-31 20:23:15 -07:00
Maximiliano Korp b48bbd20ea test(integrations): tighten retired env boundaries 2026-08-31 20:23:15 -07:00
Maximiliano Korp a26767c538 fix(integrations): activate managed starters with project key 2026-08-31 20:23:15 -07:00
Maximiliano Korp 15b24e51a3 chore(examples): update CLI starters to CopilotKit 1.70.0 2026-08-31 20:23:15 -07:00
Benjamin Taylor ebf180b1cd fix(docs): name the project API key correctly in managed quickstarts (refs OSS-1029)
Three defects, all in the credential this branch renames.

Twelve integration quickstarts read `CPK_INTELLIGENCE_API_KEY=your_license_key`,
eleven of them under "The runtime reads the license key from step 1". The project
API key and the self-hosted license token are different credentials with
different lifetimes, and ENT-1151 exists to take the license token out of managed
setup -- so a reader who goes looking for a license key to paste finds a dead end
on the very page meant to connect them. Now `cpk-...`, and "reads the project API
key from step 1".

The placeholder prefix was wrong in the other direction on five pages, and newly
pinned that way by a test: `cpk_...`, with `cpk-...` asserted absent. A
provisioned key is `cpk-<projectId>_<short>_<long>` -- see the `cpk-` keyPrefix
in Intelligence's `apps/app-api/src/api-keys.ts` and the `parseApiKeyToken`
fixtures. No key the platform issues starts with `cpk_`, so the placeholder
taught a reader to distrust their own key. Both assertions are flipped.

The new copy guard scans every MDX page rather than listing the twelve, so a page
added next month is covered the day it lands. It reports the offending file and
value, which is how the twelve above were enumerated.

Finally, the retired-name boundary check is extracted to an exported
`retiredNameReference` and unit-tested. It is the load-bearing half of that rule
and it fails in one direction only: the canonical name ends with the retired one,
so a plain substring match reports all ~250 correct sites and the guard gets
switched off. The repo-wide scan cannot cover this -- it can say "clean", not
that the boundary is what made it clean, and it goes green either way once the
last old name is gone.

Verified: guard script exit 0; guard tests 20 passed; managed-starter-docs 10
passed (was 9); oxfmt and oxlint clean on the three changed TypeScript files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 20:23:15 -07:00
Mike Ryan 5a89b8f6c0 test(integrations): allow compose validation time 2026-08-31 20:23:15 -07:00
Mike Ryan f3b1ef345b fix(integrations): standardize Intelligence project key name 2026-08-31 20:23:15 -07:00
Mike Ryan f57c045f6f fix(integrations): remove AgentCore license token requirement 2026-08-31 20:23:15 -07:00
Mike Ryan 1d8ab5a778 test(integrations): stub uv in deploy harness 2026-08-31 20:23:15 -07:00
Mike Ryan 62b90dacee fix(integrations): preserve managed endpoint defaults 2026-08-31 20:23:15 -07:00