Skip to content

Commit b6909ed

Browse files
Long Chen (from Dev Box)Copilot
andcommitted
fix: only strip classic PATs (ghp_) from Copilot ACP child env
Root cause: Copilot CLI uses its own credential store and doesn't need env tokens. But when GITHUB_TOKEN contains a classic PAT (ghp_), Copilot tries to use it, fails ('Authentication required'), and does NOT fall back to its credential store. Fix: only delete GITHUB_TOKEN/GH_TOKEN when they contain classic PATs (ghp_ prefix). Keep OAuth tokens (gho_) and fine-grained PATs (github_pat_) intact since Copilot supports those. Also tighten classifyAcpError auth detection regex — the old /login/i pattern could false-match informational messages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d0bceea commit b6909ed

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

src/adapters/AcpAdapter.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,14 @@ export class AcpAdapter implements AgentAdapter {
147147
const code = error.code;
148148
const data = error.data ? ` Details: ${JSON.stringify(error.data)}` : '';
149149

150-
// Authentication
151-
if (/auth/i.test(msg) || /unauthorized/i.test(msg) || /login/i.test(msg)) {
150+
// Debug: log raw ACP error for diagnosis
151+
console.error(`[AcpAdapter] Raw ACP error: code=${code}, message="${msg}", data=${JSON.stringify(error.data)}`);
152+
153+
// Authentication — require explicit auth keywords, not generic "login" which
154+
// can appear in informational messages (e.g. "Run copilot login")
155+
if (/unauthorized|403|401/i.test(msg) || /authentication required/i.test(msg)) {
152156
return new Error(
153-
`ACP auth_failed: ${msg}. Fix: for Copilot run \`gh auth login\` (uses gh CLI auth, not env vars). For Claude run \`claude login\` or set ANTHROPIC_API_KEY.`
157+
`ACP auth_failed: ${msg}. Fix: check that .env GITHUB_TOKEN is not a classic PAT (ghp_) — Copilot doesn't support those. For Claude run \`claude login\` or set ANTHROPIC_API_KEY.`
154158
);
155159
}
156160

src/utils/copilotAuthEnv.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as path from 'path';
2+
3+
function normalizeExecutable(executable: string): string {
4+
return path.basename(executable).toLowerCase();
5+
}
6+
7+
export function isCopilotCliExecutable(executable: string): boolean {
8+
const normalized = normalizeExecutable(executable);
9+
return normalized === 'copilot' || normalized === 'copilot.exe' || normalized === 'copilot.cmd';
10+
}
11+
12+
/**
13+
* Sanitize env for Copilot CLI child processes.
14+
*
15+
* Copilot CLI uses its own credential store and does NOT need env tokens.
16+
* However, if GITHUB_TOKEN contains a classic PAT (ghp_), Copilot will
17+
* try to use it, fail, and report "Authentication required" instead of
18+
* falling back to its credential store. So we must remove classic PATs.
19+
*/
20+
export function sanitizeCopilotAuthEnv(env: NodeJS.ProcessEnv): void {
21+
if (env.COPILOT_GITHUB_TOKEN) {
22+
return;
23+
}
24+
25+
// Remove classic PATs (ghp_) — they poison Copilot's auth flow.
26+
// Keep OAuth tokens (gho_) and fine-grained PATs (github_pat_) intact.
27+
if (env.GITHUB_TOKEN?.startsWith('ghp_')) {
28+
delete env.GITHUB_TOKEN;
29+
}
30+
if (env.GH_TOKEN?.startsWith('ghp_')) {
31+
delete env.GH_TOKEN;
32+
}
33+
}

0 commit comments

Comments
 (0)