Skip to content

Commit 9ad32c8

Browse files
committed
feat: convert to OAuth type with preliminary prompts
- Convert from custom auth type to proper OAuth type - Use preliminary prompts for deployment type selection - Remove console.log in favor of OAuth callback pattern - Add timeout protection to OAuth polling - Set baseURL correctly for both github.com and enterprise Plugin now uses clean OAuth architecture: - Prompts ask deployment questions first - authorize() returns immediately with url/instructions - Core displays them using proper @clack/prompts - callback() handles OAuth polling with timeout protection
1 parent e2fc6fb commit 9ad32c8

1 file changed

Lines changed: 60 additions & 48 deletions

File tree

index.mjs

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ export async function CopilotAuthPlugin({ client }) {
4040
}
4141
}
4242

43-
// For enterprise, set baseURL dynamically based on enterpriseUrl in auth data
43+
// Set baseURL based on deployment type
4444
const enterpriseUrl = info.enterpriseUrl;
4545
const baseURL = enterpriseUrl
4646
? `https://copilot-api.${normalizeDomain(enterpriseUrl)}`
47-
: undefined;
47+
: "https://api.githubcopilot.com";
4848

4949
return {
50-
...(baseURL && { baseURL }),
50+
baseURL,
5151
apiKey: "",
5252
async fetch(input, init) {
5353
const info = await getAuth();
@@ -122,7 +122,7 @@ export async function CopilotAuthPlugin({ client }) {
122122
},
123123
methods: [
124124
{
125-
type: "custom",
125+
type: "oauth",
126126
label: "Login with GitHub Copilot",
127127
prompts: [
128128
{
@@ -163,8 +163,8 @@ export async function CopilotAuthPlugin({ client }) {
163163
},
164164
},
165165
],
166-
async authorize(inputs) {
167-
const deploymentType = inputs.deploymentType;
166+
async authorize(inputs = {}) {
167+
const deploymentType = inputs.deploymentType || "github.com";
168168

169169
let domain = "github.com";
170170
let actualProvider = "github-copilot";
@@ -191,61 +191,73 @@ export async function CopilotAuthPlugin({ client }) {
191191
});
192192

193193
if (!deviceResponse.ok) {
194-
return { type: "failed" };
194+
throw new Error("Failed to initiate device authorization");
195195
}
196196

197197
const deviceData = await deviceResponse.json();
198198

199-
console.log(`Go to: ${deviceData.verification_uri}`);
200-
console.log(`Enter code: ${deviceData.user_code}`);
199+
return {
200+
url: deviceData.verification_uri,
201+
instructions: `Enter code: ${deviceData.user_code}`,
202+
method: "auto",
203+
callback: async () => {
204+
const maxAttempts = Math.ceil(
205+
(deviceData.expires_in || 900) / (deviceData.interval || 5)
206+
);
207+
let attempts = 0;
201208

202-
while (true) {
203-
await new Promise((resolve) =>
204-
setTimeout(resolve, (deviceData.interval || 5) * 1000),
205-
);
209+
while (attempts < maxAttempts) {
210+
await new Promise((resolve) =>
211+
setTimeout(resolve, (deviceData.interval || 5) * 1000)
212+
);
206213

207-
const response = await fetch(urls.ACCESS_TOKEN_URL, {
208-
method: "POST",
209-
headers: {
210-
Accept: "application/json",
211-
"Content-Type": "application/json",
212-
"User-Agent": "GitHubCopilotChat/0.35.0",
213-
},
214-
body: JSON.stringify({
215-
client_id: CLIENT_ID,
216-
device_code: deviceData.device_code,
217-
grant_type:
218-
"urn:ietf:params:oauth:grant-type:device_code",
219-
}),
220-
});
214+
const response = await fetch(urls.ACCESS_TOKEN_URL, {
215+
method: "POST",
216+
headers: {
217+
Accept: "application/json",
218+
"Content-Type": "application/json",
219+
"User-Agent": "GitHubCopilotChat/0.35.0",
220+
},
221+
body: JSON.stringify({
222+
client_id: CLIENT_ID,
223+
device_code: deviceData.device_code,
224+
grant_type:
225+
"urn:ietf:params:oauth:grant-type:device_code",
226+
}),
227+
});
221228

222-
if (!response.ok) return { type: "failed" };
229+
if (!response.ok) return { type: "failed" };
223230

224-
const data = await response.json();
231+
const data = await response.json();
225232

226-
if (data.access_token) {
227-
const result = {
228-
type: "success",
229-
auth_type: "oauth",
230-
refresh: data.access_token,
231-
access: "",
232-
expires: 0,
233-
};
233+
if (data.access_token) {
234+
const result = {
235+
type: "success",
236+
refresh: data.access_token,
237+
access: "",
238+
expires: 0,
239+
};
234240

235-
if (actualProvider === "github-copilot-enterprise") {
236-
result.provider = "github-copilot-enterprise";
237-
result.enterpriseUrl = domain;
238-
}
241+
if (actualProvider === "github-copilot-enterprise") {
242+
result.provider = "github-copilot-enterprise";
243+
result.enterpriseUrl = domain;
244+
}
239245

240-
return result;
241-
}
246+
return result;
247+
}
242248

243-
if (data.error === "authorization_pending") {
244-
continue;
245-
}
249+
if (data.error === "authorization_pending") {
250+
attempts++;
251+
continue;
252+
}
246253

247-
if (data.error) return { type: "failed" };
248-
}
254+
if (data.error) return { type: "failed" };
255+
}
256+
257+
// Timeout
258+
return { type: "failed" };
259+
},
260+
};
249261
},
250262
},
251263
],

0 commit comments

Comments
 (0)