@nick3/copilot-api 1.9.2 → 1.10.4
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 +114 -89
- package/README.zh-CN.md +114 -86
- package/dist/{account-MllYSdRC.js → account-COtMmvzU.js} +20 -24
- package/dist/account-COtMmvzU.js.map +1 -0
- package/dist/admin/assets/index-CBMFCvqO.css +1 -0
- package/dist/admin/assets/index-DG4TRVMu.js +110 -0
- package/dist/admin/index.html +2 -2
- package/dist/{auth-DZoQA-kn.js → auth-B0y-2njL.js} +103 -112
- package/dist/auth-B0y-2njL.js.map +1 -0
- package/dist/{check-usage-DEbsehjH.js → check-usage-DdevqHE5.js} +6 -7
- package/dist/{check-usage-DEbsehjH.js.map → check-usage-DdevqHE5.js.map} +1 -1
- package/dist/{debug-BJfZVBB7.js → debug-BMo6ltbp.js} +6 -6
- package/dist/debug-BMo6ltbp.js.map +1 -0
- package/dist/{get-copilot-token-4mCKt94e.js → get-copilot-token-8Rm-rVsp.js} +3 -4
- package/dist/{get-copilot-token-4mCKt94e.js.map → get-copilot-token-8Rm-rVsp.js.map} +1 -1
- package/dist/main.js +6 -7
- package/dist/main.js.map +1 -1
- package/dist/{paths-DGlr310R.js → paths-CclKwouX.js} +3 -5
- package/dist/{paths-DGlr310R.js.map → paths-CclKwouX.js.map} +1 -1
- package/dist/{poll-access-token-Dvk6Ho0R.js → poll-access-token-BAgM2-7k.js} +65 -21
- package/dist/poll-access-token-BAgM2-7k.js.map +1 -0
- package/dist/{accounts-manager-BM66oT38.js → proxy-BwmADhKh.js} +494 -52
- package/dist/proxy-BwmADhKh.js.map +1 -0
- package/dist/request-outbound-BJjWS_jF.js +2 -0
- package/dist/{request-outbound-qyTeXbzy.js → request-outbound-Pu1kp2x8.js} +16 -9
- package/dist/request-outbound-Pu1kp2x8.js.map +1 -0
- package/dist/{server-DR9ZR_MN.js → server-DxQsi1x2.js} +2106 -935
- package/dist/server-DxQsi1x2.js.map +1 -0
- package/dist/{start-DDhYUFQR.js → start-8QHzPrcg.js} +11 -60
- package/dist/start-8QHzPrcg.js.map +1 -0
- package/package.json +20 -7
- package/dist/account-MllYSdRC.js.map +0 -1
- package/dist/accounts-manager-BM66oT38.js.map +0 -1
- package/dist/admin/assets/index-8eGib92I.js +0 -107
- package/dist/admin/assets/index-B2qj1asn.css +0 -1
- package/dist/auth-DZoQA-kn.js.map +0 -1
- package/dist/debug-BJfZVBB7.js.map +0 -1
- package/dist/poll-access-token-Dvk6Ho0R.js.map +0 -1
- package/dist/request-outbound-DhI9-SrV.js +0 -4
- package/dist/request-outbound-qyTeXbzy.js.map +0 -1
- package/dist/server-DR9ZR_MN.js.map +0 -1
- package/dist/start-DDhYUFQR.js.map +0 -1
package/dist/admin/index.html
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
}
|
|
19
19
|
})()
|
|
20
20
|
</script>
|
|
21
|
-
<script type="module" crossorigin src="/admin/assets/index-
|
|
22
|
-
<link rel="stylesheet" crossorigin href="/admin/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/admin/assets/index-DG4TRVMu.js"></script>
|
|
22
|
+
<link rel="stylesheet" crossorigin href="/admin/assets/index-CBMFCvqO.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
25
25
|
<div id="root"></div>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { d as loadRegistry, g as saveRegistry, h as saveAccountToken, l as listAccountsFromRegistry, m as removeAccountToken, n as parseAccountType, p as removeAccountFromRegistry, r as addAccountToRegistry, u as loadAccountToken } from "./account-
|
|
3
|
-
import { r as ensurePaths } from "./paths-
|
|
1
|
+
import { A as state, g as getCopilotUsage, h as getDeviceCode, m as getGitHubUser, t as pollAccessToken } from "./poll-access-token-BAgM2-7k.js";
|
|
2
|
+
import { d as loadRegistry, g as saveRegistry, h as saveAccountToken, l as listAccountsFromRegistry, m as removeAccountToken, n as parseAccountType, p as removeAccountFromRegistry, r as addAccountToRegistry, u as loadAccountToken } from "./account-COtMmvzU.js";
|
|
3
|
+
import { r as ensurePaths } from "./paths-CclKwouX.js";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import consola from "consola";
|
|
6
|
-
|
|
7
6
|
//#region src/auth.ts
|
|
8
7
|
/**
|
|
9
8
|
* Fetch quota info for an account (used by auth ls -q)
|
|
@@ -89,110 +88,6 @@ const authAdd = defineCommand({
|
|
|
89
88
|
}
|
|
90
89
|
});
|
|
91
90
|
/**
|
|
92
|
-
* auth ls - List all registered accounts
|
|
93
|
-
*/
|
|
94
|
-
const authLs = defineCommand({
|
|
95
|
-
meta: {
|
|
96
|
-
name: "ls",
|
|
97
|
-
description: "List all registered accounts"
|
|
98
|
-
},
|
|
99
|
-
args: {
|
|
100
|
-
"show-quota": {
|
|
101
|
-
alias: "q",
|
|
102
|
-
type: "boolean",
|
|
103
|
-
default: false,
|
|
104
|
-
description: "Show quota information (requires API call)"
|
|
105
|
-
},
|
|
106
|
-
verbose: {
|
|
107
|
-
alias: "v",
|
|
108
|
-
type: "boolean",
|
|
109
|
-
default: false,
|
|
110
|
-
description: "Enable verbose logging"
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
async run({ args }) {
|
|
114
|
-
if (args.verbose) consola.level = 5;
|
|
115
|
-
await ensurePaths();
|
|
116
|
-
const accounts = await listAccountsFromRegistry();
|
|
117
|
-
if (accounts.length === 0) {
|
|
118
|
-
consola.info("No accounts registered. Use 'auth add' to add an account.");
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
consola.info(`Found ${accounts.length} account(s):\n`);
|
|
122
|
-
for (const [i, account] of accounts.entries()) {
|
|
123
|
-
const addedDate = new Date(account.addedAt).toLocaleString();
|
|
124
|
-
const quotaInfo = args["show-quota"] ? await fetchQuotaInfo(account) : "";
|
|
125
|
-
console.log(` ${i + 1}. ${account.id} (${account.accountType})${quotaInfo}`);
|
|
126
|
-
console.log(` Added: ${addedDate}\n`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
/**
|
|
131
|
-
* auth rm - Remove an account
|
|
132
|
-
*/
|
|
133
|
-
const authRm = defineCommand({
|
|
134
|
-
meta: {
|
|
135
|
-
name: "rm",
|
|
136
|
-
description: "Remove an account"
|
|
137
|
-
},
|
|
138
|
-
args: {
|
|
139
|
-
target: {
|
|
140
|
-
type: "positional",
|
|
141
|
-
description: "Account ID or index (1-based)",
|
|
142
|
-
required: true
|
|
143
|
-
},
|
|
144
|
-
force: {
|
|
145
|
-
alias: "f",
|
|
146
|
-
type: "boolean",
|
|
147
|
-
default: false,
|
|
148
|
-
description: "Skip confirmation prompt"
|
|
149
|
-
},
|
|
150
|
-
verbose: {
|
|
151
|
-
alias: "v",
|
|
152
|
-
type: "boolean",
|
|
153
|
-
default: false,
|
|
154
|
-
description: "Enable verbose logging"
|
|
155
|
-
}
|
|
156
|
-
},
|
|
157
|
-
async run({ args }) {
|
|
158
|
-
if (args.verbose) consola.level = 5;
|
|
159
|
-
await ensurePaths();
|
|
160
|
-
const target = args.target;
|
|
161
|
-
const accounts = await listAccountsFromRegistry();
|
|
162
|
-
if (accounts.length === 0) {
|
|
163
|
-
consola.error("No accounts to remove.");
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
let accountToRemove;
|
|
167
|
-
const index = Number.parseInt(target, 10);
|
|
168
|
-
if (!Number.isNaN(index) && index >= 1 && index <= accounts.length) accountToRemove = {
|
|
169
|
-
id: accounts[index - 1].id,
|
|
170
|
-
index: index - 1
|
|
171
|
-
};
|
|
172
|
-
else {
|
|
173
|
-
const foundIndex = accounts.findIndex((acc) => acc.id === target);
|
|
174
|
-
if (foundIndex !== -1) accountToRemove = {
|
|
175
|
-
id: accounts[foundIndex].id,
|
|
176
|
-
index: foundIndex
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
if (!accountToRemove) {
|
|
180
|
-
consola.error(`Account "${target}" not found.`);
|
|
181
|
-
consola.info("Use 'auth ls' to see available accounts.");
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
if (!args.force) {
|
|
185
|
-
if (!await consola.prompt(`Are you sure you want to remove account "${accountToRemove.id}"?`, { type: "confirm" })) {
|
|
186
|
-
consola.info("Cancelled.");
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
await removeAccountToken(accountToRemove.id);
|
|
191
|
-
await removeAccountFromRegistry(accountToRemove.id);
|
|
192
|
-
consola.success(`Account "${accountToRemove.id}" removed.`);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
/**
|
|
196
91
|
* Main auth command with subcommands
|
|
197
92
|
*/
|
|
198
93
|
const auth = defineCommand({
|
|
@@ -202,8 +97,104 @@ const auth = defineCommand({
|
|
|
202
97
|
},
|
|
203
98
|
subCommands: {
|
|
204
99
|
add: authAdd,
|
|
205
|
-
ls:
|
|
206
|
-
|
|
100
|
+
ls: defineCommand({
|
|
101
|
+
meta: {
|
|
102
|
+
name: "ls",
|
|
103
|
+
description: "List all registered accounts"
|
|
104
|
+
},
|
|
105
|
+
args: {
|
|
106
|
+
"show-quota": {
|
|
107
|
+
alias: "q",
|
|
108
|
+
type: "boolean",
|
|
109
|
+
default: false,
|
|
110
|
+
description: "Show quota information (requires API call)"
|
|
111
|
+
},
|
|
112
|
+
verbose: {
|
|
113
|
+
alias: "v",
|
|
114
|
+
type: "boolean",
|
|
115
|
+
default: false,
|
|
116
|
+
description: "Enable verbose logging"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
async run({ args }) {
|
|
120
|
+
if (args.verbose) consola.level = 5;
|
|
121
|
+
await ensurePaths();
|
|
122
|
+
const accounts = await listAccountsFromRegistry();
|
|
123
|
+
if (accounts.length === 0) {
|
|
124
|
+
consola.info("No accounts registered. Use 'auth add' to add an account.");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
consola.info(`Found ${accounts.length} account(s):\n`);
|
|
128
|
+
for (const [i, account] of accounts.entries()) {
|
|
129
|
+
const addedDate = new Date(account.addedAt).toLocaleString();
|
|
130
|
+
const quotaInfo = args["show-quota"] ? await fetchQuotaInfo(account) : "";
|
|
131
|
+
console.log(` ${i + 1}. ${account.id} (${account.accountType})${quotaInfo}`);
|
|
132
|
+
console.log(` Added: ${addedDate}\n`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}),
|
|
136
|
+
rm: defineCommand({
|
|
137
|
+
meta: {
|
|
138
|
+
name: "rm",
|
|
139
|
+
description: "Remove an account"
|
|
140
|
+
},
|
|
141
|
+
args: {
|
|
142
|
+
target: {
|
|
143
|
+
type: "positional",
|
|
144
|
+
description: "Account ID or index (1-based)",
|
|
145
|
+
required: true
|
|
146
|
+
},
|
|
147
|
+
force: {
|
|
148
|
+
alias: "f",
|
|
149
|
+
type: "boolean",
|
|
150
|
+
default: false,
|
|
151
|
+
description: "Skip confirmation prompt"
|
|
152
|
+
},
|
|
153
|
+
verbose: {
|
|
154
|
+
alias: "v",
|
|
155
|
+
type: "boolean",
|
|
156
|
+
default: false,
|
|
157
|
+
description: "Enable verbose logging"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
async run({ args }) {
|
|
161
|
+
if (args.verbose) consola.level = 5;
|
|
162
|
+
await ensurePaths();
|
|
163
|
+
const target = args.target;
|
|
164
|
+
const accounts = await listAccountsFromRegistry();
|
|
165
|
+
if (accounts.length === 0) {
|
|
166
|
+
consola.error("No accounts to remove.");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
let accountToRemove;
|
|
170
|
+
const index = Number.parseInt(target, 10);
|
|
171
|
+
if (!Number.isNaN(index) && index >= 1 && index <= accounts.length) accountToRemove = {
|
|
172
|
+
id: accounts[index - 1].id,
|
|
173
|
+
index: index - 1
|
|
174
|
+
};
|
|
175
|
+
else {
|
|
176
|
+
const foundIndex = accounts.findIndex((acc) => acc.id === target);
|
|
177
|
+
if (foundIndex !== -1) accountToRemove = {
|
|
178
|
+
id: accounts[foundIndex].id,
|
|
179
|
+
index: foundIndex
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (!accountToRemove) {
|
|
183
|
+
consola.error(`Account "${target}" not found.`);
|
|
184
|
+
consola.info("Use 'auth ls' to see available accounts.");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (!args.force) {
|
|
188
|
+
if (!await consola.prompt(`Are you sure you want to remove account "${accountToRemove.id}"?`, { type: "confirm" })) {
|
|
189
|
+
consola.info("Cancelled.");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
await removeAccountToken(accountToRemove.id);
|
|
194
|
+
await removeAccountFromRegistry(accountToRemove.id);
|
|
195
|
+
consola.success(`Account "${accountToRemove.id}" removed.`);
|
|
196
|
+
}
|
|
197
|
+
})
|
|
207
198
|
},
|
|
208
199
|
args: {
|
|
209
200
|
"account-type": {
|
|
@@ -229,7 +220,7 @@ const auth = defineCommand({
|
|
|
229
220
|
if (!(firstArg === "add" || firstArg === "ls" || firstArg === "rm") && authAdd.run) await authAdd.run(ctx);
|
|
230
221
|
}
|
|
231
222
|
});
|
|
232
|
-
|
|
233
223
|
//#endregion
|
|
234
224
|
export { auth };
|
|
235
|
-
|
|
225
|
+
|
|
226
|
+
//# sourceMappingURL=auth-B0y-2njL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-B0y-2njL.js","names":[],"sources":["../src/auth.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport {\n addAccountToRegistry,\n listAccountsFromRegistry,\n loadAccountToken,\n loadRegistry,\n removeAccountFromRegistry,\n removeAccountToken,\n saveAccountToken,\n saveRegistry,\n} from \"./lib/accounts-registry\"\nimport { ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport {\n parseAccountType,\n type AccountMeta,\n type AccountType,\n} from \"./lib/types/account\"\nimport { getCopilotUsage } from \"./services/github/get-copilot-usage\"\nimport { getDeviceCode } from \"./services/github/get-device-code\"\nimport { getGitHubUser } from \"./services/github/get-user\"\nimport { pollAccessToken } from \"./services/github/poll-access-token\"\n\n/**\n * Fetch quota info for an account (used by auth ls -q)\n */\nasync function fetchQuotaInfo(account: AccountMeta): Promise<string> {\n try {\n const token = await loadAccountToken(account.id)\n if (!token) {\n return \" | Quota: (no token)\"\n }\n\n const usage = await getCopilotUsage({\n githubToken: token,\n accountType: account.accountType,\n })\n const premium = usage.quota_snapshots.premium_interactions\n\n return premium.unlimited ?\n \" | Quota: unlimited\"\n : ` | Quota: ${premium.remaining}/${premium.entitlement}`\n } catch (error) {\n consola.debug(`Failed to fetch quota for ${account.id}:`, error)\n return \" | Quota: (failed to fetch)\"\n }\n}\n\n/**\n * auth add - Add a new GitHub Copilot account\n */\nconst authAdd = defineCommand({\n meta: {\n name: \"add\",\n description: \"Add a new GitHub Copilot account\",\n },\n args: {\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type (individual, business, enterprise)\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token after auth\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = args[\"show-token\"]\n\n let accountType: AccountType\n try {\n accountType = parseAccountType(args[\"account-type\"])\n } catch (error) {\n consola.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n }\n\n await ensurePaths()\n\n // Start device code flow\n consola.info(\"Starting GitHub device code authentication...\")\n const deviceResponse = await getDeviceCode()\n consola.debug(\"Device code response:\", deviceResponse)\n\n consola.info(\n `Please enter the code \"${deviceResponse.user_code}\" at ${deviceResponse.verification_uri}`,\n )\n\n // Poll for access token\n const token = await pollAccessToken(deviceResponse)\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n\n // Get user info to determine account ID\n const user = await getGitHubUser({ githubToken: token, accountType })\n const accountId = user.login\n\n // Save token and check if account already exists\n await saveAccountToken(accountId, token)\n const existingAccounts = await listAccountsFromRegistry()\n const alreadyExists = existingAccounts.some((acc) => acc.id === accountId)\n\n if (alreadyExists) {\n // Touch registry file so a running server can hot-reload updated tokens.\n await saveRegistry(await loadRegistry())\n\n consola.success(\n `Account \"${accountId}\" already exists. Token has been updated.`,\n )\n } else {\n await addAccountToRegistry({\n id: accountId,\n accountType,\n addedAt: Date.now(),\n })\n consola.success(`Account \"${accountId}\" added successfully!`)\n }\n\n consola.info(`Account type: ${accountType}`)\n },\n})\n\n/**\n * auth ls - List all registered accounts\n */\nconst authLs = defineCommand({\n meta: {\n name: \"ls\",\n description: \"List all registered accounts\",\n },\n args: {\n \"show-quota\": {\n alias: \"q\",\n type: \"boolean\",\n default: false,\n description: \"Show quota information (requires API call)\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n }\n\n await ensurePaths()\n\n const accounts = await listAccountsFromRegistry()\n\n if (accounts.length === 0) {\n consola.info(\"No accounts registered. Use 'auth add' to add an account.\")\n return\n }\n\n consola.info(`Found ${accounts.length} account(s):\\n`)\n\n for (const [i, account] of accounts.entries()) {\n const addedDate = new Date(account.addedAt).toLocaleString()\n\n const quotaInfo = args[\"show-quota\"] ? await fetchQuotaInfo(account) : \"\"\n\n console.log(\n ` ${i + 1}. ${account.id} (${account.accountType})${quotaInfo}`,\n )\n console.log(` Added: ${addedDate}\\n`)\n }\n },\n})\n\n/**\n * auth rm - Remove an account\n */\nconst authRm = defineCommand({\n meta: {\n name: \"rm\",\n description: \"Remove an account\",\n },\n args: {\n target: {\n type: \"positional\",\n description: \"Account ID or index (1-based)\",\n required: true,\n },\n force: {\n alias: \"f\",\n type: \"boolean\",\n default: false,\n description: \"Skip confirmation prompt\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n },\n async run({ args }) {\n if (args.verbose) {\n consola.level = 5\n }\n\n await ensurePaths()\n\n const target = args.target\n const accounts = await listAccountsFromRegistry()\n\n if (accounts.length === 0) {\n consola.error(\"No accounts to remove.\")\n return\n }\n\n // Determine account to remove (by ID or index)\n let accountToRemove: { id: string; index: number } | undefined\n\n // Try parsing as index (1-based)\n const index = Number.parseInt(target, 10)\n if (!Number.isNaN(index) && index >= 1 && index <= accounts.length) {\n accountToRemove = { id: accounts[index - 1].id, index: index - 1 }\n } else {\n // Try finding by ID\n const foundIndex = accounts.findIndex((acc) => acc.id === target)\n if (foundIndex !== -1) {\n accountToRemove = { id: accounts[foundIndex].id, index: foundIndex }\n }\n }\n\n if (!accountToRemove) {\n consola.error(`Account \"${target}\" not found.`)\n consola.info(\"Use 'auth ls' to see available accounts.\")\n return\n }\n\n // Confirmation\n if (!args.force) {\n const confirmed = await consola.prompt(\n `Are you sure you want to remove account \"${accountToRemove.id}\"?`,\n { type: \"confirm\" },\n )\n if (!confirmed) {\n consola.info(\"Cancelled.\")\n return\n }\n }\n\n // Remove token file and registry entry\n await removeAccountToken(accountToRemove.id)\n await removeAccountFromRegistry(accountToRemove.id)\n\n consola.success(`Account \"${accountToRemove.id}\" removed.`)\n },\n})\n\n/**\n * Main auth command with subcommands\n */\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Manage GitHub Copilot accounts\",\n },\n subCommands: {\n add: authAdd,\n ls: authLs,\n rm: authRm,\n },\n args: {\n // Legacy args for backward compatibility (when no subcommand)\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type (individual, business, enterprise)\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token after auth\",\n },\n },\n async run(ctx) {\n // Check if a subcommand was specified in rawArgs.\n // Only treat the *first* raw arg as a subcommand to avoid false positives\n // when flags accept values like \"add\"/\"ls\"/\"rm\".\n const firstArg = ctx.rawArgs[0]\n const hasSubCommand =\n firstArg === \"add\" || firstArg === \"ls\" || firstArg === \"rm\"\n\n // Backward compatibility: if no subcommand, run 'add'\n if (!hasSubCommand && authAdd.run) {\n await authAdd.run(ctx)\n }\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { _ as HTTPError, g as getCopilotUsage, h as getDeviceCode,
|
|
2
|
-
import { r as ensurePaths, t as PATHS } from "./paths-
|
|
3
|
-
import "./get-copilot-token-
|
|
1
|
+
import { A as state, _ as HTTPError, g as getCopilotUsage, h as getDeviceCode, m as getGitHubUser, t as pollAccessToken } from "./poll-access-token-BAgM2-7k.js";
|
|
2
|
+
import { r as ensurePaths, t as PATHS } from "./paths-CclKwouX.js";
|
|
3
|
+
import "./get-copilot-token-8Rm-rVsp.js";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import consola from "consola";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
7
|
-
|
|
8
7
|
//#region src/lib/token.ts
|
|
9
8
|
const readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8");
|
|
10
9
|
const writeGithubToken = (token) => fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token);
|
|
@@ -37,10 +36,10 @@ async function setupGitHubToken(options) {
|
|
|
37
36
|
}
|
|
38
37
|
async function logUser() {
|
|
39
38
|
const user = await getGitHubUser();
|
|
39
|
+
state.userName = user.login;
|
|
40
40
|
consola.info(`Logged in as ${user.login}`);
|
|
41
41
|
state.copilotApiUrl = (await getCopilotUsage()).endpoints.api;
|
|
42
42
|
}
|
|
43
|
-
|
|
44
43
|
//#endregion
|
|
45
44
|
//#region src/check-usage.ts
|
|
46
45
|
const checkUsage = defineCommand({
|
|
@@ -76,7 +75,7 @@ const checkUsage = defineCommand({
|
|
|
76
75
|
}
|
|
77
76
|
}
|
|
78
77
|
});
|
|
79
|
-
|
|
80
78
|
//#endregion
|
|
81
79
|
export { checkUsage };
|
|
82
|
-
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=check-usage-DdevqHE5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-usage-
|
|
1
|
+
{"version":3,"file":"check-usage-DdevqHE5.js","names":[],"sources":["../src/lib/token.ts","../src/check-usage.ts"],"sourcesContent":["import consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport { setTimeout as delay } from \"node:timers/promises\"\n\nimport { isOpencodeOauthApp } from \"~/lib/api-config\"\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nlet copilotRefreshLoopController: AbortController | null = null\n\nexport const stopCopilotRefreshLoop = () => {\n if (!copilotRefreshLoopController) {\n return\n }\n\n copilotRefreshLoopController.abort()\n copilotRefreshLoopController = null\n}\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\nexport const setupCopilotToken = async () => {\n if (isOpencodeOauthApp()) {\n if (!state.githubToken) throw new Error(`opencode token not found`)\n\n state.copilotToken = state.githubToken\n\n consola.debug(\"GitHub Copilot token set from opencode auth token\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", state.copilotToken)\n }\n\n stopCopilotRefreshLoop()\n return\n }\n\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n stopCopilotRefreshLoop()\n\n const controller = new AbortController()\n copilotRefreshLoopController = controller\n\n runCopilotRefreshLoop(refresh_in, controller.signal)\n .catch(() => {\n consola.warn(\"Copilot token refresh loop stopped\")\n })\n .finally(() => {\n if (copilotRefreshLoopController === controller) {\n copilotRefreshLoopController = null\n }\n })\n}\n\nconst REFRESH_POLL_INTERVAL_MS = 15_000\nconst EARLY_REFRESH_BUFFER_MS = 60_000\nconst RETRY_REFRESH_DELAY_MS = 15_000\nconst MIN_REFRESH_DELAY_MS = 1_000\n\nexport const getRefreshDeadlineMs = (\n refreshIn: number,\n nowMs: number = Date.now(),\n) =>\n nowMs\n + Math.max(refreshIn * 1000 - EARLY_REFRESH_BUFFER_MS, MIN_REFRESH_DELAY_MS)\n\n// Use short wall-clock chunks so the next wake after sleep notices elapsed time\n// quickly, without relying on the server's absolute expires_at matching local time.\nexport const getRefreshPollDelayMs = (\n refreshAtMs: number,\n nowMs: number = Date.now(),\n) => Math.min(Math.max(refreshAtMs - nowMs, 0), REFRESH_POLL_INTERVAL_MS)\n\nconst runCopilotRefreshLoop = async (\n refreshIn: number,\n signal: AbortSignal,\n) => {\n let refreshAtMs = getRefreshDeadlineMs(refreshIn)\n\n while (!signal.aborted) {\n const nextDelayMs = getRefreshPollDelayMs(refreshAtMs)\n if (nextDelayMs > 0) {\n await delay(nextDelayMs, undefined, { signal })\n continue\n }\n\n consola.debug(\"Refreshing Copilot token\")\n\n try {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n refreshAtMs = getRefreshDeadlineMs(refresh_in)\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n refreshAtMs = Date.now() + RETRY_REFRESH_DELAY_MS\n consola.warn(\n `Retrying Copilot token refresh in ${RETRY_REFRESH_DELAY_MS / 1000}s`,\n )\n }\n }\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nexport async function logUser() {\n const user = await getGitHubUser()\n state.userName = user.login\n consola.info(`Logged in as ${user.login}`)\n\n const copilotUser = await getCopilotUsage()\n state.copilotApiUrl = copilotUser.endpoints.api\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\nimport {\n getCopilotUsage,\n type QuotaDetail,\n} from \"./services/github/get-copilot-usage\"\n\nexport const checkUsage = defineCommand({\n meta: {\n name: \"check-usage\",\n description: \"Show current GitHub Copilot usage/quota information\",\n },\n async run() {\n await ensurePaths()\n await setupGitHubToken()\n try {\n const usage = await getCopilotUsage()\n const premium = usage.quota_snapshots.premium_interactions\n const premiumTotal = premium.entitlement\n const premiumUsed = premiumTotal - premium.remaining\n const premiumPercentUsed =\n premiumTotal > 0 ? (premiumUsed / premiumTotal) * 100 : 0\n const premiumPercentRemaining = premium.percent_remaining\n\n // Helper to summarize a quota snapshot\n function summarizeQuota(name: string, snap: QuotaDetail | undefined) {\n if (!snap) return `${name}: N/A`\n const total = snap.entitlement\n const used = total - snap.remaining\n const percentUsed = total > 0 ? (used / total) * 100 : 0\n const percentRemaining = snap.percent_remaining\n return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`\n }\n\n const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`\n const chatLine = summarizeQuota(\"Chat\", usage.quota_snapshots.chat)\n const completionsLine = summarizeQuota(\n \"Completions\",\n usage.quota_snapshots.completions,\n )\n\n consola.box(\n `Copilot Usage (plan: ${usage.copilot_plan})\\n`\n + `Quota resets: ${usage.quota_reset_date}\\n`\n + `\\nQuotas:\\n`\n + ` ${premiumLine}\\n`\n + ` ${chatLine}\\n`\n + ` ${completionsLine}`,\n )\n } catch (err) {\n consola.error(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n"],"mappings":";;;;;;;AA0BA,MAAM,wBAAwB,GAAG,SAAS,MAAM,mBAAmB,OAAO;AAE1E,MAAM,oBAAoB,UACxB,GAAG,UAAU,MAAM,mBAAmB,MAAM;AAkG9C,eAAsB,iBACpB,SACe;CACf,IAAI;EACF,MAAM,cAAc,MAAM,iBAAiB;EAE3C,IAAI,eAAe,CAAC,SAAS,OAAO;GAClC,MAAM,cAAc;GACpB,IAAI,MAAM,WACR,QAAQ,KAAK,iBAAiB,YAAY;GAE5C,MAAM,SAAS;GAEf;;EAGF,QAAQ,KAAK,0CAA0C;EACvD,MAAM,WAAW,MAAM,eAAe;EACtC,QAAQ,MAAM,yBAAyB,SAAS;EAEhD,QAAQ,KACN,0BAA0B,SAAS,UAAU,OAAO,SAAS,mBAC9D;EAED,MAAM,QAAQ,MAAM,gBAAgB,SAAS;EAC7C,MAAM,iBAAiB,MAAM;EAC7B,MAAM,cAAc;EAEpB,IAAI,MAAM,WACR,QAAQ,KAAK,iBAAiB,MAAM;EAEtC,MAAM,SAAS;UACR,OAAO;EACd,IAAI,iBAAiB,WAAW;GAC9B,QAAQ,MAAM,+BAA+B,MAAM,MAAM,SAAS,MAAM,CAAC;GACzE,MAAM;;EAGR,QAAQ,MAAM,+BAA+B,MAAM;EACnD,MAAM;;;AAIV,eAAsB,UAAU;CAC9B,MAAM,OAAO,MAAM,eAAe;CAClC,MAAM,WAAW,KAAK;CACtB,QAAQ,KAAK,gBAAgB,KAAK,QAAQ;CAG1C,MAAM,iBAAgB,MADI,iBAAiB,EACT,UAAU;;;;ACtK9C,MAAa,aAAa,cAAc;CACtC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,MAAM;EACV,MAAM,aAAa;EACnB,MAAM,kBAAkB;EACxB,IAAI;GACF,MAAM,QAAQ,MAAM,iBAAiB;GACrC,MAAM,UAAU,MAAM,gBAAgB;GACtC,MAAM,eAAe,QAAQ;GAC7B,MAAM,cAAc,eAAe,QAAQ;GAC3C,MAAM,qBACJ,eAAe,IAAK,cAAc,eAAgB,MAAM;GAC1D,MAAM,0BAA0B,QAAQ;GAGxC,SAAS,eAAe,MAAc,MAA+B;IACnE,IAAI,CAAC,MAAM,OAAO,GAAG,KAAK;IAC1B,MAAM,QAAQ,KAAK;IACnB,MAAM,OAAO,QAAQ,KAAK;IAC1B,MAAM,cAAc,QAAQ,IAAK,OAAO,QAAS,MAAM;IACvD,MAAM,mBAAmB,KAAK;IAC9B,OAAO,GAAG,KAAK,IAAI,KAAK,GAAG,MAAM,SAAS,YAAY,QAAQ,EAAE,CAAC,UAAU,iBAAiB,QAAQ,EAAE,CAAC;;GAGzG,MAAM,cAAc,YAAY,YAAY,GAAG,aAAa,SAAS,mBAAmB,QAAQ,EAAE,CAAC,UAAU,wBAAwB,QAAQ,EAAE,CAAC;GAChJ,MAAM,WAAW,eAAe,QAAQ,MAAM,gBAAgB,KAAK;GACnE,MAAM,kBAAkB,eACtB,eACA,MAAM,gBAAgB,YACvB;GAED,QAAQ,IACN,wBAAwB,MAAM,aAAa,mBACtB,MAAM,iBAAiB,iBAEnC,YAAY,MACZ,SAAS,MACT,kBACV;WACM,KAAK;GACZ,QAAQ,MAAM,kCAAkC,IAAI;GACpD,QAAQ,KAAK,EAAE;;;CAGpB,CAAC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { t as PATHS } from "./paths-
|
|
1
|
+
import { t as PATHS } from "./paths-CclKwouX.js";
|
|
2
2
|
import { defineCommand } from "citty";
|
|
3
3
|
import consola from "consola";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
5
|
import os from "node:os";
|
|
6
|
-
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
7
|
//#region src/debug.ts
|
|
8
8
|
async function getPackageVersion() {
|
|
9
9
|
try {
|
|
10
|
-
const packageJsonPath = new URL("../package.json", import.meta.url)
|
|
10
|
+
const packageJsonPath = fileURLToPath(new URL("../package.json", import.meta.url));
|
|
11
11
|
return JSON.parse(await fs.readFile(packageJsonPath)).version;
|
|
12
12
|
} catch {
|
|
13
13
|
return "unknown";
|
|
@@ -76,7 +76,7 @@ const debug = defineCommand({
|
|
|
76
76
|
return runDebug({ json: args.json });
|
|
77
77
|
}
|
|
78
78
|
});
|
|
79
|
-
|
|
80
79
|
//#endregion
|
|
81
|
-
export { debug
|
|
82
|
-
|
|
80
|
+
export { debug };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=debug-BMo6ltbp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-BMo6ltbp.js","names":[],"sources":["../src/debug.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { PATHS } from \"./lib/paths\"\n\ninterface DebugInfo {\n version: string\n runtime: {\n name: string\n version: string\n platform: string\n arch: string\n }\n paths: {\n APP_DIR: string\n GITHUB_TOKEN_PATH: string\n }\n tokenExists: boolean\n}\n\ninterface RunDebugOptions {\n json: boolean\n}\n\nasync function getPackageVersion(): Promise<string> {\n try {\n const packageJsonPath = fileURLToPath(\n new URL(\"../package.json\", import.meta.url),\n )\n // @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md\n // JSON.parse() can actually parse buffers\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {\n version: string\n }\n return packageJson.version\n } catch {\n return \"unknown\"\n }\n}\n\nfunction getRuntimeInfo() {\n const isBun = typeof Bun !== \"undefined\"\n\n return {\n name: isBun ? \"bun\" : \"node\",\n version: isBun ? Bun.version : process.version.slice(1),\n platform: os.platform(),\n arch: os.arch(),\n }\n}\n\nasync function checkTokenExists(): Promise<boolean> {\n try {\n const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)\n if (!stats.isFile()) return false\n\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\nasync function getDebugInfo(): Promise<DebugInfo> {\n const [version, tokenExists] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\n ])\n\n return {\n version,\n runtime: getRuntimeInfo(),\n paths: {\n APP_DIR: PATHS.APP_DIR,\n GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,\n },\n tokenExists,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n consola.info(`copilot-api debug\n\nVersion: ${info.version}\nRuntime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})\n\nPaths:\n- APP_DIR: ${info.paths.APP_DIR}\n- GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}\n\nToken exists: ${info.tokenExists ? \"Yes\" : \"No\"}`)\n}\n\nfunction printDebugInfoJson(info: DebugInfo): void {\n console.log(JSON.stringify(info, null, 2))\n}\n\nexport async function runDebug(options: RunDebugOptions): Promise<void> {\n const debugInfo = await getDebugInfo()\n\n if (options.json) {\n printDebugInfoJson(debugInfo)\n } else {\n printDebugInfoPlain(debugInfo)\n }\n}\n\nexport const debug = defineCommand({\n meta: {\n name: \"debug\",\n description: \"Print debug information about the application\",\n },\n args: {\n json: {\n type: \"boolean\",\n default: false,\n description: \"Output debug information as JSON\",\n },\n },\n run({ args }) {\n return runDebug({\n json: args.json,\n })\n },\n})\n"],"mappings":";;;;;;;AA6BA,eAAe,oBAAqC;CAClD,IAAI;EACF,MAAM,kBAAkB,cACtB,IAAI,IAAI,mBAAmB,OAAO,KAAK,IAAI,CAC5C;EAMD,OAHoB,KAAK,MAAM,MAAM,GAAG,SAAS,gBAAgB,CAG/C,CAAC;SACb;EACN,OAAO;;;AAIX,SAAS,iBAAiB;CACxB,MAAM,QAAQ,OAAO,QAAQ;CAE7B,OAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,SAAS,QAAQ,IAAI,UAAU,QAAQ,QAAQ,MAAM,EAAE;EACvD,UAAU,GAAG,UAAU;EACvB,MAAM,GAAG,MAAM;EAChB;;AAGH,eAAe,mBAAqC;CAClD,IAAI;EAEF,IAAI,EAAC,MADe,GAAG,KAAK,MAAM,kBAAkB,EACzC,QAAQ,EAAE,OAAO;EAG5B,QAAO,MADe,GAAG,SAAS,MAAM,mBAAmB,OAAO,EACnD,MAAM,CAAC,SAAS;SACzB;EACN,OAAO;;;AAIX,eAAe,eAAmC;CAChD,MAAM,CAAC,SAAS,eAAe,MAAM,QAAQ,IAAI,CAC/C,mBAAmB,EACnB,kBAAkB,CACnB,CAAC;CAEF,OAAO;EACL;EACA,SAAS,gBAAgB;EACzB,OAAO;GACL,SAAS,MAAM;GACf,mBAAmB,MAAM;GAC1B;EACD;EACD;;AAGH,SAAS,oBAAoB,MAAuB;CAClD,QAAQ,KAAK;;WAEJ,KAAK,QAAQ;WACb,KAAK,QAAQ,KAAK,GAAG,KAAK,QAAQ,QAAQ,IAAI,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,KAAK;;;aAGvF,KAAK,MAAM,QAAQ;uBACT,KAAK,MAAM,kBAAkB;;gBAEpC,KAAK,cAAc,QAAQ,OAAO;;AAGlD,SAAS,mBAAmB,MAAuB;CACjD,QAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;;AAG5C,eAAsB,SAAS,SAAyC;CACtE,MAAM,YAAY,MAAM,cAAc;CAEtC,IAAI,QAAQ,MACV,mBAAmB,UAAU;MAE7B,oBAAoB,UAAU;;AAIlC,MAAa,QAAQ,cAAc;CACjC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,EACJ,MAAM;EACJ,MAAM;EACN,SAAS;EACT,aAAa;EACd,EACF;CACD,IAAI,EAAE,QAAQ;EACZ,OAAO,SAAS,EACd,MAAM,KAAK,MACZ,CAAC;;CAEL,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as getGitHubApiBaseUrl, _ as HTTPError, k as accountFromState, w as githubHeaders } from "./poll-access-token-BAgM2-7k.js";
|
|
2
2
|
import consola from "consola";
|
|
3
|
-
|
|
4
3
|
//#region src/services/github/get-copilot-token.ts
|
|
5
4
|
const getCopilotToken = async (account) => {
|
|
6
5
|
const ctx = account ?? accountFromState();
|
|
@@ -12,7 +11,7 @@ const getCopilotToken = async (account) => {
|
|
|
12
11
|
}
|
|
13
12
|
return await response.json();
|
|
14
13
|
};
|
|
15
|
-
|
|
16
14
|
//#endregion
|
|
17
15
|
export { getCopilotToken as t };
|
|
18
|
-
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=get-copilot-token-8Rm-rVsp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-copilot-token-
|
|
1
|
+
{"version":3,"file":"get-copilot-token-8Rm-rVsp.js","names":[],"sources":["../src/services/github/get-copilot-token.ts"],"sourcesContent":["import consola from \"consola\"\n\nimport type { AccountContext } from \"~/lib/types/account\"\n\nimport { getGitHubApiBaseUrl, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { accountFromState } from \"~/lib/state\"\n\nexport const getCopilotToken = async (account?: AccountContext) => {\n const ctx = account ?? accountFromState()\n const response = await fetch(\n `${getGitHubApiBaseUrl()}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(ctx),\n },\n )\n\n if (!response.ok) {\n const errorText = await response.clone().text()\n consola.error(\"Failed to get Copilot token response body\", errorText)\n\n throw new HTTPError(\"Failed to get Copilot token\", response)\n }\n\n return (await response.json()) as GetCopilotTokenResponse\n}\n\n// Trimmed for the sake of simplicity\nexport interface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\n}\n"],"mappings":";;;AAQA,MAAa,kBAAkB,OAAO,YAA6B;CACjE,MAAM,MAAM,WAAW,kBAAkB;CACzC,MAAM,WAAW,MAAM,MACrB,GAAG,qBAAqB,CAAC,6BACzB,EACE,SAAS,cAAc,IAAI,EAC5B,CACF;CAED,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,YAAY,MAAM,SAAS,OAAO,CAAC,MAAM;EAC/C,QAAQ,MAAM,6CAA6C,UAAU;EAErE,MAAM,IAAI,UAAU,+BAA+B,SAAS;;CAG9D,OAAQ,MAAM,SAAS,MAAM"}
|
package/dist/main.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { defineCommand, parseArgs, runMain } from "citty";
|
|
3
|
-
|
|
4
3
|
//#region src/main.ts
|
|
5
4
|
const cliArgs = {
|
|
6
5
|
"api-home": {
|
|
@@ -20,10 +19,10 @@ const args = parseArgs(process.argv, cliArgs);
|
|
|
20
19
|
if (typeof args["api-home"] === "string") process.env.COPILOT_API_HOME = args["api-home"];
|
|
21
20
|
if (typeof args["oauth-app"] === "string") process.env.COPILOT_API_OAUTH_APP = args["oauth-app"];
|
|
22
21
|
if (typeof args["enterprise-url"] === "string") process.env.COPILOT_API_ENTERPRISE_URL = args["enterprise-url"];
|
|
23
|
-
const { auth } = await import("./auth-
|
|
24
|
-
const { checkUsage } = await import("./check-usage-
|
|
25
|
-
const { debug } = await import("./debug-
|
|
26
|
-
const { start } = await import("./start-
|
|
22
|
+
const { auth } = await import("./auth-B0y-2njL.js");
|
|
23
|
+
const { checkUsage } = await import("./check-usage-DdevqHE5.js");
|
|
24
|
+
const { debug } = await import("./debug-BMo6ltbp.js");
|
|
25
|
+
const { start } = await import("./start-8QHzPrcg.js");
|
|
27
26
|
await runMain(defineCommand({
|
|
28
27
|
meta: {
|
|
29
28
|
name: "copilot-api",
|
|
@@ -37,7 +36,7 @@ await runMain(defineCommand({
|
|
|
37
36
|
},
|
|
38
37
|
args: cliArgs
|
|
39
38
|
}));
|
|
40
|
-
|
|
41
39
|
//#endregion
|
|
42
|
-
export {
|
|
40
|
+
export {};
|
|
41
|
+
|
|
43
42
|
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":[],"sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { defineCommand, runMain, parseArgs } from \"citty\"\n\nconst cliArgs = {\n \"api-home\": {\n type: \"string\",\n description: \"Path to the API home directory.\",\n },\n \"oauth-app\": {\n type: \"string\",\n description: \"OAuth app identifier.\",\n },\n \"enterprise-url\": {\n type: \"string\",\n description: \"Enterprise URL for GitHub.\",\n },\n} as const\n\nconst args = parseArgs(process.argv, cliArgs)\n\n// Set environment variables before loading other modules\nif (typeof args[\"api-home\"] === \"string\") {\n process.env.COPILOT_API_HOME = args[\"api-home\"]\n}\nif (typeof args[\"oauth-app\"] === \"string\") {\n process.env.COPILOT_API_OAUTH_APP = args[\"oauth-app\"]\n}\nif (typeof args[\"enterprise-url\"] === \"string\") {\n process.env.COPILOT_API_ENTERPRISE_URL = args[\"enterprise-url\"]\n}\n\n// Dynamically import other modules to ensure environment variables are set\nconst { auth } = await import(\"./auth\")\nconst { checkUsage } = await import(\"./check-usage\")\nconst { debug } = await import(\"./debug\")\nconst { start } = await import(\"./start\")\n\nconst main = defineCommand({\n meta: {\n name: \"copilot-api\",\n description:\n \"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.\",\n },\n subCommands: { auth, start, \"check-usage\": checkUsage, debug },\n args: cliArgs,\n})\n\nawait runMain(main)\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.js","names":[],"sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { defineCommand, runMain, parseArgs } from \"citty\"\n\nconst cliArgs = {\n \"api-home\": {\n type: \"string\",\n description: \"Path to the API home directory.\",\n },\n \"oauth-app\": {\n type: \"string\",\n description: \"OAuth app identifier.\",\n },\n \"enterprise-url\": {\n type: \"string\",\n description: \"Enterprise URL for GitHub.\",\n },\n} as const\n\nconst args = parseArgs(process.argv, cliArgs)\n\n// Set environment variables before loading other modules\nif (typeof args[\"api-home\"] === \"string\") {\n process.env.COPILOT_API_HOME = args[\"api-home\"]\n}\nif (typeof args[\"oauth-app\"] === \"string\") {\n process.env.COPILOT_API_OAUTH_APP = args[\"oauth-app\"]\n}\nif (typeof args[\"enterprise-url\"] === \"string\") {\n process.env.COPILOT_API_ENTERPRISE_URL = args[\"enterprise-url\"]\n}\n\n// Dynamically import other modules to ensure environment variables are set\nconst { auth } = await import(\"./auth\")\nconst { checkUsage } = await import(\"./check-usage\")\nconst { debug } = await import(\"./debug\")\nconst { start } = await import(\"./start\")\n\nconst main = defineCommand({\n meta: {\n name: \"copilot-api\",\n description:\n \"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.\",\n },\n subCommands: { auth, start, \"check-usage\": checkUsage, debug },\n args: cliArgs,\n})\n\nawait runMain(main)\n"],"mappings":";;;AAIA,MAAM,UAAU;CACd,YAAY;EACV,MAAM;EACN,aAAa;EACd;CACD,aAAa;EACX,MAAM;EACN,aAAa;EACd;CACD,kBAAkB;EAChB,MAAM;EACN,aAAa;EACd;CACF;AAED,MAAM,OAAO,UAAU,QAAQ,MAAM,QAAQ;AAG7C,IAAI,OAAO,KAAK,gBAAgB,UAC9B,QAAQ,IAAI,mBAAmB,KAAK;AAEtC,IAAI,OAAO,KAAK,iBAAiB,UAC/B,QAAQ,IAAI,wBAAwB,KAAK;AAE3C,IAAI,OAAO,KAAK,sBAAsB,UACpC,QAAQ,IAAI,6BAA6B,KAAK;AAIhD,MAAM,EAAE,SAAS,MAAM,OAAO;AAC9B,MAAM,EAAE,eAAe,MAAM,OAAO;AACpC,MAAM,EAAE,UAAU,MAAM,OAAO;AAC/B,MAAM,EAAE,UAAU,MAAM,OAAO;AAY/B,MAAM,QAVO,cAAc;CACzB,MAAM;EACJ,MAAM;EACN,aACE;EACH;CACD,aAAa;EAAE;EAAM;EAAO,eAAe;EAAY;EAAO;CAC9D,MAAM;CACP,CAEiB,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import os from "node:os";
|
|
4
|
-
|
|
5
4
|
//#region src/lib/paths.ts
|
|
6
5
|
const AUTH_APP = process.env.COPILOT_API_OAUTH_APP?.trim() || "";
|
|
7
6
|
const ENTERPRISE_PREFIX = process.env.COPILOT_API_ENTERPRISE_URL ? "ent_" : "";
|
|
@@ -11,14 +10,13 @@ const GITHUB_TOKEN_PATH = path.join(APP_DIR, AUTH_APP, ENTERPRISE_PREFIX + "gith
|
|
|
11
10
|
const CONFIG_PATH = path.join(APP_DIR, "config.json");
|
|
12
11
|
const MODELS_PATH = path.join(APP_DIR, "models.json");
|
|
13
12
|
const TOKENS_DIR = path.join(APP_DIR, "tokens");
|
|
14
|
-
const ACCOUNTS_REGISTRY_PATH = path.join(APP_DIR, "accounts-registry.json");
|
|
15
13
|
const PATHS = {
|
|
16
14
|
APP_DIR,
|
|
17
15
|
GITHUB_TOKEN_PATH,
|
|
18
16
|
CONFIG_PATH,
|
|
19
17
|
MODELS_PATH,
|
|
20
18
|
TOKENS_DIR,
|
|
21
|
-
ACCOUNTS_REGISTRY_PATH
|
|
19
|
+
ACCOUNTS_REGISTRY_PATH: path.join(APP_DIR, "accounts-registry.json")
|
|
22
20
|
};
|
|
23
21
|
/**
|
|
24
22
|
* Get the token file path for a specific account.
|
|
@@ -43,7 +41,7 @@ async function ensureFile(filePath) {
|
|
|
43
41
|
await fs.chmod(filePath, 384);
|
|
44
42
|
}
|
|
45
43
|
}
|
|
46
|
-
|
|
47
44
|
//#endregion
|
|
48
45
|
export { accountTokenPath as n, ensurePaths as r, PATHS as t };
|
|
49
|
-
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=paths-CclKwouX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths-
|
|
1
|
+
{"version":3,"file":"paths-CclKwouX.js","names":[],"sources":["../src/lib/paths.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport path from \"node:path\"\n\nconst AUTH_APP = process.env.COPILOT_API_OAUTH_APP?.trim() || \"\"\nconst ENTERPRISE_PREFIX = process.env.COPILOT_API_ENTERPRISE_URL ? \"ent_\" : \"\"\n\nconst DEFAULT_DIR = path.join(os.homedir(), \".local\", \"share\", \"copilot-api\")\nconst APP_DIR = process.env.COPILOT_API_HOME || DEFAULT_DIR\n\nconst GITHUB_TOKEN_PATH = path.join(\n APP_DIR,\n AUTH_APP,\n ENTERPRISE_PREFIX + \"github_token\",\n)\nconst CONFIG_PATH = path.join(APP_DIR, \"config.json\")\nconst MODELS_PATH = path.join(APP_DIR, \"models.json\")\n\n// Multi-account paths\nconst TOKENS_DIR = path.join(APP_DIR, \"tokens\")\nconst ACCOUNTS_REGISTRY_PATH = path.join(APP_DIR, \"accounts-registry.json\")\n\nexport const PATHS = {\n APP_DIR,\n GITHUB_TOKEN_PATH,\n CONFIG_PATH,\n MODELS_PATH,\n TOKENS_DIR,\n ACCOUNTS_REGISTRY_PATH,\n}\n\n/**\n * Get the token file path for a specific account.\n * @param id - The account ID (GitHub login)\n * @returns The absolute path to the account's token file\n */\nexport function accountTokenPath(id: string): string {\n return path.join(TOKENS_DIR, `github_${id}`)\n}\n\nexport async function ensurePaths(): Promise<void> {\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\n await fs.mkdir(path.join(PATHS.APP_DIR, AUTH_APP), { recursive: true })\n await fs.mkdir(PATHS.TOKENS_DIR, { recursive: true })\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\n await ensureFile(PATHS.CONFIG_PATH)\n}\n\nasync function ensureFile(filePath: string): Promise<void> {\n try {\n await fs.access(filePath, fs.constants.W_OK)\n } catch {\n await fs.writeFile(filePath, \"\")\n await fs.chmod(filePath, 0o600)\n }\n}\n"],"mappings":";;;;AAIA,MAAM,WAAW,QAAQ,IAAI,uBAAuB,MAAM,IAAI;AAC9D,MAAM,oBAAoB,QAAQ,IAAI,6BAA6B,SAAS;AAE5E,MAAM,cAAc,KAAK,KAAK,GAAG,SAAS,EAAE,UAAU,SAAS,cAAc;AAC7E,MAAM,UAAU,QAAQ,IAAI,oBAAoB;AAEhD,MAAM,oBAAoB,KAAK,KAC7B,SACA,UACA,oBAAoB,eACrB;AACD,MAAM,cAAc,KAAK,KAAK,SAAS,cAAc;AACrD,MAAM,cAAc,KAAK,KAAK,SAAS,cAAc;AAGrD,MAAM,aAAa,KAAK,KAAK,SAAS,SAAS;AAG/C,MAAa,QAAQ;CACnB;CACA;CACA;CACA;CACA;CACA,wBAR6B,KAAK,KAAK,SAAS,yBAQhD;CACD;;;;;;AAOD,SAAgB,iBAAiB,IAAoB;CACnD,OAAO,KAAK,KAAK,YAAY,UAAU,KAAK;;AAG9C,eAAsB,cAA6B;CACjD,MAAM,GAAG,MAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;CAClD,MAAM,GAAG,MAAM,KAAK,KAAK,MAAM,SAAS,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;CACvE,MAAM,GAAG,MAAM,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;CACrD,MAAM,WAAW,MAAM,kBAAkB;CACzC,MAAM,WAAW,MAAM,YAAY;;AAGrC,eAAe,WAAW,UAAiC;CACzD,IAAI;EACF,MAAM,GAAG,OAAO,UAAU,GAAG,UAAU,KAAK;SACtC;EACN,MAAM,GAAG,UAAU,UAAU,GAAG;EAChC,MAAM,GAAG,MAAM,UAAU,IAAM"}
|