Skip to content

Pass the proxy and certificate variables to the Copilot CLI the Planner runs - #785

Merged
lavaman131 merged 1 commit into
mainfrom
fix-759-copilot-cli-proxy
Nov 5, 2026
Merged

lavaman131 merged 1 commit into
mainfrom
fix-759-copilot-cli-proxy

Conversation

@lavaman131

Copy link
Copy Markdown
Collaborator

Summary

The Planner's Copilot CLI now receives the server's proxy and certificate variables, so a server behind an HTTP or HTTPS proxy can run Planner turns under HARNESS=copilot-sdk.

Cause

defaultConnect created the client with env: { COPILOT_PLUGIN_DIR_ONLY: "true" }. The SDK uses that env as the CLI process's whole environment, so HTTPS_PROXY, HTTP_PROXY and NO_PROXY never reached the CLI. The server's own requests used the proxy; the CLI went direct and session.create failed on api.github.com/copilot_internal/user. No other code creates a CopilotClient with an env.

Change

  • apps/server/src/harness/copilot-sdk/adapter.ts: the CLI environment is built from a fixed list: HTTPS_PROXY, HTTP_PROXY, NO_PROXY (and lowercase forms), NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, SSL_CERT_DIR (each present in the bundled CLI's option table). Undefined variables are not added; set values, including an empty string, pass verbatim. COPILOT_PLUGIN_DIR_ONLY stays "true"; tokens, other variables and COPILOT_ENABLE_BUILTIN_GITHUB_MCP are still not passed. defaultConnect is exported for the test.
  • apps/server/src/harness/copilot-sdk/cli-environment.test.ts: spawns a stand-in CLI through COPILOT_CLI_PATH and reads the environment the SDK gives it (present when set, absent when unset, no GITHUB_TOKEN or other secret), plus a local-proxy test where the stand-in's HTTPS request produces CONNECT api.github.com:443 at a 127.0.0.1 proxy.

Docs

docs/self-hosting.md and docs/hosted-agent.md list the variables the CLI receives under HARNESS=copilot-sdk and say nothing else is passed.

Verification

  • red before fix: with the source change reverted (only defaultConnect exported), 3 of the 4 new tests failed and the secrets-absent test passed; with the fix all 4 pass
  • bun test apps/server/src/harness: 384 pass, 0 fail
  • bun run fix, bun run types, bun run ci: pass (72 existing lint warnings)
  • not run: the real CLI through a proxy (needs a Copilot credential and live GitHub); bun run e2e

Fixes #759

Assistant-model: Claude Sonnet 5.5
Assistant-workflow: goal (run f6b196ad-78d2-4d43-addc-1ea742a72646)
Assistant-duration: 4m converged, estimated 30m
Assistant-verification: red before fix passed: with defaultConnect only exported and the source change otherwise reverted, 3 of the 4 new tests failed (proxy and certificate variables missing from the CLI environment; no CONNECT reached the local proxy) and the secrets-absent test passed; with the fix all 4 pass
Assistant-verification: bun test apps/server/src/harness passed: 384 pass, 0 fail across 23 files
Assistant-verification: bun run fix passed: no changes beyond the edits, 72 existing lint warnings
Assistant-verification: bun run types passed: whole workspace and e2e
Assistant-verification: bun run ci passed: dprint, oxlint (72 warnings, 0 errors), token and design checks
Assistant-verification: local CONNECT proxy test passed: a stand-in CLI spawned by the SDK sent its HTTPS request to a 127.0.0.1 proxy that saw CONNECT api.github.com:443; the real CLI through a proxy was not run
Co-authored-by: Alex Lavaee lavaman131@github.com

…er runs

The copilot-sdk harness created its client with `env: { COPILOT_PLUGIN_DIR_ONLY: "true" }`. The SDK uses the `env` it is given as the CLI process's whole environment, so a server run behind an HTTP or HTTPS proxy kept using the proxy for its own requests while the CLI, which never received `HTTPS_PROXY`, `HTTP_PROXY` or `NO_PROXY`, went direct. Planner turns then failed at `session.create` with a network fetch error for `api.github.com/copilot_internal/user` (#759). Nothing else in the server creates a CopilotClient with an `env`; the runtime only receives the client the adapter builds.

The adapter now builds the CLI's environment from a fixed list: the proxy variables in upper and lower case, plus the certificate variables a proxy that re-signs TLS needs (`NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE`, `SSL_CERT_DIR`, each checked against the bundled CLI's own option table). A variable the server has not set is not added; one set to an empty string is passed as it is. `COPILOT_PLUGIN_DIR_ONLY` stays "true", and tokens, other variables and `COPILOT_ENABLE_BUILTIN_GITHUB_MCP` still never reach the CLI. `defaultConnect` is exported so the test can drive it. The self-hosting and hosted-agent guides say which variables the CLI receives and that nothing else is passed.

The new tests spawn a stand-in CLI through `COPILOT_CLI_PATH` under the SDK's own spawn and read the environment it is given: the variables appear when set and are absent when unset, and an unrelated token and secret are not passed. A fourth sends an HTTPS request from that stand-in to a local proxy and checks the proxy sees `CONNECT api.github.com:443`. The real CLI is not run through a proxy: it needs a Copilot credential and live GitHub, so that is not deterministic.

Fixes #759

Assistant-model: Claude Sonnet 5.5
Assistant-workflow: goal (run f6b196ad-78d2-4d43-addc-1ea742a72646)
Assistant-duration: 4m converged, estimated 30m
Assistant-verification: red before fix passed: with defaultConnect only exported and the source change otherwise reverted, 3 of the 4 new tests failed (proxy and certificate variables missing from the CLI environment; no CONNECT reached the local proxy) and the secrets-absent test passed; with the fix all 4 pass
Assistant-verification: bun test apps/server/src/harness passed: 384 pass, 0 fail across 23 files
Assistant-verification: bun run fix passed: no changes beyond the edits, 72 existing lint warnings
Assistant-verification: bun run types passed: whole workspace and e2e
Assistant-verification: bun run ci passed: dprint, oxlint (72 warnings, 0 errors), token and design checks
Assistant-verification: local CONNECT proxy test passed: a stand-in CLI spawned by the SDK sent its HTTPS request to a 127.0.0.1 proxy that saw CONNECT api.github.com:443; the real CLI through a proxy was not run
Co-authored-by: Alex Lavaee <lavaman131@github.com>
@lavaman131
lavaman131 merged commit b478aba into main Nov 5, 2026
24 checks passed
@lavaman131
lavaman131 deleted the fix-759-copilot-cli-proxy branch November 5, 2026 00:41
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.

copilot-sdk harness drops proxy variables, so the Planner can't run behind a proxy

1 participant