copilot-api-plus 1.0.8 → 1.0.10
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 +482 -507
- package/dist/{auth-KlL1W4gV.js → auth-BO-mwvoU.js} +1 -1
- package/dist/auth-Cm_0h9bp.js +268 -0
- package/dist/auth-Cm_0h9bp.js.map +1 -0
- package/dist/{auth-C5zV8JbW.js → auth-Cua-c0dq.js} +1 -1
- package/dist/auth-Cua-c0dq.js.map +1 -0
- package/dist/auth-D2wtETTq.js +4 -0
- package/dist/get-models-Bbb8B5jI.js +218 -0
- package/dist/get-models-Bbb8B5jI.js.map +1 -0
- package/dist/{get-models-Hlxa1hWY.js → get-models-DJfPj_Rg.js} +2 -2
- package/dist/get-models-DJfPj_Rg.js.map +1 -0
- package/dist/get-models-Dq2ZDU9m.js +5 -0
- package/dist/{get-user-DgPgvnrS.js → get-user-BFf5xJXg.js} +2 -2
- package/dist/{get-user-DgPgvnrS.js.map → get-user-BFf5xJXg.js.map} +1 -1
- package/dist/get-user-hpkh0FzZ.js +5 -0
- package/dist/main.js +1021 -33
- package/dist/main.js.map +1 -1
- package/dist/{state-DAw5jMjc.js → state-CcLGr8VN.js} +3 -2
- package/dist/state-CcLGr8VN.js.map +1 -0
- package/dist/{token-DYeOMeid.js → token-B8crDDoA.js} +14 -12
- package/dist/token-B8crDDoA.js.map +1 -0
- package/dist/{token-BssxOyqn.js → token-DS09XjQ5.js} +3 -3
- package/package.json +4 -2
- package/dist/auth-C5zV8JbW.js.map +0 -1
- package/dist/get-models-Hlxa1hWY.js.map +0 -1
- package/dist/get-user-M3sQS0U8.js +0 -5
- package/dist/state-DAw5jMjc.js.map +0 -1
- package/dist/token-DYeOMeid.js.map +0 -1
|
@@ -4,9 +4,10 @@ const state = {
|
|
|
4
4
|
manualApprove: false,
|
|
5
5
|
rateLimitWait: false,
|
|
6
6
|
showToken: false,
|
|
7
|
-
zenMode: false
|
|
7
|
+
zenMode: false,
|
|
8
|
+
antigravityMode: false
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
//#endregion
|
|
11
12
|
export { state };
|
|
12
|
-
//# sourceMappingURL=state-
|
|
13
|
+
//# sourceMappingURL=state-CcLGr8VN.js.map
|
|
@@ -0,0 +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":";AAiCA,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
|
-
import { state } from "./state-
|
|
3
|
-
import { GITHUB_API_BASE_URL, GITHUB_APP_SCOPES, GITHUB_BASE_URL, GITHUB_CLIENT_ID, copilotBaseUrl, copilotHeaders, getGitHubUser, githubHeaders, standardHeaders } from "./get-user-
|
|
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-BFf5xJXg.js";
|
|
4
4
|
import { HTTPError } from "./error-CvU5otz-.js";
|
|
5
5
|
import consola from "consola";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
@@ -94,15 +94,17 @@ async function pollAccessToken(deviceCode) {
|
|
|
94
94
|
const json = await response.json();
|
|
95
95
|
consola.debug("Polling access token response:", json);
|
|
96
96
|
if ("access_token" in json && json.access_token) return json.access_token;
|
|
97
|
-
if ("error" in json)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
if ("error" in json) switch (json.error) {
|
|
98
|
+
case "authorization_pending":
|
|
99
|
+
await sleep(sleepDuration);
|
|
100
|
+
continue;
|
|
101
|
+
case "slow_down":
|
|
102
|
+
await sleep(sleepDuration * 2);
|
|
103
|
+
continue;
|
|
104
|
+
case "expired_token": throw new Error("Device code expired. Please try again.");
|
|
105
|
+
case "access_denied": throw new Error("Authorization was denied by the user.");
|
|
106
|
+
default: throw new Error(`Authentication failed: ${json.error_description || json.error}`);
|
|
107
|
+
}
|
|
106
108
|
await sleep(sleepDuration);
|
|
107
109
|
}
|
|
108
110
|
throw new Error("Device code expired. Please try again.");
|
|
@@ -193,4 +195,4 @@ async function logUser() {
|
|
|
193
195
|
|
|
194
196
|
//#endregion
|
|
195
197
|
export { cacheModels, cacheVSCodeVersion, clearGithubToken, isNullish, setupCopilotToken, setupGitHubToken, sleep };
|
|
196
|
-
//# sourceMappingURL=token-
|
|
198
|
+
//# sourceMappingURL=token-B8crDDoA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./paths-Ch0ixSo2.js";
|
|
2
|
-
import "./state-
|
|
3
|
-
import "./get-user-
|
|
2
|
+
import "./state-CcLGr8VN.js";
|
|
3
|
+
import "./get-user-BFf5xJXg.js";
|
|
4
4
|
import "./error-CvU5otz-.js";
|
|
5
|
-
import { clearGithubToken, setupCopilotToken, setupGitHubToken } from "./token-
|
|
5
|
+
import { clearGithubToken, setupCopilotToken, setupGitHubToken } from "./token-B8crDDoA.js";
|
|
6
6
|
|
|
7
7
|
export { clearGithubToken };
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "copilot-api-plus",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Turn GitHub Copilot
|
|
3
|
+
"version": "1.0.10",
|
|
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",
|
|
7
7
|
"github-copilot",
|
|
8
8
|
"openai-compatible",
|
|
9
9
|
"anthropic-compatible",
|
|
10
10
|
"opencode-zen",
|
|
11
|
+
"google-antigravity",
|
|
11
12
|
"claude-code"
|
|
12
13
|
],
|
|
13
14
|
"homepage": "https://github.com/imbuxiangnan-cyber/copilot-api-plus",
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"*": "bun run lint --fix"
|
|
44
45
|
},
|
|
45
46
|
"dependencies": {
|
|
47
|
+
"@clack/prompts": "^0.11.0",
|
|
46
48
|
"citty": "^0.1.6",
|
|
47
49
|
"clipboardy": "^5.0.0",
|
|
48
50
|
"consola": "^3.4.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-C5zV8JbW.js","names":[],"sources":["../src/services/zen/auth.ts"],"sourcesContent":["/**\r\n * OpenCode Zen Authentication\r\n *\r\n * Handles API key authentication for OpenCode Zen.\r\n * API keys are created at https://opencode.ai/zen\r\n */\r\n\r\nimport consola from \"consola\"\r\nimport { PATHS, ensurePaths } from \"~/lib/paths\"\r\n\r\nexport interface ZenAuth {\r\n apiKey: string\r\n}\r\n\r\nconst ZEN_AUTH_FILENAME = \"zen-auth.json\"\r\n\r\n/**\r\n * Get the path to the Zen auth file\r\n */\r\nexport function getZenAuthPath(): string {\r\n return `${PATHS.DATA_DIR}/${ZEN_AUTH_FILENAME}`\r\n}\r\n\r\n/**\r\n * Save Zen API key to file\r\n */\r\nexport async function saveZenAuth(auth: ZenAuth): Promise<void> {\r\n await ensurePaths()\r\n const authPath = getZenAuthPath()\r\n await Bun.write(authPath, JSON.stringify(auth, null, 2))\r\n consola.success(\"Zen API key saved to\", authPath)\r\n}\r\n\r\n/**\r\n * Load Zen API key from file\r\n */\r\nexport async function loadZenAuth(): Promise<ZenAuth | null> {\r\n try {\r\n const authPath = getZenAuthPath()\r\n const file = Bun.file(authPath)\r\n\r\n if (!(await file.exists())) {\r\n return null\r\n }\r\n\r\n const content = await file.text()\r\n return JSON.parse(content) as ZenAuth\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\n/**\r\n * Clear Zen API key\r\n */\r\nexport async function clearZenAuth(): Promise<void> {\r\n try {\r\n const authPath = getZenAuthPath()\r\n const fs = await import(\"node:fs/promises\")\r\n await fs.unlink(authPath)\r\n consola.success(\"Zen API key cleared\")\r\n } catch {\r\n // File might not exist, ignore\r\n }\r\n}\r\n\r\n/**\r\n * Setup Zen API key interactively\r\n */\r\nexport async function setupZenApiKey(force = false): Promise<string> {\r\n const existingAuth = await loadZenAuth()\r\n\r\n if (existingAuth && !force) {\r\n consola.info(\"Using existing Zen API key\")\r\n return existingAuth.apiKey\r\n }\r\n\r\n consola.info(\"OpenCode Zen gives you access to all the best coding models\")\r\n consola.info(\"Get your API key at: https://opencode.ai/zen\")\r\n consola.info(\"\")\r\n\r\n const apiKey = await consola.prompt(\"Enter your OpenCode Zen API key:\", {\r\n type: \"text\",\r\n })\r\n\r\n if (!apiKey || typeof apiKey !== \"string\") {\r\n throw new Error(\"API key is required\")\r\n }\r\n\r\n // Validate the API key by fetching models\r\n try {\r\n const response = await fetch(\"https://opencode.ai/zen/v1/models\", {\r\n headers: {\r\n Authorization: `Bearer ${apiKey}`,\r\n },\r\n })\r\n\r\n if (!response.ok) {\r\n throw new Error(`Invalid API key: ${response.status} ${response.statusText}`)\r\n }\r\n\r\n consola.success(\"API key validated successfully\")\r\n } catch (error) {\r\n consola.error(\"Failed to validate API key:\", error)\r\n throw error\r\n }\r\n\r\n await saveZenAuth({ apiKey })\r\n return apiKey\r\n}\r\n"],"mappings":";;;;AAcA,MAAM,oBAAoB;;;;AAK1B,SAAgB,iBAAyB;AACvC,QAAO,GAAG,MAAM,SAAS,GAAG;;;;;AAM9B,eAAsB,YAAY,MAA8B;AAC9D,OAAM,aAAa;CACnB,MAAM,WAAW,gBAAgB;AACjC,OAAM,IAAI,MAAM,UAAU,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AACxD,SAAQ,QAAQ,wBAAwB,SAAS;;;;;AAMnD,eAAsB,cAAuC;AAC3D,KAAI;EACF,MAAM,WAAW,gBAAgB;EACjC,MAAM,OAAO,IAAI,KAAK,SAAS;AAE/B,MAAI,CAAE,MAAM,KAAK,QAAQ,CACvB,QAAO;EAGT,MAAM,UAAU,MAAM,KAAK,MAAM;AACjC,SAAO,KAAK,MAAM,QAAQ;SACpB;AACN,SAAO;;;;;;AAOX,eAAsB,eAA8B;AAClD,KAAI;EACF,MAAM,WAAW,gBAAgB;AAEjC,SADW,MAAM,OAAO,qBACf,OAAO,SAAS;AACzB,UAAQ,QAAQ,sBAAsB;SAChC;;;;;AAQV,eAAsB,eAAe,QAAQ,OAAwB;CACnE,MAAM,eAAe,MAAM,aAAa;AAExC,KAAI,gBAAgB,CAAC,OAAO;AAC1B,UAAQ,KAAK,6BAA6B;AAC1C,SAAO,aAAa;;AAGtB,SAAQ,KAAK,8DAA8D;AAC3E,SAAQ,KAAK,+CAA+C;AAC5D,SAAQ,KAAK,GAAG;CAEhB,MAAM,SAAS,MAAM,QAAQ,OAAO,oCAAoC,EACtE,MAAM,QACP,CAAC;AAEF,KAAI,CAAC,UAAU,OAAO,WAAW,SAC/B,OAAM,IAAI,MAAM,sBAAsB;AAIxC,KAAI;EACF,MAAM,WAAW,MAAM,MAAM,qCAAqC,EAChE,SAAS,EACP,eAAe,UAAU,UAC1B,EACF,CAAC;AAEF,MAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,oBAAoB,SAAS,OAAO,GAAG,SAAS,aAAa;AAG/E,UAAQ,QAAQ,iCAAiC;UAC1C,OAAO;AACd,UAAQ,MAAM,+BAA+B,MAAM;AACnD,QAAM;;AAGR,OAAM,YAAY,EAAE,QAAQ,CAAC;AAC7B,QAAO"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-models-Hlxa1hWY.js","names":[],"sources":["../src/services/zen/get-models.ts"],"sourcesContent":["/**\r\n * OpenCode Zen Models\r\n *\r\n * Fetches available models from OpenCode Zen.\r\n */\r\n\r\nimport consola from \"consola\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport interface ZenModel {\r\n id: string\r\n object: string\r\n created: number\r\n owned_by: string\r\n}\r\n\r\nexport interface ZenModelsResponse {\r\n object: string\r\n data: ZenModel[]\r\n}\r\n\r\n/**\r\n * Fetch available models from OpenCode Zen\r\n */\r\nexport async function getZenModels(): Promise<ZenModelsResponse> {\r\n const apiKey = state.zenApiKey\r\n\r\n if (!apiKey) {\r\n throw new Error(\"Zen API key not configured\")\r\n }\r\n\r\n const response = await fetch(\"https://opencode.ai/zen/v1/models\", {\r\n headers: {\r\n Authorization: `Bearer ${apiKey}`,\r\n },\r\n })\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch Zen models: ${response.status} ${response.statusText}`)\r\n }\r\n\r\n const data = (await response.json()) as ZenModelsResponse\r\n consola.debug(`Fetched ${data.data.length} models from Zen`)\r\n\r\n return data\r\n}\r\n\r\n/**\r\n * Cache Zen models in state\r\n */\r\nexport async function cacheZenModels(): Promise<void> {\r\n try {\r\n const models = await getZenModels()\r\n state.zenModels = models\r\n consola.info(`Loaded ${models.data.length} Zen models`)\r\n } catch (error) {\r\n consola.error(\"Failed to load Zen models:\", error)\r\n throw error\r\n }\r\n}\r\n"],"mappings":";;;;;;;AAwBA,eAAsB,eAA2C;CAC/D,MAAM,SAAS,MAAM;AAErB,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,6BAA6B;CAG/C,MAAM,WAAW,MAAM,MAAM,qCAAqC,EAChE,SAAS,EACP,eAAe,UAAU,UAC1B,EACF,CAAC;AAEF,KAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,+BAA+B,SAAS,OAAO,GAAG,SAAS,aAAa;CAG1F,MAAM,OAAQ,MAAM,SAAS,MAAM;AACnC,SAAQ,MAAM,WAAW,KAAK,KAAK,OAAO,kBAAkB;AAE5D,QAAO;;;;;AAMT,eAAsB,iBAAgC;AACpD,KAAI;EACF,MAAM,SAAS,MAAM,cAAc;AACnC,QAAM,YAAY;AAClB,UAAQ,KAAK,UAAU,OAAO,KAAK,OAAO,aAAa;UAChD,OAAO;AACd,UAAQ,MAAM,8BAA8B,MAAM;AAClD,QAAM"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state-DAw5jMjc.js","names":["state: State"],"sources":["../src/lib/state.ts"],"sourcesContent":["import 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\nexport const state: State = {\n accountType: \"individual\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n zenMode: false,\n}\n"],"mappings":";AA4BA,MAAaA,QAAe;CAC1B,aAAa;CACb,eAAe;CACf,eAAe;CACf,WAAW;CACX,SAAS;CACV"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"token-DYeOMeid.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 AccessTokenResponse | 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 if (json.error === \"authorization_pending\") {\n // User hasn't authorized yet, continue polling\n await sleep(sleepDuration)\n continue\n } else if (json.error === \"slow_down\") {\n // We're polling too fast, increase interval\n await sleep(sleepDuration * 2)\n continue\n } else if (json.error === \"expired_token\") {\n throw new Error(\"Device code expired. Please try again.\")\n } else if (json.error === \"access_denied\") {\n throw new Error(\"Authorization was denied by the user.\")\n } else {\n throw new Error(`Authentication failed: ${json.error_description || json.error}`)\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(\"GitHub token may have been revoked. Please restart and re-authenticate.\")\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(\"Stored GitHub token is invalid or expired, clearing and re-authenticating...\")\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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"}
|