Limits concurrent chat generation on capped deployments to 5 root chats
and 10 delegated subagent chats. The pools are deployment-wide and
independent, so delegated work can continue while root capacity is full.
The default caps live in AGPL code. Enterprise contributes only a
licensing unlock, so unlicensed deployments stay capped and cannot fail
open. Licensed deployments are uncapped while Agent Hours usage stays
below an explicit hard limit. Deployments without a hard limit remain
uncapped, and reaching the Agent Hours allocation only triggers
warnings.
Admission happens before a worker takes chat ownership. Capped
deployments serialize admission across replicas with a
transaction-scoped advisory lock and derive active and queued state from
current ownership plus fresh runner heartbeats, rather than persisted
queue markers or per-replica state. The acquisition query returns a
bounded, pool-interleaved candidate set instead of ranking the whole
backlog; a migration replaces the acquisition index with a pool-aware
one. Refused chats stay running but unowned, and interrupt requests
bypass admission so users can stop queued or over-cap chats.
The single-chat API derives `queued_for_capacity` from live pool state;
list endpoints do not report it. The UI polls that value every 5 seconds
while a chat is running and shows a callout when the chat is waiting for
capacity.
Updates the administrator documentation and deployment-wide Prometheus
gauges for active and queued agents. Replica-level values must be
aggregated with `max`, not `sum`.
> Mux updated this PR on Mike's behalf.
> 🤖 This PR was modified by Coder Agents on behalf of Jake Howell.
Until we meet again.
## Stack
- #27636
- #27718
- #27719
- #27722
- #27723
- #27724
- #27728
- #27730
- #27732
- #27762
- #27763
- #27786
- #27787
- #27788
- #27789
- #27790
- #27791
- #27817
- #27820
- #28009
## Final removal (`c39b664`)
Removes the last of MUI and Emotion now that every surface has been
migrated:
- **Dependencies**: drops `@mui/material` and
`@emotion/{cache,css,react,styled}` from `package.json` /
`pnpm-lock.yaml`, and deletes the `@types/emotion.d.ts` and
`@types/mui.d.ts` module augmentations.
- **Theming**: replaces the Emotion `CacheProvider`, MUI `ThemeProvider`
/ `StyledEngineProvider`, and `CssBaseline` in `ThemeProvider` with a
lightweight `theme/context.tsx` that exposes `ThemeContextProvider` and
a `useTheme` hook.
- **Global styles**: moves the base `body` styles (background, text
color, font, antialiasing) that `CssBaseline` previously provided into
`index.css`, and drops the temporary MUI modal/popover scrollbar-gutter
workaround.
- **Cleanup**: removes the MUI → shadcn / Emotion → Tailwind migration
guidance from `site/AGENTS.md`, updates the Storybook `preview.tsx`, and
adjusts assorted components (`Command`, `Slider`, `Switch`, `Tabs`,
`SyntaxHighlighter`, timing charts) and theme files to consume the new
context instead of MUI/Emotion.
Previously, there could be a gap where the web socket has been connected
and gets the initial message but the build parameters request was still
in flight. This caused two issues:
1. Because we only send initial parameters as a response to a message,
when the message comes first and the build parameters have not resolved
yet, we end up not sending the initial parameters, meaning the form
could be stale until the next edit the user makes.
2. And if the user does make an edit, once we get that response back we
would then send the initial parameters, essentially reverting back to
the initial state since the initial params do not include the user's
edits. So the user would need a second edit to finally sync up.
To resolve both issues, we ignore the web socket's initial message until
we get the build parameters, at which point we decide whether we can use
that initial message (when there are no build params) or if we need to
continue ignoring it and send the initial parameters to get the correct
state then finally render the form.
This branch tightens import hygiene and editor guidance to reduce
accidental use of legacy or discouraged patterns.
It also updates consumers too, by propagating the new `lucide-react`
import convention across the existing UI surfaces that reference those
icons.
- Updated `.vscode/settings.json` to prefer non-relative imports and
improve TypeScript auto-import behavior.
- Re-enabled and expanded Biome restricted-import enforcement in
`biome.jsonc` for migration guardrails.
- Added/used `lucide-react` `-Icon` naming conventions for clarity and
consistency.
- Updated consumers too across components, modules, and pages so the new
import rules are applied end-to-end.
Replaces the single-purpose PR diff right panel with a tabbed sidebar
that shows both the existing PR diff and real-time git repository
changes from the workspace agent.
There's an accompanying backend PR
[here](https://github.com/coder/coder/pull/22565).
https://github.com/user-attachments/assets/bbd53f1c-d753-4574-a159-6dad5989e5e3
## Backend surface
One endpoint drives this feature:
- **`WS /api/experimental/workspaceagents/{id}/git/watch`** —
bidirectional WebSocket. The client sends `refresh` messages; the agent
responds with `changes` messages containing per-repo branch and unified
diff. The workspace agent also automatically pushes changes as they
occur in the workspace.
Adds deprecation markers for MUI components and the custom Stack
component to guide migration to shadcn/ui and Tailwind CSS.
Changes:
- Added JSDoc @deprecated tags to Stack component and type definitions
- Added deprecation comments to MUI imports in theme files
- Expanded Biome noRestrictedImports rules to flag all MUI component
imports
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Changes made
- Patched React `CSSProperties` type to add support for custom CSS
properties
- Updated several of the components in the `components` directory to
Tailwind
- Updated most of the `WorkspacePageBuildView` component to Tailwind to
account for CSS specificity changes
- Updated `Search` to address accessibility violation and removed all
MUI logic
- Updated `Search` stories (added new story, decoupled all stories from
single decorator)
- Updated `autoFocus` behavior in `SearchField`
- Updated the styling for `WorkspacePageBuildView` to make sure the tabs
had enough padding
- Fixed layout effect in `WorkspacePageBuildView` to fire correctly
Closes https://github.com/coder/coder/issues/16775
## Changes made
- Added `OneWayWebSocket` function that establishes WebSocket
connections that don't allow client-to-server communication
- Added tests for the new function
- Updated API endpoints to make new WS-based endpoints, and mark
previous SSE-based endpoints as deprecated
- Updated existing SSE handlers to use the same core logic as the new WS
handlers
## Notes
- Frontend changes handled via #16855
* fix: prefer organization display name for workspaces table
* fix: update story to account for organization name changes
* fix: resolve typo in regex search for test
I noticed we have been overusing colors in the UI, so simplifying is better for the "look and feel" and maintaining the styles over time.

If you want to have a better sense of what it looks like, I recommend you go to the Chromatic snapshot.