mirror of
https://github.com/coder/coder.git
synced 2026-10-31 19:36:41 +08:00
45f2eb48ccf2a2e18d9ef6665ccfaf62b42d3e4b
117
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
845790e652 |
feat: enable Coder Agents for organization members (#28186)
## Summary - make Coder Agents available to organization members without a separate built-in role - remove the obsolete role from backend and frontend role surfaces - update authorization, UI, documentation, and regression coverage ## Database note This PR intentionally ships no migration so it backports cleanly across diverged migration numbers. Stale `agents-access` grants may remain in user role arrays and org default member roles; the retired name is treated as a grant of nothing (role expansion drops it, assignment validation ignores it, and the name stays reserved). A follow-up PR will add the data cleanup migration. ## Validation - `make gen` - `make lint` - repository pre-commit checks - targeted RBAC, migration, chat API, enterprise, site, Storybook, and race tests - `git diff --check` ## Rollback note Rolling back the deployment restores the previous behavior directly: no data changed, and older binaries still resolve any lingering `agents-access` grants. > Mux created this pull request on Mike's behalf. |
||
|
|
ce59a86a81 |
docs: fix Coder Agents tool tables, search filters, attachments, template ranking (#28575)
Corrects four independent factual errors in the Coder Agents documentation, each verified against the current implementation. - **Missing tools in the tool tables.** `stop_workspace` was absent from the built-in tool table in `docs/ai-coder/agents/index.md` and the platform tool table in `docs/ai-coder/agents/architecture.md`, and from the root-chat-only tool list. `find_tools` was undocumented entirely; both docs now list it with its `mcp-tool-search` experiment gating. - **Missing `source:` search filter.** `docs/ai-coder/agents/chat-search-syntax.md` documented every chat filter except `source:`, while also stating that unrecognized keys return HTTP 400. Adds the filter row and an example. - **Attachments described as images only.** The attachments section claimed PNG, JPEG, GIF, and WebP up to 10 MB. The upload allowlist also accepts plain text, Markdown, CSV, JSON, and PDF; the cap is 10 MiB per upload with at most 50 attachments per conversation, and Anthropic models cap inline images at 5 MiB. Also notes that providers differ in accepted file types and that rejected parts are downgraded to text. - **Template ranking described as popularity sort.** `docs/ai-coder/agents/platform-controls/template-optimization.md` said templates are sorted by active developer count. `list_templates` ranks by query relevance tiers first, then by an affinity score that weights the user's own recent usage far above organization popularity. Wording now matches `docs/ai-coder/agents/tools/index.md`, which already documents the formula, and links to it. Linear: DOCS-716 https://linear.app/codercom/issue/DOCS-716 <details><summary>Analysis evidence</summary> | Claim | Source | |-------|--------| | `stop_workspace` is a root-chat platform tool registered alongside `create_workspace` and `start_workspace` | `coderd/x/chatd/chattool/stopworkspace.go`; registration in `coderd/x/chatd/chatd.go` (`chattool.StopWorkspace`), root-only gate in `builtinPlanToolAllowed`, disabled for explore sub-agents in `allowedExploreToolNames` | | `find_tools` requires the `mcp-tool-search` experiment and deferrable MCP candidates | `coderd/x/chatd/chattool/findtools.go`; `decideMCPToolSearch` in `coderd/x/chatd/mcp_tool_search.go` returns false without `codersdk.ExperimentMCPToolSearch` or with no candidates; wired in `coderd/x/chatd/generation_preparer.go` | | `source:` accepts `created_by_me` and `shared_with_me`; passing both returns owned plus shared; default is owned only | `coderd/searchquery/search.go` (`Chats`): filter defaults to `OwnedOnly: true`; the `source` parser rejects any other value, and both values together set `OwnedOnly` and `SharedOnly`. The literal value `all` appears in the doc comment but is not accepted by the parser, so it is not documented. | | Attachment allowlist, size caps, and per-conversation limit | `codersdk/chats.go`: `AllChatAttachmentMediaTypes` covers `application/json`, `application/pdf`, `image/gif`, `image/jpeg`, `image/png`, `image/webp`, `text/csv`, `text/markdown`, `text/plain`; `MaxChatFileSizeBytes = 10 * 1024 * 1024`; `MaxChatFileIDs = 50`; `AnthropicInlineImageCapBytes = 5 * 1024 * 1024` | | Anthropic and Bedrock share the inline image cap; rejected file parts are downgraded to text | `coderd/x/chatd/chatprovider/chatprovider.go`: `InlineImageCapBytes` and `Model.AcceptsFilePartMediaType` | | Template ranking is relevance tiers then a composite affinity score | `coderd/x/chatd/chattool/listtemplates.go`: `rankTemplates` sorts by query score first; `computeAffinityScore` adds recency-decayed personal usage at `listTemplatesPersonalWeight = 10.0` to `ln(1 + active_developers)` at `listTemplatesOrgWeight = 1.0` | Note: `MaxChatFileIDs` is enforced per chat, not per message (`coderd/exp_chats.go`: "A chat can reference at most %d attachments"), so the docs say per conversation. Validation: `pnpm run format-docs` and `pnpm run lint-docs` both pass (0 errors). The formatter widened the touched tables, which accounts for the reformatted rows in the diff. </details> Generated by Coder Agents on behalf of @nickvigilante. |
||
|
|
06c0d3918a |
docs: correct plan mode MCP tool availability (#28569)
`docs/ai-coder/agents/index.md` claimed that MCP tools are blocked in plan mode. Root plan-mode chats actually receive external MCP tools for each server configuration an administrator approved for plan mode; only workspace MCP tools and plan-mode sub-agents get none. Corrects the plan-mode tool-availability wording in both places it appears in `index.md` so it matches `docs/ai-coder/agents/architecture.md` and the implementation. The tool table and attachment wording are out of scope here. Linear: DOCS-724 https://linear.app/codercom/issue/DOCS-724 <details><summary>Analysis evidence</summary> `coderd/x/chatd/chatd.go`, `filterExternalMCPConfigsForTurn`: in plan mode, a chat with a parent gets no external MCP configs ("Plan-mode subagents do not receive external MCP tools"); a root chat keeps every config whose `AllowInPlanMode` flag is set and returns those IDs as approved. `coderd/x/chatd/generation_preparer.go`: the returned `approvedPlanMCPConfigIDs` flows into `filterToolsForTurn` and `activeToolNamesForTurn`, so approved external MCP tools remain exposed for the turn. `coderd/x/chatd/chatd.go`, `toolAllowedForTurn`: in plan mode a tool passes only if it is on the built-in plan allowlist or is an MCP tool whose `MCPServerConfigID()` is in the approved set. Workspace MCP tools are not in the external config set, so they stay unavailable. `docs/ai-coder/agents/architecture.md` already documents this behavior; `index.md` now uses the same framing. </details> Generated by Coder Agents on behalf of @nickvigilante. |
||
|
|
b146e6f262 |
docs: align Coder Agents docs with GA framing and licensing terms (#28571)
Removes early-access-program framing from the Coder Agents docs, drops a stale `early access` manifest tag, and standardizes the licensing wording on "Premium license with the Agent Hours entitlement". - `docs/ai-coder/agents/getting-started.md`: replaces the "collaborative evaluation between your team and Coder" and customer-specific Slack channel feedback path with GitHub issues plus normal Coder support channels, and rewrites the remaining evaluation-period wording to GA tone. Rollout guidance (pilot group, cost planning, concurrency) is kept. - `docs/manifest.json`: removes `"state": ["early access"]` from `ai-coder/agents/platform-controls/chat-debug-logging.md`, which is not experiment-gated. - Licensing terminology aligned across `getting-started.md`, `licensing-usage.md`, and `platform-controls/index.md`. No changes to `docs/reference/api/**` and no API path changes. <details><summary>Analysis evidence</summary> **Manifest state tag decisions (all `ai-coder/agents` pages)** | Page | Tag before | Tag after | Why | |------|-----------|-----------|-----| | `platform-controls/chat-debug-logging.md` | `["early access"]` | none | Routes at `coderd/coderd.go` (`GET`/`PUT /debug-logging`, `GET`/`PUT /user-debug-logging`) sit outside any `RequireExperimentWithDevBypass` group, there is no matching experiment in the `codersdk.Experiment` list, and the page body already states the feature is not experiment-gated. | | `platform-controls/advisor.md` | `["early access"]` | unchanged | Gated by `codersdk.ExperimentChatAdvisor` (`chat-advisor`); routes wrapped in `RequireExperimentWithDevBypass`. | | `platform-controls/virtual-desktop.md` | `["early access"]` | unchanged | Gated by `codersdk.ExperimentChatVirtualDesktop` (`chat-virtual-desktop`); routes wrapped in `RequireExperimentWithDevBypass`. | | `platform-controls/spend-management.md` | `["premium"]` | unchanged | `premium` is a licensing tag, not a maturity tag, and the page states budget endpoints require a license that includes AI Gateway. Flagging for awareness rather than changing it. | | All other `ai-coder/agents` pages | none | none | No maturity tags to review. | **Licensing mechanics** `enterprise/coderd/license/license.go` decodes `agent_runtime_hours_allocation`, `agent_runtime_hours_limit_soft`, and `agent_runtime_hours_limit_hard` into `codersdk.FeatureAgentRuntimeHours` on Premium licenses. `enterprise/coderd/x/chatd/agentadmission.go` lifts the concurrency cap only when that feature is enabled and usage is below the hard limit. So the entitlement, not the license tier alone, is what removes the cap. Wording is now "Premium license with the Agent Hours entitlement". `licensing-usage.md` keeps "Agent Time" as the name of the measured usage metric (matching `runtime_ms` reporting) and now says explicitly that Agent Time draws down the Agent Hours entitlement. Renaming the metric itself was left out of scope; flagging in case the product team wants one name for both. **Validation** `pnpm install --frozen-lockfile`, `pnpm run format-docs` (no table changes), `pnpm run lint-docs` (499 files, 0 errors). </details> Linear: DOCS-718 https://linear.app/codercom/issue/DOCS-718 Generated by Coder Agents on behalf of @nickvigilante. |
||
|
|
827c11f43a |
docs: update Coder Agents admin navigation to AI Settings (#28572)
## Summary Fixes stale admin navigation on the three Coder Agents platform-controls pages not covered by #28482: the retention pages pointed at tabs that do not exist ("Behavior", the old Agents settings "Lifecycle" tab), and template optimization pointed at the removed **Agents** > **Settings** > **Manage Agents** navigation. Breadcrumbs follow the **Admin settings** > **AI** > **Coder Agents** convention established by #28482. ## Changes - `docs/ai-coder/agents/platform-controls/chat-retention.md`: replace the nonexistent **Behavior** tab with **Admin settings** > **AI** > **Coder Agents** > **Lifecycle**. - `docs/ai-coder/agents/platform-controls/chat-debug-retention.md`: same page, same convention, aligned with chat-retention.md. - `docs/ai-coder/agents/platform-controls/template-optimization.md`: replace **Agents** > **Settings** > **Manage Agents** > **Templates** with **Admin settings** > **AI** > **Coder Agents** > **Templates**. ## Scope note The first revision also fixed `models.md`, `advisor.md`, `chat-debug-logging.md`, and `platform-controls/index.md`. Those pages are covered by #28482 with the same corrections, so this PR reverted them to avoid conflicting edits and adopted that PR's breadcrumb convention instead. Linear: DOCS-715 https://linear.app/codercom/issue/DOCS-715 <details><summary>Analysis evidence</summary> - `site/src/router.tsx` (~735-780): `/ai/settings/{lifecycle,templates,coder-agents}` are the live routes; `/agents/settings/{admin pages}` (~833-890) are `Navigate`-only redirects. - No "Behavior" tab exists in any router revision; `RetentionPeriodSettings` and `DebugRetentionSettings` both render in `LifecyclePageView.tsx`. - Breadcrumb convention **Admin settings** > **AI** verified against `AdminSettings.tsx` / `AISettingsSidebarView.tsx` in #28482. </details> Generated by Coder Agents on behalf of @nickvigilante. |
||
|
|
409049d1d8 |
docs: document org-scoped admin configuration for agents (#28482)
## Summary Documents the organization scoping of Coder Agents admin configuration, and corrects the navigation paths, access wording, and default-model instructions that no longer matched the product. Documentation only, no product code changes. Follows #28473, which moved the organization model overrides into an **Organization settings** section on **Admin settings > AI > Coder Agents**. #28473 is merged, so this targets `main`. Closes CODAGT-715 ## Changes - **New page** `docs/ai-coder/agents/platform-controls/organizations.md`, registered in `docs/manifest.json`. Covers the deployment/organization scope split, what an upgrade changes, how an organization without models or MCP servers behaves, who configures each scope, and how model and MCP server sharing works. - **`models.md`**: models are organization-scoped while providers and their credentials stay deployment-wide. Each organization has one default model, and the first model added becomes it. Documents the **Default** badge and the **Set as Coder Agents default model** form option in place of the star action that no longer exists, and points model overrides at **Organization settings**. - **`getting-started.md`**: replaces the Owner-only claim with the actual access model, adds an organization selection step, and uses the **Add model** label. - **`platform-controls/index.md`**: separates deployment-wide controls from organization-scoped controls, documents personal model overrides alongside the model configuration section rather than as an enforcement caveat, and adds `--agents-allowed` plus the `agents-allowed:` search filter. - **`platform-controls/advisor.md`** and **`platform-controls/virtual-desktop.md`**: the Advisor and Virtual desktop settings are cards in the **Deployment settings** section of the **Coder Agents** page, not sidebar entries. **Providers** is a sidebar item, not a tab. - **`platform-controls/mcp-servers.md`**: slug uniqueness is per organization, the **Add server** label is correct, and the page is no longer described as admin-only. - **`architecture.md`**, **`index.md`**, **`tasks-to-chats-migration.md`**: organization scope corrections and organization-scoped model routes. - Breadcrumbs standardized to **Admin settings > AI > ...**, verified against `AdminSettings.tsx` and `AISettingsSidebarView.tsx`. <details> <summary>Review follow-ups</summary> The first revision leaked implementation detail into user-facing pages and contained several claims that did not match the UI. The follow-up commit removed and corrected the following. Removed as implementation detail: - The `chat_model_config` RBAC resource, its actions, and the token scopes. - The `available`, `unavailable_reason`, and `unsupported_providers` response fields, along with the `missing_api_key`, `fetch_failed`, and `user_api_key_required` values. - Role and permission tables, ACL storage mechanics, audit internals, and JSON error bodies on the new organizations page. - Migration mechanics with no effect on what a user does. Corrected against the product: - The star action does not exist. The list shows a **Default** badge and the add/edit form offers **Set as Coder Agents default model** (`ModelRow.tsx`, `ModelFormFields.tsx`). - The first model added to an organization becomes its default automatically (`coderd/exp_chats.go`). An organization without a stored default does not fail every chat, so that claim is gone. - Advisor and Virtual desktop are cards under **Deployment settings** (`CoderAgentsPageView.tsx`). - The MCP servers page does not require deployment configuration edit permission (`AISettingsSidebarView.tsx`). - Button labels: **Add model** and **Add server**. - The organization query parameter is `org`, confirmed by `modelOrganizationSearchParam`. Left alone deliberately: pre-existing defects outside the introduced text, including the `/api/v2/chats` route prefixes, create-chat examples missing `organization_id`, and the pre-existing MCP permissions table. </details> ## Testing - `pnpm run format-docs` and `pnpm run lint-docs` pass. - `make lint/emdash` passes. No emdash or endash added. - `grep -rn "Defaults & overrides" docs/` returns nothing. - Every navigation path, button label, and access claim checked against the corresponding file under `site/src/pages/AISettingsPage/` and `site/src/modules/management/`. --- This pull request was generated by Coder Agents on behalf of @ethanndickson. |
||
|
|
c07bde80c4 |
fix: use medium badges and shorter shared key label on agent API keys page (#28557)
On `/agents/settings/api-keys`, bumps the provider key status badge and the enabled model badges from `sm`/`xs` to the medium (`md`) size, and shortens the status label "Using shared key" to "Shared key". Updates the matching Storybook assertion and the status indicator name in `docs/ai-coder/agents/models.md`. Verified with `tsc` and the page's Storybook tests (15 passing). --- *Created by Coder Agents on behalf of @tracyjohnsonux.* |
||
|
|
7cf24b1a37 |
docs(docs/ai-coder/agents): document the chat search: full-text filter (#28474)
Documents the `search:` full-text filter in `docs/ai-coder/agents/chat-search-syntax.md` and drafts the release notes copy for chat history search. Describes `main` plus #28319, which must merge first: stemming and stopword removal apply to message content only; titles and PR titles keep `simple` whole-word matching. All claims verified against the implementation. Two statements in CODAGT-727 were inaccurate and are documented as the code behaves: - A value that tokenizes to no searchable words returns an **empty list**, not HTTP 400 (`TestListChats_Search/NoSearchableWordsReturnsEmpty`). HTTP 400 covers only an empty `search:` value, unsupported keys, bare terms, or combining `search:` with `title:`, `pr_title:`, or `pr:` (`coderd/searchquery/search.go`). - Results are **paginated** with the standard chat list cursor (default 50), not a bounded non-paginated set (`GetChats`, `listChats`). Ordering is pinned first, then most recently updated. Also verified: message bodies are indexed by the dbpurge sweep (10-minute tick, up to 5 x 10,000 rows, newest first) while titles and PR titles are searchable immediately; numeric values match exact PR numbers; `title:`, `pr_title:`, and `repo:` retain `ILIKE` semantics. `pnpm run format-docs` and `pnpm run lint-docs` pass. Closes [CODAGT-727](https://linear.app/codercom/issue/CODAGT-727/chat-search-documentation-and-release-notes) <details> <summary>Release notes draft</summary> ### Chat history search You can now search your chat history by what was said, not just by title. The chat list `q` parameter accepts a new `search:` filter that performs full-text search across chat titles, pull request titles, PR numbers, and message content, for example `?q=search:"kubernetes restart"`. Matching is case-insensitive and supports quoted phrases, `OR`, and `-` negation. Message content additionally matches English word stems (`refactor` finds a message containing `refactoring`). `search:` cannot be combined with the `title:`, `pr_title:`, or `pr:` filters; the existing substring filters are unchanged. **Upgrading with existing chat history:** the message search index is populated by a background job (every 10 minutes, up to 50,000 messages per run, newest first). Upgrades are not blocked, and chat reads and writes are unaffected while the index fills. Older messages appear in search results progressively; messages indexed before the stemming upgrade match exact word forms until re-indexed. Titles and PR titles are searchable immediately. </details> --- 🤖 This PR was generated by Coder Agents on behalf of @f0ssel. |
||
|
|
eedc0ece47 | fix: avoid 500 when generating chat title from rename dialog and remove unused endpoint (#28306) | ||
|
|
0ef331fcd0 |
feat!: scope chat model override settings to organizations (#28442)
Moves chat model override settings from deployment scope to organization scope, following the org-scoping of chat model configs in #28440. Depends on #28440 (based on `ethan/chat-models-availability-consolidation`). Remote dogfood UAT passed on this change, including multi-organization scenarios on a licensed deployment with real models. ## Problem Chat model configs are now owned by organizations, but the override settings that reference them stayed deployment-wide: admin subagent/title/compaction overrides in `site_configs`, personal overrides in `user_configs`, and the advisor model embedded in the advisor runtime JSON. A single deployment-level override can only point at one organization's model config, so overrides effectively worked for the default organization only, and title generation had to soften its hard-failure contract to tolerate unusable overrides. ## Fix Admin overrides (general, explore, title generation, compaction, advisor) and personal overrides (root, general, explore) become organization-scoped rows in two new typed tables, `chat_organization_model_overrides` and `chat_user_model_overrides`. Composite foreign keys on `(organization_id, model_config_id)` make cross-organization model references unrepresentable. The migration deletes the legacy serialized `site_configs`/`user_configs` override keys instead of migrating them; admins and users re-select models in the new organization-scoped settings. New endpoints live under `/api/experimental/organizations/{organization}/chats/model-overrides` (admin defaults) and `/api/experimental/organizations/{organization}/members/{user}/chats/model-overrides` (personal overrides); the legacy deployment-level routes are removed. chatd resolves overrides via the chat's organization, restoring the hard-failure contract for configured-but-unusable title generation overrides. The deployment-level `AllowUsers` switch and advisor runtime limits stay deployment-scoped. The Coder Agents settings UI gains a per-organization "Defaults & overrides" page under AI Settings > Models, and the personal overrides page gains an organization selector for users in multiple organizations. Advisor telemetry now reports per-organization override rows. **BREAKING CHANGE**: Existing deployment-level overrides are dropped, not migrated. Every organization starts with no overrides after upgrade, and model selections must be re-applied in the new settings. The legacy deployment-level override endpoints are removed. Closes https://linear.app/coder/issue/CODAGT-872 > [!NOTE] > Xum (AI agent) authored this PR on behalf of @ibetitsmike. <!-- xum-attribution: model=claude-opus-4-6 thinking=high --> --------- Co-authored-by: Ethan Dickson <ethan@coder.com> |
||
|
|
3809314b31 |
refactor!: consolidate chat model availability (#28440)
## Summary Consolidate chat model management and runtime availability into a single organization model collection contract. The organization model response now includes provider availability, unavailable reasons, and unsupported-provider details, so callers no longer need a separate availability request. Depends on #28439. ## Problem The organization-scoped API exposes two overlapping representations of the same chat models: ```text GET /api/experimental/organizations/{organization}/chats/models GET /api/experimental/organizations/{organization}/chats/models/available ``` The collection route returns organization-owned model configurations and redacted provider descriptors. The availability route returns a second catalog-oriented response with provider availability and synthetic catalog entries. Callers must fetch, reconcile, and cache both responses even though they describe the same effective set of models. This creates duplicated server logic and separate SDK, OpenAPI, and frontend types. It can also produce inconsistent client state when one request succeeds while the other fails or when the two responses are refreshed at different times. ## Fix Return all model-management and runtime-availability information from the organization model collection route: ```text GET /api/experimental/organizations/{organization}/chats/models ``` `OrganizationChatModelsResponse` continues to return the caller-readable organization model configurations and redacted provider descriptors. Provider descriptors now also include: - `available` - `unavailable_reason` The response additionally includes `unsupported_providers`, allowing clients to explain configurations that the Agents harness cannot use. Frontend model settings, agent creation, existing chat recovery, and model override surfaces now consume this single collection query. This keeps model ownership, caller visibility, provider availability, and unsupported-provider guidance in one cache entry and one authorization path. The default-organization compatibility route remains available: ```text GET /api/experimental/chats/models ``` It now returns the same consolidated `OrganizationChatModelsResponse` contract instead of the former availability response. ## Breaking change This removes the separate organization model availability endpoint: ```text GET /api/experimental/organizations/{organization}/chats/models/available ``` Clients using that endpoint must migrate to: ```text GET /api/experimental/organizations/{organization}/chats/models ``` This PR also removes the corresponding public experimental client and schema surface: - `ExperimentalClient.ChatModelAvailability` - `ChatModelAvailabilityResponse` - `ChatModelProvider` - `ChatModelCatalogEntry` - The generated OpenAPI schema and frontend API/query types for the availability endpoint Callers must use `ExperimentalClient.ChatModels` and `OrganizationChatModelsResponse` instead. Availability is now reported on each `ChatModelProviderDescriptor`, and unsupported providers are returned in `OrganizationChatModelsResponse.UnsupportedProviders`. The default-organization compatibility route retains its URL, but its response schema changes from `ChatModelAvailabilityResponse` to `OrganizationChatModelsResponse`. Direct HTTP clients and generated clients that decode the previous response type must be updated even if they do not use the removed organization-scoped `/available` route. |
||
|
|
75ad45109d |
feat: use organization-scoped chat models (#27960)
Move chat model settings to `/ai/settings/organizations/:organization/models`, add an organization switcher, and redirect legacy settings paths. The pages use organization permissions for read, create, update, and delete controls. They use redacted provider descriptors. Agent creation loads models for the selected organization. Existing chats load models for the chat organization. Chat views warn about unavailable historical models, select a usable local recovery model, and disable generation when none exists. Settings that aggregate organizations retain successful results when one request fails. Depends on #27959 _This pull request description was generated by Coder Agents._ |
||
|
|
24b83dc727 |
feat: add organization picker to MCP server settings pages (#28150)
Adds an organization picker to the MCP server settings pages so
multi-org deployments can manage every organization's MCP servers
through the UI, not just the default organization's. Closes CODAGT-714
(scoped to MCP servers only; model configs stay deployment-wide until
CODAGT-709 lands).
## Stack Context
Top of the CODAGT-711/717/712/806 stack: MCP server configs are
org-scoped with RBAC, audit logging, per-config ACLs, and owner-scoped
user tokens. This layer makes the admin UI org-aware, resolving the
"default org only" limitation documented in the bottom PR.
## Summary
- The MCP servers list and add pages resolve the working organization
from an `org` search param (falling back to the default org), and render
an organization picker built on the existing `OrganizationAutocomplete`.
The picker only appears when more than one organization is visible, so
single-org deployments see no change.
- Selecting an organization rewrites the search param, refetches the
list for that org, and threads through to the add page so creation posts
to the selected organization.
- The update page now loads the server by ID (new organization-scoped
`GET /api/experimental/organizations/{organization}/mcp-servers/{id}`
frontend binding) instead of listing the default org and searching
client-side, so servers from any organization can be edited. Post-save
navigation returns to the owning organization's list via the server's
`organization_id`.
- Removes the now-unused `getDefaultOrganizationId` helper.
- Review hardening: organization display labels are disambiguated with
the unique org name when effective display names collide (picker
options, trigger text, and accessible name). Access is no longer
restricted to deployment admins: the pages, sidebar item, and nav entry
accept org-scoped `mcp_server_config` permissions, the picker lists only
organizations the user can view, content and affordances (add, edit,
delete) are gated on the selected organization's permissions, and
deployment admins keep full access everywhere.
## Testing
Storybook interaction stories cover: picker hidden with one org,
switching orgs refetches and swaps list contents, add posting to the
URL-selected org, add posting after an in-form org switch (asserting
typed form state survives the switch), and update loading by ID.
Red-green verified by breaking the search-param resolution and observing
the new stories fail.
> Mux acted on Mike's behalf for this PR.
|
||
|
|
8203b2ebaf | feat!: hide Coder Tasks behind the enable-ai-tasks flag (#28008) | ||
|
|
7ca7c30f40 |
feat: add group and user ACLs to MCP server configs (#27944)
Adds group and user ACLs to org-scoped MCP server configs so
organizations can restrict specific MCP servers to subsets of members,
mirroring the template ACL pattern.
## Summary
- Migration adds `group_acl`/`user_acl` JSONB columns (nested `{"<id>":
{"permissions": [...]}}` shape) and seeds every existing config with its
organization's Everyone group read entry (the Everyone group ID equals
the org ID), so member access is unchanged by default. Creation seeds
the same entry.
- The blanket org-member read grant from the base PR is replaced by ACL
evaluation: Rego requires org membership for every ACL grant, and
`GetAuthorizedMCPServerConfigs` compiles ACL-aware SQL filters.
- New `ActionShare` (org admins) gates `GET|PATCH
/api/experimental/organizations/{organization}/mcp-servers/{mcpserverconfig}/acl`
(nested under the organization like the rest of the config surface).
PATCH validates principals against the config's organization, merges
sparse updates under a row lock, stamps `updated_by`/`updated_at`, and
is audited as a Write with `Old` captured before authorization. A config
deleted concurrently between the middleware fetch and the locked
re-fetch is concealed as 404, matching the update and delete handlers.
ACL columns are tracked in the audit table.
- ACL management is available in all editions (no enterprise
entitlement), documented in the MCP servers page. Revoking an ACL does
not retro-strip already-selected configs from existing chats; new
selection is blocked at chat create.
- Force On respects the ACL: the forced set is loaded as the chat owner,
so a `force_on` server whose ACL denies the owner never attaches at
create, send, or generation time.
- No rolling-upgrade machinery: upgrades run in scheduled maintenance
downtime, so the migration only backfills existing rows; the API sets
the Everyone read grant explicitly on every insert.
Stacked on #27943. Part of the MCP org-separation stack.
Closes https://linear.app/codercom/issue/CODAGT-712
UAT: verified on a dogfood instance with two members and a custom group:
Everyone-seed default visibility, group grant with Everyone removal
(non-member loses list/fetch/selection), foreign-principal rejection,
non-admin share denial (audited 403 / concealed 404), user_acl restore,
and audited ACL diffs.
> Mux (AI agent) authored this PR on Mike's behalf.
<!-- mux-attribution: model=claude-fable-5 thinking=high -->
|
||
|
|
f7a0de7a11 |
fix: harden org-scoped MCP config chat gating, updates, and visibility (#28065)
Hardens the org-scoped MCP server config surface from #27942 with fixes and regression pins that are independent of the core cutover: - Keep chats sendable after a selected MCP server is disabled (persisted selections are exempt from message-time rejection). - Keep cached MCP selections usable after a background refetch error (gate the composer on missing data, not `isSuccess`). - Merge PATCH updates onto the current row so unset fields are not clobbered. - Give auditors the full management view of MCP configs their audit logs reference (site and org auditor roles). - Regression pins: frozen OAuth2 callback path, cross-org concealment for item routes, OAuth callback token binding, and disconnect responses indistinguishable from nonexistent config IDs. - Storybook: semantic textbox queries in MCP loading stories; docs note that the MCP settings page needs deployment access. ## Stack context Part of the MCP org-separation stack (CODAGT-711 org scope -> apidocs -> hardening -> CODAGT-717 audit -> CODAGT-712 ACLs -> CODAGT-806 token RBAC). Split out of #27942 to keep the core cutover reviewable; each change here builds on the org-scoped routes and chat gating introduced below it. > Mux (AI agent) authored this PR on Mike's behalf. <!-- mux-attribution: model=claude-fable-5 thinking=high --> |
||
|
|
443e3b9b80 |
feat!: org-scope MCP server configs with RBAC (#27942)
Moves `mcp_server_configs` from deployment scope to organization scope
so each organization fully controls the MCP servers its members can use
with Coder Agents.
## Summary
- Migration: adds `organization_id` (NOT NULL, FK) and keeps existing
rows as the default organization's originals with credentials intact.
Other organizations start with no MCP servers and configure their own;
nothing is copied across organizations. Chats outside the default
organization keep any now-cross-organization `mcp_server_ids` entries;
the runtime already ignores IDs that do not resolve in the chat's
organization, so no data rewrite is needed. Slug uniqueness becomes
`(organization_id, slug)`.
- RBAC: new org-scoped `ResourceMCPServerConfig` with regosql converter
and `GetAuthorizedMCPServerConfigs`; org admins get in-org CRUD, org
members get read (replaced by ACL evaluation in the follow-up ACL PR in
this stack).
- API: all config routes nest under the organization, matching
templates: `POST|GET
/api/experimental/organizations/{organization}/mcp-servers` and
`GET|PATCH|DELETE .../mcp-servers/{mcpserverconfig}` (plus
`oauth2/connect`), resolved by a read-only param middleware that
conceals read-denied and cross-organization access as 404. Two routes
stay on the frozen `/api/experimental/mcp/servers/{mcpServer}` block:
the OAuth2 callback (the redirect URI baked into existing AS-side client
registrations) and `oauth2/disconnect`, which must remain reachable by
users removed from the organization so they can still revoke their token
grant.
- Chat runtime: selection validation and generation resolve configs
strictly by IDs, enabled state, and the chat's organization in SQL;
requested duplicates are normalized; invalid or cross-org IDs are
rejected with the precise ID list. IDs already persisted on a chat are
exempt from message-time rejection so disabling a selected server never
blocks sends; generation skips servers that are no longer usable.
- Frontend: API layer and admin settings pages target the new endpoints.
The admin page manages the default organization's servers; the org
picker is tracked separately (CODAGT-714).
- Security hardening from review: OAuth user grants are additionally
bound to `oauth2_revocation_url` (changing it invalidates grants, and a
racing OAuth callback gets 409 instead of recreating a grant).
Stack-wide SSRF protection for MCP config-directed traffic was split
into its own PR at the top of this stack (#28242) to keep this diff
reviewable; this PR keeps main's existing discovery IP-range guard.
OAuth2 auto-discovery now completes before the config row is inserted: a
failed discovery persists nothing, and there is no provisional row that
concurrent updates could race against.
Two follow-up PRs in this stack were split out to keep this diff
reviewable: #28064 completes the swagger annotations for the moved
routes (main already ships these experimental MCP handlers unannotated),
and #28065 carries hardening fixes and regression pins on top of the
cutover.
- Force On enforcement (landed on main mid-review) is org-scoped: the
forced set is read per chat organization
(`GetForcedMCPServerConfigsByOrganization`), so another organization's
`force_on` server never attaches to a chat.
## Breaking changes (experimental API)
The MCP server config endpoints move from the deployment-scoped
`/api/experimental/mcp/servers` block to organization-nested paths:
`POST|GET /api/experimental/organizations/{organization}/mcp-servers`
and `GET|PATCH|DELETE
/api/experimental/organizations/{organization}/mcp-servers/{mcpserverconfig}`
(plus `oauth2/connect`). The old paths are removed, so API consumers
must supply an organization. Two routes intentionally stay on the frozen
`/api/experimental/mcp/servers/{mcpServer}` block: the OAuth2 callback
(its redirect URI is baked into existing AS-side client registrations)
and `oauth2/disconnect` (must remain reachable by users removed from the
organization). These endpoints are under `/api/experimental`, so no
deprecation window is provided.
## Rolling upgrades
During a rolling deploy, an old replica creating an MCP config can fail
the new `NOT NULL organization_id` constraint until it is upgraded
(reads are unaffected: old binaries' generated queries select their own
column lists). This matches the repo's existing precedent for additive
NOT NULL migrations (000562) and affects only the admin config-create
path in the upgrade window.
Upgrades are expected to run in scheduled maintenance downtime with the
database locked during migration, so the migration ships no
rolling-upgrade compatibility machinery. The down migration deletes
organization-created configs (their chat references are cleaned by the
000510 delete trigger) and restores deployment-wide slug uniqueness.
Part of the MCP org-separation stack (CODAGT-711 -> CODAGT-717 audit ->
CODAGT-712 ACLs -> CODAGT-806 token RBAC).
Closes https://linear.app/codercom/issue/CODAGT-711
UAT: validated end to end on a two-org dogfood deployment, including a
real pre-migration to post-migration upgrade, cross-org isolation
(404s), same-slug-two-orgs, chat selection gating, and a live MCP tool
call through the org-scoped generation path. The migration was later
revised to keep existing rows in the default organization only (no
per-organization copies); that revision is covered by the migration test
suite.
> Mux (AI agent) authored this PR on Mike's behalf.
<!-- mux-attribution: model=claude-fable-5 thinking=high -->
---------
Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
|
||
|
|
ddf2d33665 |
docs: update Tallyman Agent Time reporting (#28275)
Moves Coder Agents usage reporting into the Licensing & Usage page and updates the documentation to describe Agent Time and the `hb_agent_runtime_v1` Tallyman payload. Removes the superseded Usage Data Reporting page and its manifest entry, and removes the obsolete AI Governance link to that page. PR generated with Coder Agents |
||
|
|
5f6eeda588 |
docs: add Licensing & Usage page and reorder agents manifest (#28263)
Adds a new Licensing & Usage page under `docs/ai-coder/agents/` covering the difference between Community and AI Premium licenses, how Agent Time is measured, and what happens when concurrency or usage limits are reached. Reorders the Coder Agents section in `docs/manifest.json` to the following sequence: Getting Started, Architecture, Platform Controls, Extending Agents, Models, Tools, Chat Sharing, Search Syntax, Licensing & Usage, Tasks to Chats API Migration. --- PR generated with Coder Agents --------- Co-authored-by: Nick Vigilante <nickvigilante@users.noreply.github.com> |
||
|
|
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. |
||
|
|
1458d27d78 |
fix: allow manual chat compaction from the error state (#28022)
A chat that fails generation with a context overflow (for example `Input
length 262625 exceeds the maximum allowed input length of 262112
tokens`) is stuck in a catch-22: `POST /chats/{id}/compact` returns 409
because the `RequestCompaction` transition is only allowed from the
waiting state, and the only other way out of the error state is sending
or editing a message, which re-runs generation with the same oversized
prompt and fails again. Compaction is exactly the recovery a
context-overflowed chat needs, and it is unreachable exactly when it is
needed.
Three semantic changes:
- Allow `RequestCompaction` from the error states: `E0 -> R0` and `E1 ->
R1` (queued messages are preserved and processed after the compaction
turn).
- Clear `last_error` in `Tx.RequestCompaction`, matching the
architecture rule that transitions leaving `E0`/`E1` clear the stored
error. Without this a successful compaction would land in waiting with a
stale persisted error.
- Grant the compaction turn a fresh history epoch: a
`grant_history_epoch` flag on `UpdateChatExecutionState` sets
`history_version = snapshot_version`, resets `generation_attempt`, and
clears `retry_state` in the same atomic update that clears `last_error`
(mirroring the `chat_messages` trigger postcondition). The transition
inserts no history, so without this the turn inherits the failed turn's
spent retry budget, and resetting the counter alone could collide with
message part episode keys still retained on the erroring replica.
No frontend change is required: the chat input is already enabled in the
error state and `/compact` submission already handles both the success
and 409 paths. Also updates ARCHITECTURE.md (transition matrix,
endpoint, and manual compaction sections), the endpoint's swagger
description, and SDK comments.
> Mux created this PR on Mike's behalf.
<!-- mux-attribution: model=claude-sonnet-4-6 thinking=high -->
|
||
|
|
75e0790cd7 |
docs: remove beta references from Coder Agents docs and manifest (#27939)
Removes all references to "beta" from the Coder Agents documentation under `docs/ai-coder/agents/` and the corresponding `"state": ["beta"]` entries in `docs/manifest.json`. Also updates screenshots, video, and hero image, and regenerates the auto-generated feature-stages table. **Beta reference removal:** - `getting-started.md`: Removed "Coder Agents is in Beta" from the top note, "is in beta" from the Chats API note, and "during Beta" from the feedback section. Removed the version/stability note pinning 2.33.1. - `index.md`: Removed the "Product status" section that stated Coder Agents is in Beta. - `manifest.json`: Removed `"state": ["beta"]` from 17 entries for pages under `docs/ai-coder/agents/`. Preserved all `premium` and `early access` states. - `feature-stages.md`: Regenerated the auto-generated beta features table, which no longer lists Coder Agents. **Asset updates:** - `coder-agents-ui.mp4`: Updated demo video on the agents landing page. - `llm-providers.png`: Updated LLM provider support screenshot. - `models-list.png`: Updated models list screenshot. - `models-add-model.png`: Updated add model form screenshot. - `agents-hero-image.png`: Updated hero image on the `docs/ai-coder` landing page. Two references in `models.md` (`v1beta` in the Google Gemini API URL and `anthropic-beta` in the Anthropic header name) were left unchanged as they are provider API identifiers, not product status labels. PR generated with Coder Agents --------- Co-authored-by: Nick Vigilante <nickvigilante@users.noreply.github.com> |
||
|
|
57f38b5c24 |
fix: keep chat attachments while a linking chat exists
Fixes https://linear.app/codercom/issue/CODAGT-616/keep-chat-attachments-while-chats-remain-unarchived Chat attachments could disappear even though the chat was still available. This happened when a message was saved without recording which attachments it used, or when cleanup deleted attachments before an archived chat itself was removed. Creating a chat, sending or queuing a message, and editing a message now record both the message and which attachments it uses as one operation. If the chat is already at the 50-attachment limit, the chat change fails without being partially saved. Concurrent attachment writes serialize the 50-file cap per chat. Cleanup locks candidates and checks again for new links before deleting. If a file becomes unavailable after input validation, create, send, and edit return a clear client error and roll back the chat change. An attachment stays available while any chat that uses it still exists. After an archived chat reaches the end of its retention period and is deleted, an old attachment that no remaining chat uses can be cleaned up. The retention guide and unavailable-attachment UI text document this lifecycle. This change cannot restore attachments that were already deleted. The database migration adds two indexes so attachment cleanup stays fast as attachments accumulate. > This PR was authored by Mux (AI) on Mike's behalf. |
||
|
|
ee49107ea9 |
docs: document per-template agents_allowed (#27518)
Relates to CODAGT-713 Depends on #27517 This updates the Coder Agents platform controls documentation for the per-template `agents_allowed` model. It replaces the deployment-wide allowlist instructions with the **Agents allowed** controls in AI Settings and template settings, documents that templates allow agents by default, and explains that disabled templates are excluded from `list_templates`, `read_template`, and `create_workspace`. This is the final PR in the stack and aligns the template routing and optimization guidance with the database, API, frontend, cleanup, and CLI changes in the preceding PRs. |
||
|
|
6b8f820493 |
feat: remove native chat cost tracking in favor of AI Gateway cost data (#27330)
## Stack Context This stack makes AI Gateway data and budgets the source of truth for AI spend controls. 1. Re-back the per-chat cost endpoint with AI Gateway data (#27328, merged). 2. Remove native chat usage limits (#27329, merged). 3. **This PR, now based on `main`:** remove native chat cost tracking and its dedicated admin UI. ## Summary Removes native per-message price calculation, model pricing fields, cost persistence, aggregate cost queries, and admin cost API types. It also deletes the Analytics and Spend pages plus their legacy redirects. The AI Gateway-backed per-chat cost row and compact budget indicators remain. The spend documentation is renamed to `spend-management.md` and updated for the remaining surfaces, group budget APIs, CSV export, upgrade handling for native pricing and cost history, and the absence of a deployment-wide spend dashboard. The per-chat cost API documents that data follows AI Gateway retention and reports zero after all matching requests are purged. No schema is dropped in this release. `chat_messages.total_cost_micros` remains nullable and unwritten so replicas from the previous release can continue inserting messages during rolling upgrades. #27600 tracks removal after the compatibility window. > Mux prepared this PR on Mike's behalf. |
||
|
|
f0e6ac64b3 |
feat: remove native chat usage limits in favor of AI Gateway budgets (#27329)
## Stack Context This stack makes AI Gateway data and budgets the source of truth for AI spend controls. 1. Re-back the per-chat cost endpoint with AI Gateway data (#27328, merged). 2. **This PR:** remove native chat usage limits. 3. Remove native chat cost tracking and its dedicated admin UI (#27330). ## Summary Removes the native usage-limit API, SDK types, SQL, and chat enforcement for deployment, user, and group chat limits. Compact AI Gateway budget indicators remain in the Agents sidebar, user menu, and group settings. Gateway budget rejections and provider quota failures continue to classify as usage-limit errors, including a 409 response for synchronous title generation. Budget-period labels now use the API's UTC boundaries, so users see the same dates in every browser timezone. The documentation explains the AI Gateway replacement, its licensing requirements, and the differences from native limits. No schema is dropped in this release. The usage-limit table, index, user and group columns, constraints, audit mappings, and generated scan fields remain for mixed-version rolling upgrades. #27600 tracks their removal after the compatibility window. ## Breaking change Native day, week, and month chat spend limits are removed and are not migrated. AI Gateway budgets are month-based, group-scoped with per-user overrides, and require the AI Gateway entitlement. Deployments without that entitlement no longer have chat spend enforcement. > Mux prepared this PR on Mike's behalf. |
||
|
|
bfcfb71860 |
fix: show 'Unset' for missing providers in AI models list (#27400)
## Summary
Frontend-only fixes for the `/ai/settings/models` page:
1. **Provider column displays "Unset"** with an info tooltip when a
model's provider has been deleted, instead of "N/A".
2. **Models without a usable provider display as "Disabled"** in the
list, regardless of the stored `enabled` flag. Covers both missing
(soft-deleted) and disabled providers.
3. **Save button re-enabled when only the provider changes** on the edit
page (previously the button stayed disabled because provider changes
lived outside the formik state).
## Scope
Frontend only. The DB constraint
`chat_model_configs_ai_provider_required_when_active` already prevents a
non-deleted model from having a NULL `ai_provider_id`; CODAGT-709
addresses the server-side cascade when a provider is deleted.
## Changes
- `ModelsPageView.tsx`: two `useMemo` maps (`hasProviderByModelId`,
`providerEnabledByModelId`) passed to `ModelRow`.
- `ModelRow.tsx`: `isEffectivelyEnabled = model.enabled && hasProvider
&& providerEnabled`. When `hasProvider` is false, renders "Unset" with a
standard `InfoIcon` tooltip.
- `ModelForm.tsx`: `canSubmit` OR's in `hasProviderChange` so the save
button enables when only the provider dropdown changes.
- `ModelRow.stories.tsx`: four stories covering baseline,
missing-provider (with tooltip assertion), disabled-provider, and
disabled-model paths.
- `ModelsPageView.stories.tsx`: `OrphanedModelShowsUnset` feeds an
orphaned model through the real derivation (map-miss + `?? false`),
matching the production shape produced by `deriveProviderStates`.
`DisabledProviderModelsStillListed` now asserts the "Disabled" badge.
- `ModelForm.stories.tsx`: `EditUpdateEnabledOnProviderChange` asserts
the save button is enabled when the selected provider differs from the
model's stored provider.
- `testFixtures.ts`: `mockOrphanedModel` fixture representing the
deleted-provider case.
Diff: 7 files, 240 insertions, 9 deletions.
> 🤖 This PR was updated with Coder Agents.
|
||
|
|
02fd1cc691 | feat: allow spawn_agent model and reasoning effort override (#27385) | ||
|
|
3227cac217 |
feat: add manual chat compaction via /compact (#27081)
Adds a user-triggered `/compact` action for Coder Agents chats: typing
`/compact` in the composer (or picking it from the `/` trigger menu)
summarizes the conversation so far to free up context window space.
## How it works
- New `POST /api/experimental/chats/{chat}/compact` endpoint
(owner-only, RBAC `ActionUpdate`, excluded from the public API reference
via `x-apidocgen skip`). It marks the chat with a durable one-shot
`chats.compaction_requested_at` signal and moves it `waiting -> running`
via a new `RequestCompaction` state transition; no message row is
inserted. AI Gateway attribution needs no per-request key: generation
preparation resolves the owner's synthetic API key (#27170) like any
other turn.
- `RequestCompaction` hands off chat ownership (clears
`worker_id`/`runner_id`) so a worker acquisition hint is published;
since the transition changes no history, the previous runner could
otherwise miss the request under reordered pubsub delivery.
- The background chat worker picks the chat up like any other turn. A
pending manual request takes precedence over turn completion in the
generation decision, and forces compaction even below the automatic
threshold (and when compaction is disabled via threshold=100). The
commit step consumes the request marker in the same transaction; any
transition that ends the turn clears stale markers.
- The summary triplet reuses the automatic-compaction path, now tagged
with a `source` (`automatic` | `manual`) that is plumbed through
streamed progress parts, persisted tool JSON, and the UI label
("Summarized (manual)").
- Validation order: busy chats reject with 409 (state-machine conflict),
empty/already-compacted chats with 409 "nothing to compact", archived
chats with 400; the owner usage-limit check runs last so no-op requests
surface the specific conflict instead of a limit error.
- Web UI: the `/` trigger menu now has a built-in "Commands" group
listing `/compact`; submit intercepts exactly `/compact` and calls the
endpoint instead of sending a message. A personal or workspace skill
named `compact` takes precedence over the built-in command; while skill
collisions are still resolving, an exact `/compact` submission is
blocked with a retryable hint instead of leaking as message text.
History and queued-message edits are never intercepted. After
compaction, the context usage indicator resets to its unknown state
until the next assistant response reports fresh usage, instead of
showing the stale pre-compaction number.
- codersdk: `ExperimentalClient.CompactChat`.
Worker-path execution (rather than compacting synchronously in the
handler) reuses the existing lock fencing, live "Summarizing..."
streaming, retry accounting, restart resilience, and debug-run
observability. Rationale documented in `coderd/x/chatd/ARCHITECTURE.md`.
## Testing
- State machine: transition-matrix coverage for `RequestCompaction`,
marker lifecycle tests (carried by lease renewals/queue appends, cleared
by terminal transitions, consumed by commit), ownership handoff +
acquisition hint assertions.
- Worker: decision-ordering and forced-compaction unit tests;
active-server end-to-end test (manual compact below threshold produces a
`source=manual` summary, returns to `waiting`, no assistant follow-up;
busy chat rejected).
- API: success, archived, non-owner, RBAC-denied, empty-chat, no-daemon
cases; usage-limit ordering (at-limit owners still get
state/nothing-to-compact conflicts for no-op requests, with marker
rollback).
- Frontend: Storybook play tests for the Commands menu group, submit
intercept, skill-name collision, queued-edit passthrough, and
manual/automatic tool rendering; unit tests for command availability
resolution and the post-compaction context usage reset.
> This PR was created by Mux, an AI coding agent, working on Mike's
behalf.
|
||
|
|
9f4ddea571 |
feat: revoke MCP server OAuth grants at the provider on disconnect (#27300)
Closes [CODAGT-805](https://linear.app/codercom/issue/CODAGT-805/revoke-oauth-grants-at-the-source-for-mcp-servers). The experimental MCP server OAuth2 disconnect endpoint previously deleted only the stored token row, leaving the grant active at the OAuth provider. This PR adds provider-side token revocation while keeping local disconnect independent of provider availability. ## Changes - Add `mcp_server_configs.oauth2_revocation_url` in migration `000547`. The value can be configured manually, discovered from RFC 8414 metadata, and managed through the MCP server settings UI. Non-admin responses redact it with the other OAuth2 fields. - Revoke the refresh token first through the RFC 7009 endpoint, then fall back to the access token only for `unsupported_token_type`. Public clients send `client_id`; confidential clients use `client_secret_basic`. - Delete the local token transactionally before best-effort provider revocation. Callers without a token receive the same response for hidden and nonexistent config IDs, and provider failures return a generic warning without exposing provider response bodies. - Require HTTPS revocation endpoints except for HTTP loopback URLs. Redirects must preserve the POST and remain on the configured origin. Redirect errors omit provider-controlled paths and query strings so reflected token material cannot enter logs. - Treat `200 OK` and `204 No Content` as completed revocations. `202 Accepted` remains a failure because it does not confirm completion. - Prevent an in-flight refresh from recreating a token deleted by disconnect. Refresh persistence now uses an optimistic update keyed by token ID and `updated_at`; only the OAuth callback can create a token row. Refresh conflicts reload the current row or clear in-memory auth when disconnect deleted it. - Return `{token_revoked, token_revocation_error}` from disconnect, while retaining SDK compatibility with the legacy `204` response. The UI surfaces provider revocation failures as warning toasts. - Document revocation endpoint discovery, HTTPS requirements, and best-effort disconnect behavior. No token or no configured revocation URL returns `token_revoked: false` without an error, so disconnect remains idempotent. > Updated by Mux, an AI coding agent, on Mike's behalf. |
||
|
|
1ac106255b | feat: add Anthropic 1M context window toggle for Agents model configs (#27257) | ||
|
|
c84aa564ba |
docs: normalize code-fence languages for Shiki compatibility (#27161)
Normalizes non-standard code-fence language tags across `docs/**` so a strict highlighter (Shiki, used by Fumadocs) won't fail the build on an unrecognized language, and unifies redundant synonym tags onto one canonical form per language. The current renderer (Speed-Highlight) detects the language from the code content, not the fence label, so this drift wasn't visible until now. ## Changes - `hcl` -> `tf` (199 fences, including indented ones nested in numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**` is actually Terraform resource/data/provider syntax, so the more specific `terraform` grammar is correct for all of them. `tf` is Shiki's own alias for that grammar, and it's also what GitHub's own markdown renderer resolves to the same HCL/Terraform highlighting. - `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a registered file extension (`.ps` isn't), so `ps1` renders identically to `powershell` there today while bare `ps` would silently lose highlighting. - `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files) - `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text fallback either way, just shorter. - `Dockerfile` -> `dockerfile` (lowercase) - `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all three to a single shell grammar; this was already the style guide's stated preference, just not enforced across the existing corpus until now. - `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki and GitHub. - `jsonc` -> `json` (1 fence). The block has no comments or trailing commas, so it doesn't need the comments-capable grammar. - `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`). Verified the actual content tokenizes identically under both grammars, and a sibling block in the same file already needs `tsx` for real JSX, so unifying to one tag is safe for this file. Documented a caveat: `tsx` mis-tokenizes the legacy angle-bracket type-assertion syntax (`<Type>value`), which is invalid in real `.tsx` files anyway, so use `value as Type` instead. - `yml` -> `yaml` (1 fence) - Updated `docs/.style/style-guide/formatting.md` to document all canonical tags `promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki doesn't bundle a grammar for either, so they need a custom grammar registration when the site adopts Shiki, rather than degrading to `txt`. Tracked as follow-up work under DOCS-118 and [DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting) (promql). Does not touch `offlinedocs/`. Linear: [DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs) <details> <summary>How the fence tags were verified</summary> Each tag was tested against a real `shiki@latest` highlighter instance (`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's `@wooorm/starry-night` grammar sources (the renderer that actually displays these `.md` files today, in repo browsing and PR diffs), since that's what determines whether brevity is safe before Shiki adoption: ```text FAIL env -- Language `env` is not included in this bundle. FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle. FAIL promql -- Language `promql` is not included in this bundle. FAIL caddyfile -- Language `caddyfile` is not included in this bundle. FAIL pwsh -- Language `pwsh` is not included in this bundle. FAIL output -- Language `output` is not included in this bundle. ``` `hcl` doesn't error in Shiki, since it's a real grammar, but that's exactly the trap: it was silently rendering every fence with the generic HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged fence in `docs/**` was manually checked against `origin/main` and is genuinely Terraform content. For `ts`/`tsx`, tokenizing the actual doc content confirmed identical output under both grammars; a synthetic test with the legacy angle-bracket cast syntax confirmed `tsx` degrades on that specific construct, which the style guide now calls out. The first normalization pass only matched fence tags at column 0 (`^```tag$`), missing tags indented inside numbered/bulleted lists. A follow-up pass caught the remaining occurrences at any indentation level. </details> --- *This PR description and the underlying changes were prepared with Coder Agents assistance.* |
||
|
|
55b06f14a3 | feat: allow overriding advisor reasoning effort (#27196) | ||
|
|
6f6d7539c8 |
feat: remove unused chat statuses pending, paused, and completed (#27064)
The chatd state machine only recognizes `waiting`, `running`, `error`, `requires_action`, and `interrupting`. Remove the unused `pending`, `paused`, and `completed` values from the database enum, backend, SDK, frontend, generated queries, and API docs. Migration `000543_chat_status_remove_unused` remaps existing `pending` rows to `running`, remaps `paused` and `completed` rows to `waiting`, drops the obsolete `idx_chats_pending` index, and recreates `chats_expanded` around the enum swap. It also removes the dead `AcquireChats` query and all remaining query literals for the deleted statuses. **NOTE**: The enum swap can break chat queries from older replicas during a mixed-version rollout because they still reference `'pending'::chat_status`. Chats are experimental, so this PR accepts that limited rollout window instead of adding a two-release expand and contract sequence. > This PR was authored by Mux (AI agent) on Mike's behalf. |
||
|
|
9af3d31036 | fix: relabel advisor max uses setting from per run to per turn (#27046) | ||
|
|
14767dfa8e |
feat: explain missing POSIX sh on Windows workspaces (#27048)
When a workspace has no POSIX sh on PATH (typical for fresh Windows workspaces), the execute tool fails with a raw `exec: "sh": executable file not found in %PATH%` error the model cannot act on. This change: - Enriches the above error in chattool with remediation steps and a docs link. - Documents the requirement in the Coder Agents architecture page. > This PR was generated by Coder Agents on behalf of @johnstcn |
||
|
|
7c78698a6d | feat: notify users when chats are shared (#26914) | ||
|
|
6b8c38b5a4 | fix: gate chat advisor and virtual desktop behind experiments, delete experiments page (#26809) | ||
|
|
2fd5ae4323 |
fix: stop Agents dead-ending on unsupported providers (#26841)
Configuring only a GitHub Copilot provider left the Agents page stuck on "set up a provider then add a model", even with a provider and models configured. The catalog dropped any provider type that NormalizeProvider did not recognize, so a Copilot-only deployment looked identical to an empty one and never unlocked the page. The Agents harness cannot use Copilot: it needs a per-request token only an official Copilot client can mint, and the harness is not one. Instead of dropping such providers, the catalog now reports them as unsupported so the UI can explain the dead end and point elsewhere, rather than ask for setup that already happened. The providers stay usable through the AI Gateway proxy. Support is derived from the provider type, not stored, so there is no migration. codersdk.IsAgentsUnsupportedProviderType is the single source of truth, consulted by the chatd catalog and, through the generated AgentsUnsupportedProviderTypes list, the frontend. The diff also carries unrelated modernization of nearby db2sdk and chatprovider helpers (slices.SortFunc, strings.Cut, range-over-int). Closes CODAGT-627 Refs CODAGT-256 Refs CODAGT-682 |
||
|
|
5f42bbcdbf |
feat(site/src): nest agent pages under a Coder Agents subsection in AI nav (#26667)
Groups the agent-related AI settings pages under a new **Coder Agents** parent in the sidebar, with a continuous left rule connecting the children and an active-segment indicator that lights up the rule where the current sub-item sits. The new nav order: - AI Governance - AI Gateway keys - Providers - Coder Agents - Models - MCP servers - Templates - Spend - Instructions - Lifecycle All target pages already exist on main (Danielle's recent migrations of Models, MCP servers, Templates, Instructions, Lifecycle, Spend, and Coder Agents into AI Settings). This PR only changes the sidebar visual structure: the children move into an indented group with a `border-l border-l-border` rule, and the active child paints a `border-l-content-primary` segment over that rule via `-ml-px` so the rule and indicator share a column instead of stacking. <details> <summary>Design notes</summary> Concept 1 from the earlier exploration: always-expanded with indents, the parent is its own page. Chosen because it adds no expand/collapse state, no "which child is the default" question, and no animation work; the parent reuses the existing nav-item, and the children sit in a wrapper `div` with a left rule. The site bundle ships without Tailwind's preflight, so the wrapper and sub-item borders are paired with `border-solid` to actually paint, matching the pattern already in `Sidebar.tsx`. </details> --- _This PR was prepared by Coder Agents on behalf of @tracyjohnsonux._ |
||
|
|
59fcc9c0ad |
feat: improve sub-agent orchestration tools (#26673)
Tool errors caused orchestrators to abandon spawned agents. Bare error responses and the close_agent name framed delegation as one-shot: one transient failure or timeout ended the work, and the orchestrator had no way to recover or reuse agents. Renames close_agent to interrupt_agent with a hidden backward-compatible alias. wait_agent and message_agent return structured payloads instead of bare errors, so the orchestrator can retry after a timeout, recover from an error status, or redirect an idle agent. Adds list_agents so orchestrators can rediscover spawned agents. Adds root-only orchestration guidance for error recovery. |
||
|
|
48fd0ef4bc |
feat: return workspace skill directory from read_skill (#26713)
Workspace skills live on the workspace filesystem, and the agent's read_file and execute tools already operate there. read_skill now returns "dir", the absolute skill directory, for workspace skills, so the agent can read or run bundled supporting files (for example a scripts/ helper) with the workspace tools. The field is omitted for personal skills, which are database-backed and have no files. read_skill_file is unchanged. Generated with Coder Agents on behalf of @kylecarbs. |
||
|
|
a1921b6bc0 |
docs: update AI Gateway URLs from /aibridge to /ai-gateway (#26664)
## Description Updates documentation to use the new `/api/v2/ai-gateway/` URLs and `/ai-gateway/` UI paths, following the backend rename in #26475 and frontend route rename in #26569. ## Changes - Update URL references across documentation files from `/api/v2/aibridge/` to `/api/v2/ai-gateway/` - Update UI path reference from `/aibridge/sessions` to `/ai-gateway/sessions` - Update route path references in client setup guides - Covers client setup guides, authentication, monitoring, proxy setup, and provider configuration Addresses https://github.com/coder/coder/pull/26475#issuecomment-4768351217 Refs https://linear.app/codercom/issue/AIGOV-226 > Generated with the assistance of Coder Agents (@ssncferreira) |
||
|
|
2d28c1b396 |
feat: surface template README to agent template tools (#26334)
Fixes CODAGT-447. Alternative implementation of https://github.com/coder/coder/pull/26212 and https://github.com/coder/coder/pull/25978 - Adds up to the first 1000 characters of `README.md` (with leading frontmatter stripped) to `chattool.list_templates` output - Adds up to 800 characters of `README.md` to `chattool.read_template`. **Note:** skipping `toolsdk` versions to keep scope small. > 🤖 Generated by Coder Agents |
||
|
|
85652554f9 | feat: move MCP servers to AI settings (#26642) | ||
|
|
3133a8b9c6 | feat: move instructions to AI settings (#26624) | ||
|
|
ecfff8a7db | feat: move model settings page to ai settings | ||
|
|
bc44cdda75 |
feat: rank chat workspace templates (#25037)
closes CODAGT-203
## Summary
`list_templates` now returns a ranked shortlist with a recommendation,
so the chat agent can pick the right template the way a colleague would:
prefer what matches the request, what the user already uses, and what
the rest of the organization uses. Instead of teaching the model an enum
protocol in prompts, every result carries a fixed `next_step`
instruction telling the agent what to do.
## How list_templates works
1. **Fetch**: active, non-deprecated templates in the chat's
organization, filtered by the admin template allowlist, authorized as
the chat owner (no system escalation).
2. **Query relevance** (optional `query` argument): each template
receives the highest tier any of its fields matches, and a higher tier
always outranks a lower one regardless of usage:
| Tier | Match |
|------|-------|
| 4 | name or display name equals the query |
| 3 | name or display name starts with the query |
| 2 | name or display name contains the query |
| 1 | description contains the query (checked only when no name field
matched) |
| 0 | no match; the template is excluded |
Matching is case-insensitive and ignores spaces/hyphens/underscores
(`python gpu` matches `python-gpu`).
3. **Usage signals**: a new `GetTemplateRankingSignalsByOwnerID` query
returns, per template, the owner's active and recently-deleted workspace
counts within a 60-day window, the last in-window usage, and the count
of distinct developers with an active workspace (unclaimed prebuilds
excluded).
4. **Affinity score** (computed in Go, per template, from that
template's signals only):
```text
affinity = 10 x (active + 0.5 x deleted) x 0.5^(days_since_last_use /
14)
+ ln(1 + active_developers)
```
`active`/`deleted` are the owner's in-window workspace counts,
`days_since_last_use` is measured from the most recent in-window usage
(the personal term is zero without in-window usage), and
`active_developers` is the org-wide count. Personal usage carries 10x
the weight of org popularity; the confidence floor is the score of two
active developers (`ln 3`) and the required lead over the runner-up is
`ln 3 - ln 2`.
5. **Rank**: query tier first (when a query is present), then affinity
score, then name/ID for determinism. Results paginate 10 per page with
`next_page` present only when more exist.
## Recommendation contract
The result tells the agent what to do next instead of describing
confidence levels:
- `recommended_template_id` is present only when the top template is a
clear winner: the only available template, a decisive query match, or an
affinity score that clears a floor and leads the runner-up by a derived
margin.
- `next_step` is always present and is one of four fixed sentences: use
the recommendation, ask the user to choose, retry a query that matched
nothing, or report that no templates are available.
Per-template items carry raw evidence (`active_developers`,
`your_workspace_count`, `last_used_by_you`) rather than derived labels.
When signals fail to load, the tool logs and degrades to asking the user
unless the query alone is decisive.
Prompts and the `create_workspace`/`read_template` descriptions
reference the field through the `chattool.NextStepField` constant, so
the instruction lives in one place and cannot drift. `create_workspace`
remains idempotent and allowlist-enforced.
## Authorization
The signals query runs with the chat owner's permissions: reading the
owner's own workspaces plus a template-metadata read for the cross-user
popularity count. dbauthz rejects the call if any requested template is
not readable by the owner (covered by allow and deny method tests).
## Docs
Adds `docs/ai-coder/agents/tools/` explaining how agent tool calls work,
with `list_templates` ranking and the `next_step` contract as the first
documented tools.
|
||
|
|
79a28bad72 | feat(site): group shared agents in sidebar (#26328) | ||
|
|
efbaedeefb |
docs: clarify Coder Agents AI Gateway routing (#25852)
> Mux updated this PR on behalf of Mike. Clarifies that Coder Agents route through AI Gateway automatically, while admins configure Agents providers with upstream provider or proxy endpoint/base URLs. Moves Agents-specific setup and credential guidance into the Agents models page, removes the obsolete AI Gateway Coder Agents client page, removes Coder Agents from the AI Gateway external client list, and links BYOK credential selection to the global AI Gateway BYOK setting. |