Commit Graph
5121 Commits
Author SHA1 Message Date
Ethan 987d415be3 feat(site): show workspace quota failures in chats (#25020)
Create and start workspace tool cards now recognize `INSUFFICIENT_QUOTA`
results and use the server-provided quota failure title in the build-log
dropdown. The existing warning icon and tooltip remain, while the
assistant response remains the place for the detailed recovery guidance.

Adds Storybook coverage for quota-reached create and start workspace
results.

https://github.com/coder/coder/pull/24956 added the necessary backend
changes.
<img width="897" height="505" alt="image"
src="https://github.com/user-attachments/assets/6cab8798-393d-429f-a3c3-a8ed50402d42"
/>



Closes CODAGT-20
2026-05-08 13:25:53 +10:00
Jon Ayers 400374992c fix: add pnpm overrides for vulnerable transitive dependencies (#25064) 2026-05-07 15:11:32 -05:00
Danielle Maywood e7958713a9 feat: add code diff display mode preference (#25027) 2026-05-07 20:15:28 +01:00
Michael SuchaczandCoder Agents d32842f084 feat(site): cycle prompt history with up/down arrows (#25004)
Fixes
[CODAGT-319](https://linear.app/codercom/issue/CODAGT-319/support-prompt-history-cycling-with-up-arrow).

Pressing the up-arrow key in the agent chat composer now cycles through
prior user prompts in the chat (terminal/Discord/iTerm2 style).
Down-arrow steps forward, Escape exits cycling and restores the
in-progress draft. Cycling is non-destructive: the per-message hover
**Edit** button is still the destructive truncate-and-edit path.

Replaces the previous up-arrow shortcut that immediately entered
destructive history-edit mode (and which had a regression where the
composer rendered as "editing" with an empty input box).

## Behaviour

- **Up** when composer is empty: snapshot the (empty) draft and load the
most recent user prompt; subsequent **Up** presses load older prompts.
Clamp at oldest, no wrap.
- **Up** while non-empty and not yet cycling: pass through (caret
movement preserved).
- Once cycling, **Up / Down** are intercepted unconditionally because
the cycle text fully replaces editor contents. Exit explicitly via
Escape, by sending, or by typing.
- **Down** while cycling: load the next-newer prompt, or restore the
saved draft when past newest.
- **Escape** while cycling: exit cycle and restore the saved draft. This
also applies during streaming; the same keypress is stopped before it
reaches the interrupt handler, and a second Escape interrupts as before.
- **Typing / paste / drop / attach / send / `remountKey` change**: exit
cycle mode and clear the snapshot.
- Cycling is suppressed while `isEditingHistoryMessage`,
`editingQueuedMessageID !== null`, or the input is `disabled` /
`isLoading`.
- Empty `userPromptHistory` makes Up a no-op (no destructive fallback).

## Out of scope (filed as follow-ups if needed)

- Restoring file-reference chips / attachments on cycled messages — v1
cycles plain text only, matching the existing per-message destructive
Edit's `text` payload.
- `^N` / `^P` keybindings (per Cian's note in the Linear thread).
- Per-user "enable/disable history cycling" preference (per Rowan's
note).
- Cross-chat history; cycling is per-chat.

## Tests

New Storybook play functions in `AgentChatInput.stories.tsx`:

- `PromptHistoryCycling` — Up cycles older, clamps at oldest; Down
returns to newer / draft; Escape restores draft.
- `PromptHistoryCyclingExitsOnTyping` — typing exits cycle mode;
subsequent Up snapshots the fresh empty draft and Down restores it.
- `NoPromptHistoryUpArrowIsNoOp` — empty history → Up is a no-op.
- `PromptHistorySuppressedWhileEditingHistoryMessage` — cycling does not
engage while history-editing.
- `PromptHistorySuppressedWhileDisabled` — cycling does not engage while
disabled.
- `PromptHistorySuppressedWhileLoading` — cycling does not engage while
loading.

## Implementation notes

Also rewrites `useImperativeHandle` to delegate to `internalRef.current`
lazily on every call instead of capturing it eagerly at factory time.
The old code crashed when methods were called after a remount because
the captured ref was stale; the new wrapper sees the current Lexical
instance. Behavior changes from throw-on-null to silent no-op, which
matches every other consumer of `ChatMessageInputRef`.

Verified locally:

```
pnpm format
pnpm check
pnpm test:storybook src/pages/AgentsPage/components/AgentChatInput.stories.tsx         # 41 passed
pnpm lint
```

## Manual UAT

A 13-case manual UAT covering cycle entry/exit, clamping, draft
restoration, no-history no-op, suppression while editing a history
message, and the send-button enable state — all PASS. Spec lives at the
deleted artifact branch; happy to re-attach if reviewers want it.

<details>
<summary>Implementation plan and decision log</summary>

The complete plan that drove this PR, including design alternatives
considered and edge cases:

```md
# CODAGT-319 — Up-arrow prompt history cycling

## Goal
Pressing the up-arrow key in the agent chat composer should cycle through the
user's previously-sent prompts in the current chat, terminal/Discord/iTerm2
style. Down-arrow steps forward; Escape exits cycle mode and restores the
in-progress draft. Cycling is non-destructive — it only populates the
composer with text the user can choose to resend, edit, or discard.

## Today's behaviour (and the regression)
- `ChatMessageInput` is a Lexical-based plain-text editor used inside `AgentChatInput.tsx`.
- `AgentChatInput.tsx` already wires an `ArrowUp` handler. When the composer is empty and not already editing, it calls `onEditLastUserMessage`.
- `onEditLastUserMessage` puts the user into a destructive "edit history" mode that warns "Editing will delete all subsequent messages and restart the conversation here.".
- Danielle's regression report ("shows me as editing but the input box is empty") indicates the destructive flow has a bug in addition to being the wrong UX for the request. We're replacing that path on the up-arrow, not patching it. The destructive edit remains accessible via the per-message hover Edit button.

## Design

### Behaviour
- Up when composer is empty: snapshot the (empty) draft and load the most recent user prompt. Subsequent Up loads older prompts, clamping at oldest. No wrap.
- Up while non-empty and not yet cycling: pass through. Matches existing gating.
- Once cycling, Up/Down are intercepted unconditionally. Exit via Escape, send, or typing.
- Down while cycling: next-newer or restore draft past newest.
- Escape while cycling: restore draft. During streaming, stop propagation so the same keypress does not interrupt; a second Escape interrupts as before.
- Typing/paste/drop/attach/send: exit cycle.
- Suppressed while isEditingHistoryMessage, editingQueuedMessageID !== null, or disabled/isLoading.
- No history => Up is a no-op.

### State
Local to `AgentChatInput.tsx`:
- `cycleIndex: number | null` — null means not cycling. 0 = newest user prompt.
- `cycleSavedDraft: string | null` — text restored on dismiss.

No localStorage persistence — refresh is a clean exit signal and the chat already has history server-side.

### Wiring
- New prop `userPromptHistory: readonly string[]` on `AgentChatInput`, newest-first.
- Removed `onEditLastUserMessage` prop entirely (its single call-site is being replaced). Removed dead `onEditUserMessage` prop on `ChatPageInput` (no longer needed since the destructive last-message shortcut is gone; the destructive Edit button uses a separate prop chain through `ChatPageTimeline`).
- `ChatPageContent.tsx` derives `userPromptHistory` from existing message store, filtered to `role === "user"` with non-empty `getEditableUserMessagePayload(message).text.trim()`.

### Reset triggers
`cycleIndex` and `cycleSavedDraft` reset on:
1. New `remountKey` (chat change, edit start/cancel).
2. Successful send.
3. Paste, drop, file attach.
4. User typing (detected via `handleContentChange` by comparing the incoming content to `currentCycleValueRef`, the last value applied programmatically).

### Out of scope
- Chip/attachment cycling.
- ^N/^P (Cian's note).
- Per-user toggle (Rowan's note).
- Cross-chat history.
```

</details>

---
> [!NOTE]
> This PR was created on behalf of @ibetitsmike by Coder Agents.

---------

Co-authored-by: Coder Agents <noreply@coder.com>
2026-05-07 20:31:41 +02:00
dependabot[bot] 39789c5c3b chore: bump uuid from 11.1.1 to 14.0.0 in /site (#24653)
Bumps [uuid](https://github.com/uuidjs/uuid) from 11.1.1 to 14.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/uuidjs/uuid/releases">uuid's
releases</a>.</em></p>
<blockquote>
<h2>v14.0.0</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v13.0.0...v14.0.0">14.0.0</a>
(2026-04-19)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>expect <code>crypto</code> to be global everywhere (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>)</li>
<li>drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>) (<a
href="https://github.com/uuidjs/uuid/commit/dc4ddb87272ed2843faccd130bcc41d492688bd3">dc4ddb8</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>expect <code>crypto</code> to be global everywhere (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>) (<a
href="https://github.com/uuidjs/uuid/commit/f2c235f93059325fa43e1106e624b5291bb523c4">f2c235f</a>)</li>
<li>Use GITHUB_TOKEN for release-please and enable npm provenance (<a
href="https://redirect.github.com/uuidjs/uuid/issues/925">#925</a>) (<a
href="https://github.com/uuidjs/uuid/commit/ffa31383e8e4e1f0b4e22e504561272041b8738c">ffa3138</a>)</li>
</ul>
<h2>v13.0.2</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v13.0.1...v13.0.2">13.0.2</a>
(2026-05-04)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>rerelease to fix provenance. (<a
href="https://github.com/uuidjs/uuid/commit/49ccb35f78c0c4ce1409dd2f1d89f83caadba10b">49ccb35</a>)</li>
</ul>
<h2>v13.0.1</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v13.0.0...v13.0.1">13.0.1</a>
(2026-04-27)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>backport fix for GHSA-w5hq-g745-h8pq (<a
href="https://github.com/uuidjs/uuid/commit/9d27ddf7046ce496ef39569ff84d948eeff9cb2a">9d27ddf</a>)</li>
</ul>
<h2>v13.0.0</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v12.0.0...v13.0.0">13.0.0</a>
(2025-09-08)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>) (<a
href="https://github.com/uuidjs/uuid/commit/bce9d72a3ae5b9a3dcd8eb21ef6d1820288a427a">bce9d72</a>)</li>
</ul>
<h2>v12.0.1</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v12.0.0...v12.0.1">12.0.1</a>
(2026-04-29)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md">uuid's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v13.0.0...v14.0.0">14.0.0</a>
(2026-04-19)</h2>
<h3>Security</h3>
<ul>
<li>Fixes <a
href="https://github.com/uuidjs/uuid/security/advisories/GHSA-w5hq-g745-h8pq">GHSA-w5hq-g745-h8pq</a>:
<code>v3()</code>, <code>v5()</code>, and <code>v6()</code> did not
validate that writes would remain within the bounds of a caller-supplied
buffer, allowing out-of-bounds writes when an invalid
<code>offset</code> was provided. A <code>RangeError</code> is now
thrown if <code>offset &lt; 0</code> or <code>offset + 16 &gt;
buf.length</code>.</li>
</ul>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li><code>crypto</code> is now expected to be globally defined (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>)</li>
<li>drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>)</li>
<li>upgrade minimum supported TypeScript version to 5.4.3, in keeping
with the project's policy of supporting TypeScript versions released
within the last two years</li>
</ul>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v12.0.0...v13.0.0">13.0.0</a>
(2025-09-08)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>) (<a
href="https://github.com/uuidjs/uuid/commit/bce9d72a3ae5b9a3dcd8eb21ef6d1820288a427a">bce9d72</a>)</li>
</ul>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v11.1.0...v12.0.0">12.0.0</a>
(2025-09-05)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>update to typescript@5.2 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/887">#887</a>)</li>
<li>remove CommonJS support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/886">#886</a>)</li>
<li>drop node@16 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/883">#883</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>add node@24 to ci matrix (<a
href="https://redirect.github.com/uuidjs/uuid/issues/879">#879</a>) (<a
href="https://github.com/uuidjs/uuid/commit/42b6178aa21a593257f0a72abacd220f0b7b8a92">42b6178</a>)</li>
<li>drop node@16 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/883">#883</a>) (<a
href="https://github.com/uuidjs/uuid/commit/0f38cf10366ab074f9328ae2021eea04d5f2e530">0f38cf1</a>)</li>
<li>remove CommonJS support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/886">#886</a>) (<a
href="https://github.com/uuidjs/uuid/commit/ae786e27265f50bcf7cead196c29f1869297c42f">ae786e2</a>)</li>
<li>update to typescript@5.2 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/887">#887</a>) (<a
href="https://github.com/uuidjs/uuid/commit/c7ee40598ed78584d81ab78dffded9fe5ff20b01">c7ee405</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>improve v4() performance (<a
href="https://redirect.github.com/uuidjs/uuid/issues/894">#894</a>) (<a
href="https://github.com/uuidjs/uuid/commit/5fd974c12718c8848035650b69b8948f12ace197">5fd974c</a>)</li>
<li>restore node: prefix (<a
href="https://redirect.github.com/uuidjs/uuid/issues/889">#889</a>) (<a
href="https://github.com/uuidjs/uuid/commit/e1f42a354593093ba0479f0b4047dae82d28c507">e1f42a3</a>)</li>
</ul>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v11.0.5...v11.1.0">11.1.0</a>
(2025-02-19)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/uuidjs/uuid/commit/7c1ea087a8149b57380fc8bb7f68c3a215cb6e4b"><code>7c1ea08</code></a>
chore(main): release 14.0.0 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/926">#926</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/3d2c5b0342f0fcb52a5ac681c3d47c13e7444b34"><code>3d2c5b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/f2c235f93059325fa43e1106e624b5291bb523c4"><code>f2c235f</code></a>
fix!: expect <code>crypto</code> to be global everywhere (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/529ef0899f5dd503d2ee90d690585d63d78bc212"><code>529ef08</code></a>
chore: upgrade TypeScript and fixup types (<a
href="https://redirect.github.com/uuidjs/uuid/issues/927">#927</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/086fd7976f11433edf9ac80be876b3ad243fe087"><code>086fd79</code></a>
chore: update dependencies (<a
href="https://redirect.github.com/uuidjs/uuid/issues/933">#933</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/dc4ddb87272ed2843faccd130bcc41d492688bd3"><code>dc4ddb8</code></a>
feat!: drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/0f1f9c9c9cedbae5a1d363d5406c5dfbabe81404"><code>0f1f9c9</code></a>
chore: switch to Biome for parsing and linting (<a
href="https://redirect.github.com/uuidjs/uuid/issues/932">#932</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/e2879e64bf125add903c1eff6e0860542c605013"><code>e2879e6</code></a>
chore: use maintained version of npm-run-all (<a
href="https://redirect.github.com/uuidjs/uuid/issues/930">#930</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/ffa31383e8e4e1f0b4e22e504561272041b8738c"><code>ffa3138</code></a>
fix: Use GITHUB_TOKEN for release-please and enable npm provenance (<a
href="https://redirect.github.com/uuidjs/uuid/issues/925">#925</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/0423d49df2dc8efc300c804731d25f4d7e0fccc4"><code>0423d49</code></a>
docs: remove obsolete v1 option notes (<a
href="https://redirect.github.com/uuidjs/uuid/issues/915">#915</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/uuidjs/uuid/compare/v11.1.1...v14.0.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 17:41:46 +00:00
Jon Ayers be5753dd63 chore: pin overrides in site/package.json (#25052) 2026-05-07 12:31:33 -05:00
Kayla はな 9fd2cc78fe refactor(site): migrate more styles from emotion to tailwind (#24914) 2026-05-07 11:09:25 -06:00
dependabot[bot] 6d633a0283 chore: bump react-router from 7.9.6 to 7.12.0 in /site (#25048)
Bumps
[react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router)
from 7.9.6 to 7.12.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/releases">react-router's
releases</a>.</em></p>
<blockquote>
<h2>v7.12.0</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7120">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7120</a></p>
<h2>v7.11.0</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7110">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7110</a></p>
<h2>v7.10.1</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7101">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7101</a></p>
<h2>v7.10.0</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7100">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7100</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md">react-router's
changelog</a>.</em></p>
<blockquote>
<h2>7.12.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>Add additional layer of CSRF protection by rejecting submissions to
UI routes from external origins. If you need to permit access to
specific external origins, you can specify them in the
<code>react-router.config.ts</code> config
<code>allowedActionOrigins</code> field. (<a
href="https://redirect.github.com/remix-run/react-router/pull/14708">#14708</a>)</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>
<p>Fix <code>generatePath</code> when used with suffixed params (i.e.,
&quot;/books/:id.json&quot;) (<a
href="https://redirect.github.com/remix-run/react-router/pull/14269">#14269</a>)</p>
</li>
<li>
<p>Export <code>UNSAFE_createMemoryHistory</code> and
<code>UNSAFE_createHashHistory</code> alongside
<code>UNSAFE_createBrowserHistory</code> for consistency. These are not
intended to be used for new apps but intended to help apps usiong
<code>unstable_HistoryRouter</code> migrate from v6-&gt;v7 so they can
adopt the newer APIs. (<a
href="https://redirect.github.com/remix-run/react-router/pull/14663">#14663</a>)</p>
</li>
<li>
<p>Escape HTML in scroll restoration keys (<a
href="https://redirect.github.com/remix-run/react-router/pull/14705">#14705</a>)</p>
</li>
<li>
<p>Validate redirect locations (<a
href="https://redirect.github.com/remix-run/react-router/pull/14706">#14706</a>)</p>
</li>
<li>
<p>[UNSTABLE] Pass <code>&lt;Scripts nonce&gt;</code> value through to
the underlying <code>importmap</code> <code>script</code> tag when using
<code>future.unstable_subResourceIntegrity</code> (<a
href="https://redirect.github.com/remix-run/react-router/pull/14675">#14675</a>)</p>
</li>
<li>
<p>[UNSTABLE] Add a new
<code>future.unstable_trailingSlashAwareDataRequests</code> flag to
provide consistent behavior of <code>request.pathname</code> inside
<code>middleware</code>, <code>loader</code>, and <code>action</code>
functions on document and data requests when a trailing slash is present
in the browser URL. (<a
href="https://redirect.github.com/remix-run/react-router/pull/14644">#14644</a>)</p>
<p>Currently, your HTTP and <code>request</code> pathnames would be as
follows for <code>/a/b/c</code> and <code>/a/b/c/</code></p>
<table>
<thead>
<tr>
<th>URL <code>/a/b/c</code></th>
<th><strong>HTTP pathname</strong></th>
<th><strong><code>request</code> pathname`</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Document</strong></td>
<td><code>/a/b/c</code></td>
<td><code>/a/b/c</code> ✅</td>
</tr>
<tr>
<td><strong>Data</strong></td>
<td><code>/a/b/c.data</code></td>
<td><code>/a/b/c</code> ✅</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>URL <code>/a/b/c/</code></th>
<th><strong>HTTP pathname</strong></th>
<th><strong><code>request</code> pathname`</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Document</strong></td>
<td><code>/a/b/c/</code></td>
<td><code>/a/b/c/</code> ✅</td>
</tr>
<tr>
<td><strong>Data</strong></td>
<td><code>/a/b/c.data</code></td>
<td><code>/a/b/c</code> ⚠️</td>
</tr>
</tbody>
</table>
<p>With this flag enabled, these pathnames will be made consistent
though a new <code>_.data</code> format for client-side
<code>.data</code> requests:</p>
<table>
<thead>
<tr>
<th>URL <code>/a/b/c</code></th>
<th><strong>HTTP pathname</strong></th>
<th><strong><code>request</code> pathname`</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Document</strong></td>
<td><code>/a/b/c</code></td>
<td><code>/a/b/c</code> ✅</td>
</tr>
<tr>
<td><strong>Data</strong></td>
<td><code>/a/b/c.data</code></td>
<td><code>/a/b/c</code> ✅</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>URL <code>/a/b/c/</code></th>
<th><strong>HTTP pathname</strong></th>
<th><strong><code>request</code> pathname`</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Document</strong></td>
<td><code>/a/b/c/</code></td>
<td><code>/a/b/c/</code> ✅</td>
</tr>
<tr>
<td><strong>Data</strong></td>
<td><code>/a/b/c/_.data</code> ⬅️</td>
<td><code>/a/b/c/</code> ✅</td>
</tr>
</tbody>
</table>
<p>This a bug fix but we are putting it behind an opt-in flag because it
has the potential to be a &quot;breaking bug fix&quot; if you are
relying on the URL format for any other application or caching
logic.</p>
<p>Enabling this flag also changes the format of client side
<code>.data</code> requests from <code>/_root.data</code> to
<code>/_.data</code> when navigating to <code>/</code> to align with the
new format. This does not impact the <code>request</code> pathname which
is still <code>/</code> in all cases.</p>
</li>
<li>
<p>Preserve <code>clientLoader.hydrate=true</code> when using
<code>&lt;HydratedRouter unstable_instrumentations&gt;</code> (<a
href="https://redirect.github.com/remix-run/react-router/pull/14674">#14674</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/remix-run/react-router/commit/26653a6bcbf8a9c5541f99dcfb526eafadf13434"><code>26653a6</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14712">#14712</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/7ac2346873b4bba26d16c88e5cd5c5cb81ce6bb3"><code>7ac2346</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14709">#14709</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/75b1ef50867d8fa3d5ffdab28245d5fec307d6a7"><code>75b1ef5</code></a>
Add origin checks for UI route submissions (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14708">#14708</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/c05ef936fd9334f82aafa7e9087b78a8bf5c745d"><code>c05ef93</code></a>
Validate redirect locations (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14706">#14706</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/c89c32c562a7723c45ee71dab1c892acaf7a608d"><code>c89c32c</code></a>
Escape HTML in scroll restoration keys (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14705">#14705</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/cbcbf3091b55ef0067724fbd744f31c6d85eb1e6"><code>cbcbf30</code></a>
fix: pass nonce to importmap script when using subResourceIntegrity (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14675">#14675</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/30f6c1d8142cbd2c26aef57cb2e12a4a8708eb4f"><code>30f6c1d</code></a>
fix(react-router): handle parameters with static suffixes in
generatePath (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/1">#1</a>...</li>
<li><a
href="https://github.com/remix-run/react-router/commit/7f140e098ecd83fd183468e0c0acae86589bfd11"><code>7f140e0</code></a>
Handle data requests with trailing slash consistently (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14644">#14644</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/1954af63742be277162f8d5d054ca07e04a4a401"><code>1954af6</code></a>
Preserve hydrate property on client loaders during instrumentation (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14674">#14674</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/5ce5cd4ebfc6959bf8d667075cb5b9ae0a9d5476"><code>5ce5cd4</code></a>
chore: format</li>
<li>Additional commits viewable in <a
href="https://github.com/remix-run/react-router/commits/react-router@7.12.0/packages/react-router">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react-router&package-manager=npm_and_yarn&previous-version=7.9.6&new-version=7.12.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-05-07 16:41:36 +00:00
Dean Sheather e1b1c7ec5b feat: resize chat image attachments client-side for provider budgets (#24533)
Anthropic rejects inline images over 5,242,880 bytes, but our upload
endpoint accepts images up to 10 MiB — so 5–10 MiB images were
reaching the provider and failing. This adds two layers of
protection: the browser resizes oversized images before upload, and
the server rejects any that still slip through before an upstream
request is issued.

Client-side resizing uses `createImageBitmap` with
`resizeWidth`/`resizeHeight` to clamp the decoded bitmap at decode
time, then iteratively shrinks on an `OffscreenCanvas` (falling back
to `HTMLCanvasElement`) until the output fits the applicable budget.
Anthropic (and Bedrock-hosted Claude — fantasy's bedrock provider is
a thin wrapper around the Anthropic client) uses a ~5 MiB budget;
other providers use a ~10 MiB budget to stay under the server cap.
Doing the resize in the browser avoids decoding attacker-controlled
image bytes in `coderd` (image-bomb DoS surface).

Server-side, `chatFileResolver` now takes a provider string and
looks up the inline-image cap via a new
`chatprovider.InlineImageByteCap`
helper; oversized `image/*` files for capped providers are rejected
with a pre-classified `chaterror` before the SDK call. The backstop
fires for older clients, direct API callers, or any image that was
committed to the composer before the user switched to a stricter
provider.

Attachments commit to composer state synchronously with a new
`"processing"` `UploadState` so paste+Enter can't dispatch before
the resize finishes; the `"uploading"` send gate now covers both
states. Dismissed-while-resizing attachments are tracked in a
`WeakSet` so a late swap can't resurrect a removed file.

Closes CODAGT-215
2026-05-08 02:07:33 +10:00
Thomas Kosiewski 273e828442 fix: remove advisor reasoning configuration (#25030) 2026-05-07 15:19:19 +02:00
Bartek Gatz 20453e123e fix(site): clamp lander position on landing to keep feet on pad (#25026) 2026-05-07 11:36:15 +01:00
Jaayden Halko 9ec2df9574 feat(site/src/pages/AgentsPage): resize agents sidebar (#24963)
Adds a persisted, draggable left sidebar width for the agents page. The
resize handle uses the same pointer-capture resize technique as the
existing right panel and clamps the expanded sidebar between 240px and
`min(520px, 50vw)`.

Updates the agents page skeleton to read the same stored sidebar width
and adds Storybook interaction coverage for resize clamping and
persistence.
2026-05-07 10:21:53 +01:00
Thomas Kosiewski 10a22a4753 fix(site/src/pages/AgentsPage): polish advisor UI (#25002)
Polishes the advisor tool card so the header uses a clearer lightbulb icon, inline pill metadata, wrapped/clamped question text, and a separate advice pill before the rendered response.

Adds Storybook coverage for a long advice plus 1.8k-character question peak state, including collapse/expand behavior.

Refs https://linear.app/codercom/issue/CODAGT-322/improve-advisor-icon-and-duplicate-loading-ui

<details>
<summary>Coder Agents disclosure</summary>

This PR was generated by Coder Agents.

</details>
2026-05-07 11:06:14 +02:00
Ethan ef0151601e feat: report insufficient quota build failures in chat tools (#24956)
## Summary

When a workspace build fails because the user is over their group quota,
the chat tools currently surface the failure as a bare `"workspace build
failed: insufficient quota"` string with no machine-readable error code
and no visibility into the user's current usage. Agents and the UI
cannot distinguish quota failures from any other Terraform error, so
users see an opaque message and have no clear path to recovery.

This PR tags quota failures with a typed error code at the source and
propagates it through the chat tool layer so callers can react to it
explicitly.

Relates to CODAGT-20

## Changes

**Provisioner runner**

- Add `InsufficientQuotaErrorCode = "INSUFFICIENT_QUOTA"` and set it
explicitly at the `commitQuota` failure site via a new
`failedWorkspaceBuildfCode` helper, so `provisioner_jobs.error_code` is
populated only on the genuine quota path. The substring matcher used for
externally produced sentinels (e.g. `"missing parameter"`, `"required
template variables"`) is intentionally not extended; provider errors
that happen to mention "insufficient quota" stay classified as generic
build failures.

**SDK and API contract**

- Add `JobErrorCodeInsufficientQuota` and a
`JobIsInsufficientQuotaErrorCode` helper to `codersdk`.
- Extend the swagger `enums` tag on `ProvisionerJob.ErrorCode` to
include `INSUFFICIENT_QUOTA`.
- Regenerate `coderd/apidoc`, `docs/reference/api/*`, and
`site/src/api/typesGenerated.ts`.

**chattool create_workspace / start_workspace**

- `waitForBuild` now returns a typed `*workspaceBuildError` carrying
both the message and the `JobErrorCode`, instead of a bare error string.
- New `quotaerror.go` introduces a structured `quotaErrorResult` (with
`error_code`, `title`, `message`, `build_id`, and optional `quota`) and
a best-effort `workspaceQuotaDetails` lookup that wraps owner
authorization internally and fetches `credits_consumed` and `budget`
from the database. Quota lookup failures (including authorization
failures) never block the failure payload.
- On quota-coded build failures, both `create_workspace` and
`start_workspace` now return the structured response (with the recovery
guidance inlined into `message`) instead of the bare `"insufficient
quota"` string. This applies to all three failure paths: post-creation,
an in-progress existing build, and a freshly triggered start build.
Non-quota build failures continue to use the existing
`buildToolResponse` / `newBuildError` path.
- Owner authorization is wrapped only on the call sites that need it
(the `CreateFn` and `StartFn` invocations and the quota-detail lookup),
so idempotent fast paths (already running, already in progress,
existing-workspace early returns) do not pay for an extra RBAC
round-trip or fail when role lookup is transient.

## Out of scope

- No changes to quota math, allowances, or bypass behavior.
- No automatic retries.
- No new quota-inspection tools and no changes to MCP
`coder_create_workspace` (which returns immediately and never observed
the build outcome here).
- No frontend UI changes; those will land in a follow-up PR that
consumes the new `INSUFFICIENT_QUOTA` code.
2026-05-07 15:01:58 +10:00
TJ 6737e2588e fix(site): reduce agents beta badge size from sm to xs (#25011)
Reduces the beta badge size in the Coder Agents UI from `sm` to `xs` for
better visual balance with the logo.

## Changes

- Added `xs` size variant to `FeatureStageBadge`, styled to match the
existing `Badge` component's `xs` variant (`text-2xs`, `h-[18px]`,
`border-0`, `rounded`)
- Updated both usages in `AgentPageHeader` (mobile) and `AgentsSidebar`
(desktop) from `size="sm"` to `size="xs"`
- Added `ExtraSmallBeta` Storybook story for the new size

> Generated by Coder Agents
2026-05-06 18:25:41 -07:00
Kayla はな 9d1315ffba refactor(site): align user settings layout with organization settings (#25016) 2026-05-06 17:29:01 -06:00
Jake Howell 8c2b1c7d69 chore: de-emotion style constant (#24835)
This pull-request looks at all (most) of our instances of `const styles
= { ... }` and attempts to smooth them down into the minimum viable
Tailwind equivalent 🙂
2026-05-07 09:21:24 +10:00
Kayla はな d19e5f86a7 fix(site): use ExternalImage on template insights (#25010) 2026-05-06 17:16:28 -06:00
Danielle Maywood 8ac4b9ab45 refactor: remove unnecessary typeof window checks (#24999) 2026-05-06 22:39:59 +01:00
Kayla はな f5ad6fb4cb fix(site): improve info icon styles in audit and connection log rows (#25009) 2026-05-06 13:27:31 -06:00
Kayla はな 4e1dccaabd refactor: remove ChooseOne component (#24983) 2026-05-06 12:08:51 -06:00
Bartek Gatz 894a1e0f7f feat(site): add Codernauts lunar lander game (#25001) 2026-05-06 17:50:46 +00:00
Danielle Maywood 92b1fc48b4 fix(site/src/pages/AgentsPage/components): right-align user chat bubbles (#25000) 2026-05-06 17:44:43 +01:00
dylanhuff-at-coder 6a200a49d3 feat: refresh dynamic parameters on secret changes (#24786)
Publishes user secret create, update, and delete events and subscribes
dynamic parameter websockets to authorized owner secret changes.

Secret changes trigger fresh renders with monotonic response IDs, with
backend tests covering subscription authorization and websocket refresh
behavior.
2026-05-06 09:27:24 -07:00
Mathias Fredriksson 6b0518d051 fix: state-aware queued message promotion (#24819)
PromoteQueued now branches on chat status: synth tool results before
the user message on requires_action, deferred reorder + Waiting on
running so the worker's persist+auto-promote keeps partial output.
Stale heartbeat falls through to the synchronous path; GetStaleChats
picks up Waiting+queue to recover post-cleanup-crash. Endpoint
returns 202.

Closes CODAGT-119
2026-05-06 19:11:56 +03:00
Michael Suchacz 0bfb9f6f13 feat: show agent turn summary in agents sidebar (#24942)
Persists the agent-generated turn-end summary on `chats` and shows it as
the Agents sidebar subtitle when present, falling back to the model
name. Errors still take precedence.

> Mux is acting on Mike's behalf.

## What changes

**Storage.** New nullable `last_turn_summary` column on `chats`
(migration `000486`). New `UpdateChatLastTurnSummary` query normalizes
blank/whitespace input to `NULL`, preserves `updated_at` (so the chat
does not jump to the top of the sidebar on summary writes), and uses an
`expected_updated_at` stale-write guard so an older async summary cannot
overwrite a newer turn.

**Backend.** `coderd/x/chatd/chatd.go` decouples summary generation from
webpush. Generated summaries persist for completed parent turns even
when webpush is unconfigured or has no subscriptions. The same generated
text is reused as the webpush body when webpush is configured, so the
summary model is not called twice. Generic fallback push text is no
longer persisted; it clears any stale summary instead.
Error/interrupt/pending-action terminal paths clear `last_turn_summary`
for the latest turn.

**Frontend.** `AgentsSidebar.tsx` subtitle priority is now `errorReason
|| lastTurnSummary || modelName`, normalized via the existing
`asNonEmptyString` helper from `blockUtils.ts`.

## Tests

- `TestUpdateChatLastTurnSummary` (database): success,
whitespace-to-NULL, stale guard rejects, `updated_at` preserved.
- `TestUpdateLastTurnSummaryRejectsStaleWrites` (chatd internal): direct
stale-`expected_updated_at` test.
- `TestSuccessfulChatPersistsTurnSummaryWithoutWebPush`: persistence
works without webpush subscriptions.
- `TestSuccessfulChatSendsWebPushWithSummary`: same generated text
drives both DB and push body.
-
`TestSuccessfulChatSendsWebPushFallbackWithoutSummaryForEmptyAssistantText`:
fallback text is not persisted.
- `TestErroredChatClearsLastTurnSummaryAndSendsWebPush`: error path
clears the field.
- `TestInterruptChatDoesNotSendWebPushNotification`: interrupt path
clears the field, no push fires.
- `AgentsSidebar.test.tsx`: subtitle priority for summary-present,
error-wins, no-summary fallback, whitespace fallback.
- `AgentsSidebar.stories.tsx`: `ChatWithTurnSummary` and
`ChatWithTurnSummaryAndError`.

## Notes

- No backfill. Existing chats keep showing the model name until their
next turn completes.
- Parent chats only in this iteration; the field is rendered on any
`Chat` if a future change extends generation to children.
- Decoupling generation from webpush adds quickgen model calls for
completed parent turns that previously skipped generation when no
subscriptions existed. Existing parent-only, assistant-text-present,
`PushSummaryModel` configured, and bounded-timeout gates keep this
behavior bounded.
2026-05-06 16:43:35 +02:00
Nick Vigilante 369a191972 feat: add Quickstart template with language and IDE selection (#24904)
Add a new Quickstart starter template that lets users pick programming
languages, editors, and an optional Git repo to clone. The template uses
Docker under the hood but presents a developer-focused experience: pick
your tools, start coding.

## What's included

- **Languages parameter** (multi-select): Python, Node.js, Go, Rust,
Java, C/C++
- **IDEs parameter** (multi-select): VS Code (Browser), VS Code Desktop,
Cursor, JetBrains, Zed, Windsurf
- **Git repo parameter**: Optional URL to clone on workspace start
- **JetBrains filtering**: Maps selected languages to relevant IDE codes
(Python → PyCharm, Go → GoLand, etc.)
- **Docker precondition check**: Uses `data "external"` +
`terraform_data` precondition to surface a friendly error when Docker is
unavailable, before the Docker provider fails with a cryptic message
- **4 presets**: Web Development, Backend (Go), Data Science, Full Stack
- **Single install script**: All languages install in one `coder_script`
to avoid apt-get lock conflicts (agent scripts run in parallel via
`errgroup`)

<details><summary>Design decisions</summary>

- **Docker as invisible backend**: Docker is required on the Coder
server but never mentioned in the user-facing parameter UI. The
experience is entirely "pick languages, pick editors, start coding."
- **`coder_script` over startup_script**: Language installs use a
templated script file (`install-languages.sh.tftpl`) driven by the
languages parameter. A single script avoids dpkg lock contention since
`coder_script` resources execute concurrently.
- **`data "external"` for Docker check**: The external provider probes
Docker availability independently of the Docker provider. If Docker is
down, the `terraform_data` precondition fails with a human-readable
message before any `docker_*` resource is evaluated. This depends on the
Docker provider connecting lazily (at resource eval time, not at
provider init), which current behavior confirms.
- **JetBrains filtering by language**: Rather than showing all 9
JetBrains IDEs, the template computes relevant IDE codes from the
language selection (e.g. Python → PY, Go → GO) and passes them as
`default` to the JetBrains module.
- **Arch-aware Go install**: The install script detects `uname -m` to
download the correct Go binary for amd64 or arm64.

</details>

<details><summary>Screenshots and recordings from the UI</summary>
<p>
<img width="1851" height="1471" alt="Screenshot 2026-05-05 at 2 14
20 PM"
src="https://github.com/user-attachments/assets/d4c9cdc5-d311-43a5-9e2e-f90b0019eda7"
/>
<img width="1851" height="1471" alt="Screenshot 2026-05-05 at 2 15
06 PM"
src="https://github.com/user-attachments/assets/cf3023fe-b6db-4503-a6c4-eaa0ec0659f8"
/>


https://github.com/user-attachments/assets/7507fd7d-ddb5-457a-9f7d-cbf89b36eb20


</p>
</details> 

> [!NOTE]
> This PR was authored by Coder Agents.
2026-05-06 13:55:38 +00:00
Ethan 46a60e6d5d refactor: move chat error kinds into codersdk (#24955)
Moves the chat error kind taxonomy from `coderd/x/chatd/chaterror` into
`codersdk.ChatErrorKind` and types `ChatError.Kind` /
`ChatStreamRetry.Kind` so generated TypeScript exposes an SDK-owned
union, including `usage_limit`. Backend chat classification now
references the SDK constants directly while preserving the existing JSON
string values.

Keeps chat usage-limit admission failures on their existing 409 response
shape. The frontend maps structured usage-limit responses to the
SDK-owned `usage_limit` kind, uses generated `TypesGen.ChatErrorKind`
directly, and removes the local string union and alias.
2026-05-06 11:57:48 +10:00
Jake Howell 859e5d3dda fix: remove last import of @mui/material/SvgIcon (#24916)
This pull-request finds the last place we make use of
`@mui/material/SvgIcon` and removes it 🙂 Therefore, another MUI import
we no longer need.
2026-05-06 11:50:52 +10:00
Michael Suchacz 2874d4b4cd feat: add chat debug retention purge (#24943)
> Mux is acting on Mike's behalf.

Adds configurable retention for chat debug data, including the purge
query, updated_at index, site config, experimental API, SDK types,
frontend lifecycle setting, and docs.

The purge deletes debug runs older than the configured retention window
and relies on existing cascades to delete steps. The default retention
is 30 days, and setting the value to 0 disables the purge.
2026-05-05 22:37:13 +02:00
Kayla はな 57a6421670 fix(site): ignore empty file path segments in template file tree (#24980) 2026-05-05 13:33:59 -06:00
Kayla はな 21a877df84 feat: update OrganizationMembersPage role editing to match new designs (#24858) 2026-05-05 13:18:01 -06:00
david-fraley e7360da974 docs: generate Chats API docs from swagger annotations (#24830) 2026-05-05 18:52:54 +00:00
Steven Masley 9b4666020b fix(site): show cross-org workspaces as disabled in chat picker (#24944)
All user workspaces now appear in the picker. Workspaces from a
different organization are rendered as disabled (greyed out, not
selectable) with a tooltip on hover: "Chat and workspace must be in the
same organization."
2026-05-05 09:07:54 -05:00
Danielle Maywood 5322755691 fix(site/src/pages/AgentsPage/components/ChatElements): align code block rendering (#24966) 2026-05-05 14:28:39 +01:00
Jaayden Halko dd2b121b20 feat(site/src/pages/AgentsPage): guide users when chat providers or models are missing (#24863)
<img width="674" height="508" alt="Screenshot 2026-05-04 at 20 43 11"
src="https://github.com/user-attachments/assets/de33dba9-33f5-4dbe-a1af-9bff5f048b8f"
/>


When the agents chat page loads with no chat providers or no chat models
configured, new users currently get no in-product guidance about the
missing setup step.

also adds a Add model button on the provider page after a provider is
setup

This adds a setup notice rendered as a no dismissable modalthat explains
both a provider and a model must be configured before agents can be
used. The notice conditionally links to `/agents/settings/providers`
and/or `/agents/settings/models` depending on which is missing, and only
renders after the relevant config queries succeed (no flash during
loading).
2026-05-05 14:08:35 +01:00
Jaayden Halko a24ebb9d38 fix: keep agents desktop layout at 200% zoom (#24699)
Fixes layout issues on the agents empty state page.

1. At 200% zoom on a 1440 px desktop, the CSS viewport shrinks to
   720 px, which was below the previous `md:` breakpoint (768 px) and
   collapsed the page into the mobile stack. Switching the page shell
   and shell-level controls to the `sm:` breakpoint (640 px) keeps the
   sidebar and chat area side-by-side at common zoom levels while
   preserving the mobile stack for real phone viewports.
2. The empty state stays bottom-aligned on mobile and centered on the
   desktop branch, with tighter spacing so the chat input sits closer to
   the bottom of the screen at 200% zoom.
3. The inner stack gap shrinks from `gap-4` (16 px) to `gap-2` (8 px)
   and the footer paragraph drops its `mt-1`, tightening the space
   around the organization selector, the chat input, and the
   "Introductory access to Coder Agents through September 2026" line.
4. Sidebar header/footer controls, the page header, the chat top bar,
   and the plan-mode badge now use the same `sm:` desktop breakpoint as
   the page shell. A collapsed sidebar can be expanded again at 640 to
   767 px.

Dropdown full-width CSS (`@media (max-width: 767px)`) and the
`isBelowMdViewport` helper are intentionally left at 768 px. Those
govern dropdown UX rather than page layout, and the chat pane is still
narrow at 640 to 767 px after the sidebar is visible. The page is in
desktop mode in that range while dropdowns stay full-width.

<img width="1460" height="858" alt="Screenshot 2026-04-30 at 23 03 48"
src="https://github.com/user-attachments/assets/62072432-6edf-4bf5-9a7f-88fd69f89602"
/>

<img width="1460" height="856" alt="Screenshot 2026-04-30 at 23 03 57"
src="https://github.com/user-attachments/assets/76d94673-ac45-4a50-9c6b-3cfeffa1d6c7"
/>

Regression coverage in Storybook:

- `AgentsPageView.stories.tsx > EmptyStateZoom200Desktop` pins a new
  720 px Chromatic viewport and asserts the rendered layout is
  horizontal, the sidebar is left of the main panel, and the sidebar
  header/footer controls are visible.
- `AgentsPageView.stories.tsx > CollapsedSidebarZoom200Desktop` pins
  the same 720 px viewport and asserts the expand-sidebar control is
  visible when the sidebar is collapsed.
- `AgentCreateForm.stories.tsx > OrgPickerTightSpacing` measures the
  vertical gap between the org selector row and the chat-input
  composer and expects it to stay below 16 px.

---

Generated by Coder Agents.
2026-05-05 14:08:21 +01:00
Ben Potter 63db689ab7 fix(site/src/pages/AgentsPage): cap queued messages list height so chat scroll keeps working (#24950)
Linear:
[CODAGT-313](https://linear.app/codercom/issue/CODAGT-313/unable-to-scroll-long-queued-messages-in-coder-agents)

## Summary

When many messages are queued in the agent chat, the chat history
becomes unscrollable: mouse wheel and scrollbar drag both stop
responding.

The input wrapper in `AgentChatPageView.tsx:496` is `shrink-0
overflow-y-auto` with **no `max-height`**, so `overflow-y-auto` is a
no-op and the section grows unbounded as `QueuedMessagesList` adds rows.
Its sibling `ChatScrollContainer` is `flex-1 min-h-0`, so it absorbs the
shrinkage and `clientHeight` collapses to 0. The chat list is then a
zero-height viewport with nothing to scroll.

Measured against the actual `AgentChatPageView` rendered in Storybook
with 20 queued messages (1280x800):

| | scroll-container `clientHeight` | input wrapper height | scrollable?
|
|---|---:|---:|---|
| 0 queued | 502 px | 270 px | yes |
| 20 queued, `main` | **0 px** | 1182 px | **no** |
| 20 queued, this PR | 258 px | 502 px | yes |

## Demo

![scroll fix
side-by-side](https://raw.githubusercontent.com/coder/coder/bpmct/codagt-313-assets/scroll-fix-side-by-side.gif)

Left (`main`): wheel-up does nothing because the chat scroll container
has been crushed to zero height.
Right (this PR): the queued list scrolls inside its own pane and the
chat history scrolls normally.

Recording is `AgentChatPageView` rendered through Storybook with the
production component source. The same gesture (wheel-up over the chat
history, then wheel-down over the queued list) is applied to both sides.
Source for the recording is in `bpmct/codagt-313-assets`.

## Change

```diff
-		<div className={cn("flex w-full flex-col", className)}>
+		// Cap the queue at ~40% of the small viewport so a long queue
+		// does not push the chat history's scroll container down to
+		// zero height (CODAGT-313). The list scrolls inside its own pane.
+		<div
+			className={cn(
+				"flex w-full flex-col max-h-[40svh] overflow-y-auto [scrollbar-gutter:stable] [scrollbar-width:thin] [scrollbar-color:hsl(var(--surface-quaternary))_transparent]",
+				className,
+			)}
+		>
```

## Why this spot, not the outer wrapper

The composer textarea already self-caps at `max-h-[50vh]` in
`ChatMessageInput.tsx:688`, so the only unbounded growth source in the
input section is the queued list. Capping the list keeps the constraint
colocated with the component that owns it, and any future consumer of
`QueuedMessagesList` is automatically safe.

`40svh` (small viewport height) so the queue doesn't fight with the iOS
keyboard once it appears, matching the `h-dvh` decision in #24848.

---

*Generated by Coder Agents.*
2026-05-05 08:05:11 -05:00
dependabot[bot] 2505709475 chore: bump axios from 1.15.0 to 1.15.2 in /site (#24965)
Bumps [axios](https://github.com/axios/axios) from 1.15.0 to 1.15.2.
<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.15.2</h2>
<p>This release delivers prototype-pollution hardening for the Node HTTP
adapter, adds an opt-in <code>allowedSocketPaths</code> allowlist to
mitigate SSRF via Unix domain sockets, fixes a keep-alive socket memory
leak, and ships supply-chain hardening across CI and security docs.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Prototype Pollution Hardening (HTTP Adapter):</strong>
Hardened the Node HTTP adapter and
<code>resolveConfig</code>/<code>mergeConfig</code>/validator paths to
read only own properties and use null-prototype config objects,
preventing polluted <code>auth</code>, <code>baseURL</code>,
<code>socketPath</code>, <code>beforeRedirect</code>, and
<code>insecureHTTPParser</code> from influencing requests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10779">#10779</a></strong>)</li>
<li><strong>SSRF via <code>socketPath</code>:</strong> Rejects
non-string <code>socketPath</code> values and adds an opt-in
<code>allowedSocketPaths</code> config option to restrict permitted Unix
domain socket paths, returning <code>AxiosError</code>
<code>ERR_BAD_OPTION_VALUE</code> on mismatch. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
<li><strong>Supply-chain Hardening:</strong> Added <code>.npmrc</code>
with <code>ignore-scripts=true</code>, lockfile lint CI, non-blocking
reproducible build diff, scoped CODEOWNERS, expanded
<code>SECURITY.md</code>/<code>THREATMODEL.md</code> with provenance
verification (<code>npm audit signatures</code>), 60-day resolution
policy, and maintainer incident-response runbook. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10776">#10776</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong><code>allowedSocketPaths</code> Config Option:</strong> New
request config option (and TypeScript types) to allowlist Unix domain
socket paths used by the Node http adapter; backwards compatible when
unset. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Keep-alive Socket Memory Leak:</strong> Installs a single
per-socket <code>error</code> listener tracking the active request via
<code>kAxiosSocketListener</code>/<code>kAxiosCurrentReq</code>,
eliminating per-request listener accumulation,
<code>MaxListenersExceededWarning</code>, and linear heap growth under
concurrent or long-running keep-alive workloads (fixes <a
href="https://redirect.github.com/axios/axios/issues/10780">#10780</a>).
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10788">#10788</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li><strong>Changelog:</strong> Updated <code>CHANGELOG.md</code> with
v1.15.1 release notes. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10781">#10781</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.15.1...v1.15.2">Full
Changelog</a></p>
<h2>v1.15.1</h2>
<p>This release ships a coordinated set of security hardening fixes
across headers, body/redirect limits, multipart handling, and
XSRF/prototype-pollution vectors, alongside a broad sweep of bug fixes,
test migrations, and threat-model documentation updates.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Header Injection Hardening:</strong> Tightened validation
and sanitisation across request header construction to close the
header-injection attack surface. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10749">#10749</a></strong>)</li>
<li><strong>CRLF Stripping in Multipart Headers:</strong> Correctly
strips CR/LF from multipart header values to prevent injection via field
names and filenames. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10758">#10758</a></strong>)</li>
<li><strong>Prototype Pollution / Auth Bypass:</strong> Replaced unsafe
<code>in</code> checks with <code>hasOwnProperty</code> to prevent
authentication bypass via prototype pollution on config objects, with
additional regression tests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10761">#10761</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10760">#10760</a></strong>)</li>
<li><strong><code>withXSRFToken</code> Truthy Bypass:</strong>
Short-circuits on any truthy non-boolean value, so an ambiguous config
no longer silently leaks the XSRF token cross-origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10762">#10762</a></strong>)</li>
<li><strong><code>maxBodyLength</code> With Zero Redirects:</strong>
Enforces <code>maxBodyLength</code> even when <code>maxRedirects</code>
is set to <code>0</code>, closing a bypass path for oversized request
bodies. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10753">#10753</a></strong>)</li>
<li><strong>Streamed Response <code>maxContentLength</code>
Bypass:</strong> Applies <code>maxContentLength</code> to streamed
responses that previously bypassed the cap. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10754">#10754</a></strong>)</li>
<li><strong>Follow-up CVE Completion:</strong> Completes an earlier
incomplete CVE fix to fully close the regression window. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10755">#10755</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>AI-Based Docs Translations:</strong> Initial scaffold for
AI-assisted translations of the documentation site. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10705">#10705</a></strong>)</li>
<li><strong><code>Location</code> Request Header Type:</strong> Adds
<code>Location</code> to <code>CommonRequestHeadersList</code> for
accurate typing of redirect-aware requests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7528">#7528</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>FormData Handling:</strong> Removes
<code>Content-Type</code> when no boundary is present on
<code>FormData</code> fetch requests, supports multi-select fields,
cancels <code>request.body</code> instead of the source stream on fetch
abort, and fixes a recursion bug in form-data serialisation. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7314">#7314</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10676">#10676</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10702">#10702</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10726">#10726</a></strong>)</li>
<li><strong>HTTP Adapter:</strong> Handles socket-only request errors
without leaking keep-alive listeners. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10576">#10576</a></strong>)</li>
<li><strong>Progress Events:</strong> Clamps <code>loaded</code> to
<code>total</code> for computable upload/download progress events.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/7458">#7458</a></strong>)</li>
<li><strong>Types:</strong> Aligns <code>runWhen</code> type with the
runtime behaviour in <code>InterceptorManager</code> and makes response
header keys case-insensitive. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7529">#7529</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10677">#10677</a></strong>)</li>
<li><strong><code>buildFullPath</code>:</strong> Uses strict equality in
the base/relative URL check. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7252">#7252</a></strong>)</li>
<li><strong><code>AxiosURLSearchParams</code> Regex:</strong> Improves
the regex used for param serialisation to avoid edge-case mismatches.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10736">#10736</a></strong>)</li>
<li><strong>Resilient Value Parsing:</strong> Parses out header/config
values instead of throwing on malformed input. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10687">#10687</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.15.2 - April 21, 2026</h2>
<p>This release delivers prototype-pollution hardening for the Node HTTP
adapter, adds an opt-in <code>allowedSocketPaths</code> allowlist to
mitigate SSRF via Unix domain sockets, fixes a keep-alive socket memory
leak, and ships supply-chain hardening across CI and security docs.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Prototype Pollution Hardening (HTTP Adapter):</strong>
Hardened the Node HTTP adapter and
<code>resolveConfig</code>/<code>mergeConfig</code>/validator paths to
read only own properties and use null-prototype config objects,
preventing polluted <code>auth</code>, <code>baseURL</code>,
<code>socketPath</code>, <code>beforeRedirect</code>, and
<code>insecureHTTPParser</code> from influencing requests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10779">#10779</a></strong>)</li>
<li><strong>SSRF via <code>socketPath</code>:</strong> Rejects
non-string <code>socketPath</code> values and adds an opt-in
<code>allowedSocketPaths</code> config option to restrict permitted Unix
domain socket paths, returning <code>AxiosError</code>
<code>ERR_BAD_OPTION_VALUE</code> on mismatch. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
<li><strong>Supply-chain Hardening:</strong> Added <code>.npmrc</code>
with <code>ignore-scripts=true</code>, lockfile lint CI, non-blocking
reproducible build diff, scoped CODEOWNERS, expanded
<code>SECURITY.md</code>/<code>THREATMODEL.md</code> with provenance
verification (<code>npm audit signatures</code>), 60-day resolution
policy, and maintainer incident-response runbook. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10776">#10776</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong><code>allowedSocketPaths</code> Config Option:</strong> New
request config option (and TypeScript types) to allowlist Unix domain
socket paths used by the Node http adapter; backwards compatible when
unset. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Keep-alive Socket Memory Leak:</strong> Installs a single
per-socket <code>error</code> listener tracking the active request via
<code>kAxiosSocketListener</code>/<code>kAxiosCurrentReq</code>,
eliminating per-request listener accumulation,
<code>MaxListenersExceededWarning</code>, and linear heap growth under
concurrent or long-running keep-alive workloads (fixes <a
href="https://redirect.github.com/axios/axios/issues/10780">#10780</a>).
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10788">#10788</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li><strong>Changelog:</strong> Updated <code>CHANGELOG.md</code> with
v1.15.1 release notes. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10781">#10781</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.15.1...v1.15.2">Full
Changelog</a></p>
<hr />
<h2>v1.15.1 - April 19, 2026</h2>
<p>This release ships a coordinated set of security hardening fixes
across headers, body/redirect limits, multipart handling, and
XSRF/prototype-pollution vectors, alongside a broad sweep of bug fixes,
test migrations, and threat-model documentation updates.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li>
<p><strong>Header Injection Hardening:</strong> Tightened validation and
sanitisation across request header construction to close the
header-injection attack surface. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10749">#10749</a></strong>)</p>
</li>
<li>
<p><strong>CRLF Stripping in Multipart Headers:</strong> Correctly
strips CR/LF from multipart header values to prevent injection via field
names and filenames. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10758">#10758</a></strong>)</p>
</li>
<li>
<p><strong>Prototype Pollution / Auth Bypass:</strong> Replaced unsafe
<code>in</code> checks with <code>hasOwnProperty</code> to prevent
authentication bypass via prototype pollution on config objects, with
additional regression tests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10761">#10761</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10760">#10760</a></strong>)</p>
</li>
<li>
<p><strong><code>withXSRFToken</code> Truthy Bypass:</strong>
Short-circuits on any truthy non-boolean value, so an ambiguous config
no longer silently leaks the XSRF token cross-origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10762">#10762</a></strong>)</p>
</li>
<li>
<p><strong><code>maxBodyLength</code> With Zero Redirects:</strong>
Enforces <code>maxBodyLength</code> even when <code>maxRedirects</code>
is set to <code>0</code>, closing a bypass path for oversized request
bodies. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10753">#10753</a></strong>)</p>
</li>
<li>
<p><strong>Streamed Response <code>maxContentLength</code>
Bypass:</strong> Applies <code>maxContentLength</code> to streamed
responses that previously bypassed the cap. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10754">#10754</a></strong>)</p>
</li>
<li>
<p><strong>Follow-up CVE Completion:</strong> Completes an earlier
incomplete CVE fix to fully close the regression window. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10755">#10755</a></strong>)</p>
</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>AI-Based Docs Translations:</strong> Initial scaffold for
AI-assisted translations of the documentation site. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10705">#10705</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/582934382e4e0e0bcb679c628071a4203e93cf57"><code>5829343</code></a>
chore(release): prepare release 1.15.2 (<a
href="https://redirect.github.com/axios/axios/issues/10789">#10789</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/4709a48fa2717ba97f43f5432d48ca4e26c2d326"><code>4709a48</code></a>
fix: added fix for memory leak in sockets (<a
href="https://redirect.github.com/axios/axios/issues/10788">#10788</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/be3336014e01f9a4fc1f8aef15303cf7daaf58db"><code>be33360</code></a>
chore: update changelog (<a
href="https://redirect.github.com/axios/axios/issues/10781">#10781</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/47915144662f2733e6c051bdcb895a8c8f0586aa"><code>4791514</code></a>
fix: more header pollutions (<a
href="https://redirect.github.com/axios/axios/issues/10779">#10779</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/6feafcff6c2dbafe206161c5d09e38e1d36af66f"><code>6feafcf</code></a>
fix: socket issue (<a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/302e2739c602f00e323d4f3f5c79500647633a73"><code>302e273</code></a>
docs: update docs, add a couple actions etc (<a
href="https://redirect.github.com/axios/axios/issues/10776">#10776</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/ac42446be51300fe214ba3c6e40cc95f34fd6871"><code>ac42446</code></a>
chore(release): prepare release 1.15.1 (<a
href="https://redirect.github.com/axios/axios/issues/10767">#10767</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/908f2206b6bfeff67236784abce85935698ac1d9"><code>908f220</code></a>
docs: update threatmodel (<a
href="https://redirect.github.com/axios/axios/issues/10765">#10765</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/f93f8155250c2e066205521eda05ae22983a1f6d"><code>f93f815</code></a>
docs: added docs around potential decompressions bomb (<a
href="https://redirect.github.com/axios/axios/issues/10763">#10763</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/1728aa1b15b8857f970611fd8983c06b423fc486"><code>1728aa1</code></a>
fix: short-circuits on any truthy non-boolean in withXSRFToken (<a
href="https://redirect.github.com/axios/axios/issues/10762">#10762</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/axios/axios/compare/v1.15.0...v1.15.2">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.15.0&new-version=1.15.2)](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-05-05 11:30:43 +00:00
Michael Suchacz 1e7874c2c1 feat(site): add personal model override settings UI (#24748)
Adds the UI for personal chat model overrides for root chats, General
subagents, and Explore subagents. Backend support landed in #24715, and
this PR now targets `main`.

## Summary

- Add the admin switch for enabling user personal model overrides.
- Add the user `Agents` settings page at `/agents/settings/user-agents`.
- Use one dropdown per context with pinned chat default and deployment
default options.
- Show the resolved deployment default model in personal settings when
available.
- Teach root chat creation to honor saved root preferences without
replacing explicit user selections.
- Add shared unavailable and malformed override alerts, select separator
support, and Storybook coverage.

## Testing

- `pnpm --dir site lint:types`
- `pnpm --dir site check`
- `pnpm --dir site test:storybook
src/pages/AgentsPage/AgentSettingsUserAgentsPageView.stories.tsx
src/pages/AgentsPage/components/AdminPersonalModelOverridesSettings.stories.tsx
src/pages/AgentsPage/components/AgentCreateForm.stories.tsx
src/pages/AgentsPage/components/Sidebar/AgentsSidebar.stories.tsx`

> Mux is working on behalf of Mike.
2026-05-05 13:11:59 +02:00
Mathias Fredriksson 0c5a25c018 fix(site): deduplicate expired-attachment probes for repeated file IDs (#24760)
When multiple RemoteImageBlock components share a file ID, Chromium
fires native error events on all of them before the first probe's
fetch resolves. Each handler independently checked hasExpired(),
saw false, and started its own probe.

FileProbeContext (renamed from ExpiredFileIdsContext) now coordinates
probes across blocks for the same file ID:

- A ref-based pending set (isPending/markPending/clearPending) gates
  duplicate probes. A ref is used so the second handler can read it
  synchronously before React re-renders.
- Resolved outcomes are stored in context state (probeResults map) so
  sibling blocks re-render with the full result, including API error
  detail for tooltips.
- Context writes (markExpired, setProbeResult) run above the
  per-instance abort-controller guard so siblings receive the result
  even if the probing block unmounts mid-flight.
2026-05-05 14:01:06 +03:00
Ethan 4751416b29 fix!: persist structured chat errors (#24919)
**Breaking change for changelog:**

> `codersdk.Chat.last_error` now returns a structured `ChatError` object
(`{message, kind, provider, retryable, status_code, detail}`) instead of
a plain string. The chats API is experimental
(`/api/experimental/chats`), so this ships without a deprecation cycle;
consumers reading `chat.last_error` as a string must update to read
`chat.last_error.message`. SDK/generated TypeScript terminal error
payloads now use the single `ChatError` type; the live stream error
payload type is renamed from `ChatStreamError` to `ChatError`.

Persisted chat errors now carry the same provider-specific detail (kind,
provider, retryable, HTTP status, optional detail) as the live stream,
so refreshing a failed chat rehydrates with the full structured error
instead of a one-line headline.

Existing rows are migrated in place: legacy text errors are wrapped into
`{message, kind: "generic"}` so already-errored chats still render, and
rows with `last_error IS NULL` stay NULL. Internally, persisted fallback
decoding now reuses the existing `chaterror.KindGeneric` constant, with
no JSON value change.

Closes CODAGT-239
2026-05-05 12:56:06 +10:00
Ethan 7e01edeb8e fix: align chat attachment picker with allowed file types (#24917)
The agent chat composer only advertised image uploads to the OS file
picker and filtered drag-and-drop and paste events to `image/*`, even
though the backend accepts text, CSV, JSON, PDF, and a narrower set of
image types.

Move the allowed chat attachment media types into `codersdk` so the
frontend picker and backend enforcement share one source of truth. Use
the generated TypeScript list to drive the file input `accept` attribute
and the drag-and-drop and paste filters, while adding common text
extensions so platforms without MIME registrations still surface those
files in the picker.
2026-05-05 12:25:13 +10:00
Michael Suchacz 632dcdb63a feat: add personal chat model overrides (#24715) 2026-05-05 00:57:51 +02:00
Michael Suchacz 43aa0498d6 feat(site): warn when viewing another user's chat (#24941) 2026-05-05 00:47:24 +02:00
Kyle Carberry f0fd2111fd feat(site/src/pages/AgentsPage): render markdown attachments in preview popup (#24936)
Markdown attachments on `/agents` now render through the same `Response`
component used for chat messages instead of falling back to a monospaced
`<pre>` block. The popup detects markdown via an explicit
`text/markdown` media type and falls back to the `.md`/`.markdown`
filename extension when no media type is available.

`PreviewTextAttachment` and `TextPreviewDialog` gain an optional
`mediaType` so that callers (`AttachmentBlock` for already-sent messages
and `AttachmentPreview` for live drafts) can plumb the upload metadata
through. Plain `.txt` and unrecognized text attachments keep the
existing monospaced rendering.

## Demo

![Markdown attachment preview
demo](https://raw.githubusercontent.com/coder/coder/kylecarbs/preview-assets-md-attachments/markdown-attachment-preview.gif)

## Screenshots

| Markdown rendering | Plain text rendering |
| --- | --- |
| ![Markdown by
extension](https://raw.githubusercontent.com/coder/coder/kylecarbs/preview-assets-md-attachments/markdown-by-extension.png)
| ![Plain text stays
monospaced](https://raw.githubusercontent.com/coder/coder/kylecarbs/preview-assets-md-attachments/plain-text-stays-monospaced.png)
|

Light theme also verified:

![Markdown by extension
(light)](https://raw.githubusercontent.com/coder/coder/kylecarbs/preview-assets-md-attachments/markdown-by-extension-light.png)

<details>
<summary>Coverage details</summary>

New stories in `TextPreviewDialog.stories.tsx` cover:

- `MarkdownByExtension` — `.md` filename, headings/lists/tables/fenced
code render natively.
- `MarkdownByMediaType` — explicit `text/markdown` mediaType wins even
without a `.md` suffix.
- `MarkdownProseOnly` — inline `**bold**`, `_italic_`, and `` `code` ``
render via streamdown.
- `PlainTextStaysMonospaced` — `.txt` content stays inside `<pre>` so
existing previews don't regress.

Manual verification (desktop, Chromium, dark + light): all four stories
above plus the existing `Default`, `LongContent`, and `NoFileName`
stories pass.
</details>

_Coder Agents generated PR._
2026-05-04 17:37:57 -04:00
dependabot[bot] 63412012b6 chore: bump lodash from 4.17.21 to 4.18.1 in /site (#24940)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.18.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lodash/lodash/releases">lodash's
releases</a>.</em></p>
<blockquote>
<h2>4.18.1</h2>
<h2>Bugs</h2>
<p>Fixes a <code>ReferenceError</code> issue in <code>lodash</code>
<code>lodash-es</code> <code>lodash-amd</code> and
<code>lodash.template</code> when using the <code>template</code> and
<code>fromPairs</code> functions from the modular builds. See <a
href="https://redirect.github.com/lodash/lodash/issues/6167#issuecomment-4165269769">lodash/lodash#6167</a></p>
<p>These defects were related to how lodash distributions are built from
the main branch using <a
href="https://github.com/lodash-archive/lodash-cli">https://github.com/lodash-archive/lodash-cli</a>.
When internal dependencies change inside lodash functions, equivalent
updates need to be made to a mapping in the lodash-cli. (hey, it was
ahead of its time once upon a time!). We know this, but we missed it in
the last release. It's the kind of thing that passes in CI, but fails bc
the build is not the same thing you tested.</p>
<p>There is no diff on main for this, but you can see the diffs for each
of the npm packages on their respective branches:</p>
<ul>
<li><code>lodash</code>: <a
href="https://github.com/lodash/lodash/compare/4.18.0-npm...4.18.1-npm">https://github.com/lodash/lodash/compare/4.18.0-npm...4.18.1-npm</a></li>
<li><code>lodash-es</code>: <a
href="https://github.com/lodash/lodash/compare/4.18.0-es...4.18.1-es">https://github.com/lodash/lodash/compare/4.18.0-es...4.18.1-es</a></li>
<li><code>lodash-amd</code>: <a
href="https://github.com/lodash/lodash/compare/4.18.0-amd...4.18.1-amd">https://github.com/lodash/lodash/compare/4.18.0-amd...4.18.1-amd</a></li>
<li><code>lodash.template</code><a
href="https://github.com/lodash/lodash/compare/4.18.0-npm-packages...4.18.1-npm-packages">https://github.com/lodash/lodash/compare/4.18.0-npm-packages...4.18.1-npm-packages</a></li>
</ul>
<h2>4.18.0</h2>
<h2>v4.18.0</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lodash/lodash/compare/4.17.23...4.18.0">https://github.com/lodash/lodash/compare/4.17.23...4.18.0</a></p>
<h3>Security</h3>
<p><strong><code>_.unset</code> / <code>_.omit</code></strong>: Fixed
prototype pollution via <code>constructor</code>/<code>prototype</code>
path traversal (<a
href="https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh">GHSA-f23m-r3pf-42rh</a>,
<a
href="https://github.com/lodash/lodash/commit/fe8d32eda854377349a4f922ab7655c8e5df9a0b">fe8d32e</a>).
Previously, array-wrapped path segments and primitive roots could bypass
the existing guards, allowing deletion of properties from built-in
prototypes. Now <code>constructor</code> and <code>prototype</code> are
blocked unconditionally as non-terminal path keys, matching
<code>baseSet</code>. Calls that previously returned <code>true</code>
and deleted the property now return <code>false</code> and leave the
target untouched.</p>
<p><strong><code>_.template</code></strong>: Fixed code injection via
<code>imports</code> keys (<a
href="https://github.com/lodash/lodash/security/advisories/GHSA-r5fr-rjxr-66jc">GHSA-r5fr-rjxr-66jc</a>,
CVE-2026-4800, <a
href="https://github.com/lodash/lodash/commit/879aaa93132d78c2f8d20c60279da9f8b21576d6">879aaa9</a>).
Fixes an incomplete patch for CVE-2021-23337. The <code>variable</code>
option was validated against <code>reForbiddenIdentifierChars</code> but
<code>importsKeys</code> was left unguarded, allowing code injection via
the same <code>Function()</code> constructor sink. <code>imports</code>
keys containing forbidden identifier characters now throw
<code>&quot;Invalid imports option passed into
_.template&quot;</code>.</p>
<h3>Docs</h3>
<ul>
<li>Add security notice for <code>_.template</code> in threat model and
API docs (<a
href="https://redirect.github.com/lodash/lodash/pull/6099">#6099</a>)</li>
<li>Document <code>lower &gt; upper</code> behavior in
<code>_.random</code> (<a
href="https://redirect.github.com/lodash/lodash/pull/6115">#6115</a>)</li>
<li>Fix quotes in <code>_.compact</code> jsdoc (<a
href="https://redirect.github.com/lodash/lodash/pull/6090">#6090</a>)</li>
</ul>
<h3><code>lodash.*</code> modular packages</h3>
<p><a
href="https://redirect.github.com/lodash/lodash/pull/6157">Diff</a></p>
<p>We have also regenerated and published a select number of the
<code>lodash.*</code> modular packages.</p>
<p>These modular packages had fallen out of sync significantly from the
minor/patch updates to lodash. Specifically, we have brought the
following packages up to parity w/ the latest lodash release because
they have had CVEs on them in the past:</p>
<ul>
<li><a
href="https://www.npmjs.com/package/lodash.orderby">lodash.orderby</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.tonumber">lodash.tonumber</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.trim">lodash.trim</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.trimend">lodash.trimend</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.sortedindexby">lodash.sortedindexby</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.zipobjectdeep">lodash.zipobjectdeep</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.unset">lodash.unset</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.omit">lodash.omit</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.template">lodash.template</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/lodash/lodash/commit/cb0b9b9212521c08e3eafe7c8cb0af1b42b6649e"><code>cb0b9b9</code></a>
release(patch): bump main to 4.18.1 (<a
href="https://redirect.github.com/lodash/lodash/issues/6177">#6177</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/75535f57883b7225adb96de1cfc1cd4169cfcb51"><code>75535f5</code></a>
chore: prune stale advisory refs (<a
href="https://redirect.github.com/lodash/lodash/issues/6170">#6170</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/62e91bc6a39c98d85b9ada8c44d40593deaf82a4"><code>62e91bc</code></a>
docs: remove n_ Node.js &lt; 6 REPL note from README (<a
href="https://redirect.github.com/lodash/lodash/issues/6165">#6165</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/59be2de61f8aa9461c7856533b51d31b7d8babc4"><code>59be2de</code></a>
release(minor): bump to 4.18.0 (<a
href="https://redirect.github.com/lodash/lodash/issues/6161">#6161</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/af634573030f979194871da7c68f79420992f53d"><code>af63457</code></a>
fix: broken tests for _.template 879aaa9</li>
<li><a
href="https://github.com/lodash/lodash/commit/1073a7693e1727e0cf3641e5f71f75ddcf8de7c0"><code>1073a76</code></a>
fix: linting issues</li>
<li><a
href="https://github.com/lodash/lodash/commit/879aaa93132d78c2f8d20c60279da9f8b21576d6"><code>879aaa9</code></a>
fix: validate imports keys in _.template</li>
<li><a
href="https://github.com/lodash/lodash/commit/fe8d32eda854377349a4f922ab7655c8e5df9a0b"><code>fe8d32e</code></a>
fix: block prototype pollution in baseUnset via constructor/prototype
traversal</li>
<li><a
href="https://github.com/lodash/lodash/commit/18ba0a32f42fd02117f096b032f89c984173462d"><code>18ba0a3</code></a>
refactor(fromPairs): use baseAssignValue for consistent assignment (<a
href="https://redirect.github.com/lodash/lodash/issues/6153">#6153</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/b8190803d48d60b8c80ad45d39125f32fa618cb2"><code>b819080</code></a>
ci: add dist sync validation workflow (<a
href="https://redirect.github.com/lodash/lodash/issues/6137">#6137</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/lodash/lodash/compare/4.17.21...4.18.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=lodash&package-manager=npm_and_yarn&previous-version=4.17.21&new-version=4.18.1)](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-05-04 18:45:57 +00:00
Michael Suchacz 0bb09935bc feat: add computer-use provider selection for AI agents (#24772)
Adds a deployment-wide setting to select the computer-use provider
(Anthropic or OpenAI) for AI agents, plus the OpenAI computer-use runner
needed to honor that selection.

The setting is stored in `site_configs` under
`agents_computer_use_provider`, defaults to Anthropic when unset, and is
exposed via experimental GET/PUT endpoints under
`/api/experimental/chats/config/computer-use-provider`. The chatd
computer-use tool now dispatches to either `runAnthropicComputerUse` or
`runOpenAIComputerUse` based on the resolved provider, with
provider-specific result metadata for OpenAI screenshots.

Frontend adds a provider dropdown to the Agents Experiments settings
page nested under the virtual desktop toggle, with disabled state
handling while virtual desktop is off and skeleton loaders while config
queries are in flight.

Hugo and Codex review follow-up:
- Uses shared provider validation and clearer computer-use constant
names.
- Removes stale OpenAI pending-safety-checks commentary.
- Documents why provider result metadata is needed for OpenAI
screenshots.
- Keeps the computer-use subagent visible when provider credentials are
missing, then returns a clear spawn-time configuration error.
- Uses OpenAI's recommended 1600x900 screenshot geometry to preserve the
native 16:9 aspect ratio.
- Moves OpenAI-specific computer-use helpers into
`coderd/x/chatd/chatopenai/computeruse` after rebasing onto the provider
package refactor in `main`.
- Converts OpenAI pixel scroll deltas to Coder desktop wheel-click
amounts.
- Preserves OpenAI pointer modifiers with key down/up desktop actions
and rejects unsupported non-left double-click buttons explicitly.
- Maps OpenAI back/forward side-button clicks to browser navigation key
actions.
- Defaults omitted OpenAI click buttons to left-click.
- Retries mouse release cleanup if the final OpenAI drag release fails.
- Keeps computer-use subagent availability messages stable when provider
config cannot be loaded, while logging the backend error.
- Releases remaining OpenAI modifier keys if a synthetic key-up cleanup
action fails.
- Updates Storybook interaction stories so provider snapshots show the
selected final provider.

> Mux updated this PR description on behalf of Mike.
2026-05-04 20:30:50 +02:00
Kyle Carberry 1ecdad689b fix(site/src/pages/AgentsPage): restore sticky user message pinning after react-infinite-scroll-component refactor (#24937)
Restores the sticky user message pinning behavior in the Agents chat
that regressed after #24687 swapped the chat scroll container for
`react-infinite-scroll-component`.

## Root cause

`react-infinite-scroll-component` renders two wrapper divs between the
`.overflow-y-auto` scroller and the rendered messages, and its inner
wrapper hard-codes `overflow: auto` in its inline style. With the new
layout, `position: sticky` on a user message resolved against that
inner wrapper rather than the real scroller, so the message scrolled
out with its sentinel and the existing fade/clip overlay never
engaged.

## Fix

Force both InfiniteScroll wrappers to `display: contents` so they no
longer participate in layout. The user message's nearest scrolling
ancestor is once again the `.overflow-y-auto` element, and
`position: sticky` anchors to the scroll container as it did before
#24687.

The outer wrapper is reached via the Tailwind arbitrary selector
`[&>[class$=outerdiv]]:contents` because the library only exposes
`style` for the inner wrapper.

The inverse infinite-scroll behavior is preserved: the scroller
itself stays `flex-col-reverse`, so it remains bottom-anchored and
the library's load-more sentinel still lands at the visual top of
the content stack.

Also drops the dead `overflow-y-auto` class on the floating
scroll-to-bottom button wrapper noted in the bug report.

## Test coverage

Adds `StickyUserMessagePinsOnScroll` to
`AgentChatPageView.stories.tsx`. With a 40-message conversation it
walks the user-message sentinels in reverse DOM order to find the
one currently pinned (the latest sentinel above the scroller's top
edge) and asserts the matching sticky container is anchored within
a few pixels of that edge. Without the fix the container ends up
hundreds of pixels above the scroller because `position: sticky`
silently no-ops.

The existing structural `StickyUserMessageStructure` story in
`ConversationTimeline.stories.tsx` continues to pass unchanged.

<details>
<summary>Verification</summary>

```sh
pnpm exec tsc -p .                                      # 0 errors
pnpm run lint:check                                     # passes
pnpm exec vitest run --project=unit                     # 2303 passed
pnpm exec vitest run --project=storybook \
  src/pages/AgentsPage/AgentChatPage.stories.tsx \
  src/pages/AgentsPage/AgentChatPageView.stories.tsx \
  src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.stories.tsx
                                                        # 90 passed
```

Confirmed the new story fails on `main` (sticky container at the
sentinel's position instead of the scroller top) and passes with
the fix applied.

</details>

---

Generated by Coder Agents.
2026-05-04 13:35:35 -04:00
Kayla はな 162acaf8bf feat: update UsersPage role editing to match new designs (#24857) 2026-05-04 11:19:21 -06:00