[pull] main from CopilotKit:main#727
Open
pull[bot] wants to merge 4514 commits into
Open
Conversation
…nostics aren't dead code Both entrypoints run under set -e. The tail `wait -n $AGENT_PID $NEXTJS_PID` returns non-zero on the PRIMARY designed exit path (137 = size-gate/watchdog SIGKILL of the agent tree, or an agent crash), so set -e aborted the script AT that line — making EXIT_CODE=$?, the entire 'which process exited with code N' diagnostic, and the final `exit $EXIT_CODE` dead code on exactly the interesting exits. Capture the code with `EXIT_CODE=0; wait -n ... || EXIT_CODE=$?` so the diagnostic and explicit exit run and preserve the exact code (incl. 137); the container-restart path is unchanged. Same class: langgraph's LANGGRAPH_SIZE_THRESHOLD_MB was used in `[ "$DIR_SIZE_MB" -ge "$threshold" ]` with no numericity guard, so a non-integer operator override made the test error and silently no-op the size gate every cycle. Validate the threshold the same way DIR_SIZE_MB already is (numeric case guard + 'size guard inactive' WARNING, then skip safely).
## Release monorepo v1.62.3 **Scope:** `monorepo` | **Bump:** `patch` --- ### How this release process works 1. **This PR was created automatically** by the "release / create-pr" workflow. It bumped the `monorepo` packages to `1.62.3` and generated AI-enhanced release notes. 2. **CI runs on this PR** — the full test suite (unit tests, lint, type checks, build) must pass before merging. This is the review gate. 3. **Review the release notes** in `release-notes.md` in this PR. If a Notion draft was created, you can edit the release notes there before merging. 4. **When this PR is merged**, the `release / publish` workflow automatically: - Builds all packages - Publishes the `monorepo` packages to npm at version `1.62.3` - Creates git tag `monorepo/v1.62.3` - Creates a GitHub Release with the final release notes ### Before merging - [ ] CI is green (tests, lint, types, build) - [ ] Version bumps look correct - [ ] Release notes are accurate (edit in Notion if a draft was created) --- > **Do not merge until CI is fully green.** The full test suite runs automatically on this PR.
…bpath
The package entry (@copilotkit/bot) re-exported runStateStoreConformance from
./testing/state-store-conformance, which imports vitest at module top-level.
An ESM re-export eagerly evaluates that module, so a bare
`import { createBot } from "@copilotkit/bot"` dragged vitest into every
consumer's runtime graph and threw ERR_MODULE_NOT_FOUND when vitest wasn't
installed (i.e. any production consumer).
- Drop the re-export from src/index.ts (entry is now vitest-free)
- Publish the conformance helper under the ./testing export subpath
- Declare vitest as an optional peerDependency (documents the /testing need)
- Update docs to import from @copilotkit/bot/testing
Names/behavior of the runtime API are unchanged; only the import path for the
test-only conformance helper moves.
run-demo.sh detaches everything except the Next.js dev server (docker
compose up -d, native Metal TEI via nohup/disown, then exec pnpm dev), so
Ctrl-C on the dev server leaves the docker stack and the host embedder
running. stop-demo.sh brings those leftovers down in one command.
Tears down, idempotently:
- the Next.js dev server on :3000 (defensive; usually gone via Ctrl-C)
- the docker compose stack (project banking-memory), containers only by
default so a re-run reuses the built image + seeded data
- the native Metal TEI on :7067 (Apple Silicon; the host process docker
doesn't manage), SIGTERM then SIGKILL
Flags: --purge also drops volumes for a clean slate; --keep-tei leaves the
slow-to-warm embedder running when only bouncing the stack.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bpath (#5875) ## Problem `@copilotkit/bot`'s package entry re-exports `runStateStoreConformance` from `./testing/state-store-conformance`, which does `import { describe, it, expect, ... } from "vitest"` at module top-level. In ESM a static re-export **eagerly evaluates** the re-exported module, so a plain: ```ts import { createBot } from "@copilotkit/bot"; ``` drags `vitest` into the consumer's runtime module graph and throws `ERR_MODULE_NOT_FOUND: Cannot find package 'vitest'` for any consumer that doesn't have vitest installed (i.e. every production consumer). `vitest` is only a devDependency. Surfaced while smoke-testing the package rename (OSS-438) — but it's a pre-existing bug on `main`, independent of that rename. ## Fix - **Drop the re-export from `src/index.ts`** → the package entry is now vitest-free. - **Publish the helper under a `./testing` subpath** (`@copilotkit/bot/testing`) — test tooling lives off the runtime entry, the standard pattern. - **Declare `vitest` as an optional `peerDependency`** so consumers of `/testing` get the right signal. - **Docs** updated to `import { runStateStoreConformance } from "@copilotkit/bot/testing"`. Only the import path of the test-only conformance helper changes; the runtime API is untouched. ## Verification - Static import trace: the entry graph is 12 runtime modules, **none** import vitest; every vitest importer is a `.test.js` (not in the graph) or `testing/state-store-conformance.js` (only reachable via `/testing`). - `@copilotkit/bot` builds; **143/143** tests pass; `publint` + `attw` clean (the internal conformance test imports the helper by relative path, unaffected). ## Coordination Touches `packages/bot` on `main`. The OSS-438 rename PR (#5849) renames this package to `@copilotkit/channels`; that PR re-derives from `main` before merge, so it will absorb this fix automatically. If #5849 merges first, this rebases onto `packages/channels` mechanically. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…5877) ## What Adds `examples/showcases/banking/stop-demo.sh` — the teardown companion to the existing `run-demo.sh`. ## Why `run-demo.sh` detaches everything except the Next.js dev server: - `docker compose up -d --wait` (detached stack) - native Metal TEI via `nohup … & disown` (Apple Silicon only) - `exec pnpm dev` (the only foreground process) So Ctrl-C stops *only* the dev server and silently leaves the docker stack (`banking-memory`) and the host embedder on `:7067` running. There was no one-command way to bring those down. This script fills that gap and mirrors `run-demo.sh`'s conventions (same `say`/`ok` helpers, same header-comment style, idempotent). ## What it does Tears down, idempotently, in order: 1. Next.js dev server on `:3000` (defensive — usually already gone via Ctrl-C) 2. docker compose stack (project `banking-memory`), **containers only** by default so a re-run of `run-demo.sh` reuses the built composite image + seeded Postgres 3. native Metal TEI on `:7067` (Apple Silicon; the host process docker doesn't manage) — SIGTERM, then SIGKILL for anything that ignores it ## Flags - `--purge` — also delete the docker volumes (postgres/redis/minio/tei model cache) for a full clean-slate reset - `--keep-tei` — leave the slow-to-warm native embedder running when only bouncing the stack ## Testing - `bash -n stop-demo.sh` — syntax clean - `shellcheck stop-demo.sh` — clean, no warnings - `./stop-demo.sh --help` renders the banner correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary - Backport the website messaging from CopilotKit/website#398 into the shell-docs Slack and Microsoft Teams frontend pages. - Replace the stale waitlist/managed-only framing with "get early access" copy that presents CopilotKit Enterprise Intelligence as the self-hosted or cloud-hosted production layer around the open source Bot SDK. - Frame Slack and Teams as frontends for agents built on any harness or framework, while reserving production-layer terminology for CopilotKit Enterprise Intelligence. - Address browser review annotations on both pages: remove filler in the opener, avoid setup-heavy lead copy, use "open source" without a hyphen, add the full CopilotKit Enterprise Intelligence name to the CTA titles, and keep CTA telemetry surfaces intact. - Update the shell-docs nav test expectation so it matches the current root IA, where Threads lives under Build Chat UIs rather than the generated Intelligence Platform section. ## Validation - `npm run lint` from `showcase/shell-docs` (passes with existing warnings) - `npm run typecheck` from `showcase/shell-docs` - `npm run test` from `showcase/shell-docs` - `npm run build` from `showcase/shell-docs` ## Notes - Hydrated Git LFS assets locally with `git lfs pull` so the shell-docs public asset tests could read real PNG bytes.
…wrapped-PID kill through guarded tree-kill CLASS 1 (guard silently disabled by a bad numeric override): add a reusable _require_int validator and run it at startup over EVERY operator-overridable numeric knob in both entrypoints (size threshold/interval, startup grace, health-probe interval, strike limit). A non-integer/empty override now WARNs and falls back to the documented default instead of breaking a sleep/loop/ arithmetic test. Closes instance #3 (LANGGRAPH_SIZE_CHECK_INTERVAL='60s' killing the size-monitor loop on its first iteration). CLASS 2 (wrapped-PID orphan + kill-0 footgun): route the cleanup() NEXTJS_PID kill through _kill_agent_tree (it is process-sub-wrapped like the agent, so a bare kill orphaned the real Next.js node server holding $PORT across redeploy). Harden _kill_agent_tree and _agent_descendants to refuse a PID that is empty, non-numeric, 0, or 1 (fail closed), making kill -9 0 / kill -9 1 structurally impossible. Remove the ${AGENT_PID:-0} sentinel in the --check-size-once seam; skip with a warning when AGENT_PID is unset instead of defaulting to 0. Shared helper code kept byte-identical between the two entrypoints.
…ect 0 and leading-zero/octal) The _require_int validator in the langgraph-typescript and strands-typescript entrypoints accepted '0' and leading-zero/octal forms like '010'/'08'. Operator typos on any numeric knob then broke a guard: - SIZE_THRESHOLD_MB=0 kills the agent on cycle 1 (instant restart loop) - HEALTH_STRIKE_LIMIT=0 kills on first probe miss - SIZE_CHECK_INTERVAL=0 / HEALTH_CHECK_INTERVAL=0 busy-spin on 'while sleep 0' - '010' is read as OCTAL (8) in arithmetic; '08'/'09' abort under set -e Tighten the predicate to accept only a positive integer with no leading zero ([1-9][0-9]*). Invalid values keep the existing fail-safe behavior: WARN and fall back to the documented default. Helper stays byte-identical across both files.
… review findings Correctness: - C1 create-bot: start() is now idempotent — a second start() no longer re-resolves the backend / rebuilds Transcripts+Telemetry+ActionRegistry or re-connects adapters (which would wipe MemoryStore state and double-bind real adapters). stop() clears the flag so start→stop→start is still a real restart. - S1 bot-slack ingress: a threaded reply that @-mentions the bot is now skipped (app_mention handles it) so the managed path no longer double-responds. Matches both the plain <@U…> and labeled <@U…|handle> mention forms. - S2 runtime: CopilotSseRuntime throws if `bots` is passed without intelligence instead of silently dropping them (guards a JS/as-any caller past the type). - S3 bot-intelligence: startManagedBots rolls back — stops already-started bots — when a later bot fails to start, instead of leaking listeners/connections. Lower: - S4 ingress: stripMentions handles the labeled <@U…|handle> form; DM turns strip mentions too (parity with app_mention/thread_reply). - S5 bot-intelligence: bot-name uniqueness is now case-insensitive. - S6 runtime: fail fast at construction when a declared bot has no name (full shape/uniqueness validation stays at the activation seam — assertValidBotNames — because it can't cross into this CJS package from pure-ESM bot-intelligence). - S7 bot-intelligence: buildActivationMetadata throws on a nameless bot instead of silently filtering it out of the activation set. - S8 bot-intelligence: startManagedBots warns on an empty bots array. - M1 intelligence-adapter: the per-turn egress seq Map entry is deleted after each turn so it can't grow unbounded over a long-running bot. - M2 intelligence-adapter: an inbound file that fails to fetch degrades to a fail-visible text note instead of being silently dropped from model context. - I2 contracts: dropped the now-dead `duplicate_skipped` RenderAccepted value (Intelligence returns duplicate_accepted or a 409 conflict). Changelog (C2/C3, intended behavior after moving init into start()): - bot.transcripts now throws before start() (was a concrete property). - telemetry `oss.bot.configured` now fires at start() rather than construction, so a constructed-but-never-started bot no longer emits it. Not addressed here (cross-repo, tracked on the Intelligence side): - I1 realtime render-event kind:"file" clause on the gateway validator. - I3 lease-token fencing on the render-accept path.
…pk-drawer-reserved-width [ENT-1051] Read grid-template-columns' first track from var(--cpk-drawer-reserved-width, 320px) so when the drawer collapses on desktop (it sets the var to 0) the reserved column collapses and the chat reclaims the space — instead of leaving an empty placeholder column. Mobile (single-column) is unchanged.
…er on desktop [ENT-1051] The floating launcher/collapsed cluster is fixed at the top-left corner. Below 1024px it always shows (already cleared via max-lg:pl-24); on desktop it appears only when the drawer is COLLAPSED. Drive the header's left padding off --cpk-drawer-reserved-width (0px when collapsed, 320px default otherwise) so the logo starts at ~6rem when collapsed and pl-6 when expanded — no overlap. No-op on current packages (var never set → stays pl-6).
…go (6rem->7rem) [ENT-1051]
…[ENT-1051] The 7px/16px launcher inset was tuned for the mobile off-canvas launcher; on desktop it leaked onto the collapsed cluster. Move it into the mobile media query so desktop-collapse uses the element's own 24px gutter default.
… match the drawer [ENT-1051] - Mobile header: max-lg:pb-0 -> pb-4 so chat content clears the fixed launcher/ toggle strip instead of butting right under it (no boundary). - Chat/App ModeToggle: rounded-full -> rounded-[4px] container + rounded-[2px] buttons, matching the drawer's 4px radius cap so the header controls are visually consistent.
…her left matches right gutter, logo/toggle on one line [ENT-1051] - ModeToggle: move left (right-[72px]) so the top-right inspector FAB no longer covers the App segment; grow to 46px (lg:min-h) + center on the logo line (top-6) to match the launcher; keep the 4px corners. - Launcher: left gutter -> 16px to match the right-side controls' inset. - Logo: pt-7 so it centers on the same line as the launcher + toggle.
- ModeToggle: one style on both breakpoints (top-4/right-4 = 16px gutter, 46px min-height, 4px corners); symmetric p-1.5 + fixed 20px button leading so the selected pill has an even gap on all four sides (was tight L/R vs T/B). - Launcher: uniform 16px gutter (top + left) on both breakpoints so it mirrors the toggle; drop the mobile-only 7px override. - Logo: centered on the launcher/toggle middle line (pt-[23px]); wordmark padding normalized so its height matches on both breakpoints. - Inspector FAB: sits beneath the toggle, gap = the 16px top gutter (one rule, no media query, since the toggle is identical across breakpoints). Net: launcher, logo, toggle share center-y; launcher + toggle are both 46px; the FAB tucks under the toggle with a matching gap; the selected toggle pill is evenly inset.
The 1.62.3 release publishes the CopilotThreadsDrawer redesign (web-components + react-core wrapper) and the stateless /suggest feature. Bump the 15 integration examples that consume the drawer from 1.62.2 -> 1.62.3 (package.json + lockfiles) so they pick up the released packages alongside this branch's example CSS. Validated: langgraph-js runs on the published 1.62.3 (no local links) — the redesigned drawer renders (New Conversation, Recent Conversations, filter funnel, desktop collapse toggle, per-row kebab), threads are licensed, and a real agent message round-trips.
…ads list scrolls internally [ENT-1051] (post-release follow-up) (#5828) ## What Applies the threads-drawer grid fix to all 15 integration examples: adds `grid-template-rows: minmax(0, 1fr)` to each example's `.layout` so the drawer's threads list scrolls **internally** (pinned header + New Conversation) instead of the whole page growing to content height. Without this, `height: 100dvh` on a grid whose rows aren't bounded lets the row size to content, so the list can't scroll within the drawer and the delete-confirm dialog centers against a content-tall root. ## Why this is a separate PR These are **example** changes that consume **published** `@copilotkit/*` packages. They were pulled out of the drawer-redesign PR (#5823) so that PR stays scoped to the packages. This one lands **after** the redesigned drawer is released. ## ⛔ Blocked / TODO before marking ready - [ ] Drawer redesign PR #5823 merged - [ ] Lockstep release cut (web-components + react-core + vue + angular) - [ ] Bump each example's `@copilotkit/*` dependency to the new published versions **in this PR** (currently only the CSS is here) - [ ] Re-verify one example end-to-end against the released packages ## Testing - Grid fix verified live during the redesign work (langgraph-js against a hosted Intelligence backend): threads list scrolls internally, header + New Conversation pinned, delete-confirm renders correctly. - Example dependency bumps + a fresh end-to-end pass will be added/redone here once the release is published. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…ce-delivered events (OSS-360/361) (#5761) ## Summary Lets the `@copilotkit/bot` SDK run from **Intelligence-delivered events** without a second programming model, and adds the runtime `bots` declaration API. A managed event (delivered by Intelligence) runs the *same* customer handlers, tools, context, commands, Bot UI, and agents as local/custom adapters — the managed path is "just another `PlatformAdapter`," fed by injected transports. This is the **OSS / SDK slice** of the Hosted Managed Bots work. The credentialed transports (Realtime Gateway, Connector Outbox) and the frozen shared contracts live elsewhere (see *Out of scope*); this PR ships the seams they plug into, fully runnable headless. Relates to **OSS-360** (runtime bots API), **OSS-361** (run the SDK from Intelligence events), **OSS-363** (Slack render/codec reuse). ## What's in here - **`intelligenceAdapter()` bridge** (`@internal`, not publicly documented) — implements `PlatformAdapter` over two injected transports: `DeliverySource` (inbound) + `EgressSink` (outbound). Ingress → `onTurn`/`onCommand`/`onInteraction`/`onThreadStarted`/`onReaction`; ack on success / nack on throw (at-least-once). Egress emits generic operations carrying `BotNode[]` IR with **deterministic ids** (`turnId:seq`, reset per turn) so a redelivered turn reproduces the same ids for the Connector Outbox to dedupe. Idempotency lives at egress, so the managed path skips ingress dedup (`skipIngressDedup`) — a redelivery re-runs rather than being dropped. - **Runtime `bots` API** — `new CopilotRuntime({ intelligence, bots })`, accepted by TypeScript **only when `intelligence` is configured** (discriminated union). `createBot({ name })`; `startManagedBots()` validates names (required, identifier-style, unique — fail-loud), builds activation metadata, and wires each bot to its resolved transport. - **`PlatformCodec` seam** + Slack egress codec (`slackCodec`) composing the existing pure `renderSlackMessage`, so IR→native rendering is shared (no Bolt/creds) instead of duplicated. - **Backwards-compatible SDK foundations**: `bot.addAdapter()` + optional `adapters`, deferred backend resolution at `start()` with `stateStore`-provider precedence (+ multi-provider warning), `bot.transcripts` throws pre-start, optional `eventId`/`turnId`/`deliveryId` on ingress + handler context. Existing `createBot` callers and every `PlatformAdapter` implementer are unaffected. - **In-memory transports + fixture tests** — the full dispatch path (envelope in → handler runs → egress op out) runs with zero Slack/Intelligence/network. ## Out of scope (external / separate tickets) - **Realtime Gateway + Connector Outbox transports** — implemented in the closed-source repo against the `DeliverySource`/`EgressSink` interfaces shipped here. - **Shared contracts freeze (OSS-377)** — consumed here via a minimal, isolated placeholder (`managed/contracts.ts`, marked `TODO(OSS-377)`); swaps in via one import change. - **OSS-363 ingress normalization** — the egress codec is done; extracting the pure Slack event→neutral mapping out of the Bolt listener (so local + Intelligence ingress share it) is the remaining, higher-risk half and is left to that ticket (`TODO(OSS-363)`). ## Testing TDD throughout (RED→GREEN per behavior). New: managed adapter dispatch/ack-nack/ids/run-renderer/exclusivity, all-kinds routing, name validation + metadata + lifecycle, runtime `bots` option, Slack codec. Full suites green: `bot` 147, `bot-slack` 256, `runtime` 1574. All builds typecheck (`bot`/`bot-slack`/`bot-discord`/`runtime`); oxlint/oxfmt clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Drop the resurrected inline buildContentParts method from the adapter; the turn path now uses the extracted ./content-parts.js helper (#5814's refactor). - Port main's fail-visible file-fetch behavior into content-parts.ts so a file that can't be retrieved becomes a short note in both the live-turn and history-seeding paths (they share the helper). - Update the state-store conformance import to the @copilotkit/bot/testing subpath (main moved it there to keep vitest out of consumers' runtime graph).
…restart actually fires (#5874) ## What & why Two showcase agent containers (**langgraph-typescript**, **strands-typescript**) could enter a *running-but-dead* state: Railway showed the service `● Online` while `/api/health` returned **HTTP 502**. This took down all 36 LGT dashboard cells on staging **and** prod (prod's `.langgraph_api` had crossed the 200 MB size-watchdog threshold). **Root cause:** the agent is launched via process substitution (`... &> >(awk …) &`), so `$AGENT_PID` (`=$!`) is the **wrapper subshell**, not the real `npm`→`node` server that holds the port. Every watchdog/cleanup did a bare `kill -9 $AGENT_PID`, which reaped only the subshell and **orphaned the real server** (reparented to PID 1, still bound to the port). The watchdog's "kill agent → container restart → boot-purge" contract therefore never fired: the frontend kept proxying to a dead agent → 502 forever. ## Fixes (each with local red-green on the real entrypoint in `node:22-slim`) 1. **cleanup() EXIT trap** → routes through `_kill_agent_tree` (was orphaning the agent on every SIGTERM/redeploy). 2. **`_kill_agent_tree`** → `/proc`-based tree-kill with a bounded re-scan (root killed last) so mid-walk forks can't escape; refuses PID ≤ 1 (fail-closed). 3. **size-watchdog** hardened against non-numeric `du` and transient errors (no silent gate-disable, no permanent loop death). 4. **strands health-watchdog** → 180 s startup-grace window (parity with langgraph); the now-effective kill would otherwise loop a slow cold start. 5. **`wait -n` under `set -e`** → capture exit code so the restart diagnostic isn't dead code on the primary (137) path. 6. **structural:** one `_require_int` validator over *every* operator-overridable numeric knob (fail-safe to default), and **every** wrapped-PID kill (incl. `NEXTJS_PID`) routed through the guarded tree-kill; dangerous `${AGENT_PID:-0}` sentinel removed. 7. **`_require_int`** requires a positive integer (rejects `0` and leading-zero/octal). ## Incident status Staging **and** prod LGT were restored immediately via redeploy (boot-purge cleared the oversized state) — both `/api/health` → 200. This PR stops the recurrence. ## Review Converged through a 5-round unbiased review-fix loop (1 + 4 confirmation), zero mandatory findings at close, all load-bearing guards independently re-verified. `bash -n` + shellcheck (`-S warning`) clean; 170/170 shell bats pass. ## Follow-up (tracked, separate PR — non-load-bearing) `_require_int` upper-bound clamp (LOW arith-overflow, needs a 20+-digit value); a stale `cleanup()` comment; size-guard unarmed during the startup-grace window; SIZE_PID trap-registration micro-window; diagnostic label on near-simultaneous exit; cosmetic log nits; startup readiness `sleep 3`+`kill -0` probes the wrapper subshell; no dedicated Next.js frontend watchdog.
…hannels* (OSS-438) Renames the Bots SDK to the Channels SDK. Names only — no behavior change. - 8 packages @copilotkit/bot* -> @copilotkit/channels* (git mv dirs, names, workspace: cross-deps). Now includes @copilotkit/bot-intelligence -> @copilotkit/channels-intelligence (landed on main via #5761; unpublished, so renamed fresh with the family). - release.config.json scope keys + versionSource; ReleaseScope union; canary/stable-release/publish-release scope dropdowns; verify script - examples/slack (Kite) + examples/teams: deps, jsxImportSource, imports - showcase/shell-docs: content dirs docs/bots->docs/channels and reference/bot->reference/channels, nav registry, redirects createBot and other API names unchanged. Old @copilotkit/bot* to be deprecated after the new packages publish (bot-intelligence was never published). Re-derived onto latest main (was conflicting after #5761 landed). Refs OSS-438
An unknown delivery kind previously fell through the dispatch switch as a silent no-op (dispatch acks on resolve, so it would ack an unhandled delivery as processed) and mapDeliveryToEnvelope coerced it into an empty turn. Add matching `never` exhaustiveness guards to both so a future wire kind throws instead of being silently swallowed.
…agent_descendants
The /proc PPID walk forked an awk process for every entry in the process
table on every scan pass. Replace the `echo "${stat##*) }" | awk '{print $2}'`
pipeline with the `read` builtin, which word-splits the post-comm remainder
("STATE PPID PGRP …") on IFS and captures the 2nd field with no subprocess.
Byte-identical across the langgraph-typescript and strands-typescript
entrypoints. Non-behavioral; bash -n + shellcheck --severity=warning clean.
…pure-ESM boot
The harness runs as pure Node ESM (package.json "type":"module", built
with tsc moduleResolution:"bundler" which preserves extensionless import
specifiers at emit, launched via node dist/orchestrator.js). Under pure
Node ESM, relative import specifiers must carry the .js extension — a
convention the harness already honors everywhere (79/79 relative imports
in orchestrator.ts end in .js).
The relocated shared/cell-model fold broke that convention: cell-model.ts,
live-status.ts, staleness.ts, and the equivalence fixtures/test imported
sibling modules extensionless ("./live-status", "./staleness", etc). tsc,
vitest, and tsx all resolve those fine, so it built and tested green — but
at container boot node threw ERR_MODULE_NOT_FOUND on
dist/shared/cell-model/live-status and crash-looped the orchestrator,
breaking the staging auto-deploy.
Add the .js extension to every offending relative import to match the
harness convention. Minimal fix — no tsconfig change.
…t crash-loops CI missed the extensionless-import regression because tsc (bundler resolution), vitest, and tsx all resolve extensionless relative specifiers fine — no existing step ever ran the real node dist module graph, which is what the container actually does at boot. Add a boot-smoke to the Validate Showcase job (already gated on showcase/harness/**): after building the harness dist, load dist/orchestrator.js via a node import() and fail hard on ERR_MODULE_NOT_FOUND. A later runtime error from missing env/PocketBase is expected and passes — only a module-resolution failure reddens the build. Verified red-green: the guard exits 1 on the pre-fix extensionless imports and 0 once the .js extensions are added.
…odule-resolution error class The boot-smoke step only treated ERR_MODULE_NOT_FOUND as failure, so other module-resolution regressions (ERR_UNSUPPORTED_DIR_IMPORT, ERR_PACKAGE_PATH_NOT_EXPORTED, ERR_UNKNOWN_FILE_EXTENSION, ERR_INVALID_MODULE_SPECIFIER) were swallowed as BOOT_OK/exit 0 — the very class of bug this gate exists to catch could slip through. It also had no process.exit(0) on the success/expected-error paths and no bounded timeout, so a future open handle at import time could hang node -e to the job's 25-minute ceiling. - Broaden the failure condition to a MODULE_RESOLUTION_CODES set (any of the five codes => BOOT_FAIL, exit 1). Non-module-resolution runtime errors (e.g. the HARNESS_ROLE env guard, no such code) stay BOOT_OK/exit 0. - Add explicit process.exit(0) on both the success and expected-error paths. - Wrap the node invocation in `timeout 120s` (non-zero on timeout => step fails) and add step-level timeout-minutes: 5. Red-green proof (extracted guard logic vs synthetic modules): current logic passes ERR_UNSUPPORTED_DIR_IMPORT / ERR_PACKAGE_PATH_NOT_EXPORTED at exit 0 (RED gap); hardened logic fails all five codes at exit 1, keeps benign runtime error at exit 0, and against the real built dist/orchestrator.js reports BOOT_OK and exits promptly (779ms, no hang).
…egress fix) Add an env-scoped `internalDomain` (showcase-aimock.railway.internal) to the aimock SSOT entry in both envs and emit it as `internalDomains` in the generated JSON. Railway bills public *.up.railway.app traffic as egress even intra-project, while *.railway.internal private networking is free and env-scoped. aimock is ~89% of showcase egress; routing the ~20 demo backends' LLM traffic at the private host over http://showcase-aimock.railway.internal:4010 eliminates the billed path. The public `domain` is retained for health probes. Serviceref host resolution + assertions to follow in subsequent commits on this branch.
ssot_target_host now prefers the env-scoped internalDomains host over the public domains host, so the Stage-2 (U5) serviceRef assertion expects demo backends' OPENAI_BASE_URL/etc. to point at http://showcase-aimock.railway.internal:4010 (free intra-env networking) rather than the billed public egress host. Non-aimock targets (no internalDomains) fall back to their public host unchanged. Red-green: reverting the resolver makes the three new U5 tests fail (public host asserted); restoring makes them pass. Full Ruby spec suite green (184 runs, 715 assertions, 0 failures).
…alert text The aimock-wiring probe matches on hostname, so it needs no code change for the private-networking migration. Add a discriminating test pair proving the internal host (http://showcase-aimock.railway.internal:4010, with :4010 port and /v1 suffix) resolves green while a demo still on the public egress host goes red. Update the aimock-wiring-drift.yml Fix text to point operators at the private host instead of the public production URL.
…e classifier The boot-smoke gate classified pass/fail using only the top-level `e.code`. A module-resolution error that arrives WRAPPED — nested in `e.cause` (possibly a chain), bundled inside an `AggregateError` (`e.errors[]`), or rethrown without preserving `.code` at the top — showed no code to the `MODULE_RESOLUTION_CODES.has(e.code)` check and was misclassified as BOOT_OK, defeating the gate. Add a `collectErrorCodes` helper that gathers every code reachable from the thrown error: the error itself, its cause chain (recursively), and any AggregateError members (recursively), with a depth cap to bound cause cycles. If ANY collected code is a module-resolution code -> BOOT_FAIL / exit 1. Purely additive to the FAIL set: direct top-level codes still redden, and a benign non-resolution runtime error (e.g. the `HARNESS_ROLE must be set` guard, which carries no such code anywhere) still passes as BOOT_OK / exit 0. The `timeout 120s` wrapper, `timeout-minutes: 5`, and success/expected-error `process.exit(0)` are unchanged. Local red-green (classifier extracted to a temp file, driven against synthetic errors): - RED (top-level-only): wrapped cause -> BOOT_OK exit 0 (swallowed); AggregateError member -> BOOT_OK exit 0 (swallowed). - GREEN (hardened): wrapped -> exit 1; aggregate -> exit 1; direct ERR_MODULE_NOT_FOUND -> still exit 1; benign ERR_INVALID_ARG_TYPE and HARNESS_ROLE error -> BOOT_OK exit 0; real built dist/orchestrator.js -> BOOT_OK exit 0 in <200ms (prompt exit, no hang).
…r fails
The boot-smoke previously failed only when the thrown error carried a
module-RESOLUTION code (ERR_MODULE_NOT_FOUND + siblings, walked through
the cause chain / AggregateError members) and passed everything else.
That defaults-to-pass on module-EVALUATION crashes — a top-level throw,
an await-rejection, a bad named binding, or a SyntaxError — none of which
carry a resolution code, so a real boot-crashing regression of that class
would ship green.
The smoke runs `node -e "import('./dist/orchestrator.js')"` with
process.argv[1] UNSET, so bootFleet() (the env/PocketBase validation that
legitimately throws) never runs — only the module graph is linked and
evaluated. A clean build therefore loads with no thrown error, so ANY
error thrown by import() here is a boot regression and must fail the gate.
Now: any rejection -> BOOT_FAIL / exit 1 (resolution AND
evaluation/link/binding/syntax/top-level-throw). Successful load ->
BOOT_OK / exit 0. The collectErrorCodes cause/AggregateError walk is
retained ONLY to label the failure ("module-resolution failure" vs
"boot/evaluation failure") — both exit 1, richer diagnostics preserved.
Kept process.exit(0) on success, the timeout 120s wrapper, and
timeout-minutes: 5 (a hang still fails).
No-false-red proof: built the real harness dist and ran the strict guard
against the real dist/orchestrator.js under node -e (argv[1] unset) —
BOOT_OK, exit 0, ~0.28s, no hang, confirming a clean graph loads without
throwing and the strict guard does not false-red real CI.
…ts (#5952) ## What broke The showcase control-plane harness crash-looped at boot on `origin/main` HEAD, breaking the staging auto-deploy: ``` BOOT_ERR ERR_MODULE_NOT_FOUND Cannot find module '.../dist/shared/cell-model/live-status' imported from .../dist/shared/cell-model/cell-model.js ``` ## Root cause The harness ships as **pure Node ESM**: - `showcase/harness/package.json` has `"type": "module"` - build is `tsc -p tsconfig.build.json` with `moduleResolution: "bundler"`, which **preserves extensionless import specifiers at emit** (it does not rewrite `./live-status` → `./live-status.js`) - the Docker `CMD` and the `start` script both run `node dist/orchestrator.js` Under pure Node ESM, relative import specifiers **must** carry the `.js` extension. The harness already honors this convention everywhere — `orchestrator.ts` has 79 relative imports, 79/79 ending in `.js`. The relocated `showcase/harness/src/shared/cell-model/` fold broke the convention: `cell-model.ts`, `live-status.ts`, `staleness.ts`, and the equivalence fixtures/test imported their siblings extensionless (`"./live-status"`, `"./staleness"`, etc). `tsc`, `vitest`, and `tsx` all resolve extensionless specifiers fine, so it built green and passed every test — then `node dist/orchestrator.js` threw `ERR_MODULE_NOT_FOUND` at boot and crash-looped. ## The fix Add the `.js` extension to every offending relative import in the cell-model fold, matching the harness convention. **No tsconfig change** (deliberately not switching to `nodenext`) — the minimal, convention-matching fix is the extensions. Files fixed (7 relative import specifiers across 5 files): - `cell-model.ts` — 4 specifiers (`./live-status` ×3, `./staleness` ×2 counting the re-export) - `live-status.ts` — `./format-ts`, `./staleness` - `staleness.ts` — `./live-status` - `cell-model.equivalence-fixtures.ts` — `./live-status` ×2, `./cell-model`, `./staleness` - `cell-model.equivalence.test.ts` — `./cell-model`, `./cell-model.equivalence-fixtures` The shell-dashboard re-export shims (`showcase/shell-dashboard/src/lib/{cell-model,live-status,staleness,format-ts}.ts`) were intentionally **left unchanged**: that package is a Next.js build (not `node dist`) and uses extensionless relative imports as its own convention, including reaching into harness `src`. Adding `.js` there would break it. ## Local RED / GREEN proof Same `node dist/orchestrator.js` boot probe, before and after the fix. **RED** (unmodified branch code, after `pnpm --filter @copilotkit/showcase-harness build`): ``` BOOT_ERR ERR_MODULE_NOT_FOUND Cannot find module '/…/showcase/harness/dist/shared/cell-model/live-status' imported from /…/showcase/harness/dist/shared/cell-model/cell-model.js ``` **GREEN** (after the fix, rebuilt): ``` BOOT_OK ``` The orchestrator module graph now loads fully — `ERR_MODULE_NOT_FOUND` is gone. ## Docker boot result Built the harness image locally from repo root (`docker build -f showcase/harness/Dockerfile -t harness-esm-test .`) — build succeeded (exit 0). Ran the container (`docker run harness-esm-test`, no env supplied). It did **not** crash-loop on module resolution: the full ESM module graph loaded and boot reached `bootFleet` in `orchestrator.js`, then exited cleanly on the expected missing-env application error — **no `ERR_MODULE_NOT_FOUND`**: ``` {"level":"error","msg":"showcase-harness.boot-failed","err":"HARNESS_ROLE must be set to one of: control-plane, worker (got: <unset>). ...","stack":"Error: HARNESS_ROLE must be set ... at resolveFleetRoleConfig (file:///app/dist/fleet/role-config.js:72:15) at bootFleet (file:///app/dist/orchestrator.js:3680:20) at file:///app/dist/orchestrator.js:3762:5 at ModuleJob.run (node:internal/modules/esm/module_job:343:25)"} ``` Every `dist/` module resolved (note `file:///app/dist/fleet/role-config.js` and `file:///app/dist/orchestrator.js`); the crash was the intended env-validation guard, exactly the "later runtime error is acceptable" case. On pre-fix code this same container would have thrown `ERR_MODULE_NOT_FOUND` at import time and crash-looped. ## CI regression guard CI missed this because `tsc` (bundler resolution), `vitest`, and `tsx` all resolve extensionless specifiers — **no existing CI step ever ran the real `node dist` module graph** that the container boots. Added a **harness ESM boot-smoke** step to the `Showcase: Validate` job (already gated on `showcase/harness/**`, a required PR check): after building the harness dist, it loads `dist/orchestrator.js` via `node import()` and fails hard on `ERR_MODULE_NOT_FOUND`. A later runtime error from missing env/PocketBase is expected and passes — only a module-resolution failure reddens the build. **Guard red-green** (the guard's own proof, run locally against both code states): - **pre-fix** (extensionless imports): `BOOT_FAIL: ERR_MODULE_NOT_FOUND …/dist/shared/cell-model/live-status` → exit **1** ✅ caught - **post-fix** (with `.js`): `BOOT_OK: orchestrator module graph loaded` → exit **0** ✅ passes ## Verification - `pnpm typecheck` / `tsc --noEmit`: clean - `cell-model.equivalence.test.ts`: 7/7 pass - lefthook lint + commitlint: pass on both commits Do not merge — merge is user-gated after code review.
…egress fix) (#5953) ## Summary Routes the ~20 showcase demo backends to **aimock** (the record/replay LLM proxy) over Railway **private networking** (`*.railway.internal`) instead of aimock's **public** `*.up.railway.app` host. Railway bills traffic to a public domain as **egress even intra-project**, while `*.railway.internal` private networking is **free** and **env-scoped**. The 240-concurrent-browser harness fleet drives every demo continuously, so every LLM SSE stream from aimock back to a demo backend is currently billed egress. - aimock ≈ **89% of showcase egress**, ≈ **92% of the 13TB→78TB/mo increase**. - Estimated impact: avoids the ≈ **$602/mo → $3,856/mo** growth on the aimock path. ## Change (config-only, reversible; SSOT-driven) 1. **SSOT** (`showcase/scripts/railway-envs.ts`): add an env-scoped `internalDomain: "showcase-aimock.railway.internal"` to the aimock entry in **both** envs. The public `domain` is **kept** (health probes / external reachability). 2. **Emitter** (`showcase/scripts/emit-railway-envs-json.ts`): emit `internalDomains` (additive, after `domains`) into the generated JSON. Every non-aimock service keeps its frozen shape. 3. **Generated JSON** regenerated (oxfmt-canonical; 4-line additive diff, only the aimock entry). 4. **Promote preflight** (`showcase/bin/railway`): `ssot_target_host` now **prefers** the private `internalDomains[env]` over the public `domains[env]`, so the Stage-2 (U5) serviceRef assertion requires demo backends' `OPENAI_BASE_URL`/etc. to point at the private host. Non-aimock targets (no `internalDomains`) fall back to their public host unchanged. 5. **Harness** wiring probe needs **no code change** (it matches on hostname); added a discriminating test pair + updated the drift-alert Fix text to the private host. **Target:** aimock binds `0.0.0.0:4010` (per `showcase/aimock/RAILWAY.md`); demo backends resolve to `http://showcase-aimock.railway.internal:4010`. Deployed env vars, both envs (before → after): | key | before (public, billed egress) | after (private, free) | |---|---|---| | `OPENAI_BASE_URL` | `https://<aimock>.up.railway.app/v1` | `http://showcase-aimock.railway.internal:4010/v1` | | `ANTHROPIC_BASE_URL` | `https://<aimock>.up.railway.app` | `http://showcase-aimock.railway.internal:4010` | | `GOOGLE_GEMINI_BASE_URL` | `https://<aimock>.up.railway.app` | `http://showcase-aimock.railway.internal:4010` | | `AIMOCK_URL` | `https://<aimock>.up.railway.app` | `http://showcase-aimock.railway.internal:4010` | `<aimock>` = `aimock-staging` (staging) / `showcase-aimock-production` (prod). `railway.internal` is env-scoped, so staging demos reach the staging aimock and prod demos reach prod aimock automatically — the same private DNS name in both envs. --- ## Red-green proof (verbatim) ### RED — live staging today (billed public egress) Deployed `showcase-langgraph-fastapi` (staging, service `06cccb5c-…`) via Railway `variables(...)` GraphQL: ``` OPENAI_BASE_URL = https://aimock-staging.up.railway.app/v1 ANTHROPIC_BASE_URL = https://aimock-staging.up.railway.app GOOGLE_GEMINI_BASE_URL = https://aimock-staging.up.railway.app AIMOCK_URL = https://aimock-staging.up.railway.app ``` Pre-fix generated JSON aimock entry — **no** `internalDomains`: ```json { "domains": { "staging": "aimock-staging.up.railway.app", "prod": "showcase-aimock-production.up.railway.app" }, "internalDomains": "ABSENT" } ``` ### RED — Ruby U5 serviceref resolver, with the resolver reverted to public-only The three new U5 tests FAIL when `ssot_target_host` returns the public host: ``` 7 runs, 15 assertions, 3 failures 1) test_serviceref_prod_pointing_at_public_aimock_host_refuses: expected REFUSE for prod serviceRef on the public egress host, got [] 2) test_serviceref_prod_pointing_at_private_aimock_passes: prod private aimock ref must not REFUSE, got ["REFUSE: §5.2 (showcase-ag2): prod OPENAI_BASE_URL="http://showcase-aimock.railway.internal:4010/v1" does NOT point at aimock's env-LOCAL prod host "showcase-aimock-production.up.railway.app" ..."] 3) test_ssot_target_host_prefers_internal_over_public: expected "showcase-aimock.railway.internal", actual "showcase-aimock-production.up.railway.app" ``` ### GREEN — after the fix Post-fix generated JSON aimock entry: ```json { "domains": { "staging": "aimock-staging.up.railway.app", "prod": "showcase-aimock-production.up.railway.app" }, "internalDomains": { "staging": "showcase-aimock.railway.internal", "prod": "showcase-aimock.railway.internal" } } ``` Ruby U5 serviceref tests (fixed resolver — prefers `internalDomains`): ``` 7 runs, 20 assertions, 0 failures, 0 errors, 0 skips ``` Full Ruby spec suite: ``` 184 runs, 715 assertions, 0 failures, 0 errors, 0 skips ``` Harness aimock-wiring probe (hostname-match; internal host with `:4010` + `/v1` → green, demo still on public host while harness on private → red): ``` src/probes/aimock-wiring.test.ts 29 passed (was 27; +2 new: internal-host green, public-host drift red) src/probes/drivers/aimock-wiring.test.ts 16 passed src/rules/rule-loader.test.ts 61 passed (aimock-wiring-drift.yml parses after Fix-text update) renderer + render-red-tick + orchestrator 157 passed (no alert-text snapshot broke) ``` Scripts test suite (emitter golden + everything): `2147 passed, 7 skipped` (one pre-existing `/tmp` lockfile flake in `integration-smoke-registry.test.ts`, green on rerun after clearing the stale lock). `emit --check` idempotent + oxfmt-canonical. Harness `tsc --noEmit`: clean. ### GREEN — live infra confirmation - aimock **staging** deployment status = `SUCCESS` (running), binds `0.0.0.0:4010` — so `showcase-aimock.railway.internal:4010` resolves to a live listener for any peer in the staging env. - aimock serving LLM-shaped responses on `:4010`: `GET /health` → `200`; `GET /v1/models` → `200` `{gpt-4o, gpt-4o-mini}`. ## What was vs wasn't live-validated **Validated live:** the RED (deployed staging vars still on the public egress host); aimock staging is deployed/running and serving on `:4010`; the full unit/wiring/promote-preflight test surface passes with the new internal-host values. **NOT live-validated in-session:** the in-Railway-network DNS resolution of `showcase-aimock.railway.internal:4010` from a peer service, and a full staging deploy that flips the four keys + redeploys a demo backend. Reason: the in-network vantage needs `railway ssh` (requires registering a persistent account SSH key — a stateful, human-gated change I declined to make unsupervised) or a staging deploy (the local Railway access token was expired; the CLI refreshed it for read/GraphQL but a deploy is a separate gated action). Railway private networking (`*.railway.internal`) is a standard platform feature; the local `docker-compose.local.yml` already runs the identical `http://aimock:4010` internal-host pattern, and the wiring probe's hostname match is exercised by the new tests. The staging deploy + in-network curl is the first step of the rollout plan below and must be run before prod. ## Irreducible egress remains This does **not** zero showcase egress. Still billed: real browse users hitting the public demo/shell domains; and aimock in **record mode** proxying to real providers (the outbound prompt to OpenAI/Anthropic/Google still bills). ## Rollout plan (reversible config change, staging-first, user-gated) 1. Land this branch (SSOT + generated JSON + assertions). 2. **Staging first:** set the four keys on staging demo backends + `AIMOCK_URL` on the harness to `http://showcase-aimock.railway.internal:4010` (`/v1` on `OPENAI_BASE_URL`); redeploy one demo backend + aimock; from inside a staging service curl `http://showcase-aimock.railway.internal:4010/health` (expect 200) and run a real demo LLM turn / aimock-wiring probe (expect green); confirm the aimock egress path stops accruing (`usage(measurements:[NETWORK_TX_GB])`). 3. **User-gated** promote to prod (staging→prod), same key flip. 4. **Rollback** = flip the keys back to the public host (no code revert needed). ## Follow-ups (out of scope — do NOT bundle) - Fleet right-sizing (240-concurrent-browser harness). - `OPENAI_API_KEY` consolidation. --- Draft — do not merge. Do not deploy to prod.
…ose CI gap PR #5952 (9a8cf61) added explicit `.js` extensions to the relative imports inside the harness's shared cell-model fold (showcase/harness/src/shared/cell-model/{cell-model,live-status,staleness}.ts) — REQUIRED for the harness's pure-Node-ESM runtime and correct as-is. But the dashboard re-exports that fold via shims (showcase/shell-dashboard/src/lib/{cell-model,live-status,staleness,format-ts}.ts `export * from "../../../harness/src/shared/cell-model/*"`), pulling the fold into the dashboard's `next build`. `export *` does not rewrite the fold's INTERNAL `.js` edges, and the dashboard's empty next.config.ts had no extensionAlias, so webpack resolved `./live-status.js` literally, found only the `.ts` source, and failed: Module not found: Can't resolve './live-status.js' Module not found: Can't resolve './staleness.js' Module not found: Can't resolve './format-ts.js' > Build failed because of webpack errors Two-part fix (one coherent subject): 1. Resolution: add `webpack.resolve.extensionAlias` to showcase/shell-dashboard/next.config.ts so `.js`/`.mjs` specifiers resolve to `.ts`/`.tsx`/`.mts` sources — the bundler complement to TS NodeNext's `.js`-import convention. Covers the `next build` (webpack) path CI uses. The harness fold's `.js` imports are left untouched (they are correct). 2. CI gap: the dashboard build did not run on #5952 because the build matrix is path-filtered and #5952 only touched `showcase/harness/**`, which selects `showcase_harness` but not `shell_dashboard`. Add `showcase/harness/src/shared/**` to the `shell_dashboard` paths-filter so any change to the shared fold the dashboard compiles in also selects the dashboard build — a fold change can never again ship an unbuilt dashboard. Local red-green proof: - RED (main, before fix): `next build` in showcase/shell-dashboard emitted the 4 fold-resolve errors above. - GREEN (after extensionAlias): same build → 0 fold-resolve errors; the fold resolves. Remaining `@/data/*.json` errors are the prebuild-generated files (generate-registry/probe-docs) skipped in the local repro, produced in CI's Docker build — unrelated to this fix.
…ose CI gap (#5955) ## What broke PR #5952 (`9a8cf615`) added explicit `.js` extensions to the relative imports inside the harness's shared cell-model fold (`showcase/harness/src/shared/cell-model/{cell-model,live-status,staleness}.ts`). Those `.js` extensions are **REQUIRED** for the harness's pure-Node-ESM runtime and are **correct** — this PR does not revert them. The problem: the dashboard re-exports that fold via re-export shims (`showcase/shell-dashboard/src/lib/{cell-model,live-status,staleness,format-ts}.ts`, each `export * from "../../../harness/src/shared/cell-model/*"`), which pulls the fold **into the dashboard's `next build`**. `export *` does not rewrite the fold's *internal* `.js` edges, and the dashboard's `next.config.ts` was empty (no `extensionAlias`), so webpack resolved `./live-status.js` **literally**, found only the `.ts` source, and failed: ``` ../harness/src/shared/cell-model/cell-model.ts Module not found: Can't resolve './live-status.js' Module not found: Can't resolve './staleness.js' ../harness/src/shared/cell-model/live-status.ts Module not found: Can't resolve './format-ts.js' > Build failed because of webpack errors ``` First-red at `9a8cf615`; reproduced in CI run `29306712559` (shell-dashboard build job). ## The fix (two parts, one coherent subject) **1. Resolution** — `showcase/shell-dashboard/next.config.ts`: add a webpack `resolve.extensionAlias` so `.js`/`.mjs` specifiers resolve to `.ts`/`.tsx`/`.mts` sources. This is the standard bundler complement to TypeScript NodeNext's `.js`-import convention, and it applies to the `next build` (webpack) path CI uses. A shim-only fix does **not** work — `export *` doesn't intercept the fold's internal `.js` edges; the alias in the dashboard build is the correct layer. The harness fold `.js` imports are **left untouched**. **2. CI gap** — `.github/workflows/showcase_build.yml`: the dashboard build didn't run on #5952 because the build matrix is path-filtered and #5952 only touched `showcase/harness/**`, which selects `showcase_harness` but **not** `shell_dashboard`. Added `showcase/harness/src/shared/**` to the `shell_dashboard` `dorny/paths-filter` set. Now any change to the shared fold the dashboard compiles in also selects the dashboard build — a fold change can never again ship an unbuilt dashboard. (Verified only `shell-dashboard` consumes this fold, so the gate is scoped precisely.) ## Local red-green proof **RED** (latest main, before the `next.config.ts` fix) — from `showcase/shell-dashboard`, `next build`: ``` ../harness/src/shared/cell-model/cell-model.ts Module not found: Can't resolve './live-status.js' Module not found: Can't resolve './staleness.js' ../harness/src/shared/cell-model/live-status.ts Module not found: Can't resolve './format-ts.js' Module not found: Can't resolve './staleness.js' > Build failed because of webpack errors ``` (4 fold-resolve errors.) **GREEN** (after the `extensionAlias` fix) — same `next build`: ``` (0 fold-resolve errors — the fold resolves) ``` The only remaining `Module not found` errors are `@/data/{catalog,registry,docs-status}.json`, which are generated by the dashboard's `prebuild` scripts (`generate-registry.ts` / `probe-docs.ts`) that were skipped in the local repro. CI's Docker build runs `prebuild` first, so those files exist there — unrelated to this fix. ## CI-gap trace `dorny/paths-filter` emits `changes` as the JSON array of filter keys whose patterns matched. A change to `showcase/harness/src/shared/cell-model/live-status.ts` now matches both `showcase_harness` (via `showcase/harness/**`) **and** `shell_dashboard` (via the new `showcase/harness/src/shared/**`), so the matrix `select` (`$dispatch == "" and ($changes | index($fk) != null)`) includes the `shell-dashboard` slot. Gap closed. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…d failures Two pre-existing silent-failure gaps in the showcase build/deploy/notify pipeline (surfaced in code review): 1. Green-but-zero-redeploy: the redeploy-staging job computes the redeploy set as (build matrix ∩ build-success). This job only runs when any_success=='true', so an EMPTY intersection means builds succeeded but none maps to a matrix dispatch_name — a dispatch_name/service contract skew. The old code emitted an empty services= and exited 0, going GREEN while redeploying nothing. Now it fails loud with a diagnostic naming both sides of the skew. The legitimate nothing-changed/nothing-succeeded no-ops stay guarded at the job level, so they are unaffected. 2. Starter-failure-invisible: the notify job's needs omitted build-starters, so a failed starter image build produced no Slack alert and no PR comment. Added detect-starter-changes + build-starters to notify.needs, and gave build-starters a per-slot build-result artifact mirroring the main build matrix (distinct starter-build-result-* prefix so it never pollutes the showcase aggregator's build-result-* set).
…d failures (#5956) ## Two silent-failure gaps in the showcase build/deploy/notify pipeline These are **pre-existing** silent-failure holes surfaced in code review (not caused by any recent PR). This PR fixes the two load-bearing ones. ### 1. Green-but-zero-redeploy (silent "we thought we shipped but didn't") The `redeploy-staging` job computes the redeploy set as the intersection of the build matrix and the build-success set. This job **only runs when `aggregate-build-results.outputs.any_success == 'true'`** (job-level `if:` guard). So if that intersection comes back **EMPTY**, it does NOT mean "nothing to deploy" — it means at least one slot built successfully yet none of those successes maps back to a matrix `dispatch_name`. That's a `dispatch_name`↔ `service` contract skew (the aggregator's `service` values and the matrix's `dispatch_name` values drifted apart). The old code emitted `services=` (empty) and exited 0 → the build went **GREEN while redeploying NOTHING**, silently. **Fix:** on an empty intersection in this any_success-guaranteed step, fail loud (`::error::` + `exit 1`) with a diagnostic naming both sides of the skew. The legitimate "nothing changed / nothing succeeded" no-op paths are guarded at the **job level** (`has_changes=='true' && any_success=='true'`), so the fixed step never runs there — no false-red. ### 2. Starter build failures had no alert surface (invisible failures) The `notify` job's `needs` (and its `if: failure()`) omitted `detect-starter-changes` and `build-starters`, and `build-starters` wrote no per-slot build-result artifact. So a **failed starter image build produced NO Slack alert and NO PR comment** — it shipped silently. **Fix:** - Added `detect-starter-changes` + `build-starters` to `notify.needs` so `if: failure()` sees a starter build failure → Slack alert + PR comment. - Gave `build-starters` a per-slot build-result artifact **mirroring the main `build` matrix** (same `{service,status}` shape, `cancelled→skipped` normalization, `if: always()`, `if-no-files-found: error`), using a **distinct `starter-build-result-*` prefix** so it never matches the aggregator's `build-result-*` download pattern (starters must not pollute the showcase redeploy set keyed by `dispatch_name`). ### Red / Green **Finding #1** — extracted the step's shell/jq logic and drove it with synthetic inputs: RED (pre-fix), any_success=true + empty intersection: ``` No services in matrix ∩ success-set — skipping redeploy. Computed services CSV (matrix ∩ build-success): EXIT=0 # $GITHUB_OUTPUT: services= -> silent pass, redeploys NOTHING ``` GREEN (post-fix), same inputs: ``` ::error::Build succeeded (any_success=true) but matrix ∩ success-set is EMPTY — dispatch_name/service contract skew; nothing would be redeployed. Successful build service values: ["shell-RENAMED","mastra-RENAMED"] Scheduled matrix dispatch_name values: ["shell","mastra"] EXIT=1 # fails loud ``` No-regression: non-empty intersection → `EXIT=0 ; services=shell`. The nothing-changed/nothing-succeeded paths are skipped at the job level (never reach the step) → no false-red. **Finding #2** — modeled `if: failure()` (fires iff any `needs` job result is `failure`): ``` BEFORE (starters NOT in needs), starter=failure -> notify fires = False (INVISIBLE, the bug) AFTER (starters IN needs), starter=failure -> notify fires = True (FIXED) AFTER no-regression, starters=skipped, all green -> notify fires = False (quiet) ``` ### Validation - `python3 yaml.safe_load` parses OK. - `actionlint`: only pre-existing findings remain (matrix jq SC2086 + the known `depot-ubuntu-24.04-4` runner-label warning); no new errors in edited regions. - `yamllint`: only pre-existing line-length/document-start/truthy warnings. ### Scope Touches **only** `.github/workflows/showcase_build.yml`, and only these two concerns. Does NOT touch the `shell_dashboard` paths-filter region (PR #5955's domain), nor the other backlog debt (false-root-cause comment, double-alert, check-lockfile guard). Self-contained; not stacked on #5955.
… cell-model fold Turbopack has no resolve.extensionAlias parity (Next #82945), so 'next dev --turbopack' can't resolve the shared cell-model fold's .js->.ts specifiers and fails with Can't resolve './live-status.js'. The extensionAlias in next.config.ts (added in #5955) is honoured by webpack, which next build already uses. Drop --turbopack from the dev script so dev runs on webpack too and resolves the fold. Deploy path unaffected: the Dockerfile builds with 'next build' (webpack) and serves with 'next start' -- the dev script is never in the build or runtime path.
… cell-model fold (#5959) ## Problem `pnpm dev` on the shell-dashboard fails to start the fold-importing routes: ``` Module not found: Can't resolve './live-status.js' Module not found: Can't resolve './format-ts.js' Module not found: Can't resolve './staleness.js' GET / 500 ``` The dashboard re-exports the shared **cell-model fold** from the harness (`showcase/harness/src/shared/cell-model/*.ts`). Those fold files are authored for the harness's pure-Node-ESM runtime, so their internal relative imports carry explicit `.js` extensions (e.g. `import { formatTs } from "./format-ts.js"`) even though they exist on disk as `.ts`. `export *` does not rewrite those internal edges. `next build` (webpack) already resolves this via the `resolve.extensionAlias` in `next.config.ts` (added in #5955), which tells webpack to try the TS sources for a `.js` specifier. But the `dev` script forced Turbopack (`next dev --turbopack`), and **Turbopack has no `resolve.extensionAlias` parity** ([Next #82945](vercel/next.js#82945)) — so dev couldn't resolve the fold. ## Fix Drop `--turbopack` from the `dev` script. On Next 15.5.x, `--turbopack` is an explicit opt-in flag (there is no `--webpack` opt-out); plain `next dev` runs **webpack**, which honours the existing `extensionAlias`. ```diff - "dev": "next dev --turbopack --port 3002", + "dev": "next dev --port 3002", ``` `build` is unchanged (`next build` = webpack). A note in `next.config.ts` explains why dev uses webpack. **Tradeoff:** dev loses Turbopack's faster HMR and falls back to webpack-speed dev until Turbopack ships `extensionAlias` parity (#82945), at which point dev can switch back. ## Red / Green (empirical, this branch) **Empirical proof of which bundler each command runs** (Next 15.5.15 startup banner): - `next dev --turbopack` → `▲ Next.js 15.5.15 (Turbopack)` - `next dev` → `▲ Next.js 15.5.15` (no "(Turbopack)" = webpack) **RED** — `next dev --turbopack`, `GET /`: ``` ▲ Next.js 15.5.15 (Turbopack) Module not found: Can't resolve './format-ts.js' Module not found: Can't resolve './live-status.js' Module not found: Can't resolve './staleness.js' GET / 500 in 3691ms ``` **GREEN** — `next dev` (webpack), `GET /`: ``` ▲ Next.js 15.5.15 ✓ Ready in 1124ms ✓ Compiled / in 1948ms (704 modules) GET / 200 in 2844ms ``` No `Can't resolve`. **No regression** — `next build` (webpack) still resolves the fold: ``` Creating an optimized production build ... ✓ Compiled successfully in 3.1s ``` (The fold compiles clean under webpack via the unchanged `extensionAlias`.) ## Deploy path is UNAFFECTED The `dev` script is never in the build or runtime path. `showcase/shell-dashboard/Dockerfile` builds with `npx next build` (webpack) and serves with `npx next start`. This change touches only local `pnpm dev` — the built/deployed dashboard image is byte-for-byte identical.
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/setup-node](https://redirect.github.com/actions/setup-node) | action | major | `v6.4.0` → `v7.0.0` | | [ruby/setup-ruby](https://redirect.github.com/ruby/setup-ruby) | action | minor | `v1.316.0` → `v1.317.0` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/592) for more information. --- ### Release Notes <details> <summary>actions/setup-node (actions/setup-node)</summary> ### [`v7.0.0`](https://redirect.github.com/actions/setup-node/compare/v6.5.0...v7.0.0) [Compare Source](https://redirect.github.com/actions/setup-node/compare/v7.0.0...v7.0.0) ### [`v7`](https://redirect.github.com/actions/setup-node/compare/v6.5.0...v7.0.0) [Compare Source](https://redirect.github.com/actions/setup-node/compare/v6.5.0...v7.0.0) ### [`v6.5.0`](https://redirect.github.com/actions/setup-node/compare/v6.4.0...v6.5.0) [Compare Source](https://redirect.github.com/actions/setup-node/compare/v6.4.0...v6.5.0) </details> <details> <summary>ruby/setup-ruby (ruby/setup-ruby)</summary> ### [`v1.317.0`](https://redirect.github.com/ruby/setup-ruby/releases/tag/v1.317.0) [Compare Source](https://redirect.github.com/ruby/setup-ruby/compare/v1.316.0...v1.317.0) ##### What's Changed - Add ruby-4.0.6 by [@​ruby-builder-bot](https://redirect.github.com/ruby-builder-bot) in [#​928](https://redirect.github.com/ruby/setup-ruby/pull/928) **Full Changelog**: <ruby/setup-ruby@v1.316.0...v1.317.0> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/Los_Angeles) - Branch creation - "before 9am every weekday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/CopilotKit/CopilotKit). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI1OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
…#5812) (#5885) ## Summary Pressing **Stop** while an assistant message is streaming (CopilotRuntime + `HttpAgent` proxy) crashed the chat with: ``` Cannot send event type 'TEXT_MESSAGE_END': The run has already errored with 'RUN_ERROR'. No further events can be sent. ``` Root cause: `finalizeRunEvents` appended a trailing `TEXT_MESSAGE_END` **after** the `RUN_ERROR` that the aborted agent had already emitted. Fixes #5812. ## Root cause When the upstream agent (e.g. pydantic-ai's `AGUIAdapter`) is aborted mid-stream it emits a live `RUN_ERROR` while a text message is still open — it does **not** close the message first. All runners (`in-memory`, `intelligence`, `sqlite`) stream `finalizeRunEvents`' output *after* everything the agent already emitted, so the appended closer landed past the terminal: | | outgoing event order | |---|---| | **Before** | `… TEXT_MESSAGE_CONTENT → RUN_ERROR → TEXT_MESSAGE_END` ❌ verifier throws | | **After** | `… TEXT_MESSAGE_CONTENT → RUN_ERROR` ✅ terminal closes the message client-side | Per the AG-UI invariant: at most one terminal event per run, and no sub-events after it. I confirmed against the real `@ag-ui/client` `verifyEvents` (the verifier the browser runs) that a terminal arriving with a message still open is valid — the terminal implicitly closes it. ## Fix `finalizeRunEvents` (in `@copilotkit/shared`) now returns early and appends **nothing** when the stream already contains a terminal event (`RUN_FINISHED` or `RUN_ERROR`). The abrupt-end path (no terminal → close open streams + synthesize a terminal, in the correct order) is unchanged. No API/signature change; the in-memory, intelligence, and sqlite runners all inherit the fix. ## Testing RED→GREEN verified — each new/updated assertion was confirmed to fail against the pre-fix code: - **`finalize-events.test.ts`** — terminal-present appends nothing (parametrized over `RUN_FINISHED` and `RUN_ERROR`) + a named #5812 case. - **`in-memory-runner.test.ts`** — end-to-end mid-stream-stop regression: a fake `HttpAgent`-style agent is stopped between `TEXT_MESSAGE_START` and `TEXT_MESSAGE_END`; asserts no events follow `RUN_ERROR` **and** that the collected stream passes `verifyEvents` (before the fix this threw the exact browser error). - **`intelligence-runner.test.ts`** — corrected a pre-existing assertion that had encoded the buggy post-terminal `TEXT_MESSAGE_END`. Green: full `@copilotkit/runtime` suite, `@copilotkit/sqlite-runner`, `@copilotkit/shared`, `check-types`, `oxlint` (0 errors), and build. ## Reviewer notes - The behavior change is a single early-return in `finalize-events.ts`; the `terminalEventMissing` guards simplify away because they're only reachable when no terminal exists. - Diff is +204/−55 across 4 files, the bulk of it tests.
Flip the 4 TS a2ui builders (shared/typescript + mastra, claude-sdk-typescript, langgraph-typescript) from the legacy flat operation shape to v0.9 nested (createSurface / updateComponents / updateDataModel), matching the Python builder and what A2UI consumers process. Flat ops were never processed as valid nested operations, so the surface schema and components were never applied. Also align the empty-data guard to Python's `if data:` semantics (empty object -> no updateDataModel), add a v0.9 parity guard test to all 4 test files, and add 12 gen-ui-a2ui-fixed aimock fixtures.
The shared TS builder exported `_design_a2ui_surface` / `DESIGN_A2UI_SURFACE_TOOL_SCHEMA` while the Python builder, all integration copies, and agent_server.ts use `render_a2ui` / `RENDER_A2UI_TOOL_SCHEMA`. Align the shared source to that source-of-truth name; this also unbreaks the re-export in shared/typescript/tools/index.ts.
… guard Restore the 12 Python integration tools/ dirs to symlinks into shared/python/tools. They had eroded to real, drifting copies via an accidental stage_shared() leak (commit 534cd1e) — the structural root cause of showcase divergence bugs. Symlinking re-establishes the single source of truth; content is identical to shared (only render_a2ui naming and the shared roll_dice/sanitize additions are adopted). Add showcase/AGENTS.md documenting the 4 iron rules and the single-source symlink mechanism, plus a validate-shared-symlinks CI guard (shrink-only baseline) that fails on any NEW erosion.
…hon/TS parity) (#5971) ## Summary The TypeScript A2UI operation builders (`buildA2uiOperationsFromToolCall`) emitted the **legacy flat** operation shape (`{ type: "create_surface", surfaceId }`). A2UI consumers process operations by their **nested** `createSurface` / `updateComponents` / `updateDataModel` keys — a flat op is never processed as a valid nested operation, so the surface's schema and components are never applied and the UI renders nothing (the `generate_a2ui` / `render_a2ui` path). Python was fixed to the v0.9 nested shape long ago (#4792, #5832); the TypeScript builders were **born flat and never fixed** — a Python/TS parity gap with no guard. This aligns the TS side and adds a guard so the two can't silently drift again. ## Changes - **4 TS builders → v0.9 nested** (byte-identical): `shared/typescript/tools` + integrations `mastra`, `claude-sdk-typescript`, `langgraph-typescript`. - **Empty-data parity fix**: TS `if (data)` treated `{}` as truthy and emitted a spurious `updateDataModel` op; Python `if data:` does not. Now guarded to match Python (empty object → no `updateDataModel`). Our mastra fixture records `"data": {}`, so this is exercised directly. - **v0.9 parity guard test** in all 4 test files (asserts nested keys, no flat `type`). - **12 `gen-ui-a2ui-fixed` aimock fixtures** for the fixed-schema a2ui demo. ## Red–green evidence - Empty-data: pre-fix builder emits 3 ops on `data:{}` → `toHaveLength(2)` **FAILS (red)**; fixed builder emits 2 → **passes (green)**. - Parity guard: flat shape → `.type` present / nested keys absent → **red**; nested → **green**. ## Validation (please read — what CI does and doesn't cover) CI **does** run `check-types`, `format`/`oxlint`, `Validate Showcase`, and `build-check` on the changed integrations (mastra, langgraph-typescript, claude-sdk-typescript) — these catch TS/build breaks. But the unit-test workflow has `paths-ignore: showcase/**`, so the **showcase vitest suites where the parity guard and aimock-fixtures tests live are NOT run in CI**. Those were validated **locally**: - `aimock-fixtures`: **837 passed** (all 12 new fixtures valid). - Parity guard + empty-data red–green: **verified** (`showcase/shared/typescript` vitest). - `tsc --noEmit --strict`: **clean** on all 4 builders. - **mastra Playwright screenshot**: the `render_a2ui` flow renders the flight card (SFO→JFK, Flight Details, $289) with the nested ops. ## Real-surface confirmation (bin/showcase test --direct) Proven on the live probe, not just unit tests: - **RED** (old flat builder): `d6:mastra a2ui-fixed-schema` → `1 failed — [data-testid="a2ui-fixed-card"] failed to mount within 60000ms`. - **GREEN** (this branch, rebuilt image): `d6:mastra a2ui-fixed-schema` → `✓ green, 1 passed` — the card mounts and renders (SFO→JFK, UNITED, $289, "Book flight"). - **≥3 cells `--direct` GREEN**: `mastra` ✓, `langgraph-typescript` ✓, `pydantic-ai` ✓. - **Frontend parity**: mastra ≡ langgraph-python render the same flight card (byte-identical frontend; only expected agent-specific tool-row/ordering differences). ## Iron-rule adherence | Rule | Evidence | |------|----------| | Identical tests | One shared harness probe (`d5-gen-ui-a2ui-fixed`) measures the feature across all integrations; no per-integration test copies added. | | Near-identical frontends | mastra ≡ langgraph-python frontend (byte-identical); visual parity confirmed on the rendered card. | | Minimal backends | Change is the minimal flat→nested + empty-data guard; 4 TS builder copies byte-identical. | | Per-integration fixtures | 12 `gen-ui-a2ui-fixed.json`, one per slug, context-keyed. | Note: the *single-source symlink* restoration (the `shared-tools/`/`tools/` symlinks that eroded to real files repo-wide) is handled in a **companion structural PR**, plus a `showcase/AGENTS.md` documenting the iron rules and a CI check that fails on future erosion. ## Known follow-ups (out of scope here) 1. **`render_a2ui` naming drift (pre-existing):** the *shared* builder exports `_design_a2ui_surface` while the 3 integrations + Python use `render_a2ui`; the shared test asserts `render_a2ui` and is red on `main` today. Not run by CI. A one-line rename aligns shared to the source of truth and greens the file — happy to fold it in if wanted. 2. **Integration test copies aren't executed** by their vitest `include` globs (only `shared/typescript` runs its copy) — add a cross-copy byte-identity CI check. 3. **Full `_sanitize_a2ui_components` parity** — TS forwards components raw; Python sanitizes (drops entries missing id/component, unstringifies Gemini JSON-string arrays). 4. **Showcase tests are CI-excluded** (`paths-ignore: showcase/**`) — no automated gate for showcase unit tests.
…ical component shape
… guard (#5975) ## Summary Companion structural PR to #5971. It fixes the **root cause** behind the a2ui divergence #5971 patched: the showcase's single-source symlinks eroded to real, drifting copies. `showcase/integrations/*/tools`, `*/shared-tools`, `*/_shared` are meant to be **symlinks into `showcase/shared/...`** — `stage_shared()` dereferences them for the Docker build, `restore_symlinks()` restores them. An **accidental `stage_shared()` leak** (commit `534cd1efa7`, PR #4449 "D5 all-green") committed the dereferenced real files instead of restoring the symlinks. Once they were real files, they drifted — which is exactly how the a2ui `render_a2ui` vs `_design_a2ui_surface` split (fixed in #5971) arose. ## Changes - **Restore 12 Python `tools/` dirs to symlinks** → `../../shared/python/tools` (ag2, agno, claude-sdk-python, crewai-crews, google-adk, langgraph-fastapi, langgraph-python, langroid, llamaindex, ms-agent-python, pydantic-ai, strands). Content is byte-adopted from shared — verified no load-bearing per-integration code is lost (only `render_a2ui` naming + shared `roll_dice`/sanitize additions). Integrations' intentional internal-planner names (llamaindex, ms-agent-python) live in `src/`, not `tools/`, and are untouched. - **`showcase/AGENTS.md` (+ `CLAUDE.md`, root pointers, INTEGRATION-CHECKLIST section)** — canonical statement of the 4 iron rules (identical tests, near-identical frontends, minimal backends, per-integration fixtures) + the single-source symlink mechanism ("edit the shared source only; a real file there is a bug"). These were previously written down nowhere. - **`validate-shared-symlinks` CI guard** — fails on any NEW erosion (real dir where a symlink belongs), with a shrink-only baseline that tightens to fully-enforcing as symlinks are restored. Mirrors the existing `validate-*` ratchet pattern. ## Scope / independence - **No overlap with #5971** — this PR touches nothing under `showcase/shared/typescript/` and does not modify the 3 TS integration `shared-tools/` dirs (verified: empty file-set intersection). Mergeable independently. - Build-safe: `stage_shared()` correctly dereferences the restored symlinks (targets resolve within the build context); `restore_symlinks()` recreates them post-build. ## Verified - `validate-shared-symlinks` test suite: 7/7 pass; validator EXIT 0 (no new erosion). - Reviewed by a full panel (correctness, content-integrity, build/CI, docs, scope, silent-failure, simplicity) — zero mandatory findings. ## Follow-ups (deliberately out of scope) 1. **3 TS `shared-tools` dirs** (mastra, claude-sdk-typescript, langgraph-typescript) remain real (baselined) — symlink them in a follow-up **after #5971 merges**, to avoid overlapping its TS edits. 2. **Guard hardening**: validate the symlink *target* (not just that it's a symlink), fail-loud on a malformed baseline, and code-enforce the shrink-only ratchet. (This PR's guard catches the real-file erosion — the actual failure mode; these are robustness extras.) 3. Pre-existing `shared/python` a2ui test failures (#5971-adjacent) and a couple of stale doc line-refs, noted during review. Companion: #5971.
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [ruby/setup-ruby](https://redirect.github.com/ruby/setup-ruby) | action | minor | `v1.317.0` → `v1.318.0` | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/592) for more information. --- ### Release Notes <details> <summary>ruby/setup-ruby (ruby/setup-ruby)</summary> ### [`v1.318.0`](https://redirect.github.com/ruby/setup-ruby/releases/tag/v1.318.0) [Compare Source](https://redirect.github.com/ruby/setup-ruby/compare/v1.317.0...v1.318.0) #### What's Changed - Update CRuby releases on Windows by [@​ruby-builder-bot](https://redirect.github.com/ruby-builder-bot) in [#​929](https://redirect.github.com/ruby/setup-ruby/pull/929) **Full Changelog**: <ruby/setup-ruby@v1.317.0...v1.318.0> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/Los_Angeles) - Branch creation - "before 9am every weekday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/CopilotKit/CopilotKit). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI1OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )