fix: enable Copilot HTTP transport fallback (#28494) by ssncferreira · Pull Request #28721 · coder/coder · GitHub
Skip to content

fix: enable Copilot HTTP transport fallback (#28494) - #28721

Merged
mtojek merged 1 commit into
release/2.34from
backport/28494-to-2.34
Aug 27, 2026
Merged

fix: enable Copilot HTTP transport fallback (#28494)#28721
mtojek merged 1 commit into
release/2.34from
backport/28494-to-2.34

Conversation

@ssncferreira

Copy link
Copy Markdown
Contributor

Backport of #28494

Original PR: #28494 — fix: enable Copilot HTTP transport fallback
Merge commit: 849543d
Requested by: @ssncferreira

Note

This pull request was generated by Coder Agents on behalf of @ssncferreira.

## Description

Copilot provider model metadata returned by `/models` can advertise
WebSocket support (for example, `ws:/responses`), so clients attempt
WebSocket inference even though AI Gateway supports HTTP transport only.
The Copilot CLI and Copilot in VS Code use different retry mechanisms,
and only the CLI fallback worked previously. See the investigation
details below for more information.

Authenticate every configured Copilot provider request with the Coder
token validated during CONNECT while preserving Copilot provider
credentials and preventing Coder credentials from being forwarded
upstream. Reject unsupported WebSocket upgrades on bridged inference
routes with `501 Not Implemented` so clients can fall back to HTTP.

## Changes

- Add the CONNECT-authenticated Coder token to every configured Copilot
provider request.
- Preserve Copilot provider credentials and strip Coder credentials from
provider credential headers.
- Pass through Copilot `/_ping` connectivity checks and `/auto`
model-selection requests.
- Return `501 Not Implemented` for WebSocket upgrades on bridged
inference routes.

<details>
<summary>Investigation details</summary>

These logs show the behavior before this change using `GPT-5.3-Codex`,
whose model metadata advertises `ws:/responses`.

**Copilot CLI**

1. The CLI attempts a WebSocket upgrade. AI Gateway treats the empty
`GET /responses` body as an inference request and returns 500.
```
2026-08-26 11:08:28.883 [info]  api: 2026-08-26 11:08:28.883 [warn]  coderd.ai-gateway.pool: failed to create interceptor  request_id=dcfc945c-fc10-4b8f-abc8-ae31aa21ad44  aibridgeproxy_id=6f651c82-68b2-45ee-b5e6-dc75445e2ef6  path=/copilot/responses ...
2026-08-26 11:08:28.883 [info]  api: error= unmarshal request body:
2026-08-26 11:08:28.883 [info]  api: github.com/coder/coder/v2/aibridge/provider.(*Copilot).CreateInterceptor
2026-08-26 11:08:28.883 [info]  api: /home/coder/coder/aibridge/provider/copilot.go:179
2026-08-26 11:08:28.883 [info]  api: - empty request body:
2026-08-26 11:08:28.883 [info]  api: github.com/coder/coder/v2/aibridge/intercept/responses.NewRequestPayload
2026-08-26 11:08:28.884 [info]  api: /home/coder/coder/aibridge/intercept/responses/reqpayload.go:48
2026-08-26 11:08:28.884 [info]  api: 2026-08-26 11:08:28.883 [warn]  coderd: GET  user_agent="copilot/1.0.80 (client/github/cli linux v24.18.1) term/unknown"  host=127.0.0.1:3000  received_host=127.0.0.1:3000  path=/api/v2/ai-gateway/copilot/responses  proto=HTTP/1.1  remote_addr=127.0.0.1  start="2026-08-26 11:08:28.880115732 +0000 UTC m=+402.868920240"  response_body="failed to create \"/copilot/responses\" interceptor\n"  took=3.644201ms  status_code=500  latency_ms=3  params_*=copilot/responses  request_id=dcfc945c-fc10-4b8f-abc8-ae31aa21ad44
2026-08-26 11:08:28.884 [info]  api: 2026-08-26 11:08:28.884 [erro]  coderd.aibridgeproxyd: received error response from aibridged  connect_id=17dda9cb-ae6a-416b-a812-b3b831755a2b  request_id=6f651c82-68b2-45ee-b5e6-dc75445e2ef6  provider=copilot  status=500  response_body="failed to create \"/copilot/responses\" interceptor\n"
```

2. The CLI immediately retries inference with `POST /responses`, which
succeeds.
```
2026-08-26 11:08:28.886 [info]  api: 2026-08-26 11:08:28.886 [debu]  coderd.aibridgeproxyd: request CONNECT authenticated  connect_id=7809a618-2c24-4f5f-a2f2-97af934b8c3e  host=api.business.githubcopilot.com:443  provider=copilot
2026-08-26 11:08:28.890 [info]  api: 2026-08-26 11:08:28.890 [info]  coderd.aibridgeproxyd: routing MITM request to AI Gateway  connect_id=7809a618-2c24-4f5f-a2f2-97af934b8c3e  request_id=eee98705-ffc2-4a00-8201-e316f997e19d  host=api.business.githubcopilot.com  method=POST  path=/responses  provider=copilot  gateway_target_url=http://127.0.0.1:3000/api/v2/ai-gateway/copilot/responses
2026-08-26 11:08:31.429 [info]  api: 2026-08-26 11:08:31.428 [debu]  coderd.aibridgeproxyd: received response from aibridged  connect_id=7809a618-2c24-4f5f-a2f2-97af934b8c3e  request_id=eee98705-ffc2-4a00-8201-e316f997e19d  provider=copilot  status=200
```

**Copilot in VS Code**
1. VS Code attempts a WebSocket upgrade. AI Gateway treats the empty
`GET /responses` body as an inference request and returns 500.
```
2026-08-26 11:09:20.736 [info]  api: 2026-08-26 11:09:20.736 [warn]  coderd.ai-gateway.pool: failed to create interceptor  request_id=4aab1c00-fb45-4533-b8c4-bcb150fd12f3  aibridgeproxy_id=d6867370-cefa-49bb-85ca-98dd4258e74c  path=/copilot/responses ...
2026-08-26 11:09:20.736 [info]  api: error= unmarshal request body:
2026-08-26 11:09:20.736 [info]  api: github.com/coder/coder/v2/aibridge/provider.(*Copilot).CreateInterceptor
2026-08-26 11:09:20.736 [info]  api: /home/coder/coder/aibridge/provider/copilot.go:179
2026-08-26 11:09:20.736 [info]  api: - empty request body:
2026-08-26 11:09:20.736 [info]  api: github.com/coder/coder/v2/aibridge/intercept/responses.NewRequestPayload
2026-08-26 11:09:20.736 [info]  api: /home/coder/coder/aibridge/intercept/responses/reqpayload.go:48
2026-08-26 11:09:20.736 [info]  api: 2026-08-26 11:09:20.736 [warn]  coderd: GET  user_agent=node  host=127.0.0.1:3000  received_host=127.0.0.1:3000  path=/api/v2/ai-gateway/copilot/responses  proto=HTTP/1.1  remote_addr=127.0.0.1  start="2026-08-26 11:09:20.732174884 +0000 UTC m=+454.720979381"  response_body="failed to create \"/copilot/responses\" interceptor\n"  took=4.225651ms  status_code=500  latency_ms=4  params_*=copilot/responses  request_id=4aab1c00-fb45-4533-b8c4-bcb150fd12f3
2026-08-26 11:09:20.737 [info]  api: 2026-08-26 11:09:20.736 [erro]  coderd.aibridgeproxyd: received error response from aibridged  connect_id=072a6497-7072-42d8-b52d-a3afe17d5a75  request_id=d6867370-cefa-49bb-85ca-98dd4258e74c  provider=copilot  status=500  response_body="failed to create \"/copilot/responses\" interceptor\n"
```

2. VS Code checks connectivity with `GET /_ping` before retrying
inference over HTTP. AI Gateway rejects the check because the proxy did
not forward the Coder token from the authenticated CONNECT session.
```
2026-08-26 11:09:21.813 [info]  api: 2026-08-26 11:09:21.812 [info]  coderd.aibridgeproxyd: routing MITM request to AI Gateway  connect_id=2dd5a340-7ad9-43a6-b99d-fd34b838e6a2  request_id=8fda1e3e-4ca8-4908-a2ef-23859743dc38  host=api.business.githubcopilot.com  method=GET  path=/_ping  provider=copilot  gateway_target_url=http://127.0.0.1:3000/api/v2/ai-gateway/copilot/_ping
2026-08-26 11:09:21.813 [info]  api: 2026-08-26 11:09:21.813 [warn]  coderd.ai-gateway: no auth key provided  method=GET  path=/copilot/_ping  aibridgeproxy_id=8fda1e3e-4ca8-4908-a2ef-23859743dc38  request_id=057e3288-afa9-4f8d-9698-e4a3b206b199  aibridgeproxy_id=8fda1e3e-4ca8-4908-a2ef-23859743dc38
2026-08-26 11:09:21.814 [info]  api: 2026-08-26 11:09:21.814 [warn]  coderd.aibridgeproxyd: received error response from aibridged  connect_id=2dd5a340-7ad9-43a6-b99d-fd34b838e6a2  request_id=8fda1e3e-4ca8-4908-a2ef-23859743dc38  provider=copilot  status=400  response_body="no authentication key provided\n"
```
</details>

Closes
https://linear.app/codercom/issue/AIGOV-629/ai-gateway-lacks-support-for-new-copilot-endpoints-behind-mitm

> [!NOTE]
> Generated by Coder Agents on behalf of @ssncferreira.

(cherry picked from commit 849543d)
@ssncferreira ssncferreira added the backport/v2.34 Backport PR targeting release/2.34 label Aug 27, 2026 — with Coder
@ssncferreira ssncferreira self-assigned this Aug 27, 2026
@ssncferreira ssncferreira added the backport/v2.34 Backport PR targeting release/2.34 label Aug 27, 2026
@ssncferreira
ssncferreira marked this pull request as ready for review August 27, 2026 16:15
@ssncferreira
ssncferreira requested a review from mtojek August 27, 2026 16:15
@mtojek
mtojek merged commit ff4ac10 into release/2.34 Aug 27, 2026
85 of 87 checks passed
@mtojek
mtojek deleted the backport/28494-to-2.34 branch August 27, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/v2.34 Backport PR targeting release/2.34

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants