mirror of
https://github.com/coder/coder.git
synced 2026-11-01 04:47:17 +08:00
351bb1403250c834d5d065a01252b3283b238d72
310
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
351bb14032 |
feat: mount chat API routes under /api/v2 (#28496)
## Stack context This is the base of a 3-PR stack promoting the chat API from `/api/experimental` to `/api/v2`: server compatibility mounts (this PR), codersdk promotion (#28497), and frontend path updates (#28498). ## Summary Double-mount the stable chat and MCP handlers under `/api/v2` while retaining the existing experimental routes for the one-release compatibility window decided in CODAGT-921. CODAGT-922 tracks removing the compatibility mounts. The shared route builders preserve existing authentication and middleware behavior. Experiment-gated, debug, tombstone, and legacy default-organization model routes remain experimental-only. Signed file URLs, external OAuth callback URLs, and mixed-version replica relays also remain on the experimental prefix during the transition. Update Swagger and the generated API reference for the promoted routes, including the workspace lookup and a runnable raw-body chat file upload example. Retain internal endpoints outside the published reference, share chat-file rate limits across both prefixes, enable CORS for the v2 MCP routes, and cover dual mounts plus exclusions with compatibility tests. Remote dogfood UAT passed for the promoted chat, model, MCP, and file flows. > [!NOTE] > Xum acted on Mike's behalf in this pull request. <!-- xum-attribution: model=claude-fable-5 thinking=high --> |
||
|
|
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. |
||
|
|
56c614422e |
fix: clarify AI provider collision warnings (#28549)
AI provider collision warnings were only partially asserted, and the update coverage did not exercise a provider changing from a distinct hostname to a colliding hostname. Assert the complete warning consistently across create, get, list, and update responses, cover collisions introduced by base URL and enabled-state updates, and only return the proxy-specific warning when AI Gateway Proxy is enabled. Clarify that lifecycle status values are reported by the provider metrics. Follow-up to #28208. > [!NOTE] > Generated by Coder Agents for @ssncferreira. |
||
|
|
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) | ||
|
|
042421694f |
fix: surface duplicate AI provider hostname as warning, not error (#28208)
Two live `ai_providers` rows can share the same `base_url` hostname.
This is an intended configuration (AIGOV-97): the direct routing path
(`/api/v2/ai-gateway/{name}/...`) routes by provider name and fully
supports it. Only the MITM proxy path (`aibridgeproxyd`) cannot
disambiguate, because its `nameByHost` map is 1:1.
`classifyProviderRow` marked the second provider as
`ProviderStatusError`, which surfaced as a misleading log warning and a
`status=error` Prometheus label. The provider is not actually broken; it
is fully routable via the direct path. The error was only visible in
server logs and Prometheus, not in the API or UI.
This change:
- Extracts `BaseURLHostname` into `coderd/aibridged` and eliminates
three duplicate implementations (proxy classifier, chatprovider, and the
API layer now uses it for status checks).
- Downgrades the proxy classifier from `ProviderStatusError` to a new
`ProviderStatusProxyExcluded` status. The provider is not broken; it is
just not reachable via the MITM proxy path.
- Adds `Status *AIProviderStatus` to `codersdk.AIProvider` with
`Warnings []string`, matching the `WorkspaceProxy` precedent.
- Populates warnings on create, update, GET, and list when a provider's
hostname collides with another enabled provider.
- Adds an integration test proving that a duplicate provider is routable
via the direct path but not via the proxy path.
Refs AIGOV-596
Generated by Coder Agents
https://github.com/user-attachments/assets/bf323837-5121-4d1b-ab19-593f1d32374e
|
||
|
|
54d4ae9aca | fix: detect Xum client in aibridge after Mux rename (#28448) | ||
|
|
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._ |
||
|
|
4ce8e8ed56 |
docs: address AI Gateway documentation review feedback (#28309)
Applies the review feedback from #27794. Prose only. --------- Co-authored-by: Nick Vigilante <nickvigilante@users.noreply.github.com> |
||
|
|
c6deadbc6c |
docs: fix broken .style/ link and lift details block out of list item [DOCS-661] (#28180)
## What Two small docs fixes, split out of the offlinedocs Fumadocs migration (#27390) so that PR stays a focused tooling change and these land on their own review track. - `docs/about/contributing/documentation.md`: the Vale style-guide link pointed at `docs/.style/style-guide/`, which is excluded from the published docs corpus, so the relative link 404s on the live site. Repointed to an absolute github.com URL. - `docs/ai-coder/ai-gateway/monitoring.md`: lifted the "Possible client values" `<details>` block out of the list item so it renders as a top-level accordion, and restored a dropped blockquote continuation marker (`>`). ## Why Both are genuine docs bugs on their own: - The `.style/` link is broken on the live site today, because that directory is intentionally excluded from the published corpus. - The `<details>` nested inside a list item renders inconsistently; lifting it to a sibling block is portable across renderers. They are also prerequisites for the offlinedocs Fumadocs migration, whose stricter build-time sync hard-fails on unmapped inter-doc links and only converts a `<details>` to an accordion when it is a list sibling. Landing them here first lets the migration PR drop these two files on its next rebase. ## Validation - `make fmt/markdown` and `make lint/markdown`: clean (via pre-commit-light). - Docs-only change; no CI or build config touched. > This PR was created with AI assistance (Coder Agents). |
||
|
|
d989ae36cd |
docs: clarify who can set AI model prices and how they are keyed (#28401)
The docs named the `ai_model_price:update` permission but never said which role holds it, and nothing anywhere explained that a price is keyed by provider type and model, so every configured provider of that type shares it. This names the Owner role, documents the keying and why `openai-compat` cannot be priced, and repeats both in the CLI's `--provider` descriptions and `update` help. > [!NOTE] > Initially generated by Claude Opus 5, modified and reviewed by @ssncferreira |
||
|
|
d58788cb23 |
fix: clarify AI model price configuration (#28372)
## Description Model prices displayed in the Agents model form are read-only because they are managed by AI Gateway. Add guidance and a link to the model price configuration documentation, and rename the related documentation subsection to **Configure model prices**. > [!NOTE] > Generated with Coder Agents by @ssncferreira. |
||
|
|
50ecd6959f |
feat: add a source filter to the AI model price list (#28329)
## Description With prices from the price book and prices set through the API both in the table, `list` showed only the price in effect and gave no way to tell where it came from. There was also no way to see the price book's entry for a model that had been overridden, since the listing resolves to the custom price. This adds a `source` column to the output and a `--source` filter for narrowing to one source, or to every row with `all`. Note: `--source` selects rows rather than models. A model carrying both a price book price and a custom one appears under either value, so the two filtered listings do not sum to the unfiltered one. `--source all` reports both rows at once. ## Changes - Add `Source` to `codersdk.AIModelPrice` and `AIModelPricesFilter`, and map it in `db2sdk`, which previously dropped it. - Filter `GetAIModelPrices` by source before resolution, so the price book's row for an overridden model stays reachable. - Accept `all` as a source, which reports every price a model holds instead of resolving to one. - Accept a `source` query parameter on the list endpoint, rejected with a 400 when outside the enum. - Add `--source` to the list command and a `source` column to its output. - Document the column and the filter, and lead the price section with `coder exp ai-model-prices list`. - Distinguish a deployment's default prices from the price book that ships with each release. Closes https://linear.app/codercom/issue/AIGOV-593 > [!NOTE] > Initially generated by Claude Opus 5, modified and reviewed by @ssncferreira |
||
|
|
19d1ee9fc8 |
feat: support custom prices for models in the price book (#28328)
## Description The experimental CLI could only price models the price book does not cover, so an operator with a negotiated rate for a model Coder already prices had no way to record it. The restriction existed because a single row served both the price book and prices set through the API, and the startup seeder would overwrite an override on the next restart. Each source now keeps its own row (https://github.com/coder/coder/pull/28204), so that no longer applies. This removes the restriction: a price set through the CLI takes effect over the price book for any model, and the book stays underneath it. ## Changes - Remove the validation that rejected models the price book covers. - Delete `prices.IsDefaultPriced` and the index behind it, which existed only for that check. - Generalize the `coder exp ai-model-prices update` help. - Document that a custom price overrides the price book and does not follow its updates. - Rework the spend approximation callout around what a custom price can and cannot correct. Closes https://linear.app/codercom/issue/AIGOV-594 > [!NOTE] > Initially generated by Claude Opus 5, modified and reviewed by @ssncferreira |
||
|
|
2f996d765a |
feat: remove task management MCP tools (#28354)
Removes the six task-management tools from the MCP tool surface in `codersdk/toolsdk`: - `coder_create_task` - `coder_delete_task` - `coder_list_tasks` - `coder_get_task_status` - `coder_send_task_input` - `coder_get_task_logs` Both the coderd-hosted MCP server (`coderd/mcp`) and the CLI `coder exp mcp server` derive their tool list from `toolsdk.All`, so removing the registry entries removes the tools from both servers with no server-side changes. The MCP server documentation (`docs/ai-coder/mcp-server.md`) is updated to drop the task-management entry from the tool overview. ## What stays - `coder_report_task` is intentionally kept: it is the agent-side status-reporting mechanism (`WithTaskReporter`), already excluded from the hosted MCP server, and required by `coder exp mcp server`, Claude Code configuration, and scaletest. - The `codersdk` Task SDK methods (`CreateTask`, `DeleteTask`, `Tasks`, `TaskLogs`, etc.) and the Tasks feature (CLI, UI, API) are untouched; this PR only removes MCP tool registration. - The task-only `taskIDDescription` helper is deleted; `userDescription` stays (used by `coder_create_workspace`). The code change is deletion-only: 970 removed lines across `toolsdk.go` and its test file, no added behavior. ## Validation - `go build ./...`, `go test ./coderd/mcp/`, and targeted `golangci-lint` pass. `go test ./codersdk/toolsdk/` passes all tests; the package-level goleak failure (agentssh goroutines) reproduces identically on unmodified `main` and is unrelated to this diff. - `pnpm run lint-docs` passes on the docs change. - Remote dogfood UAT ran against the toolsdk change and passed: `tools/list` on both the hosted MCP endpoint and `coder exp mcp server` confirms the six tools are absent and the remaining surface is intact (34 hosted tools; CLI adds `search`/`fetch`), a `tools/call` of `coder_get_authenticated_user` succeeds, and calling a removed tool returns `-32602 unknown tool`. `coder_report_task` still registers in the CLI server when `CODER_MCP_APP_STATUS_SLUG` is set. - The failing `Pixel / Review` commit status is unrelated: this PR contains no `site/` changes, and the same status fails on the last 8 `main` commits including this PR's merge base (`676b9bb06bf`). > Mux acted on Mike's behalf to create this pull request. |
||
|
|
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 --> |
||
|
|
dd43574990 |
refactor: remove AI add-on badge, seat column, and add-on wording leftovers (#28004)
Removes all "AI add-on" labeling from the UI, plus two leftover "AI
Governance add-on" wording items from the licensing repackaging (AI
Governance is now included with Premium).
- Remove the **AI add-on** badge from the group settings AI budget
section and the AI Governance add-on card on the Licenses page.
- Remove the **AI add-on** column (check icon showing AI seat
consumption) from the Users and Organization Members tables, along with
its help popover, the `AISeatCell` component, and the
`shouldShowAISeatColumn` entitlement helper.
- Update related Storybook stories.
- Drop "add-on" from the AI cost control route comments in
`enterprise/coderd/coderd.go` and the `coder exp ai-model-prices`
prerequisite in `docs/ai-coder/ai-gateway/cost-controls.md` (leftovers
not covered by #28075/#28077/#28268).
The `has_ai_seat` API field is left intact.
<details>
<summary>Removal scope</summary>
Badge usages removed:
- `site/src/pages/GroupsPage/GroupSettingsPageView.tsx`
-
`site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/AIGovernanceAddOnCard.tsx`
AI seat column plumbing removed:
- `site/src/pages/UsersPage/UsersTable.tsx` and `UsersPage.tsx`
- `site/src/pages/OrganizationSettingsPage/OrganizationMembersTable.tsx`
and `OrganizationMembersPage.tsx`
- `site/src/modules/users/AISeatCell.tsx` (deleted)
- `AiAddonHelpPopover` in `site/src/modules/users/UserHelpPopovers.tsx`
- `shouldShowAISeatColumn` in
`site/src/modules/dashboard/entitlements.ts`
Add-on wording leftovers:
- `enterprise/coderd/coderd.go`: 7 route comments (comments only, no
behavior change)
- `docs/ai-coder/ai-gateway/cost-controls.md`: model prices CLI
prerequisite
</details>
---
🤖 This pull request was generated by Coder Agents on behalf of
@tracyjohnsonux.
|
||
|
|
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>
|
||
|
|
7ff1278ab3 |
feat: track Junie as an AI Gateway client (#28266)
## Problem Junie CLI works with AI Gateway, but every Junie session is recorded as `Unknown`. Junie sends `User-Agent: Junie:SNAPSHOT` (observed directly from the CLI), which `GuessClient` does not match, so usage, spend, and audit views cannot attribute Junie traffic. There were also no docs for pointing Junie at AI Gateway. ## Fix - Detect the observed `junie:` user-agent prefix and add the `Junie` client value. - Add the Junie icon so sessions render with a logo instead of the fallback question mark. - Add a Junie client page and list it in the compatibility table. - Add `Roo Code` and `Charm Crush` to the documented `client` filter values. Both were already implemented but missing from the list. ## Supported configurations | Provider | API type | Endpoint | |-----------|-------------------|--------------------------| | OpenAI | `OpenAIResponses` | `/openai/v1/responses` | | Anthropic | `Anthropic` | `/anthropic/v1/messages` | BYOK works on both through `extraHeaders` with `X-Coder-AI-Governance-Token`. Preview: https://coder.com/docs/@matifali-junie-ai-gateway-client/ai-coder/ai-gateway/clients/junie > 🤖 This PR was created with the help of Coder Agents, and needs a human review. 🧑💻 |
||
|
|
023f61626d |
feat: default AI Gateway sessions list to a 24h time range (#28256)
The AI Gateway sessions list page takes 5-13 seconds to load because `ListAIBridgeSessions` scans all `aibridge_interceptions` rows (~1M on dogfood) when no time filter is set. This PR defaults the list to the last 24 hours of sessions, reducing the scan by roughly two orders of magnitude without any backend or migration changes: the `started_after`/`started_before` filters already exist end-to-end in SQL, searchquery, and the API. The default range is held in component state (not the URL) and merged into every query payload including prefetches, so the unbounded query never runs on page load. A time range filter in the filter bar lets users override the window explicitly, which doubles as a forensic tool. Picking a range writes quoted RFC 3339 timestamps into the existing filter query. There are no presets and no unbounded "all time" mode, so the fast path is the only path. Existing "All sessions"/"My sessions" presets reset the filter query, which resets the time window to the default 24 hours; that is intentional. Also makes the five filter triggers a uniform width and left-aligns the new picker so the search input keeps room on wide viewports. Depends on #28255 (the DateTimeRangeFilter component) and #28254 (filterQuery serialization). 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) |
||
|
|
71b5bc398f |
docs: fix broken callout on the AI Gateway Monitoring page (#28303)
The callout on this page is broken, as flagged by Atif. This PR moves the callout out of the `<details>` block to avoid the broken formatting. Fixes DOCS-679 <!-- If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. --> |
||
|
|
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 |
||
|
|
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.* |
||
|
|
63641b98c8 |
fix: treat a missing serve endpoint as a fatal dial error (#27864)
Adds 404 as a terminal error for establishing DRPC connection. A standalone AI Gateway pointed at a coderd that does not expose `/api/v2/ai-gateway/serve` gets a 404, which the connect loop classified as transient and retried forever. Redialing cannot fix a missing endpoint. 404 now is treated as terminal handshake failure. `--url` is expected to point directly at coderd, so a 404 from an intermediary is not distinguished. Refs https://linear.app/codercom/issue/AIGOV-320/write-connection-tests --- Generated with Coder Agents. |
||
|
|
34e95c46bf |
docs: note JetBrains client attribution in AI Gateway (#28296)
Noticed while testing Junie that JetBrains AI Assistant sends `User-Agent: ktor-client`, the stock Ktor default, so AI Gateway records these sessions as `Unknown`. Admins who enable Gateway for governance won't see their JetBrains attributed in the sessions view or the `client` filter. Documents the behavior on the JetBrains client page. Nothing to fix on our side, matching `ktor-client` would misattribute any other Ktor-based application. |
||
|
|
ddcffd8248 | docs: remove inaccurate Agent Firewall filesystem protection claim (#28286) | ||
|
|
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. |
||
|
|
062c0fdd3b |
docs: rebrand Windsurf doc page to Devin Desktop (#28205)
## Summary Cognition (maker of Devin) rebranded the Windsurf Editor as Devin Desktop on June 2, 2026, after acquiring it from Codeium in July 2025. Our docs still referred to the editor as Windsurf and linked to a dead `codeium.com` domain. ## Changes - Renamed `docs/user-guides/workspace-access/windsurf.md` to `devin-desktop.md`, rewritten to lead with Devin Desktop branding, note the Codeium -> Windsurf -> Devin Desktop history, and use current links (`windsurf.com`, `docs.windsurf.com`) instead of dead `codeium.com` ones. - Updated `docs/manifest.json` and `docs/user-guides/workspace-access/index.md` to reference the new page. - Updated remaining Windsurf mentions to Devin Desktop in `docs/ai-coder/ide-agents.md`, `docs/ai-coder/index.md`, `docs/reference/glossary.md`, and `docs/ai-coder/ai-gateway/clients/index.md`. - Added `windsurf.com`/`devin.ai` to `.github/.linkspector.yml` ignore patterns; both rate-limit repeated automated requests with 429s (same class of issue as the `codeium.com`/`marketplace.visualstudio.com` fix in #28203). - Switched every module reference from `windsurf` to the new `devin-desktop` registry module (`docs/about/contributing/modules.md`, the three `get-started/customize-your-template/*.md` Terraform tutorials, and the main doc page's module link), since the new module actually renders `display_name = "Devin Desktop"` / `slug = "devin-desktop"` in the UI (the old `windsurf` module hardcodes "Windsurf Editor"). <details> <summary>Scope notes / sequencing</summary> The `devin-desktop` module referenced here is being added in [coder/registry#1050](https://github.com/coder/registry/pull/1050) (not yet merged/released). That PR is itself gated on [coder/coder#28214](https://github.com/coder/coder/pull/28214) (whitelisting the `devin:` URI scheme) shipping in a released Coder version first. This docs PR can merge independently, the module link will 404 until #1050 is released, same as any docs-ahead-of-registry-release sequencing. The Terraform code samples now show `module "devin-desktop"` because that module's `display_name`/`slug` are properly parameterized (unlike `windsurf`, which hardcodes "Windsurf Editor"/`windsurf` regardless of what's passed in), so the docs stay accurate to the rendered UI. </details> ## Validation - `make lint` (docs lint, markdownlint, repo checks) passes. - Manually verified the new outbound links (`docs.windsurf.com`) return 200; `windsurf.com`/`devin.ai` are rate-limited (429) from this environment too, hence the added ignore patterns. Stacked on #28203 (targets that branch so the diff here stays scoped to the rebrand; will retarget to `main` once #28203 merges). > 🤖 This PR was created with the help of Coder Agents, and needs a human review. 🧑💻 |
||
|
|
db3566c1a3 |
chore: correct AI Gateway metric provider label and cardinality notes (#28220)
The cardinality notes in `aibridge/metrics/metrics.go` assume the `provider` label takes one of three values, and two for the key pool metrics. That was accurate when the notes were written: `provider` is the provider instance name, and the name defaulted to one of the three provider types aibridge supports. Instances can now be given their own names, so the label takes any configured name and the series counts scale with the number of configured providers rather than being capped at a fixed number. The monitoring docs are also updated to make clear that `provider` is the provider instance name. Comments and documentation only, no behaviour change. Follow-up to #28210. |
||
|
|
95328f1ead |
fix: label unpriced token usage metric by provider name and type (#28210)
## Problem The `provider` label was inconsistent between AI Gateway metrics. Every metric emitted by the gateway labels `provider` with the provider instance name, for example `anthropic-eu`, while `coder_ai_gateway_cost_control_unpriced_token_usage_records_total` used the provider type, for example `anthropic`. The two could not be correlated on `provider`. The metric was also inconsistent with itself: the path where a provider fails to resolve labelled by instance name, and the path where a model has no price labelled by type. The type is still worth exposing, since prices are keyed on `(provider_type, model)` and that is what an operator needs to add a price. ## Changes - Label the metric with `provider` (the instance name, consistent with the other gateway metrics) and add `provider_type` (the configured type the price is keyed on). - Use `unknown` for `provider_type` when the provider does not resolve to a configured type. - Log the unresolved-provider case at `warn` instead of `info`. A missing price is an expected steady state, but a provider that cannot be resolved is not. - Update the metrics docs and the `metricsdocgen` fixture. Closes [AIGOV-574](https://linear.app/codercom/issue/AIGOV-574) > [!NOTE] > Initially generated by Claude Opus 5, modified and reviewed by @ssncferreira |
||
|
|
58de9ab8f8 |
docs: correct broken CLI commands and flags from drift sweep (#28098)
## Summary Corrects broken CLI commands and flags surfaced by the DOCS-637 full-corpus runtime drift sweep. Each fix was verified against the generated CLI reference (`docs/reference/cli/*`) and, where relevant, `codersdk` source. ## Changes | Page | Fix | |------|-----| | `docs/user-guides/workspace-access/index.md` | `coder port forward` → `coder port-forward` (the space form is unrecognized; the command is hyphenated). | | `docs/ai-coder/github-to-tasks.md` | Remove `coder templates list --org your-org-name` in two spots — `templates list` has no `--org` flag (`unknown flag: --org`). | | `docs/admin/infrastructure/scale-utility.md` | `--cleanup-timeout 15min` → `15m` — Go durations reject the `min` unit (`invalid duration: unknown unit "min"`). | | `docs/admin/integrations/dx-data-cloud.md` | `coder users list > users.csv` emitted a whitespace table, not CSV. Emit JSON and convert to real CSV with `jq`, mirroring the API tab on the same page and using the same columns as the default table view (`username,email,created_at,status`). | ## Notes / judgment calls - **dx-data-cloud (CSV):** the page genuinely needs CSV (the DX CSM imports a CSV, and the API tab already produces one via `jq ... @csv`). `coder users list` only supports `--output table|json`, so the CLI tab now produces real CSV via `jq` rather than switching the page to JSON. - **scale-utility `:109` left as-is:** `--target-users 0:100` is prefixed with "For dashboard traffic:", which correctly scopes it to the `scaletest dashboard` subcommand, so it is not drift. - **Excluded — sessions-tokens `--lifetime=720h`:** the sweep flagged this because the throwaway SUT capped token lifetime at 168h, but `--max-token-lifetime` defaults to `876600h` (~100 years), so the example is valid on a default deployment. The `CODER_MAX_TOKEN_LIFETIME` dependency is also already documented in the page's "Set max token length" section. No change needed. Linear: https://linear.app/codercom/issue/DOCS-641 > This PR was created with AI assistance (Coder Agents). |
||
|
|
1d189cc204 |
docs: fix P2/P3 typos and syntax errors from drift sweep (#28101)
## Summary High-confidence textual subset of the DOCS-637 **P2/P3** drift batch (31 findings total). These 8 fixes are pure typo / grammar / syntax corrections verified directly against the doc source, so they carry no risk of misreconstructed command output. ## Changes (6 files) | Page | Fix | |------|-----| | `docs/admin/templates/extending-templates/variables.md` | Remove doubled word: "file in in the template directory" → "file in the template directory". | | `docs/admin/networking/port-forwarding.md` | Grammar: heading "From an coder_app resource" → "From a coder_app resource". | | `docs/user-guides/workspace-access/index.md` | Malformed heading "Through with the CLI" → "Through the CLI". | | `docs/about/contributing/modules.md` | Conventional-commit example missing the required space: `feat(git-clone):add` → `feat(git-clone): add`. | | `docs/ai-coder/tasks-migration.md` | Add missing closing double-quotes on Terraform `source`/`version` in two snippets that would fail `terraform` parsing. | | `docs/admin/users/idp-sync.md` | Role Sync section said "group sync settings" (copy-paste from the Group Sync section); remove an invalid trailing comma from a JSON output example. | ## Deferred (remaining ~23 P2/P3 items, not in this PR) The rest of the batch is stale **command-output** samples (column/schema changes, sample values) and items that need a content decision (e.g. `--psk` now deprecated in favor of `--key`; `--address` deprecated; an undocumented retention flag). Those need live-output reconstruction or a call on direction, so they're left for follow-up work, consistent with the issue's "handle after the P0/P1 fixes land" guidance. One catalog row (`reverse-proxy-nginx.md:57`, certbot `ws=apache`) is already handled by #28086 and is excluded here. Linear: https://linear.app/codercom/issue/DOCS-646 > This PR was created with AI assistance (Coder Agents). |
||
|
|
8d4d0b35dd |
feat: add Coder Agents chat tools to the MCP toolsdk (#28025)
Exposes the experimental Coder Agents chats API through the MCP tool registry, so MCP clients (the hosted `/api/experimental/mcp/http` server and `coder exp mcp server`) can start and drive server-side coding agents. New tools in `codersdk/toolsdk`, all thin wrappers over existing `codersdk.ExperimentalClient` methods: | Tool | Wraps | |---|---| | `coder_create_chat` | `CreateChat` (prompt, optional org, model config, labels) | | `coder_get_chat` | `GetChat` (status, last error, last turn summary, workspace, files) | | `coder_get_chat_messages` | `GetChatMessages` (user-facing parts, chronological, cursor pagination, queued prompts) | | `coder_send_chat_message` | `CreateChatMessage` (queue or interrupt busy behavior) | | `coder_interrupt_chat` | `InterruptChat` | | `coder_archive_chat` | `UpdateChat` with `archived: true` | | `coder_list_chat_model_configs` | `ListChatModelConfigs` (enabled configs with default flag) | Both MCP servers register tools from `toolsdk.All`, so no additional wiring is needed. Responses are trimmed to what an MCP caller needs (IDs as strings, user-facing transcripts) rather than full SDK payloads. No new endpoints and no database changes. Also adds MCP [prompts](https://modelcontextprotocol.io/specification/2026-07-28/server/prompts) for the chat workflows, defined once in `codersdk/toolsdk` and registered by both servers: | Prompt | Purpose | |---|---| | `coder_agents_delegate` | delegate a task to a Coder Agents chat and monitor it to completion | | `coder_agents_check` | check the status and recent activity of an existing chat | Each prompt declares the tools its workflow needs; the stdio server skips prompts whose tools are excluded by `--allowed-tools`. Tests run the tools against a chat-enabled coderdtest instance (fake OpenAI-compatible provider plus in-process AI bridge), covering the full lifecycle, an interrupt against a blocked turn, pagination cursors, permission-dependent model config filtering, and argument validation. Prompt coverage spans SDK rendering, the hosted `prompts/list`/`prompts/get` round trip, and the stdio server including allowlist gating. > Mux created this PR on Mike's behalf. |
||
|
|
3426f83a27 |
docs: use approximate spend and add Everyone group tip for AI Gateway cost controls (#28012)
## Summary Updates the AI Governance Cost Control docs in two ways: - **Terminology:** aligns the docs with the UI, which now labels spend as **approximate** rather than **estimated**. Renames the `Estimated spend` term, the "How spend is calculated" section (and its anchor and references), and updates the surrounding prose. - **Everyone group tip:** adds a note that, because the organization's `Everyone` group includes every member, its **Members** tab is a quick way for an admin to look up any user's effective group. This complements the existing Get user AI spend API endpoint, since there is no dedicated cost control page today. Related: https://github.com/coder/coder/pull/27977 --- _This PR was created by Coder Agents on behalf of @ssncferreira._ --------- Co-authored-by: Nick Vigilante <nickvigilante@users.noreply.github.com> |
||
|
|
2d9b6eda8f |
feat: add experimental CLI to price unpriced AI models (#27926)
## Description AI Gateway computes the cost of an interception from `ai_model_prices`, which is seeded on every server start from a price book embedded in the binary. A model the price book does not cover records a NULL cost, so its spend is invisible to cost reporting and is not enforced against budgets. The only fix was to wait for a Coder release that added the model. This adds an experimental CLI, backed by an experimental HTTP endpoint, for pricing those models. Models the price book already covers are rejected, because the seeder re-applies the book on every start and would overwrite an operator price. Support for custom pricing will be handled in https://linear.app/codercom/issue/AIGOV-589/extend-experimental-cli-command-to-set-custom-ai-model-prices. ## Commands ``` coder exp ai-model-prices list [--provider] [--model] coder exp ai-model-prices update [file|-] [--provider] [--model] [--input-price] [--output-price] [--cache-read-price] [--cache-write-price] [--yes] ``` ## Changes - Add `GET` and `POST /api/experimental/ai/model-prices`, gated behind the AI Bridge entitlement and the existing `ai_model_price` RBAC resource. - Add a `GetAIModelPrices` query with optional `provider` and `model` filters applied in SQL. - Validate the whole request before writing anything, so one bad entry cannot leave the table half updated, and report every problem at once. - Reject prices for models the embedded price book already covers, through a new `prices.IsDefaultPriced`. - Add the `coder exp ai-model-prices` command with `list` and `update`. `update` accepts a JSON document or the single-model flags and prints a plan, asking to confirm unless the document is piped in or `--yes` is passed. - Consolidate the supported provider list into `coderd/aibridge/prices/providers` so the price generator and the server share one definition. - Add `codersdk` types and client methods for both endpoints, and bound the request body at 1 MiB. - Document the command in the AI Gateway cost controls page. Closes https://linear.app/codercom/issue/AIGOV-567/experimental-cli-command-to-set-prices-for-unpriced-ai-models > [!NOTE] > Initially generated by Claude Opus 5, modified and reviewed by @ssncferreira |
||
|
|
e92fd8e96f |
chore: retire mark3labs/mcp-go dependency (#28061)
## Stack Context PR 6 of 6 in a stack that migrates every Coder MCP surface from the archived `github.com/mark3labs/mcp-go` library to the official `github.com/modelcontextprotocol/go-sdk` v1.7.0. Stack: #28056 -> #28057 -> #28058 -> #28059 -> #28060 -> #28061 ## Why With every production surface migrated, this PR removes the mark3labs dependency entirely and converts the remaining test fixtures. - Migrates the remaining mark3labs test fixtures (coderd MCP e2e tests, chatd fixtures, mcpclient fixtures, and the Force On MCP policy tests) to official stateless SDK servers. - Removes `github.com/mark3labs/mcp-go` from `go.mod` and drops the corresponding dependabot ignore entry. Zero references remain repo-wide. - Updates the MCP docs for the 2026-07-28 protocol: stateless Streamable HTTP behavior, the supported 2024-11-05 through 2026-07-28 protocol range, and explicit non-features (resources, prompts, structured output, elicitation, MCP Tasks). - The e2e ping assertion is removed because MCP 2026-07-28 removed the ping method. > Mux created 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 -->
|
||
|
|
52bd05adb4 |
docs: remove AI Governance Add-On references (#28073)
## Summary Replaces all remaining "AI Governance Add-On" references with language consistent with AI Governance being included with a Premium license. **`docs/ai-coder/ai-gateway/standalone.md`** - Admonition: "AI Gateway requires the AI Governance Add-On... deployments without the add-on will not be able to access" → "AI Gateway requires a Premium license. Community deployments cannot access AI Gateway." - Requirements list: "A Coder license with the AI Governance Add-On" → "A Premium license with AI Governance" **`docs/install/airgap.md`** - Table row: "deployments with the AI Governance Add On" → "deployments with AI Governance" **`docs/reference/glossary.md`** - Agent Firewall, AI Gateway, AI Gateway Proxy entries: "This feature requires the AI Governance Add-On" → "This feature requires a Premium license" - Agent Workspace Build entry: "the AI Governance Add-On expands the allowance" → "a Premium license expands the allowance" - Heading: "### AI Governance Add-On" → "### AI Governance" - Definition: "A separate per-user license for Premium customers, purchased on top of a Premium subscription..." → "Included with a Premium license, AI Governance unlocks..." **`docs/ai-coder/ai-governance.md`** - Removed the "Identifying AI seat consumers" section (heading through end of file), which described an "AI add-on column" in the UI ## Note References to Agent Workspace Builds will be eliminated in a separate PR that removes Coder Tasks from the docs. --- PR generated with Coder Agents. |