mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
97cb722fb87faa513bc3372eda24799b8dbaef41
5849
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
97cb722fb8 |
fix: show no budget instead of unlimited for empty group AI budget (#27993)
An empty per-member AI budget on the group settings page previously displayed "unlimited budget" with a "Members in this group have no spending cap." alert. Unlimited spend only applies when the everyone group is the sole group, so this messaging was misleading everywhere else. ## Changes - Empty budget now shows "This group has **no budget** set. View docs" with no info alert. "View docs" links to [Effective group resolution](https://coder.com/docs/ai-coder/ai-gateway/cost-controls#effective-group-resolution) using the versioned `docs()` helper. - Removed the "Members in this group have no spending cap." alert entirely. - Input placeholder changed from `unlimited` to `no budget`. - Updated the `AIBudgetUncapped` story expectations to match. ## Unchanged - Entering an explicit `$0` still shows the "A $0 limit disables AI access for this group." alert, as before. - Saving with an empty field still sends `null` to the budget API; backend semantics are untouched. Story tests pass: `pnpm test:storybook src/pages/GroupsPage/GroupSettingsPageView.stories.tsx` (7/7). --- *This PR was generated by Coder Agents on behalf of @tracyjohnsonux.* |
||
|
|
da99941099 |
feat(site): add shared DateTimeRangeFilter component (#28255)
A text-expression datetime range picker with From/To inputs accepting
`now`, a clock time (current day), a date (midnight), or a date with a
clock time. Invalid text gets inline errors, underspecified expressions
resolve on blur, and out-of-order boundaries clamp against the other
one. The trigger derives a concise label ("Last 24 hours", "Apr 10",
"Aug 11 - Today", "Apr 17 - 19").
Placed in `site/src/components/DateTimeRangeFilter/` so other pages can
reuse it. Expression parsing and trigger-label derivation live in
`timeRange.ts` next to the component; both are generic over `Date`
pairs. Depends on #28254 for the shared `filterQuery` serialization
helpers.
Part of
[AIGOV-580](https://linear.app/codercom/issue/AIGOV-580/ai-gateway-sessions-page-takes-5-10-seconds-to-load)
---
_Generated by Coder Agents on behalf of @johnstcn._$
---
**Stack:** #28254 (filterQuery fix) \u2192 #28255 (component) \u2192
#28256 (sessions page)
|
||
|
|
8405bbb26c | feat(site): show best-effort model pricing on the model form (#28290) | ||
|
|
663f41ffa9 |
feat: derive OAuth2 client type from token_endpoint_auth_method (#28043)
Adds an OAuth2 client type (public vs confidential, RFC 7591 §2) derived from the requested auth method instead of hardcoded confidential. The type is stored and guarded here, but no endpoint enforces on it yet; public behavior at the token endpoint follows in the next PR in the stack. - Client type is derived once and reused by both registration and redirect URI validation, so they can't disagree - IsPublic() fails closed: an unrecognized or missing value reads as confidential - RFC 7592 update (PUT) now rejects moving a client between public and confidential (400) instead of silently flipping it when the auth method is omitted - Discovery still doesn't advertise "none"; follows once the token endpoint honors it ### Behavior by client shape `client_type` is derived from `token_endpoint_auth_method` at POST and pinned at PUT. RFC 7592 GET/PUT authenticate with the registration access token, not the client secret, so neither endpoint reads a secret. | Registered with | Stored `client_type` / method | GET reports | PUT that flips the method | |------------------------------------|---------------------------------------|-----------------------|-----------------------------------------| | omitted, or `client_secret_basic` | `confidential` / `client_secret_basic` | `client_secret_basic` | `none` → 400 `invalid_client_metadata` | | `none` (new) | `public` / `none` | `none` | `client_secret_*` → 400 `invalid_client_metadata` | | `none` (before this PR) | `confidential` / `none` | `none` | either → 200, type stays `confidential` | - PUT still replaces every other RFC 7591 field. `client_type` is the only pinned one; the method may move within a type (`client_secret_basic` ↔ `client_secret_post`). - Row 3 is the only shape where the two columns disagree. The guard fires only on a method change that crosses the type line, so those clients keep managing themselves instead of being locked out of their own configuration endpoint. - The token endpoint does not consult `client_type` yet, so every client still authenticates with a secret and registration still issues one. Split out of #27873, second in the stack (on top of #28041). Refs https://linear.app/codercom/issue/ENG-3029/oauth2-support-public-client |
||
|
|
4d13bef74d |
feat(site): add Install Coder Desktop item to UserDropdown (#28244)
> 🤖 This PR was modified by Coder Agents on behalf of Jake Howell. Resolves [DEVEX-722](https://linear.app/codercom/issue/DEVEX-722/add-install-coder-desktop-button-to-userdropdown). Adds an **Install Coder Desktop** item to `UserDropdown`, sitting directly above the existing **Install CLI** option. Because `UserDropdownContent` is shared, it appears in both the navbar dropdown and the agents-page sidebar footer. ### Screenshots macOS/Windows shots are captured with `navigator.platform` overridden accordingly; the Linux shot is the real workspace platform, where the Coder Desktop item is hidden. Install Coder Desktop uses a monitor glyph, and Install CLI now uses a terminal glyph (it was a monitor on `main`). | `main` (before) | This PR · macOS/Windows | This PR · Linux / iPad OS | | --- | --- | --- | |  |  |  | ### Behaviour - **Platform-gated visibility:** shown only on macOS and Windows (the platforms Coder Desktop ships for), hidden on Linux/other. The Linux client ([coder/coder-desktop-linux](https://github.com/coder/coder-desktop-linux)) is experimental and not advertised yet, so it stays hidden there. - **Links to the docs** (`https://coder.com/docs/user-guides/desktop`) rather than a single install method. The docs page is the canonical hub covering Homebrew, WinGet, manual release downloads, and source, and it stays current without frontend changes. The `coder-desktop-*` repo READMEs don't enumerate install methods; they defer to these same docs. - **No installed-detection:** consistent with the Install CLI item, we don't try to detect whether Coder Desktop is already present. ### Changes - `site/src/utils/platform.ts`: add `isWindows()` and `supportsCoderDesktop()`. - `UserDropdownContent.tsx`: render the platform-gated item (`MonitorIcon`) and switch Install CLI to `TerminalIcon`. - Unit tests for the platform helpers and Storybook coverage for the dropdown item (present + correct href on macOS/Windows, absent on Linux/iPadOS). Implementation plan & decision log **Ticket open questions and decisions** 1. *Shown to all users or only supported platforms?* Only supported platforms (macOS, Windows); hidden elsewhere. The Linux client is experimental and not advertised yet, so hiding it there is intentional. 2. *Where should it link?* The Coder Desktop docs page. Users install via many methods (brew, winget, releases, source); the docs are the single hub that lists them all and are maintained in-repo. The GitHub release pages / repo READMEs only cover downloads and defer back to the docs. 3. *Hide when already installed?* No. There is no reliable browser-side way to detect a native app install, and it mirrors how Install CLI behaves. **Implementation** - Extend `site/src/utils/platform.ts` with `isWindows()` and `supportsCoderDesktop()` (reusing the existing `isMac()`). - In `UserDropdownContent.tsx`, conditionally render an `Install Coder Desktop` `DropdownMenuItem` (external link, `MonitorIcon`, opens in a new tab) above `Install CLI` when `supportsCoderDesktop()` is true. - Tests: `platform.test.ts` (OS detection via `vi.stubGlobal`) and `UserDropdown.stories.tsx` (visibility + href per platform, mocking platform detection with `spyOn`). Left as a **draft** pending review, let me know when you'd like it opened. |
||
|
|
60722bb653 | fix: link workspaces empty state to template builder (#28280) | ||
|
|
821d91fabd | fix: log tailnet tunnel authorization decisions (#27819) | ||
|
|
b3f05a23fc |
feat(site/src/pages/AgentsPage): surface subagents in the chat sidebar (#28234)
## What Makes subagents more discoverable in the agent chat sidebar, without disturbing the existing status icon or layout. - **Parent chat rows show a subagent count** with a bot icon (e.g. `3 🤖`) at the start of the metadata line, next to the diff stats. Only shown when a chat has subagents; uses lucide `BotIcon`, the same icon this codebase already uses to denote agents. Passive indicator (the leading status icon, timestamp, and kebab are untouched). - **The chat actions menu gains a "Show subagents (N)" / "Hide subagents" toggle**, grouped directly under "Rename chat" in both the kebab (⋮) and the right-click context menu. It expands/collapses the row's subagents and is only rendered when the chat has subagents. Expansion still uses the existing sidebar expand state, so the hover chevron, the menu toggle, and the count all stay in sync. ## Notes / decisions - Subagent children are capped at depth 1, so the count and toggle only appear on parent chats. - The menu toggle lives in the shared `ChatActionsMenuItems`, so it appears in both the kebab and the right-click menu; the top-bar kebab intentionally does not pass the props, so it stays hidden there. - The on-row `N 🤖` indicator is currently passive (clicking the row opens the chat as before). Can be made a click-to-expand control if wanted. ## Testing Validated in Storybook (`ChatsSidebar` stories) with 0 TypeScript errors. Added a `SubagentsMenuToggle` story with a `play` function asserting the label swaps between "Show subagents (3)" and "Hide subagents" and that children expand. Existing `ChatsSidebar.test.tsx` does not assert menu contents and is unaffected. --- *This PR was generated by Coder Agents on behalf of @tracyjohnsonux.* |
||
|
|
72a6c8ae72 | fix(site): stop the new-turn scroll snap on agent chat (#28213) | ||
|
|
d3f08b1983 |
feat: audit chat system instructions changes (#27668)
Adds an audit record for administrative events on the deployment-wide
chat instruction settings (system prompt, the include-default toggle,
and the plan-mode instructions), per CODAGT-719 and operator decision
D5. Each endpoint records under a stable identity: resource type
`chat_instruction_settings`, a fixed resource ID and a human-readable
target ("System prompt", "Plan mode instructions"), so two changes to
one setting share an ID and history-by-setting works. A real change
exports a Write entry with the old-to-new text visible; a
value-identical PUT still upserts and still returns 204 but records
nothing.
Attempts are recorded, not only transitions. Identity is assigned before
the authorization check, so a denied PUT exports a 403 row with an empty
diff (no request content reaches it), a validation failure exports a 400
row, and a write failure exports a 500 row, each with an empty diff; an
operator can tell "nothing changed" from "something changed and capture
degraded" by the status code.
The write path stays authoritative. The advisory lock and, on plan-mode,
the transaction exist only to serve change-detection; if any of that
machinery fails (lock, begin, commit, rollback), the handler runs main's
idempotent write path directly and derives the response from it, so a
member-visible failure of audit-only infrastructure can never replace
main's successful response. Accepted consequence: when the lock cannot
be taken, two concurrent identical writes can produce two rows instead
of one. That is audit degradation, which is allowed; changing a member's
response is not. Write failures keep the exact response the endpoint
produced before this wiring (transaction error for the system prompt,
which was always transactional; the raw write error for plan mode, which
was not), and the full transaction error is logged so rollback failures
cannot vanish.
<details>
<summary>CODAGT-66 plan entry: S1 (verbatim)</summary>
**S1 `feat: audit chat system instructions changes`** (CODAGT-719; base:
main)
- Struct: `database.ChatSystemPromptSettings{ID uuid.UUID; SystemPrompt
string; IncludeDefaultSystemPrompt bool; PlanModeInstructions string}`
in `coderd/database/types.go` (ticket-sketched shape; one struct, both
endpoints).
- Registration: union entry (diff.go), table.go entry (`id`
ActionIgnore, other three ActionTrack), `AuditActionMap` Write-only;
four request.go cases (`ResourceTarget` "", `ResourceID` from struct,
`ResourceType` new enum value `chat_system_prompt_settings`,
`ResourceRequiresOrgID` false with the "Artificial ID / deployment
singleton" comment convention).
- Migration: `ALTER TYPE resource_type ADD VALUE IF NOT EXISTS
'chat_system_prompt_settings';` comment-only no-op down (000558 shape);
number picked at push per the numbering constraint.
- codersdk: constant + prose `FriendlyString` ("chat system prompt
settings"); `TestAuditDBEnumsCovered` forces both. `coderd/audit.go`
presentation switches: rely on safe defaults (no link, generic
description); no FE changes (filter label falls back to capitalized
value; acceptable per precedent).
- Wiring `putChatSystemPrompt` and `putChatPlanModeInstructions`:
InitRequest with Action Write; artificial `ID: uuid.New()` on `New` only
when a change is detected; no-op suppression by leaving both aReq sides
unset (nil resource IDs skip the log, request.go skip rule); the write
path itself stays byte-identical (upserts still run unconditionally).
- `putChatSystemPrompt` (writes two keys conditionally in one existing
tx): inside that tx, read the pair via `GetChatSystemPromptConfig` for
`Old`, perform the conditional writes exactly as today, then RE-READ the
pair for `New`. The re-read is load-bearing:
`include_default_system_prompt` is computed from the toggle row AND the
prompt, so a prompt-only write can flip the effective value without the
request carrying the pointer. `PlanModeInstructions` stays zero on both
sides.
- `putChatPlanModeInstructions` (no tx exists today): wrap its
read-upsert in `InTx` (behavior-preserving: same single write);
`Old`/`New` populate only `PlanModeInstructions`; the two system-prompt
fields stay zero on both sides; no cross-key reads.
- Change detection compares the populated payload fields only (never the
artificial ID).
- Tests: handler-level coderdtest with `audit.NewMock()` asserting Write
entry on change and NO entry on a value-identical PUT, for both
endpoints (this also exercises `ResourceRequiresOrgID` end to end); the
fallback-flip case (no explicit include-default row, nonempty prompt set
to empty, effective boolean flips: entry emitted with the boolean diff);
diff assertions (old->new prompt text tracked, not secret) in
`enterprise/audit/diff_internal_test.go`; `TestAuditableResources`
passes by construction.
- Bookkeeping at PR open: correct CODAGT-719's no-op premise ("matches
the existing 204-on-unchanged behavior" does not exist on main;
suppression is new, write path unchanged).
- Review focus: Old capture and the New re-read inside the tx (three of
four existing singletons never set Old; do not copy them; and the
computed include-default value makes a naive New construction wrong);
the skip-on-no-op mechanism; prompt text deliberately visible in diffs.
</details>
Note: the plan excerpt above predates operator decision D5 (2026-07-30),
which this PR implements: the resource type is
`chat_instruction_settings` (not `chat_system_prompt_settings`), each
setting carries a stable ID and a display-name target (not a per-write
artificial ID and an empty target), no-op suppression runs through
`InitRequestWithCancel` (not the nil-ID skip), and attempts (denied,
failed, capture-degraded) record rows with real statuses and empty
diffs. Ticket bookkeeping for CODAGT-719 was corrected on Linear at
kickoff: the ticket's "matches the existing 204-on-unchanged behavior"
premise does not exist on main; suppression is new, and the write path
is unchanged.
> 🤖 This PR was created with the help of Coder Agents, and _will be_
reviewed by a human. 🏂🏻
---------
Co-authored-by: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com>
|
||
|
|
ba5717dc67 |
fix(site/src/pages/AgentsPage): disallow queued message edits (#28265)
Closes CODAGT-230.
Selecting "Edit queued message" in Agent Chat did not stop the queued
message from sending: edit mode was purely client-side state, so at turn
end the backend promoted the queued message and sent it anyway, leaving
the UI stuck in a stale "Editing queued message" state with the send
button showing "Save".
This removes queued-message editing entirely instead of adding backend
locking. Queued messages can still be promoted ("Send now") and deleted
("Remove from queue"); editing already-sent history messages is
unchanged.
## Changes
- Remove the Edit pencil from queued message rows
(`QueuedMessagesList`), the "Editing queued message" banner and "Save"
button label (`AgentChatInput`), and the queue-edit state, handlers, and
prop plumbing (`AgentChatPage`, `AgentChatPageView`, `ChatPageContent`).
- Remove the queued-edit save flow that deleted the original queued row
and re-queued a new message, plus the now-unused `rawText`/`fileBlocks`
fields of `getQueuedMessageInfo`.
- Drop the redundant `isEditingHistoryMessage` prop on `ChatPageInput`,
which had become identical to `isEditing`, and stop discarding the
delete/promote promises so `QueuedMessagesList` busy state works again.
- Replace the queued-edit stories and tests with an `ActionsExcludeEdit`
regression story asserting queued rows expose "Send now" and "Remove
from queue" but no "Edit" button.
## Testing
- `pnpm -C site check`, `pnpm -C site lint:types`.
- Unit: `AgentChatPage.test.ts`, `QueuedMessagesList.test.ts` (92
tests). Storybook: all four touched story files (102 tests). A
pre-existing unhandled xterm error in `AgentChatPageView.stories.tsx`
reproduces identically at the merge base.
- Remote dogfood UAT passed on a dev.coder.com workspace with a real
model: no edit affordance on queued rows, queued delete and turn-end
promotion still work, history-message editing and Escape behavior
unaffected.
> Mux acted on behalf of Mike for this pull request.
|
||
|
|
affeeaf9c8 |
feat: extend agent chat MCP tools for remote UAT evidence loops (#28233)
Extends the Agent-chat MCP tools so an unattended UAT evidence loop can
fetch artifacts, monitor long runs, and find prior runs without burning
model context.
## Backend
- New `chat_files_token` crypto key feature (migration 000571) with
rotator support and a dedicated signing keycache on coderd.
- `POST /api/experimental/chats/files/{file}/download-url`
(authenticated) mints a short-lived (5 min) signed URL and returns it
with `sha256`, `size_bytes`, `name`, `mime_type`, and `expires_at`.
- `GET /api/experimental/chats/files/{file}/download?token=` (no session
token) redeems the signed URL: verifies the JWS, requires the token's
`file_id` to match the path, and re-checks the minting user's RBAC
access live at redemption. Clients can `curl -o` artifacts with zero
credentials in the URL consumer.
- `ChatFileMetadata` gains `size_bytes` (via `octet_length`, no bytes
fetched).
## MCP tools (`codersdk/toolsdk`)
- `coder_download_chat_file`: by `file_id` or `chat_id`+`file_name`;
returns the signed URL plus checksum and size instead of base64.
- `coder_await_chat`: blocks (bounded `wait_secs`, 1-120) until a chat
leaves `running`/`interrupting`, using the existing watch stream with
subscribe-before-read.
- `coder_list_chats`: label, query, and limit filtering; chat
projections now include labels.
- `coder_get_chat_messages`: `after_id` forward cursor with
`next_after_id` (exact incremental reads), plus per-message `files`
metadata so artifact-bearing messages are identifiable.
- `coder_get_chat`: file listings now include `size_bytes` and
`created_at`.
- `coder_list_templates`: exposes `agents_allowed` for pre-flight
checks.
## Testing
- coderd: mint/redeem happy path with an unauthenticated client,
expired/tampered/file-mismatched tokens, auth still required on the
plain file endpoint, non-owner mint rejection.
- toolsdk: harness + integration coverage for all new/changed tools,
including signed-URL redemption with checksum verification,
forward-cursor exactness, await transition/timeout paths, and label
filtering.
- Remote dogfood UAT (dev.coder.com Coder Agent) passed all six
acceptance scenarios end to end over both MCP transports.
Note: `go test ./codersdk/toolsdk/` has a pre-existing goleak flake on
main (leaked `agentssh` non-PTY session goroutines from SSH exec tests;
reproduced 3/3 on clean `b4971bc49f1`). It is unrelated to this diff.
> Mux acted on Mike's behalf to create this PR.
<!-- mux-attribution: model=claude-sonnet-4-6 thinking=high -->
|
||
|
|
7724ee281a |
feat: defer MCP tool schemas behind a find_tools search (#28225)
## Summary When the `mcp-tool-search` experiment is enabled, chatd stops inlining connected MCP tool schemas into every generation. It instead exposes a built-in `find_tools` tool whose description carries a compact catalog of the deferred tools, and only ships full JSON schemas for tools the model has activated by searching or by calling them directly. Closes [CODAGT-760](https://linear.app/coder/issue/CODAGT-760). ## Problem Tool-heavy agent configurations (GitHub, Linear, Notion, and dev-tooling MCP servers) inline over 100k tokens of tool schema definitions into every generation. Initial uncached requests reached ~216k tokens with time-to-first-token close to nine minutes, while the model typically invokes only a handful of tools per turn. ## How it works - `decideMCPToolSearch` defers external and workspace `.mcp.json` MCP tools whenever the experiment is enabled. Native, dynamic, provider, skill, and transport tools are never deferred. - `find_tools` embeds a server-grouped catalog in its tool description (degrading to names-only, then counts-only, then a constant-size summary past a context-scaled size cap) and scores keyword matches across tool names, descriptions, parameter schemas, and server metadata. Queries can scope to one server with a `server:` prefix, and exact `names` arguments always activate. - Activation state is ephemeral: it is re-derived each generation from surviving chat history (`find_tools` results and direct calls to deferred tools), so activations naturally lapse when compaction summarizes them away. Aggregate activated schema weight is capped at 10% of the context window, shedding the least recently activated schemas first; `find_tools` shares that budget across parallel calls in one step. No new persistence. - Deferred tools stay registered for execution, so the model can call a cataloged tool directly without searching first; the schema is activated for subsequent steps. - Fail-open: the experiment being disabled, an empty candidate set, or an MCP tool named `find_tools` all disable deferral, leaving today's behavior byte-identical on the wire. - Prometheus counters/histograms track `find_tools` calls, matches, activations, and deferred token weight. - The conversation timeline renders `find_tools` calls with a collapsed search summary and expandable match list, falling back to the generic renderer on malformed payloads. ## Validation - Unit tests for the catalog, matcher, experiment-gated decision, and activation derivation; end-to-end chatd generation tests covering search-then-call, direct-call activation, experiment-off wire parity, compaction lapse, and subagent tool gating. - Storybook interaction tests for the timeline rendering and malformed-payload fallback. - Remote dogfood UAT on dev.coder.com passed: deferral with a real MCP server and Anthropic model, direct calls without prior search, activation persistence across turns, experiment-off parity, and clean UI/console. > Disclosure: Mux (AI agent) authored this PR on Mike's behalf. |
||
|
|
962366ffc6 |
fix(site): quote colon-containing values in filter serialization (#28254)
`stringifyFilter` in the shared `Filter` component only quoted values containing spaces. Filter values like RFC 3339 timestamps (`2026-08-16T20:42:00Z`) contain colons but no spaces, so when any filter was edited and the whole query re-serialized, the timestamp went out unquoted and the backend `searchTerms` parser rejected it (`Query element ... can only contain 1 ':'`). Quote values containing colons as well; they were never valid unquoted because the backend parser already rejects them. Extract `parseFilterQuery`/`stringifyFilter` into `filterQuery.ts` with unit tests, including a round-trip of quoted timestamps. Part of [AIGOV-580](https://linear.app/codercom/issue/AIGOV-580/ai-gateway-sessions-page-takes-5-10-seconds-to-load) --- _Generated by Coder Agents on behalf of @johnstcn._$ --- **Stack:** #28254 (filterQuery fix) \u2192 #28255 (component) \u2192 #28256 (sessions page) |
||
|
|
5af08a1a09 | fix(site): repair the locally-run storybook vitest suite (#28261) | ||
|
|
119f2b1dd9 |
feat: limit concurrent chat agents with pooled admission (#27902)
Limits concurrent chat generation on capped deployments to 5 root chats and 10 delegated subagent chats. The pools are deployment-wide and independent, so delegated work can continue while root capacity is full. The default caps live in AGPL code. Enterprise contributes only a licensing unlock, so unlicensed deployments stay capped and cannot fail open. Licensed deployments are uncapped while Agent Hours usage stays below an explicit hard limit. Deployments without a hard limit remain uncapped, and reaching the Agent Hours allocation only triggers warnings. Admission happens before a worker takes chat ownership. Capped deployments serialize admission across replicas with a transaction-scoped advisory lock and derive active and queued state from current ownership plus fresh runner heartbeats, rather than persisted queue markers or per-replica state. The acquisition query returns a bounded, pool-interleaved candidate set instead of ranking the whole backlog; a migration replaces the acquisition index with a pool-aware one. Refused chats stay running but unowned, and interrupt requests bypass admission so users can stop queued or over-cap chats. The single-chat API derives `queued_for_capacity` from live pool state; list endpoints do not report it. The UI polls that value every 5 seconds while a chat is running and shows a callout when the chat is waiting for capacity. Updates the administrator documentation and deployment-wide Prometheus gauges for active and queued agents. Replica-level values must be aggregated with `max`, not `sum`. > Mux updated this PR on Mike's behalf. |
||
|
|
cb0a9ebbbf |
fix(site/src/pages/AgentsPage): remove sidebar nav bottom divider (#28239)
## What Removes the horizontal divider line that appears directly under the **Search** item in the Agents chats sidebar. The line was the `border-b border-border-default` on the sidebar `<nav>` that wraps the **New chat** and **Search** items. Since Search is the last item in that nav, the border rendered as a stray line beneath it. ## Change `site/src/pages/AgentsPage/components/ChatsSidebar/chats/ChatsPanel.tsx` ```diff -className="hidden border-b border-border-default px-2 py-1.5 sm:flex sm:flex-col sm:gap-0.5" +className="hidden px-2 py-1.5 sm:flex sm:flex-col sm:gap-0.5" ``` The bottom border is dropped entirely. Note: this was a Tailwind border, not MUI. --- *This PR was generated by Coder Agents on behalf of @tracyjohnsonux.* |
||
|
|
16ae996b93 |
fix(site/src/pages/AgentsPage/components): clean up agents composer borders and normalize dropdown pills (#28230)
Audit pass on the Agents chat composer: borders, the history-edit divider, and making the model selector and workspace pill visually consistent with each other and the left chat-list chevron. ## Borders 1. **Remove the composer outline** — drop `border border-border-default/80` from the `chat-composer` container in `AgentChatInput.tsx`. Focus ring, drag-over ring, history-edit warning shadow, rounded corners, background, and `shadow-sm` are unchanged. 2. **Match the skeleton** — drop the same border from `ChatInputSkeleton` in `AgentsSkeletons.tsx` so the loading placeholder stays consistent with the loaded composer. 3. **Neutral history-edit divider** — the divider under the "Editing will delete all subsequent messages..." warning header used `border-border-warning/50` (a harsh, light gold line in dark mode). Switched to `border-border-default/70`, matching the sibling "editing queued message" divider. The warning text/icon keep `content-warning`. ## Model selector <-> workspace pill consistency The model selector (`ModelSelector.tsx`) and workspace pill (`WorkspacePill.tsx`) rendered inconsistently. Normalized both, using the left `ChatSectionHeader` chevron (`size-3.5`) as the reference: 4. **Chevron size** — model was `size-icon-sm` (18px) and forced to 24px by the shared `Button` `cva` (`[&>svg]:size-icon-lg`); workspace was `size-3` (12px). Both now render `size-3.5` (14px). The model override uses the repo's `[&>svg]:!size-3.5 [&>svg]:p-0` convention since the `Button` variant otherwise wins on specificity. 5. **Chevron color** — removed `opacity-60` from the workspace chevron so both are full-opacity `content-secondary` (and `hover:content-primary`). 6. **Chevron rotation** — the model chevron snapped instead of animating because the Button's `[&>svg]:transition-colors` overrode the icon's `transition-transform`. Switched to `[&>svg]:transition` (covers transform and color) so it rotates smoothly like the workspace/sidebar chevrons. 7. **Pill shape + fill + height** — gave the model selector `bg-surface-secondary` (hover `bg-surface-tertiary`) and `rounded-full` to match the workspace pill, and replaced the fixed `h-8` with the pill's height mechanism (`h-7` mobile, `h-auto` + `py-0.5` at desktop). ## Notes - The composer borders pre-existed in the markup; they became more visually apparent after the recent MUI/Emotion removal (#27821) changed the global baseline/theming layer. - Out of scope: `DiffViewer/CommentableDiffViewer.tsx` uses the same `border border-border-default/80` pattern for the "Add a comment" box on diffs. Separate surface, left unchanged. --- > This PR was generated by Coder Agents on behalf of @tracyjohnsonux. |
||
|
|
a3a0079bd2 |
fix(site): stop redundant RBAC paywall error toast on Groups page (#28249)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell. Fixes coder/coder#23898 / coder/coder#23898. ## Problem On a deployment without a Premium license, opening **Admin → Deployment settings → Groups** shows the Premium paywall *and* a redundant error toast in the bottom-right reading "Template RBAC is a Premium feature. Contact sales!". ## Root cause `GroupsPage.tsx` fired the paginated `groupsByOrganization` query unconditionally. Groups are gated behind the `template_rbac` (Premium) entitlement, so the request returned `403` ("Template RBAC is a Premium feature"), which a `useEffect` surfaced via `toast.error`. Meanwhile `GroupsPageView` already renders `PaywallPremium` when `groupsEnabled` is false, hence the duplicate messaging. The AI Governance page doesn't fire an entitlement-gated request, so it only shows the paywall. There's a second subtlety that made the bug load-path dependent: `selectFeatureVisibility` returns `{}` when unlicensed, so `template_rbac` is `undefined`, not `false`. React Query treats `enabled: undefined` as enabled, so a naive `enabled: groupsEnabled && ...` gate still fired the request on a fresh full page load (where entitlements were briefly in flight). Client-side navigation happened to have entitlements cached as `false`, so it looked fixed there but reproduced on hard reload. ## Fix Gate the groups query with `enabled: Boolean(groupsEnabled && organization)`. The `Boolean()` coercion is load-bearing: it turns the `undefined` entitlement into a real `false` so the request is genuinely skipped rather than defaulting to enabled. When the entitlement is missing there is no request, no error, and the paywall remains the single source of truth. Legitimate load failures (when the feature *is* entitled) still toast as before. <details><summary>Investigation notes</summary> * `site/src/pages/GroupsPage/GroupsPage.tsx` — `groupsQuery` ran regardless of entitlement; the `groupsQuery.error` effect calls `toast.error`. * `site/src/pages/GroupsPage/GroupsPageView.tsx` — renders `PaywallPremium` when `!groupsEnabled`, independent of the query. * `site/src/modules/dashboard/entitlements.ts` — `getFeatureVisibility` returns `{}` when `!hasLicense`, so feature flags are `undefined` (not `false`) on unlicensed deployments. * `usePaginatedQuery` forwards `enabled` to the underlying `useQuery`, and its prefetch / invalid-page effects are no-ops while the query is disabled. * Backend source of the message: `enterprise/coderd/templates.go`. </details> ## Testing Verified end-to-end on a local unlicensed `scripts/develop.sh` deployment (the exact repro condition): * Confirmed `GET /api/v2/organizations/coder/paginated-groups` returns `403 "Template RBAC is a Premium feature. Contact sales!"` — the toast's text. * **Before fix:** hard reload of `/deployment/groups` shows the error toast bottom-right alongside the paywall. * **After fix:** 3 consecutive hard reloads, no toast at any point (including the \~3s mark where it previously fired); paywall still renders correctly. * `pnpm --dir site lint:types` passes. Before/after screenshots are attached in the PR thread / chat. |
||
|
|
995d7fe31b |
feat: add per-license Products section with Coder Agents price gates (#28051)
<img width="1100" height="312" alt="Screenshot 2026-08-17 at 3 43 51 PM" src="https://github.com/user-attachments/assets/30d21467-93ec-4880-a430-ccd4b494b8f5" /> Each license card now always expands to a **Products** section: a Coder Workspaces box showing active seat usage, and, on Premium licenses, a Coder Agents box driven by the `agent_runtime_hours_*` license claims and the merged `agent_runtime_hours` entitlement. The card header gains a **Type** column (`Trial`/`Standard`), and the left header label now shows the feature set only (`Premium`/`Enterprise`). The Coder Agents box renders five states: no allocation (dashed purple upgrade CTA), unlimited allocation (`-1` sentinel), normal usage, allocation exceeded (red border and red "Agent hours exceeded" status; concurrent chats stay Unlimited), and hard limit exceeded (red "Hard limit exceeded" status; concurrent chats capped at 5, mirroring the backend's `maxConcurrentRootAgents`, which is not exposed via the API). Usage and overage indicators only render on the license whose allocation matches the merged entitlement and which is currently effective, following the existing AI Governance winning-license pattern via a generalized `isLicenseApplicableForFeatureUsage` helper; AI Governance add-on behavior is unchanged. Stacked on #27985 (base branch `runtime-hours-entitlements`); do not merge before it. Notes for review: - #27985 now grandfathers claim-less Premium licenses into a zero-hour `agent_runtime_hours` allocation, so the merged entitlement (disabled, `limit: 0`) and its measured `actual` are always present for Premium deployments. The upgrade card's "Agent hours used" row therefore renders universally; the `Premium` story pins that state. - Agent hours usage now renders with exactly one decimal (e.g. `16,264.3`, `42.0`), derived from #27985's new `actual_ms` field and floored to tenths with integer math. The same floored value drives the exceeded checks, so the displayed number and the red state flip at the same instant; a fraction past the allocation now trips "Agent hours exceeded" (`20,000.1 > 20,000`), pinned by the `PremiumWithAgentHoursExceededByFraction` story. The allocation denominator stays whole (it comes from the whole-hour license claim). |
||
|
|
6dfba5c567 | test(site/src/modules/workspaces): cover version picker stacking (#28154) | ||
|
|
9590e9586e | fix(site/src/pages/AgentsPage): stop gating chat stream parts on client status (#28207) | ||
|
|
14e3ae33cf | fix(site/src/pages/AgentsPage): treat interrupting chats as busy in the composer (#28209) | ||
|
|
a749cf521f |
refactor(site): tidy secrets list layout (#27917)
Tighten the user secrets settings page layout. Move the enable toggle into a leading column, truncate long descriptions, promote Add secret and docs into the settings header actions, and drop the redundant Refresh control now that mutations already invalidate the secrets query. | Old | New | | --- | --- | | <img width="2936" height="1810" alt="SECRETS_PAGE_OLD" src="https://github.com/user-attachments/assets/e7d18953-9207-4ea1-874e-054de85a0098" /> | <img width="2936" height="1810" alt="SECRETS_PAGE_NEW" src="https://github.com/user-attachments/assets/221e9ab5-3be8-4b3a-80d1-89489b61a008" /> | |
||
|
|
753f3d95c6 | chore(site): add devin icon (#28206) | ||
|
|
fa8ffe4eda |
feat: report agent runtime hours usage in entitlements (#27985)
Populate `FeatureAgentRuntimeHours.Actual` on every entitlements refresh for licenses that grant the feature. A new `GetTotalUsageHBAgentRuntimeV1` query sums `runtime_ms` over the license's usage period, reading `usage_events` directly: `hb_agent_runtime_v1` is exactly one row per hourly bucket deployment-wide with `created_at` at the bucket start, enforced by the unique partial index introduced in #27983. The measurement reuses the shared `measureUsage` policy from #27984 through a new `AgentRuntimeMsFn` closure (usage publisher subject): failures publish the stable `LicenseAgentRuntimeUsageUnavailableErrorText` and log the cause. Usage is floored to whole hours, matching the unit of the `agent_runtime_hours_*` claims, and at most one warning is emitted per refresh: reaching the allocation supersedes the advisory soft limit. The dashboard renders the soft-limit advisory muted without a sales link and treats the runtime usage-unavailable text as a diagnostic. **Precise usage.** `Feature.ActualMs` (JSON `actual_ms`), set only for `agent_runtime_hours`, carries the exact stored milliseconds backing the floored `Actual` so clients can render fractional hours (e.g. `10.3`). It has the same freshness as `Actual`; the whole-hour warning thresholds are unchanged. **Unlimited licenses.** A license minted with the unlimited (`-1`) allocation decodes to an enabled feature with a nil `Limit` (#27984), so the warning write-back now guards the allocation dereference: no thresholds can exist for an unlimited license, so no runtime hours warning is ever emitted, while `Actual` is still measured and published. `Feature.Compare` is unchanged; for usage-period features the issued-at/end dates decide first, so a metered feature outranks an unlimited one only on an exact timestamp tie, an edge pinned by a `TestFeatureComparison` case and documented on `decodeAgentRuntimeHours`. **Grandfathered premium licenses.** Premium licenses without `agent_runtime_hours_*` claims are now granted the feature disabled with a zero limit over the license term, identical to an explicit `allocation: 0`: usage is measured and published for every Premium deployment, and chatd's pooled admission (#27902) caps concurrent agentic chats until a license with a positive allocation is added. The default carries a fixed early `UsagePeriod.IssuedAt` (2026-08-01, the same mechanism as the managed-agents default) so any license actually carrying the claims outranks it in the `AddFeature` merge regardless of the licenses' relative issue dates; the constant must stay earlier than the earliest legitimately issued claim-bearing license. Zero allocations (explicit or grandfathered) emit no deployment-wide warning banner: those deployments are steered by the in-page upgrade CTA and the concurrency cap. Enterprise licenses are unchanged. Part 3 of a 3-PR stack splitting up #27796 (see there for review history). Stack: #27983 → #27984 → this PR. Closes CODAGT-852. |
||
|
|
30dc7ebd71 |
fix(site/src/pages/AgentsPage): persist empty MCP selection (#28238)
Removing the final optional MCP server from an existing chat produced an
empty selection, but the message request omitted `mcp_server_ids`. The
API interprets an omitted field as preserving the current selection.
Send the selected MCP server IDs for every message, including an empty
array. Add a Storybook interaction test that removes the final MCP
server and verifies the request contains `mcp_server_ids: []`.
<details>
<summary>Manual verification on a local dev instance</summary>
Setup: `./scripts/develop.sh`, an Anthropic provider with
`claude-haiku-4-5`, and a local test MCP server registered with
availability `default_on`.
With this branch, chat `75285d9f`:
1. The new chat showed the MCP chip selected.
2. Sent a message, then removed the chip with the X control.
3. Sent a second message, then reloaded the page.
4. No MCP chip appeared, and the picker toggle stayed off.
5. `GET /api/experimental/chats/{id}` returned `mcp_server_ids: []`.
With the one-line change reverted, chat `751ac191` repeated the same
flow. The chip returned as selected after the reload, and the API
returned `mcp_server_ids: ["b63a2a3a-..."]`.
Not covered: `force_on` servers, plan mode interaction, and queued
messages during streaming.
</details>
Generated by Coder Agents.
|
||
|
|
d15800b494 |
feat: tolerate unusable runtime hours claims and decode -1 allocation as unlimited (#27984)
Two coupled changes to the license/entitlements layer, preparing for runtime-hours usage reporting. **Tolerate unusable runtime hour claims.** Unusable `agent_runtime_hours_*` claim combinations no longer reject the whole license: rejecting a signed license over a cosmetic threshold claim would drop the deployment to unlicensed. `decodeAgentRuntimeHours` drops the unusable claims, surfaces the stable `LicenseAgentRuntimeHoursClaimsIgnoredWarningText` (deduplicated across licenses), and logs the affected license and claims through the new `FeatureArguments.Logger`; `validateAgentRuntimeHours` and its license-invalidating errors are removed. The dashboard recognizes the stable diagnostic text and renders it muted, with a "License notices" heading instead of the exceedance heading and without a sales link. **Unlimited allocation.** An `agent_runtime_hours_allocation` claim of exactly `-1` (`AgentRuntimeHoursUnlimitedAllocation`, mirrored in coder/license) is reserved to mean unlimited: it decodes to an enabled feature with no `limit` in `/api/v2/entitlements`, the shape the UI already renders as "Unlimited". Threshold claims alongside it have nothing to threshold against, so they are dropped with the claims-ignored warning, and any other negative allocation remains unusable. The issuer-side counterpart (refusing to mint `-1` together with threshold claims) is coder/license#49. The managed agent measurement path is intentionally untouched: managed agents are deprecated and slated for removal, so the shared usage-measurement failure policy (`measureUsage`) now lands in #27985 next to its runtime-hours consumer instead of converting a doomed call site here. Part 2 of a 3-PR stack splitting up #27796 (see there for review history). Stack: #27983 → this PR → #27985. |
||
|
|
fb3ed7a56a |
chore(site): allow devin: URI scheme for Devin Desktop deep links (#28214)
## Summary `coder/registry#1050` adds a new `devin-desktop` module that opens Devin Desktop via a `devin://` deep link (Devin Desktop is Cognition's June 2, 2026 rebrand of Windsurf). Coder's frontend gates which external app URI schemes it will open with a session token, `ALLOWED_EXTERNAL_APP_PROTOCOLS` in `site/src/modules/apps/apps.ts`. `devin:` isn't in that list yet, so without this change the "Open" button on that app would return the raw URL with the `$SESSION_TOKEN` placeholder unsubstituted, an unusable link. ## Change Add `"devin:"` to `ALLOWED_EXTERNAL_APP_PROTOCOLS`, next to the existing `"windsurf:"` entry. ## Validation - `pnpm exec biome check --error-on-warnings src/modules/apps/apps.ts`: clean. - `pnpm exec vitest run src/modules/apps/apps.test.ts`: 21/21 pass. - `make pre-commit`: passes. ## Sequencing `coder/registry#1050` should not be merged until this lands in a released Coder version, otherwise the `devin-desktop` module's deep link would be broken on deployments running an older Coder version. Tracked together in REG-77 / DEVEX-777. > 🤖 This PR was created with the help of Coder Agents, and needs a human review. 🧑💻 |
||
|
|
444fb8aa9b |
fix(site): allow single-label AI provider endpoints (#28122)
Closes #27980. Reduces the `baseUrl` field validation in `ProviderForm.tsx` to only validate non-empty input. The previous validation was not in line with `validateAIProviderBaseURL` in `codersdk/aiproviders.go`. This was blocking users from adding providers with a short-form hostname (e.g. `http://localhost:8080/v1`). > Generated by Coder Agents, reviewed by a human. |
||
|
|
b5d18bb9c9 | feat: add redirect URL override for external auth (#28082) | ||
|
|
46ec620767 |
fix(site): deflake adjust user theme preference (#28219)
## Summary Deflakes the `adjust user theme preference` Playwright test (`site/e2e/tests/users/userSettings.spec.ts`), tracked in DEVEX-415. The test selected the Light theme and then hard-navigated with `page.goto` before the optimistic appearance update was persisted. The navigation could cancel the in-flight `PUT /api/v2/users/me/appearance`, so the reloaded document embedded the stale `dark` preference and the final assertion flaked. `toPass` retries could not help because retrying the reload only re-reads the still-stale persisted state. ## Fix Wait for the appearance form's save spinner to clear before the hard reload, mirroring how other settings tests wait for a visible save confirmation. Asserting the optimistic light class first guarantees the spinner is already showing if a save started; a repeat run that is already light never shows it, so the test is idempotent and there are no direct API calls. To give the test a UI signal, `Spinner` gets an opt-in `label` prop that exposes it as a `role="status"` live region with an `aria-label` (decorative otherwise). `Loader` moves its label onto its own status container so it keeps a single status region. ## Changes - `site/src/components/Spinner/Spinner.tsx`: opt-in `label` prop. - `site/src/components/Loader/Loader.tsx`: label on its own status region. - `site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.tsx`: label both appearance save spinners. - `site/e2e/tests/users/userSettings.spec.ts`: wait for the save spinner. ## Validation - `biome check` and `tsc -p .` pass. - Loader + AppearancePage unit tests and the affected storybook tests pass. - The e2e test passed 20/20 under `pnpm playwright:test -g "adjust user theme preference" --repeat-each 20`. <details> <summary>Implementation plan & decision log</summary> # DEVEX-415: Fix flake in "adjust user theme preference" e2e test ## Problem Playwright test `site/e2e/tests/users/userSettings.spec.ts` → `adjust user theme preference` flakes. After selecting the Light theme and hard-navigating to `/`, the reloaded page sometimes stays `dark`, failing the final assertion. CI Flake Bot has recorded repeated recurrences on `main` (latest 2026-08-17, runs `32004239187`, `31745261984`) even after PR #25183 added `toPass` retries. ## Root cause (confirmed by reading the code) The appearance update is optimistic and its persistence is not awaited before navigation: - `updateAppearanceSettings` (`site/src/api/queries/users.ts`) has an `onMutate` that optimistically writes the new theme into the React Query cache. The `<html>` class flips to `light` immediately, before the `PUT /api/v2/users/me/appearance` completes. - `useQueuedAppearanceSubmit` (`site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx`) serializes submits: if a request is in flight, the next is queued and only fires after the first settles. - A fresh `member` user has **empty** appearance settings. `migrateLegacyPreference` (`site/src/theme/themeMode.ts`) maps empty settings to `{ mode: "single", theme: "dark" }` (`DEFAULT_THEME = "dark"`). So the "Theme mode" dropdown already starts on **Single theme** and `<html>` starts `dark`. Selecting "Single theme" in the test is therefore a **no-op** (`onChangeMode` early-returns when `mode === draft.mode`) and fires **no** PUT. The only appearance PUT in the test is the one from clicking "Light default" (`onSelectSingle("light")` → `theme_preference: "light"`). - The test's first `expectLightThemeClasses(page)` passes purely from the optimistic cache. It then calls `page.goto("/")` almost immediately (~20 ms after the click). If PUT #2 (the light one) has not persisted server-side, the new document loads the still-persisted `dark` preference from embedded metadata, and every retry of the post-navigation assertion sees `dark` for the full 10 s window. `toPass` cannot help post-navigation because it only re-reads stale, already persisted state; it cannot make an unfinished/queued PUT complete. ## Implemented fix: wait for the saving spinner (UI signal) before navigation > Iteration history: (1) An earlier attempt waited on the appearance `PUT` via > a `waitForApiCall` helper, but that couples the test to a state transition > and is non-idempotent (a repeat run that is already light fires no PUT, so > the wait times out). CI retries reuse the same ephemeral server, so this is a > real hazard. (2) A second attempt confirmed persistence with > `page.request.get(...)`, but that calls the API directly and stops being a > site test. Both were rejected. The repo's non-flaky settings tests wait for a **visible save confirmation** (e.g. "settings updated successfully" toasts) before trusting the result. The appearance theme form has no toast; its only save-in-progress feedback is the `<Spinner>`. So the fix mirrors that pattern using the spinner: 1. Make the theme section's spinner identifiable via a new opt-in `label` prop on `Spinner` (sets `role="status"` + `aria-label` only when provided; decorative otherwise). `Loader` moves its label onto its own `status` container so it keeps a single status region and its `getByLabelText` queries keep working. 2. In the test, after clicking "Light default", assert the optimistic light class, then wait for that spinner to be hidden before `page.goto("/")`. Why this is correct and idempotent: - React Query sets `isPending` before `onMutate` applies the optimistic cache update, so by the time the optimistic light class is visible the spinner is already showing if a save started. Waiting for it to clear guarantees the PUT settled (and was not canceled by navigation) before the reload. - A repeat run that is already light: clicking "Light default" is a no-op radio change, no PUT fires, the spinner never shows, and `toBeHidden` passes immediately. The reload still shows light. - No direct API calls: the test only observes site UI. ### Implemented changes `Spinner` gains an opt-in `label` prop (`site/src/components/Spinner/Spinner.tsx`): ```tsx role={label ? "status" : undefined} aria-label={label} ``` `Loader` carries the label on its own status container (`site/src/components/Loader/Loader.tsx`), and the appearance save spinners use the new prop (`AppearanceForm.tsx`): ```tsx <Spinner loading={isUpdating} size="sm" label="Saving theme preference" /> <Spinner loading={isUpdating} size="sm" label="Saving terminal font" /> ``` `site/e2e/tests/users/userSettings.spec.ts`: ```ts await expect( page.getByRole("combobox", { name: /theme mode/i }), ).toContainText("Single theme"); // precondition: single mode const singleThemeGroup = page.getByRole("group", { name: "Theme" }); await expect(singleThemeGroup).toBeVisible(); await singleThemeGroup.getByText("Light default", { exact: true }).click(); await expectLightThemeClasses(page); // optimistic DOM => spinner showing if saving await expect( page.getByRole("status", { name: "Saving theme preference" }), ).toBeHidden(); // save settled before the hard reload await page.goto("/", { waitUntil: "domcontentloaded" }); await expectLightThemeClasses(page); ``` Validation: `biome check`, `tsc -p .` pass; Loader + AppearancePage unit tests and the affected storybook tests pass; the e2e test passed 20/20 under `pnpm playwright:test -g "adjust user theme preference" --repeat-each 20` (idempotent). ## Alternatives considered - **Wait on the appearance `PUT` via a `waitForApiCall` helper**: rejected. It couples the test to a state transition and is non-idempotent, a repeat run that is already light fires no PUT so the wait times out (14/15 repeats failed). CI retries reuse the same ephemeral server, so this is a real hazard, not just a local-repeat artifact. - **Confirm persistence with `page.request.get(...)`**: rejected. It calls the API directly and stops being a site test. - **Default `role="status"` on the shared `Spinner`**: rejected. `Loader` wraps `Spinner` in its own `status` div, so a default would nest two status regions and break `Loader.test.tsx`. The opt-in `label` prop avoids this. - **Add a networkidle wait or sleep before navigation**: rejected. Violates the repo guidance against `time.Sleep`-style timing hacks and is inherently racy. - **Fix product behavior instead of the test**: out of scope. Related bug DEVEX-94 ("Light Theme setting not respected until Appearance page opened") tracks product-side persistence/embedding behavior; this task is scoped to stabilizing the e2e test. ## Files touched - `site/src/components/Spinner/Spinner.tsx` (new opt-in `label` prop). - `site/src/components/Loader/Loader.tsx` (label on its own status region). - `site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.tsx` (use the `label` prop on both appearance save spinners). - `site/e2e/tests/users/userSettings.spec.ts` (wait for the spinner). </details> --- This PR was created by Coder Agents on behalf of @jeremyruppel. --------- Co-authored-by: Samuel Volin <sam.volin@coder.com> |
||
|
|
039c0da5ae |
feat(site/src/pages/TemplateBuilder): make sidebar steps navigable (#28153)
## What Makes the remaining `SelectionSummary` sidebar elements clickable jump targets on `/templates/new/builder`, continuing the work from #27351 (which made module rows navigable). Clickable now: | Sidebar element | Jumps to | |---|---| | `Base Template` label | `base-infra` | | Selected base-template row | `base-parameters` (falls back to `base-infra` when that step is skipped) | | `Modules` label | `module-select` | | Each module row | `module-settings` + scroll (already shipped in #27351) | | `Customizations` label | `customizations` | ## Back-stack behavior The sidebar previously colored groups purely from the current step, so jumping backward would grey out and disable steps you had already reached. This adds a `maxReachedGroup` that never shrinks on backward navigation: - Groups at or below the furthest-reached group stay `complete` (green) and clickable, like a browser back-stack. - Groups strictly above render as `upcoming` and inert (no button, no hover, not focusable). - The connecting divider color keys off `maxReachedGroup`, not the current step, so it stays green after navigating backward. Clickability is gated on `maxReachedGroup` (you can only jump to steps you have already reached). ## Changes - `SelectionSummary.tsx`: new required `maxReachedStep` and `onNavigateStep` props. Split the single `variant()` into `indicatorVariant` (label circle), `dividerVariant` (connecting line), and a `reachable()` gate. `StepIndicator` and `BaseTemplateSelection` render as `<button>` (hover + focus ring, `aria-label`) when a reachable handler is supplied, else stay inert. - `TemplateBuilderPageView.tsx`: track `maxReachedGroup`; add `navigateToStepId(stepId)` that resolves skipped steps via `nearestVisible` (so `base-parameters` falls back to `base-infra`) and mirrors the existing customizations reset when leaving that step. Wire both new props into `SelectionSummary`. - `SelectionSummary.stories.tsx`: add `onNavigateStep` to meta and `maxReachedStep` to existing stories; add `NavigationClicks` (asserts each label/base/module callback), `BackwardNavigation` (dividers stay green), and `UpcomingStepsInert` (steps above max-reached are not buttons). ## Out of scope Everything else from #27077 stays out: gallery height, sensitive-var banner relocation, trash-icon wiring, and the scroll-past required-field subsystem. ## Testing - `pnpm check` (biome) clean - `pnpm lint:types` (tsc) clean - `pnpm vitest run --project=storybook src/pages/TemplateBuilder` — 37 pass - `pnpm vitest run --project=unit src/pages/TemplateBuilder` — 55 pass <details> <summary>Implementation plan / decision log</summary> ### Origin This is the remainder of PR #27077's item #2 (navigable selection summary), rebased onto current `main` after #27351 shipped the module-row navigation. ### Why a `maxReachedGroup` back-stack `furthestAllowedIndex(state)` on current `main` is all-or-nothing (0 without a base selected, otherwise the last step), so it cannot express "how far the user has progressed" for the sidebar coloring. A monotonic `maxReachedGroup` (bumped when the current group advances, never shrunk) is needed to keep completed steps green and clickable after backward navigation, matching #27077. ### Decisions - Reachability gating: gate both coloring and clickability on `maxReachedGroup` (only jump to steps already reached), rather than the looser `furthestAllowedIndex` (which would let users skip required steps once a base is chosen). - Base-template row target: jump to `base-parameters` and let `nearestVisible` fall back to `base-infra` when the base has no parameters/prerequisites. - Module rows: keep `onNavigateModule` passed directly (not re-gated on reachability), since a module can only be selected after reaching group 2, so `reachable(2)` is always true when module rows render. This preserves the earlier decision to keep the module row's handler required with no inert branch. </details> --- Coder Agents generated, on behalf of @aqandrew. |
||
|
|
b4971bc49f |
feat(site/src/modules/dashboard/Navbar): replace proxy emoji with latency radio icon in trigger (#28128)
Updates the latency dropdown's collapsed views in the navbar: - Removes the proxy emoji (`ExternalImage`) from the desktop trigger and the mobile "Workspace proxy settings" row. - Shows a lucide `RadioIcon` instead, colored via `getLatencyColor` (matching the loading state used by the `Latency` component on desktop). - Keeps the latency text in `content-primary`; only the icon carries the latency color. The expanded proxy lists are unchanged (they keep the proxy icon and colored latency text). Story changes: - Added `ClosedWarningLatency` and `ClosedCriticalLatency` to cover the icon color per latency level. - Right-aligned the ProxyMenu story trigger to match its navbar placement, so the end-aligned menu renders without collision shifting in the story canvas. > Generated by Coder Agents on behalf of @tracyjohnsonux. |
||
|
|
5d746aa594 |
fix(site/src): replace hardcoded text-[13px] with scale tokens outside agents (#28071)
Replaces the arbitrary `text-[13px]` value with the design-system tokens
`text-sm` (14px) or `text-xs` (12px) in the 18 non-agents files that
used it. `AgentsPage` usages and `modules/resources/AgentMetadata.tsx`
are intentionally left alone; they'll be handled with the agents UI
separately.
Because the custom Tailwind scale bakes `font-weight: 500` into
`text-xs`/`text-sm`, `font-normal` was added wherever the text
previously rendered at 400 and is prose, code, or log content, so only
the size changes there. Short labels, headers, and numeric values take
the token's 500 weight as-is.
### Token decisions
| File | Token | Rationale |
|---|---|---|
| `components/Logs/LogLine.tsx` | `text-xs font-normal` | Dense mono log
output; 12px keeps line-height close to current |
| `components/PaginationWidget/PaginationAmount.tsx` | `text-xs
font-normal` | Caption-style "showing X of Y" text |
| `pages/IconsPage/IconsPage.tsx` (figcaption) | `text-xs font-normal` |
88px-wide icon captions |
| `pages/WorkspacesPage/WorkspacesButton.tsx` | `text-xs font-normal` |
Secondary line under the template name in the combobox |
| `modules/templates/TemplateExampleCard.tsx`,
`pages/CreateTemplateGalleryPage/...` | `text-xs font-normal` |
Secondary card description prose (and its "Read more" link) |
| `components/FullPageLayout/Sidebar.tsx` / `Topbar.tsx` | `text-sm`
(Topbar adds `font-normal`) | Nav chrome; Topbar is a container so
`font-normal` avoids leaking 500 into all children |
| `components/Paywall/PaywallPremium.tsx` | `text-sm font-normal` |
Feature list prose (compact variant) |
| `modules/templates/TemplateFiles/TemplateFiles.tsx` /
`TemplateFileTree.tsx` | `text-sm` | File headers/tree labels (header
already `font-medium`) |
| `modules/workspaces/WorkspaceOutdatedTooltip.tsx` | `text-sm
font-normal` | Tooltip body prose |
| `pages/WorkspacePage/ResourcesSidebar.tsx` | `text-sm font-normal` |
Help text prose |
| `pages/AISettingsPage/.../CredentialField.tsx` | `text-sm font-normal`
| Mono credential input |
| `pages/DeploymentSettingsPage/Option.tsx` | `text-sm` | Already
`font-semibold` |
| `pages/HealthPage/Content.tsx` | `text-sm font-normal` | Mono detail
block |
| `pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx` |
`text-sm` | "Files" panel header label |
| `pages/TemplatePage/TemplateInsightsPage/TemplateInsightsPage.tsx` |
`text-sm` (`font-normal` on prose/empty state) | Data labels and values
in insight panels |
### Storybook review checklist
Stories directly covering changed components:
- `Logs/LogLine` and `Logs/Logs`
- `Paywall/PaywallPremium`
- `TemplateExampleCard`
- `TemplateFiles` and `TemplateFileTree`
- `WorkspaceOutdatedTooltip`
- `CreateTemplateGalleryPageView`
- `IconsPage`
- `TemplateInsightsPage`
- `TemplateVersionEditor` (also exercises FullPageLayout
`Topbar`/`Sidebar`)
Indirect coverage for components without their own stories:
- `PaginationAmount` → `PaginationWidget/PaginationContainer` stories,
plus paginated page views (`UsersPageView`, `AuditPageView`,
`ConnectionLogPageView`)
- `WorkspacesButton` → `WorkspacesPageView` stories (open the "New
workspace" combobox)
- `HealthPage/Content` → `HealthPage/*Page` stories (`DERPPage`,
`DatabasePage`, etc.)
- `ResourcesSidebar` → `WorkspacePage/Workspace` stories (failed-build
state)
- `FullPageLayout Topbar/Sidebar` → `TemplateVersionEditor` stories
- `CredentialField` → `ProviderForm` / `AddProviderPageView` stories
No story exists for `DeploymentSettingsPage/Option`; verify on the
deployment settings page (option value pills).
---
🤖 This PR was generated by Coder Agents on behalf of @tracyjohnsonux.
|
||
|
|
ce88ad131c |
chore: bump protobufjs from 7.6.1 to 7.6.5 in /site (#28201)
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.6.1 to 7.6.5. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/protobufjs/protobuf.js/releases">protobufjs's releases</a>.</em></p> <blockquote> <h2>protobufjs: v7.6.5</h2> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.4...protobufjs-v7.6.5">7.6.5</a> (2026-07-04)</h2> <h3>Bug Fixes</h3> <ul> <li>handle EOF during options parsing (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2352">#2352</a>) (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2356">#2356</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/10fba6d54815ceecca8a06b9a6db490c8f5d2217">10fba6d</a>)</li> </ul> <h2>protobufjs: v7.6.4</h2> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.3...protobufjs-v7.6.4">7.6.4</a> (2026-06-12)</h2> <h3>Bug Fixes</h3> <ul> <li>Reconfigure and speed up CI (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2329">#2329</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/574f761c05b007dab6595ca1eaed86436579ba3f">574f761</a>)</li> <li>Remove inquire submodule (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2327">#2327</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/06ddd07064329032aae6db586e2d54938b591792">06ddd07</a>)</li> </ul> <h2>protobufjs: v7.6.3</h2> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.2...protobufjs-v7.6.3">7.6.3</a> (2026-06-09)</h2> <h3>Bug Fixes</h3> <ul> <li>Avoid name collisions in generated code (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2311">#2311</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/78a9576269a5b590c54686a8122e78e28135cd50">78a9576</a>)</li> <li>Preserve null conversion behavior for fieldless messages (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2312">#2312</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/df91652aa5cb1ee0204566252df85cbe752298a6">df91652</a>)</li> </ul> <h2>protobufjs: v7.6.2</h2> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.1...protobufjs-v7.6.2">7.6.2</a> (2026-05-30)</h2> <h3>Bug Fixes</h3> <ul> <li>Backport consistency and correctness fixes (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2294">#2294</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/a92f72e1cb731f06040a7917d3e041666d5f5601">a92f72e</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/protobufjs/protobuf.js/blob/protobufjs-v7.6.5/CHANGELOG.md">protobufjs's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.4...protobufjs-v7.6.5">7.6.5</a> (2026-07-04)</h2> <h3>Bug Fixes</h3> <ul> <li>handle EOF during options parsing (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2352">#2352</a>) (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2356">#2356</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/10fba6d54815ceecca8a06b9a6db490c8f5d2217">10fba6d</a>)</li> </ul> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.3...protobufjs-v7.6.4">7.6.4</a> (2026-06-12)</h2> <h3>Bug Fixes</h3> <ul> <li>Reconfigure and speed up CI (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2329">#2329</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/574f761c05b007dab6595ca1eaed86436579ba3f">574f761</a>)</li> <li>Remove inquire submodule (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2327">#2327</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/06ddd07064329032aae6db586e2d54938b591792">06ddd07</a>)</li> </ul> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.2...protobufjs-v7.6.3">7.6.3</a> (2026-06-09)</h2> <h3>Bug Fixes</h3> <ul> <li>Avoid name collisions in generated code (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2311">#2311</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/78a9576269a5b590c54686a8122e78e28135cd50">78a9576</a>)</li> <li>Preserve null conversion behavior for fieldless messages (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2312">#2312</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/df91652aa5cb1ee0204566252df85cbe752298a6">df91652</a>)</li> </ul> <h2><a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.1...protobufjs-v7.6.2">7.6.2</a> (2026-05-30)</h2> <h3>Bug Fixes</h3> <ul> <li>Backport consistency and correctness fixes (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2294">#2294</a>) (<a href="https://github.com/protobufjs/protobuf.js/commit/a92f72e1cb731f06040a7917d3e041666d5f5601">a92f72e</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/protobufjs/protobuf.js/commit/89048ba0bbf3ed78f77199102f0614dafc2b4860"><code>89048ba</code></a> chore: release protobufjs-v7.x (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2357">#2357</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/10fba6d54815ceecca8a06b9a6db490c8f5d2217"><code>10fba6d</code></a> fix: handle EOF during options parsing (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2352">#2352</a>) (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2356">#2356</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/f8f64efbfc5b52997beb7549e7ea722704320cb1"><code>f8f64ef</code></a> chore: release protobufjs-v7.x (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2330">#2330</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/574f761c05b007dab6595ca1eaed86436579ba3f"><code>574f761</code></a> fix: Reconfigure and speed up CI (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2329">#2329</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/06ddd07064329032aae6db586e2d54938b591792"><code>06ddd07</code></a> fix: Remove inquire submodule (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2327">#2327</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/1d3796d7d29830c73eec792ccbe769be6aa020ac"><code>1d3796d</code></a> chore: release protobufjs-v7.x (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2317">#2317</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/df91652aa5cb1ee0204566252df85cbe752298a6"><code>df91652</code></a> fix: Preserve null conversion behavior for fieldless messages (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2312">#2312</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/78a9576269a5b590c54686a8122e78e28135cd50"><code>78a9576</code></a> fix: Avoid name collisions in generated code (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2311">#2311</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/ec90ef9ccc30fffe6ea9ea37e45781071898229d"><code>ec90ef9</code></a> chore: release protobufjs-v7.x (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2295">#2295</a>)</li> <li><a href="https://github.com/protobufjs/protobuf.js/commit/a92f72e1cb731f06040a7917d3e041666d5f5601"><code>a92f72e</code></a> fix: Backport consistency and correctness fixes (<a href="https://redirect.github.com/protobufjs/protobuf.js/issues/2294">#2294</a>)</li> <li>See full diff in <a href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.1...protobufjs-v7.6.5">compare view</a></li> </ul> </details> <br /> [](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) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
6af0ad7952 |
chore: bump @fontsource-variable/geist-mono from 5.2.7 to 5.3.0 in /site (#28200)
Bumps [@fontsource-variable/geist-mono](https://github.com/fontsource/font-files/tree/HEAD/fonts/variable/geist-mono) from 5.2.7 to 5.3.0. <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/fontsource/font-files/commits/HEAD/fonts/variable/geist-mono">compare view</a></li> </ul> </details> <br /> [](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) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
8e5211473f |
chore: bump tzdata from 1.0.46 to 1.0.50 in /site (#28199)
Bumps [tzdata](https://github.com/rogierschouten/tzdata-generate) from 1.0.46 to 1.0.50. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/41ba68e0dcd502a173aa8564dc7723a1eb819c58"><code>41ba68e</code></a> tzdata 2026c</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/57262ed943fbb62d8c23fb8a28a4c755fa9e7042"><code>57262ed</code></a> security fixes</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/a0b839f84fee13935e3ceadb857f118ace3b6887"><code>a0b839f</code></a> Update README.md</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/80b6adcf0670cc72df65a8cfda6fd20160213d26"><code>80b6adc</code></a> Update README.md</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/856c38fc89b471eff4c0d2bc6b8919feda48d20e"><code>856c38f</code></a> tzdata 2026b</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/a176aa9f20e398dc5044ae297cedc5451937f35e"><code>a176aa9</code></a> upgrade dependencies</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/61476aa3ea4a542ab616c8b5dd54099a8d842663"><code>61476aa</code></a> audit fix</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/156d450592f7c6dde94782a0c0497ffb84e90252"><code>156d450</code></a> tzdata 2026a</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/c56a60d642ad74215e1a4803c8d0ab3057addec3"><code>c56a60d</code></a> tz data 2025c</li> <li><a href="https://github.com/rogierschouten/tzdata-generate/commit/8126bcf20d661516ec4c9acf0c51945ad3e920b2"><code>8126bcf</code></a> tz data 2025c</li> <li>Additional commits viewable in <a href="https://github.com/rogierschouten/tzdata-generate/compare/v1.0.46...v1.0.50">compare view</a></li> </ul> </details> <br /> [](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) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
0350bfd2ea |
refactor(site): show audit log retention and Premium paywall on observability settings (#27947)
The Audit Logging section on deployment observability settings only showed a badge or an info alert, with no actual setting underneath. When audit logging is entitled, show the Audit Logs Retention option. When it is not, show the shared Premium paywall instead of the inline alert. |
||
|
|
41d2ecec0b |
feat(site): gate appearance settings behind Premium paywall (#27948)
Appearance settings previously showed a Premium paywall badge above still-visible branding and announcement banner forms. When appearance is not entitled, show only the shared Premium paywall. When entitled, show the branding form and announcement banners. |
||
|
|
c2368f8ecf |
chore: bump @pierre/diffs from 1.3.3 to 1.3.5 in /site (#28198)
Bumps @pierre/diffs from 1.3.3 to 1.3.5. [](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) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
ad278c6e35 |
chore: bump axios from 1.18.1 to 1.19.0 in /site (#28197)
Bumps [axios](https://github.com/axios/axios) from 1.18.1 to 1.19.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/axios/axios/releases">axios's releases</a>.</em></p> <blockquote> <h2>v1.19.0 - July 22, 2026</h2> <p>This release raises the form-data security floor, adds configuration and type-system capabilities, and fixes NO_PROXY matching, interceptor errors, progress reporting, and serialization edge cases.</p> <h2>🔒 Security Fixes</h2> <ul> <li>Multipart Form Data: Raised the form-data dependency floor to ^4.0.6, preventing fresh installations from resolving versions affected by the CRLF injection vulnerability GHSA-hmw2-7cc7-3qxx (<a href="https://github.com/advisories/GHSA-hmw2-7cc7-3qxx">https://github.com/advisories/GHSA-hmw2-7cc7-3qxx</a>). (<a href="https://redirect.github.com/axios/axios/issues/11028">#11028</a>)</li> </ul> <h2>🚀 New Features</h2> <ul> <li>Configuration Extensibility: Preserved own-enumerable symbol-keyed fields through mergeConfig and added a generic params type across public TypeScript declarations, responses, errors, adapters, and serializers. (<a href="https://redirect.github.com/axios/axios/issues/11043">#11043</a>, <a href="https://redirect.github.com/axios/axios/issues/11081">#11081</a>)</li> <li>Header Parameter Parsing: Added the opt-in AxiosHeaders.parseParameters() parser for quote-aware, RFC-style HTTP parameter parsing while preserving legacy parsing behavior. (<a href="https://redirect.github.com/axios/axios/issues/11051">#11051</a>)</li> <li>HTTP Status Codes: Added the missing Cloudflare 520 WebServerReturnsAnUnknownError status and matching ESM/CJS declarations. (<a href="https://redirect.github.com/axios/axios/issues/11067">#11067</a>)</li> </ul> <h2>🐛 Bug Fixes</h2> <ul> <li>Form Data Conversion: Limited formDataToJSON path splitting to dot and bracket notation, preserving literal punctuation in keys, and removed browser-facing Buffer.from usage from toFormData to avoid unnecessary polyfills. (<a href="https://redirect.github.com/axios/axios/issues/11006">#11006</a>, <a href="https://redirect.github.com/axios/axios/issues/11018">#11018</a>)</li> <li>Proxy Bypass: Canonicalized IPv4 shorthand, octal, and hexadecimal forms during NO_PROXY matching and honored * entries within comma- or space-separated bypass lists. (<a href="https://redirect.github.com/axios/axios/issues/11029">#11029</a>, <a href="https://redirect.github.com/axios/axios/issues/11053">#11053</a>)</li> <li>Cancellation: Propagated already-aborted input signals immediately when composing abort signals. (<a href="https://redirect.github.com/axios/axios/issues/11035">#11035</a>)</li> <li>Header Handling: Preserved empty first values for duplicate singleton headers and made AxiosHeaders#getSetCookie() consistently return arrays for present values. (<a href="https://redirect.github.com/axios/axios/issues/11036">#11036</a>, <a href="https://redirect.github.com/axios/axios/issues/11037">#11037</a>)</li> <li>URL Handling: Included normalized, safely redacted offending URLs in malformed-protocol errors and removed repeated trailing slashes when combining base URLs. (<a href="https://redirect.github.com/axios/axios/issues/11024">#11024</a>, <a href="https://redirect.github.com/axios/axios/issues/11038">#11038</a>)</li> <li>Progress Events: Clamped malformed negative progress values to zero and ensured final Node.js download progress events are delivered before streamed responses close. (<a href="https://redirect.github.com/axios/axios/issues/11039">#11039</a>, <a href="https://redirect.github.com/axios/axios/issues/11040">#11040</a>)</li> <li>Error and JSON Serialization: Serialized Set values as arrays in JSON-compatible snapshots and synthesized useful AxiosError messages from otherwise-empty AggregateError instances. (<a href="https://redirect.github.com/axios/axios/issues/11044">#11044</a>, <a href="https://redirect.github.com/axios/axios/issues/11059">#11059</a>)</li> <li>Content-Length Enforcement: Corrected base64 data: URL size estimation so maxContentLength is enforced consistently by the HTTP and Fetch adapters. (<a href="https://redirect.github.com/axios/axios/issues/11061">#11061</a>)</li> <li>Synchronous Interceptors: Prevented requests from being dispatched after synchronous request interceptors fail unless their paired rejection handler resolves successfully. (<a href="https://redirect.github.com/axios/axios/issues/11071">#11071</a>)</li> </ul> <h2>🔧 Maintenance & Chores</h2> <ul> <li>Dependencies: Updated development and test tooling, the docs fixture's Axios version, and GitHub Actions integrations including Checkout, Setup Node, Setup Deno, and Zizmor. (<a href="https://redirect.github.com/axios/axios/issues/11031">#11031</a>, <a href="https://redirect.github.com/axios/axios/issues/11055">#11055</a>, <a href="https://redirect.github.com/axios/axios/issues/11056">#11056</a>, <a href="https://redirect.github.com/axios/axios/issues/11058">#11058</a>, <a href="https://redirect.github.com/axios/axios/issues/11079">#11079</a>, <a href="https://redirect.github.com/axios/axios/issues/11080">#11080</a>, <a href="https://redirect.github.com/axios/axios/issues/11088">#11088</a>, <a href="https://redirect.github.com/axios/axios/issues/11089">#11089</a>, <a href="https://redirect.github.com/axios/axios/issues/11090">#11090</a>)</li> <li>Build Outputs: Limited sourcemap generation to published minified bundles, removing broken map references from non-minified builds. (<a href="https://redirect.github.com/axios/axios/issues/11054">#11054</a>)</li> <li>Form Data Internals: Centralized FormData header handling and made the Node.js adapter tolerate getHeaders() returning undefined under the content-only policy. (<a href="https://redirect.github.com/axios/axios/issues/11062">#11062</a>)</li> <li>Developer Experience: Ignored common local AI-tooling directories and fixed a constant-reassignment crash when the development sandbox serves its root path. (<a href="https://redirect.github.com/axios/axios/issues/11032">#11032</a>, <a href="https://redirect.github.com/axios/axios/issues/11073">#11073</a>)</li> <li>Documentation: Updated sponsor information, clarified that baseURL is not a path-security boundary, scoped provenance claims to attested releases, and corrected the configuration-defaults documentation. (<a href="https://redirect.github.com/axios/axios/issues/11041">#11041</a>, <a href="https://redirect.github.com/axios/axios/issues/11068">#11068</a>, <a href="https://redirect.github.com/axios/axios/issues/11076">#11076</a>, <a href="https://redirect.github.com/axios/axios/issues/11078">#11078</a>)</li> <li>Publishing: Simplified v1 publishing to use the npm version bundled with Node.js 26 and updated package metadata for the 1.19.0 release. (<a href="https://redirect.github.com/axios/axios/issues/11083">#11083</a>, <a href="https://redirect.github.com/axios/axios/issues/11095">#11095</a>)</li> </ul> <h2>🌟 New Contributors</h2> <p>We are thrilled to welcome our new contributors. Thank you for helping improve Axios:</p> <ul> <li><a href="https://github.com/afonsojramos"><code>@afonsojramos</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11028">#11028</a>)</li> <li><a href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11006">#11006</a>)</li> <li><a href="https://github.com/yassertawfik4"><code>@yassertawfik4</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11024">#11024</a>)</li> <li><a href="https://github.com/AnandSundar"><code>@AnandSundar</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11029">#11029</a>)</li> <li><a href="https://github.com/lin-hongkuan"><code>@lin-hongkuan</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11035">#11035</a>)</li> <li><a href="https://github.com/Wali007-lab"><code>@Wali007-lab</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11054">#11054</a>)</li> <li><a href="https://github.com/magicdawn"><code>@magicdawn</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11043">#11043</a>)</li> <li><a href="https://github.com/andrewkernel"><code>@andrewkernel</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11053">#11053</a>)</li> <li><a href="https://github.com/Sagargupta16"><code>@Sagargupta16</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11059">#11059</a>)</li> <li><a href="https://github.com/Rpaudel379"><code>@Rpaudel379</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11078">#11078</a>)</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.19.0 — July 22, 2026</h2> <p>This release raises the form-data security floor, adds configuration and type-system capabilities, and fixes NO_PROXY matching, interceptor errors, progress reporting, and serialization edge cases.</p> <h2>🔒 Security Fixes</h2> <ul> <li>Multipart Form Data: Raised the form-data dependency floor to ^4.0.6, preventing fresh installations from resolving versions affected by the CRLF injection vulnerability GHSA-hmw2-7cc7-3qxx (<a href="https://github.com/advisories/GHSA-hmw2-7cc7-3qxx">https://github.com/advisories/GHSA-hmw2-7cc7-3qxx</a>). (<a href="https://redirect.github.com/axios/axios/issues/11028">#11028</a>)</li> </ul> <h2>🚀 New Features</h2> <ul> <li>Configuration Extensibility: Preserved own-enumerable symbol-keyed fields through mergeConfig and added a generic params type across public TypeScript declarations, responses, errors, adapters, and serializers. (<a href="https://redirect.github.com/axios/axios/issues/11043">#11043</a>, <a href="https://redirect.github.com/axios/axios/issues/11081">#11081</a>)</li> <li>Header Parameter Parsing: Added the opt-in AxiosHeaders.parseParameters() parser for quote-aware, RFC-style HTTP parameter parsing while preserving legacy parsing behavior. (<a href="https://redirect.github.com/axios/axios/issues/11051">#11051</a>)</li> <li>HTTP Status Codes: Added the missing Cloudflare 520 WebServerReturnsAnUnknownError status and matching ESM/CJS declarations. (<a href="https://redirect.github.com/axios/axios/issues/11067">#11067</a>)</li> </ul> <h2>🐛 Bug Fixes</h2> <ul> <li> <p>Form Data Conversion: Limited formDataToJSON path splitting to dot and bracket notation, preserving literal punctuation in keys, and removed browser-facing Buffer.from usage from toFormData to avoid unnecessary polyfills. (<a href="https://redirect.github.com/axios/axios/issues/11006">#11006</a>, <a href="https://redirect.github.com/axios/axios/issues/11018">#11018</a>)</p> </li> <li> <p>Proxy Bypass: Canonicalized IPv4 shorthand, octal, and hexadecimal forms during NO_PROXY matching and honored * entries within comma- or space-separated bypass lists. (<a href="https://redirect.github.com/axios/axios/issues/11029">#11029</a>, <a href="https://redirect.github.com/axios/axios/issues/11053">#11053</a>)</p> </li> <li> <p>Cancellation: Propagated already-aborted input signals immediately when composing abort signals. (<a href="https://redirect.github.com/axios/axios/issues/11035">#11035</a>)</p> </li> <li> <p>Header Handling: Preserved empty first values for duplicate singleton headers and made AxiosHeaders#getSetCookie() consistently return arrays for present values. (<a href="https://redirect.github.com/axios/axios/issues/11036">#11036</a>, <a href="https://redirect.github.com/axios/axios/issues/11037">#11037</a>)</p> </li> <li> <p>URL Handling: Included normalized, safely redacted offending URLs in malformed-protocol errors and removed repeated trailing slashes when combining base URLs. (<a href="https://redirect.github.com/axios/axios/issues/11008">#11008</a>, <a href="https://redirect.github.com/axios/axios/issues/11038">#11038</a>)</p> </li> <li> <p>Progress Events: Clamped malformed negative progress values to zero and ensured final Node.js download progress events are delivered before streamed responses close. (<a href="https://redirect.github.com/axios/axios/issues/11039">#11039</a>, <a href="https://redirect.github.com/axios/axios/issues/11040">#11040</a>)</p> </li> <li> <p>Error and JSON Serialization: Serialized Set values as arrays in JSON-compatible snapshots and synthesized useful AxiosError messages from otherwise-empty AggregateError instances. (<a href="https://redirect.github.com/axios/axios/issues/11044">#11044</a>, <a href="https://redirect.github.com/axios/axios/issues/11059">#11059</a>)</p> </li> <li> <p>Content-Length Enforcement: Corrected base64 data: URL size estimation so maxContentLength is enforced consistently by the HTTP and Fetch adapters. (<a href="https://redirect.github.com/axios/axios/issues/11061">#11061</a>)</p> </li> <li> <p>Synchronous Interceptors: Prevented requests from being dispatched after synchronous request interceptors fail unless their paired rejection handler resolves successfully. (<a href="https://redirect.github.com/axios/axios/issues/11071">#11071</a>)</p> </li> </ul> <h2>🔧 Maintenance & Chores</h2> <ul> <li>Dependencies: Updated development and test tooling, the docs fixture's Axios version, and GitHub Actions integrations including Checkout, Setup Node, Setup Deno, and Zizmor. (<a href="https://redirect.github.com/axios/axios/issues/11031">#11031</a>, <a href="https://redirect.github.com/axios/axios/issues/11055">#11055</a>, <a href="https://redirect.github.com/axios/axios/issues/11056">#11056</a>, <a href="https://redirect.github.com/axios/axios/issues/11058">#11058</a>, <a href="https://redirect.github.com/axios/axios/issues/11079">#11079</a>, <a href="https://redirect.github.com/axios/axios/issues/11080">#11080</a>, <a href="https://redirect.github.com/axios/axios/issues/11088">#11088</a>, <a href="https://redirect.github.com/axios/axios/issues/11089">#11089</a>, <a href="https://redirect.github.com/axios/axios/issues/11090">#11090</a>)</li> <li>Build Outputs: Limited sourcemap generation to published minified bundles, removing broken map references from non-minified builds. (<a href="https://redirect.github.com/axios/axios/issues/11054">#11054</a>)</li> <li>Form Data Internals: Centralized FormData header handling and made the Node.js adapter tolerate getHeaders() returning undefined under the content-only policy. (<a href="https://redirect.github.com/axios/axios/issues/11062">#11062</a>)</li> <li>Developer Experience: Ignored common local AI-tooling directories and fixed a constant-reassignment crash when the development sandbox serves its root path. (<a href="https://redirect.github.com/axios/axios/issues/11032">#11032</a>, <a href="https://redirect.github.com/axios/axios/issues/11073">#11073</a>)</li> <li>Documentation: Updated sponsor information, clarified that baseURL is not a path-security boundary, scoped provenance claims to attested releases, and corrected the configuration-defaults documentation. (<a href="https://redirect.github.com/axios/axios/issues/11041">#11041</a>, <a href="https://redirect.github.com/axios/axios/issues/11068">#11068</a>, <a href="https://redirect.github.com/axios/axios/issues/11076">#11076</a>, <a href="https://redirect.github.com/axios/axios/issues/11078">#11078</a>)</li> <li>Publishing: Simplified v1 publishing to use the npm version bundled with Node.js 26 and updated package metadata for the 1.19.0 release. (<a href="https://redirect.github.com/axios/axios/issues/11083">#11083</a>, <a href="https://redirect.github.com/axios/axios/issues/11095">#11095</a>)</li> </ul> <h2>🌟 New Contributors</h2> <p>We are thrilled to welcome our new contributors. Thank you for helping improve Axios:</p> <ul> <li><a href="https://github.com/afonsojramos"><code>@afonsojramos</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11028">#11028</a>)</li> <li><a href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11006">#11006</a>)</li> <li><a href="https://github.com/yassertawfik4"><code>@yassertawfik4</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11024">#11024</a>)</li> <li><a href="https://github.com/AnandSundar"><code>@AnandSundar</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11029">#11029</a>)</li> <li><a href="https://github.com/lin-hongkuan"><code>@lin-hongkuan</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11035">#11035</a>)</li> <li><a href="https://github.com/Wali007-lab"><code>@Wali007-lab</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11054">#11054</a>)</li> <li><a href="https://github.com/magicdawn"><code>@magicdawn</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11043">#11043</a>)</li> <li><a href="https://github.com/andrewkernel"><code>@andrewkernel</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11053">#11053</a>)</li> <li><a href="https://github.com/Sagargupta16"><code>@Sagargupta16</code></a> (<a href="https://redirect.github.com/axios/axios/issues/11059">#11059</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/axios/axios/commit/311fcc5c8d989b7248f05d390bb83bfbfb009977"><code>311fcc5</code></a> chore(release): prepare release 1.19.0 (<a href="https://redirect.github.com/axios/axios/issues/11095">#11095</a>)</li> <li><a href="https://github.com/axios/axios/commit/cb4fd743abd1c595761c8eda25d1323fc62a3b93"><code>cb4fd74</code></a> chore(deps): bump axios from 1.16.1 to 1.18.1 in /docs (<a href="https://redirect.github.com/axios/axios/issues/11088">#11088</a>)</li> <li><a href="https://github.com/axios/axios/commit/004c93a9d2acd0561c498eff7bb4431c6bad78af"><code>004c93a</code></a> chore(deps): bump actions/setup-node from 6.4.0 to 7.0.0 in the github-action...</li> <li><a href="https://github.com/axios/axios/commit/122edde91b1183572f4ba399b5b6bc4e3b989718"><code>122edde</code></a> chore(deps-dev): bump the development_dependencies group with 3 updates (<a href="https://redirect.github.com/axios/axios/issues/11089">#11089</a>)</li> <li><a href="https://github.com/axios/axios/commit/c44f8d0a910df99486da9175584b99f56a94a73b"><code>c44f8d0</code></a> ci: use bundled npm for v1 publish (<a href="https://redirect.github.com/axios/axios/issues/11083">#11083</a>)</li> <li><a href="https://github.com/axios/axios/commit/878bb29de570765b0d4c0970e30400d9ea9399f7"><code>878bb29</code></a> fix(sandbox): resolve TypeError on constant variable path assignment (<a href="https://redirect.github.com/axios/axios/issues/11073">#11073</a>)</li> <li><a href="https://github.com/axios/axios/commit/a092bae50d1884782151b2fcea12974d6da6e376"><code>a092bae</code></a> fix(core): synchronous interceptors swallow errors and proceed with request (...</li> <li><a href="https://github.com/axios/axios/commit/3041b8fd1daf17404d1bad1f9d94026ea5ab400b"><code>3041b8f</code></a> feat(HttpStatusCode): add missing 520 status code (<a href="https://redirect.github.com/axios/axios/issues/11067">#11067</a>)</li> <li><a href="https://github.com/axios/axios/commit/58b16c88f0bddf1fadb321aed58ba3f49a90481b"><code>58b16c8</code></a> refactor(helpers): extract duplicated setFormDataHeaders into a shared helper...</li> <li><a href="https://github.com/axios/axios/commit/3077e62097726d22ba30f1cb847d7a07050e339a"><code>3077e62</code></a> feat(types): Allow the Params property to be typed, instead of <code>any</code> (<a href="https://redirect.github.com/axios/axios/issues/11081">#11081</a>)</li> <li>Additional commits viewable in <a href="https://github.com/axios/axios/compare/v1.18.1...v1.19.0">compare view</a></li> </ul> </details> <br /> [](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) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
cdaf7d4bd7 |
chore: bump @testing-library/user-event from 14.6.1 to 14.6.3 in /site (#28196)
Bumps [@testing-library/user-event](https://github.com/testing-library/user-event) from 14.6.1 to 14.6.3. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/testing-library/user-event/releases">@testing-library/user-event's releases</a>.</em></p> <blockquote> <h2>v14.6.3</h2> <h2><a href="https://github.com/testing-library/user-event/compare/v14.6.2...v14.6.3">14.6.3</a> (2026-08-03)</h2> <h3>Bug Fixes</h3> <ul> <li><strong>release:</strong> manually release a patch version (<a href="https://redirect.github.com/testing-library/user-event/issues/1321">#1321</a>) (<a href="https://github.com/testing-library/user-event/commit/1d18b1fae589eeed8e08838672a4c2de0dcc2b36">1d18b1f</a>), closes <a href="https://redirect.github.com/testing-library/user-event/issues/1317">#1317</a></li> </ul> <h2>v14.6.2</h2> <h2><a href="https://github.com/testing-library/user-event/compare/v14.6.1...v14.6.2">14.6.2</a> (2026-08-03)</h2> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/testing-library/user-event/commit/1d18b1fae589eeed8e08838672a4c2de0dcc2b36"><code>1d18b1f</code></a> fix(release): manually release a patch version (<a href="https://redirect.github.com/testing-library/user-event/issues/1321">#1321</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/232f3e6f4f92459c02161d156a70bddd13a59eaa"><code>232f3e6</code></a> docs: add migration note and clean up README badges (<a href="https://redirect.github.com/testing-library/user-event/issues/1320">#1320</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/83e2b2261b40f5f08296eaf5af3d42018e6681ed"><code>83e2b22</code></a> ci: remove deprecated CodeSandbox CI (<a href="https://redirect.github.com/testing-library/user-event/issues/1318">#1318</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/e8da81953bd9b48512a1e4ce9b73cc36aeaeee37"><code>e8da819</code></a> ci: publish to npm via OIDC trusted publishing (<a href="https://redirect.github.com/testing-library/user-event/issues/1317">#1317</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/13fa4bc1f0dedeb866a8730fa357229832437418"><code>13fa4bc</code></a> ci: stop lint errors from blocking release (<a href="https://redirect.github.com/testing-library/user-event/issues/1316">#1316</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/c3cec1832f180b6d1dcb7c5d2b0771339dd5e848"><code>c3cec18</code></a> chore(ci): make releases work with full git history (<a href="https://redirect.github.com/testing-library/user-event/issues/1315">#1315</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/ebab6c6e81e7022af7afa5aacd07d01626895eb8"><code>ebab6c6</code></a> add Liadshiran as a contributor for doc (<a href="https://redirect.github.com/testing-library/user-event/issues/1300">#1300</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/ec470bfd55ab7a741ce2a5b71e98c0f5686ac915"><code>ec470bf</code></a> docs: fix wrong default enum value (<a href="https://redirect.github.com/testing-library/user-event/issues/1298">#1298</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/ba79c2f9a58d5927725fee506210d279fde218b5"><code>ba79c2f</code></a> chore: upgrade node version in csb (<a href="https://redirect.github.com/testing-library/user-event/issues/1299">#1299</a>)</li> <li><a href="https://github.com/testing-library/user-event/commit/63ac399e06bd8f2397a6c581915acd29235f2d38"><code>63ac399</code></a> fix: allow reassignment of <code>HTMLElement.prototype.focus</code> and <code>.blur</code> (<a href="https://redirect.github.com/testing-library/user-event/issues/1265">#1265</a>)</li> <li>Additional commits viewable in <a href="https://github.com/testing-library/user-event/compare/v14.6.1...v14.6.3">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new releaser for <code>@testing-library/user-event</code> since your current version.</p> </details> <br /> [](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) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
2e79169bdb |
chore: bump vite from 8.2.0 to 8.2.1 in /site in the vite group across 1 directory (#28191)
Bumps the vite group with 1 update in the /site directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite). Updates `vite` from 8.2.0 to 8.2.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/releases">vite's releases</a>.</em></p> <blockquote> <h2>plugin-legacy@8.2.1</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.2.1/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.2.1</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.2.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md">vite's changelog</a>.</em></p> <blockquote> <h2><!-- raw HTML omitted --><a href="https://github.com/vitejs/vite/compare/v8.2.0...v8.2.1">8.2.1</a> (2026-08-06)<!-- raw HTML omitted --></h2> <h3>Bug Fixes</h3> <ul> <li><strong>build:</strong> make client chunkImportMap work with <code>sharedPlugins: true</code> (<a href="https://redirect.github.com/vitejs/vite/issues/23184">#23184</a>) (<a href="https://github.com/vitejs/vite/commit/15f03073c915d6ffb9a1fda447ef66b02bf5cde8">15f0307</a>)</li> <li><strong>bundled-dev:</strong> inject client script tag before chunk scripts (<a href="https://redirect.github.com/vitejs/vite/issues/23161">#23161</a>) (<a href="https://github.com/vitejs/vite/commit/eac0cc84aa2472a85a19ee84561c1ba71e381a55">eac0cc8</a>)</li> <li><strong>css:</strong> don't re-run lightningcss visitor during minify (fix <a href="https://redirect.github.com/vitejs/vite/issues/23146">#23146</a>) (<a href="https://redirect.github.com/vitejs/vite/issues/23147">#23147</a>) (<a href="https://github.com/vitejs/vite/commit/de041a79b05a0be965c874592fe2c1505bcd48df">de041a7</a>)</li> <li><strong>deps:</strong> update all non-major dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/23136">#23136</a>) (<a href="https://github.com/vitejs/vite/commit/14454fd8c9a399bc3fdc193e28465b6fcf001e4d">14454fd</a>)</li> <li><strong>deps:</strong> update rolldown-related dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/23070">#23070</a>) (<a href="https://github.com/vitejs/vite/commit/7ac6f7f590747bbdab9958e2c016e3dd04f10542">7ac6f7f</a>)</li> <li>don't mutate the user config when resolving the lib entry from the top-level <code>input</code> (<a href="https://redirect.github.com/vitejs/vite/issues/23135">#23135</a>) (<a href="https://github.com/vitejs/vite/commit/b4bf59686a7ac238929e91a6e1708c739b843a2f">b4bf596</a>)</li> <li>handle shebang ending with uncommon line terminators (<a href="https://redirect.github.com/vitejs/vite/issues/23038">#23038</a>) (<a href="https://github.com/vitejs/vite/commit/17f7b2f193a110d0b47742ad296d182cb4666ce7">17f7b2f</a>)</li> <li><strong>server:</strong> use a random port when port is 0 (<a href="https://redirect.github.com/vitejs/vite/issues/23158">#23158</a>) (<a href="https://github.com/vitejs/vite/commit/fddf4ea41de5f7889037a2f957438857ac12a260">fddf4ea</a>)</li> </ul> <h3>Performance Improvements</h3> <ul> <li><strong>css:</strong> look up pure CSS chunks through a Set (<a href="https://redirect.github.com/vitejs/vite/issues/23114">#23114</a>) (<a href="https://github.com/vitejs/vite/commit/1331b0b438b1e7193effb7d2341660bccb9c3155">1331b0b</a>)</li> </ul> <h3>Documentation</h3> <ul> <li><strong>build:</strong> fix incomplete <code>@default</code> for build.minify (<a href="https://redirect.github.com/vitejs/vite/issues/23177">#23177</a>) (<a href="https://github.com/vitejs/vite/commit/ef02435114c57d0422028f0e6987f3df8db72969">ef02435</a>)</li> </ul> <h3>Miscellaneous Chores</h3> <ul> <li><strong>deps:</strong> update dependency rolldown-plugin-dts to ^0.28.0 (<a href="https://redirect.github.com/vitejs/vite/issues/23137">#23137</a>) (<a href="https://github.com/vitejs/vite/commit/4adc1e7931d4beceb4e236d9a271d057c858a06f">4adc1e7</a>)</li> <li><strong>deps:</strong> update dependency strip-literal to v4 (<a href="https://redirect.github.com/vitejs/vite/issues/23140">#23140</a>) (<a href="https://github.com/vitejs/vite/commit/9db65ce63488ea8f08a3c98dcdc4282b17bd33ff">9db65ce</a>)</li> </ul> <h3>Code Refactoring</h3> <ul> <li><strong>bundled-dev:</strong> avoid injecting server values in the bundle (<a href="https://redirect.github.com/vitejs/vite/issues/22967">#22967</a>) (<a href="https://github.com/vitejs/vite/commit/23b8a088dec9dcc3f1c1353f2074f8644b3cc21f">23b8a08</a>)</li> <li><strong>bundled-dev:</strong> remove rolldown lazy stub module workaround (<a href="https://redirect.github.com/vitejs/vite/issues/23129">#23129</a>) (<a href="https://github.com/vitejs/vite/commit/e72036eed2e28936ed824971b18aeaa3900857f6">e72036e</a>)</li> </ul> <h3>Tests</h3> <ul> <li><strong>bundled-dev:</strong> enable sourcemap playgrounds (<a href="https://redirect.github.com/vitejs/vite/issues/23080">#23080</a>) (<a href="https://github.com/vitejs/vite/commit/c2155fe4d5c8d25fba3a7366d367e3296ae669fa">c2155fe</a>)</li> <li>reduce logs (<a href="https://redirect.github.com/vitejs/vite/issues/23138">#23138</a>) (<a href="https://github.com/vitejs/vite/commit/7673c02e53343ae9356c1f496c1c1da2eb732ac1">7673c02</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vitejs/vite/commit/421615865dad3ed39137d17281814fc78a41246c"><code>4216158</code></a> release: v8.2.1</li> <li><a href="https://github.com/vitejs/vite/commit/fddf4ea41de5f7889037a2f957438857ac12a260"><code>fddf4ea</code></a> fix(server): use a random port when port is 0 (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23158">#23158</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/de041a79b05a0be965c874592fe2c1505bcd48df"><code>de041a7</code></a> fix(css): don't re-run lightningcss visitor during minify (fix <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23146">#23146</a>) (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23147">#23147</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/15f03073c915d6ffb9a1fda447ef66b02bf5cde8"><code>15f0307</code></a> fix(build): make client chunkImportMap work with <code>sharedPlugins: true</code> (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23184">#23184</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/c2155fe4d5c8d25fba3a7366d367e3296ae669fa"><code>c2155fe</code></a> test(bundled-dev): enable sourcemap playgrounds (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23080">#23080</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/ef02435114c57d0422028f0e6987f3df8db72969"><code>ef02435</code></a> docs(build): fix incomplete <code>@default</code> for build.minify (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23177">#23177</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/eac0cc84aa2472a85a19ee84561c1ba71e381a55"><code>eac0cc8</code></a> fix(bundled-dev): inject client script tag before chunk scripts (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23161">#23161</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/23b8a088dec9dcc3f1c1353f2074f8644b3cc21f"><code>23b8a08</code></a> refactor(bundled-dev): avoid injecting server values in the bundle (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22967">#22967</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/e72036eed2e28936ed824971b18aeaa3900857f6"><code>e72036e</code></a> refactor(bundled-dev): remove rolldown lazy stub module workaround (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23129">#23129</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/14454fd8c9a399bc3fdc193e28465b6fcf001e4d"><code>14454fd</code></a> fix(deps): update all non-major dependencies (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23136">#23136</a>)</li> <li>Additional commits viewable in <a href="https://github.com/vitejs/vite/commits/v8.2.1/packages/vite">compare view</a></li> </ul> </details> <br /> [](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 <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
ea8ba0c678 |
refactor: remove MUI and Emotion (#27821)
> 🤖 This PR was modified by Coder Agents on behalf of Jake Howell. Until we meet again. ## Stack - #27636 - #27718 - #27719 - #27722 - #27723 - #27724 - #27728 - #27730 - #27732 - #27762 - #27763 - #27786 - #27787 - #27788 - #27789 - #27790 - #27791 - #27817 - #27820 - #28009 ## Final removal (`c39b664`) Removes the last of MUI and Emotion now that every surface has been migrated: - **Dependencies**: drops `@mui/material` and `@emotion/{cache,css,react,styled}` from `package.json` / `pnpm-lock.yaml`, and deletes the `@types/emotion.d.ts` and `@types/mui.d.ts` module augmentations. - **Theming**: replaces the Emotion `CacheProvider`, MUI `ThemeProvider` / `StyledEngineProvider`, and `CssBaseline` in `ThemeProvider` with a lightweight `theme/context.tsx` that exposes `ThemeContextProvider` and a `useTheme` hook. - **Global styles**: moves the base `body` styles (background, text color, font, antialiasing) that `CssBaseline` previously provided into `index.css`, and drops the temporary MUI modal/popover scrollbar-gutter workaround. - **Cleanup**: removes the MUI → shadcn / Emotion → Tailwind migration guidance from `site/AGENTS.md`, updates the Storybook `preview.tsx`, and adjusts assorted components (`Command`, `Slider`, `Switch`, `Tabs`, `SyntaxHighlighter`, timing charts) and theme files to consume the new context instead of MUI/Emotion. |
||
|
|
521c383f6b |
fix: repair stale chat agent bindings after workspace rebuild (#28152)
## Problem When a chat is bound to a workspace, chatd persists `chats.agent_id` pointing at a specific workspace agent, and it only rebinds on the next chat turn. A workspace stop/start creates a new agent with a new ID in the latest build, so the chat page resolves the stale agent ID to `undefined` and the right sidebar silently drops Terminal, Desktop, Browser, apps, and ports even though the workspace is running. The existing read-time enrichment only filled nil agent IDs and skipped stale non-nil ones, so refreshing did not help until the user sent another message. ## Fix - `coderd/exp_chats.go`: single-chat reads now repair agent IDs that no longer resolve in the workspace's latest build, using the same `agentselect.FindChatAgent` selection chatd uses. A repaired binding also carries the latest build's ID so the response never pairs the new agent with the previous build. Bindings that still resolve are preserved, and repair stays best-effort and response-only (no write-on-read). List reads keep the previous nil-fill-only behavior because validating existing bindings would cost a per-workspace authorization lookup per listed chat. - `site/src/pages/AgentsPage/AgentChatPage.tsx`: the workspace watch update handler detects when a running workspace's latest build no longer contains the chat's bound agent and invalidates the chat query once per chat/build/binding key for immediate recovery, and the chat query polls every 30 seconds while the binding remains unresolved so a transiently failed repair retries even when an idle workspace publishes no further watch events. The watch stream replays the current workspace on every (re)connect, so this covers rebuilds that happen while the page is open or disconnected; page loads are covered by the server-side repair. The workspace-watcher bailout now also keys on `latest_build.id` so a rebuild propagates while the page is open. - `site/src/api/queries/chats.ts`: chat watch events replay the persisted (pre-repair) binding, so the summary merge adopts a snapshot's `build_id` only when the snapshot agrees on `agent_id`, keeping the repaired agent/build pair atomic in the caches. ## Testing - `go test ./coderd -run TestEnrichChatAgentIDs` covering repair, keep-valid, selection-error, list-mode-skips-bound, and no-workspaces cases. - Storybook interaction story `RecoversSidebarAfterWorkspaceRebuild` exercising the watch-event to chat-refetch to sidebar-recovery flow (verified red without the invalidation, green with it). - `pnpm test AgentChatPage.test.ts` covering the binding-resolution predicate. > Mux created this PR on Mike's behalf. |
||
|
|
57dc47dc42 |
feat(site): migrate agent chat scrolling (#28130)
Replace the Agents chat's inverse scroll container and sticky user-message overlays with the stock MessageScroller from `@shadcn/react@0.3.0`. Transcript rows now render as direct MessageScroller Items with stable server-backed identities. Only the latest active user turn is a scroll anchor, older history preserves the reading position when prepended, and the package owns follow mode, prompt navigation, and the `Scroll to bottom` control. The integration uses the upstream component hierarchy without patches, bridges, or application-owned scroll correction. Depends on #28079. <details> <summary>Implementation notes</summary> - Use `MessageScroller.Provider`, `Root`, `Viewport`, `Content`, `Item`, and `Button` directly. - Keep durable row IDs stable across pagination; the live assistant uses an ephemeral row until its durable message arrives. - Load additional history from MessageScroller's start-edge state, including underfilled transcripts and retry after a page error. - Remove inverse scrolling, sticky message copies, scroll refs, forced scroll commands, and `react-infinite-scroll-component`. </details> Generated by Coder Agents on behalf of @DanielleMaywood. |
||
|
|
7617b6bdcc |
refactor(site): render live assistant output as a chat timeline row (#28079)
Refactor the Agents chat timeline so live assistant output renders as a timeline row through the same components as durable messages, ahead of the stacked MessageScroller migration in #28130. `ConversationTimeline`'s block rendering is extracted into `MessageBlocks`, the streaming/durable assistant split collapses into a shared `AssistantOutput`, and `LiveStreamTail` shrinks to the empty state and terminal failure callout. Row keys are plain `message:<id>` strings; the live assistant row is a separate ephemeral row. This PR does not change scrolling behavior and adds no backend, API, or database fields. <details> <summary>Implementation notes</summary> - Extract `BlockList` and friends from `ConversationTimeline` into `MessageBlocks` (pure move). - Replace `StreamingOutput` with `AssistantOutput`, used for both live and durable assistant rows. - Render the live assistant as a timeline row via `assignTimelineRows` instead of separate transient content below the transcript. - Keep existing transcript grouping, prompt navigation, and the current scroll container unchanged; the scroller swap happens in #28130. </details> Generated by Coder Agents on behalf of @DanielleMaywood. |
||
|
|
b26f4c0e03 |
feat: DEVEX-751 updated premiumpaywall component (#28070)
* implements the supergraphic component, to show a minified webp theme-aware version of the supergraphic * refine the PaywallPremium into separate PaywallSmall component * paywall no long includes link to docs for component; will be part of DEVEX-742 * appearance and custom roles page uses PaywallSmall <img width="1509" height="676" alt="Screenshot 2026-08-12 at 7 49 54 AM" src="https://github.com/user-attachments/assets/17cd1a16-acc8-415a-819d-bdb9259fdaf9" /> <img width="1499" height="702" alt="Screenshot 2026-08-11 at 12 46 55 PM" src="https://github.com/user-attachments/assets/05cd628a-c8c1-4b1c-a4c9-318814eec428" /> <img width="1466" height="549" alt="Screenshot 2026-08-11 at 12 44 43 PM" src="https://github.com/user-attachments/assets/f0bb0c0e-7702-41a0-a718-78a637c9f4e9" /> <img width="1715" height="652" alt="Screenshot 2026-08-12 at 11 25 21 AM" src="https://github.com/user-attachments/assets/55dedd2c-d44c-4cd0-a425-fbde4452f622" /> |
||
|
|
e1fa247e59 | feat: redirect to the template builder after first time setup (#27670) |