Skip to content

[pull] main from CopilotKit:main - #1

Merged
pull[bot] merged 16 commits into
mexicanamerican:mainfrom
CopilotKit:main
Oct 1, 2024
Merged

[pull] main from CopilotKit:main#1
pull[bot] merged 16 commits into
mexicanamerican:mainfrom
CopilotKit:main

Conversation

@pull

@pull pull Bot commented Oct 1, 2024

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@pull pull Bot added the ⤵️ pull label Oct 1, 2024
@pull
pull Bot merged commit ea47ad1 into mexicanamerican:main Oct 1, 2024
pull Bot pushed a commit that referenced this pull request Mar 6, 2026
…king

Fixes CopilotKit#2066

## Problem

`copilotkit_customize_config(config, emit_messages=False)` does not work -
TEXT_MESSAGE_* events are still emitted despite the configuration.

## Root Causes

1. **Metadata Reading Bug**: In `langgraph_agui_agent.py`, the code uses
   `getattr(raw_event, 'metadata', {})` to read metadata, but `raw_event`
   is a dict, not an object. This should use `.get()` instead.

2. **Encoder Crash Bug**: When the filtering logic works (after fixing bug #1),
   it returns `""` (empty string) to skip dispatching events. However, this
   empty string gets yielded to the event encoder which expects event objects
   with `model_dump_json()` method, causing an `AttributeError`.

## Fixes

1. Changed metadata reading to handle both dict and object cases.
2. Changed return value from `""` to `None` for filtered events.
3. Added `run()` method override to filter out `None` values before yielding
   to encoder.
pull Bot pushed a commit that referenced this pull request Apr 21, 2026
## Summary

Production `showcase-crewai-crews` was stuck at `agent:"down"` for ~4-5h
on 2026-04-21 (retries #1-8, 503 on `/api/health`, 30s+ hang on
`/api/smoke`). Railway runtime logs show the FastAPI agent on `:8000`
handled startup and hundreds of requests cleanly, then silently
**stopped responding** at ~06:56-07:01 UTC after an `unhandledRejection:
UND_ERR_BODY_TIMEOUT`. The Python process did not exit — it hung — so
bash's `wait -n` never fired, the container never restarted, and every
subsequent runtime-to-agent request waited out undici's default 5-minute
headers timeout (`UND_ERR_HEADERS_TIMEOUT` in the logs).

Two defensive fixes in the package:

1. **`entrypoint.sh` — agent watchdog.** Poll
`http://127.0.0.1:8000/health` every 30s (5s `curl --max-time`). After 3
consecutive failures (~90s unreachable), SIGKILL the agent PID so `wait
-n` returns and Railway restarts the container. Also adds `[entrypoint]`
/ `[agent]` / `[nextjs]` / `[watchdog]` log prefixes, a startup
PID-is-alive check, and `PYTHONUNBUFFERED=1` — bringing this package's
entrypoint closer to the starter's richer template.

2. **`src/app/api/smoke/route.ts` — split inner/outer timeouts.**
`UPSTREAM_TIMEOUT_MS = 25_000` on the inner fetch, keeping `maxDuration
= 60` as the route budget. Previously the single
`AbortSignal.timeout(45000)` on the upstream fetch, when the agent hung,
consumed nearly all the 60s envelope before Next.js cut the request —
producing HTTP 000 at the caller. Now a wedged agent surfaces as a
structured `stage: "timeout"` JSON response in ~25s.

Upstream `showcase-crewai-crews-production.up.railway.app` verified RED
(503, agent:down) via `curl` before this PR. Merge will trigger GHCR
build + Railway redeploy; recovery expected within ~4 min of deploy.

## Test plan

- [ ] Railway deploys latest image after merge; container boots healthy
- [ ] `curl
https://showcase-crewai-crews-production.up.railway.app/api/health`
returns 200 `agent:"ok"`
- [ ] `curl
https://showcase-crewai-crews-production.up.railway.app/api/smoke`
returns 200 within ~25s (or 502 `stage:"timeout"` if aimock glitches)
- [ ] Logs show `[entrypoint]` / `[agent]` / `[watchdog]` prefixes
(evidence the new entrypoint is active)
- [ ] Induce hang by sending a malformed agent request; verify watchdog
kicks in after ~90s (visible in logs as `[watchdog] Agent health probe
failed` + container restart)
- [ ] Starter service (`showcase-starter-crewai-crews`) unaffected —
only the package entrypoint/smoke route changed
pull Bot pushed a commit that referenced this pull request Apr 22, 2026
…opilotKit#4155)

## Summary

Showcase demos (e.g. gen-ui-tool-based's "Traffic pie chart", Beautiful
Chat's pie/bar-chart suggestions) were rendering nothing in prod because
aimock's substring-match fixtures cross-fired across demos with
different tool surfaces, returning tool names the target agent never
registered. This PR narrows the fixture patterns to fix the immediate
breakage and adds a static validator so the same class of drift fails CI
before it reaches prod.

## What broke

Aimock serves deterministic responses in prod for cost reasons. Fixtures
substring-match the user message and return hardcoded tool calls. The
`"pie chart"` pattern returned `query_data` (for Beautiful Chat's
two-step flow where it has that tool), but the same substring also fires
for gen-ui-tool-based's suggestions — which only registers
`render_pie_chart`. The returned `query_data` call dangles, no UI
renders.

Beautiful Chat also looped on the same fixture: aimock has no
conversation-turn awareness, so after `query_data` returned its tool
result, the follow-up model call had the same user-message context and
the fixture re-matched, emitting `query_data` again — infinite until
LangGraph's iteration cap.

Exposed by PR CopilotKit#4113 (showcase-ops) / the prod-mode migration cluster
that started routing prod traffic through aimock. The fixtures
themselves had been incrementally drifting for a while, but the routing
change turned silent drift into user-visible breakage across many demos
simultaneously.

## Fix #1 — narrow the fixture patterns

`showcase/aimock/feature-parity.json`:

- Replaced the generic `"pie chart"` / `"bar chart"` / `"show pie"` /
`"show bar"` patterns with **6 per-suggestion specific-phrase matches**.
gen-ui-tool-based and declarative-gen-ui get `render_pie_chart` /
`render_bar_chart` directly; Beautiful Chat gets `pieChart` / `barChart`
with real data (skipping the query_data loop).
- Narrowed `"schedule"` + `"meeting"` into one match for Beautiful
Chat's "30-minute meeting to learn about CopilotKit" → `scheduleTime`.
- Narrowed `"flight"` / `"fly"` to `"flights from SFO to JFK"`.
- Narrowed `"background"` to `"sunset-themed gradient"`.
- Removed `"trip"`, `"sales"`, `"pipeline"`, `"todo"` — too generic,
substring-false-firing across unrelated demos. Interrupt and A2UI demos
with those prompts fall through to the real LLM proxy.

## Fix #2 — static drift guardrail

New `showcase/scripts/validate-fixture-tool-surface.ts`:

- Pure `validate()` function: for each fixture with tool-call responses,
finds every demo whose suggestion prompt contains the fixture's match
substring, then asserts the fixture's returned tool names are all
registered by that demo's agent.
- CLI walks `packages/*/` collecting:
  - suggestions from `page.tsx` + sibling `hooks/*.tsx`
- frontend tools from `useComponent` / `useHumanInTheLoop` /
`useFrontendTool` / `useRenderTool` / `useDefaultRenderTool` calls
- backend tools via `api/copilotkit*/route.ts` → agentId→graphId map →
`langgraph.json` graph→Python-file → `@tool` decorators + `tools=[...]`
arrays
- 7 vitest cases written TDD-first (watched fail, then implemented)
covering: drift detection, content-only fixtures, no-matching-demo,
case-insensitivity, multi-demo cross-check, multi-tool responses.

Runs as `npx tsx showcase/scripts/validate-fixture-tool-surface.ts`.
Exit 0 = clean; exit 1 = per-fixture drift report.

Current state: **33 fixtures × 191 demos, no drift.**

Counterfactual: reverting just the pie-chart fixture fix correctly flags
`langgraph-python/gen-ui-tool-based` and
`langgraph-python/declarative-gen-ui` — i.e. the exact demos that broke
in prod.

## Also fixed — unrelated LangGraph Python Dockerfile bug

`showcase/packages/langgraph-python/Dockerfile`: `WORKDIR /app` left
`/app` owned by root; the explicit `--chown=app:app` on COPY lines
chowned *contents* but not the directory itself, so the `app` user
couldn't create `.langgraph_api` (the in-memory LangGraph runtime's
cache dir) and the agent crashed on boot with `PermissionError: [Errno
13]`. Added a non-recursive `chown app:app /app` (preserves the perf
intent of not doing a recursive chown).

## Known follow-ups (out of scope for this PR)

- Interrupt demos (`gen-ui-interrupt`, `interrupt-headless`,
`hitl-in-chat`) and A2UI demos (`declarative-gen-ui`,
`a2ui-fixed-schema`, `mcp-apps`, Calculator App) currently fall through
to the real LLM when unmatched. Faithful fakes would need per-agent
fixture keying in the aimock engine — separate upstream change.
- Python backend-tool parser uses regex; misses star-spread collections
like `tools=[query_data, *todo_tools]`. Safe failure mode — missing
tools surface as guardrail drift rather than silently pass.
- Add this validator to `.github/workflows/showcase_*.yml` so CI runs it
on every PR touching fixtures or demos.

## Test plan

- [x] `npx vitest run
showcase/scripts/__tests__/validate-fixture-tool-surface.test.ts` — 7/7
pass
- [x] `npx vitest run
showcase/scripts/__tests__/aimock-fixtures.test.ts` — 17/17 still pass
(no regression)
- [x] `npx tsx showcase/scripts/validate-fixture-tool-surface.ts` — 33
fixtures × 191 demos, 0 drift
- [x] Counterfactual: revert fixture fix, validator flags
gen-ui-tool-based + declarative-gen-ui exactly
- [x] Direct aimock probe (localhost:4010) for all 8 fixed prompts →
returns correct tool call
- [x] End-to-end through local LangGraph agent (localhost:3100) →
gen-ui-tool-based "Traffic pie chart" suggestion → `render_pie_chart`
with real data
- [ ] Merge → Railway redeploys aimock + langgraph-python → smoke cycle
on Beautiful Chat + gen-ui-tool-based + declarative-gen-ui suggestions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants