copilot-api-plus 1.0.31 → 1.0.33
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 +30 -2
- package/dist/{auth-Ijg_vdBM.js → auth-B2lTFLSD.js} +3 -3
- package/dist/auth-CCwbOOQN.js +4 -0
- package/dist/{auth-y23hLerx.js → auth-CM_ilreU.js} +2 -2
- package/dist/{auth-y23hLerx.js.map → auth-CM_ilreU.js.map} +1 -1
- package/dist/{auth-OZNLGzjK.js → auth-T55-Bhoo.js} +2 -2
- package/dist/{auth-OZNLGzjK.js.map → auth-T55-Bhoo.js.map} +1 -1
- package/dist/get-models-CmDpYUV-.js +5 -0
- package/dist/{get-models-B5kAooWg.js → get-models-DMdiCNoU.js} +2 -2
- package/dist/{get-models-B5kAooWg.js.map → get-models-DMdiCNoU.js.map} +1 -1
- package/dist/main.js +1096 -923
- package/dist/main.js.map +1 -1
- package/dist/{paths-Ch0ixSo2.js → paths-CVYLp61D.js} +2 -2
- package/dist/{paths-Ch0ixSo2.js.map → paths-CVYLp61D.js.map} +1 -1
- package/dist/{token-BUmQ_BcM.js → token-ClgudjZm.js} +2 -2
- package/dist/{token-BUmQ_BcM.js.map → token-ClgudjZm.js.map} +1 -1
- package/dist/{token-DhdRMuOy.js → token-sYqHiHEd.js} +2 -2
- package/package.json +1 -1
- package/dist/auth-wHA1Oitm.js +0 -4
- package/dist/get-models-D9Mg0iWy.js +0 -5
package/dist/main.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { PATHS, ensurePaths } from "./paths-
|
|
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-
|
|
7
|
-
import { clearAntigravityAuth, disableCurrentAccount, getAntigravityAuthPath, getApiKey, getValidAccessToken, rotateAccount } from "./auth-
|
|
8
|
-
import { clearZenAuth, getZenAuthPath } from "./auth-
|
|
9
|
-
import { getAntigravityModels, getAntigravityUsage, isThinkingModel } from "./get-models-
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
182
|
-
process.
|
|
183
|
-
process.env.https_proxy = proxyConfig.httpsProxy;
|
|
139
|
+
function supportsAnsi() {
|
|
140
|
+
return process.stdout.isTTY;
|
|
184
141
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
process.env.no_proxy = proxyConfig.noProxy;
|
|
142
|
+
function dim(text) {
|
|
143
|
+
return supportsAnsi() ? `\x1b[2m${text}\x1b[0m` : text;
|
|
188
144
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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;
|
|
221
|
-
}
|
|
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;
|
|
229
|
-
}
|
|
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 });
|
|
299
|
-
}
|
|
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;
|
|
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;
|
|
315
164
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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);
|
|
321
187
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
consola.success("Logged out from OpenCode Zen");
|
|
325
|
-
consola.info(`Zen API key location: ${getZenAuthPath()}`);
|
|
326
|
-
return;
|
|
188
|
+
function _warn(message) {
|
|
189
|
+
console.error(`[dotenv@${version}][WARN] ${message}`);
|
|
327
190
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
consola.success("Logged out from Google Antigravity");
|
|
331
|
-
consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
|
|
332
|
-
return;
|
|
191
|
+
function _debug(message) {
|
|
192
|
+
console.log(`[dotenv@${version}][DEBUG] ${message}`);
|
|
333
193
|
}
|
|
334
|
-
|
|
335
|
-
|
|
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;
|
|
194
|
+
function _log(message) {
|
|
195
|
+
console.log(`[dotenv@${version}] ${message}`);
|
|
364
196
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
});
|
|
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 "";
|
|
403
201
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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;
|
|
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;
|
|
463
211
|
}
|
|
464
|
-
|
|
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;
|
|
212
|
+
throw error;
|
|
470
213
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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;
|
|
475
219
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
}
|
|
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;
|
|
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;
|
|
486
225
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
config$1.enabled = false;
|
|
494
|
-
await saveProxyConfig(config$1);
|
|
495
|
-
consola.success("Proxy disabled. Settings are preserved.");
|
|
496
|
-
return;
|
|
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;
|
|
497
232
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
233
|
+
return {
|
|
234
|
+
ciphertext,
|
|
235
|
+
key
|
|
236
|
+
};
|
|
237
|
+
}
|
|
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;
|
|
246
|
+
}
|
|
247
|
+
function _resolveHome(envPath) {
|
|
248
|
+
return envPath[0] === "~" ? path$1.join(os$1.homedir(), envPath.slice(1)) : envPath;
|
|
249
|
+
}
|
|
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));
|
|
511
274
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
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;
|
|
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;
|
|
283
|
+
}
|
|
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;
|
|
541
296
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
297
|
+
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
|
|
298
|
+
}
|
|
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);
|
|
311
|
+
}
|
|
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;
|
|
337
|
+
}
|
|
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];
|
|
549
352
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
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
|
+
}) });
|
|
379
|
+
|
|
380
|
+
//#endregion
|
|
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
|
+
}) });
|
|
560
392
|
|
|
561
393
|
//#endregion
|
|
562
|
-
//#region node_modules/dotenv/
|
|
563
|
-
var
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
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 }
|
|
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/
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
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
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
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
|
-
|
|
664
|
-
|
|
476
|
+
if (proxyConfig.httpsProxy) {
|
|
477
|
+
process.env.HTTPS_PROXY = proxyConfig.httpsProxy;
|
|
478
|
+
process.env.https_proxy = proxyConfig.httpsProxy;
|
|
479
|
+
}
|
|
480
|
+
if (proxyConfig.noProxy) {
|
|
481
|
+
process.env.NO_PROXY = proxyConfig.noProxy;
|
|
482
|
+
process.env.no_proxy = proxyConfig.noProxy;
|
|
483
|
+
}
|
|
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();
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
consola.debug("HTTP proxy configured from environment (per-URL)");
|
|
532
|
+
} catch (err) {
|
|
533
|
+
consola.debug("Proxy setup skipped:", err);
|
|
534
|
+
}
|
|
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)`);
|
|
548
|
+
}
|
|
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;
|
|
560
|
+
}
|
|
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)" : ""}`);
|
|
570
|
+
}
|
|
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;
|
|
665
581
|
}
|
|
666
|
-
|
|
667
|
-
|
|
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;
|
|
668
585
|
}
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
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();
|
|
684
616
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
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
|
+
})
|
|
688
659
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
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");
|
|
668
|
+
}
|
|
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"
|
|
698
690
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
691
|
+
},
|
|
692
|
+
run({ args }) {
|
|
693
|
+
return runAuth({
|
|
694
|
+
verbose: args.verbose,
|
|
695
|
+
showToken: args["show-token"]
|
|
696
|
+
});
|
|
697
|
+
}
|
|
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);
|
|
709
740
|
}
|
|
710
|
-
return DotenvModule.parse(decrypted);
|
|
711
741
|
}
|
|
712
|
-
|
|
713
|
-
|
|
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";
|
|
714
752
|
}
|
|
715
|
-
|
|
716
|
-
|
|
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;
|
|
717
769
|
}
|
|
718
|
-
|
|
719
|
-
|
|
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;
|
|
720
777
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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;
|
|
725
863
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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;
|
|
735
|
-
}
|
|
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
|
-
};
|
|
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;
|
|
761
869
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
else possibleVaultPath = path$1.resolve(process.cwd(), ".env.vault");
|
|
768
|
-
if (fs$1.existsSync(possibleVaultPath)) return possibleVaultPath;
|
|
769
|
-
return null;
|
|
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;
|
|
770
875
|
}
|
|
771
|
-
|
|
772
|
-
|
|
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;
|
|
773
881
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
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;
|
|
783
912
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
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)"
|
|
798
942
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
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"
|
|
807
998
|
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
if (
|
|
812
|
-
const
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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;
|
|
820
1011
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
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);
|
|
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
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
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
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
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
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
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
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
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
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
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
|
-
|
|
979
|
-
|
|
980
|
-
|
|
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
|
|
@@ -2037,30 +2162,66 @@ function createErrorResponse(type, message, status) {
|
|
|
2037
2162
|
* Create Anthropic-compatible message response using Antigravity
|
|
2038
2163
|
* Note: Both Gemini and Claude models use the same endpoint and Gemini-style format
|
|
2039
2164
|
*/
|
|
2165
|
+
const MAX_RETRIES = 5;
|
|
2040
2166
|
async function createAntigravityMessages(request) {
|
|
2041
|
-
const accessToken = await getValidAccessToken();
|
|
2042
|
-
if (!accessToken) return createErrorResponse("authentication_error", "No valid Antigravity access token available. Please run login first.", 401);
|
|
2043
2167
|
const endpoint = request.stream ? ANTIGRAVITY_STREAM_URL : ANTIGRAVITY_NO_STREAM_URL;
|
|
2044
2168
|
const body = buildGeminiRequest(request);
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
"
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2169
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
2170
|
+
const accessToken = await getValidAccessToken();
|
|
2171
|
+
if (!accessToken) return createErrorResponse("authentication_error", "No valid Antigravity access token available. Please run login first.", 401);
|
|
2172
|
+
consola.debug(`Antigravity request to ${endpoint} (attempt ${attempt + 1}/${MAX_RETRIES + 1})`);
|
|
2173
|
+
try {
|
|
2174
|
+
const response = await fetch(endpoint, {
|
|
2175
|
+
method: "POST",
|
|
2176
|
+
headers: {
|
|
2177
|
+
Host: ANTIGRAVITY_API_HOST,
|
|
2178
|
+
"User-Agent": ANTIGRAVITY_USER_AGENT,
|
|
2179
|
+
Authorization: `Bearer ${accessToken}`,
|
|
2180
|
+
"Content-Type": "application/json",
|
|
2181
|
+
"Accept-Encoding": "gzip"
|
|
2182
|
+
},
|
|
2183
|
+
body: JSON.stringify(body)
|
|
2184
|
+
});
|
|
2185
|
+
if (response.ok) return request.stream ? transformStreamResponse(response, request.model) : await transformNonStreamResponse(response, request.model);
|
|
2186
|
+
const errorResult = await handleApiError(response);
|
|
2187
|
+
if (errorResult.shouldRetry && attempt < MAX_RETRIES) {
|
|
2188
|
+
consola.info(`Rate limited, retrying in ${errorResult.retryDelayMs}ms...`);
|
|
2189
|
+
await sleep(errorResult.retryDelayMs);
|
|
2190
|
+
continue;
|
|
2191
|
+
}
|
|
2192
|
+
return errorResult.response;
|
|
2193
|
+
} catch (error) {
|
|
2194
|
+
consola.error("Antigravity messages request error:", error);
|
|
2195
|
+
if (attempt < MAX_RETRIES) {
|
|
2196
|
+
await sleep(500);
|
|
2197
|
+
continue;
|
|
2198
|
+
}
|
|
2199
|
+
return createErrorResponse("api_error", `Request failed: ${String(error)}`, 500);
|
|
2200
|
+
}
|
|
2063
2201
|
}
|
|
2202
|
+
return createErrorResponse("api_error", "Max retries exceeded", 429);
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Parse retry delay from error response
|
|
2206
|
+
*/
|
|
2207
|
+
function parseRetryDelay(errorText) {
|
|
2208
|
+
try {
|
|
2209
|
+
const details = JSON.parse(errorText).error?.details ?? [];
|
|
2210
|
+
for (const detail of details) {
|
|
2211
|
+
if (detail["@type"]?.includes("RetryInfo") && detail.retryDelay) {
|
|
2212
|
+
const match = /(\d+(?:\.\d+)?)s/.exec(detail.retryDelay);
|
|
2213
|
+
if (match) return Math.ceil(Number.parseFloat(match[1]) * 1e3);
|
|
2214
|
+
}
|
|
2215
|
+
if (detail.quotaResetDelay) {
|
|
2216
|
+
const match = /(\d+(?:\.\d+)?)(?:ms|s)/.exec(detail.quotaResetDelay);
|
|
2217
|
+
if (match) {
|
|
2218
|
+
const value = Number.parseFloat(match[1]);
|
|
2219
|
+
return detail.quotaResetDelay.includes("ms") ? Math.ceil(value) : Math.ceil(value * 1e3);
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
} catch {}
|
|
2224
|
+
return 500;
|
|
2064
2225
|
}
|
|
2065
2226
|
/**
|
|
2066
2227
|
* Handle API error response
|
|
@@ -2069,8 +2230,19 @@ async function handleApiError(response) {
|
|
|
2069
2230
|
const errorText = await response.text();
|
|
2070
2231
|
consola.error(`Antigravity error: ${response.status} ${errorText}`);
|
|
2071
2232
|
if (response.status === 403) await disableCurrentAccount();
|
|
2072
|
-
if (response.status === 429 || response.status === 503)
|
|
2073
|
-
|
|
2233
|
+
if (response.status === 429 || response.status === 503) {
|
|
2234
|
+
await rotateAccount();
|
|
2235
|
+
return {
|
|
2236
|
+
shouldRetry: true,
|
|
2237
|
+
retryDelayMs: parseRetryDelay(errorText),
|
|
2238
|
+
response: createErrorResponse("api_error", `Antigravity API error: ${response.status}`, response.status)
|
|
2239
|
+
};
|
|
2240
|
+
}
|
|
2241
|
+
return {
|
|
2242
|
+
shouldRetry: false,
|
|
2243
|
+
retryDelayMs: 0,
|
|
2244
|
+
response: createErrorResponse("api_error", `Antigravity API error: ${response.status}`, response.status)
|
|
2245
|
+
};
|
|
2074
2246
|
}
|
|
2075
2247
|
/**
|
|
2076
2248
|
* Emit SSE event to controller based on stream event type
|
|
@@ -3354,7 +3526,7 @@ async function runServer(options$1) {
|
|
|
3354
3526
|
state.zenApiKey = options$1.zenApiKey;
|
|
3355
3527
|
consola.info("Using provided Zen API key");
|
|
3356
3528
|
} else {
|
|
3357
|
-
const { setupZenApiKey, loadZenAuth } = await import("./auth-
|
|
3529
|
+
const { setupZenApiKey, loadZenAuth } = await import("./auth-CCwbOOQN.js");
|
|
3358
3530
|
const existingAuth = await loadZenAuth();
|
|
3359
3531
|
if (existingAuth) {
|
|
3360
3532
|
state.zenApiKey = existingAuth.apiKey;
|
|
@@ -3367,7 +3539,7 @@ async function runServer(options$1) {
|
|
|
3367
3539
|
} else if (options$1.antigravity) {
|
|
3368
3540
|
consola.info("Google Antigravity mode enabled");
|
|
3369
3541
|
state.antigravityMode = true;
|
|
3370
|
-
const { loadAntigravityAuth, setupAntigravity, getCurrentAccount, hasApiKey, getApiKey: getApiKey$1, setOAuthCredentials } = await import("./auth-
|
|
3542
|
+
const { loadAntigravityAuth, setupAntigravity, getCurrentAccount, hasApiKey, getApiKey: getApiKey$1, setOAuthCredentials } = await import("./auth-B2lTFLSD.js");
|
|
3371
3543
|
if (options$1.antigravityClientId && options$1.antigravityClientSecret) {
|
|
3372
3544
|
setOAuthCredentials(options$1.antigravityClientId, options$1.antigravityClientSecret);
|
|
3373
3545
|
consola.info("Using provided OAuth credentials from CLI");
|
|
@@ -3396,7 +3568,7 @@ async function runServer(options$1) {
|
|
|
3396
3568
|
}
|
|
3397
3569
|
if (!await getCurrentAccount() && !hasApiKey()) throw new Error("No enabled Antigravity accounts available");
|
|
3398
3570
|
}
|
|
3399
|
-
const { getAntigravityModels: getAntigravityModels$1 } = await import("./get-models-
|
|
3571
|
+
const { getAntigravityModels: getAntigravityModels$1 } = await import("./get-models-CmDpYUV-.js");
|
|
3400
3572
|
const models = await getAntigravityModels$1();
|
|
3401
3573
|
state.antigravityModels = models;
|
|
3402
3574
|
consola.info(`Available Antigravity models: \n${models.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
@@ -3420,7 +3592,7 @@ async function runServer(options$1) {
|
|
|
3420
3592
|
const { HTTPError: HTTPError$1 } = await import("./error-CsShqJjE.js");
|
|
3421
3593
|
if (error instanceof HTTPError$1 && error.response.status === 401) {
|
|
3422
3594
|
consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
|
|
3423
|
-
const { clearGithubToken: clearGithubToken$1 } = await import("./token-
|
|
3595
|
+
const { clearGithubToken: clearGithubToken$1 } = await import("./token-sYqHiHEd.js");
|
|
3424
3596
|
await clearGithubToken$1();
|
|
3425
3597
|
consola.info("Please restart to re-authenticate");
|
|
3426
3598
|
}
|
|
@@ -3592,6 +3764,7 @@ const main = defineCommand({
|
|
|
3592
3764
|
description: "A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements."
|
|
3593
3765
|
},
|
|
3594
3766
|
subCommands: {
|
|
3767
|
+
antigravity,
|
|
3595
3768
|
auth,
|
|
3596
3769
|
start,
|
|
3597
3770
|
"check-usage": checkUsage,
|