Commit Graph

13957 Commits

Author SHA1 Message Date
Michael Suchacz 99a83a2702 fix: clean Bedrock headers (#24718)
Bedrock chat provider requests can inherit Anthropic public API headers
from the process environment, which causes mixed Anthropic and Bedrock
auth headers on signed requests.

Update the Anthropic SDK fork so its Bedrock middleware strips
Anthropic-only headers before signing requests, and keep a chatprovider
regression test for the production request shape.

> Mux is acting on Mike's behalf.
2026-04-26 21:50:29 +02:00
dependabot[bot] e32581dc68 chore: bump postcss from 8.5.6 to 8.5.10 in /site (#24727)
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.6 to
8.5.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/releases">postcss's
releases</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code>&lt;/style&gt;</code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@​TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's
changelog</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code>&lt;/style&gt;</code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@​TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/postcss/postcss/commit/33b9790263dc1562a46ce45d9532bd63e95b7986"><code>33b9790</code></a>
Release 8.5.10 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/536c79e4b01e58a3a56b09c3c0cf2323f4b9a28b"><code>536c79e</code></a>
Escape &lt;/style&gt; in CSS output (<a
href="https://redirect.github.com/postcss/postcss/issues/2074">#2074</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/afa96b2a139ce625c4d27973313479c7c85f39d4"><code>afa96b2</code></a>
Update dependencies (<a
href="https://redirect.github.com/postcss/postcss/issues/2073">#2073</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/effe88bb87cabdc1876e02adbdd30f392f19f40d"><code>effe88b</code></a>
Typo (<a
href="https://redirect.github.com/postcss/postcss/issues/2072">#2072</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/3ee79a2c4a11e41d52db50b444eebe38299495ad"><code>3ee79a2</code></a>
Thread model (<a
href="https://redirect.github.com/postcss/postcss/issues/2071">#2071</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/2e0683daca4dc2919211b03774f6b2d137136c01"><code>2e0683d</code></a>
Create incident response docs (<a
href="https://redirect.github.com/postcss/postcss/issues/2070">#2070</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/fe88ac29c06b7b218be32994cdc6ca1525bdf2c9"><code>fe88ac2</code></a>
Release 8.5.9 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/c551632496b87ab3f1965bfda5dc386b6c71963e"><code>c551632</code></a>
Avoid RegExp when we can use simple JS</li>
<li><a
href="https://github.com/postcss/postcss/commit/89a6b744060eb8dee743351c785a9fbe37d4525a"><code>89a6b74</code></a>
Move SECURITY.txt for docs folder to keep GitHub page cleaner</li>
<li><a
href="https://github.com/postcss/postcss/commit/6ceb8a46af9f9de821faee98f861bdf84617347b"><code>6ceb8a4</code></a>
Create SECURITY.md</li>
<li>Additional commits viewable in <a
href="https://github.com/postcss/postcss/compare/8.5.6...8.5.10">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=postcss&package-manager=npm_and_yarn&previous-version=8.5.6&new-version=8.5.10)](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-04-26 19:41:35 +00:00
Michael Suchacz 62e9752acd fix: prevent malformed OpenAI Responses continuations (#24725)
> Worked on by Mux on Mike's behalf.

## Summary

- Disable OpenAI Responses `previous_response_id` chain mode when the
prior assistant response has unresolved local tool calls, so the next
request can include paired tool outputs instead of sending an incomplete
continuation.
- Update the fantasy pin to a Responses replay fix that preserves stored
reasoning references, only replays web search references when paired
with reasoning, and validates local function-call output pairing before
send.
- Add fake OpenAI Responses input validation for the two production 400
shapes and integration coverage for full-history reasoning plus web
search replay.
- Add sanitized diagnostics for the OpenAI Responses continuity errors.

## Tests

- `go test ./providers/openai -run
'TestResponsesToPrompt_(ReasoningWithStore|ReasoningWithWebSearchCombined|WebSearchRequiresReasoningReference|ReasoningWithFunctionCallCombined|WebSearchProviderExecutedToolResults)|TestPrepareParams_(SkipsProviderExecutedToolReferences|ValidatesFunctionCallOutputPairing)|TestValidateResponsesInput_WebSearchReferenceRequiresReasoning'
-count=1`
- `go test ./providers/openai -count=1`
- `GOWORK=off go test ./coderd/x/chatd/chattest -run
TestValidateResponsesAPIInput -count=1`
- `GOWORK=off go test ./coderd/x/chatd -run
'TestOpenAIResponses(NoStaleWebSearchReplay|FullReplayPairsReasoningAndWebSearch|ChainModeSkipsWhenLocalCallPending|ChainModeStillFiresForProviderExecutedOnly)$|TestResolveChainMode_'
-count=1`
- `GOWORK=off go test ./coderd/x/chatd/chatprompt -run
'TestInjectMissingToolResults_' -count=1`
- `GOWORK=off go test ./coderd/x/chatd/chaterror -run
TestClassify_OpenAIResponsesAPIDiagnostics -count=1`
- `GOWORK=off go test ./coderd/x/chatd/... -count=1`
- `git diff --check`
- `git commit` pre-commit hook
2026-04-26 21:23:06 +02:00
Michael Suchacz ed33e28b13 fix(coderd/x/chatd): wake after auto-promoting queued message (#24714)
`tryAutoPromoteQueuedMessage` in `processChat`'s deferred cleanup could
set a chat back to `pending` without waking the processor. The processor
only noticed on the next 10ms poll, so under load tests like
`TestAutoPromoteQueuedMessageFallsBackForInvalidQueuedModelConfigID`
could time out waiting for the second streaming request (#1500).

Call `p.signalWake()` after the promoted-message publishes when
`promotedMessage != nil`, matching the pattern used by `CreateChat`,
`SendMessage`, `EditMessage`, `PromoteQueued`, and `InterruptChat`. Make
the regression helper `testAutoPromoteQueuedMessageFallback`
deterministic by setting `PendingChatAcquireInterval = time.Hour` and
synchronizing on a `secondRunStarted` channel instead of polling
`requestCount`, so the test fails without the wake instead of relying on
the 10ms ticker.

Closes https://github.com/coder/internal/issues/1500

> Mux is acting on Mike's behalf.
2026-04-26 11:08:32 +02:00
Michael Suchacz aee85040f0 fix(site/src/pages/AgentsPage): persist chat draft attachments (#24709)
When switching between existing `/agents` chats, unsent file attachments
were kept only in React state and were lost when the chat page
remounted.

This adds chat-scoped draft attachment persistence for the compose
input, keeps edit-mode attachments isolated from compose drafts, warns
when a file cannot be saved to localStorage, and cleans up restored
draft payloads after upload or send.

> Mux is acting on Mike's behalf.
2026-04-26 03:29:09 +02:00
Jake Howell 056203f8fc fix: resolve outsideBox style for tabs (#24561)
> 🤖 This PR was modified by Coder Agents on behalf of Jake Howell.

Fixes the `outsideBox` variant styling for tabs and simplifies the kebab
overflow logic. The overflow calculation now accounts for `column-gap`
between tabs so the menu trigger appears at the correct breakpoint.

- Fix Tailwind hover selector syntax for `outsideBox` variant
(`[&_[data-slot=tabs-trigger]:hover]` instead of
`[&_[data-slot=tabs-trigger]]:hover`)
- Account for `column-gap` in `useKebabMenu` overflow calculation via a
new `getTabGap` helper
- Use content-box width (`getContentBoxWidth`) for the initial overflow
pass so it matches `ResizeObserver`'s `contentRect.width`
- Consolidate `calculateTabValues` into a single-pass loop, removing the
separate `findFirstTabIndex` function
- Drop `FC` wrapper in favor of inline prop destructuring across all tab
components
- Forward `ref` through `TabsList` so consumers can attach refs directly
- Add `useKebabMenu` unit tests covering both all-visible and overflow
scenarios
2026-04-25 11:32:04 +10:00
Michael Suchacz 0211448d09 fix(coderd): sanitize Anthropic provider tool history (#24706)
Anthropic can reject replayed chat histories when a provider-executed
tool call, such as `web_search`, is present without its matching
provider result block.

This sanitizes unpaired Anthropic provider-executed tool calls during
prompt reconstruction, before Anthropic requests, and before persistence
so existing poisoned histories can continue and new malformed turns are
not stored.

Resolves: CODAGT-259

> Mux is acting on Mike's behalf.
2026-04-24 23:57:30 +02:00
Jeremy Ruppel 780aa6ce94 feat(site): opt AI Gateway pages into React Compiler (#24713)
Adds AI Gateway pages to the list of React Compiler-compiled pages.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 17:24:50 -04:00
Jeremy Ruppel 02b123518c fix: honor parameter defaults in --use-parameter-defaults and SSH auto-start (#24591)
## Problem

The CLI does not honor `default` values on template parameters in two
ways:

1. **`--use-parameter-defaults` rejects empty-string defaults.** The
check `parameterValue != ""` means `default = ""` in Terraform falls
through to an interactive prompt. In CI this causes an EOF error.

2. **`--use-parameter-defaults` only exists on `coder create`.** The
`start`, `update`, and `restart` commands never wire it through. SSH
auto-start passes empty `workspaceParameterFlags{}`, so users SSH-ing
into a stopped workspace with new template parameters get stuck in an
interactive prompt they cannot complete.

## Fix

### 1. Fix empty-string default detection and expose flag on all
commands

Replace `parameterValue != ""` with a check based on `!tvp.Required`. A
parameter with `Required==false` always has a valid default in
Terraform, even if that default is `""`. Also respect CLI defaults
provided via `--parameter-default`.

Move `--use-parameter-defaults` from a standalone option on `create`
into the shared `workspaceParameterFlags` struct. This exposes the flag
(and `CODER_WORKSPACE_USE_PARAMETER_DEFAULTS`) on `start`, `update`, and
`restart` via `allOptions()`. Wire it through
`buildWorkspaceStartRequest` so the resolver receives it.

### 2. SSH auto-start always uses defaults

Set `useParameterDefaults: true` on both `startWorkspace` calls in the
SSH auto-start path (initial start and the forbidden/upgrade fallback).
SSH is non-interactive and should never prompt.

Fixes https://linear.app/codercom/issue/DEVEX-180
Fixes https://github.com/coder/coder/issues/22272

<details><summary>Implementation notes</summary>

### Scoping decisions

- **`--yes` does not imply `--use-parameter-defaults`**: Making `--yes`
auto-accept defaults exposes a validation gap in the dynamic parameter
path (client-side validation happens during prompting, and skipping
prompts bypasses it). This is deferred to a follow-up that also
addresses `codersdk.ValidateWorkspaceBuildParameter` integration in the
resolver. Tracked in PLAT-114.
- **Explicit overrides always win**: `--parameter`,
`--rich-parameter-file`, and `--preset` are resolved in stages 1-5 of
the resolver, before `resolveWithInput` runs. No change needed for
precedence.
- **`!tvp.Required` vs `parameterValue != ""`**: The `Required` field is
set by the Terraform provider based on whether a `default` is present.
This is the canonical signal for "has a default," not the string value
itself.

</details>

> Generated with [Coder Agents](https://coder.com/agents)
2026-04-24 17:09:17 -04:00
Jon Ayers 6ac25c9ece fix: reduce re-registration interval to 5s to prevent replica staleness flapping (#24597) 2026-04-24 15:56:22 -05:00
blinkagent[bot] a497d934db chore: bump coder/fantasy to include gpt-5.5 Responses API support (#24712)
Bumps the `charm.land/fantasy` replace directive to pick up
<https://github.com/coder/fantasy/pull/29>, which adds `gpt-5.5` and
`gpt-5.5-pro` to `responsesReasoningModelIDs`.

Without this, chatd's `useOpenAIResponsesOptions` returns false for
GPT-5.5, so it falls back to Chat Completions and never attaches
`ResponsesProviderOptions` (losing `store=true` + `previous_response_id`
chaining and other Responses-only features).

## Changes
- `go.mod`: `github.com/coder/fantasy
v0.0.0-20260416152503-959aa39579d2` →
`v0.0.0-20260424191546-5ab464a305f4`
- `go.sum`: updated hashes

Verified `go build ./coderd/x/chatd/...` passes locally.

Created on behalf of @ibetitsmike

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2026-04-24 19:35:26 +00:00
Asher d958d89b6f fix: do not clobber dynamic parameters (#24645)
Once a user has touched a field, it is better to leave it alone and display explicit validation errors over silently overwriting their inputs.  Same for auto-filled values (whether from query parameters or a previous build).
2026-04-24 11:26:04 -08:00
Thomas Kosiewski 88b62a3359 fix(site/src/pages/AgentsPage): add copy buttons to raw attempts (#24705) 2026-04-24 20:13:10 +02:00
Paweł Banaszewski b8906c84a1 fix: fixes aibridge integration tests failing on windows (#24665)
Fixes aibridge responses and apidump integration tests in windows CI
job.

example failing job before the fix:
https://github.com/coder/coder/actions/runs/24873191866/job/72823942378
2026-04-24 18:28:22 +02:00
Cian Johnston 0ccfd575d0 fix(coderd/database/migrations): rename duplicate migration 477 (#24707) 2026-04-24 14:49:11 +00:00
DevCats c488658fd2 feat: add alert with link to template agent skill on page after template creation (#24588)
This pull request adds a dismissible alert that appears after creating a
template with links to the agent skill and template docs.

Screenshot:

<img width="1566" height="640" alt="image"
src="https://github.com/user-attachments/assets/61d26dcd-45ab-4b1d-a4ee-5ae7ab7822af"
/>
2026-04-24 09:37:59 -05:00
Michael Suchacz c7cac9debe fix: persist per-turn model on chats and queued messages (#24688)
Previously, `chats.last_model_config_id` was not updated when a user
sent a mid-chat message with a different model, and queued messages did
not store their own per-turn model, so promotion ran against whatever
the chat row said at promote time. Chat watch events also did not merge
`last_model_config_id` into the site's root, child, and per-chat
caches, so sidebar labels stayed stale after direct sends and queued
promotions.

- Add nullable `chat_queued_messages.model_config_id`, backfilled from
  `chats.last_model_config_id`. Queued inserts round-trip the effective
  model id at enqueue time.
- In `coderd/x/chatd`, direct sends update `chats.last_model_config_id`
  inside the same transaction that inserts the admitted user message.
  Manual promotion and auto-promotion use the queued row's stored
  `model_config_id`, with a fallback to `chats.last_model_config_id`
for legacy NULL rows during rollout.
`PromoteQueuedOptions.ModelConfigID`
  is now ignored.
- On the site, extract `mergeWatchedChatSummary` and
  `mergeWatchedChatIntoCaches` in `site/src/api/queries/chats.ts` so
  status-change watch events merge `last_model_config_id` into the
  root infinite chat list, the parent-embedded child entry, and the
  per-chat `chatKey(chatId)` cache. `updated_at` guards against stale
  watch payloads clobbering newer cached state, while diff status
  events still merge their PR metadata because they are timestamped
  outside the chat row. Watch timestamps are compared as instants so
  variable fractional precision does not make fresh events look stale.
- Queued promotion validates stored model config IDs before admission.
  Invalid legacy queued IDs fall back to the chat's current model config
  instead of dropping the queued message during auto-promotion.
- Backend and frontend regression coverage added for admission, queue
  promotion (including FIFO across mixed models, legacy NULL fallback,
  and invalid queued model IDs), and chat watch cache merging.

> Mux is acting on Mike's behalf.
2026-04-24 15:36:08 +02:00
Cian Johnston a876287d36 feat: auto-archive inactive chats with audit trail (#24642)
Adds a background job in `dbpurge` that periodically archives chats
inactive beyond a configurable threshold. Each archived root chat gets a
background audit entry tagged `chat_auto_archive`. Disabled by default.

* New `AutoArchiveInactiveChats` SQL query with LATERAL last-activity
subquery and partial index on archive candidates
* `site_configs`-backed `auto_archive_days` setting with admin-only PUT,
any-authenticated-user GET
* Cascade archive via `root_chat_id`; pinned chats and active threads
exempt
* Root-only audit dispatch on detached context, matching manual archive
(`patchChat`) behavior
* 11 subtests covering disabled no-op, boundary, deleted messages, child
activity, pinned exemption, multi-owner, idempotency, and batch
pagination

PR #24643 adds per-owner digest notifications.
PR #24704 adds the requisite UI controls.

> 🤖
2026-04-24 14:18:28 +01:00
Danny Kopping 346b46228f feat(site): add Charm Crush client icon to AI Bridge UI (#24662)
*Disclaimer: implemented by a Coder Agent using Claude Opus 4.6*

Follow-up to https://github.com/coder/coder/pull/24630 which added
backend Charm Crush client detection.

## Summary

Adds a `"Charm Crush"` case to the `AIBridgeClientIcon` switch so the
client filter and request logs show an icon instead of the generic
question mark fallback.

Uses a 💘 emoji-based SVG as a placeholder, matching Crush's branding.
Replace with an official brand SVG when one becomes available from the
Charm team.

## Changes

- `site/static/icon/charm-crush.svg`: new emoji-based placeholder icon.
-
`site/src/pages/AIBridgePage/RequestLogsPage/icons/AIBridgeClientIcon.tsx`:
added `"Charm Crush"` case.
2026-04-24 14:54:03 +02:00
Danielle Maywood 3a9a60dff8 feat: add collapsible thinking blocks with configurable display mode (#24635) 2026-04-24 11:29:08 +00:00
Mathias Fredriksson ce125831d3 fix(Makefile): run storybook tests after Go tests in pre-push (#24703)
Rolldown's tokio workers stall when competing with Go compilation
and the production site build for CPU, causing Vite transform
requests to hang. Vitest browser mode has no import-phase timeout,
so a stalled browser import() blocks the run indefinitely.
2026-04-24 13:40:37 +03:00
Michael Suchacz 3d90546aae feat: add general subagent model override (#24610)
Adds a deployment-wide admin override for general delegated subagents.

## What changed
- store the general override in `site_configs` and expose it through the
shared `agent-model-override/{context}` API
- apply the general override when spawning delegated general subagents,
while preserving the existing Explore override behavior
- reuse a shared Agents settings form for the general and Explore
override sections

## Validation
- `make gen`
- `go test ./coderd -run 'TestChatModelOverrides'`
- `go test ./coderd/x/chatd -run
'TestSpawnAgent_(GeneralUsesConfiguredModelOverride|GeneralOverrideLogsAndFallsBackWhenCredentialsUnavailable|GeneralOverrideLogsAndFallsBackWhenProviderDisabled)'`
- `pnpm -C site lint:types`
- `pnpm -C site test:storybook --
AgentSettingsAgentsPageView.stories.tsx`
- `make lint`
- `make pre-commit`

> Mux is acting on Mike's behalf.
2026-04-24 12:37:20 +02:00
Danielle Maywood 4505278a9f refactor(site): replace custom scroll implementation with react-infinite-scroll-component (#24687) 2026-04-23 22:12:39 +01:00
Cian Johnston a02339c66a fix(coderd/x/chatd): prevent invalid tool results from poisoning chat history (#24663)
- **computeruse.go**: Decode base64 screenshot data before storing in
`ToolResponse.Data` (was casting base64 string to bytes without
decoding)
- **chatloop.go**: Re-encode `ToolResponse.Data` to base64 via
`base64.StdEncoding.EncodeToString` instead of `string()` cast
- **mcpclient.go**: UTF-8 validate all text from MCP responses in
`convertCallResult()` using `strings.ToValidUTF8`
- **chatprompt.go (persist)**: Defense-in-depth UTF-8 sanitization of
text and media Text fields before database storage
- **chatprompt.go (replay)**: Antivenom layer that validates base64 and
UTF-8 at read time, auto-healing already-poisoned chats without
requiring a migration
- `TestToolResultAntivenom`: 4 subtests covering poisoned text, poisoned
media, valid media round-trip, and media with invalid UTF-8 text
-  Adds `TestConvertCallResult_UTF8Sanitization`: 4 subtests covering invalid
UTF-8 in TextContent, EmbeddedResource, valid passthrough, and
multi-part
- Adds `TestComputerUseTool_Run_ScreenshotDataIsDecodedBinary`: Verifies no
double-encode in the computer-use path
- Updated existing computer-use tests for the new decoded-binary
contract

> 🤖
2026-04-23 19:58:38 +01:00
Cian Johnston c602a31856 fix(coderd): reject pinning child chats in patchChat handler (#24669)
The UI already prevents child (delegated/subagent) chats from being
pinned, but the `PATCH /api/experimental/chats/{chat}` endpoint did not
enforce this. A direct API call could pin a child chat.

- Add a `400 Bad Request` guard in `patchChat` when `pinOrder > 0` and
the chat has a `ParentChatID`
- Add `TestChatPinOrder/RejectsChildChat` test

> 🤖
2026-04-23 18:36:20 +01:00
Michael Suchacz dbcc654d28 feat: snapshot explore subagent tool entitlements (#24638)
Explore sub-agents previously could not use `web_search` or external MCP
tools. `runChat` hard-skipped both for Explore. Lifting those guards
naively would over-grant tools, because a child chat could outlive the
spawning turn's plan-mode filter.

This change persists the spawning parent turn's filtered external MCP
server IDs onto the child Explore chat, and simplifies the Explore
provider-tool filter in `runChat`:

- New `resolveExploreToolSnapshot` helper: computes the child's
inherited external MCP subset by running the parent's configs through
`filterExternalMCPConfigsForTurn` (plan-mode policy) and, if the parent
is itself an Explore child, further narrowing to the parent's own
persisted `MCPServerIDs`. The result is written to the child's
`MCPServerIDs` column at spawn time.
- The existing `mcp_server_ids` column is the sole durable snapshot. No
new chat column is added.
- `runChat` for Explore children: loads MCP tools from the persisted
snapshot, and keeps only `web_search` from provider-native tools (to
block computer-use and other write-style tools, since Explore is
read-only). Whether `web_search` is actually available is a per-model
decision, determined by the current model config, just like a main chat.
- Built-in Explore allowlist is unchanged. Workspace-local MCP remains
excluded for Explore.

Verification: `go build ./...`, `go test ./coderd/x/chatd/... -count=1`,
`make gen` (clean tree), `make lint/emdash`, `go vet`. Deep-review ran
12 reviewers on the feature and 5 on the clarity refactor; CAR reviewed
and approved; a subsequent scope reduction dropped a temporary
`allow_web_search` column in favor of per-model handling.

> Mux is acting on Mike's behalf.
2026-04-23 19:07:38 +02:00
Cian Johnston b5a625549e feat: migrate agents-access to org-scoped system role for proper chat RBAC (#24438)
The agents-access role previously granted chat permissions at user
scope, but chats are org-scoped objects. Rego skips user-level perms
when org_owner is set, making the grants invisible. Handler-level
band-aids used synthetic non-org-scoped objects as a workaround.

  - Migrates agents-access from users.rbac_roles (site-level) to
    organization_members.roles (org-scoped) via DB migration
  - Redefines agents-access as a predefined org-scoped builtin role
    alongside organization-admin, organization-auditor, etc., with
    Member permissions granting chat create/read/update
  - Excludes ResourceChat from OrgMemberPermissions so org membership
    alone no longer grants chat access
  - Fixes handler Authorize checks to use org-scoped objects with
semantically correct actions (ActionUpdate for message/tool operations)
  - Grants org admins the ability to assign agents-access

Closes #24250
Fixes CODAGT-174

Note: this does not update the "Usage" endpoints. Tracked by CODAGT-161.
> 🤖
2026-04-23 17:59:42 +01:00
Cian Johnston 7efccfa996 fix(site): fix OpensAdminSubPanelOnMobile story on mobile viewport (#24678)
`OpensAdminSubPanelOnMobile` story has been failing due to not finding a
role="link" with name "Settings".

Agent investigated and claimed the Settings icon gets hidden in mobile
view.
Suggested fix is to start the story directly at `/agents/settings`.

> Generated with [Coder Agents](https://coder.com/agents)
2026-04-23 16:41:31 +00:00
Hugo Dutka c56061a09d fix(site): focus agents terminal on tab switch (#24677)
Fixes
[CODAGT-221](https://linear.app/codercom/issue/CODAGT-221/terminal-selection-in-side-panel-does-not-focus-input).
Verified manually that the fix automatically focuses the terminal input
when the terminal tab is selected.
2026-04-23 18:36:46 +02:00
Mathias Fredriksson f8fe5d680b fix(coderd): reject API operations on archived chats (#24633)
Archived chats accept mutations (messages, edits, queued-message
promotions, tool-result submissions) via the API, causing them to
re-enter the processing pipeline. This violates the hard-stop
design intent from PR #23758.

Add archived checks at three layers:

- HTTP handlers (postChatMessages, patchChatMessage,
  promoteChatQueuedMessage, postChatToolResults): return 400
  after auth so callers get a clear error.
- Daemon functions (SendMessage, EditMessage, PromoteQueued,
  SubmitToolResults): return ErrChatArchived after row lock,
  guarding against future callers that bypass the handler.
- AcquireChats SQL: filter out archived chats so they are never
  acquired for processing.

Fixes CODAGT-245
2026-04-23 19:03:33 +03:00
Cian Johnston a13f7f18e5 fix(site): remove last-checked label from git diff panel (#24675)
Removes `LastCheckedLabel.tsx` component and all related plumbing.

Note: chromatic is failing on main, seems to be pre-existing.

> 🤖
2026-04-23 16:45:05 +01:00
TJ e56b409873 fix(site): use highlight-orange for warning badge text and border (#24674)
## Summary

Fixes the warning badge color in light mode by switching text and border
tokens from `content-warning`/`border-warning` to `highlight-orange`.

## What changed

The `warning` variant in `Badge` was the only colored badge variant not
using the `highlight-*` token pattern:

| Variant | Before | After |
|---|---|---|
| warning (text) | `text-content-warning` | `text-highlight-orange` |
| warning (border) | `border-border-warning` | `border-highlight-orange`
|

In light mode, `content-warning` (HSL 27 96% 61%) produced a washed-out
orange. `highlight-orange` (HSL 30 100% 32%) gives a darker, more
legible result that matches the screenshot in the issue.

> [!NOTE]
> This PR was authored by Coder Agents.
2026-04-23 08:41:59 -07:00
david-fraley 50dbb3d2cb feat(site/src/pages/AgentsPage/components): allow disengaging plan mode from Planning badge (#24651)
Adds an inline `X` button to the "Planning" indicator so users can
disengage plan mode directly from the chat input, without reopening the
`+` menu. Reuses the same pattern that already ships on the
attached-workspace and MCP-server badges.

- When `onPlanModeToggle` is provided and plan mode is on, the pill
renders a dismiss `X` next to the label; clicking it calls
`onPlanModeToggle(false)`.
- When no toggle handler is passed, no `X` renders (matches the other
badges).
- Extracts `BadgeDismissButton` inside `AgentChatInput.tsx` now that the
dismiss pattern lives in three places, collapsing ~24 lines of
duplicated markup.
- Storybook coverage: tightened `PlanningIndicator`, new
`DisablePlanModeFromBadge` (click fires `onPlanModeToggle(false)`), new
`PlanningIndicatorWithoutToggle` (no handler, no `X`).

### Demo

![Demo: open + menu, enable Plan first, click X on the Planning pill to
disengage](https://github.com/david-fraley/coder/raw/pr-24651-media/plan-mode-dismiss.gif)

<sub>Higher-quality
[MP4](https://github.com/david-fraley/coder/raw/pr-24651-media/plan-mode-dismiss.mp4)
also available.</sub>

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

### Red / Green / Refactor

1. **Red**: Extended `AgentChatInput.stories.tsx` to assert the `X`
button exists in the Planning pill, clicking it fires
`onPlanModeToggle(false)`, and no `X` renders when `onPlanModeToggle` is
absent. Two stories failed as expected.
2. **Green**: Added an inline `<button aria-label="Disable plan mode">`
with `XIcon` to the Planning pill, gated on `onPlanModeToggle`, reusing
the existing `handlePlanModeToggle` handler. All 35 stories pass.
3. **Refactor**: Rule-of-three met with three duplicated dismiss-button
sites (workspace, MCP, planning). Extracted `BadgeDismissButton` with
`onClick` + `ariaLabel` props and replaced all three copies. Stories
still pass.

### Design notes

- `aria-label` is `"Disable plan mode"` (mode toggle, not item removal)
rather than `"Remove planning"` which would be misleading.
- Planning pill stays outside the `badgeContainerRef` overflow container
by design so it never collapses into the `+N` popover.
- No changes to the `Plan first` menu item in the `+` popover or its
behavior.

</details>

---

_This PR was opened by a Coder agent on behalf of @david-fraley._

---------

Co-authored-by: Jaayden Halko <jaayden@coder.com>
2026-04-23 15:19:24 +01:00
david-fraley f96f7b992f fix: promote MCP server display name to a required form field (#24652)
A customer reported that on the `/agents` MCP server create form, the
Create button stays disabled even after filling in Slug and Server URL.
The form also requires a non-empty display name, but the display name
was rendered as a placeholder-style inline title, so it looked optional.

Addressing [Tracy's
feedback](https://github.com/coder/coder/pull/24652#issuecomment-4301473164),
this PR promotes the display name to a proper labeled form field,
matching Slug and Server URL.

## Changes

- Remove the inline editable title input and pencil icon from the
header.
- Header now shows a static server name (or `New MCP server` when
creating).
- Add a labeled `Display name` field as the first field in the form,
with the same required marker treatment used by Slug and Server URL.
- Update the `CreateServer` story to match (no longer asserts the
removed pencil icon).

## Screenshot

![MCP server create form with Display name as a proper labeled field
above
Slug](https://raw.githubusercontent.com/david-fraley/coder/pr-24652-screenshots/mcp-server-required-display-name.png)

Reported via Support for a Netflix user on the MCP server admin panel.

---

_Filed on behalf of the user by Coder Agents._

---------

Co-authored-by: Jaayden Halko <jaayden@coder.com>
2026-04-23 14:51:25 +01:00
Atif Ali 1e21b288b9 ci: add permissions section to backport.yaml (#24654) 2026-04-23 18:41:03 +05:00
Danny Kopping a8613b2209 chore: deprecate /api/v2/aibridge/interceptions endpoint (#24670)
*Disclaimer: implemented by a Coder Agent using Claude Opus 4.6*

Marks the `GET /api/v2/aibridge/interceptions` endpoint as deprecated in
favor of `/aibridge/sessions`, which provides richer session-level
aggregation including threads and agentic actions.

Changes:
- Add `@Deprecated` Swagger annotation to the endpoint handler
- Add deprecation notice to the
`codersdk.Client.AIBridgeListInterceptions` method
- Regenerated OpenAPI spec with `"deprecated": true` flag

The endpoint remains fully functional.

Fixes https://github.com/coder/internal/issues/1339
2026-04-23 15:33:40 +02:00
Jaayden Halko e17da2f648 fix(site): fix action bar hidden after null-returning assistant messages (#24566)
closes CODAGT-121

When an invisible assistant message (e.g. a `provider_executed`
tool-result with no text content) appeared between a visible assistant
message and the next user message, the visible assistant's action bar
was incorrectly hidden. The chain logic computed `isLastInChain` from
the raw `parsedMessages` array, which includes entries that
`ChatMessageItem` returns `null` for.

Extract a shared `isTimelineMessageVisible` helper that encodes the
three null-return conditions (`provider_executed` tool-result-only,
all-provider-executed parts, metadata-only) in one place. Use it both to
guard the early return in `ChatMessageItem` and to skip invisible
entries when computing `isLastInChain`, so chain boundaries are based on
the next *rendered* message.
2026-04-23 14:31:46 +01:00
Cian Johnston ca14aa37c4 fix: stabilize git tab during edit_files (#24648)
- feat(agent/agentgit): shorten fallback poll to 5s
- fix(site/AgentsPage): keep git tab visible after reverting to clean
- feat(site/AgentsPage): show last-checked time in git tab

> 🤖
2026-04-23 14:02:47 +01:00
Hugo Dutka 397c9fb76a fix(agent/x/agentdesktop): flaky TestPortableDesktop_StopRecording_WithThumbnail (#24671)
Fixes https://github.com/coder/internal/issues/1462
2026-04-23 14:54:05 +02:00
TJ 95386f526a fix(site): improve agents page mobile view (#24508)
closes DES-22030

## Summary

Mobile view cleanup for the agents page — all changes are behind the
`md:` breakpoint so desktop is unchanged.

**Dropdowns:** Full-width on mobile with dynamic positioning via a
`--mobile-dropdown-bottom` CSS custom property set by a `ResizeObserver`
on the chat input box. Three position variants: `-bottom` (above chat
input), `-top` (below header), `-top-below-header` (below sidebar
header). Viewport branching uses a new `isBelowMdViewport()` helper (`<
768px`) so 640–767 px landscape phones pick the mobile branch instead of
the desktop flyout.

**Layout:** On the main agents page, mobile ordering is header → chat
list → chat input using CSS `order` and `contents` on the content
wrapper. The chat input aligns to the bottom of available space. The
sidebar list uses a top/bottom fade mask on mobile to hint at scrollable
content.

**Header:** Settings, Analytics, sound, and notification icons
consolidated into a single meatball menu dropdown on mobile.
Sound/notification toggles use `e.preventDefault()` to keep the menu
open for state feedback. Chime and notification state is lifted into
`AgentCreatePage` and passed down, so the mobile meatball menu and the
desktop `ChimeButton`/`WebPushButton` stay in sync.

**Workspace pill:** Icon-only on mobile (`size-7` round button with
`StatusIcon`), full pill on desktop. Tooltip hidden on mobile to prevent
ghost tooltip after dropdown close.

**Plus menu:** Workspace picker replaces the flyout with an inline
sub-panel on mobile (back button + search list). Desktop flyout
unchanged. `modal={false}` prevents double-tap when switching between
dropdowns.

**Model selector:** Truncated via `shrink` + `min-w-0` on mobile
(flex-based, no fixed max-width), inline provider/context subtext per
item, tooltip hidden on mobile. Added `open` / `onOpenChange` /
`onTriggerTouchStart` props for external control.

**Consistency:** All back/close buttons normalized to `ArrowLeftIcon`.
Right panel, sidebar settings, header `mobileBack`, and workspace
sub-panel all match the chat top bar pattern.

**Misc polish:** Chat tree nodes use `select-none` +
`-webkit-touch-callout:none` on coarse pointers to suppress the
long-press selection/callout on mobile.

<details>
<summary>Files changed (18)</summary>

- `site/src/index.css` — mobile dropdown CSS with 3 position variants
- `site/src/utils/mobile.ts` — new `isBelowMdViewport()` helper
(`<768px`)
- `site/src/pages/AgentsPage/AgentChatPageView.tsx` — bottom padding
`pb-3`
- `site/src/pages/AgentsPage/AgentCreatePage.tsx` — lift chime + webpush
state; pass handlers to header and buttons
- `site/src/pages/AgentsPage/AgentsPageView.tsx` — `contents` wrapper +
sidebar `border-b`
- `site/src/pages/AgentsPage/components/AgentChatInput.tsx` —
`ResizeObserver` composer ref, `plusMenuView` state, inline workspace
picker, `modal={false}`, mobile branching via `isBelowMdViewport`, bg
- `site/src/pages/AgentsPage/components/AgentCreateForm.tsx` —
`order-last` + `items-end` on mobile
- `site/src/pages/AgentsPage/components/AgentPageHeader.tsx` — meatball
menu (controlled chime/webpush props), `ArrowLeftIcon`, `order-first`,
padding, desktop/mobile branching via `matchMedia`
- `site/src/pages/AgentsPage/components/AgentPageHeader.stories.tsx` —
new Storybook coverage + `play` assertions that toggle state stays in
sync across breakpoints
- `site/src/pages/AgentsPage/components/ChimeButton.tsx` — optional
controlled `enabled` / `onToggle` props
- `site/src/pages/AgentsPage/components/WebPushButton.tsx` — optional
controlled `webPush` / `onToggle` props
-
`site/src/pages/AgentsPage/components/ChatElements/CompactOrgSelector.tsx`
— full-width dropdown class
- `site/src/pages/AgentsPage/components/ChatElements/ModelSelector.tsx`
— truncation, inline subtext, tooltip hidden on mobile, new props
(`open`, `onOpenChange`, `onTriggerTouchStart`)
- `site/src/pages/AgentsPage/components/ChatTopBar.tsx` — full-width
dropdown class
- `site/src/pages/AgentsPage/components/ContextUsageIndicator.tsx` —
full-width dropdown class (mobile branch)
- `site/src/pages/AgentsPage/components/Sidebar/AgentsSidebar.tsx` —
`ArrowLeftIcon`, filter dropdown class, top/bottom fade mask on scroll
area, `select-none` on tree nodes
- `site/src/pages/AgentsPage/components/Sidebar/SidebarTabView.tsx` —
`ArrowLeftIcon`, padding, back button placement
- `site/src/pages/AgentsPage/components/WorkspacePill.tsx` — compact
icon trigger, tooltip hidden on mobile, full-width dropdown class

</details>

> 🤖 Generated by Coder Agents

---------

Co-authored-by: Jaayden Halko <jaayden@coder.com>
2026-04-23 13:41:44 +01:00
Jake Howell 537e35dd94 chore: de-css <UserSettingsPage /> children (#24647)
This is a cleanup for some leftover `css={}` props within our
`site/src/pages/UserSettingsPage/...` pages.
2026-04-23 22:19:34 +10:00
Cian Johnston 2e5c7d99c2 fix(coderd/x/chatd): fix flaky TestSpawnComputerUseAgentInheritsContext (#24666)
Fixes flaky `TestSpawnComputerUseAgentInheritsContext`.

- The test inserts an Anthropic provider directly into the DB after
`CreateChat` has already been called
- The server's background goroutine may have already cached the provider
list (OpenAI only) via `configCache.EnabledProviders()` with a 10s TTL
- The direct DB insert bypasses the pubsub event that production uses to
invalidate the cache
- `isAnthropicConfigured()` returns the stale cached result, making
`computer_use` appear unavailable
- Fix: call `server.configCache.InvalidateProviders()` after the insert,
mirroring what production does via pubsub

CI failure:
https://github.com/coder/coder/actions/runs/24829197096/job/72673070101?pr=24648

> 🤖
2026-04-23 13:18:18 +01:00
Danielle Maywood 6edb49dcfa fix(site): prevent sticky message cycling when submitting edited message (#24292) 2026-04-23 12:09:54 +01:00
Cian Johnston be011b210b fix(cli): fix flaky TestExpAgentsE2E/ExistingChatHistory (#24661)
- Remove racy sequential `expect("esc")` after `expect("direct open
seed")`
- Both strings appear in the same initial PTY render; their byte-stream
order depends on async title generation timing
- The seed text alone proves we are in the chat view; pressing esc +
expecting `enter: open` confirms list navigation

> 🤖
2026-04-23 11:25:24 +01:00
Cian Johnston d9e3e206cc fix(enterprise/coderd/x/chatd): deflake relay drain test for multiple timers (#24609)
Fixes https://github.com/coder/internal/issues/1474.

PR #24549 introduced a `quartz.NewMock` clock +
`Trap().NewTimer("drain")` to
remove the wall-clock race. However, the trap consumed only **one**
`NewTimer("drain")` call via `MustWait/MustRelease`.

The merge loop has two code paths that create drain timers with the same
tag:
- Relay result handler (`drainAndClose` path in `relayReadyCh` case):
when an async dial completes after `drainAndClose` was set.
- Status notification handler (`relayParts != nil` branch in
`statusNotifications` case): when `status!=running` arrives while an
active relay exists.

Depending on goroutine scheduling, one or both paths fire. When two
calls hit
the trap, the second blocks the merge loop in `matchCallLocked` (quartz
waits
for all traps to release). Since the test already moved past `MustWait`,
nobody
reads the second call from the trap channel, deadlocking the test.

- Replace the single `MustWait/MustRelease/Advance` with a goroutine
that
loops over `trapDrain.Wait`, releasing and advancing for every drain
timer.
- No production code changes.

> 🤖
2026-04-23 11:13:41 +01:00
Mathias Fredriksson 7e29a67b50 chore(dogfood): add CODER_AGENT_EXP_MCP_CONFIG_FILES env var (#24664)
Set CODER_AGENT_EXP_MCP_CONFIG_FILES to ~/.mcp.json,.mcp.json so the
Coder agent reads both the harness-managed global MCP config and any
project-local .mcp.json. The agent resolves .mcp.json relative to its
manifest Directory (~/coder), so without this env var, a ~/.mcp.json
written by a user harness would be invisible to the agent.

Multiple files are merged by Manager.Connect; first file wins on name
conflicts. Missing files are silently skipped.
2026-04-23 13:07:20 +03:00
Danny Kopping 135ab29aa8 docs: add v2.32 to release calendar (#24589)
*Disclaimer: implemented by a Coder Agent using Claude Opus 4.6*

The [release calendar](https://coder.com/docs/install/releases) was
missing a link and details for v2.32, which was released on April 14,
2026.

Changes:
- Add v2.32 as Mainline with changelog link and release date
- Add v2.33 as the next upcoming (Not Released) entry
- Update latest patch versions: v2.29.10, v2.30.7, v2.31.9
2026-04-23 10:42:31 +02:00
Jiachen Jiang fb26b39780 docs(docs/admin/infrastructure): add Governance Layer section to architecture page (#24587)
Adds a new "Governance Layer" section to the architecture page with
short descriptions of AI Gateway and Agent Firewall, linking to their
dedicated reference pages.

> Generated by Coder Agents

---------

Co-authored-by: Danny Kopping <danny@coder.com>
2026-04-23 08:41:00 +00:00
Jakub Domeracki 9f02fec3a9 ci(.github/workflows/contrib): skip community label for dependabot (#24660) 2026-04-23 10:25:46 +02:00
Cian Johnston f5ccf68e53 feat: add lima incus example (#24640)
Depends on https://github.com/coder/coder/pull/24616

Adds a sample Lima configuration for Coder+Incus.
2026-04-23 08:24:03 +01:00