feat: mount chat API routes under /api/v2 by ibetitsmike · Pull Request #28496 · coder/coder · GitHub
Skip to content

feat: mount chat API routes under /api/v2 - #28496

Merged
ibetitsmike merged 15 commits into
mainfrom
mike/chat-api-v2-server
Aug 26, 2026
Merged

feat: mount chat API routes under /api/v2#28496
ibetitsmike merged 15 commits into
mainfrom
mike/chat-api-v2-server

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

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.

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

@ibetitsmike ibetitsmike changed the title mike/chat api v2 server feat: mount chat API routes under /api/v2 Aug 24, 2026
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 69dd96a36e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/coderdtest/swaggerparser.go Outdated
Comment thread coderd/coderd.go
Comment thread coderd/coderd.go Outdated
Comment thread coderd/exp_chats.go
Comment thread coderd/exp_chats.go
Comment thread coderd/exp_chats.go
Comment thread coderd/mcp.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-api-v2-server branch from 69dd96a to 9b7aa41 Compare August 24, 2026 18:19
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b7aa41e86

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/exp_chats.go
Comment thread coderd/exp_chats.go
Comment thread coderd/coderd.go Outdated
Comment thread coderd/exp_chats.go Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 80d2708c38

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/exp_chats.go
Comment thread coderd/mcp.go
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 13de197c79

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 816d7eddad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/exp_chats.go Outdated
Comment thread coderd/exp_chats.go
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review current head d28c59cafa603adb761e0bf4ad16c2cb6b771374.

Xum acted on Mike's behalf.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d28c59cafa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/mcp.go Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

Xum acted on Mike's behalf in requesting a fresh Codex review for head 832bf3aed4f2.

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 832bf3aed4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/exp_chats.go Outdated
Comment thread coderd/httpmw/ratelimit.go Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review current head 860c858b82a0a41292aa3aaa9af4ef750379da78.

Xum acted on Mike's behalf.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 860c858b82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/exp_chats.go
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review current head bb0f66499598e7271ce21d90eb3b3db875df820c.

Xum acted on Mike's behalf.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb0f664995

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/chat_routes_test.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-api-v2-server branch from bb0f664 to 12c3c47 Compare August 25, 2026 05:03
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review current head 12c3c470ead1190d36670b1cb0c25dc22d6386fc.

Xum acted on Mike's behalf.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 12c3c470ea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike force-pushed the mike/chat-api-v2-server branch 2 times, most recently from 49ed887 to 054d748 Compare August 25, 2026 16:26
Publish pagination params on GET /chats, describe the stream frame as
an event array, document the raw upload body via form data instead of
a parser exemption, restore the media-type contracts on the file
download routes and the OAuth callback, extend permissive MCP CORS to
/api/v2/mcp/, and share one FilesRateLimit limiter across both prefix
mounts with prefix-stripped endpoint keys.
Publish the stream parts frame as an event array and the stream
after_id resume cursor, type the queued-message path IDs as integers,
and move the chatd architecture TODO markers into this PR where the
dual mounts land.
@ibetitsmike
ibetitsmike force-pushed the mike/chat-api-v2-server branch from 054d748 to f06af18 Compare August 25, 2026 22:10
Comment thread coderd/chat_routes.go Outdated
return api.chatFilesRateLimit
}

func (api *API) registerChatFileDownloadRoute(r chi.Router) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have fewer of these methods and consolidate them, the endpoints are so spread out it's hard to follow. Although that may cause a need to invert where the exceptions are defined (i.e. moving them here vs keep in coderd).

@ibetitsmike ibetitsmike Aug 26, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidated in 968b807. The per-group helpers are collapsed into a single registerChatAPIRoutes(r, apiKeyMiddleware, prefix) mounted once per API prefix, with the exceptions inverted into chat_routes.go: the unpromoted experimental routes and the /api/v2 404-reservations now sit behind a chatAPIPrefix selector instead of being spread through coderd.go. The MCP OAuth2 pair merged into one registerMCPServerOAuth2Routes(r, prefix) and the org-scoped MCP server config routes folded into registerOrganizationChatRoutes. coderd.go is down to one call per prefix plus the org/member mounts that hang off existing route trees.

🤖 Posted by Xum on Mike's behalf.

Comment thread coderd/chat_routes.go Outdated
}

func (api *API) registerExperimentalMCPServerOAuth2Routes(r chi.Router) {
// TODO(CODAGT-922): migrate provider redirect URIs before promoting this callback.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC provider redirect URI cannot be changed for existing sessions, so refresh flows would break and require re-authing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - reworded the comment in 968b807: providers pin the redirect URI when a session is established, so it cannot change for existing sessions without breaking token refresh and forcing re-auth. The callback stays experimental-only, and CODAGT-922 now tracks promotion as needing a re-auth story rather than a redirect URI migration.\n\n> 🤖 Posted by Xum on Mike'''s behalf.

Comment thread coderd/coderdtest/swaggerparser.go Outdated
var allowedProduceTypes = []string{"json", "text/event-stream", "text/html", "text/plain"}

func assertProduce(t *testing.T, comment SwaggerComment) {
if comment.method == "get" && (comment.router == "/api/v2/chats/files/{file}" ||

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do these need to be separate from the rest below?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No good reason - they fit the existing exception list (GET with @produce but no response model), so 968b807 folds them into it and drops the early return.\n\n> 🤖 Posted by Xum on Mike'''s behalf.

Comment thread coderd/chat_routes.go Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we adding this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#28632 will fully rip out the default organization model routes anyway

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped in 968b807: GET /chats/models stays experimental-only since the org-scoped collection supersedes it and #28632 removes it. The doc-only wrapper handler is deleted and /api/v2/chats/models now 404s via the segment reservation (covered in TestChatRoutesCompatibility).\n\n> 🤖 Posted by Xum on Mike'''s behalf.

Address review feedback on the /api/v2 chat promotion:

- Collapse the per-group chat register helpers into a single
  registerChatAPIRoutes mounted once per API prefix, inverting the
  unpromoted experimental routes and the /api/v2 404 reservations into
  chat_routes.go behind a chatAPIPrefix selector. Merge the MCP OAuth2
  helper pair and fold the organization MCP server config routes into
  registerOrganizationChatRoutes.
- Keep GET /chats/models experimental-only instead of promoting it: the
  organization-scoped models collection supersedes it and #28632
  removes it. /api/v2/chats/models now 404s via a segment reservation.
- Reword the MCP OAuth2 callback TODO: providers pin the redirect URI
  for existing sessions, so promotion needs a re-auth story rather than
  a redirect URI migration.
- Fold the chat file @produce exceptions into the swagger parser's
  existing no-response-model exception list.
@ibetitsmike
ibetitsmike merged commit 351bb14 into main Aug 26, 2026
35 checks passed
@ibetitsmike
ibetitsmike deleted the mike/chat-api-v2-server branch August 26, 2026 14:17
ibetitsmike added a commit that referenced this pull request Aug 26, 2026
## Stack context

This is the second PR in the 3-PR chat API promotion stack: server
compatibility mounts (#28496), codersdk promotion (this PR), and
frontend path updates (#28498).

## Summary

Move the promoted chat and MCP SDK methods from `ExperimentalClient` to
`Client` and update them to use `/api/v2`. Methods for routes that
remain experimental stay on `ExperimentalClient`.

Update in-repository callers and generated types. The multi-replica chat
stream relay dials `/api/v2` directly: mixed-version replica sets are
not a supported upgrade path, so no experimental-path fallback is kept
(per review). Remote dogfood UAT passed for the composed stack.

> [!NOTE]
> Xum acted on Mike's behalf in this pull request.
<!-- xum-attribution: model=claude-fable-5 thinking=high -->
ibetitsmike added a commit that referenced this pull request Aug 26, 2026
## Stack context

This is the final PR in the 3-PR chat API promotion stack: server
compatibility mounts (#28496), codersdk promotion (#28497), and frontend
path updates (this PR).

## Summary

Switch promoted frontend chat and MCP REST and WebSocket calls to
`/api/v2`. Debug runs, virtual desktop streaming, advisor, and
computer-use provider routes remain on `/api/experimental` because those
surfaces were not promoted.

Update the matching tests, stories, helpers, and end-to-end route
expectations. Remote dogfood UAT passed with chat traffic verified on
the v2 routes.

> [!NOTE]
> Xum acted on Mike's behalf in this pull request.
<!-- xum-attribution: model=claude-fable-5 thinking=high -->
mtojek added a commit that referenced this pull request Aug 27, 2026
Batch backport of ibetitsmike's PRs that merged into `main` after the
`release/2.37` branch was cut (merge-base `c275327fb72`, 2026-08-24).

## Included (9 cherry-picks, in order)

| PR | Title |
|----|-------|
| #28470 | fix(coderd/x): surface Gemini malformed-function-call stream
deaths as retryable errors |
| #28471 | fix: apply MCP server selection when editing a chat message |
| #28460 | refactor: consolidate viewport hooks and remove
defineProperty matchMedia stub |
| #28476 | feat(coderd/x/chatd/chattool): improve find_tools relevance
and model guidance |
| #28400 | fix(coderd/x/chatd/mcpclient): enforce MCP connect budget and
unblock session cleanup |
| #28589 | fix(coderd/x/chatd): truncate overlong generated chat titles
instead of rejecting them |
| #28496 | feat: mount chat API routes under /api/v2 |
| #28497 | feat: promote codersdk chat API methods to Client |
| #28498 | feat(site): use /api/v2 chat API paths |

All picks applied cleanly with `git cherry-pick -x` onto `release/2.37`.

## Excluded and follow-up backports

The remaining post-cut PRs are cherry-picked onto this PR as a GitHub
stack (#28692) that merges bottom-up, so the dependency order is
enforced by the PR bases:

| Stack order | Original PR | Backport PR | Notes |
|-------------|-------------|-------------|-------|
| 1 | #28462 (repair failing Storybook stories) | #28687 | One fixture
adaptation: 2.37's `OrganizationModelsContextValue` has no
`organizations` field |
| 2 | #28186 (enable Coder Agents for organization members) | #28688 |
One story-assertion conflict resolved to the picked regex; ships no
migration by design |
| 3 | #28593 (allow sharing MCP servers with users and groups) | #28686
| Clean pick on top of #28688, plus the 1-line test fix #28657 (expect
v2 MCP ACL path) |
| 4 | #28659 (point MCP server ACL msw handlers at v2 paths) | #28689 |
Clean pick on top of #28686 |

Intentionally skipped: #28587 (restore agents-access cleanup migration).
Release branches cannot take a migration unless its sequence number
matches main with no gap.

## Validation

- `go build ./...` and test-binary compilation for `./coderd/...
./codersdk/... ./enterprise/... ./site` pass
- `pnpm check` and `pnpm lint:types` pass
- Targeted Vitest on all touched test files: unit 281/281 pass;
Storybook 180/181 pass. The single failure (`AgentChatPage.stories.tsx`
> Queued For Capacity After Polling) reproduces identically on the
untouched `release/2.37` baseline, so it is pre-existing and unrelated.

> Xum acted on Mike's behalf.
<!-- xum-attribution: model=claude-fable-5 thinking=high -->
ethanndickson added a commit that referenced this pull request Aug 27, 2026
> [!IMPORTANT]
> Most of the added lines in this PR are generated API reference content
for publishing the organization-scoped `GET` and `POST
/api/v2/organizations/{organization}/chats/models` replacements. There
is no matching generated-doc deletion because the three removed
default-organization endpoints are experimental and are not present in
the generated public API reference on the current base. The removed
paths remain only as explicit 404 reservations, with no
default-organization shim or functional handler.

## Summary

Remove the unused default-organization chat model collection routes:

```text
GET  /api/experimental/chats/models
GET  /api/experimental/chats/model-configs
POST /api/experimental/chats/model-configs
```

Use the organization-scoped collection instead:

```text
GET  /api/v2/organizations/{organization}/chats/models
POST /api/v2/organizations/{organization}/chats/models
```

## Context

The intention of PR #28440 was to consolidate model availability into
the organization-scoped models collection for CODAGT-898 and remove the
superseded collection routes. That PR removed
`/organizations/{organization}/chats/models/available`, but it missed
these older default-organization routes and explicitly retained one of
them. This PR completes the intended #28440 cutover. The repository has
no SDK, CLI, or frontend consumer for the removed routes.

This change also prevents PR #28496 from promoting the missed
default-organization `/chats/models` route into the stable `/api/v2`
API.

This change is separate from the one-release `/api/experimental`
compatibility window in CODAGT-921. That window preserves experimental
versions of the intended stable API. It does not require compatibility
routes for unused deployment-scoped endpoints.

Refs CODAGT-898.

## Breaking change

Clients that call the removed routes must use the organization-scoped
model collection and provide an organization.

## Changelog

Remove unused default-organization Coder Agents model API routes. API
clients must use the organization-scoped chat models collection.

> [!NOTE]
> Coder Agents generated this pull request on Ethan Dickson's behalf.
ethanndickson added a commit that referenced this pull request Aug 27, 2026
> [!IMPORTANT]
> Most of the added lines in this PR are generated API reference content
for publishing the organization-scoped `GET` and `POST
/api/v2/organizations/{organization}/chats/models` replacements. There
is no matching generated-doc deletion because the three removed
default-organization endpoints are experimental and are not present in
the generated public API reference on the current base. The removed
paths remain only as explicit 404 reservations, with no
default-organization shim or functional handler.

## Summary

Remove the unused default-organization chat model collection routes:

```text
GET  /api/experimental/chats/models
GET  /api/experimental/chats/model-configs
POST /api/experimental/chats/model-configs
```

Use the organization-scoped collection instead:

```text
GET  /api/v2/organizations/{organization}/chats/models
POST /api/v2/organizations/{organization}/chats/models
```

## Context

The intention of PR #28440 was to consolidate model availability into
the organization-scoped models collection for CODAGT-898 and remove the
superseded collection routes. That PR removed
`/organizations/{organization}/chats/models/available`, but it missed
these older default-organization routes and explicitly retained one of
them. This PR completes the intended #28440 cutover. The repository has
no SDK, CLI, or frontend consumer for the removed routes.

This change also prevents PR #28496 from promoting the missed
default-organization `/chats/models` route into the stable `/api/v2`
API.

This change is separate from the one-release `/api/experimental`
compatibility window in CODAGT-921. That window preserves experimental
versions of the intended stable API. It does not require compatibility
routes for unused deployment-scoped endpoints.

Refs CODAGT-898.

## Breaking change

Clients that call the removed routes must use the organization-scoped
model collection and provide an organization.

## Changelog

Remove unused default-organization Coder Agents model API routes. API
clients must use the organization-scoped chat models collection.

> [!NOTE]
> Coder Agents generated this pull request on Ethan Dickson's behalf.

(cherry picked from commit 0f5c7b3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants