@jeffreycao/copilot-api 1.12.7 → 1.12.9

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.
Files changed (31) hide show
  1. package/README.md +38 -34
  2. package/README.zh-CN.md +38 -34
  3. package/dist/auth-15xzL-eW.js +331 -0
  4. package/dist/auth-15xzL-eW.js.map +1 -0
  5. package/dist/{check-usage-A0wChz3s.js → check-usage-Bu9w7RbA.js} +4 -4
  6. package/dist/{check-usage-A0wChz3s.js.map → check-usage-Bu9w7RbA.js.map} +1 -1
  7. package/dist/{config-B-_X-1gj.js → config-B71_S_hQ.js} +12 -5
  8. package/dist/config-B71_S_hQ.js.map +1 -0
  9. package/dist/{debug-BiGuRO0S.js → debug-TyT2u9dt.js} +2 -2
  10. package/dist/{debug-BiGuRO0S.js.map → debug-TyT2u9dt.js.map} +1 -1
  11. package/dist/electron-fetch-DPhDE6JE.js +22 -0
  12. package/dist/electron-fetch-DPhDE6JE.js.map +1 -0
  13. package/dist/main.js +7 -24
  14. package/dist/main.js.map +1 -1
  15. package/dist/{mcp-CTb-DbQH.js → mcp-BseuqgHR.js} +2 -2
  16. package/dist/{mcp-CTb-DbQH.js.map → mcp-BseuqgHR.js.map} +1 -1
  17. package/dist/{server-ypsjdIs5.js → server-34rnRg4k.js} +44 -44
  18. package/dist/server-34rnRg4k.js.map +1 -0
  19. package/dist/{start-BBRI5K7R.js → start-8y_02ZHG.js} +5 -5
  20. package/dist/{start-BBRI5K7R.js.map → start-8y_02ZHG.js.map} +1 -1
  21. package/dist/{tls-CaLAeSaF.js → tls-BniQ6Rel.js} +1 -1
  22. package/dist/{tls-CaLAeSaF.js.map → tls-BniQ6Rel.js.map} +1 -1
  23. package/dist/{token-CIpQTF2M.js → token-fpw8tAQS.js} +4 -4
  24. package/dist/{token-CIpQTF2M.js.map → token-fpw8tAQS.js.map} +1 -1
  25. package/dist/{tool-search-D3SN0jX-.js → tool-search-OX6iPJ9D.js} +1 -1
  26. package/dist/{tool-search-D3SN0jX-.js.map → tool-search-OX6iPJ9D.js.map} +1 -1
  27. package/package.json +1 -1
  28. package/dist/auth-bQxQAUnE.js +0 -117
  29. package/dist/auth-bQxQAUnE.js.map +0 -1
  30. package/dist/config-B-_X-1gj.js.map +0 -1
  31. package/dist/server-ypsjdIs5.js.map +0 -1
package/README.md CHANGED
@@ -168,9 +168,14 @@ The following command line options are available for the `start` command:
168
168
 
169
169
  | Option | Description | Default | Alias |
170
170
  | ------------ | ------------------------- | ------- | ----- |
171
+ | --provider | Provider to log in with or configure (`copilot`, `codex`, `deepseek`, `dashscope`, `openrouter`, or `custom`) | prompt | none |
171
172
  | --verbose | Enable verbose logging | false | -v |
172
173
  | --show-token | Show GitHub token on auth | false | none |
173
174
 
175
+ Use `copilot-api auth login --provider deepseek`, `--provider dashscope`, or `--provider openrouter` to add or update those common third-party providers from the CLI. DeepSeek and DashScope prompt for masked `apiKey`, provider `type` (default `openai-compatible`), and `baseUrl` with the provider default prefilled. OpenRouter prompts for masked `apiKey` and prefilled `baseUrl` only, and writes `type: "anthropic"`.
176
+
177
+ Use `copilot-api auth login --provider custom` to add or update another third-party provider from the CLI. The command prompts for the provider name, supported type (`anthropic`, `openai-compatible`, or `openai-responses`), `baseUrl`, masked `apiKey`, and `authType`; `authType` may be left as the type default or set to `x-api-key` / `authorization`.
178
+
174
179
  ### Debug Command Options
175
180
 
176
181
  | Option | Description | Default | Alias |
@@ -187,39 +192,7 @@ The following command line options are available for the `start` command:
187
192
  "apiKeys": [],
188
193
  "adminApiKey": "<auto-generated-on-startup>"
189
194
  },
190
- "providers": {
191
- "custom": {
192
- "type": "anthropic",
193
- "enabled": true,
194
- "baseUrl": "your-base-url",
195
- "apiKey": "sk-your-provider-key",
196
- "authType": "x-api-key"
197
- },
198
- "dashscope": {
199
- "type": "openai-compatible",
200
- "enabled": true,
201
- "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode",
202
- "apiKey": "sk-your-dashscope-key",
203
- "models": {
204
- "qwen3.6-plus": {
205
- "temperature": 1,
206
- "topP": 0.95,
207
- "topK": 20,
208
- "extraBody": {
209
- "preserve_thinking": true
210
- }
211
- },
212
- "glm-5.1": {
213
- "temperature": 0.7,
214
- "topP": 0.95,
215
- "contextCache": true,
216
- "extraBody": {
217
- "preserve_thinking": true
218
- }
219
- }
220
- }
221
- }
222
- },
195
+ "providers": {},
223
196
  "modelMappings": {},
224
197
  "extraPrompts": {
225
198
  "gpt-5-mini": "<built-in exploration prompt>",
@@ -256,7 +229,6 @@ The following command line options are available for the `start` command:
256
229
  - `baseUrl` should be provider API base URL without the final endpoint. For Anthropic providers, omit `/v1/messages`; for OpenAI-compatible providers, omit `/v1/chat/completions`; for OpenAI Responses providers, omit `/v1/responses`.
257
230
  - `apiKey` is used as the upstream credential value and is required for regular providers.
258
231
  - `authType` (optional): Controls how `apiKey` is sent upstream. Supports `x-api-key` and `authorization` for regular providers. Anthropic providers default to `x-api-key`; OpenAI-compatible and OpenAI Responses providers default to `authorization`. When set to `authorization`, the proxy sends `Authorization: Bearer <apiKey>`. `oauth2` is reserved for the built-in `codex` provider and is written automatically by `auth login --provider codex`.
259
- - `adjustInputTokens` (optional): When `true`, the proxy will adjust the `input_tokens` in the usage response by subtracting `cache_read_input_tokens` and `cache_creation_input_tokens`.
260
232
  - `models` (optional): Per-model configuration map. Each key is a model ID (matching the model name in requests), and the value is:
261
233
  - `temperature` (optional): Default temperature value used when the request does not specify one.
262
234
  - `topP` (optional): Default top_p value used when the request does not specify one.
@@ -265,6 +237,38 @@ The following command line options are available for the `start` command:
265
237
  - `contextCache` (optional): Defaults to `true` for OpenAI-compatible providers. This enables Alibaba Cloud Model Studio/DashScope explicit context cache by injecting `cache_control: { "type": "ephemeral" }` on up to 4 content blocks using the Context Cache format. The cache breakpoint strategy matches opencode's main provider flow: the first 2 system messages plus the last 2 non-system messages. Marked string content is converted to text content part arrays for `system` / `user` / `assistant` / `tool` messages; existing array content is marked on the last part. Set this to `false` when the model already supports implicit caching, or when the upstream does not accept this explicit-cache extension field.
266
238
  - `supportPdf` (optional): Controls whether the model supports PDF/document content. Defaults to `false`; unsupported PDFs are converted to a text notice. Set it to `true` to send PDF/document blocks as OpenAI Chat Completions file parts.
267
239
  - `toolContentSupportType` (optional): Tool result content capabilities for that model, as an array of `array`, `image`, and `pdf`. Provider routes default to string-only tool content when omitted. If `supportPdf` is `true` but this list does not include `pdf`, file parts in tool results are moved to user role messages. This provider default does not change the Copilot main flow, which continues to support array + image and not PDF.
240
+
241
+ Example DashScope model settings:
242
+ ```json
243
+ {
244
+ "providers": {
245
+ "dashscope": {
246
+ "type": "openai-compatible",
247
+ "enabled": true,
248
+ "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode",
249
+ "apiKey": "sk-your-dashscope-key",
250
+ "models": {
251
+ "qwen3.6-plus": {
252
+ "temperature": 1,
253
+ "topP": 0.95,
254
+ "topK": 20,
255
+ "extraBody": {
256
+ "preserve_thinking": true
257
+ }
258
+ },
259
+ "glm-5.1": {
260
+ "temperature": 0.7,
261
+ "topP": 0.95,
262
+ "contextCache": true,
263
+ "extraBody": {
264
+ "preserve_thinking": true
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+ ```
268
272
  - **smallModel:** Fallback model used for tool-less warmup messages (e.g., Claude Code probe requests); defaults to gpt-5-mini.
269
273
  - **useResponsesApiContextManagement:** When `true`, the proxy adds Responses API `context_management` compaction instructions. Defaults to `true`. Set it to `false` to disable this globally. When enabled, the request includes `context_management` in the body and keeps only the latest compaction carrier on follow-up turns. This is especially useful for long-running tasks.
270
274
  - **modelResponsesApiCompactThresholds:** Per-model Responses API `compact_threshold` overrides used when the proxy adds `context_management`. These values take precedence over the fallback threshold from `resolveResponsesCompactThreshold` (`max_prompt_tokens * ratio`, or the default fallback). Defaults set `gpt-5.4` and `gpt-5.5` to `217600` (`272000 * 0.8`). Models not listed continue to use the normal fallback logic.
package/README.zh-CN.md CHANGED
@@ -168,9 +168,14 @@ Copilot API 现在使用子命令结构,主要命令包括:
168
168
 
169
169
  | 选项 | 说明 | 默认值 | 别名 |
170
170
  | --- | --- | --- | --- |
171
+ | --provider | 要登录或配置的 provider(`copilot`、`codex`、`deepseek`、`dashscope`、`openrouter` 或 `custom`) | 交互选择 | 无 |
171
172
  | --verbose | 启用详细日志 | false | -v |
172
173
  | --show-token | 认证时显示 GitHub token | false | 无 |
173
174
 
175
+ 使用 `copilot-api auth login --provider deepseek`、`--provider dashscope` 或 `--provider openrouter` 可以通过 CLI 快速新增或更新这些常用第三方 provider。DeepSeek 和 DashScope 会提示输入掩码显示的 `apiKey`、provider `type`(默认 `openai-compatible`)和预填默认值的 `baseUrl`。OpenRouter 只提示输入掩码显示的 `apiKey` 和预填默认值的 `baseUrl`,并固定写入 `type: "anthropic"`。
176
+
177
+ 使用 `copilot-api auth login --provider custom` 可以通过 CLI 新增或更新其他第三方 provider。命令会依次提示输入 provider name、项目支持的 type(`anthropic`、`openai-compatible` 或 `openai-responses`)、`baseUrl`、掩码显示的 `apiKey` 和 `authType`;`authType` 可保持 type 默认值,也可选择 `x-api-key` / `authorization`。
178
+
174
179
  ### Debug 命令选项
175
180
 
176
181
  | 选项 | 说明 | 默认值 | 别名 |
@@ -189,39 +194,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
189
194
  "apiKeys": [],
190
195
  "adminApiKey": "<startup 自动生成>"
191
196
  },
192
- "providers": {
193
- "custom": {
194
- "type": "anthropic",
195
- "enabled": true,
196
- "baseUrl": "your-base-url",
197
- "apiKey": "sk-your-provider-key",
198
- "authType": "x-api-key"
199
- },
200
- "dashscope": {
201
- "type": "openai-compatible",
202
- "enabled": true,
203
- "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode",
204
- "apiKey": "sk-your-dashscope-key",
205
- "models": {
206
- "qwen3.6-plus": {
207
- "temperature": 1,
208
- "topP": 0.95,
209
- "topK": 20,
210
- "extraBody": {
211
- "preserve_thinking": true
212
- }
213
- },
214
- "glm-5.1": {
215
- "temperature": 0.7,
216
- "topP": 0.95,
217
- "contextCache": true,
218
- "extraBody": {
219
- "preserve_thinking": true
220
- }
221
- }
222
- }
223
- }
224
- },
197
+ "providers": {},
225
198
  "modelMappings": {},
226
199
  "extraPrompts": {
227
200
  "gpt-5-mini": "<built-in exploration prompt>",
@@ -258,7 +231,6 @@ Copilot API 现在使用子命令结构,主要命令包括:
258
231
  - `baseUrl`:provider API 的基础 URL,不要带结尾的 endpoint。Anthropic provider 不要带 `/v1/messages`;OpenAI 兼容 provider 不要带 `/v1/chat/completions`;OpenAI Responses provider 不要带 `/v1/responses`。
259
232
  - `apiKey`:作为上游凭据值使用;普通 provider 必须配置。
260
233
  - `authType`:可选,控制 `apiKey` 如何发送到上游。普通 provider 支持 `x-api-key` 和 `authorization`。Anthropic provider 默认 `x-api-key`;OpenAI 兼容和 OpenAI Responses provider 默认 `authorization`。当设置为 `authorization` 时,代理会发送 `Authorization: Bearer <apiKey>`。`oauth2` 仅保留给内置 `codex` provider,并由 `auth login --provider codex` 自动写入。
261
- - `adjustInputTokens`:可选,当为 `true` 时,代理会在 usage 响应里用 `input_tokens` 减去 `cache_read_input_tokens` 和 `cache_creation_input_tokens`。
262
234
  - `models`:可选,按模型 ID 配置的映射。每个键为请求中的模型名,值支持:
263
235
  - `temperature`:可选,当请求未指定时使用的默认温度。
264
236
  - `topP`:可选,当请求未指定时使用的默认 `top_p`。
@@ -267,6 +239,38 @@ Copilot API 现在使用子命令结构,主要命令包括:
267
239
  - `contextCache`:可选,OpenAI 兼容 provider 默认 `true`,用于启用阿里云百炼/DashScope 的显式缓存(explicit context cache),会按其 Context Cache 格式在最多 4 个 content block 上注入 `cache_control: { "type": "ephemeral" }`。缓存断点策略与 opencode 主链路保持一致:前 2 条 system 消息 + 最后 2 条非 system 消息。标记字符串 content 时会把 `system` / `user` / `assistant` / `tool` 消息转换为 text content part 数组;已有数组 content 则标记最后一个 part。如果模型本身已经支持隐式缓存,或上游不支持该显式缓存扩展字段,可在模型配置中设为 `false`。
268
240
  - `supportPdf`:可选,控制该模型是否支持 PDF/document content。默认 `false`,不支持时会把 PDF 转成提示文本;设为 `true` 时会把 PDF/document 转成 OpenAI Chat Completions 的 file part。
269
241
  - `toolContentSupportType`:可选,配置该模型的 tool result content 支持能力,值为 `array`、`image`、`pdf` 的数组。provider 侧未配置时默认只发送 string tool content。若 `supportPdf` 为 `true` 但这里不包含 `pdf`,tool result 里的 file part 会被转成 user role 消息。Copilot 主链路不使用这个 provider 默认,仍按 array + image 且不支持 PDF 的能力处理。
242
+
243
+ DashScope 模型配置示例:
244
+ ```json
245
+ {
246
+ "providers": {
247
+ "dashscope": {
248
+ "type": "openai-compatible",
249
+ "enabled": true,
250
+ "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode",
251
+ "apiKey": "sk-your-dashscope-key",
252
+ "models": {
253
+ "qwen3.6-plus": {
254
+ "temperature": 1,
255
+ "topP": 0.95,
256
+ "topK": 20,
257
+ "extraBody": {
258
+ "preserve_thinking": true
259
+ }
260
+ },
261
+ "glm-5.1": {
262
+ "temperature": 0.7,
263
+ "topP": 0.95,
264
+ "contextCache": true,
265
+ "extraBody": {
266
+ "preserve_thinking": true
267
+ }
268
+ }
269
+ }
270
+ }
271
+ }
272
+ }
273
+ ```
270
274
  - **smallModel:** 无工具预热消息的回退模型(例如 Claude Code 的探测请求);默认是 `gpt-5-mini`。
271
275
  - **useResponsesApiContextManagement:** 当为 `true` 时,代理会为 Responses API 附加 `context_management` 压缩指令。默认值为 `true`。如需全局关闭,可设为 `false`。启用后,请求体会带上 `context_management`,并在后续轮次中仅保留最新的压缩承载内容,因此特别适合长任务场景。
272
276
  - **modelResponsesApiCompactThresholds:** 按模型覆盖 Responses API 的 `compact_threshold`,仅在代理自动附加 `context_management` 时使用。它的优先级高于 `resolveResponsesCompactThreshold` 基于 `max_prompt_tokens * ratio` 的兜底阈值。默认将 `gpt-5.4` 和 `gpt-5.5` 设为 `217600`(`272000 * 0.8`)。未列出的模型继续使用原有兜底逻辑。
@@ -0,0 +1,331 @@
1
+ import { E as ensurePaths, T as PATHS, t as SUPPORTED_PROVIDER_TYPES, u as getRawProviderConfig, v as isSupportedProviderType, w as setProviderConfig, x as normalizeProviderBaseUrl } from "./config-B71_S_hQ.js";
2
+ import { A as loginCodex, L as state, a as setupGitHubToken, n as persistCodexCredentials } from "./token-fpw8tAQS.js";
3
+ import { defineCommand } from "citty";
4
+ import consola from "consola";
5
+ //#region src/auth.ts
6
+ const authArgs = {
7
+ provider: {
8
+ type: "string",
9
+ description: "Provider to log in with or configure (copilot, codex, deepseek, dashscope, openrouter, custom)"
10
+ },
11
+ verbose: {
12
+ alias: "v",
13
+ type: "boolean",
14
+ default: false,
15
+ description: "Enable verbose logging"
16
+ },
17
+ "show-token": {
18
+ type: "boolean",
19
+ default: false,
20
+ description: "Show provider access token on auth"
21
+ }
22
+ };
23
+ const BUILTIN_PROVIDER_NAMES = ["copilot", "codex"];
24
+ const QUICK_PROVIDER_CONFIGS = {
25
+ deepseek: {
26
+ type: "openai-compatible",
27
+ baseUrl: "https://api.deepseek.com",
28
+ editableType: true
29
+ },
30
+ dashscope: {
31
+ type: "openai-compatible",
32
+ baseUrl: "https://dashscope.aliyuncs.com/compatible-mode",
33
+ editableType: true
34
+ },
35
+ openrouter: {
36
+ type: "anthropic",
37
+ baseUrl: "https://openrouter.ai/api",
38
+ editableType: false
39
+ }
40
+ };
41
+ const QUICK_PROVIDER_NAMES = Object.keys(QUICK_PROVIDER_CONFIGS);
42
+ const AUTH_PROVIDER_NAMES = [
43
+ ...BUILTIN_PROVIDER_NAMES,
44
+ ...QUICK_PROVIDER_NAMES,
45
+ "custom"
46
+ ];
47
+ const CUSTOM_PROVIDER_AUTH_TYPE_OPTION = "__default__";
48
+ const QUICK_PROVIDER_DEFAULT_TYPE_OPTION = "__default__";
49
+ const CUSTOM_PROVIDER_AUTH_TYPES = ["x-api-key", "authorization"];
50
+ const AUTH_PROVIDER_LABELS = {
51
+ copilot: "GitHub Copilot",
52
+ codex: "OpenAI Codex",
53
+ deepseek: "DeepSeek",
54
+ dashscope: "DashScope",
55
+ openrouter: "OpenRouter",
56
+ custom: "Custom provider"
57
+ };
58
+ function isAuthProviderName(providerName) {
59
+ return AUTH_PROVIDER_NAMES.includes(providerName);
60
+ }
61
+ function isCustomProviderAuthType(value) {
62
+ return CUSTOM_PROVIDER_AUTH_TYPES.includes(value);
63
+ }
64
+ function isQuickProviderName(providerName) {
65
+ return QUICK_PROVIDER_NAMES.includes(providerName);
66
+ }
67
+ async function resolveProviderSelection(providerArg) {
68
+ const availableProviders = [...AUTH_PROVIDER_NAMES];
69
+ if (providerArg !== void 0) {
70
+ const providerName = providerArg.trim();
71
+ if (!isAuthProviderName(providerName)) throw new Error(`Unknown provider '${providerArg}'. Expected one of: ${availableProviders.join(", ")}`);
72
+ return providerName;
73
+ }
74
+ if (availableProviders.length === 1) return availableProviders[0];
75
+ const provider = await consola.prompt("Select a provider to log in with", {
76
+ type: "select",
77
+ options: availableProviders.map((providerName) => ({
78
+ label: `${AUTH_PROVIDER_LABELS[providerName]} (${providerName})`,
79
+ value: providerName
80
+ }))
81
+ });
82
+ if (!provider || !isAuthProviderName(provider)) throw new Error("No provider selected");
83
+ return provider;
84
+ }
85
+ function assertCustomProviderName(providerName) {
86
+ if (!providerName) throw new Error("Provider name must be a non-empty string");
87
+ if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/u.test(providerName)) throw new Error("Provider name must start with a letter or number and contain only letters, numbers, underscores, or hyphens");
88
+ if (providerName === "copilot" || providerName === "codex") throw new Error(`Provider name '${providerName}' is reserved for a builtin provider`);
89
+ }
90
+ async function promptRequiredText(message, fieldName) {
91
+ const value = await consola.prompt(message, { type: "text" });
92
+ const normalizedValue = typeof value === "string" ? value.trim() : "";
93
+ if (!normalizedValue) throw new Error(`${fieldName} must be a non-empty string`);
94
+ return normalizedValue;
95
+ }
96
+ function canUseMaskedPrompt() {
97
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY && typeof process.stdin.setRawMode === "function");
98
+ }
99
+ async function promptMaskedText(message) {
100
+ if (!canUseMaskedPrompt()) {
101
+ const value = await consola.prompt(message, { type: "text" });
102
+ return typeof value === "string" ? value : "";
103
+ }
104
+ return await new Promise((resolve, reject) => {
105
+ let value = "";
106
+ const rawModeWasEnabled = process.stdin.isRaw === true;
107
+ function cleanup() {
108
+ process.stdin.off("data", onData);
109
+ process.stdin.setRawMode(rawModeWasEnabled);
110
+ process.stdin.pause();
111
+ }
112
+ function finish() {
113
+ cleanup();
114
+ process.stdout.write("\n");
115
+ resolve(value);
116
+ }
117
+ function cancel() {
118
+ cleanup();
119
+ process.stdout.write("\n");
120
+ reject(/* @__PURE__ */ new Error("Prompt cancelled"));
121
+ }
122
+ function onData(chunk) {
123
+ const input = chunk.toString("utf8");
124
+ if (input.startsWith("\x1B")) return;
125
+ for (const char of input) {
126
+ if (char === "") {
127
+ cancel();
128
+ return;
129
+ }
130
+ if (char === "\r" || char === "\n") {
131
+ finish();
132
+ return;
133
+ }
134
+ if (char === "\b" || char === "") {
135
+ if (value.length > 0) {
136
+ value = value.slice(0, -1);
137
+ process.stdout.write("\b \b");
138
+ }
139
+ continue;
140
+ }
141
+ if (char >= " ") {
142
+ value += char;
143
+ process.stdout.write("*");
144
+ }
145
+ }
146
+ }
147
+ process.stdout.write(`${message}: `);
148
+ process.stdin.setRawMode(true);
149
+ process.stdin.resume();
150
+ process.stdin.on("data", onData);
151
+ });
152
+ }
153
+ async function promptRequiredSecret(message, fieldName) {
154
+ const normalizedValue = (await promptMaskedText(message)).trim();
155
+ if (!normalizedValue) throw new Error(`${fieldName} must be a non-empty string`);
156
+ return normalizedValue;
157
+ }
158
+ async function promptCustomProviderName() {
159
+ const providerName = await promptRequiredText("Enter provider name", "Provider name");
160
+ assertCustomProviderName(providerName);
161
+ return providerName;
162
+ }
163
+ async function promptCustomProviderType() {
164
+ const providerType = await consola.prompt("Select provider type", {
165
+ type: "select",
166
+ options: SUPPORTED_PROVIDER_TYPES.map((type) => ({
167
+ label: type,
168
+ value: type
169
+ }))
170
+ });
171
+ if (typeof providerType !== "string" || !isSupportedProviderType(providerType)) throw new Error("No provider type selected");
172
+ return providerType;
173
+ }
174
+ async function promptQuickProviderType(defaultType) {
175
+ const providerType = await consola.prompt(`Select provider type (default: ${defaultType})`, {
176
+ type: "select",
177
+ options: [{
178
+ label: `Default (${defaultType})`,
179
+ value: QUICK_PROVIDER_DEFAULT_TYPE_OPTION
180
+ }, ...SUPPORTED_PROVIDER_TYPES.map((type) => ({
181
+ label: type,
182
+ value: type
183
+ }))]
184
+ });
185
+ if (providerType === QUICK_PROVIDER_DEFAULT_TYPE_OPTION) return defaultType;
186
+ if (typeof providerType === "string" && isSupportedProviderType(providerType)) return providerType;
187
+ throw new Error("No provider type selected");
188
+ }
189
+ function getDefaultProviderAuthType(providerType) {
190
+ return providerType === "anthropic" ? "x-api-key" : "authorization";
191
+ }
192
+ async function promptCustomProviderAuthType(providerType) {
193
+ const defaultAuthType = getDefaultProviderAuthType(providerType);
194
+ const authType = await consola.prompt("Select provider auth type", {
195
+ type: "select",
196
+ options: [{
197
+ label: `Default (${defaultAuthType})`,
198
+ value: CUSTOM_PROVIDER_AUTH_TYPE_OPTION
199
+ }, ...CUSTOM_PROVIDER_AUTH_TYPES.map((value) => ({
200
+ label: value,
201
+ value
202
+ }))]
203
+ });
204
+ if (authType === CUSTOM_PROVIDER_AUTH_TYPE_OPTION) return;
205
+ if (typeof authType === "string" && isCustomProviderAuthType(authType)) return authType;
206
+ throw new Error("No provider auth type selected");
207
+ }
208
+ async function promptQuickProviderBaseUrl(defaultBaseUrl) {
209
+ const value = await consola.prompt(`Enter provider baseUrl (default: ${defaultBaseUrl})`, {
210
+ type: "text",
211
+ default: defaultBaseUrl,
212
+ initial: defaultBaseUrl
213
+ });
214
+ const baseUrl = normalizeProviderBaseUrl(typeof value === "string" && value.trim() ? value : defaultBaseUrl);
215
+ if (!baseUrl) throw new Error("baseUrl must be a non-empty string");
216
+ return baseUrl;
217
+ }
218
+ function buildCustomProviderConfig(existingProviderConfig, options) {
219
+ return {
220
+ type: options.type,
221
+ enabled: true,
222
+ baseUrl: options.baseUrl,
223
+ apiKey: options.apiKey,
224
+ ...options.authType ? { authType: options.authType } : {},
225
+ ...existingProviderConfig.models ? { models: existingProviderConfig.models } : {}
226
+ };
227
+ }
228
+ async function configureCustomProvider() {
229
+ const providerName = await promptCustomProviderName();
230
+ const type = await promptCustomProviderType();
231
+ const baseUrl = normalizeProviderBaseUrl(await promptRequiredText("Enter provider baseUrl", "baseUrl"));
232
+ if (!baseUrl) throw new Error("baseUrl must be a non-empty string");
233
+ const apiKey = await promptRequiredSecret("Enter provider apiKey", "apiKey");
234
+ const authType = await promptCustomProviderAuthType(type);
235
+ setProviderConfig(providerName, buildCustomProviderConfig(getRawProviderConfig(providerName) ?? {}, {
236
+ apiKey,
237
+ authType,
238
+ baseUrl,
239
+ type
240
+ }));
241
+ consola.success(`Custom provider '${providerName}' written to ${PATHS.CONFIG_PATH}`);
242
+ }
243
+ async function configureQuickProvider(providerName) {
244
+ const defaultProviderConfig = QUICK_PROVIDER_CONFIGS[providerName];
245
+ const apiKey = await promptRequiredSecret(`Enter ${providerName} apiKey`, "apiKey");
246
+ const type = defaultProviderConfig.editableType ? await promptQuickProviderType(defaultProviderConfig.type) : defaultProviderConfig.type;
247
+ const baseUrl = await promptQuickProviderBaseUrl(defaultProviderConfig.baseUrl);
248
+ setProviderConfig(providerName, buildCustomProviderConfig(getRawProviderConfig(providerName) ?? {}, {
249
+ apiKey,
250
+ baseUrl,
251
+ type
252
+ }));
253
+ consola.success(`${AUTH_PROVIDER_LABELS[providerName]} provider '${providerName}' written to ${PATHS.CONFIG_PATH}`);
254
+ }
255
+ async function loginWithCodex() {
256
+ await persistCodexCredentials(await loginCodex({
257
+ onAuth(info) {
258
+ consola.info("Open the following URL to authenticate with Codex:");
259
+ consola.log(info.url);
260
+ if (info.instructions) consola.info(info.instructions);
261
+ },
262
+ onPrompt(message) {
263
+ return consola.prompt(message, { type: "text" });
264
+ },
265
+ onProgress(message) {
266
+ consola.debug(message);
267
+ }
268
+ }), { enableProvider: true });
269
+ consola.success(`Codex provider config written to ${PATHS.CONFIG_PATH} and credentials written to ${PATHS.CODEX_CREDENTIAL_PATH}`);
270
+ }
271
+ async function loginWithProvider(provider) {
272
+ if (provider === "copilot") {
273
+ await setupGitHubToken({ force: true });
274
+ consola.success("GitHub token written to", PATHS.GITHUB_TOKEN_PATH);
275
+ return;
276
+ }
277
+ if (provider === "codex") {
278
+ await loginWithCodex();
279
+ return;
280
+ }
281
+ if (isQuickProviderName(provider)) {
282
+ await configureQuickProvider(provider);
283
+ return;
284
+ }
285
+ await configureCustomProvider();
286
+ }
287
+ async function runAuthLogin(options) {
288
+ (await import("./tls-BniQ6Rel.js")).enableSystemCACompat();
289
+ if (options.verbose) {
290
+ consola.level = 5;
291
+ consola.info("Verbose logging enabled");
292
+ }
293
+ state.showToken = options.showToken;
294
+ await ensurePaths();
295
+ const provider = await resolveProviderSelection(options.provider);
296
+ consola.info(`Logging in with ${AUTH_PROVIDER_LABELS[provider]}`);
297
+ await loginWithProvider(provider);
298
+ }
299
+ const auth = defineCommand({
300
+ meta: {
301
+ name: "auth",
302
+ description: "Run authentication flows without running the server"
303
+ },
304
+ args: authArgs,
305
+ subCommands: { login: defineCommand({
306
+ meta: {
307
+ name: "login",
308
+ description: "Authenticate or configure a provider without running the server"
309
+ },
310
+ args: authArgs,
311
+ run({ args }) {
312
+ return runAuthLogin({
313
+ provider: args.provider,
314
+ verbose: args.verbose,
315
+ showToken: args["show-token"]
316
+ });
317
+ }
318
+ }) },
319
+ run({ args }) {
320
+ if ((args._[0] ?? "").trim()) return;
321
+ return runAuthLogin({
322
+ provider: args.provider,
323
+ verbose: args.verbose,
324
+ showToken: args["show-token"]
325
+ });
326
+ }
327
+ });
328
+ //#endregion
329
+ export { auth };
330
+
331
+ //# sourceMappingURL=auth-15xzL-eW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-15xzL-eW.js","names":[],"sources":["../src/auth.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport {\n getRawProviderConfig,\n isSupportedProviderType,\n normalizeProviderBaseUrl,\n setProviderConfig,\n SUPPORTED_PROVIDER_TYPES,\n type ProviderAuthType,\n type ProviderConfig,\n type ProviderType,\n} from \"./lib/config\"\nimport { loginCodex } from \"./lib/oauth/codex\"\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport { persistCodexCredentials, setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n provider?: string\n verbose: boolean\n showToken: boolean\n}\n\nconst authArgs = {\n provider: {\n type: \"string\",\n description:\n \"Provider to log in with or configure (copilot, codex, deepseek, dashscope, openrouter, custom)\",\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 provider access token on auth\",\n },\n} as const\n\nconst BUILTIN_PROVIDER_NAMES = [\"copilot\", \"codex\"] as const\nconst QUICK_PROVIDER_CONFIGS = {\n deepseek: {\n type: \"openai-compatible\",\n baseUrl: \"https://api.deepseek.com\",\n editableType: true,\n },\n dashscope: {\n type: \"openai-compatible\",\n baseUrl: \"https://dashscope.aliyuncs.com/compatible-mode\",\n editableType: true,\n },\n openrouter: {\n type: \"anthropic\",\n baseUrl: \"https://openrouter.ai/api\",\n editableType: false,\n },\n} satisfies Record<\n string,\n {\n type: ProviderType\n baseUrl: string\n editableType: boolean\n }\n>\nconst QUICK_PROVIDER_NAMES = Object.keys(QUICK_PROVIDER_CONFIGS) as Array<\n keyof typeof QUICK_PROVIDER_CONFIGS\n>\nconst AUTH_PROVIDER_NAMES = [\n ...BUILTIN_PROVIDER_NAMES,\n ...QUICK_PROVIDER_NAMES,\n \"custom\",\n] as const\nconst CUSTOM_PROVIDER_AUTH_TYPE_OPTION = \"__default__\"\nconst QUICK_PROVIDER_DEFAULT_TYPE_OPTION = \"__default__\"\nconst CUSTOM_PROVIDER_AUTH_TYPES = [\"x-api-key\", \"authorization\"] as const\n\ntype BuiltinProviderName = (typeof BUILTIN_PROVIDER_NAMES)[number]\ntype QuickProviderName = (typeof QUICK_PROVIDER_NAMES)[number]\ntype AuthProviderName = (typeof AUTH_PROVIDER_NAMES)[number]\ntype CustomProviderAuthType = (typeof CUSTOM_PROVIDER_AUTH_TYPES)[number]\n\nconst BUILTIN_PROVIDER_LABELS: Record<BuiltinProviderName, string> = {\n copilot: \"GitHub Copilot\",\n codex: \"OpenAI Codex\",\n}\nconst AUTH_PROVIDER_LABELS: Record<AuthProviderName, string> = {\n ...BUILTIN_PROVIDER_LABELS,\n deepseek: \"DeepSeek\",\n dashscope: \"DashScope\",\n openrouter: \"OpenRouter\",\n custom: \"Custom provider\",\n}\n\nfunction isAuthProviderName(\n providerName: string,\n): providerName is AuthProviderName {\n return AUTH_PROVIDER_NAMES.includes(providerName as AuthProviderName)\n}\n\nfunction isCustomProviderAuthType(\n value: string,\n): value is CustomProviderAuthType {\n return CUSTOM_PROVIDER_AUTH_TYPES.includes(value as CustomProviderAuthType)\n}\n\nfunction isQuickProviderName(\n providerName: AuthProviderName,\n): providerName is QuickProviderName {\n return QUICK_PROVIDER_NAMES.includes(providerName as QuickProviderName)\n}\n\nasync function resolveProviderSelection(\n providerArg: string | undefined,\n): Promise<AuthProviderName> {\n const availableProviders = [...AUTH_PROVIDER_NAMES]\n\n if (providerArg !== undefined) {\n const providerName = providerArg.trim()\n if (!isAuthProviderName(providerName)) {\n throw new Error(\n `Unknown provider '${providerArg}'. Expected one of: ${availableProviders.join(\", \")}`,\n )\n }\n return providerName\n }\n\n if (availableProviders.length === 1) {\n return availableProviders[0]\n }\n\n const provider = await consola.prompt(\"Select a provider to log in with\", {\n type: \"select\",\n options: availableProviders.map((providerName) => ({\n label: `${AUTH_PROVIDER_LABELS[providerName]} (${providerName})`,\n value: providerName,\n })),\n })\n\n if (!provider || !isAuthProviderName(provider)) {\n throw new Error(\"No provider selected\")\n }\n\n return provider\n}\n\nfunction assertCustomProviderName(providerName: string): void {\n if (!providerName) {\n throw new Error(\"Provider name must be a non-empty string\")\n }\n\n if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/u.test(providerName)) {\n throw new Error(\n \"Provider name must start with a letter or number and contain only letters, numbers, underscores, or hyphens\",\n )\n }\n\n if (providerName === \"copilot\" || providerName === \"codex\") {\n throw new Error(\n `Provider name '${providerName}' is reserved for a builtin provider`,\n )\n }\n}\n\nasync function promptRequiredText(\n message: string,\n fieldName: string,\n): Promise<string> {\n const value = await consola.prompt(message, { type: \"text\" })\n const normalizedValue = typeof value === \"string\" ? value.trim() : \"\"\n if (!normalizedValue) {\n throw new Error(`${fieldName} must be a non-empty string`)\n }\n return normalizedValue\n}\n\nfunction canUseMaskedPrompt(): boolean {\n return Boolean(\n process.stdin.isTTY\n && process.stdout.isTTY\n && typeof process.stdin.setRawMode === \"function\",\n )\n}\n\nasync function promptMaskedText(message: string): Promise<string> {\n if (!canUseMaskedPrompt()) {\n const value = await consola.prompt(message, { type: \"text\" })\n return typeof value === \"string\" ? value : \"\"\n }\n\n return await new Promise<string>((resolve, reject) => {\n let value = \"\"\n const rawModeWasEnabled = process.stdin.isRaw === true\n\n function cleanup(): void {\n process.stdin.off(\"data\", onData)\n process.stdin.setRawMode(rawModeWasEnabled)\n process.stdin.pause()\n }\n\n function finish(): void {\n cleanup()\n process.stdout.write(\"\\n\")\n resolve(value)\n }\n\n function cancel(): void {\n cleanup()\n process.stdout.write(\"\\n\")\n reject(new Error(\"Prompt cancelled\"))\n }\n\n function onData(chunk: Buffer): void {\n const input = chunk.toString(\"utf8\")\n\n if (input.startsWith(\"\\u001B\")) {\n return\n }\n\n for (const char of input) {\n if (char === \"\\u0003\") {\n cancel()\n return\n }\n\n if (char === \"\\r\" || char === \"\\n\") {\n finish()\n return\n }\n\n if (char === \"\\b\" || char === \"\\u007F\") {\n if (value.length > 0) {\n value = value.slice(0, -1)\n process.stdout.write(\"\\b \\b\")\n }\n continue\n }\n\n if (char >= \" \") {\n value += char\n process.stdout.write(\"*\")\n }\n }\n }\n\n process.stdout.write(`${message}: `)\n process.stdin.setRawMode(true)\n process.stdin.resume()\n process.stdin.on(\"data\", onData)\n })\n}\n\nasync function promptRequiredSecret(\n message: string,\n fieldName: string,\n): Promise<string> {\n const value = await promptMaskedText(message)\n const normalizedValue = value.trim()\n if (!normalizedValue) {\n throw new Error(`${fieldName} must be a non-empty string`)\n }\n return normalizedValue\n}\n\nasync function promptCustomProviderName(): Promise<string> {\n const providerName = await promptRequiredText(\n \"Enter provider name\",\n \"Provider name\",\n )\n assertCustomProviderName(providerName)\n return providerName\n}\n\nasync function promptCustomProviderType(): Promise<ProviderType> {\n const providerType = await consola.prompt(\"Select provider type\", {\n type: \"select\",\n options: SUPPORTED_PROVIDER_TYPES.map((type) => ({\n label: type,\n value: type,\n })),\n })\n\n if (\n typeof providerType !== \"string\"\n || !isSupportedProviderType(providerType)\n ) {\n throw new Error(\"No provider type selected\")\n }\n\n return providerType\n}\n\nasync function promptQuickProviderType(\n defaultType: ProviderType,\n): Promise<ProviderType> {\n const providerType = await consola.prompt(\n `Select provider type (default: ${defaultType})`,\n {\n type: \"select\",\n options: [\n {\n label: `Default (${defaultType})`,\n value: QUICK_PROVIDER_DEFAULT_TYPE_OPTION,\n },\n ...SUPPORTED_PROVIDER_TYPES.map((type) => ({\n label: type,\n value: type,\n })),\n ],\n },\n )\n\n if (providerType === QUICK_PROVIDER_DEFAULT_TYPE_OPTION) {\n return defaultType\n }\n\n if (\n typeof providerType === \"string\"\n && isSupportedProviderType(providerType)\n ) {\n return providerType\n }\n\n throw new Error(\"No provider type selected\")\n}\n\nfunction getDefaultProviderAuthType(\n providerType: ProviderType,\n): ProviderAuthType {\n return providerType === \"anthropic\" ? \"x-api-key\" : \"authorization\"\n}\n\nasync function promptCustomProviderAuthType(\n providerType: ProviderType,\n): Promise<ProviderAuthType | undefined> {\n const defaultAuthType = getDefaultProviderAuthType(providerType)\n const authType = await consola.prompt(\"Select provider auth type\", {\n type: \"select\",\n options: [\n {\n label: `Default (${defaultAuthType})`,\n value: CUSTOM_PROVIDER_AUTH_TYPE_OPTION,\n },\n ...CUSTOM_PROVIDER_AUTH_TYPES.map((value) => ({\n label: value,\n value,\n })),\n ],\n })\n\n if (authType === CUSTOM_PROVIDER_AUTH_TYPE_OPTION) {\n return undefined\n }\n\n if (typeof authType === \"string\" && isCustomProviderAuthType(authType)) {\n return authType\n }\n\n throw new Error(\"No provider auth type selected\")\n}\n\nasync function promptQuickProviderBaseUrl(\n defaultBaseUrl: string,\n): Promise<string> {\n const value = await consola.prompt(\n `Enter provider baseUrl (default: ${defaultBaseUrl})`,\n {\n type: \"text\",\n default: defaultBaseUrl,\n initial: defaultBaseUrl,\n },\n )\n const baseUrl = normalizeProviderBaseUrl(\n typeof value === \"string\" && value.trim() ? value : defaultBaseUrl,\n )\n if (!baseUrl) {\n throw new Error(\"baseUrl must be a non-empty string\")\n }\n\n return baseUrl\n}\n\nfunction buildCustomProviderConfig(\n existingProviderConfig: ProviderConfig,\n options: {\n apiKey: string\n authType?: ProviderAuthType\n baseUrl: string\n type: ProviderType\n },\n): ProviderConfig {\n return {\n type: options.type,\n enabled: true,\n baseUrl: options.baseUrl,\n apiKey: options.apiKey,\n ...(options.authType ? { authType: options.authType } : {}),\n ...(existingProviderConfig.models ?\n { models: existingProviderConfig.models }\n : {}),\n }\n}\n\nasync function configureCustomProvider(): Promise<void> {\n const providerName = await promptCustomProviderName()\n const type = await promptCustomProviderType()\n const baseUrl = normalizeProviderBaseUrl(\n await promptRequiredText(\"Enter provider baseUrl\", \"baseUrl\"),\n )\n if (!baseUrl) {\n throw new Error(\"baseUrl must be a non-empty string\")\n }\n\n const apiKey = await promptRequiredSecret(\"Enter provider apiKey\", \"apiKey\")\n const authType = await promptCustomProviderAuthType(type)\n const existingProviderConfig = getRawProviderConfig(providerName) ?? {}\n\n setProviderConfig(\n providerName,\n buildCustomProviderConfig(existingProviderConfig, {\n apiKey,\n authType,\n baseUrl,\n type,\n }),\n )\n\n consola.success(\n `Custom provider '${providerName}' written to ${PATHS.CONFIG_PATH}`,\n )\n}\n\nasync function configureQuickProvider(\n providerName: QuickProviderName,\n): Promise<void> {\n const defaultProviderConfig = QUICK_PROVIDER_CONFIGS[providerName]\n const apiKey = await promptRequiredSecret(\n `Enter ${providerName} apiKey`,\n \"apiKey\",\n )\n const type =\n defaultProviderConfig.editableType ?\n await promptQuickProviderType(defaultProviderConfig.type)\n : defaultProviderConfig.type\n const baseUrl = await promptQuickProviderBaseUrl(\n defaultProviderConfig.baseUrl,\n )\n const existingProviderConfig = getRawProviderConfig(providerName) ?? {}\n\n setProviderConfig(\n providerName,\n buildCustomProviderConfig(existingProviderConfig, {\n apiKey,\n baseUrl,\n type,\n }),\n )\n\n consola.success(\n `${AUTH_PROVIDER_LABELS[providerName]} provider '${providerName}' written to ${PATHS.CONFIG_PATH}`,\n )\n}\n\nasync function loginWithCodex(): Promise<void> {\n const credentials = await loginCodex({\n onAuth(info) {\n consola.info(\"Open the following URL to authenticate with Codex:\")\n consola.log(info.url)\n if (info.instructions) {\n consola.info(info.instructions)\n }\n },\n onPrompt(message) {\n return consola.prompt(message, {\n type: \"text\",\n })\n },\n onProgress(message) {\n consola.debug(message)\n },\n })\n\n await persistCodexCredentials(credentials, { enableProvider: true })\n consola.success(\n `Codex provider config written to ${PATHS.CONFIG_PATH} and credentials written to ${PATHS.CODEX_CREDENTIAL_PATH}`,\n )\n}\n\nasync function loginWithProvider(provider: AuthProviderName): Promise<void> {\n if (provider === \"copilot\") {\n await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n return\n }\n\n if (provider === \"codex\") {\n await loginWithCodex()\n return\n }\n\n if (isQuickProviderName(provider)) {\n await configureQuickProvider(provider)\n return\n }\n\n await configureCustomProvider()\n}\n\nexport async function runAuthLogin(options: RunAuthOptions): Promise<void> {\n const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = options.showToken\n\n await ensurePaths()\n const provider = await resolveProviderSelection(options.provider)\n\n consola.info(`Logging in with ${AUTH_PROVIDER_LABELS[provider]}`)\n await loginWithProvider(provider)\n}\n\nconst authLogin = defineCommand({\n meta: {\n name: \"login\",\n description:\n \"Authenticate or configure a provider without running the server\",\n },\n args: authArgs,\n run({ args }) {\n return runAuthLogin({\n provider: args.provider,\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run authentication flows without running the server\",\n },\n args: authArgs,\n subCommands: {\n login: authLogin,\n },\n run({ args }) {\n if ((args._[0] ?? \"\").trim()) {\n return\n }\n\n return runAuthLogin({\n provider: args.provider,\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n"],"mappings":";;;;;AA0BA,MAAM,WAAW;CACf,UAAU;EACR,MAAM;EACN,aACE;EACH;CACD,SAAS;EACP,OAAO;EACP,MAAM;EACN,SAAS;EACT,aAAa;EACd;CACD,cAAc;EACZ,MAAM;EACN,SAAS;EACT,aAAa;EACd;CACF;AAED,MAAM,yBAAyB,CAAC,WAAW,QAAQ;AACnD,MAAM,yBAAyB;CAC7B,UAAU;EACR,MAAM;EACN,SAAS;EACT,cAAc;EACf;CACD,WAAW;EACT,MAAM;EACN,SAAS;EACT,cAAc;EACf;CACD,YAAY;EACV,MAAM;EACN,SAAS;EACT,cAAc;EACf;CACF;AAQD,MAAM,uBAAuB,OAAO,KAAK,uBAAuB;AAGhE,MAAM,sBAAsB;CAC1B,GAAG;CACH,GAAG;CACH;CACD;AACD,MAAM,mCAAmC;AACzC,MAAM,qCAAqC;AAC3C,MAAM,6BAA6B,CAAC,aAAa,gBAAgB;AAWjE,MAAM,uBAAyD;CAH7D,SAAS;CACT,OAAO;CAIP,UAAU;CACV,WAAW;CACX,YAAY;CACZ,QAAQ;CACT;AAED,SAAS,mBACP,cACkC;CAClC,OAAO,oBAAoB,SAAS,aAAiC;;AAGvE,SAAS,yBACP,OACiC;CACjC,OAAO,2BAA2B,SAAS,MAAgC;;AAG7E,SAAS,oBACP,cACmC;CACnC,OAAO,qBAAqB,SAAS,aAAkC;;AAGzE,eAAe,yBACb,aAC2B;CAC3B,MAAM,qBAAqB,CAAC,GAAG,oBAAoB;CAEnD,IAAI,gBAAgB,KAAA,GAAW;EAC7B,MAAM,eAAe,YAAY,MAAM;EACvC,IAAI,CAAC,mBAAmB,aAAa,EACnC,MAAM,IAAI,MACR,qBAAqB,YAAY,sBAAsB,mBAAmB,KAAK,KAAK,GACrF;EAEH,OAAO;;CAGT,IAAI,mBAAmB,WAAW,GAChC,OAAO,mBAAmB;CAG5B,MAAM,WAAW,MAAM,QAAQ,OAAO,oCAAoC;EACxE,MAAM;EACN,SAAS,mBAAmB,KAAK,kBAAkB;GACjD,OAAO,GAAG,qBAAqB,cAAc,IAAI,aAAa;GAC9D,OAAO;GACR,EAAE;EACJ,CAAC;CAEF,IAAI,CAAC,YAAY,CAAC,mBAAmB,SAAS,EAC5C,MAAM,IAAI,MAAM,uBAAuB;CAGzC,OAAO;;AAGT,SAAS,yBAAyB,cAA4B;CAC5D,IAAI,CAAC,cACH,MAAM,IAAI,MAAM,2CAA2C;CAG7D,IAAI,CAAC,+BAA+B,KAAK,aAAa,EACpD,MAAM,IAAI,MACR,8GACD;CAGH,IAAI,iBAAiB,aAAa,iBAAiB,SACjD,MAAM,IAAI,MACR,kBAAkB,aAAa,sCAChC;;AAIL,eAAe,mBACb,SACA,WACiB;CACjB,MAAM,QAAQ,MAAM,QAAQ,OAAO,SAAS,EAAE,MAAM,QAAQ,CAAC;CAC7D,MAAM,kBAAkB,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG;CACnE,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,GAAG,UAAU,6BAA6B;CAE5D,OAAO;;AAGT,SAAS,qBAA8B;CACrC,OAAO,QACL,QAAQ,MAAM,SACT,QAAQ,OAAO,SACf,OAAO,QAAQ,MAAM,eAAe,WAC1C;;AAGH,eAAe,iBAAiB,SAAkC;CAChE,IAAI,CAAC,oBAAoB,EAAE;EACzB,MAAM,QAAQ,MAAM,QAAQ,OAAO,SAAS,EAAE,MAAM,QAAQ,CAAC;EAC7D,OAAO,OAAO,UAAU,WAAW,QAAQ;;CAG7C,OAAO,MAAM,IAAI,SAAiB,SAAS,WAAW;EACpD,IAAI,QAAQ;EACZ,MAAM,oBAAoB,QAAQ,MAAM,UAAU;EAElD,SAAS,UAAgB;GACvB,QAAQ,MAAM,IAAI,QAAQ,OAAO;GACjC,QAAQ,MAAM,WAAW,kBAAkB;GAC3C,QAAQ,MAAM,OAAO;;EAGvB,SAAS,SAAe;GACtB,SAAS;GACT,QAAQ,OAAO,MAAM,KAAK;GAC1B,QAAQ,MAAM;;EAGhB,SAAS,SAAe;GACtB,SAAS;GACT,QAAQ,OAAO,MAAM,KAAK;GAC1B,uBAAO,IAAI,MAAM,mBAAmB,CAAC;;EAGvC,SAAS,OAAO,OAAqB;GACnC,MAAM,QAAQ,MAAM,SAAS,OAAO;GAEpC,IAAI,MAAM,WAAW,OAAS,EAC5B;GAGF,KAAK,MAAM,QAAQ,OAAO;IACxB,IAAI,SAAS,KAAU;KACrB,QAAQ;KACR;;IAGF,IAAI,SAAS,QAAQ,SAAS,MAAM;KAClC,QAAQ;KACR;;IAGF,IAAI,SAAS,QAAQ,SAAS,KAAU;KACtC,IAAI,MAAM,SAAS,GAAG;MACpB,QAAQ,MAAM,MAAM,GAAG,GAAG;MAC1B,QAAQ,OAAO,MAAM,QAAQ;;KAE/B;;IAGF,IAAI,QAAQ,KAAK;KACf,SAAS;KACT,QAAQ,OAAO,MAAM,IAAI;;;;EAK/B,QAAQ,OAAO,MAAM,GAAG,QAAQ,IAAI;EACpC,QAAQ,MAAM,WAAW,KAAK;EAC9B,QAAQ,MAAM,QAAQ;EACtB,QAAQ,MAAM,GAAG,QAAQ,OAAO;GAChC;;AAGJ,eAAe,qBACb,SACA,WACiB;CAEjB,MAAM,mBAAkB,MADJ,iBAAiB,QAAQ,EACf,MAAM;CACpC,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,GAAG,UAAU,6BAA6B;CAE5D,OAAO;;AAGT,eAAe,2BAA4C;CACzD,MAAM,eAAe,MAAM,mBACzB,uBACA,gBACD;CACD,yBAAyB,aAAa;CACtC,OAAO;;AAGT,eAAe,2BAAkD;CAC/D,MAAM,eAAe,MAAM,QAAQ,OAAO,wBAAwB;EAChE,MAAM;EACN,SAAS,yBAAyB,KAAK,UAAU;GAC/C,OAAO;GACP,OAAO;GACR,EAAE;EACJ,CAAC;CAEF,IACE,OAAO,iBAAiB,YACrB,CAAC,wBAAwB,aAAa,EAEzC,MAAM,IAAI,MAAM,4BAA4B;CAG9C,OAAO;;AAGT,eAAe,wBACb,aACuB;CACvB,MAAM,eAAe,MAAM,QAAQ,OACjC,kCAAkC,YAAY,IAC9C;EACE,MAAM;EACN,SAAS,CACP;GACE,OAAO,YAAY,YAAY;GAC/B,OAAO;GACR,EACD,GAAG,yBAAyB,KAAK,UAAU;GACzC,OAAO;GACP,OAAO;GACR,EAAE,CACJ;EACF,CACF;CAED,IAAI,iBAAiB,oCACnB,OAAO;CAGT,IACE,OAAO,iBAAiB,YACrB,wBAAwB,aAAa,EAExC,OAAO;CAGT,MAAM,IAAI,MAAM,4BAA4B;;AAG9C,SAAS,2BACP,cACkB;CAClB,OAAO,iBAAiB,cAAc,cAAc;;AAGtD,eAAe,6BACb,cACuC;CACvC,MAAM,kBAAkB,2BAA2B,aAAa;CAChE,MAAM,WAAW,MAAM,QAAQ,OAAO,6BAA6B;EACjE,MAAM;EACN,SAAS,CACP;GACE,OAAO,YAAY,gBAAgB;GACnC,OAAO;GACR,EACD,GAAG,2BAA2B,KAAK,WAAW;GAC5C,OAAO;GACP;GACD,EAAE,CACJ;EACF,CAAC;CAEF,IAAI,aAAa,kCACf;CAGF,IAAI,OAAO,aAAa,YAAY,yBAAyB,SAAS,EACpE,OAAO;CAGT,MAAM,IAAI,MAAM,iCAAiC;;AAGnD,eAAe,2BACb,gBACiB;CACjB,MAAM,QAAQ,MAAM,QAAQ,OAC1B,oCAAoC,eAAe,IACnD;EACE,MAAM;EACN,SAAS;EACT,SAAS;EACV,CACF;CACD,MAAM,UAAU,yBACd,OAAO,UAAU,YAAY,MAAM,MAAM,GAAG,QAAQ,eACrD;CACD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,qCAAqC;CAGvD,OAAO;;AAGT,SAAS,0BACP,wBACA,SAMgB;CAChB,OAAO;EACL,MAAM,QAAQ;EACd,SAAS;EACT,SAAS,QAAQ;EACjB,QAAQ,QAAQ;EAChB,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,UAAU,GAAG,EAAE;EAC1D,GAAI,uBAAuB,SACzB,EAAE,QAAQ,uBAAuB,QAAQ,GACzC,EAAE;EACL;;AAGH,eAAe,0BAAyC;CACtD,MAAM,eAAe,MAAM,0BAA0B;CACrD,MAAM,OAAO,MAAM,0BAA0B;CAC7C,MAAM,UAAU,yBACd,MAAM,mBAAmB,0BAA0B,UAAU,CAC9D;CACD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,qCAAqC;CAGvD,MAAM,SAAS,MAAM,qBAAqB,yBAAyB,SAAS;CAC5E,MAAM,WAAW,MAAM,6BAA6B,KAAK;CAGzD,kBACE,cACA,0BAJ6B,qBAAqB,aAAa,IAAI,EAAE,EAInB;EAChD;EACA;EACA;EACA;EACD,CAAC,CACH;CAED,QAAQ,QACN,oBAAoB,aAAa,eAAe,MAAM,cACvD;;AAGH,eAAe,uBACb,cACe;CACf,MAAM,wBAAwB,uBAAuB;CACrD,MAAM,SAAS,MAAM,qBACnB,SAAS,aAAa,UACtB,SACD;CACD,MAAM,OACJ,sBAAsB,eACpB,MAAM,wBAAwB,sBAAsB,KAAK,GACzD,sBAAsB;CAC1B,MAAM,UAAU,MAAM,2BACpB,sBAAsB,QACvB;CAGD,kBACE,cACA,0BAJ6B,qBAAqB,aAAa,IAAI,EAAE,EAInB;EAChD;EACA;EACA;EACD,CAAC,CACH;CAED,QAAQ,QACN,GAAG,qBAAqB,cAAc,aAAa,aAAa,eAAe,MAAM,cACtF;;AAGH,eAAe,iBAAgC;CAmB7C,MAAM,wBAAwB,MAlBJ,WAAW;EACnC,OAAO,MAAM;GACX,QAAQ,KAAK,qDAAqD;GAClE,QAAQ,IAAI,KAAK,IAAI;GACrB,IAAI,KAAK,cACP,QAAQ,KAAK,KAAK,aAAa;;EAGnC,SAAS,SAAS;GAChB,OAAO,QAAQ,OAAO,SAAS,EAC7B,MAAM,QACP,CAAC;;EAEJ,WAAW,SAAS;GAClB,QAAQ,MAAM,QAAQ;;EAEzB,CAAC,EAEyC,EAAE,gBAAgB,MAAM,CAAC;CACpE,QAAQ,QACN,oCAAoC,MAAM,YAAY,8BAA8B,MAAM,wBAC3F;;AAGH,eAAe,kBAAkB,UAA2C;CAC1E,IAAI,aAAa,WAAW;EAC1B,MAAM,iBAAiB,EAAE,OAAO,MAAM,CAAC;EACvC,QAAQ,QAAQ,2BAA2B,MAAM,kBAAkB;EACnE;;CAGF,IAAI,aAAa,SAAS;EACxB,MAAM,gBAAgB;EACtB;;CAGF,IAAI,oBAAoB,SAAS,EAAE;EACjC,MAAM,uBAAuB,SAAS;EACtC;;CAGF,MAAM,yBAAyB;;AAGjC,eAAsB,aAAa,SAAwC;CAEzE,CAAA,MADwB,OAAO,sBACrB,sBAAsB;CAEhC,IAAI,QAAQ,SAAS;EACnB,QAAQ,QAAQ;EAChB,QAAQ,KAAK,0BAA0B;;CAGzC,MAAM,YAAY,QAAQ;CAE1B,MAAM,aAAa;CACnB,MAAM,WAAW,MAAM,yBAAyB,QAAQ,SAAS;CAEjE,QAAQ,KAAK,mBAAmB,qBAAqB,YAAY;CACjE,MAAM,kBAAkB,SAAS;;AAmBnC,MAAa,OAAO,cAAc;CAChC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM;CACN,aAAa,EACX,OAvBc,cAAc;EAC9B,MAAM;GACJ,MAAM;GACN,aACE;GACH;EACD,MAAM;EACN,IAAI,EAAE,QAAQ;GACZ,OAAO,aAAa;IAClB,UAAU,KAAK;IACf,SAAS,KAAK;IACd,WAAW,KAAK;IACjB,CAAC;;EAEL,CASU,EACR;CACD,IAAI,EAAE,QAAQ;EACZ,KAAK,KAAK,EAAE,MAAM,IAAI,MAAM,EAC1B;EAGF,OAAO,aAAa;GAClB,UAAU,KAAK;GACf,SAAS,KAAK;GACd,WAAW,KAAK;GACjB,CAAC;;CAEL,CAAC"}
@@ -1,5 +1,5 @@
1
- import { C as ensurePaths } from "./config-B-_X-1gj.js";
2
- import { _ as getCopilotUsage, a as setupGitHubToken } from "./token-CIpQTF2M.js";
1
+ import { E as ensurePaths } from "./config-B71_S_hQ.js";
2
+ import { _ as getCopilotUsage, a as setupGitHubToken } from "./token-fpw8tAQS.js";
3
3
  import { defineCommand } from "citty";
4
4
  import consola from "consola";
5
5
  //#region src/check-usage.ts
@@ -9,7 +9,7 @@ const checkUsage = defineCommand({
9
9
  description: "Show current GitHub Copilot usage/quota information"
10
10
  },
11
11
  async run() {
12
- (await import("./tls-CaLAeSaF.js")).enableSystemCACompat();
12
+ (await import("./tls-BniQ6Rel.js")).enableSystemCACompat();
13
13
  await ensurePaths();
14
14
  await setupGitHubToken();
15
15
  try {
@@ -40,4 +40,4 @@ const checkUsage = defineCommand({
40
40
  //#endregion
41
41
  export { checkUsage };
42
42
 
43
- //# sourceMappingURL=check-usage-A0wChz3s.js.map
43
+ //# sourceMappingURL=check-usage-Bu9w7RbA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"check-usage-A0wChz3s.js","names":[],"sources":["../src/check-usage.ts"],"sourcesContent":["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 const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\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":";;;;;AAUA,MAAa,aAAa,cAAc;CACtC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,MAAM;EAEV,CAAA,MADwB,OAAO,sBACrB,sBAAsB;EAEhC,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
+ {"version":3,"file":"check-usage-Bu9w7RbA.js","names":[],"sources":["../src/check-usage.ts"],"sourcesContent":["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 const tlsModule = await import(\"./lib/tls\")\n tlsModule.enableSystemCACompat()\n\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":";;;;;AAUA,MAAa,aAAa,cAAc;CACtC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,MAAM;EAEV,CAAA,MADwB,OAAO,sBACrB,sBAAsB;EAEhC,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"}