UNPKG

abyss-ai

Version:

Autonomous AI coding agent - enhanced OpenCode with autonomous capabilities

148 lines (125 loc) 3.8 kB
import { z } from "zod" import { Auth } from "./index" import { NamedError } from "../util/error" export namespace AuthGithubCopilot { const CLIENT_ID = "Iv1.b507a08c87ecfe98" const DEVICE_CODE_URL = "https://github.com/login/device/code" const ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token" const COPILOT_API_KEY_URL = "https://api.github.com/copilot_internal/v2/token" interface DeviceCodeResponse { device_code: string user_code: string verification_uri: string expires_in: number interval: number } interface AccessTokenResponse { access_token?: string error?: string error_description?: string } interface CopilotTokenResponse { token: string expires_at: number refresh_in: number endpoints: { api: string } } export async function authorize() { const deviceResponse = await fetch(DEVICE_CODE_URL, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", "User-Agent": "GitHubCopilotChat/0.26.7", }, body: JSON.stringify({ client_id: CLIENT_ID, scope: "read:user", }), }) const deviceData: DeviceCodeResponse = await deviceResponse.json() return { device: deviceData.device_code, user: deviceData.user_code, verification: deviceData.verification_uri, interval: deviceData.interval || 5, expiry: deviceData.expires_in, } } export async function poll(device_code: string) { const response = await fetch(ACCESS_TOKEN_URL, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", "User-Agent": "GitHubCopilotChat/0.26.7", }, body: JSON.stringify({ client_id: CLIENT_ID, device_code, grant_type: "urn:ietf:params:oauth:grant-type:device_code", }), }) if (!response.ok) return "failed" const data: AccessTokenResponse = await response.json() if (data.access_token) { // Store the GitHub OAuth token await Auth.set("github-copilot", { type: "oauth", refresh: data.access_token, access: "", expires: 0, }) return "complete" } if (data.error === "authorization_pending") return "pending" if (data.error) return "failed" return "pending" } export async function access() { const info = await Auth.get("github-copilot") if (!info || info.type !== "oauth") return if (info.access && info.expires > Date.now()) return info.access // Get new Copilot API token const response = await fetch(COPILOT_API_KEY_URL, { headers: { Accept: "application/json", Authorization: `Bearer ${info.refresh}`, "User-Agent": "GitHubCopilotChat/0.26.7", "Editor-Version": "vscode/1.99.3", "Editor-Plugin-Version": "copilot-chat/0.26.7", }, }) if (!response.ok) return const tokenData: CopilotTokenResponse = await response.json() // Store the Copilot API token await Auth.set("github-copilot", { type: "oauth", refresh: info.refresh, access: tokenData.token, expires: tokenData.expires_at * 1000, }) return tokenData.token } export const DeviceCodeError = NamedError.create("DeviceCodeError", z.object({})) export const TokenExchangeError = NamedError.create( "TokenExchangeError", z.object({ message: z.string(), }), ) export const AuthenticationError = NamedError.create( "AuthenticationError", z.object({ message: z.string(), }), ) export const CopilotTokenError = NamedError.create( "CopilotTokenError", z.object({ message: z.string(), }), ) }