Skip to content

feat: Add GitHub Copilot as a model provider for inference#192

Open
jyje wants to merge 16 commits into
langchain-ai:mainfrom
jyje:jyje-add-github-copilot-provider
Open

feat: Add GitHub Copilot as a model provider for inference#192
jyje wants to merge 16 commits into
langchain-ai:mainfrom
jyje:jyje-add-github-copilot-provider

Conversation

@jyje

@jyje jyje commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds GitHub Copilot as a supported inference provider, so teams can reuse an existing Copilot subscription instead of provisioning a separate inference API key.

Closes #34, closes #30.

What's included

  • Provider config: new copilot entry in PROVIDER_CONFIGS (src/constants.ts), routed through the OpenAI-compatible Copilot API (https://api.githubcopilot.com).
  • Auth: COPILOT_API_KEY must be a GitHub OAuth token (e.g. gh auth token); Personal Access Tokens are rejected early with a clear error, since the Copilot API doesn't accept them for third-party integrations.
  • GitHub CLI auto-detect: if an active gh auth login session exists, OpenWiki detects and offers to reuse it during onboarding — no manual token entry needed.
  • Model routing: GPT-5-family models are routed through Copilot's Responses API; other models use chat completions.
  • Model catalog: verified directly against the real GitHub Copilot API's available-models list for the copilot-4-cli integrator, keeping only confirmed-available IDs: gpt-5.5, gpt-5.4-mini, claude-opus-4.8, claude-sonnet-5, claude-sonnet-4.6, claude-haiku-4.5, claude-fable-5, gemini-2.5-pro.
  • Alternative base URL: COPILOT_BASE_URL env var overrides the default endpoint (e.g. GHE.com data-residency hosts, proxied gateways), mirroring the existing ANTHROPIC_BASE_URL pattern.
  • Diagnostics: COPILOT_API_KEY is redacted from error/debug output like other provider keys.
  • CI: added a GitHub Copilot provider smoke test workflow.
  • Docs: README section for GitHub Copilot setup, plus COPILOT_BASE_URL documented under "Alternative base URLs".

Testing

Unit testspnpm run format:check && pnpm run lint:check && pnpm run build && pnpm exec vitest run — 87/87 pass, including new/extended coverage in test/constants.test.ts (provider validity, default model, base URL override) and test/redaction.test.ts (COPILOT_API_KEY redaction).

Manual end-to-end verification against the real GitHub Copilot API via pnpm run dev:

  1. Initial onboarded state — provider and model persisted to ~/.openwiki/.env, no re-prompt needed.
    1

  2. /provider — GitHub Copilot listed alongside all other providers, correctly marked as current.
    2

  3. /model — full Copilot model catalog listed and selectable.
    image

  4. Real chat response from gemini-2.5-pro.
    4

  5. Real chat response from claude-fable-5.
    5

All five confirm the provider, credential reuse, model selection, and live inference path work end to end — not just the unit-level config wiring.

Any questions or suggestions are welcome

jyje and others added 10 commits July 3, 2026 06:26
Adds `copilot` as a selectable OpenWiki provider backed by the
OpenAI-compatible GitHub Copilot API (https://api.githubcopilot.com),
authenticated via the COPILOT_API_KEY environment variable.

Resolves langchain-ai#34

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
Verified locally against api.githubcopilot.com: GitHub OAuth tokens
(gh auth token) work as-is as bearer tokens, so no copilot_internal
token exchange is needed. Also fix the Claude Haiku model ID to match
the Copilot catalog (claude-haiku-4.5) and document supported token
types (fine-grained PAT requires the "Copilot Requests" permission).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
The Copilot API refuses PATs for third-party integrations regardless
of permissions (verified empirically; only the first-party Copilot CLI
flow accepts them). Fail fast with actionable guidance instead of
surfacing the raw HTTP 400 from the API.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
Verified against the live Copilot API: GPT-5-family models are only
served through /responses, while other models (Claude, GPT-5.4-mini,
etc.) use /chat/completions. The Copilot-Integration-Id/Editor-Version
headers turned out to be unnecessary for either path, so they're
removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
Reverse-engineered Copilot backends (e.g. ericc-ch/copilot-api) show
that the api.githubcopilot.com endpoint only accepts OAuth tokens
issued by an allow-listed first-party client (VS Code, gh CLI, the
Copilot CLI) -- not arbitrary OAuth Apps or PATs. Rather than
embedding a borrowed client_id to run our own device flow (what those
reverse-engineered proxies do), OpenWiki delegates to the official
`gh` CLI, which is already an allow-listed client:

- At the Copilot credential step in `openwiki --init`, silently probe
  `gh auth token`. If a session exists, offer to reuse it with a single
  Enter press instead of requiring a manual paste.
- If no session is found, surface `gh`'s own interactive device-flow
  login inline (Tab key), temporarily releasing Ink's raw-mode control
  of stdin so `gh auth login`'s own prompts render correctly, then
  restoring it afterward.
- Manual token entry remains available as a fallback for environments
  without the GitHub CLI installed.

The GitHub Copilot CLI's own token store was intentionally left out of
scope: it has no documented "print current token" command, and its
storage format isn't guaranteed to stay stable across releases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
The probe effect listed copilotAuth.kind in its dependency array, so
the setCopilotAuth({ kind: "checking" }) call inside the effect
immediately re-triggered it: React ran the previous run's cleanup,
flipping the `cancelled` flag before the async gh probe resolved. The
result was a credential prompt stuck on "Checking for an existing
GitHub CLI session..." where Tab was ignored and Enter surfaced
"COPILOT_API_KEY is required."

Guard the probe with a ref and depend only on step/provider, so it
runs exactly once per setup and its resolution is no longer discarded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
…ilot-provider

# Conflicts:
#	README.md
#	src/agent/index.ts
#	src/cli.tsx
#	src/env.ts
- Verify model options against the real GitHub Copilot API model list and
  add gpt-5.5, gpt-5.4-mini, claude-opus-4.8, claude-sonnet-5,
  claude-sonnet-4.6, claude-haiku-4.5, claude-fable-5, and gemini-2.5-pro.
- Add COPILOT_BASE_URL_ENV_KEY so the copilot provider supports an
  alternative endpoint override (e.g. GHE.com data residency, a proxied
  gateway), mirroring the existing ANTHROPIC_BASE_URL pattern. Wired
  through PROVIDER_CONFIGS.copilot.baseUrlEnvKey, MANAGED_ENV_KEYS,
  isNonSecretDiagnosticKey, and the debug-value URL masking list.
- Document COPILOT_BASE_URL in README's Alternative base URLs section.
- Extend test/constants.test.ts's resolveProviderBaseUrl coverage with a
  copilot override case.

87/87 tests pass.
@emmanuelcvarghese

Copy link
Copy Markdown

When this is getting closed

jyje and others added 3 commits July 11, 2026 10:41
* bump langchain-openai dep (langchain-ai#232)

* openai langchain version bump (langchain-ai#241)

* feat: Make OpenWiki general purpose (langchain-ai#48)

* feat: Make general purpose

* cr

* cr

* fix gmail

* make it much better

* add cron hooks

* better ngrok

* write wiki to root

* cr

* Harrison/vibe code (langchain-ai#109)

* some vibe coding

* cr

* cr

* cr

* cr

* fix gh action

---------

Co-authored-by: bracesproul <braceasproul@gmail.com>

* update readme

* fix oauth link clicking

* drop just openwiki --init

* fix: oauth connection flow

* improve prompting

* cr

* cr

* brain->personal (langchain-ai#226)

* cr

* write instructions to INSTRUCTIONS.md file

* cr

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>

* fix: Update readme description (langchain-ai#242)

* fix: add configurable provider retry attempts (langchain-ai#239)

* fix: add OPENAI_COMPATIBLE_API_KEY to secret redaction list (langchain-ai#245)

The sanitizeDiagnosticText function redacted secrets for 6 provider API keys
but was missing OPENAI_COMPATIBLE_API_KEY. Users of the openai-compatible
provider could have their API keys leaked in error messages.

Added OPENAI_COMPATIBLE_API_KEY_ENV_KEY to both the import and the redaction
loop in diagnostics.ts, and added a test case to verify the redaction works.

Co-authored-by: Test User <test@example.com>

* fix: constrain init update writes to openwiki (langchain-ai#230)

Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>

* feat: add OpenAI ChatGPT-login provider (Codex OAuth) (langchain-ai#151)

* feat: add OpenAI ChatGPT-login provider (Codex OAuth)

Add an `openai-chatgpt` provider that authenticates model calls with a
ChatGPT/Codex OAuth login instead of a metered API key, so usage draws on the
ChatGPT subscription's included Codex usage.

It reuses `@langchain/openai`'s ChatOpenAI Responses-API integration pointed at
the Codex backend (`useResponsesApi` + `zdrEnabled` for `store: false`, base URL
and account/originator/beta headers), so DeepAgents' tool-calling and streaming
keep working with zero changes to the agent harness. Two Codex-backend quirks
are handled at model construction: forcing `stream: true`, and rewriting the
`system` input role to `developer`.

Includes a PKCE browser login + token refresh, an `oauth-login` step in the
existing credential wizard, token persistence in `~/.openwiki/.env`, tests, and
docs.

* feat: make ChatGPT login URL copyable (borderless render + c-to-copy via OSC 52)

* feat: let users paste the ChatGPT OAuth callback URL/code to finish login

Adds a manual-paste fallback to the browser login: while the loopback
callback server waits, the user can paste the redirect URL (or bare code)
into the wizard and press Enter to complete the login in-process. Removes
the need to curl the callback or set up SSH port forwarding on remote hosts.
Whichever arrives first — browser callback or pasted value — wins.

* feat: show ChatGPT account info and re-ask model after login

- Decode the signed-in email and plan (plus/pro/etc.) from the access-token
  JWT, persist them, show them in the ChatGPT login step, and add an
  "account:" line to the run header.
- Continue to the model and LangSmith steps after the ChatGPT login just like
  the API-key providers. Selecting a provider in the wizard now re-asks for the
  model even if one is stored, so a stale model id from a previous provider is
  not carried over.

* refactor: address review feedback on the ChatGPT login provider

- Centralize the CodexTokens <-> env mapping in openai-chatgpt-oauth.ts as
  codexTokensToEnv() and readCodexTokensFromEnv(), and use them from both the
  agent's refresh-at-startup and the credential wizard. The env contract now
  lives next to the type it serializes and is tested with the OAuth flow.
  readCodexTokensFromEnv() also returns null on a partial token set, so a
  leftover access token without an account id no longer looks signed in.
- Move formatChatGptAccount() into the same module and use it from cli.tsx
  instead of a second copy.
- Fix opening the browser on Windows. Under shell: true, cmd treats the & in
  the auth URL's query string as a command separator and mangles the URL. Use
  cmd /c start with a quoted URL and windowsVerbatimArguments instead.

* fix succ login msg

---------

Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>
Co-authored-by: bracesproul <braceasproul@gmail.com>

* fix assertion (langchain-ai#255)

* docs: add github issue templates (langchain-ai#172)

* docs: add GitHub issue templates

* convert to yaml and add config

---------

Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>
Co-authored-by: Colin Francis <colin.francis@langchain.dev>

* fix (langchain-ai#254)

* docs: document windows bun installation requirements (langchain-ai#217)

* fix: warn on Windows Bun installs

* add .cjs to esling config

* fix: document Windows Bun installation requirements

---------

Co-authored-by: akyourowngames <akyourowngames@users.noreply.github.com>
Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>
Co-authored-by: Colin Francis <colin.francis@langchain.dev>

* feat: add GPT-5.6 OpenAI model options (langchain-ai#252)

* feat: add GPT-5.6 OpenAI model options

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

* fix failing test

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>
Co-authored-by: Colin Francis <colin.francis@langchain.dev>

* fix(agent): keep init update checkpoints ephemeral (langchain-ai#259)

Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>

* fix: keep typeof check to reject unsupported source instance targets in cron commands (langchain-ai#246)

The cron pause/resume/delete commands only support string targets
(connector IDs or 'all'). Source instance targets are not yet supported
by the schedule functions. The typeof check correctly rejects them.

Added tests verifying source instance targets are properly rejected.

Co-authored-by: Test User <test@example.com>
Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>

* fix: Improve code onboarding, save INSTRUCTIONS.md to openwiki/ (langchain-ai#264)

* fix: Improve code onboarding, save INSTRUCTIONS.md to openwiki/

* cr

* fix: chatgpt login with 5.6-luna (langchain-ai#268)

* fix: chatgpt login with 5.6-luna

* cr

* release: 0.1.1 (langchain-ai#269)

---------

Co-authored-by: Colin Francis <131073567+colifran@users.noreply.github.com>
Co-authored-by: Brace Sproul <braceasproul@gmail.com>
Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
Co-authored-by: Abhishek Ranjan <aviranjan444@gmail.com>
Co-authored-by: Himanshu Kumar <145797211+himanshu231204@users.noreply.github.com>
Co-authored-by: Test User <test@example.com>
Co-authored-by: Eva <admin@100yen.org>
Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Yassine Mhirsi <98828473+Yassine-Mhirsi@users.noreply.github.com>
Co-authored-by: sarthug <smpingale2469@gmail.com>
Co-authored-by: Colin Francis <colin.francis@langchain.dev>
Co-authored-by: Krish <animeit158@gmail.com>
Co-authored-by: akyourowngames <akyourowngames@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: zan22ye <iwillgotothemoon@163.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Records merge ancestry with upstream/main so GitHub recomputes the
PR langchain-ai#192 merge-base. The tree is unchanged: the squash-merged #7
already contains all upstream changes plus the conflict resolution.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XjawjWsUJb2MhBXQGp79f
…ilot-provider

Syncs with upstream 0.1.1+ (9 new commits, most notably NVIDIA NIM
(langchain-ai#42) landing on main). Four files conflicted, all additive
side-by-side insertions from the two providers being added in
parallel; resolved by keeping both sides:

- README.md: kept the GitHub Copilot section, merged NVIDIA NIM into
  the provider list intro sentence.
- src/cli.tsx: merged both providers into the invalid-provider error
  message.
- test/constants.test.ts, test/redaction.test.ts: union of both
  providers' assertions (isValidModelId/isValidProvider/
  resolveProviderBaseUrl/getDefaultModelId cases, and the
  COPILOT_API_KEY/NVIDIA_API_KEY redaction test pairs).

src/constants.ts, src/diagnostics.ts, and src/env.ts auto-merged
cleanly.

Verified: format:check, lint:check, typecheck, build, and pnpm test
(199/199) all pass after resolution.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjNFojcfsEnwPRSkhqcxbt
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.

Support GitHub Copilot CLI as a Model Provider Works with GitHub copilot ?

2 participants