mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
chore/nix-langgraph-threads-docs
6858 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c6b1617bef | chore(showcase/starters): regenerate all starters post-generator fix | ||
|
|
70f8df05a4 |
chore(showcase/starters): regenerate langgraph-{fastapi,typescript} after generator fix
langgraph-fastapi/src/agents/src/agent.py now imports
`src.agents.tools.*` (module exists) rather than `src.agents.src.tools.*`
(nonexistent path) -- fixes the ModuleNotFoundError crash that held
/api/health at agent: "down".
langgraph-typescript/package.json now includes @langchain/core,
@langchain/langgraph, @langchain/langgraph-checkpoint,
@langchain/langgraph-cli, @langchain/openai, and @copilotkit/sdk-js so
the agent subtree can resolve its runtime imports after the Dockerfile
deletes agent/package.json.
Local docker build + run verified: both /api/health return
{"status":"ok","agent":"ok"} and their entrypoint logs show
`Agent server started` with the captured PID belonging to the agent,
not an awk/sed prefixer.
|
||
|
|
710da8cc30 |
fix(showcase/scripts): restore langgraph starter subprocess boot path
Three interlocking fixes to generate-starters.ts that together restore langgraph-fastapi and langgraph-typescript /api/health to "ok" after #4099 shipped an entrypointOverride feature that accidentally reverted earlier fixes and left gaps for the TS starter. 1. Resolution-aware python import rewrite for langgraph starters. langgraph_cli loads agent modules standalone (not as packages), so the generator rewrites `from .X import ...` to absolute form. The previous flat rewrite produced `from <agentDir>.X import ...`, and the subsequent subdir-aware variant used the file's OWN dir as the package. Both assume sibling targets sit alongside the importing file. langgraph-fastapi violates that: agent.py lives at `src/agents/src/agent.py` but the `tools/` it imports lives at `src/agents/tools/` -- one level up, not inside `src/`. Either prior rewrite produced `from src.agents.src.tools import ...`, a path that doesn't exist, and langgraph_cli crashed on module import with `ModuleNotFoundError: No module named 'src.agents.src.tools'` before ever binding 8123. Walk UP from the file's own dir toward agentDest and rebase the absolute import on the shallowest directory that actually contains `<firstSeg>/` or `<firstSeg>.py`. Correct both for co-located imports (`tools/get_weather.py` importing `.types`) and for sibling-directory imports (`src/agent.py` importing `.tools` from `../tools`). 2. Merge langgraph-typescript agent runtime deps into root package.json. The TS Dockerfile deliberately deletes `agent/package.json` to collapse the ESM package boundary between the Next.js frontend and the agent subtree. Without merging the agent's runtime deps up into the root package.json, the langgraph-cli's runtime import of graph.ts fails with `Cannot find module '@langchain/openai'` and the agent never binds 8123. Add `extraDependencies` to the langgraph-typescript framework def with @langchain/core, @langchain/langgraph, @langchain/langgraph-checkpoint, @langchain/langgraph-cli, @langchain/openai, and @copilotkit/sdk-js. 3. Restore AGENT_LOG_PREFIX process-substitution helper. #4099 inadvertently replaced `cmd &> >(awk … fflush …)` with `cmd 2>&1 | sed …` across every getEntrypointBlock branch. After a pipeline `$!` points at `sed`, not the agent, so `kill -0 $AGENT_PID` and `wait -n $AGENT_PID` monitor the wrong process and mask real crashes; `sed` also line-buffers so crash output can be lost. Restore the helper so the committed starter entrypoint.sh files and regenerated output stay consistent. |
||
|
|
c3d105ae00 |
feat(showcase/langgraph-python): port 4084 cells into 4085 demos layout
Port 15+ cells from PR 4084 (per-demo workspace) into PR 4085's
shared-column layout (src/agents/*.py + src/app/demos/<cell>/*.tsx).
New cells:
- beautiful-chat (port scaffold — full component tree deferred)
- declarative-gen-ui-hardcoded (single-file catalog variant)
- interrupt-headless (useHeadlessInterrupt from primitives)
- open-gen-ui-advanced (sandbox functions + app-tool-calling)
- readonly-state-agent-context (useAgentContext one-way channel)
- reasoning-default-render (built-in CopilotChatReasoningMessage)
- shared-state-read-write (preferences write + notes read)
- tool-rendering-reasoning-chain (reasoning emitter + chaining loop)
Restructured cells:
- declarative-gen-ui: BYOC with 3-file a2ui/{definitions,renderers,catalog}
- a2ui-fixed-schema: compositional tree with Title/Airport/Arrow/
AirlineBadge/PriceTag + 3-file catalog; search_flight renamed
display_flight
- mcp-apps: simplified to mcpApps.servers runtime config targeting
Excalidraw; drops custom MCPAppsStubMiddleware
- open-gen-ui: minimal provider + openGenerativeUI runtime flag
- tool-rendering + 3 variants: per-tool WeatherCard + FlightListCard
plus useDefaultRenderTool wildcard
Runtime wiring:
- /api/copilotkit: registers new agents + a2ui.injectA2UITool for
declarative + fixed-schema cells
- /api/copilotkit-ogui: adds open-gen-ui-advanced
- /api/copilotkit-mcp-apps: NEW dedicated endpoint for mcpApps
Backend graphs:
- shared_state_read_write.py (PreferencesInjectorMiddleware + set_notes)
- readonly_state_agent_context.py
- hitl_in_chat_agent.py (tools=[] + tailored prompt)
- a2ui_dynamic_hardcoded.py (secondary-LLM dynamic schema)
- open_gen_ui_advanced_agent.py
- tool_rendering_reasoning_chain_agent.py (reason→tool loop)
Flight fixed-schema JSON now assembles Card>Column>[Title,Row,Row,Button].
All `@region[...]` markers ported to drive docs <Snippet> resolution.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
6e1aa87072 |
chore(showcase/starters): regenerate all starters after #4098
#4098 landed two generator-level changes that affect every starter slug but only langroid was regenerated in that PR: 1. rewritePythonImports now strips `import sys` when sys.path.insert is removed and no other `sys` reference survives in the file (paired with existing osUsed detection). 2. starters/template/entrypoint.template.sh switched from pipeline (`2>&1 | sed 's/^/[agent] /'`) to process substitution (`&> >(awk '{print "[agent] " $0; fflush()}')`) so $! captures the real agent PID, not sed's — prior pattern masked uvicorn crashes behind sed's exit code. Regenerate the remaining 16 starters so drift-check passes on main. No source logic change. |
||
|
|
09d08b1e43 |
fix(showcase/langroid): route A2UI planner through langroid LLM abstraction (#4098)
## Summary langroid is provider-agnostic by design — operators pick a chat model via `LANGROID_MODEL`. But `GenerateA2UITool` hardcoded `openai.OpenAI()` + `gpt-4.1`, forcing non-OpenAI users to keep an `OPENAI_API_KEY` around just for the A2UI dashboard demo. This PR routes the A2UI planner through `lm.OpenAIGPT` (langroid's universal LLM abstraction) and hardens the deploy/boot path around it. ## Core fix - **Provider-agnostic A2UI planner.** `GenerateA2UITool` now uses `lm.OpenAIGPT` keyed on `A2UI_MODEL` (override) → `LANGROID_MODEL` (inherit) → `gpt-4.1` (default, bare name — `openai/` prefix is NOT langroid-native and silently breaks at request time). - **Structured error surface.** `_A2uiError` TypedDict with `_A2uiErrorKind` enum (values pinned to sibling adapters), `_a2ui_error` factory with non-empty-string validation at construction, runtime `ValueError` (not `assert`) so `python -O` can't strip it. - **`_ARGS_MISSING` sentinel** distinguishes "no tool call" from "tool call with degraded shape" — different remediations for the frontend. - **Narrow re-raise tuple** propagates programmer errors (`AttributeError`, `TypeError`, `NameError`, `ImportError`, `ModuleNotFoundError`, `AssertionError`, `NotImplementedError`, `pydantic.ValidationError`) while wrapping recoverable SDK errors into `a2ui_llm_error`. - **Backend tool handlers** now wrap impls in try/except → `_tool_error(kind: _ToolErrorKind, ...)` JSON surfaces, preventing unhandled exceptions from escaping to langroid's tool machinery. - **Boundary validation** after `build_a2ui_operations_from_tool_call` return. ## Deploy / entrypoint hardening - **Provider-aware credential guard.** Detects `LANGROID_MODEL` prefix (`openai/` → warns it's not routable, `gemini/` → `GEMINI_API_KEY`, `litellm/anthropic/` → `ANTHROPIC_API_KEY`, `ollama/`/`local/`/`vllm/`/`llamacpp/` → no-key-required, `langdb/`/`litellm-proxy/`/`litellm/<other>/` → config-resolved) and fails fast under `REQUIRE_LANGROID_API_KEY=1` only when credentials are genuinely missing. - **Real PID capture** for uvicorn + Next.js via process substitution (prior `| sed` pattern captured the sed PID, masking crash diagnostics). - **Graceful shutdown:** trap cleanup with `set +e` safety + 5s SIGTERM→SIGKILL grace window, survivor-kill with EPERM diagnostics. - **Package Dockerfile** now runs as non-root with `ENV PORT=10000` / `ENV HOSTNAME=0.0.0.0` parity with starter. ## Generator + CI - **`entrypointOverride`** mechanism in `generate-starters.ts` so the langroid starter's provider-aware entrypoint survives regeneration. Reads canonical from `STARTERS_DIR/<slug>/` (not `outDir`) so `--check` mode doesn't false-flag drift. - **Fail-loud** on missing required inputs (agent_server.py, extraFiles, PIN_OVERRIDES stale deps, missing override file) instead of silent warn+skip. - **Regression test** pins the `entrypointOverride` preservation behavior. - **`.gitattributes`** enforces LF on `.sh` for Windows contributor safety. ## Review 5 full CR rounds (7 agents each) + 6 fix rounds. Load-bearing bugs converged: - Round 1: R1 → 47 findings, most resolved - Round 2: R2 → 30+ findings, critical (lru_cache keying, build_a2ui wrapper, starter parity, `_A2uiError` hardening) - Round 3: R3 → sed-PID bug (production-blocking), `--check` drift, file mode, `entrypointOverride` hard-error, `saw_modern_call` logic gap - Round 4: R4 → `google/*` FATAL, bare-prefix FATAL, RecursionError test naming, caplog ambiguity, ClassDef walker, `_ToolErrorKind` enum - Round 5: R5 → **`openai/gpt-4.1` default empirically broken** (langroid doesn't strip the prefix → OpenAI SDK rejects), fail-fast refusing ollama/local/vllm/llamacpp, missing regression test for entrypointOverride, rootful package Dockerfile - Round 6: R6 → `langdb/`/`litellm-proxy/`/`litellm/<non-anthropic>/` refused under fail-fast, starter `wait -n` pid quoting, cleanup trap `set -e` safety Deferred as design-scope follow-ups (not load-bearing, current code is correct): - `_A2uiError` TypedDict → frozen dataclass / pydantic model (stronger encapsulation, cross-sibling alignment required) - `_ARGS_MISSING: object` → named sentinel class (cleaner narrowing) - `list[dict]` tool fields → TypedDict / pydantic models for schema enforcement at ingestion - Comment rot around "Identical TypedDicts live in siblings" (sibling adapters diverged on the Literal) - Frontend-tool `handle()` server-side regression path returns benign string (explicit UX tradeoff) ## Tests - 109 passed, 1 skipped (integration test gated by `LANGROID_INTEGRATION_TESTS=1`) - Module-import hygiene via subprocess isolation (no more stale `importlib.reload` state) - AST walker catches top-level + `try/except` `import openai` (including ClassDef bodies) - LRU eviction pinned at `maxsize=4` - Forced-function-call kwargs + `stream=False` planner assertion - Parametrized error propagation (both re-raise and wrap tuples) - Backend tool handle happy + error paths across all 6 tools - `create_agent` factory: stream=True + enable_message(ALL_TOOLS) ## Test plan - [x] `pytest showcase/packages/langroid/tests/python/` — 109 pass, 1 skipped - [x] `npx tsx showcase/scripts/generate-starters.ts --check` — no langroid drift - [x] `bash -n` clean on both entrypoints - [x] Manual: `REQUIRE_LANGROID_API_KEY=1` + various `LANGROID_MODEL` values — bare anthropic/ FATALs, langdb/litellm-proxy/litellm-non-anthropic INFO-pass, ollama/local no-key-required INFO-pass - [ ] CI green (watching) - [ ] Railway deploy of showcase-langroid once merged 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
ede34dabc1 | chore(showcase/langroid): regenerate starter after source+generator updates | ||
|
|
e862feb63b |
feat(showcase/scripts): per-slug entrypointOverride + fail-loud on missing inputs
generate-starters.ts: - Add entrypointOverride?: boolean to FrameworkDef so slugs whose boot sequence diverges from the shared template (e.g. langroid's provider-aware credential guard) can preserve their committed entrypoint.sh through regeneration. - Snapshot the override from STARTERS_DIR/<slug>/entrypoint.sh (canonical committed path), NOT outDir — so --check mode (which passes a temp outDir) doesn't false-flag the override as drift. - Force mode: 0o755 on the restored file regardless of source mode so editors that strip the executable bit can't silently ship a broken starter. - Throw (not warn) when an entrypointOverride slug is missing the override file, when declared extraFiles / agent_server.py / Dockerfile are missing, and when PIN_OVERRIDES references a stale dep. These are repo-integrity failures — silent-warn-and-continue ships broken starters. - Strip unused `import sys` after sys.path.insert removal (pair with the existing osUsed detection). Opt langroid in via entrypointOverride: true. Also adds a regression test in __tests__/generate-starters.test.ts that calls generateStarterToDir against a tmp dir and asserts the emitted entrypoint.sh byte-equals the committed langroid starter entrypoint, plus a negative test that a non-override slug does NOT preserve its file. |
||
|
|
2dea75a5ab |
fix(showcase/langroid): non-root Dockerfile + pin direct Python deps
Package Dockerfile: - Create unprivileged app:app user (UID/GID 1001) matching starter Dockerfile - USER app drop with --chown=app:app on COPY for security parity - ENV PORT=10000 / ENV HOSTNAME=0.0.0.0 so child processes inherit defaults - Preserves PYTHONPATH=/app/shared/python for shared-tools imports requirements.txt (package + starter): pin httpx, pydantic, openai directly rather than relying on transitive resolution from langroid / fastapi. agui_adapter.py imports these symbols directly — the module's contract shouldn't depend on upstream pin discipline we don't control. |
||
|
|
c2234312b8 |
fix(showcase/langroid): provider-aware entrypoint credential guard + graceful shutdown
Replace the OPENAI_API_KEY-hardcoded credential guard with a provider-aware _check_key that inspects LANGROID_MODEL's prefix and probes the correct env var for that provider: - openai/ → WARN (not a langroid-native prefix; use bare model names) - anthropic/ → WARN (not routable; suggest litellm/anthropic/<model>) - litellm/anthropic/ → ANTHROPIC_API_KEY - gemini/ → GEMINI_API_KEY - openrouter/, groq/, cerebras/, glhf/, minimax/, portkey/, deepseek/ → dedicated keys - ollama/, local/, vllm/, llamacpp/ → NO_KEY_REQUIRED (local inference) - langdb/, litellm-proxy/, litellm/<non-anthropic>/ → NO_KEY_REQUIRED_* (credentials resolved via config, not env) Under REQUIRE_LANGROID_API_KEY=1 a missing credential FATALs the boot; the default is warn-and-continue so dev containers boot cleanly. Process lifecycle hardening: - Use process substitution `> >(sed ...)` instead of pipelines so $! captures the real python/next PID (not sed's) — prior pipeline pattern would mask uvicorn crashes behind sed's exit code - Trap cleanup with `set +e` at entry (trap may fire from FATAL `exit 1` path where set -e would otherwise abort the cleanup loop) - 5s SIGTERM→SIGKILL grace window on the surviving child - Extended exit-code case statement (0, 1, 2, 126, 127, 130, 137, 139, 143, 255) - Survivor-kill diagnostics distinguish EPERM from ESRCH - wait -n with explicit positional PIDs so unrelated subshell reaps can't satisfy the wait .env.example updates document the multi-provider options so operators discover them from the file itself, not entrypoint.sh. .gitattributes enforces LF on *.sh so Windows contributors regenerating the starter don't silently ship CRLF entrypoints. |
||
|
|
65f3790653 |
fix(showcase/langroid): route A2UI planner through langroid LLM abstraction
The secondary GenerateA2UITool previously hardcoded openai.OpenAI() + gpt-4.1, forcing non-OpenAI users to keep an OPENAI_API_KEY around just for the A2UI dashboard demo even when LANGROID_MODEL pointed at another provider. Route the planner through lm.OpenAIGPT (langroid's universal LLM abstraction) keyed on A2UI_MODEL (override) → LANGROID_MODEL (inherit) → gpt-4.1 (default). Default uses the bare model name because `openai/` is NOT a langroid-native prefix — langroid passes it literally to the OpenAI SDK which rejects it. Additional hardening: - _A2uiError TypedDict with _A2uiErrorKind enum, factory with non-empty-string validation that raises ValueError (not assert, so python -O can't strip it) - _ARGS_MISSING sentinel distinguishes "no tool call" from "degraded shape" so the frontend gets correct remediation - Narrow re-raise tuple propagates programmer errors (AttributeError, TypeError, NameError, ImportError, ModuleNotFoundError, AssertionError, NotImplementedError, pydantic.ValidationError) while wrapping recoverable SDK errors into _a2ui_error - _ToolErrorKind enum for backend tool error codes — typo-safe parity with _A2uiErrorKind - Boundary validation after build_a2ui_operations_from_tool_call return - Backend tool handlers wrap impls in try/except so exceptions don't escape to langroid's tool machinery - @lru_cache(maxsize=4) on _get_a2ui_llm keyed on resolved model string - FRONTEND_TOOL_NAMES canary raises RuntimeError at import time on drift - No top-level import of openai (AST walker test pins this contract) Covered by 109 tests (integration test gated by LANGROID_INTEGRATION_TESTS=1). |
||
|
|
5eb4da7db9 |
chore(showcase): regenerate shell/src/data bundles after port
Regenerate registry.json (41 features, 11 categories, 17 integrations), demo-content.json (152 demos bundled with region markers support + dual-path highlight resolution), constraints.json (new allowlists), and status.json (no variants field) so the shell + shell-internal dashboards render the ported state without stale cached inputs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
2a52cf05ba |
chore(showcase/scripts): drop variants mock-seeding from generate-status
Port the 4084 simplification of the status generator: remove the MOCK_VARIANTS seeding table + mockVariantTest / mockVariantQA / mockVariantHealth helpers + Variant type. Informational demos (no route) are skipped from health probing. The status JSON no longer carries per-demo `variants[]` — the shell-internal dashboard renders one row per demo without variant expansion. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
18ed9dbdbd |
chore(showcase/scripts): port bundle regions + parity dual-location
Port the 4084 scripts-layer enhancements so 4085's showcase toolchain
matches the new feature shape:
- lib/manifest.ts: ManifestDemo gains optional `command` field; parser
accepts + validates it (non-empty string, frozen).
- bundle-demo-content.ts: inline `@region[name]` / `@endregion[name]`
comment-marker extraction; informational-only demos (no route, e.g.
cli-start) are skipped; markers stripped from bundled content;
regions: { file, startLine, endLine, code, language } emitted per
demo. External-highlight-file merging (4085-specific) preserved, so
backend agents under src/agents/*.py still flow into the bundle.
- validate-parity.ts: accepts demos at BOTH demos/<cell>/ (4084 layout)
and src/app/demos/<cell>/ (4085 layout); informational demos
(command field) are excluded from the parity audit.
- tests: bundle-demo-content.test.ts expectedDemos updated for the
shared-state rename; generate-registry.test.ts feature count 25→32;
validate-parity.test.ts missing-demo-dir message updated to match
the new dual-location wording.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
fb062d3750 |
chore(showcase): port shared schema + feature-registry + constraints
Port the 4084 internal-showcase-followups state of the shared showcase schema to 4085 (no Docker restructure): - feature-registry.json: new Dev Ex category, category reorder (Dev Ex → Chat & UI → Platform → Controlled → Declarative → Open → Operational → Interactivity → Agent State → Multi-Agent → BYOC); +8 new features (beautiful-chat, cli-start, interrupt-headless, reasoning-default-render, tool-rendering-reasoning-chain, open-gen-ui-advanced, declarative-gen-ui-hardcoded, readonly-state-agent-context); renames (shared-state-write → shared-state-read-write, shared-state-agent-readonly → readonly-state-agent-context); removals (shared-state-read, state-rendering, a2ui-*, shared-state-io, shared-state, readables, a2a-chat, deep-agents, vnext-chat, byoc-a2ui, byoc-tambo); gen-ui-agent → kind: testing. - constraints.yaml: allowlists updated to reference the new IDs. - manifest.schema.json: `route` is optional; `command` field added for informational demos (e.g. cli-start). - All 17 column manifests: shared-state-read removed, shared-state-write renamed to shared-state-read-write. - langgraph-python manifest: full 4084 features list + demos entries with 4085-appropriate highlight paths (src/agents/*.py + src/app/demos/<cell>/* rather than backend/ + frontend/). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
beb42019d4 |
docs(showcase/shell): port ~70 MDX pages from 4084 into shell
Port the MDX content delta between the 4085 base branch
(atai/2026-04-18/feature-port-no-docker-restructure) and the 4084
follow-ups branch (atai/2026-04-17/internal-showcase-followups):
- built-in-agent tree (ag-ui, coding-agents, copilot-runtime,
frontend-tools, inspector, prebuilt-components, programmatic-control,
custom-look-and-feel/{headless-ui,slots}, generative-ui/{a2ui,
tool-rendering,your-components/{display-only,interactive}},
premium/{headless-ui,observability,overview},
troubleshooting/{common-issues,error-debugging,migrate-to-*})
- top-level feature docs (agentic-chat-ui, frontend-tools, headless,
human-in-the-loop, inspector, shared-state, programmatic-control,
ag-ui-middleware, coding-agents, coding-agent-setup)
- custom-look-and-feel (css, reasoning-messages, slots)
- generative-ui (a2ui, a2ui/dynamic-schema, a2ui/fixed-schema,
mcp-apps, open-generative-ui, reasoning, tool-based, tool-rendering)
- human-in-the-loop (headless, useInterrupt)
- prebuilt-components (index, popup, sidebar) — replaces the single
prebuilt-components.mdx
- shared-state (agent-readonly, streaming)
- troubleshooting (common-issues, debug-mode, error-debugging,
migrate-to-*, observability-connectors)
- learn (connect-mcp-servers)
- multi-agent/subagents
- integrations/built-in-agent/custom-agent,
integrations/langgraph/generative-ui/tool-rendering
- meta.json updates across backend, custom-look-and-feel,
generative-ui, generative-ui/a2ui, prebuilt-components,
troubleshooting, root docs
These pages use the new Snippet / InlineDemo / FrameworkTabs
components shipped in the preceding infrastructure commit, plus the
FrameworkGuardedContent pattern that only applies when a page has a
defaultCell frontmatter. Framework-agnostic pages (/learn/*,
/troubleshooting/*, /premium/*) keep rendering their body
unconditionally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
c1b595596e |
feat(showcase/shell): port /docs routing + framework-scoped routes from 4084
Port the full docs routing + rendering infrastructure from the 4084 branch (atai/2026-04-17/internal-showcase-followups): - New [framework]/[[...slug]] catch-all that validates the first segment against the registry and renders framework-scoped docs with a "not available for this framework" banner when the page's defaultCell is not tagged in the framework's cells. - FrameworkProvider + selector: framework is strictly URL-derived, storedFramework is an advisory localStorage signal. No auto-redirect from localStorage. - /docs/[[...slug]] rewritten as a thin wrapper around DocsPageView with a new DocsOverview landing: framework picker + topic cards. - New lib/docs-render.tsx centralising snippet inlining, frontmatter parsing, nav tree + breadcrumb builders. - New lib/mdx-registry.tsx consolidating the ~700-line component shim used by both routes. - Server <Snippet> component with demo-content regions + syntax highlighting via highlight.js. - Per-feature <InlineDemo> iframe embedder pointing at the integration's backend (single-container shape http://localhost:3100/demos/<cell>). - FrameworkTabs, docs-callout, docs-steps, docs-tabs, router-pivot, stored-framework-highlight components for the MDX registry. - Global typography + color pivot in globals.css: Plus Jakarta Sans body, Spline Sans Mono code, cool-gray background, purple accent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
218a356256 |
feat(showcase/shell-internal): port enriched cell chrome + command cell from 4084
- Drop the 5 experimental variant-presentation routes + SingleCell helper;
the variant layouts no longer match the enriched cell chrome.
- Rename variant-pieces.tsx -> cell-pieces.tsx; expose a shared
<CellStatus ctx={ctx} /> that renders the docs-og/docs-shell row +
E2E/Smoke/QA/health badges so both the runnable-demo cell and the
informational CommandCell share the same bottom section.
- Add CommandCell (client component): takes the full CellContext, renders
<code> + Copy button for ctx.demo.command, then the same CellStatus row.
- page.tsx branches on ctx.demo.command so the CLI Start row renders a
copy-pasteable command in place of Demo/Code links while keeping the
matrix visually consistent.
- registry.ts: Feature gains kind + og_docs_url/shell_docs_url; Demo.route
is optional and Demo.command is the new informational field. Feature-grid
passes the full demo onto CellContext.
- status.ts: drop variant helpers / types (no longer used).
- Add docs-status.ts reader + a stub docs-status.json so the enriched
DocsRow renders without blowing up the build before the schema agent
lands the generated bundle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
3be1bda487 |
fix(showcase/starters): chown /app to app user to prevent CLI cache-dir crashes (#4099)
## Summary **Root cause:** PR #4092 replaced a blanket `RUN chown -R app:app /app` with per-COPY `COPY --chown=app:app` lines. That covers the copied files, but `WORKDIR /app` at the top of the runner stage creates `/app` as root BEFORE the `app` user exists, and `COPY --chown=` only reassigns the copied files — not the parent dir. Result: `/app` stays owned by root. **Symptom:** `starter-mastra` deploy CRASHED on Railway with: ``` Error: EACCES: permission denied, mkdir '/app/.mastra' ``` `npx mastra dev` tries to create its cache dir under CWD at runtime as user `app`, and fails. **Likely co-victims:** any starter whose runtime invokes a Node CLI that writes to CWD. `starter-langgraph-typescript` (uses `@langchain/langgraph-cli dev`) fits the exact same signature — same class of bug, would have hit the same wall once traffic forced a cache write. **Fix:** add `RUN chown app:app /app` immediately before `USER app` in all four Dockerfile templates (typescript, python, dotnet, java), applied uniformly to all 17 generated starters via `showcase/scripts/generate-starters.ts`. Surgical, cheap, idempotent. ## Evidence — local docker build + run **starter-mastra:** ``` $ docker exec starter-mastra-test ls -la /app | head drwxr-xr-x 1 app app 4096 . ← WORKDIR now owned by app drwxr-xr-x 1 root root 4096 .. drwxr-xr-x 4 app app 4096 .mastra ← created successfully by mastra dev ... $ curl http://localhost:13010/api/health {"status":"ok","integration":"mastra","agent":"ok",...} ← HTTP 200 ``` **starter-langgraph-typescript:** ``` $ docker ps --filter name=starter-langgraph-ts-test starter-langgraph-ts-test Up 8 minutes ← stable, not crashlooping $ docker exec starter-langgraph-ts-test touch /app/test-write && echo OK OK $ curl http://localhost:13020/api/health {"status":"degraded","integration":"langgraph-typescript","agent":"down",...} ← HTTP 503 (dummy key) — NOT a crash ``` ## Scope - 17 starter Dockerfiles regenerated - 4 template Dockerfiles updated (the source of truth) - Generator TS untouched — the fix is purely in the Dockerfile templates that the generator copies verbatim - `showcase/scripts` vitest: 1073/1073 green ## Test plan - [x] `pnpm run generate-starters` regenerates without errors - [x] `pnpm test` in `showcase/scripts` — 1073 tests green - [x] `docker build` + `docker run` starter-mastra — container stays up, `/api/health` 200 - [x] `docker build` + `docker run` starter-langgraph-typescript — container stays up 8+ min, `/api/health` 503 degraded (expected on dummy key) - [ ] Railway redeploy of starter-mastra after merge — expect container to boot and reach `running` - [ ] Railway redeploy of starter-langgraph-typescript after merge — expect container to boot and reach `running` Independent of #4096 — branched from `origin/main`, no dependency. |
||
|
|
98841aaba5 |
fix(showcase/starters): chown WORKDIR to app user in Dockerfiles
Root cause: `WORKDIR /app` at the top of the runner stage creates /app owned by root BEFORE the unprivileged `app` user is created. The `COPY --chown=app:app` lines added in #4092 only reassign the files being copied, NOT the /app directory itself. Symptom: starter-mastra CRASHED on Railway with EACCES: permission denied, mkdir '/app/.mastra' when `npx mastra dev` tried to create its cache dir under CWD as user `app`. Likely co-victim class: any starter whose runtime invokes a Node CLI that writes to CWD (e.g. langgraph-typescript via @langchain/langgraph-cli dev). Fix: add `RUN chown app:app /app` immediately before `USER app` in all four Dockerfile templates (typescript, python, dotnet, java), applied uniformly to all 17 generated starters via the generator. Verified locally: - docker build + run starter-mastra → container stays up, /app owned by app:app, /app/.mastra created successfully, /api/health returns 200. - docker build + run starter-langgraph-typescript → container stays up (8+ min), write to /app succeeds, /api/health returns 503 degraded (expected on dummy OPENAI_API_KEY) — NOT a crash. All 17 starter Dockerfiles regenerated via pnpm run generate-starters and the existing showcase/scripts vitest suite stays green (1073 tests). |
||
|
|
692c57db01 |
fix(showcase/starters): restore /api/health accuracy across 15 degraded agent starters (#4096)
## Summary
15 of 17 showcase starters were reporting `{status: "degraded", agent:
"error" | "down"}` from `/api/health`. Root-caused to two compounding
bugs that hid each other.
### Cause 1 — FastAPI route shadowed by mount catch-all
Python FastAPI starters registered `@app.get("/health")` but then
installed an AG-UI adapter at `/` (either `app.mount("/",
stream.build_asgi())` or
`add_agent_framework_fastapi_endpoint(path="/")`). Starlette's `Mount`
at `/` is a prefix match and swallows every subsequent request including
`/health`, so the decorated handler never fired and the runtime saw a
non-JSON agent response and flagged the starter as "degraded".
Repro (reduced, before):
```python
app = FastAPI()
app.mount("/", mounted) # or adapter that mounts at "/"
@app.get("/health")
def health():
return {"status": "ok"}
# curl /health -> "agent-saw:/health" (wrong — mount won)
```
Fix: install a `HealthMiddleware` (BaseHTTPMiddleware) that
short-circuits `GET /health` above the routing layer, which runs before
any Mount can claim the path. Agent mount stays intact so AG-UI traffic
at `/` is unaffected.
Applies to 10 Python agent starters: ag2, agno, claude-sdk-python,
crewai-crews, google-adk, langroid, llamaindex, ms-agent-python,
pydantic-ai, strands.
### Cause 2 — `$!` after a pipeline points to `sed`, not the agent
The entrypoint template used:
```bash
cmd 2>&1 | sed 's/^/[agent] /' &
AGENT_PID=$!
```
After a pipeline, `$!` is the last command (`sed`), not the agent. Every
`kill -0 $AGENT_PID` and `wait -n $AGENT_PID` therefore monitored `sed`,
which stays alive until its stdin closes — long after the agent crashed.
Compounding that, `sed` buffers by default and Python agents buffer
their own stdout, so a stack trace at crash time was discarded when the
pipe closed.
Fix: process substitution instead of pipeline, plus `PYTHONUNBUFFERED=1`
at the entrypoint level:
```bash
cmd &> >(awk '{print "[agent] " $0; fflush()}') &
AGENT_PID=$!
```
Process substitution doesn't create a pipeline, so `$!` stays the
agent's PID. `awk` with `fflush()` line-flushes prefixed output
immediately.
Applied to all 17 starters via `generate-starters.ts` + the template.
### Cause 2a — hidden langgraph-fastapi crash
`generate-starters.ts` rewrites relative imports to absolute for
langgraph starters (langgraph_cli loads modules standalone, not as
packages). The rewrite was flat: `from .X import ...` -> `from
<agentDir>.X import ...`. For a file at
`<agentDir>/tools/get_weather.py`, `from .types import ...` resolves to
`tools.types` (the CURRENT package), not `<agentDir>.types`. The flat
rewrite dropped the `tools` segment and produced:
```
ModuleNotFoundError: No module named 'src.agents.types'
```
at import time. The agent crashed; the `sed` pipe bug swallowed the
traceback; the 2-3s sleep guard caught the window while `sed` was still
alive; `/api/health` reported `agent: "error"`.
Fix: make the rewrite subdir-aware — compute the file's containing
Python package from its relative path under `agentDest` and prepend that
to the relative import target. So `from .types import ...` inside
`src/agents/tools/get_weather.py` becomes `from src.agents.tools.types
import ...`.
langgraph-python had the same broken imports in `tools/__init__.py` but
doesn't crash at runtime because `main.py` doesn't import from `tools`
(dead path). Regenerating fixes the dead code too.
## Verification
### Middleware logic (reduced reproduction)
```python
# With HealthMiddleware installed above the routing layer:
app = FastAPI()
app.add_middleware(HealthMiddleware)
app.mount("/", mounted)
c.get("/health") # 200 {"status": "ok"} <- short-circuited
c.get("/anything") # 200 agent-saw:/anything <- reaches mount
c.get("/") # 200 agent-saw:/ <- reaches mount
```
### Tests
- `showcase/scripts` vitest: 1061/1061 passing
- `generate-starters.test.ts` (258) and `starter-consistency.test.ts`
(306) both still green — no test updates required
### Starters touched
- Cause 1 (HealthMiddleware): ag2, agno, claude-sdk-python,
crewai-crews, google-adk, langroid, llamaindex, ms-agent-python,
pydantic-ai, strands (10)
- Cause 2 (entrypoint PID): all 17 starters via generator + template
- Cause 2a (langgraph import): langgraph-fastapi (crash path),
langgraph-python (dead path)
## Commits
1. `fix(showcase/starters): serve /health via middleware to bypass
FastAPI mount shadow` — Cause 1
2. `fix(showcase/starters): capture real agent PID in entrypoint.sh +
unbuffer stderr` — Cause 2
3. `fix(showcase/starters/langgraph-fastapi): correct src.agents.tools.*
imports` — Cause 2a
## Test plan
- [ ] Docker build + run ag2: `curl -i http://localhost:3000/api/health`
returns 200 `{"status":"ok",...}`
- [ ] Docker build + run langgraph-fastapi: health OK, agent imports
succeed, no ModuleNotFoundError in logs
- [ ] Docker build + run langgraph-typescript: health OK
(entrypoint-only fix)
- [ ] Post-merge Railway: monitor all 17 starter health endpoints return
`status: "ok"` after redeploy
- [ ] Post-merge: inspect logs for any starter that still reports
`degraded` — with awk+fflush+PYTHONUNBUFFERED, the real import/crash
error should now surface in container logs
## Safety notes
- No `.github/workflows/*.yml` edits
- No force-push, no amend
- Author: Jordan Ritter <jordan@copilotkit.ai>
- Do NOT merge until reviewer approves
|
||
|
|
05f181891d |
chore(showcase): ratchet validate-pins baseline for main (post-4095) (#4097)
## MERGE ASAP — main is RED `Showcase validate` / `Run validate-pins (ratchet)` is failing on main after PR #4095 (agno SDK upgrade) merged. This PR unblocks main CI. ## What drifted Pure **set drift** — count unchanged, hash differs: | field | before | after | | --- | --- | --- | | `validatePinsFailCount` | 110 | **110** (unchanged) | | `validatePinsFailHash` | `c87ecdd6…a45560` | `958bcf24…4ae17` | From failing run [24632821166](https://github.com/CopilotKit/CopilotKit/actions/runs/24632821166): ``` validate-pins FAIL: actual=110 baseline=110 validate-pins HASH: actual=958bcf24c27cef69d7856e12deafe92073af7ad716289b2f6e4418827264ae17 baseline=c87ecdd6cc0829f8ef93c6e3cc4bb30aa3a577f99c5c8e9349b7c2dc78a45560 ``` ## Why PR #4095 (`fix(showcase/agno): upgrade agno SDK to 2.5.17`) ratcheted the hash against its own branch state, but other PRs merged in between (#4094 google-adk, #4092 chown, etc.) shifted the baseline further. End result: one `[FAIL]` healed while another regressed — net zero on the counter but the failing tuples changed, so the hash no longer matches. ## What this PR does Re-ratchets `showcase/scripts/fail-baseline.json` to the hash currently produced by main. Count stays at 110. ## Risk Minimal. Single field change in a JSON baseline file. No workflow edits. No source changes. Does not hide new regressions — if any NEW failure appears after this merges, the count (not just the hash) will bump and CI will catch it. ## Test plan - [x] Extracted actual hash from failing run output, not guessed - [ ] CI green after merge (unblocks main) |
||
|
|
de586ececd |
chore(showcase): regenerate starters post-#4095 rebase
- Regenerate agno starter to pick up agno>=2.5.17 (from #4095) - Ratchet validate-pins fail-baseline hash to match new FAIL set (count unchanged at 110; hash rotates because agno Dojo/showcase pair now reflects the SDK upgrade) |
||
|
|
689a4b8da7 |
fix(showcase/strands): teach _FakeFastAPI stub to accept add_middleware
agent_server.py now calls app.add_middleware(HealthMiddleware) to serve
/health above the routing layer (restores starter health accuracy after
create_strands_app's catch-all at "/" shadowed @app.get("/health")).
Both _FakeFastAPI stubs — in tests/python/conftest.py and
tests/python/test_instrumentor_patch.py::test_agent_server_module_installs_patch —
only covered the decorator surface (get/post/put/delete/patch). When the
test execs agent_server.py verbatim under the stub, add_middleware raises
AttributeError and fails Python unit tests (3.12). The 3.10 matrix skips
strands (ag_ui_strands requires >=3.12) so the regression only showed
under 3.12.
Mirror the stub's API with a no-op add_middleware so the module loads
cleanly; the patched ThreadingInstrumentor assertion is still the
invariant under test.
|
||
|
|
e45d86b8f3 | style: auto-fix formatting | ||
|
|
dfd8346bc1 |
fix(showcase/starters/langgraph-fastapi): correct src.agents.tools.* imports
generate-starters.ts rewrites relative imports to absolute for langgraph starters because langgraph_cli loads modules standalone rather than as packages. The rewrite was flat: from .X import ... -> from <agentDir>.X import ... For a file at <agentDir>/tools/get_weather.py, `from .types import ...` resolves to `tools.types` — the CURRENT package — not `<agentDir>.types`. The flat rewrite dropped the `tools` segment and produced: ModuleNotFoundError: No module named 'src.agents.types' at startup. The agent crashed during module import; the entrypoint pipe swallowed the traceback (see previous commit for the pipe bug); the 2-3s sleep guard happened to fire while `sed` was still alive; and Railway's /api/health probe reported `agent: "error"`. Make the rewrite subdir-aware: compute the file's containing Python package from its relative path under agentDest, and prepend that to the relative import target. So `from .types import ...` inside `src/agents/tools/get_weather.py` becomes `from src.agents.tools.types import ...`. langgraph-python has the same broken imports in its tools/__init__.py but doesn't crash at runtime because main.py doesn't import from tools (dead path). Regenerating fixes the dead code too. |
||
|
|
de815ae2d5 |
fix(showcase/starters): capture real agent PID in entrypoint.sh + unbuffer stderr
The entrypoint.sh template used `cmd 2>&1 | sed 's/^/[agent] /' &`
followed by `AGENT_PID=\$!`. After a pipeline, `\$!` points to the LAST
command in the pipe (the `sed` process), not the agent. Every subsequent
`kill -0 \$AGENT_PID` and `wait -n \$AGENT_PID` was therefore monitoring
`sed`, which stays alive until its stdin closes — long after the agent has
crashed. Railway restarts the container mid-loop; the health probe sees
`{status: "degraded", agent: "down"}` for a few seconds during each cycle.
A second, compounding bug: `sed` buffers by default, and Python agents
buffer their own stdout, so a stack trace emitted during module import
could sit in userspace memory until the pipe closed — by which point the
log was discarded and the real cause of the crash was lost.
Fix both by switching to bash process substitution:
cmd &> >(awk '{print "[agent] " \$0; fflush()}') &
AGENT_PID=\$!
Process substitution does not create a pipeline, so `\$!` remains the
agent's PID. `awk` with `fflush()` flushes each prefixed line to the
container log immediately. Also export `PYTHONUNBUFFERED=1` at the
entrypoint level so Python-based agents don't buffer before awk.
Applies to all 17 starters (python, langgraph-python, langgraph-fastapi,
langgraph-typescript, mastra, typescript, java/spring-ai, csharp/
ms-agent-dotnet). Done once in generate-starters.ts + the template +
regenerated entrypoint.sh files.
|
||
|
|
20efc40960 |
fix(showcase/starters): serve /health via middleware to bypass FastAPI mount shadow
Python FastAPI showcase starters were registering an @app.get("/health")
handler BEFORE app.mount("/", ...) (or the adapter's equivalent catch-all).
Starlette's Mount at "/" is a prefix match that swallows every subsequent
request including /health, so the decorated handler never fired and the
Next.js /api/health probe saw a non-JSON agent response and flagged the
starter as "degraded".
Install a HealthMiddleware (BaseHTTPMiddleware) that short-circuits
GET /health above the routing layer, which runs before any Mount can
claim the path. The agent mount is kept intact so AG-UI traffic at / is
unaffected.
Affects 10 Python agent starters: ag2, agno, claude-sdk-python,
crewai-crews, google-adk, langroid, llamaindex, ms-agent-python,
pydantic-ai, strands.
|
||
|
|
321ceb9fa0 |
chore(showcase): ratchet validate-pins baseline for main (post-4095)
PR #4095 (agno SDK upgrade to 2.5.17) merged into main and shifted the `[FAIL]` set produced by validate-pins.ts. The FAIL count is unchanged (110 -> 110), but the hash of the sorted/deduplicated FAIL lines drifted because a FAIL healed in one package while another regressed — net zero on the counter, different tuples in the set. Re-ratchets `showcase/scripts/fail-baseline.json` to reflect current main: validatePinsFailCount: 110 (unchanged) validatePinsFailHash: c87ecdd6... -> 958bcf24... Main CI is red until this lands; please merge ASAP. Observed from run 24632821166: validate-pins FAIL: actual=110 baseline=110 validate-pins HASH: actual=958bcf24... baseline=c87ecdd6... |
||
|
|
6092c8f888 |
fix(showcase/agno): upgrade agno SDK to 2.5.17 (#4095)
## Summary Bumps the `agno` Python SDK pin from `>=1.7.8` to `>=2.5.17` (latest stable on PyPI) in `showcase/packages/agno/requirements.txt`. ## Why The agno 1.x AGUI interface had a known bug where the terminal SSE event (`RUN_FINISHED` / `TEXT_MESSAGE_END`) was never emitted, causing consumers that block on stream close (such as `/api/smoke` calling `await res.text()`) to hang until AbortSignal fired (25-45s). Agno 2.5.17 emits the terminal `RUN_FINISHED` frame and closes the stream cleanly, even when the underlying LLM call fails (dummy API key -> 401). ## Version | | Before | After | |---|---|---| | Pin | `agno>=1.7.8` | `agno>=2.5.17` | | Installed | 1.7.x | 2.5.17 | ## Breaking changes encountered None in this package. All existing imports continue to resolve without change: - `from agno.os import AgentOS` - `from agno.os.interfaces.agui import AGUI` - `from agno.agent.agent import Agent` - `from agno.models.openai import OpenAIChat` - `from agno.tools import tool` No API adaptation was required. ## Relationship to PR #4093 PR #4093 works around the 1.x SSE bug in the consumer (`/api/smoke`) by reading the stream incrementally and bailing on `TEXT_MESSAGE_CONTENT "OK"`. With this upstream fix, that workaround becomes defense-in-depth rather than load-bearing. **Recommendation:** leave #4093 in place after this merges. It's cheap, it's already written, and it protects against future agno regressions in stream termination. ## Local verification evidence All tests ran against a local `docker build -t agno-test .` of this package (`agno==2.5.17`, Python 3.12.13). ### Imports ``` $ docker exec agno-test python -c "import agno; print(agno.__version__)" 2.5.17 $ docker exec agno-test python -c "from agno.os.interfaces.agui import AGUI; ..." all imports OK ``` ### /api/smoke timing (three consecutive runs) ``` run 1: time=0.256s code=200 run 2: time=0.157s code=200 run 3: time=0.151s code=200 {"status":"ok","integration":"agno","latency_ms":12,"timestamp":"2026-04-19T15:03:36.057Z"} ``` Previously: 25-45s hang ending in `AbortError`. ### Raw SSE stream inspection (dummy OpenAI key -> 401) ``` data: {"type":"RUN_STARTED","threadId":"test-thread","runId":"test-run",...} data: {"type":"RUN_FINISHED","threadId":"test-thread","runId":"test-run"} ``` Stream closes immediately after `RUN_FINISHED`. Terminal event is present. ### Demos (homepage + 9 demo routes) ``` / 200 0.008s /demos/agentic-chat 200 0.010s /demos/hitl 200 0.005s /demos/tool-rendering 200 0.005s /demos/gen-ui-tool-based 200 0.006s /demos/subagents 200 0.004s /demos/shared-state-read 200 0.005s /demos/shared-state-write 200 0.006s /demos/shared-state-streaming 200 0.005s /demos/gen-ui-agent 200 0.005s ``` ### Agent object ``` agent loaded: Agent tool count: 8 model: gpt-4o ``` ## Test plan - [x] `docker build` succeeds with new pin - [x] `import agno` reports 2.5.17 - [x] All existing `from agno...` imports resolve unchanged - [x] `/api/health` returns 200 - [x] `/api/smoke` returns 200 in <1s (was 25-45s hang) - [x] Raw SSE stream contains `RUN_FINISHED` terminal event - [x] Homepage + all 9 demo routes return 200 - [x] Agent object loads with 8 tools - [ ] CI green on PR |
||
|
|
a2fa0bdcb5 |
fix(showcase/google-adk): use Gemini for A2UI planner instead of OpenAI (#4094)
## Summary The google-adk package's primary agent uses Gemini via `google-adk`'s `LlmAgent`, but the secondary `generate_a2ui` tool was calling OpenAI's `gpt-4.1` through `openai.OpenAI()`. Cross-provider dependency with no architectural justification — the A2UI planner's function-calling + forced tool-choice pattern works equally well via `google.genai`. Rewrite to use `google.genai.Client.models.generate_content` with a `ToolConfig` forcing the `render_a2ui` function call (`mode="ANY"` + `allowed_function_names`). Drop the `openai` + `httpx` direct dependency entirely; `google-genai` is already pulled in transitively via `google-adk` and is now pinned explicitly at `>=0.8.0`. Replaces short-term hotfix **PR #4090** (which pinned `openai` in `requirements.txt` after the post-merge Railway deploy of #4083 crashed with `ModuleNotFoundError: No module named 'openai'`). #4090 is already closed; this PR is the architectural correction that keeps the Gemini-primary package on Gemini end-to-end. ## Changes - **`src/agents/main.py`** — `_get_openai_client` → `_get_genai_client` (`lru_cache`'d `google.genai.Client`). Rewrote `generate_a2ui` body to build a `types.Tool(function_declarations=[FunctionDeclaration])`, force the call via `types.ToolConfig(function_calling_config=FunctionCallingConfig(mode="ANY", allowed_function_names=["render_a2ui"]))`, and read the response from `candidates[0].content.parts[*].function_call.args`. Narrowed `except` clause to `genai_errors.APIError`/`ClientError`/`ServerError` + `ValueError` (for construction-time failures). `A2UI_MODEL` env var overrides the default `gemini-2.5-flash` model. - **`entrypoint.sh`** — `OPENAI_API_KEY` guard → `GOOGLE_API_KEY` guard; `REQUIRE_OPENAI_API_KEY` → `REQUIRE_GOOGLE_API_KEY`. Warn / fail-fast semantics preserved. - **`requirements.txt`** — explicit `google-genai>=0.8.0` pin; no `openai`, no `httpx`. - **`src/app/api/health|debug/route.ts`** — report `GOOGLE_API_KEY` status instead of OpenAI/Anthropic/LangSmith (this is a Gemini-only package). - **`playwright.config.ts`** — inject `GOOGLE_API_KEY` to the dev-server env, not `OPENAI_API_KEY` / `OPENAI_BASE_URL`. - **`tests/python/test_generate_a2ui.py`** — rewrote 19 tests to mock `google.genai.Client` in place of `openai.OpenAI`. Preserves every error branch (`a2ui_llm_error`, `a2ui_empty_response`, `a2ui_no_tool_call`, `a2ui_invalid_arguments`) plus the happy path. Added `A2UI_MODEL` override coverage + string-args-parseable-as-JSON fallback. - **`tests/python/test_entrypoint_env_guards.py`** — migrated to exercise the `GOOGLE_API_KEY` / `REQUIRE_GOOGLE_API_KEY` branch. ## Test plan - [x] Unit tests: 53 passed locally (Python 3.12, `google-adk` + `google-genai` + all package deps installed) - [x] `docker build` / `scripts/dev-local.sh build google-adk`: clean - [x] `docker compose up -d google-adk` against latest image: container starts cleanly (no `ModuleNotFoundError`); uvicorn healthy; new WARN emitted when `GOOGLE_API_KEY` unset - [x] `import agents.main` inside the container no longer pulls in any `openai.*` module - [x] L1 (health) + L2 (agent) smoke via `LOCAL_PORTS=1 playwright test integration-smoke -g "google-adk"`: both pass - [ ] L3 (chat) / L4 (tools) smoke: requires a live `GOOGLE_API_KEY`; left to CI / reviewer with secrets |
||
|
|
e3b9defb45 | style: auto-fix formatting | ||
|
|
0aa95d7e15 | chore(showcase): ratchet validate-pins baseline 109->110 for google-genai pin | ||
|
|
f5b69285c3 | style: auto-fix formatting | ||
|
|
420254cfdc |
fix(showcase/agno): upgrade agno SDK to 2.5.17 to fix SSE stream termination
Bumps agno from >=1.7.8 to >=2.5.17 (latest stable on PyPI). The agno 1.x AGUI interface had a known bug where the terminal SSE event (RUN_FINISHED) was never emitted, causing consumers that block on stream close (such as /api/smoke reading via res.text()) to hang until AbortSignal fired at ~25-45s. Verified locally against a docker build of this package that 2.5.17 emits the terminal RUN_FINISHED frame and closes the stream cleanly, even when the underlying LLM call fails (dummy API key -> 401). Measured /api/smoke round-trip: ~150-400ms (was 25-45s timeout). All existing imports (agno.os.AgentOS, agno.os.interfaces.agui.AGUI, agno.agent.agent.Agent, agno.models.openai.OpenAIChat, agno.tools.tool) continue to resolve without changes — no API adaptation required. |
||
|
|
e851ea70e6 | fix(showcase/starters): regenerate google-adk starter after Gemini rewrite | ||
|
|
5bc22a396d |
fix(showcase/google-adk): use Gemini for A2UI planner instead of OpenAI
The google-adk package's primary agent uses Gemini via google-adk's LlmAgent, but the secondary `generate_a2ui` tool was calling OpenAI's gpt-4.1 through openai.OpenAI(). Cross-provider dependency with no architectural justification — the A2UI planner's function-calling + forced tool-choice pattern works equally well via google.genai. Rewrite to use google.genai.Client.models.generate_content with a ToolConfig forcing the render_a2ui function call (mode="ANY" + allowed_function_names). Drop the openai + httpx direct dependency entirely; google-genai is already pulled in transitively via google-adk and is now pinned explicitly at >=0.8.0. Replaces short-term hotfix PR #4090 (which pinned openai in requirements.txt after post-merge Railway deploy of #4083 crashed with ModuleNotFoundError). Changes: - src/agents/main.py: `_get_openai_client` → `_get_genai_client` (lru_cached google.genai.Client). Rewrote generate_a2ui to build a `types.Tool(function_declarations=[FunctionDeclaration])`, force the call via `types.ToolConfig(function_calling_config=...)` and read the response from `candidates[0].content.parts[*].function_call.args`. Narrowed except clause to `genai_errors.APIError`/`ClientError`/ `ServerError` + `ValueError` (for construction-time failures). A2UI_MODEL env var overrides the default gemini-2.5-flash model. - entrypoint.sh: `OPENAI_API_KEY` guard → `GOOGLE_API_KEY` guard; `REQUIRE_OPENAI_API_KEY` → `REQUIRE_GOOGLE_API_KEY`. - requirements.txt: explicit `google-genai>=0.8.0` pin; no openai, no httpx. - src/app/api/health|debug/route.ts: report GOOGLE_API_KEY status, not OpenAI/Anthropic/LangSmith (this is a Gemini-only package). - playwright.config.ts: inject GOOGLE_API_KEY to the dev server env, not OPENAI_API_KEY / OPENAI_BASE_URL. - tests/python/test_generate_a2ui.py: rewrote 19 tests to mock google.genai.Client in place of openai.OpenAI. Preserves every error branch (a2ui_llm_error, a2ui_empty_response, a2ui_no_tool_call, a2ui_invalid_arguments) plus happy path. Added A2UI_MODEL override coverage. - tests/python/test_entrypoint_env_guards.py: migrated to exercise the GOOGLE_API_KEY / REQUIRE_GOOGLE_API_KEY branch. Verification: - Unit tests: 53 passed locally against Python 3.12 (google-adk + google- genai + all package deps installed). - Docker build: clean (showcase-google-adk:local) via scripts/dev-local.sh. - Container startup: `docker compose up -d google-adk` launches cleanly (no ModuleNotFoundError); uvicorn reports healthy; entrypoint emits the new WARN when GOOGLE_API_KEY is unset. - L1+L2 smoke against local compose: both pass for google-adk. - `import agents.main` inside the container no longer pulls in any `openai.*` module. |
||
|
|
a4be366e95 |
perf(showcase): replace recursive chown in starter Dockerfiles with COPY --chown (#4092)
## Summary Replaces `RUN chown -R app:app /app` with `COPY --chown=app:app` across all 17 starter Dockerfiles + 4 shared templates. Every starter ended with a recursive chown over `/app`, which walks ~50k files (Next.js `node_modules` dominates) to fix ownership after the fact. Under the 23-way Depot runner fan-out used by `.github/workflows/deploy-showcase-services.yml`, that step consistently ran 5+ minutes under I/O contention — busting the **15-minute GH Actions job budget** before images could finish pushing. Failed run this fixes: https://github.com/CopilotKit/CopilotKit/actions/runs/24621469277 (22/23 showcase services cancelled mid-push). ## What changed - Create the `app` user right after `WORKDIR /app` in every runner stage so `--chown=app:app` resolves by name. - Add `--chown=app:app` to every runner-stage COPY (including multi-stage `COPY --from=frontend` and `COPY --from=<agent-builder>`). - Drop the trailing `RUN chown -R app:app /app` (or the tail of the compound RUN in the TS starters). - For langgraph starters, fold `chown app:app /app/.langgraph_api` into the same RUN as the `mkdir`, so `langgraph_cli`'s scratch dir remains writable by the runtime user. - Update `showcase/scripts/generate-starters.ts` so the shared templates (`Dockerfile.python/typescript/dotnet/java`) emit the new pattern. Starters are regenerated from templates. ## Local timing (Docker Desktop, single starter, no contention) | Starter | Pre-fix | Post-fix | `chown -R` step | | --- | --- | --- | --- | | ag2 (Python) | 3:03 | 1:39 | 50.1s → removed | | langgraph-fastapi | n/a | 1:41 | replaced with 0.2s targeted chown on `.langgraph_api` | | mastra (TS) | n/a | 2:16 | removed | The real-world win on the 23-way Depot fan-out is substantially larger than the local 50s baseline — recursive chown degrades super-linearly with concurrent I/O pressure, which is exactly what the 5+ min Depot step demonstrated. ## Smoke tests - ag2 image: container starts clean as `app` user, all files under `/app` owned by `app:app`, `/api/health` returns 200. - langgraph-fastapi image: `/app/.langgraph_api` exists and is owned by `app:app`. - mastra image: builds cleanly, ownership correct. ## Test plan - [ ] CI green (existing showcase starter smoke suite covers startup) - [ ] Watch the next showcase deploy workflow run — expect jobs to finish well under 15m ## Not touched No workflow files, no `examples/` Dockerfiles (none matched the problem pattern), no `chmod -R` offenders (none found). 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
2c73a3480b |
ci: close showcase deploy automation gap for starters (#4082)
## Summary
Two related defects in the showcase deploy pipeline let stale images sit
live on Railway while Slack stayed green. This PR fixes both.
### Defect 1 — Drift detector skipped all starter services
`.github/workflows/showcase_smoke-monitor.yml` listed only 19
**package** slugs in its `SERVICES=(...)` array (ag2, mastra,
llamaindex, ...). Zero **starter** slugs. As a result:
- GHCR `showcase-starter-<svc>` tags were never checked for drift.
- `gh workflow run showcase_deploy.yml -f service=starter-*` was never
auto-dispatched.
- Starter services could run with weeks-old images and no alert would
fire.
`showcase_deploy.yml` already supports `starter-*` dispatch names and
already calls `serviceInstanceRedeploy` for any service with a
`railway_id`, so no change is required there. The fix is extending
`SERVICES=(...)` to include all 17 starter slugs via a
sparse-checkout-driven filesystem enumeration (no more literal
duplication between workflow and `showcase/starters/`).
### Defect 2 — Silent deploy failures reported green
`.github/workflows/showcase_deploy.yml` emitted `::warning::` and exited
0 when a service never returned 200 on its health path within 360s. The
legacy justification (`# Don't fail — sleep-on-idle services take time
to wake`) no longer applies: Railway is on the Pro tier with no
sleep-on-idle, so a 6-minute failure to become healthy is a real
failure. Changed to `::error::` + `exit 1`.
## Round 2 fixes
Round 2 CR raised six findings against the original smoke-monitor +
validator changes. All fixed in this PR:
- **BLOCKING 1/2 — smoke-monitor guard.** Replaced the magic `-eq 19`
sentinel with `grep -c '^starter-'` so adds/removes to the literal
non-starter list can't silently disable the guard. Added `shopt -s
nullglob` around the `showcase/starters/*/` loop so an empty starters
tree no longer corrupts `SERVICES` with a `starter-*` literal.
- **BLOCKING 3 — GHCR stderr isolation.** Dropped `2>&1` on the `gh api
-i` call; captured stderr to a temp file and surfaced it only when `gh`
returns a non-zero RC with no HTTP status. Auth / rate-limit / network
noise can no longer splice into the HTTP header block and poison
`HTTP_STATUS` / `API_BODY` parsing.
- **BLOCKING 4 — validator tests.** Added
`showcase/scripts/__tests__/validate-workflow-starters.test.ts` (12
specs): happy path, missing-from-options-only, missing-from-matrix-only,
missing-from-both, empty starters dir (exit 3), template/ excluded,
substring-spoof (starter-ag2 vs starter-ag2-extended), missing workflow
file (exit 3). Also extended `VALIDATE_WORKFLOW_STARTERS_REPO_ROOT` to
re-home the starters dir for testability.
- **MEDIUM 1 — YAML parsing.** Replaced the fragile regex-over-YAML
options scanner with a real `yaml.parse()` + typed navigation down
`on.workflow_dispatch.inputs.service.options`. ALL_SERVICES stays
regex-scanned (embedded JSON in a bash heredoc, with `${{ ... }}`
interpolations that aren't valid JSON pre-execution), but the
surrounding step is now located via YAML.
- **MEDIUM 2 — Slack list truncation.** Replaced `cut -c1-200` with a
`truncate_csv` helper that drops whole comma-separated entries until
under budget and appends `…` when truncated. No more
`starter-claude-sdk-pyth` mid-slug corruption.
- **MEDIUM 3 — template/ exclusion cross-references.** Both the TS
validator's `EXCLUDED_DIRS` and `showcase_smoke-monitor.yml`'s `[
"$slug" = "template" ] && continue` now carry `# keep in sync with ...`
comments pointing at each other.
- **NIT 2 — entry-check simplification.** Dropped the
belt-and-suspenders `import.meta.url === \`file://${argv[1]}\`` branch;
kept only the canonical `fileURLToPath(import.meta.url)` form.
- **NIT 3 — jq pipeline collapse.** Single-pass `.jobs[]? | select |
"\(...)"` replaces the three-pass `map | map | .[]` chain in the notify
step.
## Files changed
- `.github/workflows/showcase_deploy.yml` — warning → error + exit 1 on
unhealthy deploy; `truncate_csv` replaces `cut -c1-200` (3 sites);
single-pass jq pipeline in notify step.
- `.github/workflows/showcase_smoke-monitor.yml` — filesystem-driven
`SERVICES=(...)`, starter-count guard, `nullglob` loop, stderr-isolated
`gh api` call, cross-reference comment.
- `.github/workflows/showcase_validate.yml` — wires
`validate-workflow-starters` into CI.
- `showcase/scripts/validate-workflow-starters.ts` — YAML-aware presence
checks; env-var override homes both starters dir and workflow path.
- `showcase/scripts/tsconfig.json` — scripts-local tsconfig for LSP type
resolution.
- `showcase/scripts/__tests__/validate-workflow-starters.test.ts` — 12
specs covering the full matrix of drift scenarios.
## Test plan
- [ ] Next scheduled `showcase_smoke-monitor` run includes starter
services in its drift scan.
- [ ] A deliberately-unhealthy deploy (simulate by pointing health_path
at a 404) fails the job and fires the Slack alert.
- [ ] `showcase_validate` CI job runs `validate-workflow-starters` and
`npx vitest run scripts/__tests__/validate-workflow-starters.test.ts`
green.
|
||
|
|
c591ad71b1 |
perf(showcase): replace recursive chown with COPY --chown in starter Dockerfiles
Every starter Dockerfile ended with `RUN chown -R app:app /app`, which
recursively walks the full `/app` tree (Next.js `node_modules` dominates
— ~50k files) to fix ownership after the fact. On the 23-way Depot
runner fan-out used by .github/workflows/deploy-showcase-services.yml
this step consistently took 5+ minutes under I/O contention, busting
the 15-minute GH Actions job budget before the image could even finish
pushing (run 24621469277 — 22/23 services cancelled).
The standard Docker idiom is `COPY --chown=<user>:<group>` which applies
ownership during the copy step itself — no extra layer, no full-tree
traversal, zero runtime cost.
Changes:
- Create the `app` user right after `WORKDIR /app` in every runner
stage so `--chown=app:app` resolves by name.
- Add `--chown=app:app` to every COPY instruction that lands files
under `/app` in the runner stage (including `COPY --from=frontend`
and `COPY --from=<agent-builder>` multi-stage copies).
- Drop the trailing `RUN chown -R app:app /app` (or the tail of the
compound RUN in the TS starters).
- For langgraph starters, fold `chown app:app /app/.langgraph_api`
into the mkdir RUN so langgraph_cli's scratch dir is still writable
by the runtime user.
- Update showcase/scripts/generate-starters.ts so the shared templates
(Dockerfile.python/typescript/dotnet/java) emit the new pattern and
the framework-specific COPY lines (`COPY ${dest} ./` for extra files
and `COPY agent_server.py ./` for Python starters) include `--chown`.
Local verification (Docker Desktop, single starter, no contention):
ag2 pre-fix: 3:03 total, `RUN chown -R app:app /app` = 50.1s
ag2 post-fix: 1:39 total, no chown step
langgraph-fastapi post-fix: 1:41 (langgraph_api chown is 0.2s)
mastra post-fix: 2:16
Smoke test on ag2 image: container starts clean, all files under /app
owned by app:app, /api/health returns 200.
Under the 23-way Depot fan-out the real-world win is substantially
larger than the local 50s baseline because recursive chown degrades
super-linearly with concurrent I/O pressure.
Failed run that motivated this: https://github.com/CopilotKit/CopilotKit/actions/runs/24621469277
|
||
|
|
da487b7e8c |
ci: probe only /api/health in starter smoke test (#4088)
## Summary
The Deployed Starters smoke test is falsely reporting `status=404
path=/health` for every starter whose agent process is degraded. The
reported path is misleading — it's just the last path probed before the
test gave up. The real upstream is a 503 on `/api/health`.
## Root cause
`checkHealth()` in `showcase/tests/e2e/helpers.ts` defaulted to probing
`[\"/api/health\", \"/health\"]` in sequence. All deployed starters and
showcase backends serve their health endpoint at `/api/health` (standard
Next.js convention). `/health` returns a Next.js 404 HTML page.
When `/api/health` returns a legitimate 5xx (e.g. 503 `\"agent
degraded\"`), the helper's `res.ok()` check is false, so it falls
through to probe `/health`, gets a 404, and reports that as
`lastResult`. The Slack alert then reads `path=/health` and implies a
route-missing bug, hiding the real 503.
Verified with live probes:
- Healthy starter `/api/health` → `200 {\"status\":\"ok\",...}`
- Degraded starter `/api/health` → `503
{\"status\":\"degraded\",\"agent\":\"error\",...}`
- Either starter `/health` → `404` (Next.js not-found page)
## Fix (Shape A — remove the fallback)
Change the default `paths` argument from `[\"/api/health\",
\"/health\"]` to `[\"/api/health\"]`. No fallback. The reported status
and body are the actual `/api/health` response.
- `starter-smoke.spec.ts` passes an explicit `paths` argument and is
unaffected.
- `integration-smoke.spec.ts` L1 health check targets `/api/health` on
all deployed backends (verified live on langgraph-python and mastra).
## Out of scope
15/17 starters currently return 503 because their agent processes are
failing. That's a separate investigation — this PR is purely about
making the smoke alert accurate so that investigation can proceed
per-service.
## Evidence runs (all same failure mode tonight)
- https://github.com/CopilotKit/CopilotKit/actions/runs/24619147643
- https://github.com/CopilotKit/CopilotKit/actions/runs/24618944101
- https://github.com/CopilotKit/CopilotKit/actions/runs/24617315522
## Test plan
- [ ] Next scheduled smoke run surfaces `status=503 path=/api/health`
for the 15 degraded starters (agent-down state, clearly attributable)
- [ ] Healthy starters (langgraph-python, one other) continue to pass L1
- [ ] `starter-smoke.spec.ts` (local Docker starters) unaffected — still
uses explicit `starter.healthPaths`
|
||
|
|
35a7e0038a |
fix(showcase): raise /api/smoke upstream timeout from 25s to 45s (#4089)
## Summary Cold-start 502s on showcase package smoke probes (notably `agno`) consistently land just over the 25s upstream budget. The Next.js `/api/smoke` route uses `AbortSignal.timeout(25000)` to call its own `/api/copilotkit` which proxies to the Python agent which calls the LLM. On cold start, the end-to-end round-trip takes >25s and the probe aborts with `latency_ms: 25001, stage: "timeout"`, returning 502. This PR raises the upstream budget from **25s -> 45s** across all showcase packages that exercise a full agent round-trip on smoke, and bumps Next.js `maxDuration` from 30s -> 60s so the route can actually run that long. The `create-integration` template is bumped too so new packages inherit the new budget. The 3 `langgraph-*` routes have a different (lightweight health probe) pattern and `ms-agent-dotnet` is already at 50s — their `maxDuration` is bumped for consistency but their abort budgets are left alone. **Evidence — agno 502 alerts tonight (PDT):** - 18:40 PDT attempt 1 — HTTP 502 on `/api/smoke`, self-recovered - 19:42 PDT attempt 2 — HTTP 502 on `/api/smoke`, `/api/health` already 200 Both probes had `latency_ms: 25001, stage: "timeout"` — a textbook cold-start boundary trip. ## Why 45s (not 60s or 90s) The alert tells us the cold path lands **just over** 25s. 45s gives ~20s of headroom — enough to absorb cold starts without making slow failures look like slow successes. Tail latency beyond 45s would still alert, which is the intent. If we see tail probes >45s, we'll revisit with a post-deploy warmup ping. ## Files changed (17) - 16 `showcase/packages/*/src/app/api/smoke/route.ts` (13 with both abort + maxDuration bumped, 3 langgraph-* with only maxDuration bumped, ms-agent-dotnet untouched) - `showcase/scripts/create-integration/index.ts` template (new packages inherit the new budget) ## Test plan - [ ] Deploy to Railway, observe agno `/api/smoke` no longer 502s on cold start - [ ] Confirm other showcase services still smoke-pass - [ ] If cold path drifts beyond 45s for any service, add a post-deploy warmup step (deferred) Do not merge yet — pending user review. |
||
|
|
11c624b22c |
fix(showcase): unblock L3/L4 smoke across 6 integrations (plus spring-ai L3) (#4083)
## Summary Surfaced by running the integration-smoke suite (`pnpm smoke:local` from PR #4077) against all 17 integrations locally. 8 commits fix L3 (round-trip chat) and/or L4 (tool rendering) for 6 packages — plus spring-ai L3 (L4 still WIP in a follow-up). ## Fixes | Package | Commit | L3 | L4 | Root cause | |---|---|---|---|---| | mastra | `3e8c2b6c` | ✅ | ✅ | `@ag-ui/mastra` forwarded empty-string `resourceId` to Memory. Pass a stable per-demo id. | | langroid (empty delta) | `c7f32cde` | ✅ | — | AG-UI `TextMessageContentEvent` rejects `delta=""`. Skip empty emissions. | | ms-agent-dotnet | `b71a3704` | ✅ | ✅ | `SharedStateAgent` forced `ForJsonSchema<SalesStateSnapshot>()` on every request, killing plain-chat streams via `yield break`. Gate the two-pass on actual sales state. | | google-adk | `2de569f1` | ✅ | ✅ | Gemini intermittently returned empty parts; `simple_after_model_modifier` over-terminated; `PROGRESSIVE_SSE_STREAMING` emitted partial events. Reordered system prompt, hardened modifier, disabled progressive SSE. | | strands (OTel) | `7a8ab4d0` | ✅ | — | `strands-agents` unconditionally calls `ThreadingInstrumentor().instrument()`, recursing fatally. Monkey-patch to no-op before import. | | langroid (tool calls) | `5c059362` | ✅ | ✅ | Adapter only inspected `response.content`; tool calls arrive via `response.oai_tool_calls`. Synthesize `TOOL_CALL_*` events from them. | | strands (tool cap) | `a2b41e71` | ✅ | ✅ | No upstream max-iteration cap led to 300+ weather-tool loops. HookProvider caps at 8 + `stop_streaming_after_result`; `_HookInjectingAgentDict` propagates hooks across per-thread agents since `ag_ui_strands` doesn't. | | spring-ai (L3) | `0c62d462` | ✅ | ⏳ | Spring-AI ignored showcase-wide `OPENAI_BASE_URL` (expects no-`/v1`); HTTP client advertised `Upgrade: h2c` on cleartext; JDK HttpClient pooling reused half-closed sockets. New `SPRING_AI_OPENAI_BASE_URL` + `WebClientConfig` (HTTP/1.1 pin) + `jdk.httpclient.keepalive.timeout=0`. L4 tool-rendering still times out — `BoundedToolCallingManagerConfig` scaffold included; follow-up commit / PR will finalize. | ## Verification Full local run (all 17 integrations via `LOCAL_PORTS=1 SMOKE_ALL=true`): - **30 passed** / **1 failed** (spring-ai L4) / **3 flaky** (agno L3, ag2 L3, strands L4 — all pass on retry) out of 34 L3+L4 tests (17.3 min wall clock) - Every fixed package verified stable at 3/3 reruns against the local Docker stack ## Scope note Fixes are applied in `showcase/packages/*/` only. Some share roots with canonical code in `examples/integrations/` or upstream repos (`@ag-ui/mastra`, `ag_ui_strands`, `strands-agents`, MS Agent Framework samples). Separate backport PRs + upstream issues will follow. ## Test plan - [ ] CI green (unit, format, lint, commitlint, Validate Showcase, package-quality) - [ ] Post-merge Railway deploy of ms-agent-dotnet, mastra, langroid, google-adk, strands shows `/api/health` returning `agent:"ok"` + tool-rendering works in the UI - [ ] spring-ai L4 follow-up PR closes out the last gap |
||
|
|
a05ccfbc68 | fix(ci): skip langroid on Python 3.10 (tests import typing.Self) | ||
|
|
df83668bd0 |
fix(showcase): raise /api/smoke upstream timeout from 25s to 45s
Cold-start on showcase packages with heavy Python agents (agno in particular) consistently lands just over the 25s budget, producing 502s on first probe with latency_ms: 25001 and stage: "timeout". Raise the upstream AbortSignal.timeout on /api/smoke from 25s to 45s across all 16 showcase packages that exercise the full agent round-trip, and bump Next.js maxDuration from 30s to 60s so the route can actually run that long. Also bumps the create-integration template so new packages inherit the new budget. Tail-latency beyond 45s will still alert — which is the intent. Evidence: agno 502 alerts tonight at 18:40 PDT and 19:42 PDT, both with latency_ms: 25001, stage: "timeout" on /api/smoke. /api/health already 200 on both probes — pure cold-start boundary issue. |
||
|
|
4439b79fba |
fix(ci): install pytest-asyncio + skip strands on Python 3.10
Two CI fixes for the showcase_validate python-unit-tests job on PR #4083: 1. Install pytest-asyncio (and pytest-mock) in the shared "minimal test deps" step. langroid/tests/python/test_agui_adapter.py has 16 tests annotated with @pytest.mark.asyncio; without the plugin, pytest reports "async def functions are not natively supported" and skips them. Locally the user's venv has it; CI did not. 2. Surgically skip the strands package on Python 3.10. ag_ui_strands==0.1.0 declares requires-python >=3.12,<3.14, so pip install fails on 3.10 before pytest runs. Prefer the surgical skip over dropping 3.10 from the matrix so the typing_extensions NotRequired fallback path in aimock_toggle.py keeps getting exercised. |
||
|
|
31a7d23d1e |
ci: probe only /api/health in starter smoke test
The Deployed Starters smoke test in integration-smoke.spec.ts uses checkHealth() with its default paths list ["/api/health", "/health"]. All deployed starters serve their health endpoint at /api/health (standard Next.js convention); /health returns a Next.js 404 HTML page. When /api/health returns a legitimate 5xx (e.g. 503 "agent degraded"), the fallback silently probes /health and the resulting 404 becomes the reported failure — so the Slack alert reads "status=404 path=/health" and implies a route-missing bug, hiding the real upstream 503. Shape A fix: change the default to ["/api/health"] only. No fallback. The reported status and body are now the actual /api/health response. starter-smoke.spec.ts passes an explicit paths argument and is unaffected. The integration backend L1 health check also targets /api/health on all deployed backends (verified). Evidence runs (all same failure mode): - https://github.com/CopilotKit/CopilotKit/actions/runs/24619147643 - https://github.com/CopilotKit/CopilotKit/actions/runs/24618944101 - https://github.com/CopilotKit/CopilotKit/actions/runs/24617315522 |
||
|
|
de27e9453f |
fix(showcase/starters): add .NET build outputs to template .gitignore
ms-agent-dotnet starter was hand-patched with bin/, obj/, *.user, *.suo but the template wasn't updated — drift-check kept flagging it on regen. Add the entries to the template so all 17 starters pick them up uniformly (harmless for non-.NET starters). |
||
|
|
d5fab09687 |
fix(ci): install package requirements before running showcase Python unit tests
Python unit-test workflow previously installed only pytest + typing_extensions, assuming stdlib-only tests. Tests now import runtime deps (openai, google.genai, httpx, opentelemetry, etc.) at module load time, causing ModuleNotFoundError at pytest collection before conftest-based stub finders run. Loop each showcase/packages/*/ with a tests/python/ dir, pip install the package's requirements.txt (if present) before pytest. Re-enable pip cache keyed on those requirements files. Matches real-runtime parity. Refs blocker 2 on PR #4083 (fix/showcase-smoke-failures). |
||
|
|
51e6f4869d |
fix(showcase/starters): regenerate after R5 spring-ai template changes
R5 added BoundedToolCallingManagerConfig, OpenAiApiKeyValidator, and WebClientConfig to showcase/packages/spring-ai/agent/ plus updated application.properties and pom.xml. Starters were out of sync so drift-check failed. Ran generate-starters.ts to sync. Also add bin/ and obj/ .NET build artifacts to ms-agent-dotnet starter .gitignore so generator output stays clean. |