summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/plugin/copilot.ts24
1 files changed, 22 insertions, 2 deletions
diff --git a/packages/opencode/src/plugin/copilot.ts b/packages/opencode/src/plugin/copilot.ts
index 17ce9debc..776b70fe9 100644
--- a/packages/opencode/src/plugin/copilot.ts
+++ b/packages/opencode/src/plugin/copilot.ts
@@ -3,6 +3,9 @@ import { Installation } from "@/installation"
import { iife } from "@/util/iife"
const CLIENT_ID = "Ov23li8tweQw6odWQebz"
+// Add a small safety buffer when polling to avoid hitting the server
+// slightly too early due to clock skew / timer drift.
+const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 // 3 seconds
function normalizeDomain(url: string) {
return url.replace(/^https?:\/\//, "").replace(/\/$/, "")
@@ -204,6 +207,7 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
const data = (await response.json()) as {
access_token?: string
error?: string
+ interval?: number
}
if (data.access_token) {
@@ -230,13 +234,29 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
}
if (data.error === "authorization_pending") {
- await new Promise((resolve) => setTimeout(resolve, deviceData.interval * 1000))
+ await Bun.sleep(deviceData.interval * 1000 + OAUTH_POLLING_SAFETY_MARGIN_MS)
+ continue
+ }
+
+ if (data.error === "slow_down") {
+ // Based on the RFC spec, we must add 5 seconds to our current polling interval.
+ // (See https://www.rfc-editor.org/rfc/rfc8628#section-3.5)
+ let newInterval = (deviceData.interval + 5) * 1000
+
+ // GitHub OAuth API may return the new interval in seconds in the response.
+ // We should try to use that if provided with safety margin.
+ const serverInterval = data.interval
+ if (serverInterval && typeof serverInterval === 'number' && serverInterval > 0) {
+ newInterval = serverInterval * 1000
+ }
+
+ await Bun.sleep(newInterval + OAUTH_POLLING_SAFETY_MARGIN_MS)
continue
}
if (data.error) return { type: "failed" as const }
- await new Promise((resolve) => setTimeout(resolve, deviceData.interval * 1000))
+ await Bun.sleep(deviceData.interval * 1000 + OAUTH_POLLING_SAFETY_MARGIN_MS)
continue
}
},