refactor: consolidate chat streaming endpoints under /stream (#23248)

Moves per-chat streaming/watch endpoints under a `/stream` sub-route for
better API consistency:

| Before | After |
|--------|-------|
| `GET /{chat}/stream` | `GET /{chat}/stream/` |
| `GET /{chat}/desktop` | `GET /{chat}/stream/desktop` |
| `GET /{chat}/git/watch` | `GET /{chat}/stream/git` |

### Changes
- **`coderd/coderd.go`** — Route definitions: replaced flat routes with
`r.Route("/stream", ...)` sub-router
- **`site/src/api/api.ts`** — Updated WebSocket URLs for `watchChatGit`
and `watchChatDesktop`
- **`coderd/chats_test.go`** — Updated desktop test URL
- **`coderd/workspaceagents_internal_test.go`** — Updated git watcher
test URLs (route mounts + dial URLs)
- **`site/src/pages/AgentsPage/AgentDetail.stories.tsx`** — Updated
storybook WebSocket mock paths
This commit is contained in:
Kyle Carberry
2026-03-18 14:04:42 -04:00
committed by GitHub
parent 0b13ba978a
commit 90cf4f0a91
5 changed files with 22 additions and 18 deletions
+1 -1
View File
@@ -4538,7 +4538,7 @@ func TestWatchChatDesktop(t *testing.T) {
res, err := client.Request(
ctx,
http.MethodGet,
fmt.Sprintf("/api/experimental/chats/%s/desktop", createdChat.ID),
fmt.Sprintf("/api/experimental/chats/%s/stream/desktop", createdChat.ID),
nil,
)
require.NoError(t, err)
+5 -3
View File
@@ -1209,13 +1209,15 @@ func New(options *Options) *API {
r.Route("/{chat}", func(r chi.Router) {
r.Use(httpmw.ExtractChatParam(options.Database))
r.Get("/", api.getChat)
r.Get("/git/watch", api.watchChatGit)
r.Get("/desktop", api.watchChatDesktop)
r.Patch("/", api.patchChat)
r.Get("/messages", api.getChatMessages)
r.Post("/messages", api.postChatMessages)
r.Patch("/messages/{message}", api.patchChatMessage)
r.Get("/stream", api.streamChat)
r.Route("/stream", func(r chi.Router) {
r.Get("/", api.streamChat)
r.Get("/desktop", api.watchChatDesktop)
r.Get("/git", api.watchChatGit)
})
r.Post("/interrupt", api.interruptChat)
r.Get("/diff", api.getChatDiffContents)
r.Route("/queue/{queuedMessage}", func(r chi.Router) {
+10 -10
View File
@@ -109,7 +109,7 @@ func TestWatchChatGit(t *testing.T) {
// And: We mount the HTTP handler.
r.With(httpmw.ExtractChatParam(mDB)).
Get("/chats/{chat}/git/watch", api.watchChatGit)
Get("/chats/{chat}/stream/git", api.watchChatGit)
// Given: We create the HTTP server.
srv := httptest.NewServer(r)
@@ -117,7 +117,7 @@ func TestWatchChatGit(t *testing.T) {
// When: We make a request.
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
fmt.Sprintf("%s/chats/%s/git/watch", srv.URL, chatID), nil)
fmt.Sprintf("%s/chats/%s/stream/git", srv.URL, chatID), nil)
require.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
@@ -165,7 +165,7 @@ func TestWatchChatGit(t *testing.T) {
// And: We mount the HTTP handler.
r.With(httpmw.ExtractChatParam(mDB)).
Get("/chats/{chat}/git/watch", api.watchChatGit)
Get("/chats/{chat}/stream/git", api.watchChatGit)
// Given: We create the HTTP server.
srv := httptest.NewServer(r)
@@ -173,7 +173,7 @@ func TestWatchChatGit(t *testing.T) {
// When: We make a request.
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
fmt.Sprintf("%s/chats/%s/git/watch", srv.URL, chatID), nil)
fmt.Sprintf("%s/chats/%s/stream/git", srv.URL, chatID), nil)
require.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
@@ -242,7 +242,7 @@ func TestWatchChatGit(t *testing.T) {
// And: We mount the HTTP handler.
r.With(httpmw.ExtractChatParam(mDB)).
Get("/chats/{chat}/git/watch", api.watchChatGit)
Get("/chats/{chat}/stream/git", api.watchChatGit)
// Given: We create the HTTP server.
srv := httptest.NewServer(r)
@@ -250,7 +250,7 @@ func TestWatchChatGit(t *testing.T) {
// When: We make a request.
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
fmt.Sprintf("%s/chats/%s/git/watch", srv.URL, chatID), nil)
fmt.Sprintf("%s/chats/%s/stream/git", srv.URL, chatID), nil)
require.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
@@ -376,7 +376,7 @@ func TestWatchChatGit(t *testing.T) {
})
// And: We mount the HTTP handler.
r.With(httpmw.ExtractChatParam(mDB)).
Get("/chats/{chat}/git/watch", api.watchChatGit)
Get("/chats/{chat}/stream/git", api.watchChatGit)
// Given: We create the HTTP server.
coderdSrv := httptest.NewServer(r)
@@ -384,7 +384,7 @@ func TestWatchChatGit(t *testing.T) {
// And: Dial the WebSocket as a client.
wsURL := strings.Replace(coderdSrv.URL, "http://", "ws://", 1)
clientConn, resp, err := websocket.Dial(ctx, fmt.Sprintf("%s/chats/%s/git/watch", wsURL, chatID), nil)
clientConn, resp, err := websocket.Dial(ctx, fmt.Sprintf("%s/chats/%s/stream/git", wsURL, chatID), nil)
require.NoError(t, err)
if resp.Body != nil {
defer resp.Body.Close()
@@ -538,7 +538,7 @@ func TestWatchChatGit(t *testing.T) {
})
// And: We mount the HTTP handler.
r.With(httpmw.ExtractChatParam(mDB)).
Get("/chats/{chat}/git/watch", api.watchChatGit)
Get("/chats/{chat}/stream/git", api.watchChatGit)
// Given: We create the HTTP server.
coderdSrv := httptest.NewServer(r)
@@ -546,7 +546,7 @@ func TestWatchChatGit(t *testing.T) {
// And: Dial the WebSocket as a client.
wsURL := strings.Replace(coderdSrv.URL, "http://", "ws://", 1)
clientConn, resp, err := websocket.Dial(ctx, fmt.Sprintf("%s/chats/%s/git/watch", wsURL, chatID), nil)
clientConn, resp, err := websocket.Dial(ctx, fmt.Sprintf("%s/chats/%s/stream/git", wsURL, chatID), nil)
require.NoError(t, err)
if resp.Body != nil {
defer resp.Body.Close()
+4 -2
View File
@@ -160,11 +160,13 @@ export const watchChats = (): OneWayWebSocket<TypesGen.ServerSentEvent> => {
};
export const watchChatGit = (chatId: string): WebSocket => {
return createWebSocket(`/api/experimental/chats/${chatId}/git/watch`);
return createWebSocket(`/api/experimental/chats/${chatId}/stream/git`);
};
export const watchChatDesktop = (chatId: string): WebSocket => {
const socket = createWebSocket(`/api/experimental/chats/${chatId}/desktop`);
const socket = createWebSocket(
`/api/experimental/chats/${chatId}/stream/desktop`,
);
// RFB is a binary protocol — noVNC expects arraybuffer, not blob.
socket.binaryType = "arraybuffer";
return socket;
@@ -764,7 +764,7 @@ export const SidebarWithPRAndRepos: Story = {
{ diffUrl: "https://github.com/coder/coder/pull/456" },
),
webSocket: {
"/git/watch": [
"/stream/git": [
{
event: "message",
data: JSON.stringify({
@@ -945,7 +945,7 @@ export const SidebarWithSingleRepo: Story = {
{ diffUrl: undefined },
),
webSocket: {
"/git/watch": [
"/stream/git": [
{
event: "message",
data: JSON.stringify({