Commit Graph

4104 Commits

Author SHA1 Message Date
github-actions[bot] b624a987a3 style: auto-fix formatting 2026-06-24 19:30:30 +00:00
Atai Barkai 2d4cfb4846 test(showcase): reconcile default catch-all probe checks 2026-06-24 12:26:42 -07:00
Atai Barkai 3c3b251a5b test(showcase): tighten PR tour recordings 2026-06-24 12:20:42 -07:00
Atai Barkai f0f3b1f21f fix(showcase): assert interactive PR tour recordings 2026-06-24 12:20:41 -07:00
Atai Barkai 6a45b1e864 fix(showcase): require interactive PR tour recordings 2026-06-24 12:20:41 -07:00
Atai Barkai 3e463d4ef1 fix(showcase): tolerate noninteractive tour previews 2026-06-24 12:20:41 -07:00
Atai Barkai 45854c4cde chore(showcase): add PR tour video recorder 2026-06-24 12:20:40 -07:00
Atai Barkai c47269b1be chore(showcase): add PR tour row filtering 2026-06-24 12:20:40 -07:00
Atai Barkai 2fa1aa68ad fix(showcase): align langgraph fastapi tool rendering backend 2026-06-24 12:20:40 -07:00
github-actions[bot] eaa7265351 style: auto-fix formatting 2026-06-24 12:20:40 -07:00
Atai Barkai f82e1125ac fix(showcase): stabilize ag2 tool rendering demos 2026-06-24 12:20:40 -07:00
Atai Barkai f92c047ba9 test(showcase): disambiguate tool rendering fixtures 2026-06-24 12:20:39 -07:00
Atai Barkai 3226604990 chore(docs): drop unrelated formatting churn 2026-06-24 12:20:39 -07:00
github-actions[bot] 6d507c3957 style: auto-fix formatting 2026-06-24 12:20:39 -07:00
Atai Barkai bc18011da1 docs(shell-docs): fix catch-all highlight ranges 2026-06-24 12:20:39 -07:00
Atai Barkai 8b78ca2911 docs(showcase): cover catch-all renderer variants 2026-06-24 12:20:06 -07:00
Atai Barkai c20a2fcc57 test(showcase): clean default catchall probe tests 2026-06-24 12:19:03 -07:00
Atai Barkai e0b93a7adc test(showcase): harden default catchall D6 probe 2026-06-24 12:19:03 -07:00
Atai Barkai 2b3c54ac4e docs(showcase): label catch-all as default rendering 2026-06-24 12:18:11 -07:00
Atai Barkai 6fc2c3a73c docs(showcase): highlight catch-all renderer snippet 2026-06-24 12:18:11 -07:00
Atai Barkai dfa1b03064 docs(showcase): highlight catch-all opt-out APIs 2026-06-24 12:18:11 -07:00
Atai Barkai a0d7f1cc84 docs(showcase): use hook for catch-all opt-out 2026-06-24 12:18:11 -07:00
Atai Barkai 5243be84cb docs(showcase): inline catch-all suppress example 2026-06-24 12:18:11 -07:00
Atai Barkai 436a5ea610 docs(showcase): move suppress snippet out of live demo 2026-06-24 12:17:19 -07:00
Atai Barkai 75bc9fe300 docs(showcase): show full render opt-out signature 2026-06-24 12:17:19 -07:00
Atai Barkai a007c66f9a docs(showcase): trim catch-all opt-out snippet 2026-06-24 12:17:18 -07:00
Atai Barkai e56d5fbebe docs(showcase): source catch-all opt-out snippet 2026-06-24 12:17:18 -07:00
Atai Barkai 84b1aa9cf7 docs(shell-docs): trim catch-all tool rendering page 2026-06-24 12:17:18 -07:00
Atai Barkai 167e16e5c5 docs(shell-docs): restore tool rendering snippet highlighting 2026-06-24 12:17:18 -07:00
Atai Barkai 23eaeed648 docs(shell-docs): preserve tool rendering examples 2026-06-24 12:16:40 -07:00
Atai Barkai ff43adce6b docs(shell-docs): rename default rendering to catch-all 2026-06-24 12:15:16 -07:00
Atai Barkai f70658aaea docs(shell-docs): split tool rendering section 2026-06-24 12:14:24 -07:00
Atai Barkai 435c12c297 docs(shell-docs): clarify render opt-out status prop 2026-06-24 12:12:00 -07:00
Sam Julien 93ce311cfb docs: move Threads into chat UI docs (#5653)
## Summary

- Moves the canonical `/threads` guide into the **Build Chat UIs** nav
group, immediately after prebuilt components
- Keeps `/premium/threads-explained` under **Intelligence Platform** as
the architecture/persistence explanation
- Adds contextual cross-links between the Threads guide, Threads
architecture page, and relevant prebuilt chat UI docs
- Shows `Threads` in the authored framework sidebars next to their chat
UI basics

## Why

Threads are primarily discovered by developers adding saved
conversations, history, and thread switching to a chat UI. The
implementation guide belongs with chat UI docs, while the platform page
remains the deeper explanation of persistence, realtime sync, and
Enterprise Intelligence Platform backing.

## Screenshots

**Root docs navigation: `/threads` now appears with the chat UI basics,
immediately after Prebuilt Components.**

![Root docs Threads
navigation](https://raw.githubusercontent.com/CopilotKit/CopilotKit/92e68e787ec0e137124460637549b0df33929389/pr-5653/root-threads-build-chat-uis-nav.png)

**Authored framework navigation: framework-specific docs now show
Threads next to Prebuilt Components too.**

![Authored framework Threads
navigation](https://raw.githubusercontent.com/CopilotKit/CopilotKit/92e68e787ec0e137124460637549b0df33929389/pr-5653/authored-langgraph-threads-nav.png)

**Intelligence Platform navigation: the architecture page stays in the
platform section.**

![Threads architecture in Intelligence Platform
navigation](https://raw.githubusercontent.com/CopilotKit/CopilotKit/92e68e787ec0e137124460637549b0df33929389/pr-5653/threads-architecture-intelligence-nav.png)

## Validation

- `git diff --check origin/main...HEAD`
- `git diff --check`
- `npm run typecheck` from `showcase/shell-docs`
- Local route smoke checks for `/threads`, `/premium/threads-explained`,
`/prebuilt-components`, and `/prebuilt-components/chat` returned 200
- Authored framework route smoke checks returned 200
2026-06-24 11:11:33 -07:00
Sam Julien 5507c75d2d docs: add framework-scoped Threads callouts (#5651)
## Summary

- Adds a `thread_persistence_pattern` manifest flag so shared docs can
render selected-framework Threads guidance.
- Marks LangGraph Python, LangGraph TypeScript, LangGraph FastAPI, and
Google ADK with the appropriate thread persistence pattern.
- Extends `WhenFrameworkHas` support so the shared Threads guide can
show LangGraph-only and ADK-only callouts.
- Clarifies that `useThreads` manages Enterprise Intelligence Platform
thread records, not native framework stores.
- Adds framework-selected callouts to the root/shared Threads guide
without adding a third setup path.

## Notes

The new callouts intentionally avoid claiming external store listing,
lifecycle sync, migration/import tooling, or durable ADK sessions by
default. Those remain product/runtime follow-ups tracked separately.

## Validation

- `git diff --check`
- `npm run pretypecheck` in `showcase/shell-docs`
- `npm run lint` in `showcase/shell-docs` (passes with existing
warnings)
- `npm run typecheck` in `showcase/shell-docs`
- `npm run build` in `showcase/shell-docs` (passes with existing
Turbopack/NFT warning)
- Local route smoke checks:
  - `/threads` hides framework callouts
  - `/langgraph-python/threads` shows LangGraph callout only
  - `/langgraph-typescript/threads` shows LangGraph callout only
  - `/langgraph-fastapi/threads` shows LangGraph callout only
  - `/google-adk/threads` shows ADK callout only
2026-06-24 11:11:22 -07:00
Ran Shemtov 311c47f002 Merge branch 'main' into claude/reverent-black-6ba1b9 2026-06-24 20:04:00 +02:00
Ran Shem Tov d6f618dc03 fix(showcase): make default redeploy scope env-aware for staging-only services
The strands-typescript SSOT entry is ciBuilt:true but staging-only (prod
instance not yet provisioned). redeploy-env.ts's default scope was the full
CI_BUILT_SERVICES set for BOTH envs, so a staging-only ciBuilt service would
wrongly enter the prod default scope and fail a manual `redeploy-env.ts prod`
(no prod instance). Filter the default scope by env declaration (explicit
--services stays unfiltered, preserving the contract-pin that an operator can
force a named service in an env it does not declare). imageOf expansion was
already env-aware; this extends the same invariant to the base scope.

Update the inventory-lock test counts for the new service (total 40->41,
CI_BUILT 38->39, staging default scope 39->40; prod default scope stays 38 as
the staging-only service is now correctly excluded).
2026-06-24 19:54:49 +02:00
Ran Shem Tov d779f71468 feat(showcase): deploy strands-typescript integration to staging
Wire the strands-typescript showcase integration for staging deployment,
mirroring how the Python strands integration is deployed.

- manifest: flip deployed: true so the shell lists it in the integration menu
- railway-envs.ts: add showcase-strands-typescript SSOT entry (staging-only
  for now: prod instance not yet provisioned, so it omits the prod env and is
  gateIgnore'd until promoted dual-env); regenerate railway-envs.generated.json
- showcase_build.yml + showcase_build_check.yml: add the strands-typescript
  build matrix entry, change-detection filter, and dispatch option (railway_id
  is the new Railway service id)
- golden fixture + image-ref-gate inventory tests updated for the new service

Railway staging service showcase-strands-typescript provisioned
(showcase-strands-typescript-staging.up.railway.app, health /api/health,
OpenAI-via-aimock env). Prod is added later via the promote pipeline.
2026-06-24 19:39:36 +02:00
Ran Shemtov 9319a5f57a Merge branch 'main' into claude/strands-d6-green 2026-06-24 19:26:12 +02:00
Ran Shemtov 54ef8027f6 Merge branch 'main' into claude/adk-d6-non-a2ui 2026-06-24 19:25:24 +02:00
Jordan Ritter b507054f51 fix(showcase): map AG-UI multimodal content to native pydantic-ai types (fix assert_never) (#5675)
## Summary
The pydantic-ai showcase integration crashed with `assert_never` in
pydantic-ai's `_map_user_prompt` whenever AG-UI multimodal
`InputContent` (images / documents / binary, data: and url: sources)
reached the model — AG-UI content types were never normalized to the
native pydantic-ai types (`str` / `ImageUrl` / `BinaryContent` /
`DocumentUrl`) the mapper requires.

## What changed
- **`_MultimodalFlattenModel(WrapperModel)`** normalizes content at the
**model-call boundary** (overriding `request` / `request_stream` /
`count_tokens`) — deliberately NOT a `history_processor`, because that
hook persists its return into `message_history` and would leak flattened
content back to the UI.
- **Supported-type gating + degrade centralized at the single
native-type emission choke point** (instead of scattered
per-content-branch): unsupported image subtypes (HEIC/SVG/TIFF/BMP),
audio/video, and non-fetchable url attachments degrade to a text
placeholder rather than emitting a native type the OpenAI Responses
vision API rejects (which would fail the turn).
- **Mime normalized once** — strips RFC-2045 params/whitespace,
lowercases, and aliases the common non-canonical `image/jpg` →
`image/jpeg` before the allow-list (png/jpeg/gif/webp) test, so real
JPEGs are no longer silently dropped.
- Identity-based (`is`) no-op detection replaces fragile structural
`==`.

## Why it matters
Unblocks multimodal turns in the pydantic-ai showcase integration;
eliminates the `assert_never` crash and stops valid `image/jpg` JPEGs
and url-borne documents from being silently mishandled.

## Testing
- **43 unit tests** (clean pinned venv, pydantic-ai 1.0.18), red-green
proven per gap: `image/jpg` forwarded as a supported JPEG; url-media /
non-PDF-doc degrade instead of emitting an unconditional `DocumentUrl`;
parameterized mime forwarded; state-leak guard (`request_stream`
forwards flattened, not raw); `count_tokens` override; `assert_never`
provably unreachable (all flatten paths return a native type or raise).
- 9 rounds of code review (7 agents/round) to a clean confirmation round
(zero blocking findings).

## Test plan
- [ ] CI green
2026-06-24 09:57:21 -07:00
Jordan Ritter b00817d534 fix(showcase): record pydantic-ai generate_a2ui D6 fixture (staging 503 flap) (#5661)
## Summary
- The pydantic-ai `generate_a2ui` declarative D6 turn was missing an
aimock fixture, producing HTTP 503 `no_fixture_match` on staging
(pydantic-ai 503 vs ms-agent-dotnet 200 for the same turn) — a source of
dashboard flapping.
- Adds the canonical mirror fixtures (outer `generate_a2ui` + matching
inner `_design_a2ui_surface`) to
`showcase/aimock/d6/pydantic-ai/gen-ui-declarative.json`. These are
deterministic canonical mirrors matching the langgraph-python convention
— **not** a non-deterministic real-LLM recording — preserving the
mandatory LGP 1:1 parity.

## Red-green proof
- **RED:** exact failing request (`POST /v1/responses`, gpt-4.1, "Show
me my sales dashboard for this quarter.", tools=[`generate_a2ui`],
header `x-aimock-context: pydantic-ai`, strict) against the pre-fix
fixture set → **HTTP 503 `no_fixture_match`** (reproduces staging
exactly; confirmed live on staging too).
- **GREEN:** same request against the new set → **HTTP 200** SSE
emitting the `generate_a2ui` tool call; the inner `_design_a2ui_surface`
turn also returns 200 with the dashboard surface.
- Independently re-verified. `validate-on-load` clean (no fixture
shadowing); existing pydantic-ai D6 turns (KPI/pie/bar/status) still
match identically — no regression.

## Notes
- No credentials in the committed fixture — the OpenAI key was never
even resolved (canonical mirror, not a recording). Credential scan of
the diff + full blob: zero matches.

## Test plan
- [ ] CI green
- [ ] After deploy, confirm the `generate_a2ui` declarative D6 cell
flips red→green on staging
2026-06-24 09:57:17 -07:00
Jordan Ritter 6b04bb08a9 fix(showcase/harness): reliable data-copilot-running turn-done signal (kill probe false-red flaps) (#5649)
## Summary

Makes the showcase harness probe's turn-done signal **reliable**,
killing the dominant class of dashboard false-red flaps without ever
hiding a real failure.

`waitForTurnComplete` previously relied on a fragile SSE fetch-counter
conjunct that false-reds healthy demos whenever the page-side fetch
wrapper missed the runtime URL/transport. This change makes the
**`data-copilot-running` DOM attribute** (driven directly by the agent
run lifecycle, `RUN_STARTED`→true / `RUN_FINISHED`→false,
transport-independent) the **PRIMARY** done-signal, with the SSE counter
demoted to a **headless-only fallback** (headless demos never render
`CopilotChatView`, so the attribute is absent).

Design (all three preserved — no false-green, no false-red, hangs still
red):
- **Primary signal** = the `data-copilot-running` true→false
**transition** with a **stayed-stopped quiescence window** (a stop must
persist on the same run-start count for `settleMs`; a new sub-run resets
it) — so it cannot complete on an intermediate stop in a multi-step
turn.
- **SSE counter** = headless fallback only; never an OR-trigger when the
DOM signal is present.
- **`done-signal-missing` backstop** (gated on `attrPresent===true` +
`runningNow!==true`) reds a genuine painted-but-never-finished DOM turn
before the hard timeout; headless turns use their full timeout for their
only signal.

## How it was reviewed

A full 4-round `cr-loop` (7 unbiased agents/round + confirmation rounds
+ a Procedure-3 promotion audit) caught and fixed **5 distinct
correctness defects** in the implementation before merge:
- **F1** — SSE OR-trigger could complete a multi-step turn early on an
intermediate stop (false-GREEN), in both the loop and the post-loop
classifier.
- **F2** — the run-start baseline was captured *after* the message send,
killing the primary signal on fast turns (false-RED).
- **F3** — non-atomic double `surfaceReady` read per poll (latent hazard
+ wasted round-trip).
- **F4** — the surface-mount (`completeOnMount`) path had no quiescence
window (false-GREEN on intermediate stop + false-RED on a still-running
gen-UI turn).
- **F5** — the early backstop false-redded slow-but-healthy **headless**
turns (now gated on the DOM signal).

Bidirectional red-green tests for F1–F5 plus a systematic `{DOM,
headless} × {completes, lagging-recovers, genuine-hang} × {text,
surface}` completion/backstop matrix. Full harness unit suite: **3173
passed / 18 skipped / 0 failed**; `tsc --noEmit` clean; lint 0 errors;
build clean.

## Known follow-ups (NOT in this PR — pre-existing / non-blocking)

- **Theoretical edge (not reachable on real or realistically-streamed
turns):** if a run completed within a single synchronous microtask
(zero-duration), the page-side MutationObserver could miss the true edge
while `attrPresent===true` → false-red. Real LLM turns and aimock
realistic-streaming hold the attribute true across many event-loop
ticks, so the observer reliably latches it. A naive "re-add SSE fallback
for DOM-present" fix would reintroduce F1's multi-step false-green, so
it's intentionally not done here.
- **Recommended quick follow-up (latency only, no wrong verdict):**
capture `baselineBannerText` pre-`sendTurnMessage` (mirroring the
run-start/count baselines) so a fast-erroring cold-start turn fast-fails
(#5142) instead of burning the full timeout.
- **Pre-existing sse-interceptor capture/counter internals** (none
load-bearing for the new done-signal; verified STAY_IN_C by the
Procedure-3 audit): page-side counter soft-nav/multi-capture reset,
`__hk_fetchWrapped` pattern reuse + hardcoded fallback, g/y-flag
stateful RegExp, TextDecoder end-of-stream flush, bare-catch
reader-error swallow, framenav payload discard/TOCTOU,
CDP-wallTime-vs-Date.now TTFT, addInitScript/close-listener
re-registration accumulation.

## Test plan

- [x] `pnpm test` (harness) — 3173 passed / 18 skipped / 0 failed
- [x] `tsc --noEmit` exit 0, lint 0 errors, build exit 0
- [ ] Verify on staging that auth / prebuilt-sidebar / claude-sdk-tools
(and other previously-flapping cells) stop false-redding while
genuinely-broken cells stay red

Please review the replay/primary-signal approach. Not auto-merging.
2026-06-24 09:57:13 -07:00
Jordan Ritter 27b5e79a00 test(showcase): cover pydantic-ai multimodal content mapping + degrade paths 2026-06-24 09:16:07 -07:00
Ran Shem Tov c5554f317f fix(showcase/google-adk): full D6 green — restore post-tool loop, fix interrupt + headless
Brings google-adk to 39/39 D6 (reproduced across two independent full-matrix
runs, zero regressions). Four changes:

- entrypoint.sh: remove ADK_DISABLE_PROGRESSIVE_SSE_STREAMING=1. That flag's
  non-progressive aggregation path ended ADK's agentic loop after the first
  tool round (no post-tool LLM re-invoke), which broke every demo needing a
  second turn: the subagents chain (research -> writing -> critique),
  tool-rendering-reasoning-chain (AAPL -> MSFT), shared-state-read-write's
  confirmation, and the custom-catchall narration. The partial-event abort it
  guarded against is already handled in-callback by stop_on_terminal_text.
- manifest.yaml: un-skip-list tool-rendering-reasoning-chain (now passes with
  the loop restored).
- headless_complete_agent.py: add AGUIToolset() so the frontend highlight_note
  tool is injected and routed to the browser. Removing the flag unmasked this
  pre-existing gap — turn 3 dispatched highlight_note server-side and the
  backend registry rejected it. langgraph-python auto-injects frontend tools;
  ADK needs AGUIToolset() in the agent's tools list.
- aimock/d6/google-adk/gen-ui-interrupt.json: order each pill's narration leg
  (toolCallId) before its emit leg and drop the thread-global hasToolResult
  gate, so the alice pill no longer 503s after the sales pill leaves a tool
  result in the thread.
2026-06-24 18:12:17 +02:00
Jordan Ritter d56dcbbc9d fix(showcase): map AG-UI multimodal content to native pydantic-ai types at the model-call boundary
Flatten AG-UI attachment content into native pydantic-ai content types in
the OUTGOING request only, via a WrapperModel-scoped flatten rather than a
history_processor (so the flatten never persists into ctx.state.message_history
and leak into UI state). Normalize mime types, gate on supported content types,
and degrade unsupported types at the single emission choke point. Fixes the
_map_user_prompt assert_never crash on raw AG-UI multimodal content.
2026-06-24 09:03:19 -07:00
Ran Shemtov e744e363ed Merge branch 'main' into claude/strands-d6-green 2026-06-24 17:56:54 +02:00
Jordan Ritter 82523b7297 fix(showcase): harden promote-notify alerting + debt cleanup
Fail loud on a dropped #oss-alerts page: the failure-alert cross-post no longer
swallows a 200/ok:false Slack response, so a dropped page-the-humans alert reds
the renderer job instead of vanishing on a green run. The thread reply stays
warn-only. Both posts capture the response via a shared slack_alert_posted_ok
predicate, mirrored byte-identically across the live workflow and the dry-run
helper.

Debt cleanup: drop a dead failed_count var, correct a misleading gha_url comment,
and validate the decoded blob run_id against ^[0-9a-f]{6}$ in the render step so
a malformed run_id can't reach Slack or the run name.

Tests: predicate edge cases (non-JSON, malformed, missing/null ok), an anti-drift
parity guard asserting the predicate is identical in both files, and call-site
tests locking the #oss-alerts fail-loud vs thread warn-only exit semantics.
2026-06-24 08:55:53 -07:00
Ran Shem Tov cb687d7fb0 chore(showcase): bump strands adapters for A2UI-dynamic completion fix
- @ag-ui/aws-strands 0.2.2 -> 0.2.3 (strands-typescript)
- ag_ui_strands 0.2.1 -> 0.2.2 (strands)

These releases carry the A2UI-dynamic (declarative-gen-ui) run-completion fix:
the auto-injected generate_a2ui now completes after the A2UI surface paints,
so the run emits RUN_FINISHED instead of hanging 'Running'. Should green the
gen-ui-declarative D6 cell on both integrations (-> 35/35) and resolve the
real-LLM staging hang. Pending local D6 re-verify.
2026-06-24 17:16:47 +02:00
Ran Shem Tov 22a93a05d6 fix(showcase): green strands(+TS) D6 shared-state-read + multimodal cells
Takes d6:strands and d6:strands-typescript from 32/35 to 34/35.

- shared-state-read: the turn-2 fixture leg wrongly pinned turnIndex:0, so the
  aimock matcher skipped it on turn 2 -> 404 -> turn-2 sse-missing. Drop
  turnIndex to mirror the langgraph-python gold-standard fixture.
- multimodal: sample.png/pdf/wav shipped as git-LFS pointers, so deploy/test
  environments without 'git lfs pull' served the ~130-byte pointer text as the
  upload -> the run never started (runsFinished=0). Ship them as regular
  binaries via a per-integration .gitattributes lfs-unset + real bytes,
  mirroring langgraph-python's convention.

Remaining red (gen-ui-declarative) is a Strands A2UI-dynamic run-completion bug
(reproduces on real-LLM staging too): the surface paints but generate_a2ui
never completes, so the run hangs 'Running'. Tracked separately.
2026-06-24 15:49:22 +02:00