copilot-api-plus 1.0.31 → 1.0.32

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/dist/main.js CHANGED
@@ -1,24 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import { PATHS, ensurePaths } from "./paths-Ch0ixSo2.js";
2
+ import { PATHS, ensurePaths } from "./paths-CVYLp61D.js";
3
3
  import { state } from "./state-CcLGr8VN.js";
4
4
  import { GITHUB_API_BASE_URL, copilotBaseUrl, copilotHeaders, githubHeaders } from "./get-user-BzIEATcF.js";
5
5
  import { HTTPError, forwardError } from "./error-CvU5otz-.js";
6
- import { cacheModels, cacheVSCodeVersion, clearGithubToken, isNullish, setupCopilotToken, setupGitHubToken, sleep } from "./token-BUmQ_BcM.js";
7
- import { clearAntigravityAuth, disableCurrentAccount, getAntigravityAuthPath, getApiKey, getValidAccessToken, rotateAccount } from "./auth-y23hLerx.js";
8
- import { clearZenAuth, getZenAuthPath } from "./auth-OZNLGzjK.js";
9
- import { getAntigravityModels, getAntigravityUsage, isThinkingModel } from "./get-models-B5kAooWg.js";
6
+ import { cacheModels, cacheVSCodeVersion, clearGithubToken, isNullish, setupCopilotToken, setupGitHubToken, sleep } from "./token-ClgudjZm.js";
7
+ import { clearAntigravityAuth, disableCurrentAccount, getAntigravityAuthPath, getApiKey, getValidAccessToken, rotateAccount } from "./auth-CM_ilreU.js";
8
+ import { clearZenAuth, getZenAuthPath } from "./auth-T55-Bhoo.js";
9
+ import { getAntigravityModels, getAntigravityUsage, isThinkingModel } from "./get-models-DMdiCNoU.js";
10
10
  import { createRequire } from "node:module";
11
11
  import { defineCommand, runMain } from "citty";
12
12
  import consola from "consola";
13
13
  import fs from "node:fs/promises";
14
- import os from "node:os";
15
14
  import path from "node:path";
15
+ import os from "node:os";
16
+ import { getProxyForUrl } from "proxy-from-env";
17
+ import { Agent, ProxyAgent, setGlobalDispatcher } from "undici";
16
18
  import * as p from "@clack/prompts";
17
19
  import clipboard from "clipboardy";
18
20
  import { serve } from "srvx";
19
21
  import invariant from "tiny-invariant";
20
- import { getProxyForUrl } from "proxy-from-env";
21
- import { Agent, ProxyAgent, setGlobalDispatcher } from "undici";
22
22
  import { execSync } from "node:child_process";
23
23
  import process$1 from "node:process";
24
24
  import { Hono } from "hono";
@@ -35,951 +35,1076 @@ var __commonJS = (cb, mod) => function() {
35
35
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
36
36
 
37
37
  //#endregion
38
- //#region src/auth.ts
39
- async function runAuth(options$1) {
40
- if (options$1.verbose) {
41
- consola.level = 5;
42
- consola.info("Verbose logging enabled");
43
- }
44
- state.showToken = options$1.showToken;
45
- await ensurePaths();
46
- await setupGitHubToken({ force: true });
47
- consola.success("GitHub token written to", PATHS.GITHUB_TOKEN_PATH);
48
- }
49
- const auth = defineCommand({
50
- meta: {
51
- name: "auth",
52
- description: "Run GitHub auth flow without running the server"
53
- },
54
- args: {
55
- verbose: {
56
- alias: "v",
57
- type: "boolean",
58
- default: false,
59
- description: "Enable verbose logging"
38
+ //#region node_modules/dotenv/package.json
39
+ var require_package = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/package.json": ((exports, module) => {
40
+ module.exports = {
41
+ "name": "dotenv",
42
+ "version": "17.2.3",
43
+ "description": "Loads environment variables from .env file",
44
+ "main": "lib/main.js",
45
+ "types": "lib/main.d.ts",
46
+ "exports": {
47
+ ".": {
48
+ "types": "./lib/main.d.ts",
49
+ "require": "./lib/main.js",
50
+ "default": "./lib/main.js"
51
+ },
52
+ "./config": "./config.js",
53
+ "./config.js": "./config.js",
54
+ "./lib/env-options": "./lib/env-options.js",
55
+ "./lib/env-options.js": "./lib/env-options.js",
56
+ "./lib/cli-options": "./lib/cli-options.js",
57
+ "./lib/cli-options.js": "./lib/cli-options.js",
58
+ "./package.json": "./package.json"
60
59
  },
61
- "show-token": {
62
- type: "boolean",
63
- default: false,
64
- description: "Show GitHub token on auth"
65
- }
66
- },
67
- run({ args }) {
68
- return runAuth({
69
- verbose: args.verbose,
70
- showToken: args["show-token"]
71
- });
72
- }
73
- });
74
-
75
- //#endregion
76
- //#region src/services/github/get-copilot-usage.ts
77
- const getCopilotUsage = async () => {
78
- const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, { headers: githubHeaders(state) });
79
- if (!response.ok) throw new HTTPError("Failed to get Copilot usage", response);
80
- return await response.json();
81
- };
82
-
83
- //#endregion
84
- //#region src/check-usage.ts
85
- const checkUsage = defineCommand({
86
- meta: {
87
- name: "check-usage",
88
- description: "Show current GitHub Copilot usage/quota information"
89
- },
90
- async run() {
91
- await ensurePaths();
92
- await setupGitHubToken();
93
- try {
94
- const usage = await getCopilotUsage();
95
- const premium = usage.quota_snapshots.premium_interactions;
96
- const premiumTotal = premium.entitlement;
97
- const premiumUsed = premiumTotal - premium.remaining;
98
- const premiumPercentUsed = premiumTotal > 0 ? premiumUsed / premiumTotal * 100 : 0;
99
- const premiumPercentRemaining = premium.percent_remaining;
100
- function summarizeQuota(name, snap) {
101
- if (!snap) return `${name}: N/A`;
102
- const total = snap.entitlement;
103
- const used = total - snap.remaining;
104
- const percentUsed = total > 0 ? used / total * 100 : 0;
105
- const percentRemaining = snap.percent_remaining;
106
- return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`;
107
- }
108
- const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`;
109
- const chatLine = summarizeQuota("Chat", usage.quota_snapshots.chat);
110
- const completionsLine = summarizeQuota("Completions", usage.quota_snapshots.completions);
111
- consola.box(`Copilot Usage (plan: ${usage.copilot_plan})\nQuota resets: ${usage.quota_reset_date}\n\nQuotas:\n ${premiumLine}\n ${chatLine}\n ${completionsLine}`);
112
- } catch (err) {
113
- consola.error("Failed to fetch Copilot usage:", err);
114
- process.exit(1);
115
- }
116
- }
117
- });
60
+ "scripts": {
61
+ "dts-check": "tsc --project tests/types/tsconfig.json",
62
+ "lint": "standard",
63
+ "pretest": "npm run lint && npm run dts-check",
64
+ "test": "tap run tests/**/*.js --allow-empty-coverage --disable-coverage --timeout=60000",
65
+ "test:coverage": "tap run tests/**/*.js --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
66
+ "prerelease": "npm test",
67
+ "release": "standard-version"
68
+ },
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "git://github.com/motdotla/dotenv.git"
72
+ },
73
+ "homepage": "https://github.com/motdotla/dotenv#readme",
74
+ "funding": "https://dotenvx.com",
75
+ "keywords": [
76
+ "dotenv",
77
+ "env",
78
+ ".env",
79
+ "environment",
80
+ "variables",
81
+ "config",
82
+ "settings"
83
+ ],
84
+ "readmeFilename": "README.md",
85
+ "license": "BSD-2-Clause",
86
+ "devDependencies": {
87
+ "@types/node": "^18.11.3",
88
+ "decache": "^4.6.2",
89
+ "sinon": "^14.0.1",
90
+ "standard": "^17.0.0",
91
+ "standard-version": "^9.5.0",
92
+ "tap": "^19.2.0",
93
+ "typescript": "^4.8.4"
94
+ },
95
+ "engines": { "node": ">=12" },
96
+ "browser": { "fs": false }
97
+ };
98
+ }) });
118
99
 
119
100
  //#endregion
120
- //#region src/lib/config.ts
121
- const CONFIG_FILENAME = "config.json";
122
- /**
123
- * Get the path to the config file
124
- */
125
- function getConfigPath() {
126
- return path.join(PATHS.DATA_DIR, CONFIG_FILENAME);
127
- }
128
- /**
129
- * Load configuration from file
130
- */
131
- async function loadConfig() {
132
- try {
133
- const configPath = getConfigPath();
134
- const content = await fs.readFile(configPath);
135
- return JSON.parse(content);
136
- } catch {
137
- return {};
101
+ //#region node_modules/dotenv/lib/main.js
102
+ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js": ((exports, module) => {
103
+ const fs$1 = __require("fs");
104
+ const path$1 = __require("path");
105
+ const os$1 = __require("os");
106
+ const crypto$1 = __require("crypto");
107
+ const version = require_package().version;
108
+ const TIPS = [
109
+ "🔐 encrypt with Dotenvx: https://dotenvx.com",
110
+ "🔐 prevent committing .env to code: https://dotenvx.com/precommit",
111
+ "🔐 prevent building .env in docker: https://dotenvx.com/prebuild",
112
+ "📡 add observability to secrets: https://dotenvx.com/ops",
113
+ "👥 sync secrets across teammates & machines: https://dotenvx.com/ops",
114
+ "🗂️ backup and recover secrets: https://dotenvx.com/ops",
115
+ "✅ audit secrets and track compliance: https://dotenvx.com/ops",
116
+ "🔄 add secrets lifecycle management: https://dotenvx.com/ops",
117
+ "🔑 add access controls to secrets: https://dotenvx.com/ops",
118
+ "🛠️ run anywhere with `dotenvx run -- yourcommand`",
119
+ "⚙️ specify custom .env file path with { path: '/custom/path/.env' }",
120
+ "⚙️ enable debug logging with { debug: true }",
121
+ "⚙️ override existing env vars with { override: true }",
122
+ "⚙️ suppress all logs with { quiet: true }",
123
+ "⚙️ write to custom object with { processEnv: myObject }",
124
+ "⚙️ load multiple .env files with { path: ['.env.local', '.env'] }"
125
+ ];
126
+ function _getRandomTip() {
127
+ return TIPS[Math.floor(Math.random() * TIPS.length)];
138
128
  }
139
- }
140
- /**
141
- * Save configuration to file
142
- */
143
- async function saveConfig(config$1) {
144
- const configPath = getConfigPath();
145
- await fs.writeFile(configPath, JSON.stringify(config$1, null, 2), "utf8");
146
- consola.debug(`Configuration saved to ${configPath}`);
147
- }
148
- /**
149
- * Get proxy configuration
150
- */
151
- async function getProxyConfig() {
152
- return (await loadConfig()).proxy;
153
- }
154
- /**
155
- * Save proxy configuration
156
- */
157
- async function saveProxyConfig(proxyConfig) {
158
- const config$1 = await loadConfig();
159
- config$1.proxy = proxyConfig;
160
- await saveConfig(config$1);
161
- }
162
- /**
163
- * Clear proxy configuration
164
- */
165
- async function clearProxyConfig() {
166
- const config$1 = await loadConfig();
167
- delete config$1.proxy;
168
- await saveConfig(config$1);
169
- }
170
- /**
171
- * Apply saved proxy configuration to environment variables
172
- * This should be called at startup to restore proxy settings
173
- */
174
- async function applyProxyConfig() {
175
- const proxyConfig = await getProxyConfig();
176
- if (!proxyConfig || !proxyConfig.enabled) return false;
177
- if (proxyConfig.httpProxy) {
178
- process.env.HTTP_PROXY = proxyConfig.httpProxy;
179
- process.env.http_proxy = proxyConfig.httpProxy;
129
+ function parseBoolean(value) {
130
+ if (typeof value === "string") return ![
131
+ "false",
132
+ "0",
133
+ "no",
134
+ "off",
135
+ ""
136
+ ].includes(value.toLowerCase());
137
+ return Boolean(value);
180
138
  }
181
- if (proxyConfig.httpsProxy) {
182
- process.env.HTTPS_PROXY = proxyConfig.httpsProxy;
183
- process.env.https_proxy = proxyConfig.httpsProxy;
139
+ function supportsAnsi() {
140
+ return process.stdout.isTTY;
184
141
  }
185
- if (proxyConfig.noProxy) {
186
- process.env.NO_PROXY = proxyConfig.noProxy;
187
- process.env.no_proxy = proxyConfig.noProxy;
142
+ function dim(text) {
143
+ return supportsAnsi() ? `\x1b[2m${text}\x1b[0m` : text;
188
144
  }
189
- consola.info("Proxy configuration loaded from saved settings");
190
- if (proxyConfig.httpProxy) consola.info(` HTTP_PROXY: ${proxyConfig.httpProxy}`);
191
- if (proxyConfig.httpsProxy) consola.info(` HTTPS_PROXY: ${proxyConfig.httpsProxy}`);
192
- if (proxyConfig.noProxy) consola.info(` NO_PROXY: ${proxyConfig.noProxy}`);
193
- return true;
194
- }
195
-
196
- //#endregion
197
- //#region src/debug.ts
198
- async function getPackageVersion() {
199
- try {
200
- const packageJsonPath = new URL("../package.json", import.meta.url).pathname;
201
- return JSON.parse(await fs.readFile(packageJsonPath)).version;
202
- } catch {
203
- return "unknown";
204
- }
205
- }
206
- function getRuntimeInfo() {
207
- const isBun = typeof Bun !== "undefined";
208
- return {
209
- name: isBun ? "bun" : "node",
210
- version: isBun ? Bun.version : process.version.slice(1),
211
- platform: os.platform(),
212
- arch: os.arch()
213
- };
214
- }
215
- async function checkTokenExists() {
216
- try {
217
- if (!(await fs.stat(PATHS.GITHUB_TOKEN_PATH)).isFile()) return false;
218
- return (await fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8")).trim().length > 0;
219
- } catch {
220
- return false;
145
+ const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
146
+ function parse(src) {
147
+ const obj = {};
148
+ let lines = src.toString();
149
+ lines = lines.replace(/\r\n?/gm, "\n");
150
+ let match;
151
+ while ((match = LINE.exec(lines)) != null) {
152
+ const key = match[1];
153
+ let value = match[2] || "";
154
+ value = value.trim();
155
+ const maybeQuote = value[0];
156
+ value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
157
+ if (maybeQuote === "\"") {
158
+ value = value.replace(/\\n/g, "\n");
159
+ value = value.replace(/\\r/g, "\r");
160
+ }
161
+ obj[key] = value;
162
+ }
163
+ return obj;
221
164
  }
222
- }
223
- async function checkFileExists(path$2) {
224
- try {
225
- if (!(await fs.stat(path$2)).isFile()) return false;
226
- return (await fs.readFile(path$2, "utf8")).trim().length > 0;
227
- } catch {
228
- return false;
165
+ function _parseVault(options$1) {
166
+ options$1 = options$1 || {};
167
+ const vaultPath = _vaultPath(options$1);
168
+ options$1.path = vaultPath;
169
+ const result = DotenvModule.configDotenv(options$1);
170
+ if (!result.parsed) {
171
+ const err = /* @__PURE__ */ new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
172
+ err.code = "MISSING_DATA";
173
+ throw err;
174
+ }
175
+ const keys = _dotenvKey(options$1).split(",");
176
+ const length = keys.length;
177
+ let decrypted;
178
+ for (let i = 0; i < length; i++) try {
179
+ const key = keys[i].trim();
180
+ const attrs = _instructions(result, key);
181
+ decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
182
+ break;
183
+ } catch (error) {
184
+ if (i + 1 >= length) throw error;
185
+ }
186
+ return DotenvModule.parse(decrypted);
229
187
  }
230
- }
231
- async function getDebugInfo() {
232
- const zenAuthPath = getZenAuthPath();
233
- const antigravityAuthPath = getAntigravityAuthPath();
234
- const [version$1, githubExists, zenExists, antigravityExists, proxyConfig] = await Promise.all([
235
- getPackageVersion(),
236
- checkTokenExists(),
237
- checkFileExists(zenAuthPath),
238
- checkFileExists(antigravityAuthPath),
239
- getProxyConfig()
240
- ]);
241
- return {
242
- version: version$1,
243
- runtime: getRuntimeInfo(),
244
- paths: {
245
- APP_DIR: PATHS.APP_DIR,
246
- GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,
247
- ZEN_AUTH_PATH: zenAuthPath,
248
- ANTIGRAVITY_AUTH_PATH: antigravityAuthPath
249
- },
250
- credentials: {
251
- github: githubExists,
252
- zen: zenExists,
253
- antigravity: antigravityExists
254
- },
255
- proxy: proxyConfig
256
- };
257
- }
258
- function printDebugInfoPlain(info) {
259
- let proxyStatus = "Not configured";
260
- if (info.proxy) proxyStatus = info.proxy.enabled ? `Enabled (${info.proxy.httpProxy || info.proxy.httpsProxy})` : "Disabled";
261
- consola.info(`copilot-api-plus debug
262
-
263
- Version: ${info.version}
264
- Runtime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})
265
-
266
- Paths:
267
- APP_DIR: ${info.paths.APP_DIR}
268
- GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}
269
- ZEN_AUTH_PATH: ${info.paths.ZEN_AUTH_PATH}
270
- ANTIGRAVITY_AUTH_PATH: ${info.paths.ANTIGRAVITY_AUTH_PATH}
271
-
272
- Credentials:
273
- GitHub Copilot: ${info.credentials.github ? "✅ Configured" : "❌ Not configured"}
274
- OpenCode Zen: ${info.credentials.zen ? "✅ Configured" : "❌ Not configured"}
275
- Google Antigravity: ${info.credentials.antigravity ? "✅ Configured" : "❌ Not configured"}
276
-
277
- Proxy: ${proxyStatus}`);
278
- }
279
- function printDebugInfoJson(info) {
280
- console.log(JSON.stringify(info, null, 2));
281
- }
282
- async function runDebug(options$1) {
283
- const debugInfo = await getDebugInfo();
284
- if (options$1.json) printDebugInfoJson(debugInfo);
285
- else printDebugInfoPlain(debugInfo);
286
- }
287
- const debug = defineCommand({
288
- meta: {
289
- name: "debug",
290
- description: "Print debug information about the application"
291
- },
292
- args: { json: {
293
- type: "boolean",
294
- default: false,
295
- description: "Output debug information as JSON"
296
- } },
297
- run({ args }) {
298
- return runDebug({ json: args.json });
188
+ function _warn(message) {
189
+ console.error(`[dotenv@${version}][WARN] ${message}`);
299
190
  }
300
- });
301
-
302
- //#endregion
303
- //#region src/logout.ts
304
- async function runLogout(options$1) {
305
- await ensurePaths();
306
- if (options$1.all) {
307
- await clearGithubToken();
308
- await clearZenAuth();
309
- await clearAntigravityAuth();
310
- consola.success("Logged out from all services");
311
- consola.info(`GitHub token: ${PATHS.GITHUB_TOKEN_PATH}`);
312
- consola.info(`Zen API key: ${getZenAuthPath()}`);
313
- consola.info(`Antigravity accounts: ${getAntigravityAuthPath()}`);
314
- return;
191
+ function _debug(message) {
192
+ console.log(`[dotenv@${version}][DEBUG] ${message}`);
315
193
  }
316
- if (options$1.github) {
317
- await clearGithubToken();
318
- consola.success("Logged out from GitHub Copilot");
319
- consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`);
320
- return;
194
+ function _log(message) {
195
+ console.log(`[dotenv@${version}] ${message}`);
321
196
  }
322
- if (options$1.zen) {
323
- await clearZenAuth();
324
- consola.success("Logged out from OpenCode Zen");
325
- consola.info(`Zen API key location: ${getZenAuthPath()}`);
326
- return;
197
+ function _dotenvKey(options$1) {
198
+ if (options$1 && options$1.DOTENV_KEY && options$1.DOTENV_KEY.length > 0) return options$1.DOTENV_KEY;
199
+ if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) return process.env.DOTENV_KEY;
200
+ return "";
327
201
  }
328
- if (options$1.antigravity) {
329
- await clearAntigravityAuth();
330
- consola.success("Logged out from Google Antigravity");
331
- consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
332
- return;
202
+ function _instructions(result, dotenvKey) {
203
+ let uri;
204
+ try {
205
+ uri = new URL(dotenvKey);
206
+ } catch (error) {
207
+ if (error.code === "ERR_INVALID_URL") {
208
+ const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
209
+ err.code = "INVALID_DOTENV_KEY";
210
+ throw err;
211
+ }
212
+ throw error;
213
+ }
214
+ const key = uri.password;
215
+ if (!key) {
216
+ const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing key part");
217
+ err.code = "INVALID_DOTENV_KEY";
218
+ throw err;
219
+ }
220
+ const environment = uri.searchParams.get("environment");
221
+ if (!environment) {
222
+ const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing environment part");
223
+ err.code = "INVALID_DOTENV_KEY";
224
+ throw err;
225
+ }
226
+ const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
227
+ const ciphertext = result.parsed[environmentKey];
228
+ if (!ciphertext) {
229
+ const err = /* @__PURE__ */ new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
230
+ err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
231
+ throw err;
232
+ }
233
+ return {
234
+ ciphertext,
235
+ key
236
+ };
333
237
  }
334
- switch (await consola.prompt("Which credentials do you want to clear?", {
335
- type: "select",
336
- options: [
337
- "GitHub Copilot token",
338
- "OpenCode Zen API key",
339
- "Google Antigravity accounts",
340
- "All credentials"
341
- ]
342
- })) {
343
- case "GitHub Copilot token":
344
- await clearGithubToken();
345
- consola.success("Logged out from GitHub Copilot");
346
- consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`);
347
- break;
348
- case "OpenCode Zen API key":
349
- await clearZenAuth();
350
- consola.success("Logged out from OpenCode Zen");
351
- consola.info(`Zen API key location: ${getZenAuthPath()}`);
352
- break;
353
- case "Google Antigravity accounts":
354
- await clearAntigravityAuth();
355
- consola.success("Logged out from Google Antigravity");
356
- consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
357
- break;
358
- case "All credentials":
359
- await clearGithubToken();
360
- await clearZenAuth();
361
- await clearAntigravityAuth();
362
- consola.success("Logged out from all services");
363
- break;
238
+ function _vaultPath(options$1) {
239
+ let possibleVaultPath = null;
240
+ if (options$1 && options$1.path && options$1.path.length > 0) if (Array.isArray(options$1.path)) {
241
+ for (const filepath of options$1.path) if (fs$1.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
242
+ } else possibleVaultPath = options$1.path.endsWith(".vault") ? options$1.path : `${options$1.path}.vault`;
243
+ else possibleVaultPath = path$1.resolve(process.cwd(), ".env.vault");
244
+ if (fs$1.existsSync(possibleVaultPath)) return possibleVaultPath;
245
+ return null;
364
246
  }
365
- }
366
- const logout = defineCommand({
367
- meta: {
368
- name: "logout",
369
- description: "Clear stored credentials and logout"
370
- },
371
- args: {
372
- github: {
373
- alias: "g",
374
- type: "boolean",
375
- default: false,
376
- description: "Clear only GitHub Copilot token"
377
- },
378
- zen: {
379
- alias: "z",
380
- type: "boolean",
381
- default: false,
382
- description: "Clear only OpenCode Zen API key"
383
- },
384
- antigravity: {
385
- type: "boolean",
386
- default: false,
387
- description: "Clear only Google Antigravity accounts"
388
- },
389
- all: {
390
- alias: "a",
391
- type: "boolean",
392
- default: false,
393
- description: "Clear all credentials (GitHub, Zen, and Antigravity)"
394
- }
395
- },
396
- run({ args }) {
397
- return runLogout({
398
- github: args.github,
399
- zen: args.zen,
400
- antigravity: args.antigravity,
401
- all: args.all
402
- });
247
+ function _resolveHome(envPath) {
248
+ return envPath[0] === "~" ? path$1.join(os$1.homedir(), envPath.slice(1)) : envPath;
403
249
  }
404
- });
405
-
406
- //#endregion
407
- //#region src/proxy-config.ts
408
- const proxy = defineCommand({
409
- meta: {
410
- name: "proxy",
411
- description: "Configure proxy settings (persistent)"
412
- },
413
- args: {
414
- set: {
415
- type: "boolean",
416
- default: false,
417
- description: "Set proxy configuration interactively"
418
- },
419
- enable: {
420
- type: "boolean",
421
- default: false,
422
- description: "Enable saved proxy configuration"
423
- },
424
- disable: {
425
- type: "boolean",
426
- default: false,
427
- description: "Disable proxy (keep settings)"
428
- },
429
- clear: {
430
- type: "boolean",
431
- default: false,
432
- description: "Clear all proxy settings"
433
- },
434
- show: {
435
- type: "boolean",
436
- default: false,
437
- description: "Show current proxy configuration"
438
- },
439
- "http-proxy": {
440
- type: "string",
441
- description: "HTTP proxy URL (e.g., http://proxy:8080)"
442
- },
443
- "https-proxy": {
444
- type: "string",
445
- description: "HTTPS proxy URL (e.g., http://proxy:8080)"
446
- },
447
- "no-proxy": {
448
- type: "string",
449
- description: "Comma-separated list of hosts to bypass proxy"
450
- }
451
- },
452
- async run({ args }) {
453
- await ensurePaths();
454
- if (args.show || !args.set && !args.enable && !args.disable && !args.clear && !args["http-proxy"] && !args["https-proxy"]) {
455
- const config$1 = await getProxyConfig();
456
- if (!config$1) {
457
- consola.info("No proxy configuration saved.");
458
- consola.info("");
459
- consola.info("To configure proxy, use one of:");
460
- consola.info(" copilot-api-plus proxy --set # Interactive setup");
461
- consola.info(" copilot-api-plus proxy --http-proxy http://proxy:8080 # Direct set");
462
- return;
463
- }
464
- consola.info("Current proxy configuration:");
465
- consola.info(` Status: ${config$1.enabled ? "✅ Enabled" : "❌ Disabled"}`);
466
- if (config$1.httpProxy) consola.info(` HTTP_PROXY: ${config$1.httpProxy}`);
467
- if (config$1.httpsProxy) consola.info(` HTTPS_PROXY: ${config$1.httpsProxy}`);
468
- if (config$1.noProxy) consola.info(` NO_PROXY: ${config$1.noProxy}`);
469
- return;
250
+ function _configVault(options$1) {
251
+ const debug$1 = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options$1 && options$1.debug);
252
+ const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options$1 && options$1.quiet);
253
+ if (debug$1 || !quiet) _log("Loading env from encrypted .env.vault");
254
+ const parsed = DotenvModule._parseVault(options$1);
255
+ let processEnv = process.env;
256
+ if (options$1 && options$1.processEnv != null) processEnv = options$1.processEnv;
257
+ DotenvModule.populate(processEnv, parsed, options$1);
258
+ return { parsed };
259
+ }
260
+ function configDotenv(options$1) {
261
+ const dotenvPath = path$1.resolve(process.cwd(), ".env");
262
+ let encoding = "utf8";
263
+ let processEnv = process.env;
264
+ if (options$1 && options$1.processEnv != null) processEnv = options$1.processEnv;
265
+ let debug$1 = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options$1 && options$1.debug);
266
+ let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options$1 && options$1.quiet);
267
+ if (options$1 && options$1.encoding) encoding = options$1.encoding;
268
+ else if (debug$1) _debug("No encoding is specified. UTF-8 is used by default");
269
+ let optionPaths = [dotenvPath];
270
+ if (options$1 && options$1.path) if (!Array.isArray(options$1.path)) optionPaths = [_resolveHome(options$1.path)];
271
+ else {
272
+ optionPaths = [];
273
+ for (const filepath of options$1.path) optionPaths.push(_resolveHome(filepath));
470
274
  }
471
- if (args.clear) {
472
- await clearProxyConfig();
473
- consola.success("Proxy configuration cleared.");
474
- return;
275
+ let lastError;
276
+ const parsedAll = {};
277
+ for (const path$2 of optionPaths) try {
278
+ const parsed = DotenvModule.parse(fs$1.readFileSync(path$2, { encoding }));
279
+ DotenvModule.populate(parsedAll, parsed, options$1);
280
+ } catch (e) {
281
+ if (debug$1) _debug(`Failed to load ${path$2} ${e.message}`);
282
+ lastError = e;
475
283
  }
476
- if (args.enable) {
477
- const config$1 = await getProxyConfig();
478
- if (!config$1) {
479
- consola.error("No proxy configuration saved. Use --set to configure first.");
480
- return;
284
+ const populated = DotenvModule.populate(processEnv, parsedAll, options$1);
285
+ debug$1 = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug$1);
286
+ quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
287
+ if (debug$1 || !quiet) {
288
+ const keysCount = Object.keys(populated).length;
289
+ const shortPaths = [];
290
+ for (const filePath of optionPaths) try {
291
+ const relative = path$1.relative(process.cwd(), filePath);
292
+ shortPaths.push(relative);
293
+ } catch (e) {
294
+ if (debug$1) _debug(`Failed to load ${filePath} ${e.message}`);
295
+ lastError = e;
481
296
  }
482
- config$1.enabled = true;
483
- await saveProxyConfig(config$1);
484
- consola.success("Proxy enabled. It will be used on next server start.");
485
- return;
297
+ _log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
486
298
  }
487
- if (args.disable) {
488
- const config$1 = await getProxyConfig();
489
- if (!config$1) {
490
- consola.info("No proxy configuration to disable.");
491
- return;
492
- }
493
- config$1.enabled = false;
494
- await saveProxyConfig(config$1);
495
- consola.success("Proxy disabled. Settings are preserved.");
496
- return;
299
+ if (lastError) return {
300
+ parsed: parsedAll,
301
+ error: lastError
302
+ };
303
+ else return { parsed: parsedAll };
304
+ }
305
+ function config(options$1) {
306
+ if (_dotenvKey(options$1).length === 0) return DotenvModule.configDotenv(options$1);
307
+ const vaultPath = _vaultPath(options$1);
308
+ if (!vaultPath) {
309
+ _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
310
+ return DotenvModule.configDotenv(options$1);
497
311
  }
498
- if (args["http-proxy"] || args["https-proxy"]) {
499
- const newConfig = {
500
- enabled: true,
501
- httpProxy: args["http-proxy"],
502
- httpsProxy: args["https-proxy"] || args["http-proxy"],
503
- noProxy: args["no-proxy"]
504
- };
505
- await saveProxyConfig(newConfig);
506
- consola.success("Proxy configuration saved and enabled.");
507
- consola.info(` HTTP_PROXY: ${newConfig.httpProxy || "(not set)"}`);
508
- consola.info(` HTTPS_PROXY: ${newConfig.httpsProxy || "(not set)"}`);
509
- if (newConfig.noProxy) consola.info(` NO_PROXY: ${newConfig.noProxy}`);
510
- return;
312
+ return DotenvModule._configVault(options$1);
313
+ }
314
+ function decrypt(encrypted, keyStr) {
315
+ const key = Buffer.from(keyStr.slice(-64), "hex");
316
+ let ciphertext = Buffer.from(encrypted, "base64");
317
+ const nonce = ciphertext.subarray(0, 12);
318
+ const authTag = ciphertext.subarray(-16);
319
+ ciphertext = ciphertext.subarray(12, -16);
320
+ try {
321
+ const aesgcm = crypto$1.createDecipheriv("aes-256-gcm", key, nonce);
322
+ aesgcm.setAuthTag(authTag);
323
+ return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
324
+ } catch (error) {
325
+ const isRange = error instanceof RangeError;
326
+ const invalidKeyLength = error.message === "Invalid key length";
327
+ const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
328
+ if (isRange || invalidKeyLength) {
329
+ const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
330
+ err.code = "INVALID_DOTENV_KEY";
331
+ throw err;
332
+ } else if (decryptionFailed) {
333
+ const err = /* @__PURE__ */ new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
334
+ err.code = "DECRYPTION_FAILED";
335
+ throw err;
336
+ } else throw error;
511
337
  }
512
- if (args.set) {
513
- p.intro("Proxy Configuration");
514
- const existingConfig = await getProxyConfig();
515
- const httpProxy = await p.text({
516
- message: "HTTP Proxy URL",
517
- placeholder: "http://proxy:8080",
518
- initialValue: existingConfig?.httpProxy || ""
519
- });
520
- if (p.isCancel(httpProxy)) {
521
- p.cancel("Configuration cancelled.");
522
- return;
338
+ }
339
+ function populate(processEnv, parsed, options$1 = {}) {
340
+ const debug$1 = Boolean(options$1 && options$1.debug);
341
+ const override = Boolean(options$1 && options$1.override);
342
+ const populated = {};
343
+ if (typeof parsed !== "object") {
344
+ const err = /* @__PURE__ */ new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
345
+ err.code = "OBJECT_REQUIRED";
346
+ throw err;
347
+ }
348
+ for (const key of Object.keys(parsed)) if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
349
+ if (override === true) {
350
+ processEnv[key] = parsed[key];
351
+ populated[key] = parsed[key];
523
352
  }
524
- const httpsProxy = await p.text({
525
- message: "HTTPS Proxy URL (leave empty to use HTTP proxy)",
526
- placeholder: "http://proxy:8080",
527
- initialValue: existingConfig?.httpsProxy || ""
528
- });
529
- if (p.isCancel(httpsProxy)) {
530
- p.cancel("Configuration cancelled.");
531
- return;
532
- }
533
- const noProxy = await p.text({
534
- message: "No Proxy (comma-separated hosts to bypass)",
535
- placeholder: "localhost,127.0.0.1,.local",
536
- initialValue: existingConfig?.noProxy || ""
537
- });
538
- if (p.isCancel(noProxy)) {
539
- p.cancel("Configuration cancelled.");
540
- return;
541
- }
542
- const enable = await p.confirm({
543
- message: "Enable proxy now?",
544
- initialValue: true
545
- });
546
- if (p.isCancel(enable)) {
547
- p.cancel("Configuration cancelled.");
548
- return;
549
- }
550
- await saveProxyConfig({
551
- enabled: enable,
552
- httpProxy: httpProxy || void 0,
553
- httpsProxy: httpsProxy || httpProxy || void 0,
554
- noProxy: noProxy || void 0
555
- });
556
- p.outro(`Proxy configuration saved${enable ? " and enabled" : ""}.`);
353
+ if (debug$1) if (override === true) _debug(`"${key}" is already defined and WAS overwritten`);
354
+ else _debug(`"${key}" is already defined and was NOT overwritten`);
355
+ } else {
356
+ processEnv[key] = parsed[key];
357
+ populated[key] = parsed[key];
557
358
  }
359
+ return populated;
558
360
  }
559
- });
361
+ const DotenvModule = {
362
+ configDotenv,
363
+ _configVault,
364
+ _parseVault,
365
+ config,
366
+ decrypt,
367
+ parse,
368
+ populate
369
+ };
370
+ module.exports.configDotenv = DotenvModule.configDotenv;
371
+ module.exports._configVault = DotenvModule._configVault;
372
+ module.exports._parseVault = DotenvModule._parseVault;
373
+ module.exports.config = DotenvModule.config;
374
+ module.exports.decrypt = DotenvModule.decrypt;
375
+ module.exports.parse = DotenvModule.parse;
376
+ module.exports.populate = DotenvModule.populate;
377
+ module.exports = DotenvModule;
378
+ }) });
560
379
 
561
380
  //#endregion
562
- //#region node_modules/dotenv/package.json
563
- var require_package = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/package.json": ((exports, module) => {
564
- module.exports = {
565
- "name": "dotenv",
566
- "version": "17.2.3",
567
- "description": "Loads environment variables from .env file",
568
- "main": "lib/main.js",
569
- "types": "lib/main.d.ts",
570
- "exports": {
571
- ".": {
572
- "types": "./lib/main.d.ts",
573
- "require": "./lib/main.js",
574
- "default": "./lib/main.js"
575
- },
576
- "./config": "./config.js",
577
- "./config.js": "./config.js",
578
- "./lib/env-options": "./lib/env-options.js",
579
- "./lib/env-options.js": "./lib/env-options.js",
580
- "./lib/cli-options": "./lib/cli-options.js",
581
- "./lib/cli-options.js": "./lib/cli-options.js",
582
- "./package.json": "./package.json"
583
- },
584
- "scripts": {
585
- "dts-check": "tsc --project tests/types/tsconfig.json",
586
- "lint": "standard",
587
- "pretest": "npm run lint && npm run dts-check",
588
- "test": "tap run tests/**/*.js --allow-empty-coverage --disable-coverage --timeout=60000",
589
- "test:coverage": "tap run tests/**/*.js --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
590
- "prerelease": "npm test",
591
- "release": "standard-version"
592
- },
593
- "repository": {
594
- "type": "git",
595
- "url": "git://github.com/motdotla/dotenv.git"
596
- },
597
- "homepage": "https://github.com/motdotla/dotenv#readme",
598
- "funding": "https://dotenvx.com",
599
- "keywords": [
600
- "dotenv",
601
- "env",
602
- ".env",
603
- "environment",
604
- "variables",
605
- "config",
606
- "settings"
607
- ],
608
- "readmeFilename": "README.md",
609
- "license": "BSD-2-Clause",
610
- "devDependencies": {
611
- "@types/node": "^18.11.3",
612
- "decache": "^4.6.2",
613
- "sinon": "^14.0.1",
614
- "standard": "^17.0.0",
615
- "standard-version": "^9.5.0",
616
- "tap": "^19.2.0",
617
- "typescript": "^4.8.4"
618
- },
619
- "engines": { "node": ">=12" },
620
- "browser": { "fs": false }
381
+ //#region node_modules/dotenv/lib/env-options.js
382
+ var require_env_options = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/env-options.js": ((exports, module) => {
383
+ const options = {};
384
+ if (process.env.DOTENV_CONFIG_ENCODING != null) options.encoding = process.env.DOTENV_CONFIG_ENCODING;
385
+ if (process.env.DOTENV_CONFIG_PATH != null) options.path = process.env.DOTENV_CONFIG_PATH;
386
+ if (process.env.DOTENV_CONFIG_QUIET != null) options.quiet = process.env.DOTENV_CONFIG_QUIET;
387
+ if (process.env.DOTENV_CONFIG_DEBUG != null) options.debug = process.env.DOTENV_CONFIG_DEBUG;
388
+ if (process.env.DOTENV_CONFIG_OVERRIDE != null) options.override = process.env.DOTENV_CONFIG_OVERRIDE;
389
+ if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY;
390
+ module.exports = options;
391
+ }) });
392
+
393
+ //#endregion
394
+ //#region node_modules/dotenv/lib/cli-options.js
395
+ var require_cli_options = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/cli-options.js": ((exports, module) => {
396
+ const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/;
397
+ module.exports = function optionMatcher(args) {
398
+ const options$1 = args.reduce(function(acc, cur) {
399
+ const matches = cur.match(re);
400
+ if (matches) acc[matches[1]] = matches[2];
401
+ return acc;
402
+ }, {});
403
+ if (!("quiet" in options$1)) options$1.quiet = "true";
404
+ return options$1;
621
405
  };
622
406
  }) });
623
407
 
624
408
  //#endregion
625
- //#region node_modules/dotenv/lib/main.js
626
- var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js": ((exports, module) => {
627
- const fs$1 = __require("fs");
628
- const path$1 = __require("path");
629
- const os$1 = __require("os");
630
- const crypto$1 = __require("crypto");
631
- const version = require_package().version;
632
- const TIPS = [
633
- "🔐 encrypt with Dotenvx: https://dotenvx.com",
634
- "🔐 prevent committing .env to code: https://dotenvx.com/precommit",
635
- "🔐 prevent building .env in docker: https://dotenvx.com/prebuild",
636
- "📡 add observability to secrets: https://dotenvx.com/ops",
637
- "👥 sync secrets across teammates & machines: https://dotenvx.com/ops",
638
- "🗂️ backup and recover secrets: https://dotenvx.com/ops",
639
- "✅ audit secrets and track compliance: https://dotenvx.com/ops",
640
- "🔄 add secrets lifecycle management: https://dotenvx.com/ops",
641
- "🔑 add access controls to secrets: https://dotenvx.com/ops",
642
- "🛠️ run anywhere with `dotenvx run -- yourcommand`",
643
- "⚙️ specify custom .env file path with { path: '/custom/path/.env' }",
644
- "⚙️ enable debug logging with { debug: true }",
645
- "⚙️ override existing env vars with { override: true }",
646
- "⚙️ suppress all logs with { quiet: true }",
647
- "⚙️ write to custom object with { processEnv: myObject }",
648
- "⚙️ load multiple .env files with { path: ['.env.local', '.env'] }"
649
- ];
650
- function _getRandomTip() {
651
- return TIPS[Math.floor(Math.random() * TIPS.length)];
409
+ //#region node_modules/dotenv/config.js
410
+ (function() {
411
+ require_main().config(Object.assign({}, require_env_options(), require_cli_options()(process.argv)));
412
+ })();
413
+
414
+ //#endregion
415
+ //#region src/lib/config.ts
416
+ const CONFIG_FILENAME = "config.json";
417
+ /**
418
+ * Get the path to the config file
419
+ */
420
+ function getConfigPath() {
421
+ return path.join(PATHS.DATA_DIR, CONFIG_FILENAME);
422
+ }
423
+ /**
424
+ * Load configuration from file
425
+ */
426
+ async function loadConfig() {
427
+ try {
428
+ const configPath = getConfigPath();
429
+ const content = await fs.readFile(configPath);
430
+ return JSON.parse(content);
431
+ } catch {
432
+ return {};
652
433
  }
653
- function parseBoolean(value) {
654
- if (typeof value === "string") return ![
655
- "false",
656
- "0",
657
- "no",
658
- "off",
659
- ""
660
- ].includes(value.toLowerCase());
661
- return Boolean(value);
434
+ }
435
+ /**
436
+ * Save configuration to file
437
+ */
438
+ async function saveConfig(config$1) {
439
+ const configPath = getConfigPath();
440
+ await fs.writeFile(configPath, JSON.stringify(config$1, null, 2), "utf8");
441
+ consola.debug(`Configuration saved to ${configPath}`);
442
+ }
443
+ /**
444
+ * Get proxy configuration
445
+ */
446
+ async function getProxyConfig() {
447
+ return (await loadConfig()).proxy;
448
+ }
449
+ /**
450
+ * Save proxy configuration
451
+ */
452
+ async function saveProxyConfig(proxyConfig) {
453
+ const config$1 = await loadConfig();
454
+ config$1.proxy = proxyConfig;
455
+ await saveConfig(config$1);
456
+ }
457
+ /**
458
+ * Clear proxy configuration
459
+ */
460
+ async function clearProxyConfig() {
461
+ const config$1 = await loadConfig();
462
+ delete config$1.proxy;
463
+ await saveConfig(config$1);
464
+ }
465
+ /**
466
+ * Apply saved proxy configuration to environment variables
467
+ * This should be called at startup to restore proxy settings
468
+ */
469
+ async function applyProxyConfig() {
470
+ const proxyConfig = await getProxyConfig();
471
+ if (!proxyConfig || !proxyConfig.enabled) return false;
472
+ if (proxyConfig.httpProxy) {
473
+ process.env.HTTP_PROXY = proxyConfig.httpProxy;
474
+ process.env.http_proxy = proxyConfig.httpProxy;
662
475
  }
663
- function supportsAnsi() {
664
- return process.stdout.isTTY;
476
+ if (proxyConfig.httpsProxy) {
477
+ process.env.HTTPS_PROXY = proxyConfig.httpsProxy;
478
+ process.env.https_proxy = proxyConfig.httpsProxy;
665
479
  }
666
- function dim(text) {
667
- return supportsAnsi() ? `\x1b[2m${text}\x1b[0m` : text;
480
+ if (proxyConfig.noProxy) {
481
+ process.env.NO_PROXY = proxyConfig.noProxy;
482
+ process.env.no_proxy = proxyConfig.noProxy;
668
483
  }
669
- const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
670
- function parse(src) {
671
- const obj = {};
672
- let lines = src.toString();
673
- lines = lines.replace(/\r\n?/gm, "\n");
674
- let match;
675
- while ((match = LINE.exec(lines)) != null) {
676
- const key = match[1];
677
- let value = match[2] || "";
678
- value = value.trim();
679
- const maybeQuote = value[0];
680
- value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
681
- if (maybeQuote === "\"") {
682
- value = value.replace(/\\n/g, "\n");
683
- value = value.replace(/\\r/g, "\r");
484
+ consola.info("Proxy configuration loaded from saved settings");
485
+ if (proxyConfig.httpProxy) consola.info(` HTTP_PROXY: ${proxyConfig.httpProxy}`);
486
+ if (proxyConfig.httpsProxy) consola.info(` HTTPS_PROXY: ${proxyConfig.httpsProxy}`);
487
+ if (proxyConfig.noProxy) consola.info(` NO_PROXY: ${proxyConfig.noProxy}`);
488
+ return true;
489
+ }
490
+
491
+ //#endregion
492
+ //#region src/lib/proxy.ts
493
+ function initProxyFromEnv() {
494
+ if (typeof Bun !== "undefined") return;
495
+ try {
496
+ const direct = new Agent();
497
+ const proxies = /* @__PURE__ */ new Map();
498
+ setGlobalDispatcher({
499
+ dispatch(options$1, handler) {
500
+ try {
501
+ const origin = typeof options$1.origin === "string" ? new URL(options$1.origin) : options$1.origin;
502
+ const raw = getProxyForUrl(origin.toString());
503
+ const proxyUrl = raw && raw.length > 0 ? raw : void 0;
504
+ if (!proxyUrl) {
505
+ consola.debug(`HTTP proxy bypass: ${origin.hostname}`);
506
+ return direct.dispatch(options$1, handler);
507
+ }
508
+ let agent = proxies.get(proxyUrl);
509
+ if (!agent) {
510
+ agent = new ProxyAgent(proxyUrl);
511
+ proxies.set(proxyUrl, agent);
512
+ }
513
+ let label = proxyUrl;
514
+ try {
515
+ const u = new URL(proxyUrl);
516
+ label = `${u.protocol}//${u.host}`;
517
+ } catch {}
518
+ consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`);
519
+ return agent.dispatch(options$1, handler);
520
+ } catch {
521
+ return direct.dispatch(options$1, handler);
522
+ }
523
+ },
524
+ close() {
525
+ return direct.close();
526
+ },
527
+ destroy() {
528
+ return direct.destroy();
684
529
  }
685
- obj[key] = value;
686
- }
687
- return obj;
530
+ });
531
+ consola.debug("HTTP proxy configured from environment (per-URL)");
532
+ } catch (err) {
533
+ consola.debug("Proxy setup skipped:", err);
688
534
  }
689
- function _parseVault(options$1) {
690
- options$1 = options$1 || {};
691
- const vaultPath = _vaultPath(options$1);
692
- options$1.path = vaultPath;
693
- const result = DotenvModule.configDotenv(options$1);
694
- if (!result.parsed) {
695
- const err = /* @__PURE__ */ new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
696
- err.code = "MISSING_DATA";
697
- throw err;
698
- }
699
- const keys = _dotenvKey(options$1).split(",");
700
- const length = keys.length;
701
- let decrypted;
702
- for (let i = 0; i < length; i++) try {
703
- const key = keys[i].trim();
704
- const attrs = _instructions(result, key);
705
- decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
706
- break;
707
- } catch (error) {
708
- if (i + 1 >= length) throw error;
709
- }
710
- return DotenvModule.parse(decrypted);
535
+ }
536
+
537
+ //#endregion
538
+ //#region src/antigravity.ts
539
+ /**
540
+ * Add a new Antigravity account via OAuth
541
+ */
542
+ async function addAccount() {
543
+ const { setupAntigravity, loadAntigravityAuth } = await import("./auth-B2lTFLSD.js");
544
+ const existingAuth = await loadAntigravityAuth();
545
+ if (existingAuth && existingAuth.accounts.length > 0) {
546
+ const enabledCount = existingAuth.accounts.filter((a) => a.enable).length;
547
+ consola.info(`Found ${existingAuth.accounts.length} existing accounts (${enabledCount} enabled)`);
711
548
  }
712
- function _warn(message) {
713
- console.error(`[dotenv@${version}][WARN] ${message}`);
549
+ await setupAntigravity();
550
+ }
551
+ /**
552
+ * List all Antigravity accounts
553
+ */
554
+ async function listAccounts() {
555
+ const { loadAntigravityAuth } = await import("./auth-B2lTFLSD.js");
556
+ const auth$1 = await loadAntigravityAuth();
557
+ if (!auth$1 || auth$1.accounts.length === 0) {
558
+ consola.info("No Antigravity accounts configured");
559
+ return;
714
560
  }
715
- function _debug(message) {
716
- console.log(`[dotenv@${version}][DEBUG] ${message}`);
561
+ consola.info(`\nAntigravity Accounts (${auth$1.accounts.length} total):`);
562
+ consola.info("=".repeat(50));
563
+ for (let i = 0; i < auth$1.accounts.length; i++) {
564
+ const account = auth$1.accounts[i];
565
+ const isCurrent = i === auth$1.currentIndex;
566
+ const status = account.enable ? "enabled" : "disabled";
567
+ const marker = isCurrent ? "→ " : " ";
568
+ const projectId = account.project_id || "unknown";
569
+ consola.info(`${marker}[${i}] Project: ${projectId} | Status: ${status}${isCurrent ? " (current)" : ""}`);
717
570
  }
718
- function _log(message) {
719
- console.log(`[dotenv@${version}] ${message}`);
571
+ }
572
+ /**
573
+ * Remove an Antigravity account by index
574
+ */
575
+ async function removeAccount(index) {
576
+ const { loadAntigravityAuth, saveAntigravityAuth } = await import("./auth-B2lTFLSD.js");
577
+ const auth$1 = await loadAntigravityAuth();
578
+ if (!auth$1 || auth$1.accounts.length === 0) {
579
+ consola.error("No Antigravity accounts configured");
580
+ return;
720
581
  }
721
- function _dotenvKey(options$1) {
722
- if (options$1 && options$1.DOTENV_KEY && options$1.DOTENV_KEY.length > 0) return options$1.DOTENV_KEY;
723
- if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) return process.env.DOTENV_KEY;
724
- return "";
582
+ if (index < 0 || index >= auth$1.accounts.length) {
583
+ consola.error(`Invalid index. Must be between 0 and ${auth$1.accounts.length - 1}`);
584
+ return;
725
585
  }
726
- function _instructions(result, dotenvKey) {
727
- let uri;
728
- try {
729
- uri = new URL(dotenvKey);
730
- } catch (error) {
731
- if (error.code === "ERR_INVALID_URL") {
732
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
733
- err.code = "INVALID_DOTENV_KEY";
734
- throw err;
586
+ const removed = auth$1.accounts.splice(index, 1)[0];
587
+ if (auth$1.currentIndex >= auth$1.accounts.length) auth$1.currentIndex = Math.max(0, auth$1.accounts.length - 1);
588
+ await saveAntigravityAuth(auth$1);
589
+ consola.success(`Removed account ${index} (Project: ${removed.project_id || "unknown"})`);
590
+ }
591
+ /**
592
+ * Clear all Antigravity accounts
593
+ */
594
+ async function clearAccounts() {
595
+ const { clearAntigravityAuth: clearAntigravityAuth$1 } = await import("./auth-B2lTFLSD.js");
596
+ if (await consola.prompt("Are you sure you want to remove all Antigravity accounts?", {
597
+ type: "confirm",
598
+ initial: false
599
+ })) await clearAntigravityAuth$1();
600
+ }
601
+ const antigravity = defineCommand({
602
+ meta: {
603
+ name: "antigravity",
604
+ description: "Manage Google Antigravity accounts"
605
+ },
606
+ subCommands: {
607
+ add: defineCommand({
608
+ meta: {
609
+ name: "add",
610
+ description: "Add a new Antigravity account via OAuth"
611
+ },
612
+ async run() {
613
+ await ensurePaths();
614
+ if (await applyProxyConfig()) initProxyFromEnv();
615
+ await addAccount();
735
616
  }
736
- throw error;
737
- }
738
- const key = uri.password;
739
- if (!key) {
740
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing key part");
741
- err.code = "INVALID_DOTENV_KEY";
742
- throw err;
743
- }
744
- const environment = uri.searchParams.get("environment");
745
- if (!environment) {
746
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing environment part");
747
- err.code = "INVALID_DOTENV_KEY";
748
- throw err;
749
- }
750
- const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
751
- const ciphertext = result.parsed[environmentKey];
752
- if (!ciphertext) {
753
- const err = /* @__PURE__ */ new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
754
- err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
755
- throw err;
756
- }
757
- return {
758
- ciphertext,
759
- key
760
- };
617
+ }),
618
+ list: defineCommand({
619
+ meta: {
620
+ name: "list",
621
+ description: "List all Antigravity accounts"
622
+ },
623
+ async run() {
624
+ await ensurePaths();
625
+ await listAccounts();
626
+ }
627
+ }),
628
+ remove: defineCommand({
629
+ meta: {
630
+ name: "remove",
631
+ description: "Remove an Antigravity account by index"
632
+ },
633
+ args: { index: {
634
+ type: "positional",
635
+ description: "Account index to remove (use 'list' to see indexes)",
636
+ required: true
637
+ } },
638
+ async run({ args }) {
639
+ await ensurePaths();
640
+ const indexStr = String(args.index);
641
+ const index = Number.parseInt(indexStr, 10);
642
+ if (Number.isNaN(index)) {
643
+ consola.error("Index must be a number");
644
+ return;
645
+ }
646
+ await removeAccount(index);
647
+ }
648
+ }),
649
+ clear: defineCommand({
650
+ meta: {
651
+ name: "clear",
652
+ description: "Remove all Antigravity accounts"
653
+ },
654
+ async run() {
655
+ await ensurePaths();
656
+ await clearAccounts();
657
+ }
658
+ })
761
659
  }
762
- function _vaultPath(options$1) {
763
- let possibleVaultPath = null;
764
- if (options$1 && options$1.path && options$1.path.length > 0) if (Array.isArray(options$1.path)) {
765
- for (const filepath of options$1.path) if (fs$1.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
766
- } else possibleVaultPath = options$1.path.endsWith(".vault") ? options$1.path : `${options$1.path}.vault`;
767
- else possibleVaultPath = path$1.resolve(process.cwd(), ".env.vault");
768
- if (fs$1.existsSync(possibleVaultPath)) return possibleVaultPath;
769
- return null;
660
+ });
661
+
662
+ //#endregion
663
+ //#region src/auth.ts
664
+ async function runAuth(options$1) {
665
+ if (options$1.verbose) {
666
+ consola.level = 5;
667
+ consola.info("Verbose logging enabled");
770
668
  }
771
- function _resolveHome(envPath) {
772
- return envPath[0] === "~" ? path$1.join(os$1.homedir(), envPath.slice(1)) : envPath;
669
+ state.showToken = options$1.showToken;
670
+ await ensurePaths();
671
+ await setupGitHubToken({ force: true });
672
+ consola.success("GitHub token written to", PATHS.GITHUB_TOKEN_PATH);
673
+ }
674
+ const auth = defineCommand({
675
+ meta: {
676
+ name: "auth",
677
+ description: "Run GitHub auth flow without running the server"
678
+ },
679
+ args: {
680
+ verbose: {
681
+ alias: "v",
682
+ type: "boolean",
683
+ default: false,
684
+ description: "Enable verbose logging"
685
+ },
686
+ "show-token": {
687
+ type: "boolean",
688
+ default: false,
689
+ description: "Show GitHub token on auth"
690
+ }
691
+ },
692
+ run({ args }) {
693
+ return runAuth({
694
+ verbose: args.verbose,
695
+ showToken: args["show-token"]
696
+ });
773
697
  }
774
- function _configVault(options$1) {
775
- const debug$1 = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options$1 && options$1.debug);
776
- const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options$1 && options$1.quiet);
777
- if (debug$1 || !quiet) _log("Loading env from encrypted .env.vault");
778
- const parsed = DotenvModule._parseVault(options$1);
779
- let processEnv = process.env;
780
- if (options$1 && options$1.processEnv != null) processEnv = options$1.processEnv;
781
- DotenvModule.populate(processEnv, parsed, options$1);
782
- return { parsed };
698
+ });
699
+
700
+ //#endregion
701
+ //#region src/services/github/get-copilot-usage.ts
702
+ const getCopilotUsage = async () => {
703
+ const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, { headers: githubHeaders(state) });
704
+ if (!response.ok) throw new HTTPError("Failed to get Copilot usage", response);
705
+ return await response.json();
706
+ };
707
+
708
+ //#endregion
709
+ //#region src/check-usage.ts
710
+ const checkUsage = defineCommand({
711
+ meta: {
712
+ name: "check-usage",
713
+ description: "Show current GitHub Copilot usage/quota information"
714
+ },
715
+ async run() {
716
+ await ensurePaths();
717
+ await setupGitHubToken();
718
+ try {
719
+ const usage = await getCopilotUsage();
720
+ const premium = usage.quota_snapshots.premium_interactions;
721
+ const premiumTotal = premium.entitlement;
722
+ const premiumUsed = premiumTotal - premium.remaining;
723
+ const premiumPercentUsed = premiumTotal > 0 ? premiumUsed / premiumTotal * 100 : 0;
724
+ const premiumPercentRemaining = premium.percent_remaining;
725
+ function summarizeQuota(name, snap) {
726
+ if (!snap) return `${name}: N/A`;
727
+ const total = snap.entitlement;
728
+ const used = total - snap.remaining;
729
+ const percentUsed = total > 0 ? used / total * 100 : 0;
730
+ const percentRemaining = snap.percent_remaining;
731
+ return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`;
732
+ }
733
+ const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`;
734
+ const chatLine = summarizeQuota("Chat", usage.quota_snapshots.chat);
735
+ const completionsLine = summarizeQuota("Completions", usage.quota_snapshots.completions);
736
+ consola.box(`Copilot Usage (plan: ${usage.copilot_plan})\nQuota resets: ${usage.quota_reset_date}\n\nQuotas:\n ${premiumLine}\n ${chatLine}\n ${completionsLine}`);
737
+ } catch (err) {
738
+ consola.error("Failed to fetch Copilot usage:", err);
739
+ process.exit(1);
740
+ }
783
741
  }
784
- function configDotenv(options$1) {
785
- const dotenvPath = path$1.resolve(process.cwd(), ".env");
786
- let encoding = "utf8";
787
- let processEnv = process.env;
788
- if (options$1 && options$1.processEnv != null) processEnv = options$1.processEnv;
789
- let debug$1 = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options$1 && options$1.debug);
790
- let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options$1 && options$1.quiet);
791
- if (options$1 && options$1.encoding) encoding = options$1.encoding;
792
- else if (debug$1) _debug("No encoding is specified. UTF-8 is used by default");
793
- let optionPaths = [dotenvPath];
794
- if (options$1 && options$1.path) if (!Array.isArray(options$1.path)) optionPaths = [_resolveHome(options$1.path)];
795
- else {
796
- optionPaths = [];
797
- for (const filepath of options$1.path) optionPaths.push(_resolveHome(filepath));
798
- }
799
- let lastError;
800
- const parsedAll = {};
801
- for (const path$2 of optionPaths) try {
802
- const parsed = DotenvModule.parse(fs$1.readFileSync(path$2, { encoding }));
803
- DotenvModule.populate(parsedAll, parsed, options$1);
804
- } catch (e) {
805
- if (debug$1) _debug(`Failed to load ${path$2} ${e.message}`);
806
- lastError = e;
742
+ });
743
+
744
+ //#endregion
745
+ //#region src/debug.ts
746
+ async function getPackageVersion() {
747
+ try {
748
+ const packageJsonPath = new URL("../package.json", import.meta.url).pathname;
749
+ return JSON.parse(await fs.readFile(packageJsonPath)).version;
750
+ } catch {
751
+ return "unknown";
752
+ }
753
+ }
754
+ function getRuntimeInfo() {
755
+ const isBun = typeof Bun !== "undefined";
756
+ return {
757
+ name: isBun ? "bun" : "node",
758
+ version: isBun ? Bun.version : process.version.slice(1),
759
+ platform: os.platform(),
760
+ arch: os.arch()
761
+ };
762
+ }
763
+ async function checkTokenExists() {
764
+ try {
765
+ if (!(await fs.stat(PATHS.GITHUB_TOKEN_PATH)).isFile()) return false;
766
+ return (await fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8")).trim().length > 0;
767
+ } catch {
768
+ return false;
769
+ }
770
+ }
771
+ async function checkFileExists(path$2) {
772
+ try {
773
+ if (!(await fs.stat(path$2)).isFile()) return false;
774
+ return (await fs.readFile(path$2, "utf8")).trim().length > 0;
775
+ } catch {
776
+ return false;
777
+ }
778
+ }
779
+ async function getDebugInfo() {
780
+ const zenAuthPath = getZenAuthPath();
781
+ const antigravityAuthPath = getAntigravityAuthPath();
782
+ const [version$1, githubExists, zenExists, antigravityExists, proxyConfig] = await Promise.all([
783
+ getPackageVersion(),
784
+ checkTokenExists(),
785
+ checkFileExists(zenAuthPath),
786
+ checkFileExists(antigravityAuthPath),
787
+ getProxyConfig()
788
+ ]);
789
+ return {
790
+ version: version$1,
791
+ runtime: getRuntimeInfo(),
792
+ paths: {
793
+ APP_DIR: PATHS.APP_DIR,
794
+ GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,
795
+ ZEN_AUTH_PATH: zenAuthPath,
796
+ ANTIGRAVITY_AUTH_PATH: antigravityAuthPath
797
+ },
798
+ credentials: {
799
+ github: githubExists,
800
+ zen: zenExists,
801
+ antigravity: antigravityExists
802
+ },
803
+ proxy: proxyConfig
804
+ };
805
+ }
806
+ function printDebugInfoPlain(info) {
807
+ let proxyStatus = "Not configured";
808
+ if (info.proxy) proxyStatus = info.proxy.enabled ? `Enabled (${info.proxy.httpProxy || info.proxy.httpsProxy})` : "Disabled";
809
+ consola.info(`copilot-api-plus debug
810
+
811
+ Version: ${info.version}
812
+ Runtime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})
813
+
814
+ Paths:
815
+ APP_DIR: ${info.paths.APP_DIR}
816
+ GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}
817
+ ZEN_AUTH_PATH: ${info.paths.ZEN_AUTH_PATH}
818
+ ANTIGRAVITY_AUTH_PATH: ${info.paths.ANTIGRAVITY_AUTH_PATH}
819
+
820
+ Credentials:
821
+ GitHub Copilot: ${info.credentials.github ? "✅ Configured" : "❌ Not configured"}
822
+ OpenCode Zen: ${info.credentials.zen ? "✅ Configured" : "❌ Not configured"}
823
+ Google Antigravity: ${info.credentials.antigravity ? "✅ Configured" : "❌ Not configured"}
824
+
825
+ Proxy: ${proxyStatus}`);
826
+ }
827
+ function printDebugInfoJson(info) {
828
+ console.log(JSON.stringify(info, null, 2));
829
+ }
830
+ async function runDebug(options$1) {
831
+ const debugInfo = await getDebugInfo();
832
+ if (options$1.json) printDebugInfoJson(debugInfo);
833
+ else printDebugInfoPlain(debugInfo);
834
+ }
835
+ const debug = defineCommand({
836
+ meta: {
837
+ name: "debug",
838
+ description: "Print debug information about the application"
839
+ },
840
+ args: { json: {
841
+ type: "boolean",
842
+ default: false,
843
+ description: "Output debug information as JSON"
844
+ } },
845
+ run({ args }) {
846
+ return runDebug({ json: args.json });
847
+ }
848
+ });
849
+
850
+ //#endregion
851
+ //#region src/logout.ts
852
+ async function runLogout(options$1) {
853
+ await ensurePaths();
854
+ if (options$1.all) {
855
+ await clearGithubToken();
856
+ await clearZenAuth();
857
+ await clearAntigravityAuth();
858
+ consola.success("Logged out from all services");
859
+ consola.info(`GitHub token: ${PATHS.GITHUB_TOKEN_PATH}`);
860
+ consola.info(`Zen API key: ${getZenAuthPath()}`);
861
+ consola.info(`Antigravity accounts: ${getAntigravityAuthPath()}`);
862
+ return;
863
+ }
864
+ if (options$1.github) {
865
+ await clearGithubToken();
866
+ consola.success("Logged out from GitHub Copilot");
867
+ consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`);
868
+ return;
869
+ }
870
+ if (options$1.zen) {
871
+ await clearZenAuth();
872
+ consola.success("Logged out from OpenCode Zen");
873
+ consola.info(`Zen API key location: ${getZenAuthPath()}`);
874
+ return;
875
+ }
876
+ if (options$1.antigravity) {
877
+ await clearAntigravityAuth();
878
+ consola.success("Logged out from Google Antigravity");
879
+ consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
880
+ return;
881
+ }
882
+ switch (await consola.prompt("Which credentials do you want to clear?", {
883
+ type: "select",
884
+ options: [
885
+ "GitHub Copilot token",
886
+ "OpenCode Zen API key",
887
+ "Google Antigravity accounts",
888
+ "All credentials"
889
+ ]
890
+ })) {
891
+ case "GitHub Copilot token":
892
+ await clearGithubToken();
893
+ consola.success("Logged out from GitHub Copilot");
894
+ consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`);
895
+ break;
896
+ case "OpenCode Zen API key":
897
+ await clearZenAuth();
898
+ consola.success("Logged out from OpenCode Zen");
899
+ consola.info(`Zen API key location: ${getZenAuthPath()}`);
900
+ break;
901
+ case "Google Antigravity accounts":
902
+ await clearAntigravityAuth();
903
+ consola.success("Logged out from Google Antigravity");
904
+ consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
905
+ break;
906
+ case "All credentials":
907
+ await clearGithubToken();
908
+ await clearZenAuth();
909
+ await clearAntigravityAuth();
910
+ consola.success("Logged out from all services");
911
+ break;
912
+ }
913
+ }
914
+ const logout = defineCommand({
915
+ meta: {
916
+ name: "logout",
917
+ description: "Clear stored credentials and logout"
918
+ },
919
+ args: {
920
+ github: {
921
+ alias: "g",
922
+ type: "boolean",
923
+ default: false,
924
+ description: "Clear only GitHub Copilot token"
925
+ },
926
+ zen: {
927
+ alias: "z",
928
+ type: "boolean",
929
+ default: false,
930
+ description: "Clear only OpenCode Zen API key"
931
+ },
932
+ antigravity: {
933
+ type: "boolean",
934
+ default: false,
935
+ description: "Clear only Google Antigravity accounts"
936
+ },
937
+ all: {
938
+ alias: "a",
939
+ type: "boolean",
940
+ default: false,
941
+ description: "Clear all credentials (GitHub, Zen, and Antigravity)"
807
942
  }
808
- const populated = DotenvModule.populate(processEnv, parsedAll, options$1);
809
- debug$1 = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug$1);
810
- quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
811
- if (debug$1 || !quiet) {
812
- const keysCount = Object.keys(populated).length;
813
- const shortPaths = [];
814
- for (const filePath of optionPaths) try {
815
- const relative = path$1.relative(process.cwd(), filePath);
816
- shortPaths.push(relative);
817
- } catch (e) {
818
- if (debug$1) _debug(`Failed to load ${filePath} ${e.message}`);
819
- lastError = e;
820
- }
821
- _log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
943
+ },
944
+ run({ args }) {
945
+ return runLogout({
946
+ github: args.github,
947
+ zen: args.zen,
948
+ antigravity: args.antigravity,
949
+ all: args.all
950
+ });
951
+ }
952
+ });
953
+
954
+ //#endregion
955
+ //#region src/proxy-config.ts
956
+ const proxy = defineCommand({
957
+ meta: {
958
+ name: "proxy",
959
+ description: "Configure proxy settings (persistent)"
960
+ },
961
+ args: {
962
+ set: {
963
+ type: "boolean",
964
+ default: false,
965
+ description: "Set proxy configuration interactively"
966
+ },
967
+ enable: {
968
+ type: "boolean",
969
+ default: false,
970
+ description: "Enable saved proxy configuration"
971
+ },
972
+ disable: {
973
+ type: "boolean",
974
+ default: false,
975
+ description: "Disable proxy (keep settings)"
976
+ },
977
+ clear: {
978
+ type: "boolean",
979
+ default: false,
980
+ description: "Clear all proxy settings"
981
+ },
982
+ show: {
983
+ type: "boolean",
984
+ default: false,
985
+ description: "Show current proxy configuration"
986
+ },
987
+ "http-proxy": {
988
+ type: "string",
989
+ description: "HTTP proxy URL (e.g., http://proxy:8080)"
990
+ },
991
+ "https-proxy": {
992
+ type: "string",
993
+ description: "HTTPS proxy URL (e.g., http://proxy:8080)"
994
+ },
995
+ "no-proxy": {
996
+ type: "string",
997
+ description: "Comma-separated list of hosts to bypass proxy"
822
998
  }
823
- if (lastError) return {
824
- parsed: parsedAll,
825
- error: lastError
826
- };
827
- else return { parsed: parsedAll };
828
- }
829
- function config(options$1) {
830
- if (_dotenvKey(options$1).length === 0) return DotenvModule.configDotenv(options$1);
831
- const vaultPath = _vaultPath(options$1);
832
- if (!vaultPath) {
833
- _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
834
- return DotenvModule.configDotenv(options$1);
999
+ },
1000
+ async run({ args }) {
1001
+ await ensurePaths();
1002
+ if (args.show || !args.set && !args.enable && !args.disable && !args.clear && !args["http-proxy"] && !args["https-proxy"]) {
1003
+ const config$1 = await getProxyConfig();
1004
+ if (!config$1) {
1005
+ consola.info("No proxy configuration saved.");
1006
+ consola.info("");
1007
+ consola.info("To configure proxy, use one of:");
1008
+ consola.info(" copilot-api-plus proxy --set # Interactive setup");
1009
+ consola.info(" copilot-api-plus proxy --http-proxy http://proxy:8080 # Direct set");
1010
+ return;
1011
+ }
1012
+ consola.info("Current proxy configuration:");
1013
+ consola.info(` Status: ${config$1.enabled ? "✅ Enabled" : "❌ Disabled"}`);
1014
+ if (config$1.httpProxy) consola.info(` HTTP_PROXY: ${config$1.httpProxy}`);
1015
+ if (config$1.httpsProxy) consola.info(` HTTPS_PROXY: ${config$1.httpsProxy}`);
1016
+ if (config$1.noProxy) consola.info(` NO_PROXY: ${config$1.noProxy}`);
1017
+ return;
835
1018
  }
836
- return DotenvModule._configVault(options$1);
837
- }
838
- function decrypt(encrypted, keyStr) {
839
- const key = Buffer.from(keyStr.slice(-64), "hex");
840
- let ciphertext = Buffer.from(encrypted, "base64");
841
- const nonce = ciphertext.subarray(0, 12);
842
- const authTag = ciphertext.subarray(-16);
843
- ciphertext = ciphertext.subarray(12, -16);
844
- try {
845
- const aesgcm = crypto$1.createDecipheriv("aes-256-gcm", key, nonce);
846
- aesgcm.setAuthTag(authTag);
847
- return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
848
- } catch (error) {
849
- const isRange = error instanceof RangeError;
850
- const invalidKeyLength = error.message === "Invalid key length";
851
- const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
852
- if (isRange || invalidKeyLength) {
853
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
854
- err.code = "INVALID_DOTENV_KEY";
855
- throw err;
856
- } else if (decryptionFailed) {
857
- const err = /* @__PURE__ */ new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
858
- err.code = "DECRYPTION_FAILED";
859
- throw err;
860
- } else throw error;
1019
+ if (args.clear) {
1020
+ await clearProxyConfig();
1021
+ consola.success("Proxy configuration cleared.");
1022
+ return;
861
1023
  }
862
- }
863
- function populate(processEnv, parsed, options$1 = {}) {
864
- const debug$1 = Boolean(options$1 && options$1.debug);
865
- const override = Boolean(options$1 && options$1.override);
866
- const populated = {};
867
- if (typeof parsed !== "object") {
868
- const err = /* @__PURE__ */ new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
869
- err.code = "OBJECT_REQUIRED";
870
- throw err;
1024
+ if (args.enable) {
1025
+ const config$1 = await getProxyConfig();
1026
+ if (!config$1) {
1027
+ consola.error("No proxy configuration saved. Use --set to configure first.");
1028
+ return;
1029
+ }
1030
+ config$1.enabled = true;
1031
+ await saveProxyConfig(config$1);
1032
+ consola.success("Proxy enabled. It will be used on next server start.");
1033
+ return;
871
1034
  }
872
- for (const key of Object.keys(parsed)) if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
873
- if (override === true) {
874
- processEnv[key] = parsed[key];
875
- populated[key] = parsed[key];
1035
+ if (args.disable) {
1036
+ const config$1 = await getProxyConfig();
1037
+ if (!config$1) {
1038
+ consola.info("No proxy configuration to disable.");
1039
+ return;
876
1040
  }
877
- if (debug$1) if (override === true) _debug(`"${key}" is already defined and WAS overwritten`);
878
- else _debug(`"${key}" is already defined and was NOT overwritten`);
879
- } else {
880
- processEnv[key] = parsed[key];
881
- populated[key] = parsed[key];
1041
+ config$1.enabled = false;
1042
+ await saveProxyConfig(config$1);
1043
+ consola.success("Proxy disabled. Settings are preserved.");
1044
+ return;
882
1045
  }
883
- return populated;
884
- }
885
- const DotenvModule = {
886
- configDotenv,
887
- _configVault,
888
- _parseVault,
889
- config,
890
- decrypt,
891
- parse,
892
- populate
893
- };
894
- module.exports.configDotenv = DotenvModule.configDotenv;
895
- module.exports._configVault = DotenvModule._configVault;
896
- module.exports._parseVault = DotenvModule._parseVault;
897
- module.exports.config = DotenvModule.config;
898
- module.exports.decrypt = DotenvModule.decrypt;
899
- module.exports.parse = DotenvModule.parse;
900
- module.exports.populate = DotenvModule.populate;
901
- module.exports = DotenvModule;
902
- }) });
903
-
904
- //#endregion
905
- //#region node_modules/dotenv/lib/env-options.js
906
- var require_env_options = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/env-options.js": ((exports, module) => {
907
- const options = {};
908
- if (process.env.DOTENV_CONFIG_ENCODING != null) options.encoding = process.env.DOTENV_CONFIG_ENCODING;
909
- if (process.env.DOTENV_CONFIG_PATH != null) options.path = process.env.DOTENV_CONFIG_PATH;
910
- if (process.env.DOTENV_CONFIG_QUIET != null) options.quiet = process.env.DOTENV_CONFIG_QUIET;
911
- if (process.env.DOTENV_CONFIG_DEBUG != null) options.debug = process.env.DOTENV_CONFIG_DEBUG;
912
- if (process.env.DOTENV_CONFIG_OVERRIDE != null) options.override = process.env.DOTENV_CONFIG_OVERRIDE;
913
- if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY;
914
- module.exports = options;
915
- }) });
916
-
917
- //#endregion
918
- //#region node_modules/dotenv/lib/cli-options.js
919
- var require_cli_options = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/cli-options.js": ((exports, module) => {
920
- const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/;
921
- module.exports = function optionMatcher(args) {
922
- const options$1 = args.reduce(function(acc, cur) {
923
- const matches = cur.match(re);
924
- if (matches) acc[matches[1]] = matches[2];
925
- return acc;
926
- }, {});
927
- if (!("quiet" in options$1)) options$1.quiet = "true";
928
- return options$1;
929
- };
930
- }) });
931
-
932
- //#endregion
933
- //#region node_modules/dotenv/config.js
934
- (function() {
935
- require_main().config(Object.assign({}, require_env_options(), require_cli_options()(process.argv)));
936
- })();
937
-
938
- //#endregion
939
- //#region src/lib/proxy.ts
940
- function initProxyFromEnv() {
941
- if (typeof Bun !== "undefined") return;
942
- try {
943
- const direct = new Agent();
944
- const proxies = /* @__PURE__ */ new Map();
945
- setGlobalDispatcher({
946
- dispatch(options$1, handler) {
947
- try {
948
- const origin = typeof options$1.origin === "string" ? new URL(options$1.origin) : options$1.origin;
949
- const raw = getProxyForUrl(origin.toString());
950
- const proxyUrl = raw && raw.length > 0 ? raw : void 0;
951
- if (!proxyUrl) {
952
- consola.debug(`HTTP proxy bypass: ${origin.hostname}`);
953
- return direct.dispatch(options$1, handler);
954
- }
955
- let agent = proxies.get(proxyUrl);
956
- if (!agent) {
957
- agent = new ProxyAgent(proxyUrl);
958
- proxies.set(proxyUrl, agent);
959
- }
960
- let label = proxyUrl;
961
- try {
962
- const u = new URL(proxyUrl);
963
- label = `${u.protocol}//${u.host}`;
964
- } catch {}
965
- consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`);
966
- return agent.dispatch(options$1, handler);
967
- } catch {
968
- return direct.dispatch(options$1, handler);
969
- }
970
- },
971
- close() {
972
- return direct.close();
973
- },
974
- destroy() {
975
- return direct.destroy();
1046
+ if (args["http-proxy"] || args["https-proxy"]) {
1047
+ const newConfig = {
1048
+ enabled: true,
1049
+ httpProxy: args["http-proxy"],
1050
+ httpsProxy: args["https-proxy"] || args["http-proxy"],
1051
+ noProxy: args["no-proxy"]
1052
+ };
1053
+ await saveProxyConfig(newConfig);
1054
+ consola.success("Proxy configuration saved and enabled.");
1055
+ consola.info(` HTTP_PROXY: ${newConfig.httpProxy || "(not set)"}`);
1056
+ consola.info(` HTTPS_PROXY: ${newConfig.httpsProxy || "(not set)"}`);
1057
+ if (newConfig.noProxy) consola.info(` NO_PROXY: ${newConfig.noProxy}`);
1058
+ return;
1059
+ }
1060
+ if (args.set) {
1061
+ p.intro("Proxy Configuration");
1062
+ const existingConfig = await getProxyConfig();
1063
+ const httpProxy = await p.text({
1064
+ message: "HTTP Proxy URL",
1065
+ placeholder: "http://proxy:8080",
1066
+ initialValue: existingConfig?.httpProxy || ""
1067
+ });
1068
+ if (p.isCancel(httpProxy)) {
1069
+ p.cancel("Configuration cancelled.");
1070
+ return;
976
1071
  }
977
- });
978
- consola.debug("HTTP proxy configured from environment (per-URL)");
979
- } catch (err) {
980
- consola.debug("Proxy setup skipped:", err);
1072
+ const httpsProxy = await p.text({
1073
+ message: "HTTPS Proxy URL (leave empty to use HTTP proxy)",
1074
+ placeholder: "http://proxy:8080",
1075
+ initialValue: existingConfig?.httpsProxy || ""
1076
+ });
1077
+ if (p.isCancel(httpsProxy)) {
1078
+ p.cancel("Configuration cancelled.");
1079
+ return;
1080
+ }
1081
+ const noProxy = await p.text({
1082
+ message: "No Proxy (comma-separated hosts to bypass)",
1083
+ placeholder: "localhost,127.0.0.1,.local",
1084
+ initialValue: existingConfig?.noProxy || ""
1085
+ });
1086
+ if (p.isCancel(noProxy)) {
1087
+ p.cancel("Configuration cancelled.");
1088
+ return;
1089
+ }
1090
+ const enable = await p.confirm({
1091
+ message: "Enable proxy now?",
1092
+ initialValue: true
1093
+ });
1094
+ if (p.isCancel(enable)) {
1095
+ p.cancel("Configuration cancelled.");
1096
+ return;
1097
+ }
1098
+ await saveProxyConfig({
1099
+ enabled: enable,
1100
+ httpProxy: httpProxy || void 0,
1101
+ httpsProxy: httpsProxy || httpProxy || void 0,
1102
+ noProxy: noProxy || void 0
1103
+ });
1104
+ p.outro(`Proxy configuration saved${enable ? " and enabled" : ""}.`);
1105
+ }
981
1106
  }
982
- }
1107
+ });
983
1108
 
984
1109
  //#endregion
985
1110
  //#region src/lib/shell.ts
@@ -3354,7 +3479,7 @@ async function runServer(options$1) {
3354
3479
  state.zenApiKey = options$1.zenApiKey;
3355
3480
  consola.info("Using provided Zen API key");
3356
3481
  } else {
3357
- const { setupZenApiKey, loadZenAuth } = await import("./auth-wHA1Oitm.js");
3482
+ const { setupZenApiKey, loadZenAuth } = await import("./auth-CCwbOOQN.js");
3358
3483
  const existingAuth = await loadZenAuth();
3359
3484
  if (existingAuth) {
3360
3485
  state.zenApiKey = existingAuth.apiKey;
@@ -3367,7 +3492,7 @@ async function runServer(options$1) {
3367
3492
  } else if (options$1.antigravity) {
3368
3493
  consola.info("Google Antigravity mode enabled");
3369
3494
  state.antigravityMode = true;
3370
- const { loadAntigravityAuth, setupAntigravity, getCurrentAccount, hasApiKey, getApiKey: getApiKey$1, setOAuthCredentials } = await import("./auth-Ijg_vdBM.js");
3495
+ const { loadAntigravityAuth, setupAntigravity, getCurrentAccount, hasApiKey, getApiKey: getApiKey$1, setOAuthCredentials } = await import("./auth-B2lTFLSD.js");
3371
3496
  if (options$1.antigravityClientId && options$1.antigravityClientSecret) {
3372
3497
  setOAuthCredentials(options$1.antigravityClientId, options$1.antigravityClientSecret);
3373
3498
  consola.info("Using provided OAuth credentials from CLI");
@@ -3396,7 +3521,7 @@ async function runServer(options$1) {
3396
3521
  }
3397
3522
  if (!await getCurrentAccount() && !hasApiKey()) throw new Error("No enabled Antigravity accounts available");
3398
3523
  }
3399
- const { getAntigravityModels: getAntigravityModels$1 } = await import("./get-models-D9Mg0iWy.js");
3524
+ const { getAntigravityModels: getAntigravityModels$1 } = await import("./get-models-CmDpYUV-.js");
3400
3525
  const models = await getAntigravityModels$1();
3401
3526
  state.antigravityModels = models;
3402
3527
  consola.info(`Available Antigravity models: \n${models.data.map((model) => `- ${model.id}`).join("\n")}`);
@@ -3420,7 +3545,7 @@ async function runServer(options$1) {
3420
3545
  const { HTTPError: HTTPError$1 } = await import("./error-CsShqJjE.js");
3421
3546
  if (error instanceof HTTPError$1 && error.response.status === 401) {
3422
3547
  consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
3423
- const { clearGithubToken: clearGithubToken$1 } = await import("./token-DhdRMuOy.js");
3548
+ const { clearGithubToken: clearGithubToken$1 } = await import("./token-sYqHiHEd.js");
3424
3549
  await clearGithubToken$1();
3425
3550
  consola.info("Please restart to re-authenticate");
3426
3551
  }
@@ -3592,6 +3717,7 @@ const main = defineCommand({
3592
3717
  description: "A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements."
3593
3718
  },
3594
3719
  subCommands: {
3720
+ antigravity,
3595
3721
  auth,
3596
3722
  start,
3597
3723
  "check-usage": checkUsage,