copilot-api-plus 1.0.14 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -8
- package/dist/{auth-Cm_0h9bp.js → auth-CsslwaJY.js} +137 -11
- package/dist/auth-CsslwaJY.js.map +1 -0
- package/dist/auth-DqWzJajV.js +4 -0
- package/dist/{get-models-Dq2ZDU9m.js → get-models-BOgYoUAJ.js} +2 -2
- package/dist/{get-models-Bbb8B5jI.js → get-models-DZR1TS4C.js} +2 -2
- package/dist/{get-models-Bbb8B5jI.js.map → get-models-DZR1TS4C.js.map} +1 -1
- package/dist/{get-user-BFf5xJXg.js → get-user-BzIEATcF.js} +6 -3
- package/dist/get-user-BzIEATcF.js.map +1 -0
- package/dist/get-user-CsQCc3Qx.js +5 -0
- package/dist/main.js +544 -94
- package/dist/main.js.map +1 -1
- package/dist/state-CcLGr8VN.js.map +1 -1
- package/dist/{token-B8crDDoA.js → token-BUmQ_BcM.js} +15 -5
- package/dist/token-BUmQ_BcM.js.map +1 -0
- package/dist/{token-DS09XjQ5.js → token-DhdRMuOy.js} +2 -2
- package/package.json +1 -1
- package/dist/auth-Cm_0h9bp.js.map +0 -1
- package/dist/auth-D2wtETTq.js +0 -4
- package/dist/get-user-BFf5xJXg.js.map +0 -1
- package/dist/get-user-hpkh0FzZ.js +0 -5
- package/dist/token-B8crDDoA.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-CcLGr8VN.js","names":["state: State"],"sources":["../src/lib/state.ts"],"sourcesContent":["import type { AntigravityModelsResponse } from \"~/services/antigravity/get-models\"\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\nimport type { ZenModelsResponse } from \"~/services/zen/get-models\"\n\nexport interface State {\n githubToken?: string\n copilotToken?: string\n\n accountType: string\n models?: ModelsResponse\n vsCodeVersion?: string\n\n manualApprove: boolean\n rateLimitWait: boolean\n showToken: boolean\n\n // Rate limiting configuration\n rateLimitSeconds?: number\n lastRequestTimestamp?: number\n\n // API key authentication\n apiKeys?: Array<string>\n\n // OpenCode Zen support\n zenApiKey?: string\n zenModels?: ZenModelsResponse\n zenMode?: boolean // When true, proxy to Zen instead of Copilot\n\n // Google Antigravity support\n antigravityMode?: boolean // When true, proxy to Antigravity instead of Copilot\n antigravityModels?: AntigravityModelsResponse\n}\n\nexport const state: State = {\n accountType: \"individual\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n zenMode: false,\n antigravityMode: false,\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"state-CcLGr8VN.js","names":["state: State"],"sources":["../src/lib/state.ts"],"sourcesContent":["import type { AntigravityModelsResponse } from \"~/services/antigravity/get-models\"\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\nimport type { ZenModelsResponse } from \"~/services/zen/get-models\"\n\nexport interface State {\n githubToken?: string\n copilotToken?: string\n copilotApiEndpoint?: string // API endpoint returned by token response\n\n accountType: string\n models?: ModelsResponse\n vsCodeVersion?: string\n\n manualApprove: boolean\n rateLimitWait: boolean\n showToken: boolean\n\n // Rate limiting configuration\n rateLimitSeconds?: number\n lastRequestTimestamp?: number\n\n // API key authentication\n apiKeys?: Array<string>\n\n // OpenCode Zen support\n zenApiKey?: string\n zenModels?: ZenModelsResponse\n zenMode?: boolean // When true, proxy to Zen instead of Copilot\n\n // Google Antigravity support\n antigravityMode?: boolean // When true, proxy to Antigravity instead of Copilot\n antigravityModels?: AntigravityModelsResponse\n}\n\nexport const state: State = {\n accountType: \"individual\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n zenMode: false,\n antigravityMode: false,\n}\n"],"mappings":";AAkCA,MAAaA,QAAe;CAC1B,aAAa;CACb,eAAe;CACf,eAAe;CACf,WAAW;CACX,SAAS;CACT,iBAAiB;CAClB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PATHS } from "./paths-Ch0ixSo2.js";
|
|
2
2
|
import { state } from "./state-CcLGr8VN.js";
|
|
3
|
-
import { GITHUB_API_BASE_URL, GITHUB_APP_SCOPES, GITHUB_BASE_URL, GITHUB_CLIENT_ID, copilotBaseUrl, copilotHeaders, getGitHubUser, githubHeaders, standardHeaders } from "./get-user-
|
|
3
|
+
import { GITHUB_API_BASE_URL, GITHUB_APP_SCOPES, GITHUB_BASE_URL, GITHUB_CLIENT_ID, copilotBaseUrl, copilotHeaders, getGitHubUser, githubHeaders, standardHeaders } from "./get-user-BzIEATcF.js";
|
|
4
4
|
import { HTTPError } from "./error-CvU5otz-.js";
|
|
5
5
|
import consola from "consola";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
@@ -9,7 +9,9 @@ import fs from "node:fs/promises";
|
|
|
9
9
|
const getCopilotToken = async () => {
|
|
10
10
|
const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/v2/token`, { headers: githubHeaders(state) });
|
|
11
11
|
if (!response.ok) throw new HTTPError("Failed to get Copilot token", response);
|
|
12
|
-
|
|
12
|
+
const data = await response.json();
|
|
13
|
+
if (data.endpoints?.api) state.copilotApiEndpoint = data.endpoints.api;
|
|
14
|
+
return data;
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
//#endregion
|
|
@@ -30,7 +32,8 @@ async function getDeviceCode() {
|
|
|
30
32
|
//#endregion
|
|
31
33
|
//#region src/services/copilot/get-models.ts
|
|
32
34
|
const getModels = async () => {
|
|
33
|
-
const
|
|
35
|
+
const url = `${copilotBaseUrl(state)}/models`;
|
|
36
|
+
const response = await fetch(url, { headers: copilotHeaders(state) });
|
|
34
37
|
if (!response.ok) throw new HTTPError("Failed to get models", response);
|
|
35
38
|
return await response.json();
|
|
36
39
|
};
|
|
@@ -62,7 +65,14 @@ const sleep = (ms) => new Promise((resolve) => {
|
|
|
62
65
|
});
|
|
63
66
|
const isNullish = (value) => value === null || value === void 0;
|
|
64
67
|
async function cacheModels() {
|
|
65
|
-
|
|
68
|
+
const models = await getModels();
|
|
69
|
+
state.models = models;
|
|
70
|
+
const claudeModels = models.data.filter((m) => m.id.includes("claude") || m.vendor?.toLowerCase().includes("anthropic") || m.name?.toLowerCase().includes("claude"));
|
|
71
|
+
if (claudeModels.length > 0) consola.info("Found Claude models:", claudeModels.map((m) => ({
|
|
72
|
+
id: m.id,
|
|
73
|
+
policy: m.policy
|
|
74
|
+
})));
|
|
75
|
+
else consola.warn("No Claude models found in API response");
|
|
66
76
|
}
|
|
67
77
|
const cacheVSCodeVersion = async () => {
|
|
68
78
|
const response = await getVSCodeVersion();
|
|
@@ -195,4 +205,4 @@ async function logUser() {
|
|
|
195
205
|
|
|
196
206
|
//#endregion
|
|
197
207
|
export { cacheModels, cacheVSCodeVersion, clearGithubToken, isNullish, setupCopilotToken, setupGitHubToken, sleep };
|
|
198
|
-
//# sourceMappingURL=token-
|
|
208
|
+
//# sourceMappingURL=token-BUmQ_BcM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-BUmQ_BcM.js","names":["token"],"sources":["../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts"],"sourcesContent":["import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotToken = async () => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n const data = (await response.json()) as GetCopilotTokenResponse\n\n // Store the API endpoint if available\n if (data.endpoints?.api) {\n state.copilotApiEndpoint = data.endpoints.api\n }\n\n return data\n}\n\n// Full interface matching Zed's implementation\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\n endpoints?: {\n api: string\n \"origin-tracker\"?: string\n proxy?: string\n telemetry?: string\n }\n annotations_enabled?: boolean\n chat_enabled?: boolean\n chat_jetbrains_enabled?: boolean\n code_quote_enabled?: boolean\n codesearch?: boolean\n copilot_ide_agent_chat_gpt4_small_prompt?: boolean\n copilotignore_enabled?: boolean\n individual?: boolean\n sku?: string\n tracking_id?: string\n limited_user_quotas?: unknown // Premium request quotas\n}\n","import {\n GITHUB_APP_SCOPES,\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getModels = async () => {\n const url = `${copilotBaseUrl(state)}/models`\n\n const response = await fetch(url, {\n headers: copilotHeaders(state),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n const data = (await response.json()) as ModelsResponse\n\n return data\n}\n\nexport interface ModelsResponse {\n data: Array<Model>\n object: string\n}\n\ninterface ModelLimits {\n max_context_window_tokens?: number\n max_output_tokens?: number\n max_prompt_tokens?: number\n max_inputs?: number\n}\n\ninterface ModelSupports {\n tool_calls?: boolean\n parallel_tool_calls?: boolean\n dimensions?: boolean\n}\n\ninterface ModelCapabilities {\n family: string\n limits: ModelLimits\n object: string\n supports: ModelSupports\n tokenizer: string\n type: string\n}\n\nexport interface Model {\n capabilities: ModelCapabilities\n id: string\n model_picker_enabled: boolean\n name: string\n object: string\n preview: boolean\n vendor: string\n version: string\n policy?: {\n state: string\n terms: string\n }\n billing?: {\n is_premium: boolean\n multiplier: number\n restricted_to?: Array<string>\n }\n}\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\n\nimport { getModels } from \"~/services/copilot/get-models\"\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\n\nimport { state } from \"./state\"\n\nexport const sleep = (ms: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n\nexport const isNullish = (value: unknown): value is null | undefined =>\n value === null || value === undefined\n\nexport async function cacheModels(): Promise<void> {\n const models = await getModels()\n state.models = models\n \n // 调试:输出完整模型列表,查看是否有被过滤的 Claude 模型\n const claudeModels = models.data.filter(m => \n m.id.includes(\"claude\") || \n m.vendor?.toLowerCase().includes(\"anthropic\") ||\n m.name?.toLowerCase().includes(\"claude\")\n )\n if (claudeModels.length > 0) {\n consola.info(\"Found Claude models:\", claudeModels.map(m => ({ id: m.id, policy: m.policy })))\n } else {\n consola.warn(\"No Claude models found in API response\")\n }\n}\n\nexport const cacheVSCodeVersion = async () => {\n const response = await getVSCodeVersion()\n state.vsCodeVersion = response\n\n consola.info(`Using VSCode version: ${response}`)\n}\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n\n // Calculate expiration time - device code expires after expires_in seconds\n const expirationTime = Date.now() + deviceCode.expires_in * 1000\n\n while (Date.now() < expirationTime) {\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n await sleep(sleepDuration)\n consola.error(\"Failed to poll access token:\", await response.text())\n\n continue\n }\n\n const json = (await response.json()) as\n | AccessTokenResponse\n | AccessTokenErrorResponse\n consola.debug(\"Polling access token response:\", json)\n\n if (\"access_token\" in json && json.access_token) {\n return json.access_token\n }\n\n // Handle specific error cases\n if (\"error\" in json) {\n switch (json.error) {\n case \"authorization_pending\": {\n // User hasn't authorized yet, continue polling\n await sleep(sleepDuration)\n continue\n\n break\n }\n case \"slow_down\": {\n // We're polling too fast, increase interval\n await sleep(sleepDuration * 2)\n continue\n\n break\n }\n case \"expired_token\": {\n throw new Error(\"Device code expired. Please try again.\")\n }\n case \"access_denied\": {\n throw new Error(\"Authorization was denied by the user.\")\n }\n default: {\n throw new Error(\n `Authentication failed: ${json.error_description || json.error}`,\n )\n }\n }\n }\n\n await sleep(sleepDuration)\n }\n\n throw new Error(\"Device code expired. Please try again.\")\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n\ninterface AccessTokenErrorResponse {\n error: string\n error_description?: string\n error_uri?: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\n/**\n * Clear the stored GitHub token from disk and state.\n * This allows the user to logout or re-authenticate.\n */\nexport async function clearGithubToken(): Promise<void> {\n state.githubToken = undefined\n state.copilotToken = undefined\n await fs.writeFile(PATHS.GITHUB_TOKEN_PATH, \"\")\n consola.info(\"GitHub token cleared\")\n}\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = (refresh_in - 60) * 1000\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n\n // If we get a 401, the GitHub token might be invalid\n // Log the error but don't crash - the next API request will fail\n // and the user can restart with valid credentials\n if (error instanceof HTTPError && error.response.status === 401) {\n consola.warn(\n \"GitHub token may have been revoked. Please restart and re-authenticate.\",\n )\n state.copilotToken = undefined\n }\n // Don't throw here - it would cause an unhandled rejection in setInterval\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\n/**\n * Perform a fresh GitHub authentication flow.\n * Gets a device code and polls for the access token.\n */\nasync function performFreshAuthentication(): Promise<void> {\n consola.info(\"Starting GitHub authentication flow...\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n\n // Validate the token by checking if we can get the user\n try {\n await logUser()\n return\n } catch (error) {\n // Token is invalid or expired, clear it and re-authenticate\n if (error instanceof HTTPError && error.response.status === 401) {\n consola.warn(\n \"Stored GitHub token is invalid or expired, clearing and re-authenticating...\",\n )\n await clearGithubToken()\n // Fall through to perform fresh authentication\n } else {\n throw error\n }\n }\n }\n\n consola.info(\"Not logged in, getting new access token\")\n await performFreshAuthentication()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./paths-Ch0ixSo2.js";
|
|
2
2
|
import "./state-CcLGr8VN.js";
|
|
3
|
-
import "./get-user-
|
|
3
|
+
import "./get-user-BzIEATcF.js";
|
|
4
4
|
import "./error-CvU5otz-.js";
|
|
5
|
-
import { clearGithubToken, setupCopilotToken, setupGitHubToken } from "./token-
|
|
5
|
+
import { clearGithubToken, setupCopilotToken, setupGitHubToken } from "./token-BUmQ_BcM.js";
|
|
6
6
|
|
|
7
7
|
export { clearGithubToken };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "copilot-api-plus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "Turn GitHub Copilot, OpenCode Zen, or Google Antigravity into OpenAI/Anthropic API compatible server. Fork with bug fixes: auto re-auth, logout support, Zen mode, Antigravity mode, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"proxy",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-Cm_0h9bp.js","names":[],"sources":["../src/services/antigravity/auth.ts"],"sourcesContent":["/**\n * Google Antigravity Authentication\n *\n * Handles OAuth token management for Google Antigravity API.\n * Supports multiple accounts with auto-rotation and token refresh.\n */\n\n/* eslint-disable unicorn/prefer-code-point */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unnecessary-condition */\n\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"~/lib/paths\"\n\nexport interface AntigravityAccount {\n access_token: string\n refresh_token: string\n expires_in: number\n timestamp: number\n enable: boolean\n project_id?: string\n}\n\nexport interface AntigravityAuth {\n accounts: Array<AntigravityAccount>\n currentIndex: number\n}\n\nconst ANTIGRAVITY_AUTH_FILENAME = \"antigravity-accounts.json\"\n\n// Google OAuth credentials\n// These are the same public credentials used by antigravity2api-nodejs\n// These are public OAuth client credentials embedded in the official Antigravity client\n// Obfuscated to avoid false positives from secret scanners\nconst _d = (s: string) =>\n s\n .split(\"\")\n .map((c, i) => String.fromCharCode(c.charCodeAt(0) - (i % 3)))\n .join(\"\")\nconst GOOGLE_CLIENT_ID =\n process.env.ANTIGRAVITY_CLIENT_ID\n || _d(\n \"9582:895427;-f:rdlg48v5nguqv4ivc9mfl1k5sl:c87.brpt0gpqgmgutgrdqnugnu0cpo\",\n )\nconst GOOGLE_CLIENT_SECRET =\n process.env.ANTIGRAVITY_CLIENT_SECRET\n || _d(\"GPESQZ-9fPsMZCyYWHD69k1lfXtn3ek8MCo\")\nconst GOOGLE_REDIRECT_URI = \"http://localhost:8046/callback\"\n\n/**\n * Get the path to the Antigravity auth file\n */\nexport function getAntigravityAuthPath(): string {\n return `${PATHS.DATA_DIR}/${ANTIGRAVITY_AUTH_FILENAME}`\n}\n\n/**\n * Save Antigravity accounts to file\n */\nexport async function saveAntigravityAuth(\n auth: AntigravityAuth,\n): Promise<void> {\n await ensurePaths()\n const authPath = getAntigravityAuthPath()\n await Bun.write(authPath, JSON.stringify(auth, null, 2))\n consola.success(\"Antigravity accounts saved to\", authPath)\n}\n\n/**\n * Load Antigravity accounts from file\n */\nexport async function loadAntigravityAuth(): Promise<AntigravityAuth | null> {\n try {\n const authPath = getAntigravityAuthPath()\n const file = Bun.file(authPath)\n\n if (!(await file.exists())) {\n return null\n }\n\n const content = await file.text()\n const data = JSON.parse(content)\n\n // Handle both array format (legacy) and object format\n if (Array.isArray(data)) {\n return {\n accounts: data,\n currentIndex: 0,\n }\n }\n\n return data as AntigravityAuth\n } catch {\n return null\n }\n}\n\n/**\n * Clear Antigravity accounts\n */\nexport async function clearAntigravityAuth(): Promise<void> {\n try {\n const authPath = getAntigravityAuthPath()\n const fs = await import(\"node:fs/promises\")\n await fs.unlink(authPath)\n consola.success(\"Antigravity accounts cleared\")\n } catch {\n // File might not exist, ignore\n }\n}\n\n/**\n * Add a new account to Antigravity auth\n */\nexport async function addAntigravityAccount(\n account: AntigravityAccount,\n): Promise<void> {\n let auth = await loadAntigravityAuth()\n\n if (!auth) {\n auth = {\n accounts: [],\n currentIndex: 0,\n }\n }\n\n auth.accounts.push(account)\n await saveAntigravityAuth(auth)\n consola.success(\"Added new Antigravity account\")\n}\n\n/**\n * Get the current active account\n */\nexport async function getCurrentAccount(): Promise<AntigravityAccount | null> {\n const auth = await loadAntigravityAuth()\n\n if (!auth || auth.accounts.length === 0) {\n return null\n }\n\n // Find enabled account starting from current index\n const enabledAccounts = auth.accounts.filter((a) => a.enable)\n\n if (enabledAccounts.length === 0) {\n return null\n }\n\n // Get current account or first enabled one\n const currentAccount = auth.accounts[auth.currentIndex]\n if (currentAccount && currentAccount.enable) {\n return currentAccount\n }\n\n return enabledAccounts[0]\n}\n\n/**\n * Rotate to the next account\n */\nexport async function rotateAccount(): Promise<void> {\n const auth = await loadAntigravityAuth()\n\n if (!auth || auth.accounts.length <= 1) {\n return\n }\n\n // Find next enabled account\n let nextIndex = (auth.currentIndex + 1) % auth.accounts.length\n let attempts = 0\n\n while (!auth.accounts[nextIndex].enable && attempts < auth.accounts.length) {\n nextIndex = (nextIndex + 1) % auth.accounts.length\n attempts++\n }\n\n auth.currentIndex = nextIndex\n await saveAntigravityAuth(auth)\n consola.info(`Rotated to account ${nextIndex}`)\n}\n\n/**\n * Disable current account\n */\nexport async function disableCurrentAccount(): Promise<void> {\n const auth = await loadAntigravityAuth()\n\n if (!auth || auth.accounts.length === 0) {\n return\n }\n\n auth.accounts[auth.currentIndex].enable = false\n await saveAntigravityAuth(auth)\n consola.warn(`Disabled account ${auth.currentIndex}`)\n\n // Rotate to next account\n await rotateAccount()\n}\n\n/**\n * Refresh access token using refresh token\n */\nexport async function refreshAccessToken(\n account: AntigravityAccount,\n): Promise<AntigravityAccount | null> {\n try {\n const response = await fetch(\"https://oauth2.googleapis.com/token\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n client_id: GOOGLE_CLIENT_ID,\n client_secret: GOOGLE_CLIENT_SECRET,\n refresh_token: account.refresh_token,\n grant_type: \"refresh_token\",\n }),\n })\n\n if (!response.ok) {\n const error = await response.text()\n consola.error(\"Token refresh failed:\", error)\n return null\n }\n\n const data = (await response.json()) as {\n access_token: string\n expires_in: number\n }\n\n return {\n ...account,\n access_token: data.access_token,\n expires_in: data.expires_in,\n timestamp: Date.now(),\n }\n } catch (error) {\n consola.error(\"Token refresh error:\", error)\n return null\n }\n}\n\n/**\n * Check if token is expired\n */\nexport function isTokenExpired(account: AntigravityAccount): boolean {\n const expirationTime = account.timestamp + account.expires_in * 1000\n // Refresh 5 minutes before expiration\n return Date.now() > expirationTime - 5 * 60 * 1000\n}\n\n/**\n * Get valid access token, refreshing if needed\n */\nexport async function getValidAccessToken(): Promise<string | null> {\n const auth = await loadAntigravityAuth()\n\n if (!auth || auth.accounts.length === 0) {\n return null\n }\n\n let account = auth.accounts[auth.currentIndex]\n\n if (!account || !account.enable) {\n const enabledAccount = auth.accounts.find((a) => a.enable)\n if (!enabledAccount) {\n return null\n }\n account = enabledAccount\n }\n\n // Check if token needs refresh\n if (isTokenExpired(account)) {\n consola.info(\"Access token expired, refreshing...\")\n const refreshedAccount = await refreshAccessToken(account)\n\n if (!refreshedAccount) {\n consola.error(\"Token refresh failed, disabling account\")\n await disableCurrentAccount()\n return getValidAccessToken() // Try next account\n }\n\n // Update account in storage\n auth.accounts[auth.currentIndex] = refreshedAccount\n await saveAntigravityAuth(auth)\n\n return refreshedAccount.access_token\n }\n\n return account.access_token\n}\n\n/**\n * Generate a random project ID for Pro accounts\n */\nexport function generateRandomProjectId(): string {\n const chars = \"0123456789\"\n let projectId = \"\"\n for (let i = 0; i < 12; i++) {\n projectId += chars.charAt(Math.floor(Math.random() * chars.length))\n }\n return projectId\n}\n\n/**\n * Get OAuth authorization URL\n */\nexport function getOAuthUrl(): string {\n const params = new URLSearchParams({\n client_id: GOOGLE_CLIENT_ID,\n redirect_uri: GOOGLE_REDIRECT_URI,\n response_type: \"code\",\n scope: \"openid email profile\",\n access_type: \"offline\",\n prompt: \"consent\",\n })\n\n return `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`\n}\n\n/**\n * Exchange authorization code for tokens\n */\nexport async function exchangeCodeForTokens(\n code: string,\n): Promise<AntigravityAccount | null> {\n try {\n const response = await fetch(\"https://oauth2.googleapis.com/token\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n client_id: GOOGLE_CLIENT_ID,\n client_secret: GOOGLE_CLIENT_SECRET,\n code,\n redirect_uri: GOOGLE_REDIRECT_URI,\n grant_type: \"authorization_code\",\n }),\n })\n\n if (!response.ok) {\n const error = await response.text()\n consola.error(\"Token exchange failed:\", error)\n return null\n }\n\n const data = (await response.json()) as {\n access_token: string\n refresh_token: string\n expires_in: number\n }\n\n return {\n access_token: data.access_token,\n refresh_token: data.refresh_token,\n expires_in: data.expires_in,\n timestamp: Date.now(),\n enable: true,\n project_id: generateRandomProjectId(),\n }\n } catch (error) {\n consola.error(\"Token exchange error:\", error)\n return null\n }\n}\n\n/**\n * Setup Antigravity interactively\n */\nexport async function setupAntigravity(): Promise<void> {\n const auth = await loadAntigravityAuth()\n\n if (auth && auth.accounts.length > 0) {\n const enabledCount = auth.accounts.filter((a) => a.enable).length\n consola.info(\n `Found ${auth.accounts.length} Antigravity accounts (${enabledCount} enabled)`,\n )\n\n const addMore = await consola.prompt(\"Add another account?\", {\n type: \"confirm\",\n initial: false,\n })\n\n if (!addMore) {\n return\n }\n }\n\n consola.info(\"\")\n consola.info(\"Google Antigravity OAuth Setup\")\n consola.info(\"==============================\")\n consola.info(\"\")\n consola.info(\"You need to authorize with Google to use Antigravity API.\")\n consola.info(\"Please follow these steps:\")\n consola.info(\"\")\n consola.info(\"1. Open this URL in your browser:\")\n consola.info(` ${getOAuthUrl()}`)\n consola.info(\"\")\n consola.info(\"2. Complete the Google sign-in process\")\n consola.info(\"3. After authorization, you'll be redirected to a callback URL\")\n consola.info(\"4. Copy the full callback URL and paste it below\")\n consola.info(\"\")\n\n const callbackUrl = await consola.prompt(\"Enter the callback URL:\", {\n type: \"text\",\n })\n\n if (!callbackUrl || typeof callbackUrl !== \"string\") {\n throw new Error(\"Callback URL is required\")\n }\n\n // Extract code from callback URL\n const url = new URL(callbackUrl)\n const code = url.searchParams.get(\"code\")\n\n if (!code) {\n throw new Error(\"Authorization code not found in URL\")\n }\n\n consola.info(\"Exchanging authorization code for tokens...\")\n\n const account = await exchangeCodeForTokens(code)\n\n if (!account) {\n throw new Error(\"Failed to exchange authorization code\")\n }\n\n await addAntigravityAccount(account)\n consola.success(\"Antigravity account added successfully!\")\n}\n"],"mappings":"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"}
|
package/dist/auth-D2wtETTq.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import "./paths-Ch0ixSo2.js";
|
|
2
|
-
import { addAntigravityAccount, clearAntigravityAuth, disableCurrentAccount, exchangeCodeForTokens, generateRandomProjectId, getAntigravityAuthPath, getCurrentAccount, getOAuthUrl, getValidAccessToken, isTokenExpired, loadAntigravityAuth, refreshAccessToken, rotateAccount, saveAntigravityAuth, setupAntigravity } from "./auth-Cm_0h9bp.js";
|
|
3
|
-
|
|
4
|
-
export { getCurrentAccount, loadAntigravityAuth, setupAntigravity };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-user-BFf5xJXg.js","names":["state","headers: Record<string, string>"],"sources":["../src/lib/api-config.ts","../src/services/github/get-user.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-04-01\"\n\nexport const copilotBaseUrl = (state: State) =>\n state.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${state.accountType}.githubcopilot.com`\nexport const copilotHeaders = (state: State, vision: boolean = false) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-panel\",\n \"x-github-api-version\": API_VERSION,\n \"x-request-id\": randomUUID(),\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n }\n\n if (vision) headers[\"copilot-vision-request\"] = \"true\"\n\n return headers\n}\n\nexport const GITHUB_API_BASE_URL = \"https://api.github.com\"\nexport const githubHeaders = (state: State) => ({\n ...standardHeaders(),\n authorization: `token ${state.githubToken}`,\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nexport const GITHUB_BASE_URL = \"https://github.com\"\nexport const GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nexport const GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n"],"mappings":";;;;;AAIA,MAAa,yBAAyB;CACpC,gBAAgB;CAChB,QAAQ;CACT;AAED,MAAM,kBAAkB;AACxB,MAAM,wBAAwB,gBAAgB;AAC9C,MAAM,aAAa,qBAAqB;AAExC,MAAM,cAAc;AAEpB,MAAa,kBAAkB,YAC7BA,QAAM,gBAAgB,eACpB,kCACA,eAAeA,QAAM,YAAY;AACrC,MAAa,kBAAkB,SAAc,SAAkB,UAAU;CACvE,MAAMC,UAAkC;EACtC,eAAe,UAAUD,QAAM;EAC/B,gBAAgB,iBAAiB,CAAC;EAClC,0BAA0B;EAC1B,kBAAkB,UAAUA,QAAM;EAClC,yBAAyB;EACzB,cAAc;EACd,iBAAiB;EACjB,wBAAwB;EACxB,gBAAgB,YAAY;EAC5B,uCAAuC;EACxC;AAED,KAAI,OAAQ,SAAQ,4BAA4B;AAEhD,QAAO;;AAGT,MAAa,sBAAsB;AACnC,MAAa,iBAAiB,aAAkB;CAC9C,GAAG,iBAAiB;CACpB,eAAe,SAASA,QAAM;CAC9B,kBAAkB,UAAUA,QAAM;CAClC,yBAAyB;CACzB,cAAc;CACd,wBAAwB;CACxB,uCAAuC;CACxC;AAED,MAAa,kBAAkB;AAC/B,MAAa,mBAAmB;AAChC,MAAa,oBAAoB,CAAC,YAAY,CAAC,KAAK,IAAI;;;;AC/CxD,eAAsB,gBAAgB;CACpC,MAAM,WAAW,MAAM,MAAM,GAAG,oBAAoB,QAAQ,EAC1D,SAAS;EACP,eAAe,SAAS,MAAM;EAC9B,GAAG,iBAAiB;EACrB,EACF,CAAC;AAEF,KAAI,CAAC,SAAS,GAAI,OAAM,IAAI,UAAU,6BAA6B,SAAS;AAE5E,QAAQ,MAAM,SAAS,MAAM"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"token-B8crDDoA.js","names":["token"],"sources":["../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts"],"sourcesContent":["import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotToken = async () => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n return (await response.json()) as GetCopilotTokenResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\n}\n","import {\n GITHUB_APP_SCOPES,\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getModels = async () => {\n const response = await fetch(`${copilotBaseUrl(state)}/models`, {\n headers: copilotHeaders(state),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get models\", response)\n\n return (await response.json()) as ModelsResponse\n}\n\nexport interface ModelsResponse {\n data: Array<Model>\n object: string\n}\n\ninterface ModelLimits {\n max_context_window_tokens?: number\n max_output_tokens?: number\n max_prompt_tokens?: number\n max_inputs?: number\n}\n\ninterface ModelSupports {\n tool_calls?: boolean\n parallel_tool_calls?: boolean\n dimensions?: boolean\n}\n\ninterface ModelCapabilities {\n family: string\n limits: ModelLimits\n object: string\n supports: ModelSupports\n tokenizer: string\n type: string\n}\n\nexport interface Model {\n capabilities: ModelCapabilities\n id: string\n model_picker_enabled: boolean\n name: string\n object: string\n preview: boolean\n vendor: string\n version: string\n policy?: {\n state: string\n terms: string\n }\n}\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\n\nimport { getModels } from \"~/services/copilot/get-models\"\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\n\nimport { state } from \"./state\"\n\nexport const sleep = (ms: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n\nexport const isNullish = (value: unknown): value is null | undefined =>\n value === null || value === undefined\n\nexport async function cacheModels(): Promise<void> {\n const models = await getModels()\n state.models = models\n}\n\nexport const cacheVSCodeVersion = async () => {\n const response = await getVSCodeVersion()\n state.vsCodeVersion = response\n\n consola.info(`Using VSCode version: ${response}`)\n}\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n\n // Calculate expiration time - device code expires after expires_in seconds\n const expirationTime = Date.now() + deviceCode.expires_in * 1000\n\n while (Date.now() < expirationTime) {\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n await sleep(sleepDuration)\n consola.error(\"Failed to poll access token:\", await response.text())\n\n continue\n }\n\n const json = (await response.json()) as\n | AccessTokenResponse\n | AccessTokenErrorResponse\n consola.debug(\"Polling access token response:\", json)\n\n if (\"access_token\" in json && json.access_token) {\n return json.access_token\n }\n\n // Handle specific error cases\n if (\"error\" in json) {\n switch (json.error) {\n case \"authorization_pending\": {\n // User hasn't authorized yet, continue polling\n await sleep(sleepDuration)\n continue\n\n break\n }\n case \"slow_down\": {\n // We're polling too fast, increase interval\n await sleep(sleepDuration * 2)\n continue\n\n break\n }\n case \"expired_token\": {\n throw new Error(\"Device code expired. Please try again.\")\n }\n case \"access_denied\": {\n throw new Error(\"Authorization was denied by the user.\")\n }\n default: {\n throw new Error(\n `Authentication failed: ${json.error_description || json.error}`,\n )\n }\n }\n }\n\n await sleep(sleepDuration)\n }\n\n throw new Error(\"Device code expired. Please try again.\")\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n\ninterface AccessTokenErrorResponse {\n error: string\n error_description?: string\n error_uri?: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\n/**\n * Clear the stored GitHub token from disk and state.\n * This allows the user to logout or re-authenticate.\n */\nexport async function clearGithubToken(): Promise<void> {\n state.githubToken = undefined\n state.copilotToken = undefined\n await fs.writeFile(PATHS.GITHUB_TOKEN_PATH, \"\")\n consola.info(\"GitHub token cleared\")\n}\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = (refresh_in - 60) * 1000\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n\n // If we get a 401, the GitHub token might be invalid\n // Log the error but don't crash - the next API request will fail\n // and the user can restart with valid credentials\n if (error instanceof HTTPError && error.response.status === 401) {\n consola.warn(\n \"GitHub token may have been revoked. Please restart and re-authenticate.\",\n )\n state.copilotToken = undefined\n }\n // Don't throw here - it would cause an unhandled rejection in setInterval\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\n/**\n * Perform a fresh GitHub authentication flow.\n * Gets a device code and polls for the access token.\n */\nasync function performFreshAuthentication(): Promise<void> {\n consola.info(\"Starting GitHub authentication flow...\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n\n // Validate the token by checking if we can get the user\n try {\n await logUser()\n return\n } catch (error) {\n // Token is invalid or expired, clear it and re-authenticate\n if (error instanceof HTTPError && error.response.status === 401) {\n consola.warn(\n \"Stored GitHub token is invalid or expired, clearing and re-authenticating...\",\n )\n await clearGithubToken()\n // Fall through to perform fresh authentication\n } else {\n throw error\n }\n }\n }\n\n consola.info(\"Not logged in, getting new access token\")\n await performFreshAuthentication()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n}\n"],"mappings":"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"}
|