MCPcopy
hub / github.com/coder/mux / startDeviceFlow

Method startDeviceFlow

src/node/services/copilotOauthService.ts:41–105  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

39 ) {}
40
41 async startDeviceFlow(): Promise<
42 Result<{ flowId: string; verificationUri: string; userCode: string }, string>
43 > {
44 const flowId = crypto.randomUUID();
45
46 try {
47 const res = await fetch(GITHUB_DEVICE_CODE_URL, {
48 method: "POST",
49 headers: {
50 Accept: "application/json",
51 "Content-Type": "application/x-www-form-urlencoded",
52 },
53 body: new URLSearchParams({
54 client_id: GITHUB_COPILOT_CLIENT_ID,
55 scope: SCOPE,
56 }),
57 });
58
59 if (!res.ok) {
60 const text = await res.text().catch(() => "");
61 return Err(`GitHub device code request failed (${res.status}): ${text}`);
62 }
63
64 const data = (await res.json()) as {
65 verification_uri?: string;
66 user_code?: string;
67 device_code?: string;
68 interval?: number;
69 };
70
71 if (!data.verification_uri || !data.user_code || !data.device_code) {
72 return Err("Invalid response from GitHub device code endpoint");
73 }
74
75 const { promise: resultPromise, resolve: resolveResult } =
76 createDeferred<Result<void, string>>();
77
78 const timeout = setTimeout(() => {
79 void this.finishFlow(flowId, Err("Timed out waiting for GitHub authorization"));
80 }, DEFAULT_TIMEOUT_MS);
81
82 this.flows.set(flowId, {
83 flowId,
84 deviceCode: data.device_code,
85 interval: data.interval ?? 5,
86 cancelled: false,
87 pollingStarted: false,
88 timeout,
89 cleanupTimeout: null,
90 resultPromise,
91 resolveResult,
92 });
93
94 log.debug(`Copilot OAuth device flow started (flowId=${flowId})`);
95
96 return Ok({
97 flowId,
98 verificationUri: data.verification_uri,

Callers

nothing calls this directly

Calls 8

finishFlowMethod · 0.95
ErrFunction · 0.90
createDeferredFunction · 0.90
OkFunction · 0.90
getErrorMessageFunction · 0.90
setMethod · 0.80
debugMethod · 0.80
fetchFunction · 0.50

Tested by

no test coverage detected