Commit Graph

12916 Commits

Author SHA1 Message Date
Tyler Slaton 2c531ffab9 test(scripts): capture fallback-array missing-decl warning; note ExportsEntry mirror
CR-loop final polish (non-behavioral):
- tsdown-exports.test.ts: the "maps over fallback-array targets" case left an
  unspied console.warn (b.mjs has no adjacent declaration) leaking to stderr.
  Wrap it in withWarnSpy and assert the warning fired — the declaration-less
  element is reported, not silently dropped.
- tsdown-exports.d.mts / validate-package-exports-types.ts: cross-reference the
  two hand-mirrored ExportsEntry definitions so they cannot drift silently.

No source behavior change; 36 tests pass, validate:exports exits 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:40:27 -07:00
Tyler Slaton 7df369f955 fix(build): generalize per-mode resolution to all conditions; fail-loud helper
CR-loop confirmation-round #4 findings:

- validator: `resolvesForMode` (renamed from `typesCoversMode`) now applies to
  EVERY condition, not just `types`. A partial object under `node`/`default`
  (active in both modes) no longer silently covers the mode it lacks —
  resolution falls through to the sibling, catching the untyped-JS #3324 shape
  there. This completes the per-mode model.
- helper: `withTypesConditions` throws on a non-object `exports` (bare string /
  array) instead of iterating it into a corrupt map; `typedTarget` now warns
  loudly when a JS target has no adjacent declaration (was silent, contradicting
  the helper's own fail-loud contract); idempotency skips only the helper's own
  `{ types: <string>, ... }` output, so a hand-authored types-first PARTIAL
  object is normalized (its untyped sibling gets a `types`). UMD / `.d.mts` docs
  corrected; `ctx.pkg: unknown` documented as intentional (weak-type constraint).
- tests: node/default partial fall-through regression; types-first-partial
  normalization; a helper->validator round-trip; a console.warn assertion for
  the missing-declaration path; split the untouched-target test into silent
  (non-JS) and warning (JS) cases.
- react-native: dropped a pre-existing duplicate `@ag-ui/client` external.

Call sites: resolvesForMode (internal, walk + recursion; grep-confirmed no
`typesCoversMode` refs); withTypesConditions signature unchanged, and the new
throw/warn never fire on tsdown's real input (object map, packageJsonPath
present, dts:true).

36 tests pass; validator typechecks; validate:exports exits 0; native-loader
builds of react-core + react-native unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:40:27 -07:00
Tyler Slaton f0c7e74ee4 fix(build): resolve object-valued types per mode; discriminating guard tests
CR-loop confirmation-round #3 findings:

- validator: a `types` condition now "wins" a resolution mode only when it
  actually covers that mode (new `typesCoversMode`). A partial object `types`
  (e.g. only `import`) no longer silently covers `require` — resolution falls
  through to the sibling, catching a real #3324 shape the checker previously
  missed. normalizeExports doc + a "read or parse" message tidied.
- helper: idempotency now keys on the FIRST condition being `types` (its own
  output shape) rather than mere presence, so a hand-authored `types`-last
  entry is normalized instead of passed through — keeping helper output
  consistent with what the validator accepts. JSDoc corrected (acts on every
  condition target, requires a subpath map, only ADDS a missing `types`).
- tests: made the runtime-only test discriminating (a `browser`-only target
  must not be flagged — the prior fixture couldn't catch a regression);
  exercised `node`; added partial/well-formed object-`types`, top-level
  fallback array, and types-last normalization cases.

Call sites: typesCoversMode (new internal, called by walk); walk/withTypes
signatures unchanged; isActiveCondition now also used by typesCoversMode.

32 tests pass; validator typechecks; real 25-package validate:exports exits 0;
native-loader react-core build unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:40:26 -07:00
Tyler Slaton f0c3b4bba7 fix(build): model per-mode exports resolution and wire the helper test into CI
CR-loop confirmation-round findings on the #3324 guard:

- validator: replace the single-`typesIndex` model with per-mode resolution.
  import- and require-mode resolve independently (each picks the first present
  of {types, <mode>, node, default} in object order), so a trailing
  `default`/`node` shadowed by a typed `import` + `require` is no longer a false
  positive, while a genuinely misordered/absent `types` is still flagged.
- helper: make `withTypesConditions` idempotent (skip an object that already
  carries a `types` key, so re-application never re-nests `default`) and
  optional-chain `ctx` so a missing context hits the fail-loud message.
- CI: run scripts/__tests__/tsdown-exports.test.ts in the guard workflow (the
  helper is the mechanism that injects the types conditions, and its test ran
  in NO workflow) and add it to the trigger `paths`; note the standalone gate
  validates committed artifacts, not build output.
- tests: assert `types` is emitted FIRST via serialization (toEqual is
  key-order-insensitive and missed a types-last regression); add idempotency and
  trailing-default regression cases.
- react-native: document why its exports map is hand-maintained (no tsdown
  `exports` hook) and guarded by validate:exports.

Call sites enumerated:
- walk / findExportsTypeViolations — internal to the validator + its tests;
  signatures unchanged. JS_CONDITIONS removed (grep-confirmed no refs); replaced
  by RESOLUTION_MODES + isActiveCondition.
- withTypesConditions — 13 tsdown configs via customExports; signature
  unchanged, tsdown always supplies ctx.pkg.packageJsonPath and never re-applies
  or emits null/array, so the new guards never fire on current input.

28 tests pass; validator typechecks; real 25-package validate:exports exits 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:40:26 -07:00
Tyler Slaton 1e65309252 fix(build): harden exports-types validator and helper for the full exports grammar
CR-loop findings on the #3324 regression guard:

- validator: normalize bare-string and conditions-only `exports` sugar to the
  "." subpath (previously a false negative / false positive); flag a `types`
  condition shadowed by an earlier import/require/node/default — a misordered
  `types` is the exact #3324 failure a strict resolver hits; recurse into
  object-valued `types`; ignore runtime-only conditions (browser/deno/...) so a
  typed import/require sibling is not falsely flagged; attach the file path and
  `cause` when a package.json fails to parse.
- helper: guard `null` (blocked subpath) and array (fallback) targets — the old
  code crashed on null and corrupted arrays into objects; fail loud if
  `packageJsonPath` is missing rather than silently emitting a types-less map.
- tests: hermetic fixture coverage for package discovery/filtering + the new
  exports shapes, and a new tsdown-exports.test.ts covering the previously
  untested `withTypesConditions` helper.

Call sites enumerated:
- withTypesConditions — 13 tsdown configs via customExports. tsdown always
  supplies packageJsonPath and generates no null/array targets, so the new
  throw/guards never fire on current input (verified: native-loader build of
  react-core unchanged, exports byte-identical).
- findExportsTypeViolations / validateAllPackages — signature unchanged;
  callers are the validator CLI and the tests. Real 25-package
  `validate:exports` still exits 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:40:25 -07:00
Tyler Slaton 9804d93652 chore: point tsdown-exports references at the renamed .mjs helper
Follow-up to the .ts -> .mjs rename: update the validate-package-exports
workflow trigger paths and the validator's comment/error message that still
named scripts/tsdown-exports.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:39:08 -07:00
Tyler Slaton 7673b8dfb8 fix(build): load tsdown exports helper as .mjs under native config loader
CI build runners use a Node with native TypeScript stripping enabled
(process.features.typescript), so tsdown selects its native ESM config
loader. That loader cannot resolve the extensionless relative import
"../../scripts/tsdown-exports" in each tsdown.config.ts, so every package
build failed with "Cannot find module" — cascading into the unit, runtime,
and all integration jobs (which run the build first). Local builds used
tsdown's bundler loader instead, which is why this passed pre-push.

Ship the shared helper as scripts/tsdown-exports.mjs (real ESM) plus a
hand-written tsdown-exports.d.mts, imported with the explicit .mjs
extension. This resolves under the native loader, tsdown's bundler loader,
and tsc alike. The generated exports are unchanged — package.json maps stay
identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:39:07 -07:00
Tyler Slaton fcac2e9911 fix(build): add types condition to package.json exports maps (#3324)
Under moduleResolution bundler/node16/nodenext, TypeScript ignores the
top-level "types" field once an "exports" map exists, so strict-exports
tooling (e.g. the Backstage CLI) resolves no type declarations and reports
every named export as "has no exported member". tsdown does not emit a
types condition in the exports map it generates.

Add one — first, per import/require, ESM to .d.mts and CJS to .d.cts — via
a shared withTypesConditions helper (scripts/tsdown-exports.ts) wired into
each tsdown config, and directly in the hand-maintained react-native map.

Add a regression guard, since attw and publint do NOT catch this (TS's
adjacent-file fallback masks it): scripts/validate-package-exports-types.ts,
unit + all-package tests, a validate:exports npm script, and a CI workflow
that fail if any publishable package's exports map lacks a types condition.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:38:10 -07:00
Tyler Slaton 0195ef89a2 feat(examples): add Claude Agent SDK starters (Python + TypeScript) (#5906)
## What does this PR do?

Adds two clonable starter templates —
`examples/integrations/claude-sdk-python` and
`examples/integrations/claude-sdk-typescript` — that show CopilotKit
driving a Claude Agent SDK agent over AG-UI, mirroring the
`langgraph-python` showcase (todos canvas, charts, A2UI flight cards +
dynamic dashboards, human-in-the-loop, theme toggle, threads drawer).
Each agent is a thin, idiomatic layer on the official `ag-ui-claude-sdk`
/ `@ag-ui/claude-agent-sdk` adapters: three backend tools (`query_data`,
`search_flights`, `generate_a2ui`) live in per-tool modules and are
wired into `ClaudeAgentAdapter`, while the shared todo board is driven
by the adapter's built-in `ag_ui_update_state` tool. The default model
is `claude-sonnet-5` and local dev uses a real `ANTHROPIC_API_KEY`
(matching the official AG-UI dojo). Both instances are registered in the
`_parity` manifest so their frontends stay synced with the north-star.

## Related PRs and Issues

- Complements the Claude Agent SDK quickstart docs (#5840)

## Checklist

- [ ] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [ ] "Allow edits by maintainers" is checked

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-09 19:13:24 -07:00
Tyler Slaton d59000e5d7 fix(examples): guard empty submissions in claude-sdk headless-chat
CodeRabbit flagged that the form onSubmit added to headless-chat could submit
empty/whitespace messages. The handler now returns early on blank input and the
submit button is disabled when the message is empty. Applied to the claude-sdk
starters (where the form lives); headless-chat.tsx is already declared
allowedDivergence for these instances, so parity stays green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 17:32:57 -07:00
Tyler Slaton a54ae82fc4 fix(examples): keep CodeRabbit fixes on claude-sdk starters, revert north-star sync
Revert the cross-demo parity sync from b34a9a348: langgraph-python (north-star)
and the langgraph-js / langgraph-fastapi / strands-python instances are restored
to their origin/main state — this PR should not mutate the canonical demo or its
siblings.

Instead, keep the CodeRabbit fixes on the claude-sdk-* starters and declare the
affected shared files as per-instance `allowedDivergence` in the parity manifest,
so `pnpm parity:check` passes without touching the other demos. The starters
carry fixes the north-star has not caught up to yet:

- border-3 -> border-[3px]; bg-[--x] / text-[--x] -> [var(--x)] (Tailwind v4)
- JSX.IntrinsicElements -> React.JSX.IntrinsicElements; Recharts <Bar shape> type
- tool-rendering args?: unknown; mode-toggle a11y; headless-chat <form>
- docker-route-override AGENT_URL trailing-slash normalization

next.config.ts is left matching the north-star template (its ignoreBuildErrors is
a shared build-config concern and the Docker build re-adds it regardless).

parity:check green (5/5 instances, 0 errors); claude-sdk tsc + oxfmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 17:27:28 -07:00
Tyler Slaton 71d33bae59 fix(examples): sync CodeRabbit fixes through the parity north-star
The CodeRabbit fixes in d4ef84f2c edited verbatim parity-tracked files
directly in the claude-sdk-* instances, diverging them from the north-star
(langgraph-python) and failing `pnpm parity:check`.

Move the shared-surface fixes to the north-star and propagate to every
tracked instance via `pnpm parity:sync --all`:

- border-3 -> border-[3px] (border-3 is not a Tailwind utility)
- bg-[--x] / text-[--x] -> [var(--x)] (Tailwind v4 CSS-variable syntax)
- JSX.IntrinsicElements -> React.JSX.IntrinsicElements (@types/react 19)
- Recharts <Bar shape> callback typing
- tool-rendering args?: unknown
- mode-toggle aria-pressed/type/role, headless-chat <form> + aria-label
- docker-route-override AGENT_URL trailing-slash normalization

Also revert the next.config.ts `ignoreBuildErrors` removal: next.config.ts is
a north-star template file shared across all integration demos, so the
suppression can't be dropped on a subset without breaking parity, and dropping
it template-wide would need every demo verified to build clean without it. The
two real type errors it was masking are now fixed at the north-star, so the
shared surface is type-clean regardless.

parity:check green (5/5 instances, 0 errors); claude-sdk tsc + oxfmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 17:27:28 -07:00
Tyler Slaton c6061f2e47 fix(examples): address CodeRabbit review on Claude Agent SDK starters
Resolve the real issues surfaced by CodeRabbit on the new claude-sdk-python /
claude-sdk-typescript starters (frontend files are shared, so most fixes apply
to both):

- Fix two type errors that `ignoreBuildErrors` was masking: `JSX.IntrinsicElements`
  -> `React.JSX.IntrinsicElements` (@types/react 19) and the Recharts `<Bar shape>`
  callback type; then drop the blanket `typescript.ignoreBuildErrors` from
  next.config.ts so source type-checks. The Dockerfile's build-time patch still
  re-adds it for the `next@latest` Docker build, so deploy behavior is unchanged.
- Fix Tailwind v4 CSS-variable syntax: `bg-[--x]` -> `bg-[var(--x)]`, and
  `border-3` -> `border-[3px]` (border-3 is not a utility -> invisible spinner).
- Harden the agent tools: omit the empty ANTHROPIC_API_KEY, wrap the Anthropic
  call in try/catch (TS + Python), normalize the AGENT_URL trailing slash, and
  make the Flight schema's id/airlineLogo/statusIcon required to match the
  "must have" tool description.
- Minor a11y: mode-toggle `aria-pressed`/`type`/`role`, headless-chat `<form>`
  + `aria-label` (Enter-to-submit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 17:27:28 -07:00
Tyler Slaton 2a041c2a96 docs(examples): list Claude Agent SDK starters in the examples index
Add claude-sdk-python and claude-sdk-typescript to the Integrations table
in examples/README.md (17 → 19; total 48 → 50). The two starters were added
to examples/integrations/ but were missing from the index.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 17:27:28 -07:00
github-actions[bot] 7809896d3e style: auto-fix formatting 2026-07-09 17:27:28 -07:00
Tyler Slaton 36020b061f feat(examples): add Claude Agent SDK starters (Python + TypeScript)
Two clonable starter templates showing CopilotKit driving a Claude Agent SDK
agent over AG-UI, mirroring the langgraph-python showcase (todos canvas, charts,
flight cards, dynamic dashboards, HITL, theme, threads drawer).

Each agent is a thin, idiomatic layer on the official ag-ui-claude-sdk /
@ag-ui/claude-agent-sdk adapters: three backend tools (query_data, search_flights,
generate_a2ui) live in per-tool modules and are wired into ClaudeAgentAdapter,
while the shared todo board is driven by the adapter's built-in ag_ui_update_state
tool. The default model is claude-sonnet-5 and local dev uses a real
ANTHROPIC_API_KEY (matching the official AG-UI dojo). Both instances are
registered in the _parity manifest so their frontends stay synced with the
langgraph-python north-star.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 17:27:28 -07:00
Ben Taylor bb7ad12075 feat(channels-intelligence): emit leaseToken on render-accept + complete (OSS-446) (#5899)
## Summary

SDK-emit half of **OSS-446** (lease-token fencing for hosted-bot
render/complete). The `fail` path already sends the delivery lease
token; **render-accept** and the **completion intent** did not — so
app-api fell back to the weaker instance-id + expiry check on those two
paths.

This makes the SDK send `leaseToken` on both, on **both transports**:

- **HTTP** — `HttpRenderEventSink.push` now includes `leaseToken`, via a
new `leaseTokenFor(deliveryId)` accessor on `HttpDeliverySource`
(mirrors the existing `scopeFor`). (`ack` already sent it.)
- **Phoenix** — `push` (render-accept) and `complete_requested` now
carry `leaseToken` from `DeliveryState` (`fail` already did).

## Why it's safe to ship now (ahead of the app-api "require" flip)

Verified end-to-end against the live Intelligence server:

- **Gateway** `validate_render_payload` allows `leaseToken` (optional,
`maybe_put_lease_token`) and forwards it via `accept_render_event`;
`validate_complete_payload` merges the payload through and forwards it
via `complete_delivery`.
- **app-api** fences render-accept (`$N IS NULL OR lease_token_hash =
$N`) and complete (`$N IS NULL OR ...`) **optionally** today — so
supplying the token starts fencing on it immediately, and omitting it
still works. No breakage; strictly a security improvement on the paths
that were previously unfenced.

## Scope

This is **half A** (SDK emit). **Half B** — flipping app-api's
render-accept + complete fences from optional to *required* and dropping
the instance-id/expiry fallback — is deferred until #511 (managed Teams)
settles `managed-bots/service.ts`, and follows from OSS-446's "require
*once the SDK sends it*" premise.

## Tests

- HTTP: render-accept POST asserts `leaseToken` from the claimed lease
flows into the body.
- Phoenix: render-accept + `complete_requested` payloads assert
`leaseToken`.
- Build + 95 tests green.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-09 16:30:39 -05:00
Benjamin Taylor 2bca275008 feat(channels-intelligence): emit leaseToken on render-accept + complete (OSS-446)
SDK-emit half of OSS-446 (lease-token fencing for hosted-bot render/complete).
The fail path already sends the lease token; render-accept and the completion
intent did not, so app-api fell back to instance-id + expiry there.

- HTTP: HttpRenderEventSink.push now includes leaseToken (new leaseTokenFor()
  bridge on HttpDeliverySource, mirroring scopeFor). (ack already sent it.)
- Phoenix: push (render-accept) and complete_requested now carry leaseToken
  from DeliveryState (fail already did).

Optional/forward-compatible: app-api + gateway already accept and fence on the
token when present (verified render/complete validators + fencing SQL), falling
back to the old check when absent — so this deploys safely ahead of the app-api
flip-to-required (OSS-446 half B), which waits on #511 settling managed-bots
service.ts.
2026-07-09 14:53:12 -05:00
Maxim 3c4da1affd feat(banking): data-bridged Open Generative UI (#5896)
## Summary

Adds **Open Generative UI (OGUI)** to the Northwind banking demo: the
agent can author sandboxed, interactive UI (rendered in an isolated
iframe) that pulls **real, read-only banking data** via sandbox-function
callbacks — so every figure it shows is real app data (fetched on
demand), never fabricated, and no secret ever crosses the boundary.

- **New `src/opengen/` module** — a stable, module-scope
`sandboxFunctions` array
(`getTransactions`/`getPolicies`/`getCards`/`getKpis`) whose handlers
read a module snapshot kept fresh by a headless `<SandboxDataSync/>`
mirroring the app's live (role-filtered) `useCreditCards` view. Handlers
return **projection DTOs** — `getCards` drops `pin`/`expiry`, guarded by
a no-leak unit test.
- **Shared over-limit derivation** — extracted to
`src/lib/over-limit.ts` so the chat readable, the A2UI report renderers,
and the OGUI sandbox all agree on which charges are over limit
(behavior-preserving).
- **OGUI enabled on both runtime paths** (Intelligence + OSS) with an
**artifact-type routing fence** in the agent prompt:
`generateSandboxedUi` only for interactive/custom UI, explicitly
excluded from reports/charts *even when the user says "build"* (protects
the existing "Build a spend report on the canvas" pill), and never part
of the teach/recall arc.
- **Provider wiring** — `openGenerativeUI={{ sandboxFunctions,
designSkill: NORTHWIND_DESIGN_SKILL }}` plus two OGUI-only pills ("Build
an interactive spend explorer", "Prototype a cash-flow what-if
calculator").
- **Deterministic routing guard** — `e2e/ogui-routing.spec.ts`
(dedicated OSS-mode config, isolated ports, no docker) pins both
boundary sides: the 5 visualization pills still route to their curated
tool (no iframe), and the 2 OGUI pills render an iframe. Also fixes
stale pill assertions in `smoke.spec.ts`.

Additive only — no changes to existing curated charts, the A2UI report
canvas, or the teach/recall arc beyond the behavior-preserving
over-limit extraction.

## Test Plan

- [x] Unit suite green (65 tests) — incl. `over-limit`,
`sandbox-functions` (no-`pin`/`expiry` leak + over-limit flag + KPI
counts)
- [x] `tsc --noEmit` clean · eslint clean · `nx build` success
- [x] OGUI routing e2e: **7 passed** (OSS mode, no docker) — curated
pills + boundary + OGUI pills
- [ ] **CI**: license-gated `smoke.spec.ts` + docker-backed
`memory-learning.spec.ts` (blocked locally: no license token /
Intelligence stack; must pass unchanged in CI)
- [ ] **Manual**: render "Build an interactive spend explorer", confirm
iframe figures match the dashboard in light/dark, and no PIN is ever
shown

## Notes

- Follow-up (out of scope): additional over-limit derivation copies
remain in `proactive-notice.tsx`, `transactions-list.tsx`,
`pending-approvals-chat.tsx` — candidates to migrate onto the new shared
helper.
- The deterministic e2e pins the tool call (aimock), so it proves the
tool-rendering plumbing and that curated surfaces still work — real LLM
routing is the manual check above.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-09 21:17:25 +02:00
David McKay a9c0910dea Merge branch 'main' into feat/banking-open-generative-ui 2026-07-09 12:07:23 -07:00
Maxim c1819f4932 test(banking): correct OGUI double-pill rationale comment
The .first() guard on the 'rendered on the canvas' handoff-pill assertion
was justified by an inaccurate comment (accumulation across exchanges). The
real cause is intra-turn: generateSandboxedUi has followUp:true, so aimock
re-serves the same fixture on the unchanged-userMessage follow-up turn in
replay -> a second identical pill. A terminating sequenceIndex follow-up
fixture was attempted but destabilized the suite (title-generation requests
substring-match the pill text and consume the sequence counter before the
real leg-1 turn), so the .first() guard remains. Test/fixtures only; no
source changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:34:29 +02:00
Tyler Slaton 704e31ee6a chore: release channels-slack v0.1.1 (#5903)
## Release channels-slack v0.1.1

**Scope:** `channels-slack` | **Bump:** `patch`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `channels-slack` packages to `0.1.1`
   and generated AI-enhanced release notes.

2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
   must pass before merging. This is the review gate.

3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.

4. **When this PR is merged**, the `release / publish` workflow
automatically:
   - Builds all packages
   - Publishes the `channels-slack` packages to npm at version `0.1.1`
   - Creates git tag `channels-slack/v0.1.1`
   - 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.
channels-slack/v0.1.1
2026-07-09 10:41:07 -07:00
tylerslaton 95ffa053d0 chore: release channels-slack v0.1.1 2026-07-09 17:38:30 +00:00
github-actions[bot] 87b6fa330d style: auto-fix formatting 2026-07-09 17:34:36 +00:00
Maxim cd7e49e467 test(banking): OGUI routing asserts the canvas surface 2026-07-09 19:27:57 +02:00
Maxim c541f1b32d feat(banking): render OGUI surfaces on the canvas with a chat handoff pill 2026-07-09 19:14:50 +02:00
Maxim 001b915af2 feat(banking): useOguiSurface reads the latest OGUI activity from the stream 2026-07-09 18:49:37 +02:00
Maxim 53cbeee311 feat(react-core): export OpenGenerativeUIRenderer from the public v2 barrel 2026-07-09 18:48:40 +02:00
Tyler Slaton 5cae8d4937 fix(docs): clean Claude generative UI snippets (#5890)
## Problem

Claude Agent SDK docs could render malformed or missing extracted
snippets across the generated Python and TypeScript integration docs.
The generative UI pages had stale duplicate regions and generic setup
leakage, while the custom look-and-feel reasoning and slots pages
referenced demo cells or regions that did not exist for every Claude
integration.

## Why

The docs pipeline treated accidental duplicate region names across files
as intentional multi-file regions, and several authored docs pages
drifted from the actual generated showcase demo IDs/regions. That left
some pages visually correct at a glance but broken when users opened
specific extracted code snippets.

## Fix

- Move the shared `bar-chart-renderer` regions to the complete
`useComponent` call and delete stale duplicate snippet files.
- Add an explicit duplicate-region guard and verifier coverage for
accidental cross-file region collisions.
- Add line-emphasis support for extracted `<Snippet>` blocks and setup
`<DemoCode>` output.
- Scope generative UI feature pages away from generic `agent-setup`
boilerplate.
- Repair the shared reasoning-messages docs to use the generated
`reasoning-default` and `reasoning-custom` demo cells.
- Add the missing Claude Python chat-slots teaching snippet regions and
keep both Claude slot snippets self-contained.
- Broad-audit both Claude integration docs locally, then targeted-audit
the repaired reasoning/slots pages in light and dark mode.
2026-07-09 09:42:56 -07:00
Alem Tuzlak d4a9bc3355 fix(react): resolve package types under bundler/node16/nodenext (#5264)
## Problem

The published declaration files for `@copilotkit/react-core`,
`@copilotkit/react-ui`, and `@copilotkit/react-textarea` contain imports
that TypeScript cannot resolve, so **`attw` (Are The Types Wrong)
reports `InternalResolutionError` across every resolution mode**
(`node10` / `node16` / `bundler`). In `@copilotkit/react-core` this was
being **masked in CI** by `--ignore-rules internal-resolution-error` on
the package's `attw` script — so the existing `check:packages` gate
looked green while consumers under `moduleResolution:
bundler`/`node16`/`nodenext` got broken types (the symptom reported in
#3324: `has no exported member 'useAgent'`, etc.).

Two distinct artifacts leaked into the emitted `.d.ts` / `.d.cts` /
`.d.mts` (neither affects the JS bundles):

1. **Side-effect CSS imports** — `import "./index.css"` is intentionally
kept in the JS so styles auto-load for bundler consumers, but
`rolldown-plugin-dts` also left it in the declarations, where TypeScript
can't resolve a `.css` as a typed module.
2. **Extensionless relative `./context` import** —
`@copilotkit/react-core/v2/headless` re-exports the externalized context
module; the JS bundle correctly externalizes it to
`@copilotkit/react-core/v2/context`, but the declaration kept the
relative `./context`, which is invalid in ESM declarations.

> Note: this is **not** the missing-`exports.types`-condition theory
from #3324. tsdown deliberately relies on co-located `.d.mts`/`.d.cts`
siblings; `@copilotkit/core` already resolves cleanly. The real defects
are the two leaked imports above.

## Fix

A small tsdown `build:done` hook post-processes the emitted declarations
**on disk** (after every format is written, so it catches both `.d.mts`
and `.d.cts`):

- strips side-effect CSS imports from declarations (JS keeps them);
- rewrites the relative `./context` import to the
`@copilotkit/react-core/v2/context` package path (matching how the JS
bundle externalizes it).

Also:
- **Removed the `--ignore-rules internal-resolution-error` band-aid**
from `react-core`'s `attw` script so the existing CI gate validates for
real.
- **Dropped the dead `codeSplitting` option** from the UMD configs —
tsdown never reads it (it's a rolldown-only key), and it was failing
`tsc` in the configs that type-check themselves. UMD output is unchanged
(single file).

## Verification

- All three packages build; **no CSS or relative-`./context` imports
remain in any declaration**, while the JS bundles still contain them
(styles auto-load preserved).
- `attw` + `publint` pass for all packages **with no suppression**
(`react-core`'s `/v2`, `/v2/headless`, `/v2/context` are green for
node16-cjs/esm/bundler).
- Unit tests pass.
- A standalone consumer project (real tarball install, `skipLibCheck:
false`) type-checks the public APIs — including `useAgent` /
`useFrontendTool` / `useConfigureSuggestions` — cleanly under **both
`bundler` and `nodenext`**, and the headless↔context class is nominally
identical.

## Out of scope (follow-ups)

- `@copilotkit/react-native`: its `--ignore-rules
internal-resolution-error` currently suppresses nothing (no IRE) and it
has a separate `NoResolution` flag.
- `@copilotkit/vue`: a large, genuine set of `.vue`/relative-import
declaration errors unrelated to this change.

Relates to #3324.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-09 18:42:07 +02:00
Sam Julien 3ad620137c docs: document CLI import command (#5824)
## Summary
- Add the new `copilotkit import` command to the shared CLI docs
rendered at `/cli` and integration CLI pages.
- Document ADK and LangGraph examples, scripted flags, source credential
env vars, `--dry-run`, and `--replace`.
- Update the shell-docs nav test expectation for de-duped `Threads`
placement in authored framework nav.

## Test Plan
- `cd showcase/shell-docs && npm run lint` (passes with existing
warnings)
- `cd showcase/shell-docs && npm run typecheck`
- `cd showcase/shell-docs && npm test`
- `cd showcase/shell-docs && npm run build`
2026-07-09 09:15:58 -07:00
Alem Tuzlak 52b957fda6 chore: release channels-teams v0.1.1 (#5898)
## Release channels-teams v0.1.1

**Scope:** `channels-teams` | **Bump:** `patch`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `channels-teams` packages to `0.1.1`
   and generated AI-enhanced release notes.

2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
   must pass before merging. This is the review gate.

3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.

4. **When this PR is merged**, the `release / publish` workflow
automatically:
   - Builds all packages
   - Publishes the `channels-teams` packages to npm at version `0.1.1`
   - Creates git tag `channels-teams/v0.1.1`
   - 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.
channels-teams/v0.1.1
2026-07-09 18:15:25 +02:00
tylerslaton 0653031fa2 chore: release channels-teams v0.1.1 2026-07-09 16:06:25 +00:00
Maximiliano Korp d1fbd583dd docs(shell-docs): document cli import command 2026-07-09 09:02:24 -07:00
Tyler Slaton 606afd8a13 feat(bot-teams): add ./render export for managed reuse (#5878)
## Summary

Adds a `./render` subpath export to `@copilotkit/bot-teams` surfacing
`renderAdaptiveCard`, `isPlainText`, `collectPlainText`,
`ADAPTIVE_CARD_CONTENT_TYPE`, and `createRunRenderer`, so the managed
(Intelligence-hosted) Teams egress path can reuse the adapter's Adaptive
Card rendering without deep-importing `dist/*`.

Paired with the managed Microsoft Teams work in Intelligence (OSS-441
slice ②): CopilotKit/Intelligence#511.

## Notes

- Additive only — a new `exports["./render"]` entry +
`src/render/index.ts` re-export barrel. No behavior change to existing
exports.
- Not strictly on the critical path yet: the managed runtime currently
resolves the renderer via a runtime deep-dist import of the published
package, so this export is the clean forward path rather than a hard
dependency.
- Coordinate the `bot-teams` → `channels-teams` rename (OSS-438) before
merge.
2026-07-09 08:58:43 -07:00
Alem Tuzlak f993c54bfb fix(bot-intelligence): align managed runtime delivery ownership (#5800)
## Problem

The Intelligence realtime loop exposed two SDK-side ownership gaps while
testing managed Coworkers against the Intelligence PR:

- Phoenix channel auth should use the SDK socket auth token path
expected by the gateway.
- Delivery handling needs to carry the app-api lease token and
authoritative delivery scope through render/fail/complete handling
instead of rebuilding ownership from local defaults.
- Runtime integration needs to pass the render sink into
`intelligenceAdapter` so managed runtimes stream rich render frames over
the realtime path.

## Why

The target Coworker path is websocket-first: Intelligence app-api owns
durable delivery state, realtime-gateway owns live transport, the SDK
receives leased delivery over Phoenix, streams render events, waits for
durable receipt coverage, and sends completion intent without taking
over app-api ack authority.

This PR is stacked on Alem's SDK realtime branch so the dependency trail
is explicit:

- Base SDK branch: `codex/oss-402-sdk-render-events`
- Intelligence PR: https://github.com/CopilotKit/Intelligence/pull/466
- Linear: OSS-402 / OSS-406

## Fix

- Use Phoenix socket `authToken` for the managed bot channel.
- Preserve `leaseToken` and delivery `scope` in
`PhoenixRealtimeTransport` state.
- Send fail/nack payloads with the correct lease token, delivery status,
and optional accepted-through pointer.
- Pass `renderSink` from `startManagedBots` into `intelligenceAdapter`.
- Add regression coverage for render-sink propagation and lease-token
fail payloads.

## Testing Methodology

Local verification used an external pnpm store to avoid repo-local
`.pnpm-store` churn:
`PNPM_CONFIG_STORE_DIR=/private/tmp/pnpm-store-codex`.

- `PNPM_CONFIG_STORE_DIR=/private/tmp/pnpm-store-codex
PNPM_CONFIG_CONFIRM_MODULES_PURGE=false corepack pnpm --dir
/private/tmp/copilotkit-oss-402-20260701 --filter
@copilotkit/bot-intelligence test`
  - Passed: 5 files, 48 tests.
- Commit hook also ran the package gate for
`@copilotkit/bot-intelligence`:
  - `test`: passed, 5 files / 48 tests.
  - `publint`: passed with repository URL suggestion only.
- `attw --pack . --profile esm-only`: passed with the existing ignored
CJS-to-ESM warning profile.
- `git diff --check -- packages/bot-intelligence/src/phoenix-channel.ts
packages/bot-intelligence/src/phoenix-transport.ts
packages/bot-intelligence/src/render-events.test.ts
packages/bot-intelligence/src/runtime.test.ts
packages/bot-intelligence/src/runtime.ts`
  - Passed.

Scope control: only the five `packages/bot-intelligence/src/*` files
above are committed. Existing local `pnpm-lock.yaml` and image/LFS dirt
in the SDK worktree were left unstaged and are not in this PR.
2026-07-09 17:56:38 +02:00
Maxim c54148412a test(banking): deterministic OGUI routing guard over the adjacency set
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 16:43:47 +02:00
Benjamin Taylor 58e561e2fa Merge origin/main into alem/oss-441-managed-teams (Bots→Channels rename)
Reconcile #5878 with the @copilotkit/bot*→@copilotkit/channels* rename (#5849):
- relocate the new render barrel (render/index.ts, render/index.test.ts) into
  packages/channels-teams; relative imports (./adaptive-card, ../event-renderer)
  resolve unchanged. package.json ./render export auto-merged.
- fix a stale @copilotkit/bot-teams comment ref to @copilotkit/channels-teams.
2026-07-09 08:44:19 -05:00
Benjamin Taylor b5dad876ab fix(channels-intelligence): make Phoenix delivery drops observable + cover new behaviors
Review follow-ups for the managed delivery-ownership change:
- add an optional `log` seam to PhoenixTransportConfig; the transport was
  otherwise silent, so the two new drop paths were invisible failure modes.
- log the leaseToken-missing drop distinctly (the gateway/SDK version-skew
  hazard: without it, every delivery silently re-loops on lease lapse) and the
  nack no-delivery-state drop, instead of bare returns.
- refresh TSDoc: toIngressEnvelope's new return shape + drop semantics, and the
  DeliveryState.leaseToken/scope fields.
- tests: leaseToken-required drop, nack no-state no-op, and per-delivery scope
  stamping on render + fail (the scope field previously had no coverage).
2026-07-09 08:10:44 -05:00
Benjamin Taylor 024446e5db Merge origin/main into codex/oss-402-sdk-handoff-fixes (freshen) 2026-07-09 08:07:37 -05:00
Tyler Slaton 66b5a58339 fix(docs): repair Claude custom look snippets 2026-07-08 21:39:49 -07:00
github-actions[bot] ae3ecc2cb7 style: auto-fix formatting 2026-07-09 03:39:16 +00:00
Tyler Slaton 0f5a916075 fix(docs): clean Claude generative UI snippets 2026-07-08 20:38:13 -07:00
Jordan Ritter 66502b5b3d fix(showcase-harness): D4 probe hardening follow-ups (budget-exhaustion, degraded-path, telemetry, coverage) (#5888)
Tracked follow-up to #5882 (D4 first-token SSE turn-complete fix). These
are the deferred **bucket-(b)** items from that PR's CR —
non-load-bearing polish/hardening on the D4 probe driver
(`showcase/harness/src/probes/drivers/d4-chat-roundtrip.ts` +
`.test.ts`). No re-architecture; each change is tight and scoped.

## Items

### 1. Budget-exhaustion retry guard (behavioral)
A late non-completion retry resend could floor its `type`/`press` action
timeout to ~1ms (when the remaining budget ≈ 0), throwing a
page-fault-shaped error. That throw was red-classified indistinguishably
from a real page fault — a spurious-red flap source. Fix: skip the
resend when the remaining budget is below `RETRY_MIN_BUDGET_MS` (750ms);
the stall then reds on its own terms.

**Red-green:** with the guard disabled, the doomed resend attempts a
second `type` (typeAttempts=2); with the guard, `type` fires exactly
once (typeAttempts=1). RED observed (2), GREEN observed (1).

### 2. Degraded-path floor when interceptor silently no-ops (behavioral)
When `sseAttachFailed` is true, the page-side turn-lifecycle globals
were never seeded, so the poll could only fall into the never-observed
branch and pin the deadline to the base `textPollTimeoutMs` floor —
reintroducing the slow-first-token false-red #5882 targets. Fix: consult
`sseAttachFailed` to widen the never-observed wait to the per-attempt
ceiling.

**Red-green:** degraded page + late-but-present token (800ms, base floor
bites at the ~500ms poll before the token) → RED (pre-fix, base-floor
fast-fail) vs GREEN (post-fix, widened to ceiling captures the token).
RED observed (`red`), GREEN observed (`green`). A genuinely-empty
degraded run still reds (over-correction guard).

### 3. Retry edge-header re-attribution (telemetry)
On a retry-rescued GREEN turn, `messageSendEdge` / `messageSendEdge` /
`lastMessagePostResp` stayed latched to the first (stalled) attempt,
mis-attributing `edge_interference_signal` / the DEBUG raw-byte sample.
Fix: re-arm the capture latches before the resend so the winning
attempt's response re-captures them.

**Focused test:** stalled attempt carries `cf-mitigated: stalled`,
winning resend `cf-mitigated: winning`; the final `probe.message.send`
boundary now carries `winning` (pre-fix it reported `stalled`).

### 4. Coverage (tests only, no prod change)
- FIFO-cap `CVDIAG_MAX_OUTSTANDING_STARTS_PER_URL` eviction backstop
(guard-verified: fails if the cap is removed).
- DEBUG-auto-disarm fail-closed negative test (disarmed → no raw-byte
capture).
- Alternate-content / raw-byte block SKIPPED on the container-success
(non-empty) path.
- Fixed the `makeLateTokenBrowser` shared-page state leak: each
`newContext().newPage()` now mints its own state, so L3 and L4 each run
an independent stall+retry cycle (was a singleton that leaked
`sendCount` from L3 into L4, so the L4 retry path was never genuinely
exercised).

### 5. `lastStoppedAtMs` documentation (cleanup)
Write-only in d4; documented that it is retained for shared-global
parity with the `attachSseInterceptor` global shape the d6 run-signal
snapshot mirrors, so it does not read as dead code.

## Verification
- `tsc --noEmit`: clean
- `tsc -p tsconfig.build.json` (build): clean
- Full harness vitest: **3213 passed, 0 failing** (72 in the d4 file,
all green)
- oxlint: **0 errors** (only pre-existing warnings, none new)
- Diff hygiene: only the driver + test file (no `repro_*` / `baseline`)

🤖 Generated with [Claude Code](https://claude.com/claude-code)


---

## CR follow-up round (commit 13a636b67)

CR found the follow-up left `readTurnState()` error handling
**inconsistent** — the exact false-red/flap class this effort fights.
Addressed, plus completed two of the PR's own items.

### (a) Harmonized `readTurnState()` error handling
One guarded `safeReadTurnState()` wrapper now backs all three consumers
(`readBaseline`, `readTurnComplete`, `readDegraded`). A mid-poll
`readTurnState()` throw now means ONE thing everywhere: "no reliable
signal" → return a well-defined degraded sentinel (`sseAttachFailed:
true`, zeroed counters) → route onto the degraded **widen** path (not
base-floor fast-fail, not a spurious `level-error`), and it is
**observable** via a one-shot greppable marker. Previously:
`readDegraded` swallowed the throw into `false` (silent base-floor
false-red, no telemetry) while `readBaseline`/`readTurnComplete` let it
escape → generic `level-error` (spurious red). A genuinely-empty
degraded turn still reds at the widened ceiling (no masking).

### Folds
- **item-1 first-send cap:** guard the in-send `press` against
`SEND_PRESS_MIN_BUDGET_MS` so a near-hang `type` can't floor `press` to
~1ms and yield a generic `level-error`; classify distinctly as
`send-budget-exhausted`. Only `press` is guarded (`type` opens the
envelope) so a legitimately-small `pageTimeoutMs` still issues a healthy
first send.
- **item-3 null-header:** suppress the `finally`-block fallback
`probe.message.send` once a real-header boundary already fired, so a
retry whose winning resend lands no POST no longer emits a second
NULL-header boundary (mis-attributed `edge_interference_signal`).
- errorDesc JSDoc: added `abort` to the enumeration (zero-risk).

### Red-green (verbatim, against the real runLevel/readTurnComplete
path)
- **readTurnState throw:** RED `expected 'red' to be 'green'` (pre-fix
spurious red on a late-but-present token) → GREEN (degraded widen; late
token passes; genuinely-empty degraded still reds).
- **first-send cap:** RED `expected 'level-error' to be
'send-budget-exhausted'` → GREEN (distinct classification, no
1ms-floored `press`).
- **item-3 null-header:** RED `expected 2 to be 1` (second null-header
emit) → GREEN (single correct attribution).

### Gates
`tsc --noEmit` clean · `npm run build` clean · full d4 vitest **76/76
pass** · oxlint **0 errors** (warnings pre-existing). Diff: driver +
test only (no repro_*/baseline).
2026-07-08 18:35:36 -07:00
Jordan Ritter 9d9056db60 fix(showcase-harness): propagate level errorDesc to aggregate signal + reorder abort short-circuit
The aggregate e2e-smoke:<slug> red signal omitted errorDesc on the normal
return path, so an abort/timeout/send-budget-exhausted red that runLevel
RETURNS (not throws) showed on the PRIMARY dashboard tick as an unclassified
content-shaped red — only the side chat:/tools: rows kept the classifier.
Thread the failing level's errorDesc (L3 precedence, L4 fallback) onto the
aggregate so the primary tick matches the side row and the launcher-phase
abort path. Does not change red/green — only carries the classifier.

Also reorder the aborted-and-empty short-circuit ABOVE the alternate-content
/ raw-byte evaluate reads: an aborted run's page is tearing down, so those
reads were swallowed against a dead page and emitted an ambiguous empty
histogram. Non-aborted runs still perform the alternate-content salvage.
2026-07-08 18:27:14 -07:00
Maxim 2dfedb0769 test(banking): fix stale smoke-test pill assertions 2026-07-09 02:54:43 +02:00
Maxim b041d998bf feat(banking): register OGUI on the provider, mount data-sync, add OGUI pills 2026-07-09 02:42:10 +02:00
Jordan Ritter 80bd9469c4 fix(showcase-harness): classify mid-poll abort/timeout empty as abort, not content-red
A mid-poll abort — the external ctx.abortSignal firing, or the driver's
own hard-timeout landing during the first-token poll — makes runAttempt
return empty WITHOUT throwing. The retry loop breaks and control falls to
the clean-exit path, where the level was misclassified as a generic
content red ("empty assistant response", probe.exit outcome "err", no
errorDesc). That masqueraded a teardown/abort/timeout as a CONTENT
failure on the dashboard + CVDIAG.

Add an aborted-AND-empty guard before the content-red gate that
short-circuits to the same abort classification the other paths use
(errorDesc "abort", probe.exit outcome "timeout"). Discriminator is
abortSignal.aborted, not emptiness alone: a genuinely-completed-empty
turn (not aborted) stays the content-red "empty assistant response".
2026-07-08 17:39:15 -07:00
Maxim c2f0b0f14b feat(banking): enable OGUI on both runtimes and fence it in the prompt 2026-07-09 02:11:12 +02:00
Jordan Ritter 13a636b670 fix(showcase-harness): harmonize d4 readTurnState error handling + first-send cap + null-header re-attribution
Harmonize the three readTurnState() consumers in the d4 chat-roundtrip probe
through one guarded safeReadTurnState() wrapper so a mid-poll readTurnState()
throw is handled consistently everywhere: it means "no reliable signal" ->
degraded widen + observable telemetry, never a silent false-red (the prior
readDegraded swallow) nor a spurious level-error (the prior unguarded
readBaseline/readTurnComplete escape). A genuinely-empty degraded turn still
reds at the ceiling.

Folds completing the PR's own items:
- item-1 first-send cap: guard the in-send press against SEND_PRESS_MIN_BUDGET_MS
  so a near-hang type can't floor press to ~1ms and produce a generic
  level-error; classify distinctly as send-budget-exhausted. Only press is
  guarded (type opens the envelope), so a legitimately-small pageTimeoutMs still
  issues a healthy first send.
- item-3 null-header: suppress the finally-block fallback probe.message.send once
  a real-header boundary already fired, so a retry whose winning resend lands no
  POST no longer emits a second null-header boundary (mis-attributed
  edge_interference_signal).

Also add "abort" to the errorDesc JSDoc enumeration (zero-risk).

Red-green covered for all three behavioral items against the real
runLevel/readTurnComplete path with a faithful fake.
2026-07-08 17:09:51 -07:00