Commit Graph
5594 Commits
Author SHA1 Message Date
Michael Suchacz dcf3cce51c fix(site/src/pages/AgentsPage): clarify empty context usage popover state (#27389)
## Summary

The context usage badge popover showed "Context usage unavailable"
before any assistant message reported token usage, which read like an
error. This changes the empty-state copy to "Context usage will appear
after sending a message." and fixes a spacing bug that state exposed:
the pinned context list's top margin was conditional on a usage
percentage being present, so without usage data the list sat flush
against the message.

## Changes

- `ContextUsageIndicator`: new empty-state copy; unconditional `mt-2` on
the context list.
- Stories: `NoUsage` (message only) and `NoUsageWithContext` (message
plus pinned resource list), both asserting the new copy via hover
interactions.

## Testing

- Storybook interaction stories cover both empty states.
- `biome check` and `tsc --noEmit` pass; verified visually in Storybook.

> This PR was authored by Mux, an AI coding agent, acting on Mike's
behalf.
2026-07-21 16:24:35 +00:00
Sas SwartandClaude Opus 4.8 a9a1dcc65d feat: add network calls column to AI sessions table (#27269)
Add a "Total/blocked network calls" column to the AIBridge sessions
table.

Update `ListAIBridgeSessions` query to calculate network called made and
blocked per session. See query plan
[here](https://explain.dalibo.com/plan/54355c90b165ggb4).

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 14:34:23 +02:00
Danielle Maywood 6014a44c85 fix(site): keep mobile model picker effort row and last model visible (#27336) 2026-07-21 12:37:55 +01:00
Michael Suchacz 3227cac217 feat: add manual chat compaction via /compact (#27081)
Adds a user-triggered `/compact` action for Coder Agents chats: typing
`/compact` in the composer (or picking it from the `/` trigger menu)
summarizes the conversation so far to free up context window space.

## How it works

- New `POST /api/experimental/chats/{chat}/compact` endpoint
(owner-only, RBAC `ActionUpdate`, excluded from the public API reference
via `x-apidocgen skip`). It marks the chat with a durable one-shot
`chats.compaction_requested_at` signal and moves it `waiting -> running`
via a new `RequestCompaction` state transition; no message row is
inserted. AI Gateway attribution needs no per-request key: generation
preparation resolves the owner's synthetic API key (#27170) like any
other turn.
- `RequestCompaction` hands off chat ownership (clears
`worker_id`/`runner_id`) so a worker acquisition hint is published;
since the transition changes no history, the previous runner could
otherwise miss the request under reordered pubsub delivery.
- The background chat worker picks the chat up like any other turn. A
pending manual request takes precedence over turn completion in the
generation decision, and forces compaction even below the automatic
threshold (and when compaction is disabled via threshold=100). The
commit step consumes the request marker in the same transaction; any
transition that ends the turn clears stale markers.
- The summary triplet reuses the automatic-compaction path, now tagged
with a `source` (`automatic` | `manual`) that is plumbed through
streamed progress parts, persisted tool JSON, and the UI label
("Summarized (manual)").
- Validation order: busy chats reject with 409 (state-machine conflict),
empty/already-compacted chats with 409 "nothing to compact", archived
chats with 400; the owner usage-limit check runs last so no-op requests
surface the specific conflict instead of a limit error.
- Web UI: the `/` trigger menu now has a built-in "Commands" group
listing `/compact`; submit intercepts exactly `/compact` and calls the
endpoint instead of sending a message. A personal or workspace skill
named `compact` takes precedence over the built-in command; while skill
collisions are still resolving, an exact `/compact` submission is
blocked with a retryable hint instead of leaking as message text.
History and queued-message edits are never intercepted. After
compaction, the context usage indicator resets to its unknown state
until the next assistant response reports fresh usage, instead of
showing the stale pre-compaction number.
- codersdk: `ExperimentalClient.CompactChat`.

Worker-path execution (rather than compacting synchronously in the
handler) reuses the existing lock fencing, live "Summarizing..."
streaming, retry accounting, restart resilience, and debug-run
observability. Rationale documented in `coderd/x/chatd/ARCHITECTURE.md`.

## Testing

- State machine: transition-matrix coverage for `RequestCompaction`,
marker lifecycle tests (carried by lease renewals/queue appends, cleared
by terminal transitions, consumed by commit), ownership handoff +
acquisition hint assertions.
- Worker: decision-ordering and forced-compaction unit tests;
active-server end-to-end test (manual compact below threshold produces a
`source=manual` summary, returns to `waiting`, no assistant follow-up;
busy chat rejected).
- API: success, archived, non-owner, RBAC-denied, empty-chat, no-daemon
cases; usage-limit ordering (at-limit owners still get
state/nothing-to-compact conflicts for no-op requests, with marker
rollback).
- Frontend: Storybook play tests for the Commands menu group, submit
intercept, skill-name collision, queued-edit passthrough, and
manual/automatic tool rendering; unit tests for command availability
resolution and the post-compaction context usage reset.

> This PR was created by Mux, an AI coding agent, working on Mike's
behalf.
2026-07-21 10:58:08 +02:00
dependabot[bot] 69a045f944 chore: bump axios from 1.16.1 to 1.18.0 in /site (#27350)
Bumps [axios](https://github.com/axios/axios) from 1.16.1 to 1.18.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/releases">axios's
releases</a>.</em></p>
<blockquote>
<h2>v1.18.0 — June 13, 2026</h2>
<p>This release hardens redirect and URL handling, improves the
validateStatus configuration semantics, and includes updates to
documentation, dependencies, and release metadata.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li>
<p><strong>Redirect Header Safety:</strong> Added Node HTTP adapter
support for stripping caller-specified sensitive headers on cross-origin
redirects, helping prevent custom auth headers such as API keys from
leaking to another origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10892">#10892</a></strong>)</p>
</li>
<li>
<p><strong>URL And Request Hardening:</strong> Rejects malformed
<code>http:</code> and <code>https:</code> URLs that omit
<code>//</code> with <code>ERR_INVALID_URL</code>, while tightening
prototype-pollution-safe config reads, stream size limits, FormData
depth handling, data URL sizing, and local <code>NO_PROXY</code>
matching. (<strong><a
href="https://redirect.github.com/axios/axios/issues/11000">#11000</a></strong>)</p>
</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Status Validation:</strong> Added
<code>transitional.validateStatusUndefinedResolves</code> so
applications can opt in to treating <code>validateStatus:
undefined</code> like the option was omitted, while
<code>validateStatus: null</code> remains the explicit way to accept
every status. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li>
<p><strong>Documentation:</strong> Published the v1.17.0 release notes,
fixed a changelog typo, clarified the package update PR policy, and
marked the <code>proxy</code> request config as Node.js-only in the
advanced docs. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10988">#10988</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10992">#10992</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</p>
</li>
<li>
<p><strong>Dependencies:</strong> Bumped <code>@babel/core</code>,
<code>@babel/preset-env</code>, <code>@commitlint/cli</code>,
<code>@commitlint/config-conventional</code>,
<code>@rollup/plugin-babel</code>, <code>@rollup/plugin-commonjs</code>,
<code>@vitest/browser</code>, <code>@vitest/browser-playwright</code>,
<code>eslint</code>, <code>lint-staged</code>, <code>rollup</code>,
<code>vitest</code>, and <code>actions/checkout</code>. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10989">#10989</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10996">#10996</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10997">#10997</a></strong>)</p>
</li>
<li>
<p><strong>Release Metadata:</strong> Prepared the 1.18.0 release by
updating package metadata and the runtime <code>VERSION</code> value.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/11003">#11003</a></strong>)</p>
</li>
</ul>
<h2>🌟 New Contributors</h2>
<p>We are thrilled to welcome our new contributors. Thank you for
helping improve axios:</p>
<ul>
<li><strong><a
href="https://github.com/drori12"><code>@​drori12</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>)</li>
<li><strong><a
href="https://github.com/eyupcanakman"><code>@​eyupcanakman</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
<li><strong><a
href="https://github.com/Adi-Beker"><code>@​Adi-Beker</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.17.0...v1.18.0">Full
Changelog</a></p>
<h2>v1.17.0 — June 1, 2026</h2>
<p>This release adds Node HTTP zstd decompression, hardens config and
release workflows, and fixes authentication, header, proxy, and
type-handling regressions.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Config Hardening:</strong> Guarded <code>socketPath</code>,
<code>params</code>, and <code>paramsSerializer</code> reads with
own-property checks to prevent inherited prototype values from affecting
request behavior, including SSRF-sensitive paths. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10901">#10901</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10922">#10922</a></strong>)</li>
<li><strong>Release Publishing:</strong> Switched the publish workflow
to npm staged publishing for safer, auditable package releases with
provenance. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10926">#10926</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>HTTP Compression:</strong> Added Node HTTP adapter support
for zstd response decompression, with
<code>transitional.advertiseZstdAcceptEncoding</code> controlling
whether <code>zstd</code> is advertised in <code>Accept-Encoding</code>.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/6792">#6792</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10920">#10920</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Authentication Handling:</strong> Restored Basic auth on
same-origin Node redirects while continuing to strip credentials
cross-origin, and aligned the fetch adapter with HTTP adapter behavior
for URL-embedded Basic auth. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10929">#10929</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10896">#10896</a></strong>)</li>
<li><strong>Proxy TLS:</strong> Preserved user <code>httpsAgent</code>
TLS options when tunneling HTTPS requests through HTTP CONNECT proxies.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10957">#10957</a></strong>)</li>
<li><strong>React Native FormData:</strong> Cleared default
<code>Content-Type</code> for React Native <code>FormData</code> so
multipart boundaries can be generated correctly. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10898">#10898</a></strong>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/blob/v1.x/CHANGELOG.md">axios's
changelog</a>.</em></p>
<blockquote>
<h2>v1.18.0 — June 13, 2026</h2>
<p>This release hardens redirect and URL handling, improves the
validateStatus configuration semantics, and includes updates to
documentation, dependencies, and release metadata.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li>
<p><strong>Redirect Header Safety:</strong> Added Node HTTP adapter
support for stripping caller-specified sensitive headers on cross-origin
redirects, helping prevent custom auth headers such as API keys from
leaking to another origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10892">#10892</a></strong>)</p>
</li>
<li>
<p><strong>URL And Request Hardening:</strong> Rejects malformed
<code>http:</code> and <code>https:</code> URLs that omit
<code>//</code> with <code>ERR_INVALID_URL</code>, while tightening
prototype-pollution-safe config reads, stream size limits, FormData
depth handling, data URL sizing, and local <code>NO_PROXY</code>
matching. (<strong><a
href="https://redirect.github.com/axios/axios/issues/11000">#11000</a></strong>)</p>
</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Status Validation:</strong> Added
<code>transitional.validateStatusUndefinedResolves</code> so
applications can opt in to treating <code>validateStatus:
undefined</code> like the option was omitted, while
<code>validateStatus: null</code> remains the explicit way to accept
every status. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li>
<p><strong>Documentation:</strong> Published the v1.17.0 release notes,
fixed a changelog typo, clarified the package update PR policy, and
marked the <code>proxy</code> request config as Node.js-only in the
advanced docs. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10988">#10988</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10992">#10992</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</p>
</li>
<li>
<p><strong>Dependencies:</strong> Bumped <code>@babel/core</code>,
<code>@babel/preset-env</code>, <code>@commitlint/cli</code>,
<code>@commitlint/config-conventional</code>,
<code>@rollup/plugin-babel</code>, <code>@rollup/plugin-commonjs</code>,
<code>@vitest/browser</code>, <code>@vitest/browser-playwright</code>,
<code>eslint</code>, <code>lint-staged</code>, <code>rollup</code>,
<code>vitest</code>, and <code>actions/checkout</code>. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10989">#10989</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10996">#10996</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10997">#10997</a></strong>)</p>
</li>
<li>
<p><strong>Release Metadata:</strong> Prepared the 1.18.0 release by
updating package metadata and the runtime <code>VERSION</code> value.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/11003">#11003</a></strong>)</p>
</li>
</ul>
<h2>🌟 New Contributors</h2>
<p>We are thrilled to welcome our new contributors. Thank you for
helping improve axios:</p>
<ul>
<li><strong><a
href="https://github.com/drori12"><code>@​drori12</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10984">#10984</a></strong>)</li>
<li><strong><a
href="https://github.com/eyupcanakman"><code>@​eyupcanakman</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a></strong>)</li>
<li><strong><a
href="https://github.com/Adi-Beker"><code>@​Adi-Beker</code></a></strong>
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.17.0...v1.18.0">Full
Changelog</a></p>
<h2>v1.17.0 — June 1, 2026</h2>
<p>This release adds Node HTTP zstd decompression, hardens config and
release workflows, and fixes authentication, header, proxy, and
type-handling regressions.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Config Hardening:</strong> Guarded <code>socketPath</code>,
<code>params</code>, and <code>paramsSerializer</code> reads with
own-property checks to prevent inherited prototype values from affecting
request behavior, including SSRF-sensitive paths. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10901">#10901</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10922">#10922</a></strong>)</li>
<li><strong>Release Publishing:</strong> Switched the publish workflow
to npm staged publishing for safer, auditable package releases with
provenance. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10926">#10926</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>HTTP Compression:</strong> Added Node HTTP adapter support
for zstd response decompression, with
<code>transitional.advertiseZstdAcceptEncoding</code> controlling
whether <code>zstd</code> is advertised in <code>Accept-Encoding</code>.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/6792">#6792</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10920">#10920</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Authentication Handling:</strong> Restored Basic auth on
same-origin Node redirects while continuing to strip credentials
cross-origin, and aligned the fetch adapter with HTTP adapter behavior
for URL-embedded Basic auth. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10929">#10929</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10896">#10896</a></strong>)</li>
<li><strong>Proxy TLS:</strong> Preserved user <code>httpsAgent</code>
TLS options when tunneling HTTPS requests through HTTP CONNECT proxies.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10957">#10957</a></strong>)</li>
<li><strong>React Native FormData:</strong> Cleared default
<code>Content-Type</code> for React Native <code>FormData</code> so
multipart boundaries can be generated correctly. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10898">#10898</a></strong>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/axios/axios/commit/2d06f96e8602c2db13b65a26340ee4a1bbc0b61f"><code>2d06f96</code></a>
chore(release): prepare release 1.18.0 (<a
href="https://redirect.github.com/axios/axios/issues/11003">#11003</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2"><code>32fc489</code></a>
fix: malformed http urls (<a
href="https://redirect.github.com/axios/axios/issues/11000">#11000</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/b40ce498abfa10d90b873b4fd08f520afa5d2545"><code>b40ce49</code></a>
chore(deps-dev): bump the development_dependencies group with 10 updates
(<a
href="https://redirect.github.com/axios/axios/issues/10">#10</a>...</li>
<li><a
href="https://github.com/axios/axios/commit/fe964f960ecb52c3e1155b0daf7be77541956b01"><code>fe964f9</code></a>
docs: mark proxy config as Node.js only (<a
href="https://redirect.github.com/axios/axios/issues/10995">#10995</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/5f229d2d1f018d1db3dab6bbe034dbf3f9041b99"><code>5f229d2</code></a>
chore(deps): bump actions/checkout from 6.0.2 to 6.0.3 in the
github-actions ...</li>
<li><a
href="https://github.com/axios/axios/commit/fae9d4e7db6a858c407c75e607a071c533c5c4f6"><code>fae9d4e</code></a>
docs: clarify package update PR policy (<a
href="https://redirect.github.com/axios/axios/issues/10992">#10992</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/28ab2ced820e55192806c53472ab3eb0cbb68dc2"><code>28ab2ce</code></a>
chore(deps-dev): bump the development_dependencies group with 2 updates
(<a
href="https://redirect.github.com/axios/axios/issues/10989">#10989</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/a8e4f13aeecc45a3b8fab3ecfd9ddb5d70fb772b"><code>a8e4f13</code></a>
fix(core): keep default validateStatus when request passes undefined (<a
href="https://redirect.github.com/axios/axios/issues/10899">#10899</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/614f4552a17de757d4171ad7c3bd38c9c1025fd8"><code>614f455</code></a>
docs: publish v1.17.0 release notes (<a
href="https://redirect.github.com/axios/axios/issues/10988">#10988</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/6bb12c191f5380fad321322fb90216ae0dc36985"><code>6bb12c1</code></a>
fix: custom auth headers not stripped on cross-origin redirects (<a
href="https://redirect.github.com/axios/axios/issues/10892">#10892</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/axios/axios/compare/v1.16.1...v1.18.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=axios&package-manager=npm_and_yarn&previous-version=1.16.1&new-version=1.18.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/coder/coder/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 19:06:59 +00:00
Michael Suchacz f18c664be2 fix(site): stack settings layouts on mobile (#27334)
## Problem

On mobile viewports every settings shell renders a fixed 240px sidebar
next to the content in a non-responsive flex row, leaving the content
almost no width. The MCP Servers page is worst: its fixed-layout table
cannot shrink, so the whole page collapses into a single cramped column.

## Changes

- `Sidebar` component: full width below the `lg` breakpoint, `w-60` at
`lg`+.
- Six settings layouts (AI, Deployment, Organization, User, Workspace,
Template) stack the nav above the content below `lg` and keep the
previous side-by-side spacing at `lg`+. Content wrappers get `min-w-0`
so flex children cannot force overflow, and horizontal padding tightens
on small screens.
- MCP servers table gets `min-w-[640px]` so the existing `overflow-auto`
wrapper provides horizontal scrolling instead of colliding column
headers.

Tailwind class changes only; no component or behavior changes.

## Testing

- `pnpm check` and `pnpm run lint:types` pass.
- Dogfood UAT on a dev deployment: at 390x844 the MCP Servers,
Deployment, Account, and Template settings pages stack nav-above-content
with no horizontal body overflow and a scrollable MCP table; boundary
verified stacked at 1023px and side-by-side at 1024px; at 1440x900 the
layouts are pixel-identical to before (240px sidebar, 112px gap, 40px
padding).

Closes CODAGT-828.

> Created by Mux, an AI agent, on Mike's behalf.
2026-07-20 19:35:23 +02:00
Susana Ferreira a9fdf87a2f feat: add GET /groups/{group}/members/ai/spend (#27130)
## Description

Adds `GET /api/v2/groups/{group}/members/ai/spend?user_ids=...` (also available org-scoped at `/api/v2/organizations/{org}/groups/{groupName}/members/ai/spend`) to return per-member AI spend attributed to a group, along with each member's effective budget group and the applied spend limit when the queried group is their effective budget source.

In the UI, this endpoint is used alongside the existing `/api/v2/groups/{group}/members` endpoint. AI spend data is kept separate from that endpoint so that:

- Different concepts stay on different endpoints: identity (group members) vs. cost control (spend). Cost control is an additional feature layered on top of groups/orgs.
- Callers that don't need spend information don't pay for its computation.

UI flow:

1. Request `/api/v2/groups/{group}/members` → returns the group's members.
2. Request `/api/v2/groups/{group}/members/ai/spend?user_ids=...` with the IDs from step 1.

**Note:** Only current members of the queried group are returned. `spend_limit_micros` and `limit_source` are populated only when the queried group is the member's effective budget source (its own limit or a user override). `effective_group_id` is null when the member's budget resolves to a group in another organization, since an organization is treated as a tenant boundary.

<img width="2880" height="1904" alt="image" src="https://github.com/user-attachments/assets/33ed395d-d1a3-4b46-bb04-c8d3f41c8886" />

## Changes

- Add `codersdk.GroupMembersAISpend` and `GroupMemberAISpend` types, reusing the shared `AISpendPeriodWindow`.
- Add `GetGroupMembersAISpend` SQL query with a dbauthz per-row filter that mirrors `GET /api/v2/groups/{group}/members`.
- Add handler and routes under `/groups/{group}/members/ai/spend` (and the org-scoped alias) with a required `user_ids` query param (cap 100). Callers with more than 100 members are expected to batch across multiple requests.
- Add codersdk client method.
- Tests: dbauthz, raw SQL, endpoint, and role-access.

Closes https://linear.app/codercom/issue/AIGOV-471/backend-group-members-endpoint-with-members-spend

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
2026-07-20 13:04:37 +01:00
Susana Ferreira 2adc8f5272 feat: add GET /organizations/{org}/groups/ai/spend (#27123)
## Description

Adds `GET /api/v2/organizations/{org}/groups/ai/spend?group_ids=...` to return per-group AI spend and configured limits for a set of groups in an organization.

In the UI, this endpoint is used alongside the existing `/api/v2/organizations/{org}/groups` endpoint. AI spend data is kept separate from that endpoint so that:

- Different concepts stay on different endpoints: identity (groups) vs. cost control (spend). Cost control is an additional feature layered on top of groups/orgs.
- Callers that don't need spend information don't pay for its computation.

UI flow:

1. Request `/api/v2/organizations/{org}/groups` → returns the organization's groups.
2. Request `/api/v2/organizations/{org}/groups/ai/spend?group_ids=...` with the IDs from step 1.

The groups endpoint from 1) is currently not paginated, but if pagination is added later, this design keeps the two responses in sync. This spend endpoint intentionally takes `group_ids` rather than paginating on its own, since it depends on the group set from step 1. Pagination could be added in the future, especially for Cost Control-focused pages.

<img width="2880" height="1460" alt="image" src="https://github.com/user-attachments/assets/ea83b74d-6a4f-45a6-af2f-1024e019da07" />

## Changes

- Add `codersdk.OrganizationGroupsAISpend` and `OrganizationGroupAISpend` types, plus a shared `AISpendPeriodWindow` embedded in the spend response.
- Add `GetOrganizationGroupsAISpend` SQL query with a dbauthz per-row filter that mirrors `GET /organizations/{org}/groups`.
- Add handler and route under `/organizations/{organization}/groups/ai/spend` with a required `group_ids` query param (cap 100). Callers with more than 100 groups are expected to batch across multiple requests.
- Add codersdk client method.
- Tests: dbauthz, raw SQL, endpoint, and role-access.

Closes https://linear.app/codercom/issue/AIGOV-466/backend-organization-groups-endpoint-with-groups-spend

> [!NOTE]
> Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
2026-07-20 12:54:52 +01:00
Michael Suchacz 9f4ddea571 feat: revoke MCP server OAuth grants at the provider on disconnect (#27300)
Closes
[CODAGT-805](https://linear.app/codercom/issue/CODAGT-805/revoke-oauth-grants-at-the-source-for-mcp-servers).

The experimental MCP server OAuth2 disconnect endpoint previously
deleted only the stored token row, leaving the grant active at the OAuth
provider. This PR adds provider-side token revocation while keeping
local disconnect independent of provider availability.

## Changes

- Add `mcp_server_configs.oauth2_revocation_url` in migration `000547`.
The value can be configured manually, discovered from RFC 8414 metadata,
and managed through the MCP server settings UI. Non-admin responses
redact it with the other OAuth2 fields.
- Revoke the refresh token first through the RFC 7009 endpoint, then
fall back to the access token only for `unsupported_token_type`. Public
clients send `client_id`; confidential clients use
`client_secret_basic`.
- Delete the local token transactionally before best-effort provider
revocation. Callers without a token receive the same response for hidden
and nonexistent config IDs, and provider failures return a generic
warning without exposing provider response bodies.
- Require HTTPS revocation endpoints except for HTTP loopback URLs.
Redirects must preserve the POST and remain on the configured origin.
Redirect errors omit provider-controlled paths and query strings so
reflected token material cannot enter logs.
- Treat `200 OK` and `204 No Content` as completed revocations. `202
Accepted` remains a failure because it does not confirm completion.
- Prevent an in-flight refresh from recreating a token deleted by
disconnect. Refresh persistence now uses an optimistic update keyed by
token ID and `updated_at`; only the OAuth callback can create a token
row. Refresh conflicts reload the current row or clear in-memory auth
when disconnect deleted it.
- Return `{token_revoked, token_revocation_error}` from disconnect,
while retaining SDK compatibility with the legacy `204` response. The UI
surfaces provider revocation failures as warning toasts.
- Document revocation endpoint discovery, HTTPS requirements, and
best-effort disconnect behavior.

No token or no configured revocation URL returns `token_revoked: false`
without an error, so disconnect remains idempotent.

> Updated by Mux, an AI coding agent, on Mike's behalf.
2026-07-20 00:14:03 +02:00
Michael Suchacz 9b3af629cd fix: hide and reject chat models from disabled AI providers (#27070) 2026-07-19 08:33:40 +02:00
Michael Suchacz 34ed124478 fix(site): align React Compiler check scope with vite.config.mts (#27216)
## Stack Context

First PR of a 6-PR stack that thins the agent instruction corpus (~4,800
lines down to ~2,800) by removing startup bloat, assigning each
procedure one canonical owner, and fixing rules that drifted from
reality. Split from #27203 for reviewability.

## Why?

`site/vite.config.mts` compiles `src/pages/AIBridgePage/` with the React
Compiler, but `site/scripts/check-compiler.mjs` did not include that
directory. Compiler regressions in AIBridgePage were invisible to CI:
code could silently bail out of compilation with no signal. The two
lists had already drifted once, which is exactly how this class of bug
recurs.

## What?

- Add `src/pages/AIBridgePage/` to the check-compiler scope. Verified
all 381 functions in scope compile cleanly.
- Cross-reference the two lists with comments so the next person who
edits one finds the other.

This is the only behavioral (non-docs) change in the stack, which is why
it sits at the bottom.

> This PR was prepared by Mux (AI agent) on Mike's behalf.
2026-07-19 07:29:53 +02:00
Michael Suchacz 1ea61b976b fix(site): prevent slash menu from flashing at top-left corner when closed (#27326)
Typing `/` in the agent chat input opens the skills slash menu. Pressing
Backspace to erase the `/` made the menu flash at the top-left corner of
the app for a split second before disappearing.

Radix keeps the popover content mounted through its exit animation, but
the caret-positioned `PopoverAnchor` was unmounted in the same render
that closed the menu. Without an anchor, the popper repositioned the
still-visible closing content to the viewport origin. The anchor now
stays rendered at the last known caret rect, so the menu holds its
position while it animates out.

Verified with a frame-by-frame position recorder in the browser: before
the fix the closing menu jumped from the caret position to `(0, 4)`;
after the fix it stays in place until unmount. Added a
`BackspaceClosesMenuWithoutRepositioning` story that fails without the
fix.

> This PR was created by Mux, an AI coding agent, on Mike's behalf.
2026-07-18 22:43:34 +02:00
Michael Suchacz 46d1823c0a feat: add workspace skills to agent chat slash menu (#25600)
> This Pull Request was updated by Mux working on behalf of Mike.

Adds workspace skills to the agent chat slash menu, sourced entirely
from the chat's pinned context resources (the single-chat GET response
the page already fetches), the same inventory `read_skill` resolves
from. No new API endpoint is introduced.

Personal entries insert `/name`, or `/personal/name` when the name
collides with a workspace skill or the chat's pinned context has not
resolved yet; workspace entries insert `/workspace/name`. Qualified
aliases stay searchable even when the displayed trigger is bare. Before
a chat binds a workspace (new chat form, or a selected but unbound
workspace), the menu lists personal skills only.

Sending a message invalidates the chat detail query, and chatd
broadcasts a context watch event when a first-turn bind pins the chat,
so the menu picks up newly pinned context without a reload.

Makes `UpdateChatWorkspaceBinding` a no-op when the requested
workspace/build/agent binding is unchanged, preserving `updated_at` so
chat list ordering and watch events stay stable.

Includes regression coverage for the no-op binding guard, pinned-context
skill mapping, collision qualification, and skills menu behavior.

Refs
[CODAGT-474](https://linear.app/codercom/issue/CODAGT-474/ux-improvements-for-coder-agents)
(skills autocompleting in the editor).
2026-07-18 21:52:02 +02:00
Michael Suchacz 36e36e2048 fix(site): wrap workspace topbar controls on narrow viewports (#27313)
On mobile-width viewports the workspace page grew to ~1080px wide (390px
viewport), pushing the schedule controls, status indicator, and action
buttons off-screen. Users had to zoom out or scroll horizontally to
reach Stop/Restart/Favorite/Share.

The topbar header and the right-side controls group used non-wrapping
flex rows, and every child is a `whitespace-nowrap` button, so the row's
minimum width (~725px for the controls alone) forced the document wider
than the viewport.

## Changes

- `WorkspaceTopbar`: allow the topbar header and the right controls
group to wrap; right controls stay right-aligned when they wrap onto
their own row.
- `WorkspaceActions`: allow the button row to wrap.
- `TopbarData`: merge a caller-provided `className` (no existing caller
passed one); the workspace breadcrumbs use it to wrap on very narrow
screens.

## Verification

Compared before/after with agent-browser on Storybook stories
(`Workspace: Running`, `WorkspaceTopbar: Outdated / WithQuotaWithOrgs /
Dormant / ConnectedWithMaxDeadline`):

| Viewport | Before `scrollWidth` | After `scrollWidth` |
|---|---|---|
| 320 | 1080 (overflow) | 305 (fits) |
| 390 | 1080 (overflow) | 375 (fits) |
| 768 | 1080 (overflow) | 753 (fits) |
| 1024 | 1080 (overflow) | 1009 (fits) |
| 1440 | 1425 (fits) | 1425, pixel-identical (0% diff) |

At widths >= 1280 the layout is unchanged (0% pixel diff at 1440 across
the stories above). Between ~1080-1230px the controls now wrap onto a
second right-aligned row instead of squeezing label text onto two lines
inside a single row.

Validation: `biome check`, `tsc --noEmit`, and `pnpm test:storybook` for
`Workspace.stories.tsx` + `WorkspaceTopbar.stories.tsx` (36 passed).

> This PR was prepared by Mux, an AI coding agent, on Mike's behalf.
2026-07-17 18:12:25 +02:00
Michael Suchacz 1ac106255b feat: add Anthropic 1M context window toggle for Agents model configs (#27257) 2026-07-17 13:04:13 +02:00
Asher 2ac2295b1e fix: do not send or use stale init dynamic parameter state (#27283)
In summary, we use the init message if we have no autofill params. If we
do, then we ignore the init message, send another message with the
autofilled values, and then when we get *that* response, finally we
render the form since we know we have good state. This eliminates the
possibility of temporarily rendering with stale state.

This is the same fix that was applied to the edit page, but on the
create page this time. The only difference is that the create page does
not need to wait on a build parameters query, instead it has to wait on
the first message from the socket (to get defaults).

This also makes one change where we would send the defaults in the init
message. The server already knows the defaults so there is no need to
send them. The advantage here is that we no longer need to wait for the
first message, and it also fixes an issue where fields with blank values
were getting validation errors because they were not filled out, before
the user had a chance to actually fill them out.
2026-07-16 12:55:43 -08:00
Yevhenii Shcherbina 1453b4b1fc docs: document Bedrock mantle protocol (#27296)
Implements:
https://linear.app/codercom/issue/AIGOV-518/add-docs-for-bedrock-mantle
Follow-up to: https://github.com/coder/coder/pull/26745
2026-07-16 14:58:09 -04:00
Michael Suchacz 3dd9265fa6 feat: add UI option to disconnect OAuth2 MCP credentials (#27299)
Closes
[CODAGT-804](https://linear.app/codercom/issue/CODAGT-804/add-ui-option-to-revoke-oauth-mcp-credentials).

Users could authenticate with an OAuth2 MCP server from the chat input,
but there was no UI to disconnect those per-user credentials. The
backend endpoint (`DELETE
/api/experimental/mcp/servers/{id}/oauth2/disconnect`) already existed.

## Changes

- Connected OAuth2 MCP rows in the chat input plus menu now show a
disconnect icon button next to the enable switch. It opens a
confirmation dialog; confirming calls the disconnect endpoint, shows a
toast, and refetches MCP configs so the row reverts to the `Auth` button
without a reload.
- New `disconnectMCPServerOAuth2` API client method and react-query
mutation that invalidates `mcp-server-configs`.
- Storybook interaction tests: control visibility per auth state, cancel
makes no API call, confirm calls the endpoint once, failed disconnect
keeps the dialog open.
- Hardened `TestMCPServerConfigsOAuth2Disconnect`: seeded tokens flip
`auth_connected`, disconnect only removes the calling user's token, and
repeat disconnect stays idempotent.

The endpoint removes the token stored in Coder; it does not revoke the
upstream OAuth grant, so the UI copy says "disconnect" rather than
"revoke".

Validated with the targeted Go test, Storybook tests (51 passed), tsc,
biome, the react-compiler check, and a manual dogfood run (seeded token,
disconnect/cancel/reconnect flows verified in the UI).

> This PR was authored by Mux, an AI coding agent, on Mike's behalf.
2026-07-16 18:26:35 +02:00
Yevhenii ShcherbinaandJake Howell 9862f10484 feat(site): add Bedrock mantle protocol selector to provider form (#27156)
Implements:
https://linear.app/codercom/issue/AIGOV-517/add-ui-for-bedrock-mantle

Follow-up to https://github.com/coder/coder/pull/26745, which added AWS
Bedrock **mantle** support to the backend and modeled it as a `protocol`
field on the Bedrock provider settings.
## What changed

- Adds a **Protocol** selector to the Bedrock provider form: InvokeModel
(default) or Mantle.
- The form is now protocol-aware:
- **Model** / **Small-fast model** fields are shown only for
InvokeModel. Mantle is a passthrough (the client sends the model at
request time), so the fields are hidden and omitted from the saved
settings.
- **Endpoint** validation, placeholder, and hint switch per protocol.
Mantle requires a `https://bedrock-mantle.{region}.api.aws/anthropic`
URL; InvokeModel keeps the
`https://bedrock-runtime.{region}.amazonaws.com` shape. The `/anthropic`
suffix is required for mantle because the SDK appends `/v1/messages` to
the base URL.

## Manual Testing

Tested the following scenarios:

1. Creating a new Mantle provider — works.
2. Creating a new InvokeModel provider — works.
3. Verifying that an existing InvokeModel provider continues to work.
4. Upgrading an existing InvokeModel provider to Mantle — works.

## Screenshots

### InvokeModel

<img width="1085" height="474" alt="image"
src="https://github.com/user-attachments/assets/4c36b9b0-0eb8-4b17-80b7-e2112325f8d1"
/>


### Mantle

<img width="1082" height="357" alt="image"
src="https://github.com/user-attachments/assets/e8caef26-83d1-4b7e-8f96-79079949e8f1"
/>

---------

Co-authored-by: Jake Howell <jake@hwll.me>
2026-07-16 09:37:48 -04:00
Jeremy Ruppel b3ff4baeb9 fix: smooth compose loader to files page transition (#27277)
## Summary

During the template builder compose flow, the transition into the
template
files page briefly flashed the wizard form again before the files page
settled.

Root cause: the loader was gated on `createMutation.isPending`. When the
compose
POST resolved, `isPending` flipped to `false` in the same commit that
`onSuccess` navigated to the files page, so `TemplateBuilderPageView`
repainted
the wizard form for a frame before the route change committed and
unmounted it.

Fix: keep the loader mounted while the mutation is pending **or**
succeeded
(`createMutation.isPending || createMutation.isSuccess`). Since
`onSuccess`
always navigates away, the loader stays until the component unmounts, so
the
form never reflashes. The error path is unaffected (`isSuccess` stays
false).

Resolves DEVEX-561.


https://github.com/user-attachments/assets/6d5ec04e-9f97-4864-bd18-e1e75055f079

## Scope

Targets the wizard form reflash only. Two adjacent items were identified
during
investigation and intentionally left out:

- The destination files page briefly shows its own `<Loader />` while it
fetches
template files. Smoothing that requires prefetching before navigation
and is a
  larger change.
- The `justCreated` "Awesome, you just created a template!" alert is
cleared by a
mount effect, so it renders one frame then disappears. Arguably its own
bug.

Happy to follow up on either if wanted.

## Testing

- Biome clean on the changed file.
- Manual: build a template through the wizard and confirm the loader
holds
  straight through to the files page with no form flash.

## Stack

Stacked on top of #27276 (DEVEX-593).

---

Generated by Coder Agents.
2026-07-16 09:15:11 -04:00
Jeremy Ruppel 3ddf7d3baa fix: stop the template builder build progress bar from looping (#27276)
## Summary

The template builder's "Building your template" loader had a progress
bar that
animated 0→100% every 5s with an infinite repeat, so it visibly
restarted over
and over while a template built. It looked broken and was frustrating to
watch.

This replaces the looping fill with a single ease-out fill that
decelerates
toward 90% and holds until the request resolves and the loader unmounts.

Since the loader is intentionally indeterminate and no progress is
streamed to
the browser, this also removes the now-dead `onUpdate` callback plumbing
from
the backend `waitForProvisionerJob` (its only caller passed `nil`).

Resolves DEVEX-593.


https://github.com/user-attachments/assets/6d5ec04e-9f97-4864-bd18-e1e75055f079

## Commits

- `refactor(coderd): drop unused onUpdate callback from
waitForProvisionerJob`
- `fix(site/src/pages/TemplateBuilder): stop build progress bar from
looping`

## Testing

- `go build ./coderd/` passes with the reduced `waitForProvisionerJob`
signature.
- Biome clean on the changed frontend file.
- Storybook: `pages/TemplateBuilder/BuildingTemplateLoader` shows the
bar fill
  once and hold, with no restart.

<details>
<summary>Implementation plan</summary>

# DEVEX-593: Stop the build progress bar from looping repeatedly

## Problem

While the template builder composes and imports a template, the FE shows
`BuildingTemplateLoader`. Its progress bar animates from 0% to 100% over
5s
with `repeat: Number.POSITIVE_INFINITY`, so it visibly restarts over and
over.
Users report this looks broken and is frustrating to watch while
waiting.

## Decision (scope)

Minimal fix only: **stop the loop**, plus remove the now-dead `onUpdate`
plumbing from the backend. Since the UI is intentionally indeterminate
and no
progress signal is streamed, the callback serves no purpose and should
be
deleted rather than left as dead code.

### Why not "real sync" now

- `POST /api/v2/templatebuilder/compose/template` is a single blocking
request.
  It composes, bundles, inserts the provisioner job, then calls
`waitForProvisionerJob(jobCtx, provisionerJob.ID, nil)` and only
responds once
  the job completes.
- The `onUpdate` callback runs server-side only. Nothing is streamed to
the
  browser during the wait, so the FE has no progress signal to bind to.
- A provisioner job exposes no numeric percentage. Only status
transitions
  (`pending -> running -> succeeded`) and coarse log stages
(`init/plan/graph/apply`) exist. Real sync would require converting the
endpoint to a streaming protocol (SSE/WebSocket) plus FE rework, which
is
  disproportionate for this 1-point ticket.

### Keep polling (do not switch to pubsub-block)

The wait could technically block instead of poll: on completion
`CompleteJob`
publishes `ProvisionerJobLogsNotifyMessage{EndOfLogs: true}` on the job
logs
notify channel, so we could subscribe and wait for that message with the
context timeout as a fallback. We deliberately do not do that here:
correctness
would require subscribe-before-completion plus an initial DB completion
check to
avoid a race, and Postgres LISTEN/NOTIFY is at-most-once (can drop under
load),
so a poll fallback would still be needed. The existing backoff poll
(100ms -> 200ms -> 500ms -> 1s) is simple and robust for a short-lived
synchronous request.

## Approach

Replace the looping fill with a single, non-repeating ease-out fill that
decelerates and approaches (but never reaches) ~90%, holding there until
the
request resolves and the loader unmounts. This reads as continuous
forward
progress for an unknown-duration operation and never restarts. The
floating-icon
animation is intentional ambient motion and is not in scope.

## Out of scope

- Any behavioral change to how the endpoint waits (it still blocks on
the job).
- Streaming real job progress to the browser.
- Changes to the floating-icon animation.

</details>

---

Generated by Coder Agents.
2026-07-16 09:14:07 -04:00
TJandCoder Agents 529b2ead78 feat(site/src/pages/AgentsPage): show "Archived chats" sidebar heading when viewing archived chats (#26926)
In the agents sidebar, show "Archived chats" instead of "Chats" when the
archive filter is set to `archived`. The heading reads the existing
`sidebarFilters.archiveStatus` state, the same condition already used
for the archived empty-state message.

---

_This PR was opened by [Coder Agents](https://coder.com/) on behalf of
@tracyjohnsonux._

---------

Co-authored-by: Coder Agents <noreply@coder.com>
2026-07-16 06:04:52 -07:00
Danielle Maywood 213f5ce606 fix(site): redesign provider tri-state controls (#27288) 2026-07-16 12:12:38 +01:00
Danielle Maywood 457fa5afa3 fix(site): move thinking settings to provider configuration (#27287) 2026-07-16 12:12:24 +01:00
Danielle Maywood 9d1e881093 refactor(site/src/pages/AgentsPage): use model selector for personal overrides (#27229) 2026-07-16 11:22:48 +01:00
Andrew Aquino baf4dfae4d fix(site/src/pages/TemplateBuilder): display TemplateCard/ModuleCard's official badge inline (#27036)
closes DEVEX-575

There are some screen widths / base template names where the official
badge will break lines by itself as an orphan (see Google Compute Engine
(Linux) in screenshot below). However, I personally prefer this over the
current flex layout (compare with the screenshot in original issue)

<img width="1840" height="1191" alt="image"
src="https://github.com/user-attachments/assets/d5bee310-0202-4d45-aef7-767e457be051"
/>

Unfortunately `&nbsp;` only works if the entities on either side are
both text--not text on the left + image on the right, which is what we
have here.

^One alternative to prevent orphan badges is to split the base template
name by words, then wrap the last word + the official badge in a span
with `white-space: nowrap;`. But that feels a little overwrought to me;
I like the clarity of continuing to just show `{name}` in the JSX. What
do you guys think?
2026-07-15 15:27:07 -07:00
Faur Ioan-Aurel 0caaac5d27 fix: prebuild coderd before Playwright startup for e2e tests (#27136)
The test-e2e job could flake while Playwright waited for its webServer
to become ready. CI already built site/e2e/bin/coder, but that binary
was built before pnpm build and without the embed tag, so Playwright
ignored it and started coderd with go run -tags embed instead. That put
Go compilation, including frontend asset embedding, inside Playwright's
webServer timeout.

Local runs had a similar ordering trap. pnpm playwright:test invoked
Playwright directly, and Playwright starts webServer before globalSetup,
so the existing preflight build could not guarantee a binary existed
before webServer startup.

Build the E2E coder binary with the embed tag and make it depend on
site/out/index.html. In CI, build the frontend first, then build the E2E
binary, then run Playwright. For local runs, have pnpm playwright:test
and pnpm playwright:test-ui run make site/e2e/bin/coder before invoking
Playwright.

Playwright now starts the prebuilt site/e2e/bin/coder binary and waits
on the public /healthz endpoint instead of an authenticated API
endpoint. This keeps compilation outside the webServer readiness timeout
and makes the readiness probe quieter and more direct. I moved to
/healtz because the existing endpoint was returning 401, which still
means “server is up,” but it is a strange readiness signal. /healthz is
explicitly public and returns 200 OK once the HTTP server is accepting
requests.

Caveat: running pnpm exec playwright test
--config=e2e/playwright.config.ts directly bypasses the package script
and therefore bypasses the prebuild. Use pnpm playwright:test or make
test-e2e for the supported local flow.

Because the site package scripts now call make, add make to knip's
ignored
system binaries.

Tests:
- pnpm lint:types
- pnpm exec playwright test --config=e2e/playwright.config.ts --list
-
PATH="/opt/homebrew/opt/make/libexec/gnubin:/opt/homebrew/opt/gnu-getopt/bin:$PATH"
make gen/mark-fresh
-
PATH="/opt/homebrew/opt/make/libexec/gnubin:/opt/homebrew/opt/gnu-getopt/bin:$PATH"
pnpm playwright:test --list

<!--

If you have used AI to produce some or all of this PR, please ensure you
have read our [AI Contribution
guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
before submitting.

-->
2026-07-15 21:21:59 +03:00
Ethan cc11c8a536 feat: surface model content-filter refusals as a blocked chat error (#27118)
Blocked turns from a provider's content filter (Anthropic's `refusal`
stop reason with empty content) previously ended silently on the
"Thinking" spinner. They now end as a terminal `content_filter` error
that renders as a "Response blocked" message with the provider's
category and explanation.

<img width="888" height="335" alt="image"
src="https://github.com/user-attachments/assets/cef85a59-4091-4e62-9d45-1eb06748db48"
/>


Closes CODAGT-611

Follow-ups will involve implementing fallbacks, but this alone is pretty
important
2026-07-15 16:36:31 +10:00
Cian JohnstonandCopilot Autofix powered by AI 8eaf4f507b feat: generate the known-models catalog and aigateway prices (#27146)
- Regenerates `prices.json` from models.dev. The seeder only upserts, so
existing deployments keep delisted models.
- Generate the frontend known-models catalog instead of hand-writing it.
`make gen/aibridge-prices` fetches models.dev once
- Moved patches to model definitions to separate `overrides.jq` which 
  handles both `claude-sonnet-4-5` 200k context and 'aliasing' Fable 5
  as Mythos 5.
- Editorial choices of selection, order, aliases, and reasoning defaults 
  live in `curation.json`.
- Adds golden join tests with one error case per validation, a
no-network drift test comparing curation to the checked-in artifact, and
pinned invariants for the Anthropic thinking-mode split (the wrong side
returns HTTP 400) and the sonnet-4-5 context pin.

Adding a model is now one `curation.json` entry plus `make
gen/aibridge-prices`, assuming it is present on models.dev.

> This PR was authored by Coder Agents on Cian's behalf.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-14 19:36:27 +00:00
McKayla はな b377bec5f4 fix(site): replace ansi-to-html in the log viewer (#27206) 2026-07-14 12:54:16 -06:00
Nick Vigilante 61e52532c0 docs: wrap placeholder syntax in backticks in CLI help and swagger annotations (#27194)
## Problem

Generated reference docs (`docs/reference/cli/*`,
`docs/reference/api/*`) contained raw placeholder and JSON syntax that
came straight from Go CLI help strings and swagger annotations. HTML
renderers treat the angle-bracket tokens (`<team-slug>`, `<uuid>`,
`<KEY>`, etc.) as unknown tags and drop them, so readers see
broken/half-missing text today. The same strings also break MDX parsing.

## Fix

Wrap the placeholder/JSON syntax in backticks **at the source** (Go help
strings and swagger annotation comments), then `make gen`. Rendered docs
now show the placeholders as inline code instead of dropping them.

### Source changes

| File | Placeholder wrapped | Surfaces in |
|------|--------------------|-------------|
| `codersdk/deployment.go` | `` `<organization-name>/<team-slug>` `` |
`cli/server.md`, `coder --help`, settings UI |
| `codersdk/deployment.go` | `` `CODER_AI_GATEWAY_PROVIDER_<N>_*` ``, ``
`CODER_AI_GATEWAY_PROVIDER_<N>_<KEY>` `` | `api/schemas.md` |
| `cli/tokens.go` | `` `<type>:<uuid>` `` | `cli/tokens_create.md`,
`coder --help` |
| `coderd/aitasks.go` | `` `owner:<…>` ``, `` `organization:<…>` ``, ``
`status:<status>` `` | `api/tasks.md` |
| `coderd/exp_chats.go` | `` `pr_status:<…>` `` and sibling filter
tokens | `api/chats.md` |
| `coderd/provisionerdaemons.go`, `coderd/provisionerjobs.go` | ``
`{'tag1':'value1','tag2':'value2'}` `` | `api/organizations.md`,
`api/provisioning.md` |

Everything else in the diff (`coderd/apidoc/*`, `docs/reference/**`,
`*.golden`, `site/src/api/typesGenerated.ts`) is `make gen` output.

## Reviewer notes (the "considered pass" from the ticket)

- **Product-visible:** this changes `coder server --help` and `coder
tokens create --help` output, and the `server-config.yaml` reference
comment. Backticks in terminal help are literal but read fine as
placeholder markers.
- **Settings UI:** the `deployment.go` `Description` also renders in the
deployment settings page. If that field is not Markdown-rendered,
literal backticks will show there. Happy to drop the `deployment.go`
change if you'd rather keep the UI text clean and fix `server.md`
another way.
- **Out of scope here:** `docs/reference/cli/agent-firewall.md`
(`<host>`/`<glob>`) is generated from the external
`github.com/coder/boundary` module, not this repo. It needs an upstream
fix + module bump; not included in this PR.

<details>
<summary>Implementation notes / decision log</summary>

- Scope taken from DOCS-551: source-level backtick pass for generated
reference docs only. Hand-written Markdown fixes are tracked separately
(companion ticket).
- Swagger `@Param` descriptions are Go comments, so the existing `\|`
pipe-escaping in the chats `q` filter is preserved inside the new
backticks (still required for the Markdown table cell to render `|`).
- Verified after `make gen`: generated docs render placeholders as code
spans, table pipes intact; `gofmt` clean; changed Go packages build; no
emdash/endash introduced.
- Deliberately left the `AIProviderConfig` type-level doc comment
untouched because it does not surface in any generated doc (kept the
diff to doc-feeding comments).

</details>

Linear: DOCS-551

---

_Opened by Coder Agents on behalf of @nickvigilante._



---

## Evidence: placeholders dropped on the live docs site

Verified **2026-07-14** against the live site (`coder.com/docs`, i.e.
`main`, pre-merge) by loading each affected page in headless Chrome and
reading the post-hydration DOM (confirmed identical in the raw page
payload). Each simple `<token>` placeholder is parsed as an **empty
custom HTML element**, so the browser renders nothing for it and the
placeholder text disappears from the page.

### What readers see today (before this PR)

| Page (live) | Source Markdown | Rendered on the live site |
|-------------|-----------------|---------------------------|
| [`cli/server`](https://coder.com/docs/reference/cli/server) — OAuth2
GitHub Allowed Teams | `Structured as: <organization-name>/<team-slug>.`
| `Structured as: /.` |
|
[`cli/tokens_create`](https://coder.com/docs/reference/cli/tokens_create)
— `--allow` | `Repeatable allow-list entry (<type>:<uuid>, e.g.
workspace:1234-...).` | `Repeatable allow-list entry (:, e.g.
workspace:1234-...).` |
| [`api/tasks`](https://coder.com/docs/reference/api/tasks) — `q` | `...
status:<status>` | `... status:` (nothing after the colon) |
| [`api/schemas`](https://coder.com/docs/reference/api/schemas) —
AIBridgeConfig (`anthropic`/`bedrock`/`openai`) |
`CODER_AI_GATEWAY_PROVIDER_<N>_*` | `CODER_AI_GATEWAY_PROVIDER__*` |
| [`api/schemas`](https://coder.com/docs/reference/api/schemas) —
AIBridgeConfig (`providers`) | `CODER_AI_GATEWAY_PROVIDER_<N>_<KEY>` |
`CODER_AI_GATEWAY_PROVIDER__` |

[`api/chats`](https://coder.com/docs/reference/api/chats) (`q`) drops
five tokens the same way — `title:<substring>`, `diff_url:<url>`,
`pr:<number>`, `pr_title:<text>`, and the trailing `title:<value>`. The
live parameter description reads (note the dangling `title:`,
`diff_url:`, `pr:`, `pr_title:`):

```text
Search query. Supports title: (case-insensitive, quote multi-word values), archived:bool, has_unread:bool, pr_status:<draft|open|merged|closed> as repeated or comma-separated values, source:<created_by_me|shared_with_me>, diff_url: (quote values containing colons), pr: (exact PR number match), repo:<owner/repo> (case-insensitive substring match against git remote origin or URL), pr_title: (case-insensitive PR title substring). Bare terms are not supported; use title: for title filtering.
```

<details>
<summary>Raw rendered DOM from the live site (headless Chrome,
post-hydration)</summary>

```html
<!-- reference/cli/server -->
Structured as: <organization-name>/<team-slug>.</team-slug></organization-name>

<!-- reference/cli/tokens_create -->
Repeatable allow-list entry (<type>:<uuid>, e.g. workspace:1234-...).</uuid></type>

<!-- reference/api/tasks : only status:<status> drops; the /-containing tokens are escaped and survive -->
Search query for filtering tasks. Supports: owner:&lt;username/uuid/me&gt;, organization:&lt;org-name/uuid&gt;, status:<status></status>

<!-- reference/api/schemas : anthropic / bedrock / openai rows -->
Deprecated: Use Providers with indexed CODER_AI_GATEWAY_PROVIDER_<n>_* env vars instead.</n>

<!-- reference/api/schemas : providers row -->
Providers holds provider instances populated from CODER_AI_GATEWAY_PROVIDER_<n>_<key> env vars and/or the deprecated LegacyOpenAI/LegacyAnthropic/LegacyBedrock fields above.</key></n>
```

The parser auto-inserts closing tags
(`</team-slug></organization-name>`) and lowercases the tag name (`<N>`
becomes `<n>`), leaving `__` where `<N>_` used to be. Every wrapped
placeholder renders correctly as inline code on the [docs preview for
this
branch](https://coder.com/docs/@vigilante%2Fdocs-551-backtick-placeholder-syntax-in-generated-reference-docs-cli/reference/cli/server).

</details>

### Accuracy note — cases that do *not* drop on live

These render fine today, so they are **not** evidence of dropping (the
PR still wraps them for consistency / MDX-safety):

-
[`api/organizations`](https://coder.com/docs/reference/api/organizations)
and
[`api/provisioning`](https://coder.com/docs/reference/api/provisioning):
`{'tag1':'value1','tag2':'value2'}` renders verbatim — curly braces are
not an HTML tag.
- Tokens containing `/` or `|` are escaped by the renderer and stay
visible (as literal `<...>`): `<username/uuid/me>`, `<org-name/uuid>`,
`<owner/repo>`, `<draft|open|merged|closed>`,
`<created_by_me|shared_with_me>`. Backticks still improve their
readability, but they were never dropped.
2026-07-14 13:39:58 -04:00
Paweł Banaszewski 3126306598 feat: add --aigateway-proxy-target flag (#27122)
Adds `--aigateway-proxy-target` option to
`deploymentGroupAIGatewayProxy` that defines URL to which intercepted
requests should be forwarded to.
Forward URL used to be hardcoded to `coderAPI.AccessURL` pointing to
embedded Gateway. With addition of standalone AI Gateway this needs to
be configurable.

Renamed `aibridgeproxyd.Server.coderAccessURL` and `coderAccessPort` ->
`gatewayURL` and `gatewayPort` + option to better reflect reality.
2026-07-14 16:40:22 +00:00
Michael Suchacz a567f6a89f feat: allow admins to override the chat compaction model (#27151) 2026-07-14 16:57:04 +02:00
Jake Howell bf57da58e7 chore(site): replace CircularProgress with Spinner component (#24276) 2026-07-15 00:26:43 +10:00
Jake Howell 57852112a6 chore: unify admin settings menu items (#27209)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell.

## Problem

#27191 fixed the mobile menu missing the **AI** / **AI sessions** items,
but did so by duplicating the item list. The desktop
`DeploymentDropdown` and mobile `MobileMenu` each hardcode the same
Admin settings links and permission gates. That duplication is exactly
why the two drifted out of sync in the first place, and it will happen
again the next time an item is added.

## Fix

Extract a single source of truth in `adminSettings.ts`:

- `AdminSettingsPermissions` type shared by both surfaces.
- `getAdminSettingsItems(permissions)` builds the ordered item list
using conditional spreads, e.g.

  ```ts
  ...(canViewAISettings ? [{ label: "AI", to: "/ai/settings" }] : []),
  ```

- `canViewAdminSettings(permissions)` for the desktop visibility gate.

`DeploymentDropdown` and `MobileMenu` now just `.map()` over the shared
list, so adding or changing an item is a one-line edit in one place.

No backend, permission, routing, or user-visible behavior changes. Item
labels, links, and order match the current desktop dropdown (mobile now
inherits the same `linkToAuditing` constant instead of a hardcoded
`/audit`, same value).

<details>
<summary>Rationale / approach</summary>

Following Larry Wall's virtues: laziness (one list to maintain, not
two), impatience (kill the class of bug where the two menus silently
diverge), and hubris (leave a shared module nobody has to apologize
for).

Kept `canViewOrganizations` in the permission type and visibility gate
even though Organizations always renders, preserving prior behavior
rather than changing it as part of a refactor.

Validated with `biome check` and `tsc --noEmit`; existing
`MobileMenu.stories.tsx` args already cover the Admin / Auditor /
OrgAdmin / Member permission matrices.

</details>
2026-07-14 23:33:56 +10:00
Jake Howell bff7ec7624 refactor(site): de-emotion the DERP health page (#27208)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell.

## What

Removes the last `@emotion/react` usage from the DERP health page
(`site/src/pages/HealthPage/DERPPage.tsx`).

- Drops `useTheme` from `@emotion/react`; the page no longer reads the
Emotion theme.
- Replaces the region pin's `style={{ color: healthyColor(theme,
severity) }}` with a Tailwind class derived from severity, matching the
existing pattern in sibling components (`HealthIcon`, `HealthyDot`,
`StatusIcon` in `Content.tsx`).
- Deletes `healthyColor.ts`, which was only consumed by this page and
itself depended on `@emotion/react`.

## Why

The page was already almost entirely Tailwind-based; the theme lookup
was the only Emotion holdout. Aligning it with the surrounding
components keeps the severity colours consistent and removes dead code.

<details>
<summary>Notes</summary>

Severity → class mapping mirrors `Content.tsx`:

| Severity | Class |
| --- | --- |
| `ok` | `text-content-success` |
| `warning` | `text-content-warning` |
| `error` | `text-content-destructive` |

Note: the old helper used `theme.roles.*.fill.solid` tokens, whereas the
surrounding components use the `content-*` tokens — these can differ
slightly in shade. I opted for consistency with the neighbouring health
components. Happy to swap to a dedicated `fill`-equivalent token if
you'd prefer an exact colour match.

</details>
2026-07-14 23:29:22 +10:00
Jake Howell 3060a40285 refactor(site/src/pages/UserSettingsPage/TokensPage): de-MUI TokensPageView (#27212)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell.

Removes the remaining MUI/Emotion dependency from `TokensPageView.tsx`.

## Changes

- Removed `useTheme` from `@emotion/react` and the `const theme =
useTheme()` call.
- Replaced all `style={{ color: theme.palette.text.secondary }}` inline
styles with the `text-content-secondary` Tailwind token, matching
sibling components (`Table.tsx`, other UserSettings pages).
- Preserved `data-pixel="ignore"` and all other attributes/behavior.

## Validation

- `tsc --noEmit`: no errors for the file.
- `biome check`: clean.
2026-07-14 23:27:08 +10:00
Jeremy Ruppel f2181572cc fix(site): support browser back and forward in template builder wizard (#27104)
Browser back/forward controls did not work in the template builder
wizard. Using browser navigation sent the user out of the wizard
entirely instead of moving between steps.

The wizard's current step is now driven by a `?step=` search param. Step
transitions push history entries so browser back/forward walks the
steps. Steps that are invalid, skipped, or unreachable given the wizard
state are clamped and the URL is rewritten with a replace, keeping URL
and state in sync in both directions.

`?base=` is accepted as the only entry search param and deep-links to a
preselected base template (superseding #26808). The page container
resolves it against the available bases, holds the wizard behind a
loader until it is consumed and removed from the URL, then mounts the
wizard starting on the first step after base selection.

Closes https://linear.app/codercom/issue/DEVEX-594

> Generated with [Coder](https://coder.com) by @jeremyruppel
2026-07-14 08:55:36 -04:00
Danielle Maywood 0f55c283f1 fix: use backend-selected chat agent for desktop, git, terminal (#26959) 2026-07-14 13:50:25 +01:00
Michael Suchacz 55b06f14a3 feat: allow overriding advisor reasoning effort (#27196) 2026-07-14 11:01:51 +02:00
Yevhenii Shcherbina 63ec93a7ce feat: add AWS Bedrock mantle endpoint to AI Gateway (#26745)
Implements
https://linear.app/codercom/issue/AIGOV-213/add-bedrock-provider

# AWS Bedrock mantle support in AI Gateway

## Summary

Add support for the AWS Bedrock **mantle** endpoint
(`bedrock-mantle.{region}.api.aws/anthropic/v1/messages`) to AI Gateway.
Mantle serves Claude through the native Anthropic Messages API. We model
it as a `protocol` field on the existing Bedrock provider settings
(`invoke-model` default, or `mantle`) rather than as a new provider
type, and we treat mantle as a pure passthrough: SigV4-sign and forward,
no body translation.

## Background

Claude on AWS Bedrock is reachable through two endpoints, each speaking
exactly one wire protocol:

1. **InvokeModel** (existing): `bedrock-runtime.{region}.amazonaws.com`.
Model id in the URL path, request translated into Bedrock's InvokeModel
format, responses returned as a binary AWS eventstream. This is what AI
Gateway already supported for Bedrock.
2. **Mantle** (this doc):
`bedrock-mantle.{region}.api.aws/anthropic/v1/messages`. Native
Anthropic Messages API: model in the body, plain SSE streaming.

## Why a `protocol` field, not a new provider type

The alternative is to model mantle as its own `ai_provider_type`
(`bedrock-mantle`) alongside `bedrock`. I chose the `protocol` field
instead for two reasons:

1. Mantle reads more like a protocol of Bedrock than a separate
provider. It is the same AWS account, credentials, region, and IAM,
reached over a different wire protocol and host. One Bedrock provider
with two protocols (`invoke-model` default and `mantle`) models that
more organically than two provider types.
2. It avoids a database migration. The `protocol` field lives in the
settings JSON blob (empty resolves to `invoke-model`, so existing
providers are unaffected), whereas a new type means an enum value and
the `ALTER TYPE ... ADD VALUE` migration that goes with it.

## Why passthrough, not translation

The client already emits Bedrock-legal requests in mantle mode:

```sh
export CLAUDE_CODE_USE_MANTLE=1
export CLAUDE_CODE_SKIP_MANTLE_AUTH=1
export ANTHROPIC_BEDROCK_MANTLE_BASE_URL=https://<coder>/api/v2/aibridge/<provider-name>
```

So the gateway just forwards the body and SigV4-signs it (service
`bedrock-mantle`), and skips all the InvokeModel body-translation (model
remap, thinking conversion, beta-flag allowlist, field stripping). This
keeps the mantle path thin and avoids a second copy of translation logic
to maintain.

## Consequences

- Protocol-dependent fields: `model` / `small_fast_model` are used by
InvokeModel but ignored by mantle (the client sends the model), and
`base_url` is required for mantle but optional for InvokeModel.
Validation is protocol-aware.
- No central model control on mantle: because it is a passthrough, the
operator cannot pin the model.
- `region` and the `base_url` host must name the same region (the SigV4
scope must match the endpoint); a mismatch surfaces as `Credential
should be scoped to a valid region`.

## Draft UI

<img width="1100" height="579" alt="image"
src="https://github.com/user-attachments/assets/37bab46d-8958-4a96-9f47-1fef3493e1b6"
/>

## Follow-up PRs:
- https://github.com/coder/coder/pull/27156
2026-07-13 19:44:36 -04:00
TJ 043d367cfe fix(site): show AI settings and AI Sessions in mobile admin menu (#27191)
## Problem

The desktop `DeploymentDropdown` surfaces **AI** and **AI sessions**
items under Admin settings (behind `canViewAISettings` /
`canViewAIBridge`), but the mobile `MobileMenu` was never updated to
match — its `AdminSettingsSub` only knows about Deployment,
Organizations, Audit logs, Connection logs, and Healthcheck.

This is a leftover from #25582 ("promote AI settings to a top-level
section"), which threaded `canViewAISettings` through `Navbar` /
`NavbarView` / `DeploymentDropdown` but did not touch `MobileMenu.tsx`.
`canViewAIBridge` has the same oversight.

## Fix

- Extend `MobileMenuPermissions` with `canViewAIBridge` and
`canViewAISettings`.
- Render **AI** (→ `/ai/settings`) and **AI Sessions** (→
`/ai-gateway/sessions`) in the mobile Admin settings collapsible, in the
same order as the desktop dropdown.
- Thread the two flags through `NavbarView` into `MobileMenu`.
- Cover the new args in `MobileMenu.stories.tsx` (Admin story now shows
the AI items; Auditor / OrgAdmin / Member keep them hidden).

No backend, permission, or routing changes.

> 🤖 This PR was drafted by Coder Agents on behalf of @tracyjohnsonux and
needs a human review.
2026-07-13 15:24:31 -07:00
Andrew Aquino 5334cc80b6 fix(site): pass all properties of a multi-select dynamic parameter option to MultiSelectCombobox defaultOptions (#27145)
fixes DEVEX-463

Previously, a dynamic parameter of `form_type = "multi-select"` with
default options selected would only pass in these 3 properties for each
option fed into `MultiSelectCombobox`'s `defaultOptions`:

- `value`
- `label`
- `disable` 

`defaultOptions` are used as the initial value of
`MultiSelectCombobox`'s `selected` array of `Option`s. If the `icon`
property is missing from a selected option, then no icon is shown:


https://github.com/coder/coder/blob/e59a67d63fd522d1e95b42e57d4fbfe7d2bc5fef/site/src/components/MultiSelectCombobox/MultiSelectCombobox.tsx#L501-L502

Now `icon` and `description` are included among those properties passed
to default selected options, when a default option's value can be found
among the parameter's available options in the Terraform template. This
fixes the bug where icons wouldn't display for default selected options.

If no corresponding option is found, then we fall back to the old
partial option object (`{ value, label, disable }`).

<img width="1840" height="1191" alt="Screenshot 2026-07-09 at 10 08
54 PM"
src="https://github.com/user-attachments/assets/91be4aaf-9016-46d6-871b-344c8f2504cb"
/>
2026-07-13 12:33:27 -07:00
Asher 15fd7b746a fix: use fake timers in edit workspace test (#27141)
Fixes an issue where the debounce delay plus edit delay exceeds the wait timeout.

Also remove the mocked rich parameters call; it is not used.
2026-07-13 10:30:41 -08:00
Michael Suchacz 6f6d7539c8 feat: remove unused chat statuses pending, paused, and completed (#27064)
The chatd state machine only recognizes `waiting`, `running`, `error`,
`requires_action`, and `interrupting`. Remove the unused `pending`,
`paused`, and `completed` values from the database enum, backend, SDK,
frontend, generated queries, and API docs.

Migration `000543_chat_status_remove_unused` remaps existing `pending`
rows to `running`, remaps `paused` and `completed` rows to `waiting`,
drops the obsolete `idx_chats_pending` index, and recreates
`chats_expanded` around the enum swap. It also removes the dead
`AcquireChats` query and all remaining query literals for the deleted
statuses.

**NOTE**: The enum swap can break chat queries from older replicas
during a mixed-version rollout because they still reference
`'pending'::chat_status`. Chats are experimental, so this PR accepts
that limited rollout window instead of adding a two-release expand and
contract sequence.

> This PR was authored by Mux (AI agent) on Mike's behalf.
2026-07-13 20:28:28 +02:00
Jake Howell e0b57f3154 chore: remove mui from <IconsPage /> (#27201)
This pull-request removes the MUI specific components from `<IconPage
/>`.
2026-07-13 18:12:00 +00:00
Jake Howell aee528e044 fix: remove @emotion/react from <LastSeen /> (#27199)
This removes the manual `@emotion/react` we had from the theme being
injected in `<LastSeen />`. This now is relying on Tailwind 🙂
2026-07-13 18:05:32 +00:00
Callum Styan ad29777cb2 feat: NATS mTLS pubsub implementation (#26902) 2026-07-13 11:00:02 -07:00
Jake Howell 010d96c3cd chore: remove useTheme from <OAuth2AppsSettingsPageView /> (#27198)
This wasn't used, removing 🙂
2026-07-13 17:41:39 +00:00
Ehab Younes d5e5b10ff1 feat(site): polish AI budget members table (#26805)
Finishing touches for the AI cost control group members table.

- Spend stays primary-colored until near the budget limit, via a new
  AIBudgetAmount component
- "AI budget period" label shows the current spend window in local
  time, next to the members tab
- Budget tooltip notes the reset date and the group's default limit
- "Budget type" renamed to "Budget group", with a badge for the
  governing group or override
- Distinguishes $0 budget ("None") from no budget ("Unlimited")
- Unattributed spend from another group shows a note instead of a dash
- "Manage AI budget" disabled only when another named group governs
- Replaces UserAISpend with generated UserAISpendStatus, fixing
  limit_source

Closes #26401
2026-07-13 17:33:40 +03:00