Repository navigation
feat(providers): Complete GHE Copilot OAuth provider implementation - #7546
diegosouzapw merged 27 commits into
Conversation
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Thanks for the thorough GHE Copilot implementation — the device-code flow, the endpoints.api/endpoints.proxy distinction, and the live model-discovery fallback are all well thought through, and I confirmed this doesn't duplicate any existing copilot provider. Two things I'd like fixed before merge:
Separately: your branch has drifted ~90 commits behind current The live OAuth/token-exchange flow against a real GHE tenant needs a validation run on our side before shipping (can't be exercised in CI). Will follow up once that's done. |
… gheUrl validation
Add GHE Copilot registry entry (executor: "ghe-copilot") so the provider is resolvable by the API routes and gets the same model catalog as github Copilot.
- Add gheCopilot OAuth provider (device-code flow targeting GHE host) - Register in OAuth PROVIDERS map - Thread gheUrl from query param → device-code request → poll → postExchange → providerSpecificData so the GHE host is used end-to-end - Restore corrupted src/lib/oauth/providers/github.ts from HEAD
- Route ghe-copilot through the device-code OAuth branch (was falling through to browser OAuth → "Browser OAuth unavailable" error) - Add a gheUrl collection step so the enterprise host is supplied before the device-code request, and thread it into /device-code + /poll
pollToken read gheUrl from config (GITHUB_CONFIG, which has none) and threw "gheUrl is required" on every poll — the connection hung forever after device authorization. Now reads gheUrl from extraData (passed by the route), and postExchange carries it forward into mapTokens so it is persisted in providerSpecificData for the executor.
- Capture endpoints.proxy from the GHE token response and store it as copilotProxyUrl; route chat/responses traffic to that enterprise host instead of the static gheUrl/chat/completions path (was 406/404). - Always route GHE Copilot to /chat/completions (GHE proxy 404s on /responses); the Responses API is served via the chat transformer. - Strip the ghe-copilot/ prefix from the upstream model id. - Remove openai-responses targetFormat from GHE models so chatCore does not run the Responses transformer (which dropped `messages`). - Add ghe-copilot to OAUTH_TEST_CONFIG (account test was "unsupported"). - Register executor in eslint suppressions.
The GHE Copilot proxy rejects `stream: false` ("stream": false is not
supported). Only forward the flag when actually streaming; omit it
otherwise.
The GHE Copilot proxy rejects `stream: false`. forceStream:true in the registry makes chatCore pass upstreamStream=true, but GithubExecutor .transformRequest ignores the stream arg (void stream) and keeps the client's stream:false. Override transformRequest in GheCopilotExecutor to force stream:true so the proxy accepts the request; chatCore drains the SSE back to JSON for non-stream clients.
- Add fetchGheCopilotModels/parseGheCopilotModels using enterprise proxy URL
and { models: [{ name }] } response shape (no static allowlist)
- Wire ghe-copilot into models-import route; use plain fetch (safeOutboundFetch
header guard strips the copilot bearer token -> 403)
- Import now returns real enterprise models (copilot-nes-oct, etc.) and chat
resolves them correctly
The GHE token endpoint returns two hosts:
- endpoints.api (copilotApiUrl) -> chat/completions + real chat model
catalog, shape { data: [{ id }] }
- endpoints.proxy (copilotProxyUrl) -> NES/autocomplete/instant-apply only,
shape { models: [{ name }] }
We were routing chat AND model discovery to endpoints.proxy, so import only
returned completion models (copilot-nes-*, instant-apply) and never the real
chat models (claude-*, gpt-*, gemini-*).
- Executor: capture endpoints.api as copilotApiUrl; buildUrl prefers it
- OAuth postExchange/mapTokens: persist copilotApiUrl from endpoints.api
- Model discovery: fetch from copilotApiUrl/models, parse { data:[{id}] }
(and proxy { models:[{name}] }) shapes, no allowlist
- All traffic stays on the configured GHE host (deutschebahn.ghe.com),
never api.githubcopilot.com
Verified: import returns 28 real chat models; chat with gpt-4o streams OK.
- Replace the 6 explicit `any` types in GheCopilotExecutor (transformRequest, refreshCredentials) with proper ProviderCredentials / unknown / ExecutorLog types, and drop the config/quality/eslint-suppressions.json allowlist entry added for them — policy requires new violations be fixed, not frozen. - Extract refreshViaGitHubToken() and buildRefreshedProviderSpecificData() helpers out of refreshCredentials() to bring its cyclomatic complexity (21) back under the repo's ratchet threshold (15); behavior unchanged. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
886b7da to
f089d88
Compare
Resolves conflicts in src/mitm/dns/provision.ts (keep release's provisionDefaultDns/provisionAgentDns/provisionCustomHostsDns split + canElevate container guard, preserve ghe-copilot host injection inside provisionAgentDns) and src/shared/constants/providers/oauth.ts (keep both the ghe-copilot and xai-oauth catalog entries). Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
|
Re-checked: the resolvePublicCred() usage for the OAuth client id looks correct now, that concern is resolved. The branch has drifted from the current release/v3.8.49 tip though and now conflicts — please rebase and push, then this can go through the rest of the review (mandatory isLocalOnlyPath check for the new routes, docs/openapi sync). |
…e-copilot-provider # Conflicts: # src/app/api/providers/[id]/test/route.ts
…ilot OAuth provider Extracts the GHE enterprise-URL config step from OAuthModal.tsx into a new leaf component (src/shared/components/oauthModal/GheConfigStep.tsx) to shrink the frozen file's own growth, and rebaselines the two remaining irreducible wiring bumps (device-code route.ts 960->963, OAuthModal.tsx 1030->1056) with justification comments, mirroring the existing cheaper-inference#7399/cheaper-inference#6636 precedent on this same file. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Resolves merge-train ejection caused by 11 new release commits (docs i18n, chatCore compression, combo pipeline, perplexity-web protocol, model registry refactors). No conflicts — all changes in disjoint files; the PR's own file-size splits (OAuthModal.tsx -> GheConfigStep.tsx, oauth route.ts) were preserved untouched. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…cope eslint bump Planning artifacts live outside the repo tree; package.json/lock restored to the release state (the eslint patch bump was unrelated drift from the fork's history). Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…the device-code flow Applies the PR's existing providerSpecificData HTTPS rule to the OAuth route's searchParams and device-flow extraData entry points, rejecting malformed or non-HTTPS enterprise URLs with 400 before any upstream fetch. Private-IP hosts stay allowed by design — on-prem GHE Server is the primary use case. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…dation guards (963->970) Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
|
Validated in local merge-train (fast mode) on 192.168.0.113 @ 809513aabe7c4a657710cc97c7450a42a3cf22ae — 5-PR wave: static gates + changed tests + vitest green (log: /tmp/mt-full.log + suite log on the box). Full-suite parity for today already ran on this branch (runs 4+5). |
b3d3dd5
into
cheaper-inference:release/v3.8.49
#7546 registered the ghe-copilot provider in src/lib/oauth/providers/index.ts but left it out of two mirrors that are asserted to stay in lock-step: - PROVIDERS in src/lib/oauth/constants/oauth.ts (the canonical id map), which made oauth-providers-config.test.ts fail three assertions at once; - MITM_TOOL_HOSTS, the client-safe projection of ALL_TARGETS, which made mitm-tool-hosts.test.ts fail its drift guard. Both reds reproduce on the pure release tip and turned every open PR's unit shards red, so this unblocks the whole queue. The test expectations are extended (not weakened) to cover the new provider.
…7546 AgentEmoji's AGENT_COLORS is a Record<AgentId, …>; #7546 widened AgentId with 'ghe-copilot' without adding the entry (TS2741). GheConfigStep typed its error prop as `unknown` and rendered it directly, which is not a ReactNode (TS2322). Both are counted by check:dashboard-typecheck, which was failing on the pure release tip (261 live vs 259 frozen) and reddening Fast Quality Gates for every open PR. Now back to the frozen 259.
…ilot OAuth provider Extracts the GHE enterprise-URL config step from OAuthModal.tsx into a new leaf component (src/shared/components/oauthModal/GheConfigStep.tsx) to shrink the frozen file's own growth, and rebaselines the two remaining irreducible wiring bumps (device-code route.ts 960->963, OAuthModal.tsx 1030->1056) with justification comments, mirroring the existing cheaper-inference#7399/cheaper-inference#6636 precedent on this same file. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…heaper-inference#7546) * docs: add design spec for GHE Copilot provider * feat(mitm): add GHE Copilot target descriptor * feat(executors): add GheCopilotExecutor for GHE Copilot * feat(executors): register GheCopilotExecutor in factory * feat(providers): add ghe-copilot provider with gheUrl validation * feat(providers): add ghe-copilot to OAUTH_PROVIDERS and enforce HTTPS gheUrl validation * test(ghe-copilot): add unit tests for GheCopilotExecutor and GHE_COPILOT_TARGET * feat: complete GHE Copilot provider implementation * feat: register ghe-copilot provider in registry Add GHE Copilot registry entry (executor: "ghe-copilot") so the provider is resolvable by the API routes and gets the same model catalog as github Copilot. * feat: wire ghe-copilot into OAuth flow with per-connection gheUrl - Add gheCopilot OAuth provider (device-code flow targeting GHE host) - Register in OAuth PROVIDERS map - Thread gheUrl from query param → device-code request → poll → postExchange → providerSpecificData so the GHE host is used end-to-end - Restore corrupted src/lib/oauth/providers/github.ts from HEAD * feat: add ghe-copilot device-code UI with gheUrl input - Route ghe-copilot through the device-code OAuth branch (was falling through to browser OAuth → "Browser OAuth unavailable" error) - Add a gheUrl collection step so the enterprise host is supplied before the device-code request, and thread it into /device-code + /poll * fix: thread gheUrl through GHE Copilot pollToken + postExchange pollToken read gheUrl from config (GITHUB_CONFIG, which has none) and threw "gheUrl is required" on every poll — the connection hung forever after device authorization. Now reads gheUrl from extraData (passed by the route), and postExchange carries it forward into mapTokens so it is persisted in providerSpecificData for the executor. * fix: GHE Copilot chat routing + account test - Capture endpoints.proxy from the GHE token response and store it as copilotProxyUrl; route chat/responses traffic to that enterprise host instead of the static gheUrl/chat/completions path (was 406/404). - Always route GHE Copilot to /chat/completions (GHE proxy 404s on /responses); the Responses API is served via the chat transformer. - Strip the ghe-copilot/ prefix from the upstream model id. - Remove openai-responses targetFormat from GHE models so chatCore does not run the Responses transformer (which dropped `messages`). - Add ghe-copilot to OAUTH_TEST_CONFIG (account test was "unsupported"). - Register executor in eslint suppressions. * fix: drop stream:false for GHE Copilot The GHE Copilot proxy rejects `stream: false` ("stream": false is not supported). Only forward the flag when actually streaming; omit it otherwise. * fix: force stream:true upstream for GHE Copilot (streaming-only proxy) The GHE Copilot proxy rejects `stream: false`. forceStream:true in the registry makes chatCore pass upstreamStream=true, but GithubExecutor .transformRequest ignores the stream arg (void stream) and keeps the client's stream:false. Override transformRequest in GheCopilotExecutor to force stream:true so the proxy accepts the request; chatCore drains the SSE back to JSON for non-stream clients. * fix: GHE Copilot live model discovery from copilotProxyUrl/models - Add fetchGheCopilotModels/parseGheCopilotModels using enterprise proxy URL and { models: [{ name }] } response shape (no static allowlist) - Wire ghe-copilot into models-import route; use plain fetch (safeOutboundFetch header guard strips the copilot bearer token -> 403) - Import now returns real enterprise models (copilot-nes-oct, etc.) and chat resolves them correctly * fix: GHE Copilot uses endpoints.api host for chat + model discovery The GHE token endpoint returns two hosts: - endpoints.api (copilotApiUrl) -> chat/completions + real chat model catalog, shape { data: [{ id }] } - endpoints.proxy (copilotProxyUrl) -> NES/autocomplete/instant-apply only, shape { models: [{ name }] } We were routing chat AND model discovery to endpoints.proxy, so import only returned completion models (copilot-nes-*, instant-apply) and never the real chat models (claude-*, gpt-*, gemini-*). - Executor: capture endpoints.api as copilotApiUrl; buildUrl prefers it - OAuth postExchange/mapTokens: persist copilotApiUrl from endpoints.api - Model discovery: fetch from copilotApiUrl/models, parse { data:[{id}] } (and proxy { models:[{name}] }) shapes, no allowlist - All traffic stays on the configured GHE host (deutschebahn.ghe.com), never api.githubcopilot.com Verified: import returns 28 real chat models; chat with gpt-4o streams OK. * feat(providers): finalize GHE Copilot implementation and add changelog fragment * fix(providers): resolve ghe-copilot no-explicit-any + complexity ratchet - Replace the 6 explicit `any` types in GheCopilotExecutor (transformRequest, refreshCredentials) with proper ProviderCredentials / unknown / ExecutorLog types, and drop the config/quality/eslint-suppressions.json allowlist entry added for them — policy requires new violations be fixed, not frozen. - Extract refreshViaGitHubToken() and buildRefreshedProviderSpecificData() helpers out of refreshCredentials() to bring its cyclomatic complexity (21) back under the repo's ratchet threshold (15); behavior unchanged. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * fix(oauth): unblock cheaper-inference#7546 file-size gate for GHE Copilot OAuth provider Extracts the GHE enterprise-URL config step from OAuthModal.tsx into a new leaf component (src/shared/components/oauthModal/GheConfigStep.tsx) to shrink the frozen file's own growth, and rebaselines the two remaining irreducible wiring bumps (device-code route.ts 960->963, OAuthModal.tsx 1030->1056) with justification comments, mirroring the existing cheaper-inference#7399/cheaper-inference#6636 precedent on this same file. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * chore(ghe-copilot): drop planning spec from docs/ and revert out-of-scope eslint bump Planning artifacts live outside the repo tree; package.json/lock restored to the release state (the eslint patch bump was unrelated drift from the fork's history). Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * fix(oauth): validate gheUrl (HTTPS-only) at both raw entry points of the device-code flow Applies the PR's existing providerSpecificData HTTPS rule to the OAuth route's searchParams and device-flow extraData entry points, rejecting malformed or non-HTTPS enterprise URLs with 400 before any upstream fetch. Private-IP hosts stay allowed by design — on-prem GHE Server is the primary use case. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * chore(quality): extend oauth route file-size note for the gheUrl validation guards (963->970) Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Alexander Helm <alexander.helm@deutschebahn.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com> Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com> Co-authored-by: hppsc1215 <hppsc1215@users.noreply.github.com>
cheaper-inference#7546 registered the ghe-copilot provider in src/lib/oauth/providers/index.ts but left it out of two mirrors that are asserted to stay in lock-step: - PROVIDERS in src/lib/oauth/constants/oauth.ts (the canonical id map), which made oauth-providers-config.test.ts fail three assertions at once; - MITM_TOOL_HOSTS, the client-safe projection of ALL_TARGETS, which made mitm-tool-hosts.test.ts fail its drift guard. Both reds reproduce on the pure release tip and turned every open PR's unit shards red, so this unblocks the whole queue. The test expectations are extended (not weakened) to cover the new provider.
…heaper-inference#7546 AgentEmoji's AGENT_COLORS is a Record<AgentId, …>; cheaper-inference#7546 widened AgentId with 'ghe-copilot' without adding the entry (TS2741). GheConfigStep typed its error prop as `unknown` and rendered it directly, which is not a ReactNode (TS2322). Both are counted by check:dashboard-typecheck, which was failing on the pure release tip (261 live vs 259 frozen) and reddening Fast Quality Gates for every open PR. Now back to the frozen 259.
…heaper-inference#7546) * docs: add design spec for GHE Copilot provider * feat(mitm): add GHE Copilot target descriptor * feat(executors): add GheCopilotExecutor for GHE Copilot * feat(executors): register GheCopilotExecutor in factory * feat(providers): add ghe-copilot provider with gheUrl validation * feat(providers): add ghe-copilot to OAUTH_PROVIDERS and enforce HTTPS gheUrl validation * test(ghe-copilot): add unit tests for GheCopilotExecutor and GHE_COPILOT_TARGET * feat: complete GHE Copilot provider implementation * feat: register ghe-copilot provider in registry Add GHE Copilot registry entry (executor: "ghe-copilot") so the provider is resolvable by the API routes and gets the same model catalog as github Copilot. * feat: wire ghe-copilot into OAuth flow with per-connection gheUrl - Add gheCopilot OAuth provider (device-code flow targeting GHE host) - Register in OAuth PROVIDERS map - Thread gheUrl from query param → device-code request → poll → postExchange → providerSpecificData so the GHE host is used end-to-end - Restore corrupted src/lib/oauth/providers/github.ts from HEAD * feat: add ghe-copilot device-code UI with gheUrl input - Route ghe-copilot through the device-code OAuth branch (was falling through to browser OAuth → "Browser OAuth unavailable" error) - Add a gheUrl collection step so the enterprise host is supplied before the device-code request, and thread it into /device-code + /poll * fix: thread gheUrl through GHE Copilot pollToken + postExchange pollToken read gheUrl from config (GITHUB_CONFIG, which has none) and threw "gheUrl is required" on every poll — the connection hung forever after device authorization. Now reads gheUrl from extraData (passed by the route), and postExchange carries it forward into mapTokens so it is persisted in providerSpecificData for the executor. * fix: GHE Copilot chat routing + account test - Capture endpoints.proxy from the GHE token response and store it as copilotProxyUrl; route chat/responses traffic to that enterprise host instead of the static gheUrl/chat/completions path (was 406/404). - Always route GHE Copilot to /chat/completions (GHE proxy 404s on /responses); the Responses API is served via the chat transformer. - Strip the ghe-copilot/ prefix from the upstream model id. - Remove openai-responses targetFormat from GHE models so chatCore does not run the Responses transformer (which dropped `messages`). - Add ghe-copilot to OAUTH_TEST_CONFIG (account test was "unsupported"). - Register executor in eslint suppressions. * fix: drop stream:false for GHE Copilot The GHE Copilot proxy rejects `stream: false` ("stream": false is not supported). Only forward the flag when actually streaming; omit it otherwise. * fix: force stream:true upstream for GHE Copilot (streaming-only proxy) The GHE Copilot proxy rejects `stream: false`. forceStream:true in the registry makes chatCore pass upstreamStream=true, but GithubExecutor .transformRequest ignores the stream arg (void stream) and keeps the client's stream:false. Override transformRequest in GheCopilotExecutor to force stream:true so the proxy accepts the request; chatCore drains the SSE back to JSON for non-stream clients. * fix: GHE Copilot live model discovery from copilotProxyUrl/models - Add fetchGheCopilotModels/parseGheCopilotModels using enterprise proxy URL and { models: [{ name }] } response shape (no static allowlist) - Wire ghe-copilot into models-import route; use plain fetch (safeOutboundFetch header guard strips the copilot bearer token -> 403) - Import now returns real enterprise models (copilot-nes-oct, etc.) and chat resolves them correctly * fix: GHE Copilot uses endpoints.api host for chat + model discovery The GHE token endpoint returns two hosts: - endpoints.api (copilotApiUrl) -> chat/completions + real chat model catalog, shape { data: [{ id }] } - endpoints.proxy (copilotProxyUrl) -> NES/autocomplete/instant-apply only, shape { models: [{ name }] } We were routing chat AND model discovery to endpoints.proxy, so import only returned completion models (copilot-nes-*, instant-apply) and never the real chat models (claude-*, gpt-*, gemini-*). - Executor: capture endpoints.api as copilotApiUrl; buildUrl prefers it - OAuth postExchange/mapTokens: persist copilotApiUrl from endpoints.api - Model discovery: fetch from copilotApiUrl/models, parse { data:[{id}] } (and proxy { models:[{name}] }) shapes, no allowlist - All traffic stays on the configured GHE host (deutschebahn.ghe.com), never api.githubcopilot.com Verified: import returns 28 real chat models; chat with gpt-4o streams OK. * feat(providers): finalize GHE Copilot implementation and add changelog fragment * fix(providers): resolve ghe-copilot no-explicit-any + complexity ratchet - Replace the 6 explicit `any` types in GheCopilotExecutor (transformRequest, refreshCredentials) with proper ProviderCredentials / unknown / ExecutorLog types, and drop the config/quality/eslint-suppressions.json allowlist entry added for them — policy requires new violations be fixed, not frozen. - Extract refreshViaGitHubToken() and buildRefreshedProviderSpecificData() helpers out of refreshCredentials() to bring its cyclomatic complexity (21) back under the repo's ratchet threshold (15); behavior unchanged. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * fix(oauth): unblock cheaper-inference#7546 file-size gate for GHE Copilot OAuth provider Extracts the GHE enterprise-URL config step from OAuthModal.tsx into a new leaf component (src/shared/components/oauthModal/GheConfigStep.tsx) to shrink the frozen file's own growth, and rebaselines the two remaining irreducible wiring bumps (device-code route.ts 960->963, OAuthModal.tsx 1030->1056) with justification comments, mirroring the existing cheaper-inference#7399/cheaper-inference#6636 precedent on this same file. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * chore(ghe-copilot): drop planning spec from docs/ and revert out-of-scope eslint bump Planning artifacts live outside the repo tree; package.json/lock restored to the release state (the eslint patch bump was unrelated drift from the fork's history). Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * fix(oauth): validate gheUrl (HTTPS-only) at both raw entry points of the device-code flow Applies the PR's existing providerSpecificData HTTPS rule to the OAuth route's searchParams and device-flow extraData entry points, rejecting malformed or non-HTTPS enterprise URLs with 400 before any upstream fetch. Private-IP hosts stay allowed by design — on-prem GHE Server is the primary use case. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * chore(quality): extend oauth route file-size note for the gheUrl validation guards (963->970) Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Alexander Helm <alexander.helm@deutschebahn.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com> Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com> Co-authored-by: hppsc1215 <hppsc1215@users.noreply.github.com>
cheaper-inference#7546 registered the ghe-copilot provider in src/lib/oauth/providers/index.ts but left it out of two mirrors that are asserted to stay in lock-step: - PROVIDERS in src/lib/oauth/constants/oauth.ts (the canonical id map), which made oauth-providers-config.test.ts fail three assertions at once; - MITM_TOOL_HOSTS, the client-safe projection of ALL_TARGETS, which made mitm-tool-hosts.test.ts fail its drift guard. Both reds reproduce on the pure release tip and turned every open PR's unit shards red, so this unblocks the whole queue. The test expectations are extended (not weakened) to cover the new provider.
…heaper-inference#7546 AgentEmoji's AGENT_COLORS is a Record<AgentId, …>; cheaper-inference#7546 widened AgentId with 'ghe-copilot' without adding the entry (TS2741). GheConfigStep typed its error prop as `unknown` and rendered it directly, which is not a ReactNode (TS2322). Both are counted by check:dashboard-typecheck, which was failing on the pure release tip (261 live vs 259 frozen) and reddening Fast Quality Gates for every open PR. Now back to the frozen 259.
Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping.