Commit Graph

15424 Commits

Author SHA1 Message Date
David McKay ce0576d7d1 Merge branch 'main' into fix/useagent-threadid 2026-07-29 06:50:17 -07:00
Alem Tuzlak 62d1dc1619 fix(showcase/ms-agent-dotnet): ground declarative-gen-ui charts in sales data
Secondary A2UI design call (injectA2UITool:false path) never saw frontend
App Context, so PieChart/BarChart shipped with empty data arrays ("No data
available") and DataTables rendered blank rows while Metrics invented
placeholders.

Bake the Vantage Threads Q2 dataset + composition rules (from sales-context.ts)
and non-empty chart/table examples into DeclarativeGenUiDesignSystemPrompt.
Coerce string chart values to numbers. Tighten outer agent to not dump the
dashboard as prose.
2026-07-29 15:47:56 +02:00
Maxim 85223276fa fix(a2ui-renderer): stop the filterCatalog export test depending on its own dist
The export test self-imported the package by name:

  const mod = await import("@copilotkit/a2ui-renderer");

which resolves through node_modules to dist/. Nothing guarantees dist/ exists
when the test runs: nx.json sets test.dependsOn to ["^build"], and the caret
means *dependencies'* builds, not the project's own. Under `nx run-many` the
scheduler ran a2ui-renderer:test before a2ui-renderer:build, so the import
failed with "Failed to resolve entry for package @copilotkit/a2ui-renderer".
Standalone runs passed only because an earlier build had left dist/ populated.

Nx reported the task as flaky, which it was not — it was order-dependent. The
same root cause failed check-types, since tsc resolves the dynamic import to
dist/index.d.mts.

Importing the source entry instead keeps what the test is actually for (that
src/index.ts -> react-renderer/index.ts -> ./filter-catalog re-export chain is
intact, so callers can import filterCatalog) while making it hermetic. The
package.json "exports" mapping is already covered by this package's publint and
attw targets.

Verified with dist/ deleted: 16/16 pass and check-types is clean. Both
`nx run-many -t test` and `-t check-types` across core, react-core, runtime,
web-inspector and a2ui-renderer now pass with --skip-nx-cache.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-29 15:36:14 +02:00
github-actions[bot] 66b6d3fef3 style: auto-fix formatting 2026-07-29 13:33:01 +00:00
Alem Tuzlak 5c89395dc8 fix(showcase): unbreak gen-ui-agent and declarative-json-render on a real LLM
Two built-in-agent demos were broken against a real model while their D5/D6
rows stayed green, because aimock exercises neither failure. Both root causes
were confirmed against the live OpenAI API.

gen-ui-agent stopped mid-plan on every run. `@tanstack/ai`'s `chat()` applies
`maxIterations(5)` when no `agentLoopStrategy` is passed, and nothing errors
when the budget runs out — the run just ends. GEN_UI_AGENT_PROMPT scripts 7
`set_steps` calls (1 initial + in_progress/completed per step x 3) plus a
closing message, so the walk died two calls short with the last step pinned at
`pending` and no narration. Reproduced with the real model and the real prompt:

  default budget -> 5 calls, "completed, completed, pending", no message
  maxIterations(25) -> 7 calls, all completed, 333-char summary

Every demo factory now passes the shared DEMO_AGENT_LOOP_STRATEGY (25 —
several times the longest scripted walk, still bounded). The two non-streaming
tool-free `chat()` calls keep the default: they have no loop to exhaust.

declarative-json-render rendered nothing at all: RUN_STARTED -> RUN_FINISHED,
no events, no console error, no banner. `text.format: { type: "json_object" }`
has a server-side precondition that the word "json" appear in the request
`input`, but the adapter sends `systemPrompts` as `instructions` and only
`messages` as `input` — so with the JSON directive living solely in
SYSTEM_PROMPT the API rejected every run with

  400 Response input messages must contain the word 'json' in some form to
      use 'text.format' of type 'json_object'.   (param: input)

The directive now rides in `messages` (as `user`, since TanStackChatMessage
admits no `system` role and the runtime hoists system messages into
systemPrompts — the half that is not input). json_object enforcement is kept;
verified live that the run then streams a complete, JSON.parse-able spec.

That 400 was invisible because the hand-rolled converters forward a whitelist
of chunk types and dropped RUN_ERROR — every one except reasoning-factory. The
`type: "tanstack"` factories were fine (the runtime's converter rethrows), so
the four `type: "custom"` converters now call the shared throwOnRunError.

Also: the gen-ui-agent progress card announced "All N steps complete" whenever
the RUN ended, ignoring the step data, so a truncated run read as a UI glitch
instead of an agent that stopped early. The wording is now derived from the
steps (`describeProgress`, extracted pure so it is testable without a DOM) and
a stalled run says so.

Both gotchas recorded in showcase/GOTCHAS.md.
2026-07-29 15:30:37 +02:00
renovate[bot] 4875d6d1f2 chore(deps): update docker/login-action action to v4.6.0 2026-07-29 13:28:39 +00:00
Maxim fa40e0424b Merge remote-tracking branch 'origin/blitz/glass-inspector/integration' into blitz/glass-inspector/integration 2026-07-29 15:28:16 +02:00
Alem Tuzlak 7030ea7b0f fix(showcase): settle mcp-apps D5/D6 on the full iframe cascade (#6226)
## What does this PR do?

Fixes a fleet-wide false red on `mcp-apps` D5/D6: red on all 18
integrations that support the feature since `first_failure_at`
2026-07-28 23:03Z, while the demos rendered correctly by hand.

**Root cause.** The `completeOnMount` gate added in d70d48a561 named the
`mcp-app-iframe` testid, which only Angular's `copilot-mcp-apps-widget`
declares. `react-core` and `vue` build the sandbox iframe imperatively
(`document.createElement("iframe")`) with no testid, so the settle gate
could never be satisfied — every React/Vue integration timed the turn
out at 30s with `reason=surface-missing` and never reached
`assertIframePresent`, whose `iframe[sandbox]` fallback would have
passed. `crewai-crews` and `langroid` stayed green only because they
skip the feature (`errorClass: "skipped-incapable"`).

Verified against live staging (`showcase-built-in-agent-staging`, after
clicking the "Sketch a system diagram" pill):

```
oldGate_testIdOnly: 0     <- what the probe waited for
newGate_cascade:    1     <- the surface that was there all along
allIframes: [{ sandbox: "allow-scripts allow-same-origin allow-forms", testid: null, hasSrcdoc: true }]
```

**Fixed on both sides of the contract:**

1. **Product** — `react-core` and `vue` `MCPAppsActivityRenderer` now
set `data-testid="mcp-app-iframe"` and `title="Interactive MCP
application"` on the host-created iframe, matching Angular. Pinned by a
new test in each package, so dropping the attribute fails in the package
that owns it rather than silently reddening the fleet a day later.

2. **Harness** — `completeOnMount` accepts CSS `selectors` alongside
`testIds`, so the probe settles on the cascade its own module doc and
assertion already declare:

   ```ts
completeOnMount: { selectors: ['[data-testid="mcp-app-iframe"],
iframe[sandbox]'] }
   ```

`querySelectorAll` unions comma-separated branches, so one entry
expresses "any conforming form of this surface" while the
conjunctive-across-entries and `minNewMounts` delta semantics stay
exactly as before; `testIds: ["x"]` is now sugar for `selectors:
['[data-testid="x"]']`, so every other probe is untouched. This half
matters on its own: the integrations pin
`@copilotkit/react-core@1.61.2`, so a testid-only fix would leave 18
cells red until a release plus a fleet redeploy.

Also: a `completeOnMount` spec naming no surface now throws instead of
burning the whole turn budget and reporting a misleading
`surface-missing`. The trap is recorded in `showcase/GOTCHAS.md` next to
the sibling `copilot-assistant-message` testid gotcha.

## Verification

- harness `conversation-runner.test.ts` + `d5-mcp-apps.test.ts` —
101/101, including new red-green pairs: a `selectors` cascade greens, a
never-mounting cascade still reds `surface-missing`, a leftover-only
surface still reds, an empty spec fails loud
- `@copilotkit/vue` `MCPAppsActivityRenderer.test.ts` — 6/6
- `@copilotkit/react-core` `MCPAppsActivityRenderer.e2e.test.tsx` —
17/17
- `oxfmt` clean, `check-types` clean on both packages
- Pre-existing and unrelated (fail identically on an untouched worktree
on Windows): harness `typecheck` wants the gitignored generated
`showcase/shell/src/data/frontend-catalog.json`; 6 `src/probes` tests
assert POSIX path separators

## Related PRs and Issues

- Regressed by #6212-era commit d70d48a561 ("test(showcase): add
deterministic Angular parity audit")

## Checklist

- [x] I have read the Contribution Guide
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation (`showcase/GOTCHAS.md`)
- [x] "Allow edits by maintainers" is checked

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-29 15:27:16 +02:00
Maxim 1e575233e6 test(banking): make the memory-recall e2e approval loop actually completable
The approval loop could never pass, independent of the demo's behavior:

  for (let step = 0; step < 4; step++) {
    const approve = page.getByRole("button", { name: /^approve$/i });
    await approve.first().click({ timeout: 30_000 }).catch(...)
  }

Two compounding problems. The recall path emits at most three HITL cards
(openPolicyException -> finalizePolicyException -> approveTransaction) but the
loop demanded four, so the last iteration always waited on a card that never
arrives. And the per-click timeout (30s) equalled the whole test budget
(playwright.config.ts sets no `timeout`, so Playwright's 30s default applied),
so the first miss consumed the entire test and the `.catch()` fallback to the
other APPROVE_LABELS was unreachable dead code.

Now: poll every label for the next visible approve control, treat "no card
left" as flow completion rather than a timeout, keep a runaway guard that is
explicitly not the expected card count, and give the test a budget that can
actually hold one agent turn plus the closing server poll.

Confirmed against a local run (aimock + the docker Intelligence stack): the
agent recalls the procedure, files the EXC-BOARD-APPROVED exception, and
approves the charge, and the "Record a workflow?" card never appears. The
header's "verify on first green run" notes are updated to record what that
run settled and what it did not.

The spec still fails at its closing assertion: PUT /api/v1/transactions/t-3
{status:"approved"} keeps returning 422, i.e. store.hasApprovedException() is
false, so the over-limit gate is never lifted even though the (fixture-scripted)
agent text claims it was. That is pre-existing and out of scope here — this PR
touches no part of the approval path (lib/store, the exceptions/transactions
routes, copilot-context, components/wow are all untouched). Left failing rather
than skipped so it stays visible.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-29 15:27:08 +02:00
lukasmoschitz 20cb3ab3a6 fix(showcase): align langgraph-typescript to langgraph-python north star (#6196)
## Summary

Brings the **langgraph-typescript** showcase integration to D6 parity
with the north-star **langgraph-python** (OSS-583). The frontend + demo
set were already aligned; this PR fixes the behavior gaps so the D6 grid
is honest.

**Final local D6: 39/39 green** (all cells the north star wires),
verified serially from the harness worker logs. Two of the fixes were
genuine TypeScript-runtime bugs that aimock's scripted replay had masked
as "green".

## Fixes

| Cell | Root cause | Fix |
|---|---|---|
| gen-ui-open, gen-ui-open-advanced | stale `turnIndex:0` on leg-1
tool-call fixtures → turnIndex-relaxed re-serve loop
(`done-signal-missing`) | `turnIndex:0` → `hasToolResult:false` (mirror
LGP) |
| reasoning-display | `@langchain/openai@1.4.4` streaming Responses
converter collapses reasoning + answer to the same content-block index →
answer swallowed (`text-unstable`) | `disableStreaming:true` (forces the
non-streaming converter → separate blocks); documented streaming
trade-off in PARITY_NOTES |
| tool-rendering | langchain-js streamed-chunk reassembly leaves a
tool-call-with-content only under `additional_kwargs.tool_calls` →
`shouldContinue` routes to `__end__`, no card |
`normalizeAssistantMessage()` promotes it to a clean `AIMessage` |
| frontend-tools-async | stale bare `turnIndex:0` duplicate fixture →
re-emit loop | remove the stale fixture (same class is red on LGP too —
flagged) |
| a2ui-recovery | fixture prompt drift (still LGP's prompt) + inner
`render_a2ui` sub-agent invoked config-less so `x-test-id` isn't
forwarded → flaky heal | retarget prompt to the
langgraph-typescript-unique one + `wrapModelCall`/`wrapToolCall` + ALS
header forwarding (mirror mastra) |
| multimodal | `@ag-ui/langgraph` collapses every attachment to an
`image_url` data-URL; `rewritePart` had no `image_url` branch → a PDF
was forwarded as an image → OpenAI 400 | add an `image_url` branch
routing on the data-URL MIME (image → pass through; PDF → extract text
via `pdf-parse`), mirroring langgraph-python |

## Verification
- D6 run serially against aimock (real durations from
`showcase-harness-pool-worker-1`, not the CLI's "0.0s"); the two
previously-flaky cells (frontend-tools-async, a2ui-recovery) verified
with 4–6 consecutive green runs.
- multimodal PDF upload + the fixed cells confirmed live against real
OpenAI.

## Known items (documented in `showcase/GOTCHAS.md`, out of this PR's
scope)
- **mcp-apps Excalidraw** is a masked-green cell: `gpt-4o-mini` (kept,
D6-green) emits malformed Excalidraw `create_view` JSON live → black
canvas. `gpt-5.4` fixes it live but reds aimock D6, because the **TS
MCP-Apps middleware doesn't act on aimock's replayed responses-path
tool-call** (fixture is byte-identical to LGP; LGP's Python runtime
mounts the iframe). The real fix is a TS-runtime/`@copilotkit/runtime`
change + then gpt-5.4 — follow-up.
- **multimodal** needs the image built with `git lfs pull` (its sample
attachments are LFS-tracked and baked, not mounted); a build without LFS
ships pointers and reds it. Build-layer follow-up.
- **frontend-tools-async** stale fixture is fleet-wide — the same
deletion is needed on langgraph-python (its D6 is red for the same
reason).

## Scope
Only `integrations/langgraph-typescript/`, its aimock fixtures, and
`showcase/GOTCHAS.md`. langgraph-python (the north star) was not
touched.
2026-07-29 14:57:04 +02:00
Tyler Slaton a130dfc430 fix: remove all changesets (#6230)
Recently we made a few commits that let in some changesets. As a result,
agents now frequently try to add them to every change that gets made to
CopilotKit. Likely this was just an old branch and review didn't catch
them getting merged in.

Immediate remediation is to just remove the folder and make this commit
message so future agents can find the decision in commit history.
2026-07-29 05:48:20 -07:00
Lukas Moschitz 3f0a7bda05 fix(showcase/lgt): copy manifest.yaml into runtime image
The x-pathname middleware added in this branch activates layout.tsx's
request-time readFileSync(cwd/manifest.yaml) in generateMetadata. Without
the manifest in the runner stage, every /demos page 500s with ENOENT once
middleware sets the header. Mirrors langgraph-python's Dockerfile and
satisfies scripts/__tests__/runtime-manifest-copy.test.ts.
2026-07-29 14:46:50 +02:00
Tyler Slaton 1e5ba689e0 fix: remove all changesets
Recently we made a few commits that let in some changesets.
As a result, agents now frequently try to add them to every
change that gets made to CopilotKit. Likely this was just an
old branch and review didn't catch them getting merged in.

Immediate remmediation is to just remove the folder and make
this commit message so future agents can find the decision
in commit history.

Signed-off-by: Tyler Slaton <tyler@copilotkit.ai>
2026-07-29 08:46:22 -04:00
Lukas Moschitz f1513e3554 docs(showcase/lgt): fix reasoning-agent fallback-model comment (gpt-5-mini) 2026-07-29 14:34:19 +02:00
Lukas Moschitz 3100b3ea80 docs(showcase/lgt): fix recovery-agent ALS-store comment (wrapModelCall, not beforeAgent) 2026-07-29 14:34:19 +02:00
Lukas Moschitz aa685b3957 fix(showcase/lgt): stop mcp-apps route leaking error message/stack to client
The mcp-apps POST catch block returned the raw error message and stack
to the client and logged nothing server-side, leaking internal paths and
library versions to anyone who could hit /api/copilotkit-mcp-apps. Mirror
the sibling copilotkit/route.ts hardening: log full details server-side
under a randomUUID correlation id and return only the id plus a generic
message with status 500.
2026-07-29 14:34:19 +02:00
Lukas Moschitz b1838b9de6 fix(showcase/lgt): add x-pathname middleware for per-demo titles (LGP parity) 2026-07-29 14:34:19 +02:00
github-actions[bot] 12ff61f74b style: auto-fix formatting 2026-07-29 11:40:41 +00:00
Lukas Moschitz 8f6123a5ec Merge remote-tracking branch 'origin/main' into lukas/oss-583-align-langgraph-typescript-showcase-demos-and-code
# Conflicts:
#	showcase/GOTCHAS.md
2026-07-29 13:38:42 +02:00
Lukas Moschitz 5683528f09 docs(showcase): document mcp-apps Excalidraw masked-green (gpt-4o-mini vs gpt-5.4)
mcp-apps is aimock-green but live-degraded: gpt-4o-mini emits malformed Excalidraw
create_view elements JSON (stray trailing }) -> MCP JSON.parse fails -> black
canvas live. gpt-5.4 fixes it live but reds aimock D6 because the TS MCP-Apps
middleware doesn't act on aimock's REPLAYED responses-path create_view tool call
(never mounts the iframe; fixture is byte-identical to LGP, LGP's Python runtime
mounts it — so TS-runtime-specific, not a fixture issue). Kept gpt-4o-mini to hold
D6 green; the real fix is a TS MCP-Apps-middleware/@copilotkit runtime change +
then gpt-5.4. Flagged as follow-up.
2026-07-29 13:30:15 +02:00
Lukas Moschitz 72ad5396c7 fix(showcase): langgraph-typescript multimodal handles PDF attachments (no 400)
The @ag-ui/langgraph converter collapses EVERY attachment (image and document)
into a LangChain image_url data-URL, so a PDF reached rewritePart as an
image_url part and hit neither the image nor document branch -> passed through
unchanged -> sent to gpt-4o as an image -> OpenAI 400 'Invalid MIME type. Only
image types are supported.' (The existing document-branch pdf-parse code was
dead — the part never arrives as 'document'.)

Add an image_url branch to rewritePart that routes on the data-URL MIME (mirrors
langgraph-python's multimodal_agent): image/* passes through unchanged; any
non-image (application/pdf) is flattened to text via the existing pdf-parse path
instead of being forwarded as an image. Source-only, no dep/model change.

multimodal D6 still green (PNG path unchanged); PDF upload verified live (text
extracted, no 400).
2026-07-29 13:30:15 +02:00
Alem Tuzlak ef7eae5136 fix(showcase/ms-agent-dotnet): Instructions wiring + hashbrown/json-render/gen-ui/state demos (#6227)
## Summary

Fixes more **ms-agent-dotnet** (Agent Framework) staging failures
against a real LLM.

### Root cause (load-bearing)

`ChatClientAgent` ctor is `(chatClient, instructions, name, description,
tools, …)`.

Almost every agent in this integration passed the system prompt as
**`description:`** (metadata only). The model received **null
instructions**, so:

| Demo | Symptom |
|------|---------|
| shared-state-read-write | Pills appear to do nothing / no set_notes |
| declarative-hashbrown | Empty — frontend JSON parser rejects prose |
| declarative-json-render | Wall of text instead of rendered UI |
| declarative-gen-ui | Wall of text + invented `DashboardCard` on later
pills |

### Fixes

1. **Global**: `description:` → `instructions:` for every
ChatClientAgent system prompt in `ms-agent-dotnet/agent`.
2. **Hashbrown + json-render**: also set `ChatResponseFormat.Json` (same
contract as langgraph-python's `response_format=json_object`).
3. **declarative-gen-ui**: catalog-specific secondary design prompt
(Card, not DashboardCard/FlightCard) + stricter outer agent (always call
`generate_a2ui`, one short sentence).
4. **shared-state-streaming**: add feature to `manifest.yaml`
`features:` so the shell no longer shows **Backend fixture unavailable**
for a demo that is already wired end-to-end.

### shared-state-streaming note

You *were* supposed to be able to open that link if the feature is
supported — the page existed under `demos/` but was missing from
`features:`, so the shell treated it as a non-runnable cell. That is
fixed. (D6 fixture content for this slug is still thin vs LGP; live LLM
path is the product path.)

## Test plan

- [x] `dotnet test` SharedStateAgent.Tests 79/79 (Docker SDK 9)
- [ ] Staging after deploy:
- [ ] `/react/ms-agent-dotnet/shared-state-read-write/preview` — all
three pills respond; Remember something updates notes
- [ ] `/react/ms-agent-dotnet/shared-state-streaming/preview` — cell
loads (not fixture-unavailable); document streams
- [ ] `/react/ms-agent-dotnet/declarative-hashbrown/preview` — pills
paint metrics/charts
- [ ] `/react/ms-agent-dotnet/declarative-json-render/preview` — pills
paint MetricCard/charts not raw text
- [ ] `/react/ms-agent-dotnet/declarative-gen-ui/preview` — all four
pills paint A2UI without DashboardCard error / wall of text
2026-07-29 13:08:06 +02:00
Alem Tuzlak f57151990f fix(showcase/ms-agent-dotnet): wire system prompts to Instructions + demo repairs
Root cause across nearly every ChatClientAgent: system prompts were passed as
`description:` (agent metadata) instead of `instructions:` (the actual system
message). ChatClientAgent(instructions, name, description, …) therefore ran
with null instructions, so models ignored tool guidance and BYOC JSON demos
emitted prose.

Fixes reported staging failures:
- shared-state-read-write pills: instructions now reach the model + stronger set_notes guidance
- declarative-hashbrown / declarative-json-render: instructions + ChatResponseFormat.Json (LGP parity)
- declarative-gen-ui: catalog-specific design prompt (no DashboardCard), stronger outer agent
- shared-state-streaming: feature was demo-only in the manifest → shell "Backend fixture unavailable"; added to features

Verified: unit suite 79/79 in Docker SDK 9.
2026-07-29 13:00:08 +02:00
Alem Tuzlak 9d8916a9d9 fix(showcase): settle mcp-apps D5/D6 on the full iframe cascade
The `completeOnMount` gate added in d70d48a561 named the `mcp-app-iframe`
testid, which only Angular's `copilot-mcp-apps-widget` declared. react-core
and vue build the sandbox iframe imperatively with no testid, so every
React/Vue integration timed the turn out at 30s with
`reason=surface-missing` and never reached `assertIframePresent` — whose
`iframe[sandbox]` fallback would have passed. D5 + D6 `mcp-apps` went red on
all 18 integrations that support the feature (first_failure_at 2026-07-28
23:03Z) while the demos rendered correctly by hand.

Fixed on both sides of the contract:

- react-core and vue now set `data-testid="mcp-app-iframe"` and a `title` on
  the host-created iframe, matching Angular. Pinned by a test in each package.
- `completeOnMount` accepts CSS `selectors` alongside `testIds`, so the probe
  settles on the same cascade its module doc and assertion already use
  (`[data-testid="mcp-app-iframe"], iframe[sandbox]`). A comma-joined entry is
  one conjunctive surface whose branches `querySelectorAll` unions, so the
  delta/`minNewMounts` semantics are unchanged and `testIds` is now sugar for
  the equivalent selector. This half greens the fleet on the next sweep
  without waiting for a package release, since the integrations pin
  @copilotkit/react-core 1.61.2.

A spec naming no surface now throws instead of burning the turn budget and
reporting a misleading `surface-missing`.

Verified against live staging: after clicking the pill, the old gate matched
0 elements and the cascade matched 1 (the sandboxed iframe was there all
along). Also recorded in showcase/GOTCHAS.md.
2026-07-29 12:34:38 +02:00
Alem Tuzlak 75fc766fff fix(showcase): repair ms-agent .NET real-LLM demo defects (#6224)
## Summary

Fixes staging click-through failures on **ms-agent-dotnet** and
**ms-agent-harness-dotnet** demos. Same class of bug as #6200 (GOTCHAS
#8): aimock D6 was green while real LLMs failed.

### Root causes & fixes

| Demo | Symptom | Fix |
|------|---------|-----|
| beautiful-chat Sales Dashboard | `Catalog not found: sales_dashboard`
| Force page-registered `catalogId`; stronger secondary design prompt |
| declarative-gen-ui KPI / pie / bar / status | Loader never resolves;
`without a type`; `SummaryCard` missing `id` | Sanitize + normalize flat
A2UI components; drop invalid entries; force
`declarative-gen-ui-catalog` |
| shared-state-read-write Remember something | Notes panel never updates
| AsyncLocal store write misses (tool EC); mirror writes + read
fallback; wire dead deterministic reply path for the pill |
| subagents left panel | Chat works, side UI empty | Same AsyncLocal
store bug for `state.delegations` |
| open-gen-ui-advanced calculator / ping host | Form/input calculator;
ping no-ops | System prompt for clickable keypad + `notifyHost` /
`evaluateExpression` wiring |
| beautiful-chat calculator | Buttons do nothing | OGUI guidance:
`type=button`, no `form`, click handlers |

### Voice auth error

Not a code defect in the voice route:
`GuardedOpenAITranscriptionService` correctly fails when
`OPENAI_API_KEY` is missing on the **Next.js** process. Staging needs
that env var on the showcase frontend service (transcription hits real
OpenAI, not aimock).

### MCP Excalidraw empty iframe

Left as follow-up — likely external MCP host / sandbox CSP; no
agent-side bug found in wiring.

## Test plan

- [x] `dotnet test` ms-agent-dotnet (79/79) in Docker SDK 9 — includes
new A2UI force-catalog / type-as-key / drop-invalid tests
- [x] harness agent build + cvdiag tests (5/5)
- [ ] Staging click-through after deploy:
- [ ] `/react/ms-agent-dotnet/beautiful-chat` — Sales Dashboard paints;
calculator interactive
- [ ] `/react/ms-agent-harness-dotnet/declarative-gen-ui` — all four
pills paint without A2UI errors
- [ ] `/react/ms-agent-harness-dotnet/shared-state-read-write` —
Remember something updates notes
- [ ] `/react/ms-agent-harness-dotnet/subagents` — left panel shows
running/completed delegations
- [ ] `/react/ms-agent-harness-dotnet/open-gen-ui-advanced` — calculator
keypad + ping host
- [ ] Voice: confirm `OPENAI_API_KEY` present on staging frontend, then
mic works
2026-07-29 11:51:26 +02:00
Alem Tuzlak f58d24109a fix(showcase): repair ms-agent .NET real-LLM demo defects
Staging click-through on ms-agent-dotnet / ms-agent-harness-dotnet hit
several GOTCHAS #8 defects: aimock D6 was green while live LLMs failed.

A2UI (beautiful-chat sales dashboard, declarative-gen-ui pills):
- Force the page-registered catalogId (models invent "sales_dashboard").
- Sanitize/normalize flat components; salvage type-as-key nests; drop
  entries missing id/component (SummaryCard without id, charts without type).
- Strengthen secondary design prompts with the flat catalog contract.

Shared state + subagents side panels:
- Tool invocation drops AsyncLocal set by SetActiveThread, so writes landed
  in the global slot while snapshots keyed by AgentSession/AgentThread.
  Mirror writes and fall back on read (same pattern as D5ParityAgents).
- Wire the dead TryBuildDeterministicReply path for the "Remember something"
  pill so notes update without relying on the model calling set_notes.

Open generative UI advanced + beautiful-chat calculator:
- Prompt for clickable keypad (not form/submit) and notifyHost ping wiring.

Verified: ms-agent-dotnet unit suite 79/79 green in Docker SDK 9; harness
agent builds clean and cvdiag tests 5/5.
2026-07-29 11:42:32 +02:00
Markus Ecker 4cbca9ebe5 docs(react-core): document useAgent threadId and runtimeAgentId
The reference page's Parameters section covered only `agentId` and `updates`, so
both props this branch adds were undocumented.

Adds an entry for each, and notes on `agentId` that passing `runtimeAgentId`
makes it required and turns it into a name the hook registers an agent under
rather than one it retrieves.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 11:27:57 +02:00
Markus Ecker acdd9a9ef5 fix(react-core): enforce useAgent thread-scoping props at the type level
UseAgentProps left `agentId`, `runtimeAgentId`, and `threadId` independently
optional, so every unsafe or pointless combination compiled and only
`threadId`-without-`runtimeAgentId` was caught — at runtime, on render. Given
the bug this branch fixes was a silently-ignored `threadId` prop, the type is
where it should have been caught.

Split UseAgentProps into a base plus a two-branch union so exactly two shapes
are valid:

  useAgent()                                       // shared agent
  useAgent({ agentId })                            // shared agent
  useAgent({ agentId, runtimeAgentId, threadId })  // private agent, pinned thread

Every partial combination is now a compile error, each for its own reason.
`threadId` alone would scope a thread onto a shared singleton (the original
review finding). `runtimeAgentId` without `threadId` registers a private agent
that behaves like the shared one, minus nothing but a registration and a local
id to keep unique. And without an explicit `agentId`, the proxy registers under
the chat configuration's agentId or DEFAULT_AGENT_ID — ids that already belong
to real agents — which either throws `already registered` or silently shadows
one, depending on whether runtime discovery has landed.

The runtime throws stay as backstops for callers TypeScript doesn't cover (plain
JS, `as any`, props widened to `string | undefined` at a call boundary), and now
cover all three cases, each failing before any registration happens.

Adds use-agent-types.test.tsx pinning the compile-time half of the contract
across the accept/reject matrix, plus contract tests for the two new throws. The
`@ts-expect-error` on each deliberately-bad call doubles as an assertion that the
type still rejects it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 11:27:17 +02:00
Lukas Moschitz fda8743dd5 docs(showcase): GOTCHAS — langgraph-typescript streaming/LFS edge cases + fleet follow-ups
Record the durable findings from OSS-583:
- langgraph-typescript per-framework notes: langchain-js streaming-reassembly bugs
  (reasoning index-collision -> disableStreaming; tool-call+content reassembly ->
  normalizeAssistantMessage), a2ui-recovery inner-render header forwarding via
  ALS/wrapToolCall (mirrors mastra), and multimodal's LFS-asset build requirement.
- 'What Was Green But Still Wrong' #8: single-pass sweeps hide flaky cells and
  aimock-green can mask a real backend bug -> re-run for stability + verify the
  right graph runs.
- Known fleet-wide follow-ups: the frontend-tools-async stale turnIndex fixture
  reds the north star too (needs the same deletion in langgraph-python); image
  builds must git lfs pull so multimodal ships real assets not LFS pointers.
2026-07-29 09:42:41 +02:00
Tyler Slaton c5d0881380 Merge remote-tracking branch 'origin/main' into agent/oss-615-channel-docs 2026-07-28 23:30:25 -04:00
Tyler Slaton 1c87fe9b79 docs: expand Channels guides and API reference 2026-07-28 23:30:15 -04:00
Tyler Slaton cc825c7c99 chore: release monorepo v1.64.1 (#6214)
## Release monorepo v1.64.1

**Scope:** `monorepo` | **Bump:** `patch`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.64.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 `monorepo` packages to npm at version `1.64.1`
   - Creates git tag `monorepo/v1.64.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.
v1.64.1
2026-07-28 18:53:06 -07:00
Tyler Slaton e711ff8e00 docs(channels): restore global reference 2026-07-28 21:03:55 -04:00
tylerslaton 028a5adc9d chore: release monorepo v1.64.1 2026-07-28 17:48:23 -07:00
Mark 6294579fbc chore(examples): bump ADK starters to ag-ui-adk==0.7.0 for A2UI support 2026-07-29 00:25:04 +00:00
Tyler Slaton 968f7bf497 Merge branch 'main' into agent/oss-615-channel-docs 2026-07-28 17:17:59 -07:00
Martha Kelly Schumann 501e899559 docs(voice): clarify Google ADK voice route setup (#6215)
Fixes FAC-61.

## Summary
- Documents the full Google ADK voice runtime route path:
`app/api/copilotkit-voice/[[...slug]]/route.ts`.
- Explains how browser calls to `/api/copilotkit-voice` map through the
Next.js runtime to the ADK backend `/voice` endpoint.
- Keeps the ADK-specific backend paragraph gated to integrations that
declare `voice_backend_pattern: adk-fastapi-agent-path`, so other
framework voice pages do not show Google ADK prose.
- Replaces the docs `voice-page` snippet with a minimal `CopilotKit` +
`CopilotChat` example so the docs no longer show the live demo-only
`VoiceChat` wrapper as copy-paste app code.
- Normalizes docs-only `*.snippet.*` caption display so
`page.snippet.tsx` renders as `page.tsx` while still remaining a
docs-only extraction file.
- Corrects the sample-audio button prose to match the actual
implementation: the button emits canned text through `onTranscribed`,
and the parent chat component performs the textarea insertion.

## Acceptance Evidence
- Full route path: `voice.mdx` names
`app/api/copilotkit-voice/[[...slug]]/route.ts`.
- Backend endpoint: `voice.mdx` explains that `voice-demo` is registered
with `HttpAgent` at `${AGENT_URL}/voice`, and that the Python ADK server
mounts agents at `path=f"/{agent_name}"`.
- Framework scoping: the ADK backend paragraph is wrapped in
`<WhenFrameworkHas flag="voice_backend_pattern"
equals="adk-fastapi-agent-path">`; only the Google ADK manifest declares
that value.
- No undefined docs component: the extracted `voice-page` region lives
in `page.snippet.tsx` and imports `CopilotChat` and `CopilotKit` from
`@copilotkit/react-core/v2`; the rendered caption is normalized to
`page.tsx`; the live route still uses `VoiceChat` outside the docs
region.
- Source inference removed: the page explicitly connects `runtimeUrl`,
`basePath`, catch-all runtime routes, and the backend `/voice` hop in
prose.

## Validation
- `git diff --check`
- `pnpm -C showcase/scripts validate-manifests`
- `pnpm -C showcase/scripts bundle-content`
- `npm run typecheck` in `showcase/shell-docs`
- `npm run lint` in `showcase/shell-docs`
- `npm run build` in `showcase/shell-docs`
2026-07-28 16:48:57 -07:00
copilotkit-qa-bot f150c89bdf Merge remote-tracking branch 'origin/main' into qa-factory/fac-61-20260728152034 2026-07-28 16:40:46 -07:00
Ben Taylor a76c2bcce2 feat(channels-intelligence): measure render-frame push latency (refs OSS-648) (#6212)
## What this is now

Opt-in instrumentation for the channel egress path, plus a
replay-stability guard. **Measurement and safety only — no behaviour
change to how frames are sent.**

It started as a fix too. That fix is reverted here; see below.

## The problem it measures

A streaming reply pushes one render frame per AG-UI token and awaits
each durable acceptance receipt before sending the next, so reply
latency scales with token count. Nothing recorded that, so the cost was
invisible and got attributed to the Connector Outbox's 400ms poll
instead.

```bash
COPILOTKIT_CHANNELS_RENDER_METRICS=summary   # one summary per turn
COPILOTKIT_CHANNELS_RENDER_METRICS=frames    # also one line per frame
```

Unset means off and no collector is allocated. Output goes to the
transport `log` callback when configured, else the console.

## What it found, measured against production

Hosted api + realtime gateway, local runtime, fixture agent emitting
exactly 120 deltas 15ms apart:

```
pushMsMean: 478.43   pushMsP50: 463   pushMsP95: 589   pushBlockedPct: 99.67
```

**478ms per round trip against an ~85ms network RTT**, so roughly 390ms
of every push is server-side work — the `lookupClerkOrgId` query, the
off-cluster ops-api entitlement call, the read-model build, and the
Redis publish. Intelligence#627 removes those for `text_delta` frames.

At 478ms a push, a 120-token reply costs ~123 round trips ≈ **59s**.
That matches the original "sometimes many seconds" report.

## Why the fix was reverted

Coalescing adjacent text deltas worked — 123 frames to 4, a production
turn from ~59s to 3.4s — and broke replay.

A turn's id is a pure function of its delivery id (`turn_<deliveryId>`,
enforced by app-api) and the adapter resets the per-turn seq counter on
every dispatch, so a redelivery replays into the **same seq space**.
app-api treats that space as an idempotency key: same payload at a seq
is `duplicate_accepted`, a different payload is
`CHANNEL_RENDER_FRAME_CONFLICT`, which nacks the delivery. Merge
boundaries depend on wall-clock arrival, so a replay cuts them
differently:

| | attempt 1 (slow, merged) | attempt 2 (redelivery, faster) |
|---|---|---|
| seq 1–3 | *merged away, never pushed* | `"a"`, `"b"`, `"c"` → INSERT ✓
|
| seq 4 | `text_delta "abcd"` | `text_delta "d"` → **CONFLICT** ✗ |

Before coalescing, deltas were 1:1 with AG-UI events and a replay was
byte-identical. I verified both directions: the new test passes on the
pre-coalescing adapter and fails with coalescing. The regression was
mine.

`render-frame-replay.test.ts` stays as a standing guard — it passes with
frames 1:1 and fails for any change that makes a frame's payload at a
given seq depend on timing.

## The replacement

Batch the **transport**, don't merge frame **content**: send the
buffered frames as an array in one request. Same collapse in round
trips, `seq k` still carries `delta k` so replay stays byte-identical,
and seqs stay dense so the outbox can later require contiguity
(OSS-653).

That needs an app-api batch accept and a gateway envelope, so it ships
after launch with its own deploy ordering (app-api → gateway → SDK)
rather than two days before.

## Also found, filed separately

OSS-653 — the outbox advances an in-memory cursor to the highest seq it
read (`WHERE seq > cursor ORDER BY seq ASC`), so a frame accepted out of
order is skipped and never rendered. Pre-existing and independent of
this PR. Not durable corruption: thread history is rebuilt from all
acceptance rows ordered by seq, independent of that cursor, so threads
read back complete.

## Validation

```
nx run-many -t test check-types build --projects=@copilotkit/channels-intelligence --skip-nx-cache
```

216 tests pass (12 files), check-types and build clean, `oxlint` clean
on all changed files.

refs OSS-648
2026-07-28 18:39:41 -05:00
copilotkit-qa-bot de57eea2b4 docs: normalize snippet caption filenames 2026-07-28 16:25:38 -07:00
Tyler Slaton e4d042cce2 Merge remote-tracking branch 'origin/main' into agent/oss-615-channel-docs 2026-07-28 19:23:35 -04:00
Tyler Slaton 89e13ac9a0 docs(channels): address review feedback 2026-07-28 19:23:12 -04:00
Benjamin Taylor 7845578550 docs(channels-intelligence): correct replay-test comments after the coalescing revert (refs OSS-648) 2026-07-28 18:17:16 -05:00
Benjamin Taylor 28ee17159d revert(channels-intelligence): drop frame coalescing, keep frames 1:1 with tokens (refs OSS-648)
Coalescing adjacent text deltas cut a 120-token reply from 123 frames to 4 and
took a production turn from an extrapolated ~59s to 3.4s, but it broke replay.

A turn's id is a pure function of its delivery id (turn_<deliveryId>, which
app-api enforces) and the adapter resets the per-turn seq counter on every
dispatch, so a redelivery replays into the same seq space. app-api treats that
space as an idempotency key: the same payload at a given seq is
duplicate_accepted, a different payload is CHANNEL_RENDER_FRAME_CONFLICT, which
nacks the delivery. Merge boundaries depend on wall-clock arrival, so a replay
cuts them differently and collides — attempt 1 stores "abcd" at seq 4, attempt 2
pushes "d" there. Before coalescing, deltas were 1:1 with AG-UI events and a
replay was byte-identical, so this worked; the regression is mine.

Keep the instrumentation, which is what found the problem and is what will
measure the replacement. Add the replay-stability test as a standing guard: it
passes with frames 1:1 and fails for any change that makes a frame's payload at a
given seq depend on timing.

The cost problem is real and unfixed. The replacement is to batch the TRANSPORT
(many frames per request) rather than merge frame CONTENT: it collapses the same
number of round trips, keeps seq k carrying delta k so replay stays
byte-identical, and keeps seqs dense so the outbox can later require contiguity
(OSS-653). That needs an app-api batch accept and a gateway envelope, so it ships
after launch with its own deploy ordering rather than two days before.
2026-07-28 18:16:45 -05:00
Benjamin Taylor 108f42d294 fix(web-inspector): keep the banner impression queue and stop guessing open segmentation
Both blockers from the third review.

**1. `banner_viewed` lost its pre-handshake queue.** On `main`,
`fetchAnnouncement()` stored `pendingBannerViewed` and the flush waited for
`connected`, discarding the event when the runtime reported `telemetryDisabled`.
Removing the deferral in the previous commit made the impression post directly,
so it now went out on the `false` placeholder that `telemetryDisabled` reads
before /info answers. That is a regression this PR introduced for an existing
event, distinct from the pre-existing `banner_clicked` race. The queue is
restored — widened from a single slot to a bounded array, since opening the panel
reveals the second surface and can happen before the first impression flushes —
and per-surface dedup is unchanged.

**2. `opened` recorded segmentation it could not know.** `licenseStatus` is
undefined and `runtimeMode` reads its `sse` default before the handshake
(`agent-registry.ts:77`), so an early open against an Intelligence runtime was
permanently filed as SSE. Rather than queue the open — a disconnected runtime
should not suppress a real user's open — `license_status` and `runtime_mode` are
now omitted unless the handshake has landed. An absent dimension is honest; a
wrong one corrupts the segmentation OSS-566 exists to provide. `runtime_url_type`
is config-derived and stays, since it is accurate immediately.

Also fixes a test that passed for the wrong reason: `HeaderMockCore` had no
`runtimeMode` at all, so a pre-handshake assertion about it read `undefined`
either way and would have gone green against the very bug it was meant to catch.
The mock now mirrors the real pre-handshake state (`runtimeMode: "sse"`,
`licenseStatus` absent). With that corrected, 3 of the 4 new cases fail against
the previous commit; the fourth guards the connected path.

Coverage: impression held then dropped on disabled, held then released on
allowed, open before the handshake omits both fields while keeping
`runtime_url_type`, and an open against a connected Intelligence runtime carries
`runtime_mode: intelligence` + `license_status: valid`.

Verified: web-inspector 115 passed, tsc clean, tsdown clean, oxfmt clean, oxlint
9 warnings all pre-existing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 18:11:13 -05:00
copilotkit-qa-bot 3efed933e6 docs(voice): address FAC-61 review feedback 2026-07-28 16:10:07 -07:00
Adrien Pouligny 5d86418d18 Merge branch 'main' into fix/runtime-deprecated-uuid-dependency 2026-07-28 16:03:02 -07:00
Mike Ryan cc71cdaad9 fix(showcase): restore Angular runtime parity (#6139)
## Summary

Restores Angular Showcase parity with the current React feature
contracts and makes the paired browser audit distinguish Angular
regressions from failures shared by both frontends.

The Angular host is still one shared application. Agent frameworks can
differ behind the runtime boundary, but BuiltInAgent no longer needs
frontend-only route or default-agent fallbacks: its current demos expose
the same named runtime and agent contracts used by React.

## What changed

### Angular runtime parity

- align BuiltInAgent runtime routes and named agent IDs with the current
React demos
- remove stale BuiltIn-only route, agent, reasoning, and interrupt
branches
- configure dynamically created chats with their agent and thread before
component construction, preventing the transient `default` agent lookup
against named-only runtimes
- preserve the remaining integration-specific behavior only where the
backend interaction contract genuinely differs
- preserve currency values in assistant messages without breaking inline
KaTeX rendering
- align Angular A2UI row and column schemas with the shared layout
contract
- expose authoritative running state and prevent an unnecessary
follow-up run in the complete headless demo
- reset interrupt selection state between repeated turns

### Audit and probe hardening

- merge exact-cell shard artifacts and validate source, fixture, and
feature-contract identity
- classify paired results as passed, Angular regression, shared failure,
Angular improvement, React-only, identity mismatch, or missing
counterpart
- make Angular-only failures, identity drift, and missing counterparts
blocking while keeping shared failures visible
- use rendered-surface completion for tool-rendered probes while
retaining lifecycle gates
- avoid duplicate or empty submissions in the headless-simple probe
- require interrupt resolution and resumed-run completion before
advancing
- use turn-scoped assistant content where narration is an accepted
shared contract
- add focused regression tests for Angular bindings, dynamic component
creation, matrix lifecycle handling, parity classification, and
representative probes

No new CI workflow is added by this PR.

## Scope of the parity claim

The audit proves the narrower parity condition: Angular has no failure
in a cell where React passes at the same source revision. Shared
React/Angular failures remain reported but are non-blocking, so this
does not claim that every supported cell is green.

## Validation

Final rebased head: `aeb503c37` on `d80cc9244` (`main`).

Current-head local validation:

- `pnpm nx run @copilotkit/showcase-scripts:test --skip-nx-cache
--output-style=static` — 74 files, 2,366 tests passed
- `pnpm nx run @copilotkit/showcase-harness:test:ci --skip-nx-cache
--output-style=static` — 175 files passed, 2 skipped; 3,672 tests
passed, 18 skipped
- `pnpm nx run @copilotkit/showcase-harness:test:quarantine-ratchet
--skip-nx-cache --output-style=static` — passed
- `pnpm nx run @copilotkit/showcase-harness:typecheck --skip-nx-cache
--output-style=static` — passed
- `pnpm nx run @copilotkit/angular:check-types --skip-nx-cache
--output-style=static` — passed with dependencies
- `pnpm nx run-many --targets=typecheck,test,build
--projects=@copilotkit/showcase-angular-host --parallel=1
--skip-nx-cache --output-style=static` — passed; 20 Angular files and
168 tests passed
- Angular browser build passed its performance-budget and artifact
audits

Focused BuiltInAgent regression rerun at the equivalent pre-rebase
implementation head `b9d51551c`:

- all six previously deterministic Angular failures passed: auth,
multimodal, agent-config, voice, shared-state-read, and
a2ui-fixed-schema
- 68 exact React/Angular cells classified into 35 feature comparisons
- 25 paired passes
- 7 shared failures
- 1 Angular improvement
- 2 React-only cells
- zero Angular regressions
- zero identity mismatches
- zero missing counterparts

The earlier exhaustive browser audit also passed in [GitHub
Actions](https://github.com/CopilotKit/CopilotKit/actions/runs/30065131330):

- 1,296 exact cells: 660 React and 636 Angular
- 497 paired passes
- 46 Angular improvements
- 93 shared failures
- 24 React-only cells
- zero Angular regressions, identity mismatches, or missing counterparts
2026-07-28 15:43:17 -07:00
copilotkit-qa-bot 0db84764dd docs(voice): clarify Google ADK voice route setup 2026-07-28 15:29:51 -07:00
Mike Ryan aeb503c377 fix(showcase): configure dynamic chats before construction 2026-07-28 15:25:17 -07:00