Commit Graph

6618 Commits

Author SHA1 Message Date
Alem Tuzlak c92dde419b fix(showcase): complete open-gen-ui scrub + fix smoke-test filter regression (#4029)
## Summary
Prior PR removed the open-gen-ui feature but left several loose ends.
This PR completes the scrub:

1. **Source YAML** — removed `open` profile + `open-gen-ui` entries from
`showcase/shared/constraints.yaml` (was missed before; would have
re-introduced `open-gen-ui` on next generator run)
2. **Schema enum** — dropped `"open"` from `generative_ui` enum in
`showcase/shared/manifest.schema.json`
3. **Test fixture** — `invalid-genui-manifest.yaml` now uses
`[unknown-profile]` instead of `[open]`; tests still pass (validator
rejects unknown profiles)
4. **Manifest descriptions** — all 17
`showcase/packages/*/manifest.yaml` files: "5 GenUI rendering
strategies" → "4" (open-gen-ui was the 5th; now removed)
5. **Derived JSON regen** — `registry.json` regenerated cleanly via
`generate-registry.ts`
6. **Smoke-test filter fix** — `integration-smoke.spec.ts:383` now reads
top-level `i.deployed` instead of stale `i.starter?.deployed`. The old
filter returned 0 starters post-regen (silent CI skip every 6h); new
filter correctly gates on canonical top-level field.

## Context
- `showcase/shell/src/data/demo-content.json` is also regenerated but
NOT committed because it exceeds the lefthook 1MB binary-size cap
(pre-existing repo condition, separate from this PR).
- 3 starters (mastra, crewai-crews, claude-sdk-typescript) that had
manually-patched `starter.deployed: false` are now covered by smoke —
verified all 3 starter URLs respond HTTP 200 live.

## Test plan
- [ ] CI green
- [ ] Post-merge `starter-smoke` workflow picks up all 17 starters (not
zero, as was the silent broken state)
- [ ] No `open-gen-ui` references remain anywhere in showcase/
showcase-previews
2026-04-22 14:34:14 +02:00
Alem Tuzlak d8d6b71490 feat: switch preview captures from GIF to MP4 with GitHub Release storage (#3752)
## Summary

- **CI workflow consolidation**: Merged commitlint into static_quality,
added concurrency groups to test workflows, added path filters to
publish-commit, fixed static_danger matrix bug and python-sdk
concurrency
- **Showcase deploy refactor**: Replaced 23 duplicate jobs with a
dynamic matrix strategy (~1000 lines removed)
- **Preview capture → MP4**: Switched from GIF to optimized MP4 (H.264,
CRF 28, faststart), uploads to GitHub Release `showcase-previews`
instead of committing blobs to the repo. DemoCard uses `<video autoplay
muted loop>` for hover previews.

## Test plan

- [x] Local MP4 capture test passed (langgraph-python, 14KB, 8s, H.264
400x300 @ 10fps)
- [ ] CI workflows pass on this branch
- [ ] Capture workflow produces and uploads MP4 to release
- [ ] DemoCard hover shows video preview when URL is populated

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-22 14:34:01 +02:00
Alem Tuzlak b095cf0443 fix: add remarkPlugins/rehypePlugins passthrough support (#2296) (#3822)
## Summary

Fixes #2296

The Markdown component had hardcoded remark/rehype plugins with no way
for consumers to add their own. This adds optional `remarkPlugins` and
`rehypePlugins` props that are spread into the existing plugin arrays,
enabling custom markdown processing.

## Test plan

- [ ] Verify custom remarkPlugins are applied alongside built-in plugins
- [ ] Verify custom rehypePlugins are applied alongside built-in plugins
- [ ] Verify Markdown renders correctly without custom plugins (no
regression)
2026-04-22 14:26:17 +02:00
Alem Tuzlak 2b88450b44 fix: prevent 'Unknown provider' regression for LangChainAdapter (#3840)
Closes #3217

When `getLanguageModel()` returns null and provider/model are undefined
(as with LangChainAdapter), the code constructed `"undefined/undefined"`
as a model string, causing a cryptic "Unknown provider" error.

Now checks each source of model info explicitly and throws a clear error
message directing users to provide an explicit agents config when using
adapters that don't expose model metadata.

Split from #3838.
2026-04-22 14:23:49 +02:00
Alem Tuzlak d02c5eed6a fix: allow Python 3.13+ in SDK version constraint (#3834)
## Summary
- Widens the python dependency from `>=3.10,<3.13` to `>=3.10,<4`
- Adds Python 3.13 classifier to enable installation on newer Python
versions

Closes #3156
2026-04-22 14:23:04 +02:00
Alem Tuzlak 087255de76 fix: handle null-union types in convertJsonSchemaToParameter (#3825)
## Summary

- `convertJsonSchemaToParameter` now handles null-union types
(`["string", "null"]`) by filtering out `"null"` and recursing with the
resolved scalar type

Closes #2651

## Test plan

- [x] `@copilotkit/shared` tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-22 14:22:28 +02:00
Alem Tuzlak d9c49fbeba fix: add py.typed marker to Python SDK for PEP 561 compliance (#3828)
## Summary

- Added `py.typed` marker file to the Python SDK for PEP 561 compliance,
enabling type checker support

Closes #2921

## Test plan

- [x] Python SDK builds successfully with marker included

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-22 13:36:20 +02:00
github-actions[bot] e713ad2a07 style: auto-fix formatting 2026-04-22 11:20:02 +00:00
Alem Tuzlak 06d24fd8ba Merge remote-tracking branch 'origin/main' into fix/scrub-open-gen-ui
The scrub and #4084 touched the same surface: #4084 re-added an `open:`
generative_ui profile listing `open-gen-ui`/`open-gen-ui-advanced`, and
re-added both features to `constrained-explicit.allowed`. Extending the
branch's scrub to both re-additions keeps the semantic consistent with
the schema (which already dropped `open` from the approaches enum).

- `showcase/shared/constraints.yaml`: drop `open-gen-ui` +
  `open-gen-ui-advanced` from `constrained-explicit.allowed`; drop main's
  re-added `open:` profile entirely.
- `showcase/packages/langgraph-python/manifest.yaml`: drop the now-orphan
  `open-gen-ui` + `open-gen-ui-advanced` feature and demo entries
  (validator confirmed they had no allowed approach left).
- Regenerated `showcase/shell/src/data/registry.json` + sibling
  `shell-docs`/`shell-dojo` registries and `constraints.json` via
  `pnpm --dir showcase/scripts generate-registry`. All 17 integrations
  validate.

`feature-registry.json` intentionally still defines both features — the
original scrub commits (2b996c54d, 27f886e59) left it untouched, so the
demo source files on disk also stay. Follow-up deletion if desired is
out of scope for this merge.
2026-04-22 13:17:34 +02:00
Alem Tuzlak 9ca2fc6d9d fix(ci): 4 hygiene fixes from QA/E2E blitz findings (#4024)
## CI hygiene fixes

Four direct-fix items surfaced during the 2026-04-16 QA/E2E blitz,
bundled as one PR with one commit per fix:

1. **`test_unit.yml` paths-ignore** — add `showcase/**` +
`sdk-python/**` (prevents spurious TS unit matrix runs on showcase-only
or sdk-python-only PRs). `sdk-python-old/**` was mentioned in the plan
but doesn't exist on main; only the two existing dirs are added.
2. **`test_doc-examples.yml`** — scope PR trigger to `branches: [main]`
(matches convention of other workflows).
3. **`e2e_dojo.yml`** — symmetric `.changeset` path filter on push+PR
(was asymmetric — already in the `dorny/paths-filter` step's `ts:` list,
so this aligns the trigger).
4. **`starter-smoke.yml`** — rename internal job id (`starter-smoke` →
`smoke-starter`) and artifact name pattern (cosmetic; matches the new
`test_<layer>-<target>` / `smoke-<layer>` naming convention; no external
consumers).

### Fix skipped

**`showcase_smoke-monitor.yml` slug normalization** (item #10 in the
Notion page) — inspecting the file, it already uses the
`showcase/packages/` slug convention (`ms-agent-python`,
`ms-agent-dotnet`, `strands`). The apparent inconsistency is actually in
`starter-smoke.yml`, whose matrix keys must stay as
`ms-agent-framework-*` / `strands-python` because they are literal
directory names in `examples/integrations/` (used as `working-directory:
examples/integrations/${{ matrix.starter }}`). So there is no actionable
change here — the two files use different slug conventions *by
necessity*, because they target different directories (deployed
`showcase/packages/*` vs. local `examples/integrations/*`). Flagging for
the author of the blitz notes in case the actual concern was something
else.

Refs: [Bugs Found During
Blitz](https://www.notion.so/3443aa381852812fb595c5118dd68818) items #3,
#8, #9, #12.
2026-04-22 13:08:40 +02:00
Alem Tuzlak 7c00903c6a Merge remote-tracking branch 'origin/main' into jpr5/ci-workflow-optimization
# Conflicts:
#	.github/workflows/showcase_capture-previews.yml
2026-04-22 13:03:04 +02:00
Alem Tuzlak 3f6c80d8a0 Merge branch 'main' into fix/issue-2921 2026-04-22 12:59:18 +02:00
Alem Tuzlak 2a800f99a7 Merge branch 'main' into fix/issue-3156 2026-04-22 12:57:58 +02:00
Alem Tuzlak 77dd2abc29 Merge remote-tracking branch 'origin/main' into fix/remark-rehype-plugins-2296
# Conflicts:
#	packages/react-ui/src/components/chat/Markdown.tsx
2026-04-22 12:53:35 +02:00
Alem Tuzlak 38e95491e7 refactor(react-ui/Markdown): pass through all react-markdown Options via spread
Addresses PR feedback on #3822.

Instead of plumbing remarkPlugins and rehypePlugins through the component
one prop at a time, MarkdownProps now extends Omit<Options, "children">
and spreads the remainder into the underlying ReactMarkdown. Consumers
can now pass any react-markdown Options field (urlTransform, allowedElements,
skipHtml, etc.) without further plumbing.

The three fields that need library-specific defaults (components,
remarkPlugins, rehypePlugins) are still destructured, merged, and memoized
internally so the built-in behavior is preserved and merged values keep
stable references across renders.

Dropping the custom memo comparator — now that arbitrary props flow
through, a fixed 4-key check would silently skip re-renders when
consumer-provided props change. React's default shallow-compare, combined
with the internal useMemo on merged values, gives correct behavior without
regressing the memoization for the common case.
2026-04-22 12:50:09 +02:00
Alem Tuzlak acb30f23cc Merge branch 'main' into fix/issue-2651 2026-04-22 12:42:19 +02:00
Alem Tuzlak db38f50918 test(runtime): cover handleServiceAdapter model-source resolution (#3217)
Covers the three branches added by the fix:
- getLanguageModel() returns a LanguageModel -> wired into BuiltInAgent
- provider + model strings present -> composed as "provider/model"
- neither present (e.g. LangChainAdapter) -> throws CopilotKitMisuseError
  with adapter name in the message, instead of silently producing
  "undefined/undefined" and failing downstream.

Also guards the partial-info case where only one of provider/model is set
to ensure the regression doesn't re-emerge via a half-populated adapter.
2026-04-22 12:39:31 +02:00
Alem Tuzlak b8349d2067 fix(sdk-python): copilotkit_interrupt handles non-list resume values (#3096) (#3784)
## Summary
- `copilotkit_interrupt` now handles string and dict resume values from
LangGraph 1.x's `interrupt()`
- Previously crashed with `AttributeError: 'str' object has no attribute
'content'` or `KeyError: -1`
- Type-checks response: str returned directly, dict JSON-serialized,
list uses existing `[-1].content` path

## Test plan
- [x] Red-green test: string resume value returns without crash
- [x] Red-green test: dict resume value returns JSON string
- [x] Test: list resume value still works (existing behavior)
- [x] Full test suite passes (15/15)

Closes #3096
2026-04-22 12:33:27 +02:00
Alem Tuzlak d6ff5772ed fix(sdk-python): LangGraphAGUIAgent serializes Context objects to dicts (#3690) (#3787)
## Summary
- `LangGraphAGUIAgent.langgraph_default_merge_state` now calls
`model_dump()` on Pydantic Context objects before storing in copilotkit
state
- Previously stored raw Pydantic objects, causing JSON serialization
failures downstream
- Handles mixed types: Pydantic objects get `model_dump()`, plain dicts
pass through unchanged
- Matches the existing pattern already used in `CopilotKitMiddleware`

## Test plan
- [x] Red-green test: AG-UI Context objects stored as plain dicts, not
Pydantic
- [x] Red-green test: mixed Pydantic + dict context items all
serializable
- [x] Full test suite passes (15/15)

Closes #3690
2026-04-22 12:33:14 +02:00
Alem Tuzlak 51b0513eab Merge remote-tracking branch 'origin/main' into fix/issue-3156
# Conflicts:
#	sdk-python/pyproject.toml
2026-04-22 12:13:45 +02:00
Alem Tuzlak e71b27ed97 Merge remote-tracking branch 'origin/main' into fix/issue-2651
# Conflicts:
#	packages/shared/src/utils/json-schema.ts
2026-04-22 12:02:32 +02:00
Alem Tuzlak b28d15339c feat(react-core): add pin-to-send scroll mode to CopilotChat v2 (#4142)
## What does this PR do?

Adds a new `"pin-to-send"` value to `CopilotChatView`'s `autoScroll`
prop, matching ChatGPT's scroll behavior: when the user sends a message,
that message scrolls to the top of the viewport and stays there while
the assistant's response streams in below. The user reads at their own
pace — the viewport does not chase the bottom.

### New public API

```ts
autoScroll?: "pin-to-bottom" | "pin-to-send" | "none" | boolean
```

- `"pin-to-bottom"` — current behavior. Chases the bottom as content
streams (still the default).
- `"pin-to-send"` — **new.** Scrolls the latest user message to ~16px
from the top, maintains a dynamic bottom spacer so the message can
actually reach the top, and does not chase the bottom.
- `"none"` — no auto-scroll.
- Boolean back-compat: `true` → `"pin-to-bottom"`, `false` → `"none"`.
Existing consumers unchanged.

`AutoScrollMode` type is exported from the package barrel.

### Example usage

```tsx
<CopilotChat autoScroll="pin-to-send" />
```

### How it works

1. `CopilotChat` computes the latest user message ID from `messages` and
publishes `{ id, sendNonce }` via a new `LastUserMessageContext`. The
nonce increments on each new send so message edits also retrigger.
2. A new `usePinToSend` hook reads the context and, on each new send:
measures viewport + user message heights, sets a spacer `<div>`'s
height, then does a single smooth `scrollTo` to the user message's
offset.
3. A shrink-only `ResizeObserver` on content collapses the spacer as the
assistant's response fills space below, so there's no wasted empty
space.
4. `ScrollView` branches on the normalized mode: existing
`<StickToBottom>` path for `"pin-to-bottom"`, existing plain-div path
for `"none"`, new `PinToSendScrollContainer` for `"pin-to-send"`.

### Edge cases handled

- Thread restore with existing messages doesn't trigger a spurious
scroll.
- `scrollTo` target computed via `getBoundingClientRect` arithmetic —
robust across any CSS positioning.
- Virtualization: the spacer lives outside the virtualized list.
- Back-compat: `autoScroll={true|false}` produces byte-for-byte
identical DOM to pre-change.

### Tests

- 7 unit tests for `normalizeAutoScroll`.
- 4 TDD behavior tests for `usePinToSend` (spacer sizing, scroll target,
shrink-only ResizeObserver, cleanup).
- 5 integration tests for `CopilotChatView` covering all three modes +
boolean back-compat.
- Full `@copilotkit/react-core` suite: **85 files / 1120 tests pass,
zero regressions.**
- publint + attw green across all 13 packages.
- Existing `CopilotChatView.slots.e2e.test.tsx` (43 tests) unchanged.

## Related PRs and Issues

- (none — new feature)

## Checklist

- [x] I have read the Contribution Guide
- [ ] Docs site update to follow in a separate PR

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-22 10:54:35 +02:00
Jordan Ritter 307172e9d1 fix(showcase/langgraph-typescript): bind liveness probe before heavy module imports (#4148)
## Summary
- Split `server.mjs` into `liveness.mjs` (new entry) + `server.mjs`
(actual langgraph-api server).
- `liveness.mjs` binds `/ok` on :8124 first, then dynamic-imports
`server.mjs` to kick off the real langgraph bootstrap.
- `src/agent/package.json` `start` script now runs `node --import tsx
liveness.mjs` as the entry.

## Why
#4140 put the probe inside `server.mjs` under the belief it would bind
"synchronously before any await." ES module semantics say otherwise —
all top-level `import` declarations resolve before any module-body code
runs. Cold start of `@langchain/langgraph-api` + graph transpile takes
~4m30s on Railway, but watchdog grace (180s) + strikes (90s) = 270s
kills before the probe ever opens. Dynamic import defers the heavy load
until after liveness is already serving 200.

## Test plan
- [x] Local Docker build green (amd64)
- [x] Container serves /ok within <2s of launch (measured: 1.4s)
- [ ] Railway deploy green + smoke passes sustained
2026-04-21 22:24:16 -07:00
Jordan Ritter d708419911 fix(showcase/langgraph-typescript): bind liveness probe before heavy module imports
PR #4140 placed the liveness probe inside server.mjs under the belief it
would bind "synchronously before any await." That is not how ES modules
work — all top-level `import` statements resolve before any module-body
code runs. `@langchain/langgraph-api/server` takes ~4m30s to cold-import
on Railway (graph eval + tsx transpile), but the watchdog's 180s grace +
3x30s strikes = 270s kills the container ~4s before the probe would have
bound. Kill-loop forever.

Split into:
- `src/agent/liveness.mjs` (new entry): binds :8124/ok immediately using
  only `node:http`, then dynamic-imports server.mjs so the heavy langgraph
  bootstrap runs AFTER :8124 is already serving 200.
- `src/agent/server.mjs`: removed the now-dead sibling-probe code; comment
  block explains why.
- `src/agent/package.json`: `start` script now runs `node --import tsx
  liveness.mjs` instead of `server.mjs`.
- `entrypoint.sh`: comments updated to describe the new ordering.

Local smoke (docker build + run on linux/amd64): /ok returns 200 within
1.4s of container launch vs the previous ~4m34s.
2026-04-21 22:19:12 -07:00
Jordan Ritter ba578c5a29 feat(showcase): multi-stage Docker refactor across template, 17 starters, 17 packages (#4147)
## Summary
- Rewrite starter Dockerfile templates (`typescript`, `python`, `java`,
`dotnet`) as true multi-stage: builder has dev tools, runner is minimal.
No `pip`/`npm`/`pnpm`/`tsx`/`*-cli dev` in runtime stages.
- Encode prod-mode behaviors for `claude-sdk-typescript`, `mastra`,
`langgraph-typescript` directly in the TS template + generator
conditionals (folds in the pattern from #4132 for langgraph-ts; adds
parallel migration for claude-sdk-ts + mastra).
- Regenerate all 17 starter Dockerfiles.
- Rewrite all 17 package Dockerfiles to match the template shape
(multi-stage, venv builder for Python, 3-stage Python runtime, `USER
app`, etc.).
- Cold-start instrumentation on `claude-sdk-typescript` package
(absorbed from closed PR #4133).
- Pin `platforms: linux/amd64` in the showcase deploy workflow
(`docker/build-push-action` step) to match what Railway + GHCR require.
- Template `README.md` documenting multi-stage conventions, size target,
platform mandate, and the `dockerfile_hygiene` probe.
- `generate-starters.ts` strips the `langgraph-typescript` starter's
dead `server.mjs` + its `start` script (both reference deps only needed
in the package's prod-mode path).

## Why
Railway cold starts exceed the 180s watchdog grace when the runtime
stage boots via `langgraph-cli dev` / `npx mastra dev` / `npx tsx` — the
dev-mode work (TS compile, Rollup bundle, native libsql init) blocks the
health probe. #4132 proved the fix is to move this to image build time
for langgraph-ts. This PR generalizes that shape to all TS starters that
need it and reshapes every Dockerfile in the tree so runners no longer
carry dev toolchains.

Secondary outcomes:
- Smaller runtime images (pip/npm toolchain moved to builder only).
- Consistent `--platform linux/amd64` pinning end-to-end.
- No `pnpm install --frozen-lockfile` in the TS starter template
(starters are no-lockfile by design).
- `validate-pins` ratchet re-baselined to match the regenerated spec
strings.

## Test plan
- [ ] `docker build --platform linux/amd64` green for every starter (17)
and package (17) locally
- [ ] `pnpm -C showcase/scripts` vitest: 1085/1085 pass
- [ ] `tsc --noEmit -p showcase/scripts/tsconfig.json` clean
- [ ] `oxfmt --check` + `oxlint` clean on touched TS files
- [ ] validate-pins: count 110, hash matches updated baseline
- [ ] CI Showcase Validate green on PR HEAD
- [ ] Post-merge: showcase deploy for mastra + claude-sdk-typescript
goes green (currently flapping)
2026-04-21 20:14:57 -07:00
Jordan Ritter e35071106c chore(ci): add interim keep-alive cron for showcase starters (#4126)
## Why

Adds an interim GitHub Actions cron that curls `/api/health` on each of
the 17 showcase starter services every 5 minutes. The goal is to keep
the agent's in-memory state warm — JIT tiers, module cache, connection
pools. Railway Pro tier doesn't sleep containers, but warm-state still
decays over idle periods.

This is a stopgap until the `showcase-ops` service (see Notion proposal
§2a) lands. Its smoke probe runs at the same cadence and will subsume
this workflow entirely.

## What

New file: `.github/workflows/showcase_keep-alive.yml`

- Schedule: `*/5 * * * *` (every 5 minutes) + manual `workflow_dispatch`
- Matrix over all 17 starter slugs (`ag2`, `agno`, `claude-sdk-python`,
`claude-sdk-typescript`, `crewai-crews`, `google-adk`,
`langgraph-fastapi`, `langgraph-python`, `langgraph-typescript`,
`langroid`, `llamaindex`, `mastra`, `ms-agent-dotnet`,
`ms-agent-python`, `pydantic-ai`, `spring-ai`, `strands`)
- Each cell: `curl -fsS --max-time 15
https://showcase-<slug>-production.up.railway.app/api/health`
- `fail-fast: false` + `continue-on-error: true` so one starter being
down doesn't cancel the others
- No Slack notification — `showcase_smoke-monitor.yml` already covers
alerting. This workflow is strictly keep-alive, not observability.
- Header comment marks it INTERIM and references the showcase-ops
cutover

## Interim marker

Remove this workflow once `showcase-ops` ships its smoke probe at the
same 5-min cadence (tracked in the Notion showcase-ops proposal).

## Test plan

- [ ] Verify workflow parses in the Actions UI after merge
- [ ] Trigger `workflow_dispatch` once manually; confirm all 17 cells
run and pass for healthy starters
- [ ] Confirm no Slack noise generated by this workflow
- [ ] Remove when showcase-ops cutover lands
2026-04-21 20:10:43 -07:00
Jordan Ritter 8a39783e58 fix(showcase/langgraph-typescript): restore watchdog health probe after prod-mode migration (#4140)
## Summary

- Root cause: #4132 migrated langgraph-typescript from `langgraph-cli
dev` (which exposed `/ok` immediately) to `@langchain/langgraph-api`
`startServer`. That server DOES register `/ok` via its meta routes, but
only binds the port AFTER `registerFromEnv` imports the graph and spawns
the N workers. On Railway that window has been exceeding the watchdog's
180s startup grace + 90s strike budget, producing an infinite restart
loop (deploy `ddc88ef9` is flapping ~every 4m30s).
- Fix: move liveness off the heavy Hono path entirely. `server.mjs` now
starts a bare `node:http` server on port 8124 (configurable via
`HEALTH_PORT`) synchronously before any `await`, answering `GET /ok`
with `{"status":"ok"}`. `entrypoint.sh` watchdog now probes
`127.0.0.1:8124/ok` instead of `:8123/ok`.

## Why

The service has been 502-ing all day. Railway deploy `ddc88ef9` never
serves a single `/api/health` 200 despite `[server] LangGraph API
listening on 0.0.0.0:8123` landing in the logs — the `listening`
callback fires after the watchdog has already killed PID 4 and triggered
a restart.

Liveness on a sibling port is independent of whether :8123 has finished
its graph import, so the probe reflects what the watchdog actually cares
about: is the Node process alive and its event loop responsive. A true
hang (event loop pinned) still fails the probe and triggers container
restart, so hang-detection is preserved.

## Test plan

- [x] Local Docker build green (`--platform linux/amd64`, depot)
- [x] Local container `curl http://127.0.0.1:8124/ok` returns `HTTP=200
{"status":"ok"}` within 20s of boot
- [x] `[server] Liveness probe listening on 0.0.0.0:8124` emitted before
`[server] LangGraph API listening on 0.0.0.0:8123`
- [ ] Railway redeploy recovers `/api/health` + `/api/smoke`
2026-04-21 20:10:40 -07:00
Jordan Ritter c71641db2e chore(showcase/scripts): revert validate-pins baseline hash to CI-observed value 2026-04-21 20:10:21 -07:00
github-actions[bot] 24d0ed442c style: auto-fix formatting 2026-04-22 02:49:13 +00:00
Jordan Ritter 40adafd199 fix(showcase/scripts/generate-starters): strip langgraph-ts starter start script referencing deleted server.mjs 2026-04-21 19:38:29 -07:00
Jordan Ritter 00a3fc50bf docs(vscode-extension): correct RELEASING.md and move one-time setup to appendix (#4146)
## Summary

- Correct RELEASING.md prose to reflect the metadata-sync automation:
contributors only edit CHANGELOG.md; the `VS Code Extension — Metadata
Sync` workflow auto-bumps `package.json.version`/`.description` and
commits `chore: release vX.Y.Z` on the PR branch. The old copy still
said maintainers hand-edit `package.json`.
- Fix the Rollback section step 2 to match the new flow (CHANGELOG-only,
sync workflow handles `package.json`).
- Move all one-time bootstrap setup (GH environment variables/secrets +
Open VSX namespace claim) to a `One-time setup (historical reference)`
appendix at the bottom of the doc, under a horizontal rule. The front of
the doc now flows maintainer-first: Cutting a release → CI publish flow
→ Transient failures → Verifying → Rollback → Rollback guidance → Notes.
One-time setup was completed during 2026-04-21 pipeline bootstrap and
shouldn't need redoing; keeping it for disaster recovery only.

## Why

Two readers in a row tripped on the "hand-edit package.json" wording
because the automation now does that for them. And the one-time setup
was the first thing a maintainer saw on every release, even though
they'd never need to run any of it again.

## Test plan

- [x] `oxfmt --write` clean on RELEASING.md (no re-format on second
run).
- [x] H2 order matches the maintainer-first flow: Cutting a release, CI
publish flow, Transient registry failures, Verifying, Rollback, Rollback
guidance, Notes and future work, One-time setup (historical reference).
- [x] No content edits inside the moved sections — only relocation + a
one-line historical-reference intro above them.
2026-04-21 19:32:04 -07:00
Jordan Ritter fbdaa75d65 docs(vscode-extension): correct RELEASING.md to reflect metadata-sync automation
The aimock-parity paragraph and the Rollback section still described
contributors hand-editing both package.json and CHANGELOG.md. That was
stale — the vscode-extension-changelog-sync.yml workflow auto-syncs
package.json.version (and optionally package.json.description) from
the CHANGELOG entry (and README first paragraph) when the PR is opened
and commits 'chore: release vX.Y.Z' on the PR branch.

Rewrite both passages so the documented flow matches reality: contributor
edits CHANGELOG.md only (optionally README.md), sync workflow handles the
package.json bump automatically, publish workflow self-gates via vsce show
and ships on merge to main.
2026-04-21 19:27:11 -07:00
Jordan Ritter d297f7d3e3 fix(vscode-extension): use ovsx verify-pat for Open VSX auth check (#4145) 2026-04-21 19:14:51 -07:00
Jordan Ritter 0ff68241ae fix(vscode-extension): use ovsx verify-pat for Open VSX auth check 2026-04-21 19:10:24 -07:00
Jordan Ritter 7971aafe53 docs(showcase/template): correct Node and Temurin version references in README
Template actually pins node:22-slim for both builder and runner stages,
and eclipse-temurin:21-jre (not -jre-alpine) for spring-ai runner. README
called out node:24 + temurin:21-jre-alpine. Align docs with reality.
Node 24 bump is a separate decision not made in this body of work.
2026-04-21 19:05:50 -07:00
Jordan Ritter 98a6167de2 fix(showcase/packages): remove image-scope NODE_ENV=production from mastra/spring-ai, scope to next-start in langgraph-python entrypoint
Completes the NODE_ENV scope cleanup started in the prior Python
packages commit. Image-scope ENV NODE_ENV=production leaks into every
child process (agent subprocesses, healthchecks, shell scripts) —
several frameworks change behavior under NODE_ENV and should NOT see
'production' when running as an agent backend.

- mastra: Dockerfile drops image ENV; entrypoint.sh now invokes
  'env NODE_ENV=production npx next start' (was relying on image ENV).
- spring-ai: Dockerfile drops image ENV; entrypoint.sh now scopes
  NODE_ENV=production to the Next.js child only (Java agent never
  interpreted NODE_ENV but the scoping matches every other package).
- langgraph-python entrypoint: 'npx next start' now inherits
  NODE_ENV=production via 'env' wrapper (Dockerfile already removed
  image ENV in prior commit).
2026-04-21 19:05:45 -07:00
Jordan Ritter b9bcf2e6b6 fix(showcase/packages-python): drop to USER app across 11 Python packages, add missing /app/public COPY to langgraph-python
All 11 Python runners previously executed as root. Bring them into parity
with langroid (the one Python package that already had the pattern):

- Create uid/gid 1001 'app' user/group before any COPY
- Add --chown=app:app to runner-stage COPY directives
- USER app before EXPOSE/CMD
- langgraph-python: add the missing COPY --from=frontend /app/public line
  (every other Python package has it) plus an empty public/.gitkeep so
  the copy resolves

Packages touched: ag2, agno, claude-sdk-python, crewai-crews, google-adk,
langgraph-fastapi, langgraph-python, llamaindex, ms-agent-python,
pydantic-ai, strands.
2026-04-21 19:05:23 -07:00
Jordan Ritter 400fe8a1ae fix(showcase/starters): regenerate after generator fixes (watchdog cleanup + tsc rootDir + strip langgraph-ts server.mjs)
Mechanical regen; no hand edits. Changes:
- All 17 entrypoint.sh: add '|| true' to cleanup kill (trap + final)
- claude-sdk-typescript Dockerfile: tsc now passes --rootDir .
- langgraph-typescript/agent: remove server.mjs + prune its transitive
  deps from package-lock.json
2026-04-21 19:01:30 -07:00
Jordan Ritter c6437b3443 fix(showcase/scripts/generate-starters): emit || true on watchdog cleanup kill, preserve --rootDir ., strip dead langgraph-ts server.mjs, guard AGENT_DIR expansion
- entrypoint.template.sh: cleanup trap + final kill now tolerate no-match
  (|| true) so trap doesn't abort shell when one of the three PIDs has
  already exited. Package-level entrypoint.sh already had this shape.
- generate-starters.ts: claude-sdk-typescript tsc now uses --rootDir .
  so emitted artifact is /app/dist/agent/index.js (matches entrypoint
  expectation + runner-stage COPY). tsc was inferring agent/ as rootDir
  and stripping the prefix.
- generate-starters.ts: drop server.mjs from langgraph-typescript starter
  output. The starter uses 'npx @langchain/langgraph-cli dev' and never
  invokes server.mjs; the file imports @langchain/langgraph-api/server
  which is not in the starter's extraDependencies (resolution relied on
  transitive hoist via @langchain/langgraph-cli). The file stays in the
  PACKAGE where prod mode does use it.
- generate-starters.ts: assert agentDir non-empty / non-absolute before
  Dockerfile substitution so the 'rm -f {{AGENT_DIR}}/package*.json' line
  can never degrade into 'rm -f /package*.json' across /app.
2026-04-21 19:01:10 -07:00
Jordan Ritter 050cb9085b fix(vscode-extension): run azure/login in dry-run mode (#4144)
Verify Marketplace credential expects an active Azure session via
azure/login, but login was gated only on published==false. When
dry_run=true and version is already published, the verify step ran
without a session and failed. Widening the guard to include dry_run.
2026-04-21 18:50:38 -07:00
Jordan Ritter 5ab3a81468 chore(showcase/starter-langgraph-typescript): sync package-lock.json after prod-mode deps 2026-04-21 18:44:03 -07:00
Jordan Ritter 1638c6f845 ci(showcase): pin linux/amd64 for showcase Docker builds
Add platforms: linux/amd64 to the depot/build-push-action invocation in
showcase_deploy.yml. Railway and GHCR serve x86 hosts, so an arm64-only
image crashes on pull. Matches the platform requirement enforced for
local docker build invocations (documented in
showcase/starters/template/README.md).
2026-04-21 18:42:00 -07:00
Jordan Ritter b64980d0aa style(vscode-extension): preformat workflow yaml and RELEASING.md to match CI formatter 2026-04-21 18:41:48 -07:00
Jordan Ritter bff45416e7 docs(showcase): document multi-stage Dockerfile conventions
Add showcase/starters/template/README.md covering the multi-stage build
convention (builder + runtime split), the >=40% image-size reduction
target, the linux/amd64 platform requirement for local builds, and the
dockerfile_hygiene probe rules (>=2 FROM stages, no dev-dep installs in
the runtime stage).

Expand the header comment on showcase/scripts/generate-starters.ts to
document the >=40% size target, the getAgentBuildSteps/getAgentBuildCopy
handoff in more detail, and the linux/amd64 platform pin in the deploy
workflow.
2026-04-21 18:41:48 -07:00
Jordan Ritter 7febc5cf5d chore(showcase/package-claude-sdk-typescript): add cold-start instrumentation
Package-level service claims to listen on :8000 but Railway health probes
fail. Narrow the cold-start window by timestamping each phase from
entrypoint exec to first /health-serving moment:

- entrypoint.sh: print `[entrypoint] pre-node <ISO>` immediately before
  `node /app/agent_server.js`, pairing with the agent_server.ts prints
  below to chain timestamps across the exec boundary.
- agent_server.ts: print `[agent_server] module loaded <ISO>` before any
  side-effect imports (so import-time hangs surface distinctly from
  init-time hangs), `[agent_server] pre-Anthropic <ISO>` right before
  `new Anthropic(...)`, and include an ISO timestamp in the existing
  app.listen() callback so we can read the delta directly.

No behavior change — only logs added. Next deploy cycle should reveal
which phase consumes the budget and whether the failure mode is
listen-but-unreachable vs. listen-never-reached.
2026-04-21 18:39:48 -07:00
Jordan Ritter 8da71c4a0c merge: Task 3 Lane D — llamaindex/ms-agent-py/pydantic-ai/strands Dockerfiles 2026-04-21 18:38:44 -07:00
Jordan Ritter 46e0571b4c merge: Task 3 Lane C — google-adk/langgraph-fastapi/langgraph-python/langroid Dockerfiles 2026-04-21 18:38:43 -07:00
Jordan Ritter 23f4759ff3 merge: Task 3 Lane B — ag2/agno/claude-sdk-py/crewai-crews Dockerfiles 2026-04-21 18:38:43 -07:00
Jordan Ritter e7322b07c1 merge: Task 3 Lane A — TS+Java+.NET package Dockerfiles 2026-04-21 18:38:37 -07:00
Jordan Ritter 6f5578d647 fix(showcase/package-ms-agent-dotnet): multi-stage Dockerfile with unprivileged user and scoped NODE_ENV 2026-04-21 18:37:59 -07:00