#11782: fix: resolve 403 auth error for GithubCopilot imageModel (#10277)
agents
stale
Cluster:
GitHub Copilot Enhancements
## Description
The image tool and media-understanding provider were passing the raw GitHub token directly to the `complete()` API, but GitHub Copilot requires exchanging the GitHub token for a Copilot API token first (via the token endpoint). This exchange was already implemented in the main embedding runner but missing in the image-only flows.
## Related Issue
Closes #10277
## Changes
- [src/agents/tools/image-tool.ts](src/agents/tools/image-tool.ts): Exchange GitHub token for Copilot token in `runImagePrompt()` before calling `complete()`.
- [src/media-understanding/providers/image.ts](src/media-understanding/providers/image.ts): Same exchange in `describeImageWithModel()`.
Both now mirror the token exchange pattern from the main runner ([src/agents/pi-embedded-runner/run.ts](src/agents/pi-embedded-runner/run.ts) and [src/agents/pi-embedded-runner/compact.ts](src/agents/pi-embedded-runner/compact.ts)).
## Testing
The fix applies the same auth flow already in use elsewhere, so existing tests for GitHub Copilot token exchange should cover this.
I tested this by building and running the application
Confirm by:
- Setting `agents.defaults.imageModel.primary = "github-copilot/gpt-5-mini"` with a different primary model
- Sending an image and verifying it no longer throws 403
## Fixes
#10277
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR fixes GitHub Copilot vision/image flows by exchanging the user’s GitHub token for a Copilot API token before calling `complete()`, matching the existing auth pattern used by the embedded runner. The change updates both the `image` agent tool and the media-understanding image provider to set the runtime API key to the exchanged Copilot token and to pass that token as the request `apiKey` for Copilot models, preventing 403s from using the raw GitHub token.
<h3>Confidence Score: 4/5</h3>
- This PR is likely safe to merge and aligns image auth with existing Copilot token exchange behavior.
- Changes are small and localized, and they reuse the existing Copilot token exchange implementation. Main concern is the new dynamic import path uses `github-copilot-token.js` while the repo appears to have `github-copilot-token.ts`, which could be a runtime module-resolution issue depending on the build output/TS config.
- src/agents/tools/image-tool.ts, src/media-understanding/providers/image.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#4364: fix(github-copilot): use gho_ tokens directly without exchange
by RebelSyntax · 2026-01-30
83.3%
#8467: fix(github-copilot): add configurable IDE headers + fix null filtering
by ericchansen · 2026-02-04
79.6%
#13505: feat(copilot): add GitHub Enterprise Cloud (GHE.com) support for Co...
by kryptus47 · 2026-02-10
78.9%
#8805: [Bug Fix][AI-assisted] Refresh Copilot token before expiry and retr...
by Arthur742Ramos · 2026-02-04
78.6%
#8660: fix: respect agents.defaults.models.*.params.maxTokens in image tool
by dbottme · 2026-02-04
78.2%
#15044: fix: refresh GitHub Copilot default model list
by Godzilla675 · 2026-02-12
78.0%
#4534: fix: packaging and OpenAI vision format conversion
by SalimBinYousuf1 · 2026-01-30
76.7%
#14368: fix: skip auth profile cooldown on format errors to prevent provide...
by koatora20 · 2026-02-12
75.4%
#4459: fix: enable image input for Kimi K2.5 and refresh stale config mode...
by manikv12 · 2026-01-30
74.8%
#22352: fix(auth): validate Copilot token cache belongs to requesting account
by xinhuagu · 2026-02-21
74.4%