@howaboua/opencode-usage-plugin 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/command.d.ts.map +1 -1
- package/dist/hooks/command.js +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -8
- package/dist/providers/copilot/auth.d.ts +11 -0
- package/dist/providers/copilot/auth.d.ts.map +1 -0
- package/dist/providers/copilot/auth.js +60 -0
- package/dist/providers/copilot/index.d.ts +8 -0
- package/dist/providers/copilot/index.d.ts.map +1 -0
- package/dist/providers/copilot/index.js +127 -0
- package/dist/providers/copilot/response.d.ts +36 -0
- package/dist/providers/copilot/response.d.ts.map +1 -0
- package/dist/providers/copilot/response.js +46 -0
- package/dist/providers/copilot/types.d.ts +19 -0
- package/dist/providers/copilot/types.d.ts.map +1 -0
- package/dist/providers/copilot/types.js +12 -0
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -0
- package/dist/providers/proxy/fetch.d.ts +3 -2
- package/dist/providers/proxy/fetch.d.ts.map +1 -1
- package/dist/providers/proxy/fetch.js +3 -0
- package/dist/providers/proxy/index.d.ts +1 -2
- package/dist/providers/proxy/index.d.ts.map +1 -1
- package/dist/providers/proxy/index.js +2 -3
- package/dist/providers/proxy/types.d.ts +0 -9
- package/dist/providers/proxy/types.d.ts.map +1 -1
- package/dist/state.d.ts +1 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +1 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/status.d.ts.map +1 -1
- package/dist/ui/status.js +21 -0
- package/dist/usage/config.d.ts +6 -0
- package/dist/usage/config.d.ts.map +1 -0
- package/dist/{providers/proxy → usage}/config.js +13 -12
- package/dist/usage/fetch.d.ts.map +1 -1
- package/dist/usage/fetch.js +17 -11
- package/package.json +2 -2
- package/dist/providers/proxy/config.d.ts +0 -6
- package/dist/providers/proxy/config.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/hooks/command.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAI1C,KAAK,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAWxC,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACpC,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;CAClB,GAAG,IAAI,CAAC,KAAK,EAAE,wBAAwB,GAAG,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/hooks/command.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAI1C,KAAK,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAWxC,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACpC,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;CAClB,GAAG,IAAI,CAAC,KAAK,EAAE,wBAAwB,GAAG,QAAQ,CAAC,CAoDnD"}
|
package/dist/hooks/command.js
CHANGED
|
@@ -38,6 +38,8 @@ export function commandHooks(options) {
|
|
|
38
38
|
return options.state.availableProviders.codex;
|
|
39
39
|
if (s.provider === "proxy")
|
|
40
40
|
return options.state.availableProviders.proxy;
|
|
41
|
+
if (s.provider === "copilot")
|
|
42
|
+
return options.state.availableProviders.copilot;
|
|
41
43
|
return true;
|
|
42
44
|
});
|
|
43
45
|
await renderUsageStatus({
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAWjD,eAAO,MAAM,WAAW,EAAE,MAsDzB,CAAA;AAED,eAAe,WAAW,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,22 +5,32 @@
|
|
|
5
5
|
import { commandHooks, sessionHooks, proxyHooks } from "./hooks";
|
|
6
6
|
import { createUsageState } from "./state";
|
|
7
7
|
import { loadAuths } from "./usage/fetch";
|
|
8
|
-
import {
|
|
8
|
+
import { loadUsageConfig } from "./usage/config";
|
|
9
|
+
import { existsSync } from "fs";
|
|
10
|
+
import { getQuotaConfigPath, getUsageTokenPath } from "./providers/copilot/auth";
|
|
9
11
|
export const UsagePlugin = async ({ client }) => {
|
|
10
12
|
const state = createUsageState();
|
|
11
13
|
try {
|
|
12
|
-
const [auths,
|
|
14
|
+
const [auths, usageConfig] = await Promise.all([
|
|
13
15
|
loadAuths().catch(() => ({})),
|
|
14
|
-
|
|
16
|
+
loadUsageConfig().catch(() => ({})),
|
|
15
17
|
]);
|
|
16
18
|
state.availableProviders.codex =
|
|
17
|
-
|
|
18
|
-
?
|
|
19
|
-
: Boolean("codex" in auths && auths["codex"] || "openai" in auths && auths["openai"]);
|
|
19
|
+
usageConfig?.providers?.openai !== undefined
|
|
20
|
+
? usageConfig.providers.openai
|
|
21
|
+
: Boolean(("codex" in auths && auths["codex"]) || ("openai" in auths && auths["openai"]));
|
|
20
22
|
state.availableProviders.proxy =
|
|
21
|
-
|
|
23
|
+
usageConfig?.providers?.proxy !== undefined ? usageConfig.providers.proxy : Boolean(usageConfig?.endpoint);
|
|
24
|
+
const authRecord = auths;
|
|
25
|
+
state.availableProviders.copilot =
|
|
26
|
+
usageConfig?.providers?.copilot !== undefined
|
|
27
|
+
? usageConfig.providers.copilot
|
|
28
|
+
: Boolean(authRecord["github-copilot"] ||
|
|
29
|
+
authRecord["copilot"] ||
|
|
30
|
+
existsSync(getQuotaConfigPath()) ||
|
|
31
|
+
existsSync(getUsageTokenPath()));
|
|
22
32
|
}
|
|
23
|
-
catch { }
|
|
33
|
+
catch (err) { }
|
|
24
34
|
async function sendStatusMessage(sessionID, text) {
|
|
25
35
|
await client.session.prompt({
|
|
26
36
|
path: { id: sessionID },
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/auth.ts
|
|
3
|
+
* Provides authentication and configuration helpers for GitHub Copilot.
|
|
4
|
+
* Handles local auth token discovery and quota configuration reading.
|
|
5
|
+
*/
|
|
6
|
+
import { type CopilotAuthData, type CopilotQuotaConfig } from "./types.js";
|
|
7
|
+
export declare function getQuotaConfigPath(): string;
|
|
8
|
+
export declare function getUsageTokenPath(): string;
|
|
9
|
+
export declare function readCopilotAuth(): Promise<CopilotAuthData | null>;
|
|
10
|
+
export declare function readQuotaConfig(): CopilotQuotaConfig | null;
|
|
11
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/providers/copilot/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE1E,wBAAgB,kBAAkB,IAAI,MAAM,CAM3C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA4BvE;AAED,wBAAgB,eAAe,IAAI,kBAAkB,GAAG,IAAI,CAY3D"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/auth.ts
|
|
3
|
+
* Provides authentication and configuration helpers for GitHub Copilot.
|
|
4
|
+
* Handles local auth token discovery and quota configuration reading.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from "fs";
|
|
7
|
+
import { readFile } from "fs/promises";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
import { getAppDataPath, getAuthFilePath } from "../../utils/paths.js";
|
|
11
|
+
export function getQuotaConfigPath() {
|
|
12
|
+
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "opencode", "copilot-quota-token.json");
|
|
13
|
+
}
|
|
14
|
+
export function getUsageTokenPath() {
|
|
15
|
+
return join(getAppDataPath(), "copilot-usage-token.json");
|
|
16
|
+
}
|
|
17
|
+
export async function readCopilotAuth() {
|
|
18
|
+
try {
|
|
19
|
+
const usagePath = getUsageTokenPath();
|
|
20
|
+
if (existsSync(usagePath)) {
|
|
21
|
+
const content = await readFile(usagePath, "utf-8");
|
|
22
|
+
const data = JSON.parse(content);
|
|
23
|
+
if (data?.token) {
|
|
24
|
+
return {
|
|
25
|
+
type: "oauth",
|
|
26
|
+
refresh: data.token,
|
|
27
|
+
access: data.token,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const authPath = getAuthFilePath();
|
|
32
|
+
if (existsSync(authPath)) {
|
|
33
|
+
const content = await readFile(authPath, "utf-8");
|
|
34
|
+
const authData = JSON.parse(content);
|
|
35
|
+
const copilotAuth = authData?.["github-copilot"] || authData?.["copilot"];
|
|
36
|
+
if (copilotAuth) {
|
|
37
|
+
return copilotAuth;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function readQuotaConfig() {
|
|
47
|
+
try {
|
|
48
|
+
const configPath = getQuotaConfigPath();
|
|
49
|
+
if (!existsSync(configPath))
|
|
50
|
+
return null;
|
|
51
|
+
const content = readFileSync(configPath, "utf-8");
|
|
52
|
+
const parsed = JSON.parse(content);
|
|
53
|
+
if (!parsed?.token || !parsed?.username || !parsed?.tier)
|
|
54
|
+
return null;
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/index.ts
|
|
3
|
+
* Main entry point for the GitHub Copilot usage provider.
|
|
4
|
+
* Orchestrates token exchange and fetching from public and internal APIs.
|
|
5
|
+
*/
|
|
6
|
+
import type { UsageProvider } from "../base.js";
|
|
7
|
+
export declare const CopilotProvider: UsageProvider<void>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/copilot/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAiE/C,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,IAAI,CAgF/C,CAAA"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/index.ts
|
|
3
|
+
* Main entry point for the GitHub Copilot usage provider.
|
|
4
|
+
* Orchestrates token exchange and fetching from public and internal APIs.
|
|
5
|
+
*/
|
|
6
|
+
import { COPILOT_PLAN_LIMITS } from "./types.js";
|
|
7
|
+
import { readCopilotAuth, readQuotaConfig } from "./auth.js";
|
|
8
|
+
import { toCopilotQuotaFromBilling, toCopilotQuotaFromInternal, } from "./response.js";
|
|
9
|
+
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
10
|
+
const COPILOT_INTERNAL_USER_URL = `${GITHUB_API_BASE_URL}/copilot_internal/user`;
|
|
11
|
+
const COPILOT_TOKEN_EXCHANGE_URL = `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`;
|
|
12
|
+
const COPILOT_VERSION = "0.35.0";
|
|
13
|
+
const EDITOR_VERSION = "vscode/1.107.0";
|
|
14
|
+
const EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`;
|
|
15
|
+
const USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`;
|
|
16
|
+
const COPILOT_HEADERS = {
|
|
17
|
+
"User-Agent": USER_AGENT,
|
|
18
|
+
"Editor-Version": EDITOR_VERSION,
|
|
19
|
+
"Editor-Plugin-Version": EDITOR_PLUGIN_VERSION,
|
|
20
|
+
"Copilot-Integration-Id": "vscode-chat",
|
|
21
|
+
};
|
|
22
|
+
const REQUEST_TIMEOUT_MS = 3000;
|
|
23
|
+
async function fetchWithTimeout(url, options, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
26
|
+
try {
|
|
27
|
+
return await fetch(url, {
|
|
28
|
+
...options,
|
|
29
|
+
signal: controller.signal,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
clearTimeout(timeoutId);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function exchangeForCopilotToken(oauthToken) {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetchWithTimeout(COPILOT_TOKEN_EXCHANGE_URL, {
|
|
39
|
+
headers: {
|
|
40
|
+
Accept: "application/json",
|
|
41
|
+
Authorization: `Bearer ${oauthToken}`,
|
|
42
|
+
...COPILOT_HEADERS,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
if (!response.ok)
|
|
46
|
+
return null;
|
|
47
|
+
const data = (await response.json());
|
|
48
|
+
return data.token;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export const CopilotProvider = {
|
|
55
|
+
id: "copilot",
|
|
56
|
+
displayName: "GitHub Copilot",
|
|
57
|
+
async fetchUsage() {
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
let quota = null;
|
|
60
|
+
const config = readQuotaConfig();
|
|
61
|
+
if (config) {
|
|
62
|
+
try {
|
|
63
|
+
const resp = await fetchWithTimeout(`${GITHUB_API_BASE_URL}/users/${config.username}/settings/billing/premium_request/usage`, {
|
|
64
|
+
headers: {
|
|
65
|
+
Accept: "application/vnd.github+json",
|
|
66
|
+
Authorization: `Bearer ${config.token}`,
|
|
67
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
if (resp.ok) {
|
|
71
|
+
const data = (await resp.json());
|
|
72
|
+
quota = toCopilotQuotaFromBilling(data, COPILOT_PLAN_LIMITS[config.tier]);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Fallback to internal API
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!quota) {
|
|
80
|
+
const auth = await readCopilotAuth();
|
|
81
|
+
const oauthToken = auth?.refresh || auth?.access;
|
|
82
|
+
if (oauthToken) {
|
|
83
|
+
try {
|
|
84
|
+
let resp = await fetchWithTimeout(COPILOT_INTERNAL_USER_URL, {
|
|
85
|
+
headers: {
|
|
86
|
+
Accept: "application/json",
|
|
87
|
+
Authorization: `token ${oauthToken}`,
|
|
88
|
+
...COPILOT_HEADERS,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
if (!resp.ok) {
|
|
92
|
+
const copilotToken = await exchangeForCopilotToken(oauthToken);
|
|
93
|
+
if (copilotToken) {
|
|
94
|
+
resp = await fetchWithTimeout(COPILOT_INTERNAL_USER_URL, {
|
|
95
|
+
headers: {
|
|
96
|
+
Accept: "application/json",
|
|
97
|
+
Authorization: `Bearer ${copilotToken}`,
|
|
98
|
+
...COPILOT_HEADERS,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (resp.ok) {
|
|
104
|
+
const data = (await resp.json());
|
|
105
|
+
quota = toCopilotQuotaFromInternal(data);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Ignore
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!quota)
|
|
114
|
+
return null;
|
|
115
|
+
return {
|
|
116
|
+
timestamp: now,
|
|
117
|
+
provider: "copilot",
|
|
118
|
+
planType: null,
|
|
119
|
+
primary: null,
|
|
120
|
+
secondary: null,
|
|
121
|
+
codeReview: null,
|
|
122
|
+
credits: null,
|
|
123
|
+
copilotQuota: quota,
|
|
124
|
+
updatedAt: now,
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/response.ts
|
|
3
|
+
* Transformations for GitHub Copilot API responses into internal quota formats.
|
|
4
|
+
* Handles both public billing and internal user API shapes.
|
|
5
|
+
*/
|
|
6
|
+
import type { CopilotQuota } from "../../types.js";
|
|
7
|
+
export interface CopilotInternalUserResponse {
|
|
8
|
+
limited_user_quotas?: {
|
|
9
|
+
chat?: number;
|
|
10
|
+
completions?: number;
|
|
11
|
+
};
|
|
12
|
+
limited_user_reset_date?: string;
|
|
13
|
+
quota_reset_date: string;
|
|
14
|
+
quota_snapshots?: {
|
|
15
|
+
premium_interactions?: {
|
|
16
|
+
entitlement: number;
|
|
17
|
+
percent_remaining: number;
|
|
18
|
+
remaining: number;
|
|
19
|
+
unlimited: boolean;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
monthly_quotas?: {
|
|
23
|
+
chat: number;
|
|
24
|
+
completions: number;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export interface BillingUsageItem {
|
|
28
|
+
sku: string;
|
|
29
|
+
grossQuantity: number;
|
|
30
|
+
}
|
|
31
|
+
export interface BillingUsageResponse {
|
|
32
|
+
usageItems: BillingUsageItem[];
|
|
33
|
+
}
|
|
34
|
+
export declare function toCopilotQuotaFromInternal(data: CopilotInternalUserResponse): CopilotQuota | null;
|
|
35
|
+
export declare function toCopilotQuotaFromBilling(data: BillingUsageResponse, limit: number): CopilotQuota;
|
|
36
|
+
//# sourceMappingURL=response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../src/providers/copilot/response.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,MAAM,WAAW,2BAA2B;IAC1C,mBAAmB,CAAC,EAAE;QACpB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE;QAChB,oBAAoB,CAAC,EAAE;YACrB,WAAW,EAAE,MAAM,CAAA;YACnB,iBAAiB,EAAE,MAAM,CAAA;YACzB,SAAS,EAAE,MAAM,CAAA;YACjB,SAAS,EAAE,OAAO,CAAA;SACnB,CAAA;KACF,CAAA;IACD,cAAc,CAAC,EAAE;QACf,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;CACF;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,gBAAgB,EAAE,CAAA;CAC/B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,2BAA2B,GAAG,YAAY,GAAG,IAAI,CA8BjG;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,oBAAoB,EAC1B,KAAK,EAAE,MAAM,GACZ,YAAY,CAed"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/response.ts
|
|
3
|
+
* Transformations for GitHub Copilot API responses into internal quota formats.
|
|
4
|
+
* Handles both public billing and internal user API shapes.
|
|
5
|
+
*/
|
|
6
|
+
export function toCopilotQuotaFromInternal(data) {
|
|
7
|
+
// Handle "limited" user format (Free/Pro limited)
|
|
8
|
+
if (data.limited_user_quotas) {
|
|
9
|
+
const chatRemaining = data.limited_user_quotas.chat ?? 0;
|
|
10
|
+
const chatTotal = data.monthly_quotas?.chat ?? 50;
|
|
11
|
+
const completionsRemaining = data.limited_user_quotas.completions ?? 0;
|
|
12
|
+
const completionsTotal = data.monthly_quotas?.completions ?? 2000;
|
|
13
|
+
return {
|
|
14
|
+
used: Math.max(0, chatTotal - chatRemaining),
|
|
15
|
+
total: chatTotal,
|
|
16
|
+
percentRemaining: chatTotal > 0 ? Math.round((chatRemaining / chatTotal) * 100) : 0,
|
|
17
|
+
resetTime: data.limited_user_reset_date || data.quota_reset_date,
|
|
18
|
+
completionsUsed: Math.max(0, completionsTotal - completionsRemaining),
|
|
19
|
+
completionsTotal: completionsTotal,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Handle standard format
|
|
23
|
+
if (data.quota_snapshots?.premium_interactions) {
|
|
24
|
+
const premium = data.quota_snapshots.premium_interactions;
|
|
25
|
+
return {
|
|
26
|
+
used: premium.unlimited ? 0 : premium.entitlement - premium.remaining,
|
|
27
|
+
total: premium.unlimited ? -1 : premium.entitlement,
|
|
28
|
+
percentRemaining: Math.round(premium.percent_remaining),
|
|
29
|
+
resetTime: data.quota_reset_date,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
export function toCopilotQuotaFromBilling(data, limit) {
|
|
35
|
+
const items = Array.isArray(data.usageItems) ? data.usageItems : [];
|
|
36
|
+
const used = items
|
|
37
|
+
.filter((i) => i.sku === "Copilot Premium Request" || i.sku.includes("Premium"))
|
|
38
|
+
.reduce((sum, i) => sum + (i.grossQuantity || 0), 0);
|
|
39
|
+
const remaining = Math.max(0, limit - used);
|
|
40
|
+
return {
|
|
41
|
+
used,
|
|
42
|
+
total: limit,
|
|
43
|
+
percentRemaining: Math.round((remaining / limit) * 100),
|
|
44
|
+
resetTime: new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth() + 1, 1)).toISOString(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/types.ts
|
|
3
|
+
* Defines internal types and constants for the GitHub Copilot provider.
|
|
4
|
+
* Includes auth data shapes and plan limit configurations.
|
|
5
|
+
*/
|
|
6
|
+
export type CopilotTier = "free" | "pro" | "pro+" | "business" | "enterprise";
|
|
7
|
+
export interface CopilotQuotaConfig {
|
|
8
|
+
token: string;
|
|
9
|
+
username: string;
|
|
10
|
+
tier: CopilotTier;
|
|
11
|
+
}
|
|
12
|
+
export interface CopilotAuthData {
|
|
13
|
+
type: string;
|
|
14
|
+
refresh?: string;
|
|
15
|
+
access?: string;
|
|
16
|
+
expires?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare const COPILOT_PLAN_LIMITS: Record<CopilotTier, number>;
|
|
19
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/copilot/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,CAAA;AAE7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAM3D,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providers/copilot/types.ts
|
|
3
|
+
* Defines internal types and constants for the GitHub Copilot provider.
|
|
4
|
+
* Includes auth data shapes and plan limit configurations.
|
|
5
|
+
*/
|
|
6
|
+
export const COPILOT_PLAN_LIMITS = {
|
|
7
|
+
free: 50,
|
|
8
|
+
pro: 300,
|
|
9
|
+
"pro+": 1500,
|
|
10
|
+
business: 300,
|
|
11
|
+
enterprise: 1000,
|
|
12
|
+
};
|
|
@@ -2,5 +2,6 @@ import type { UsageProvider } from "./base";
|
|
|
2
2
|
export declare const providers: Record<string, UsageProvider<unknown>>;
|
|
3
3
|
export { CodexProvider } from "./codex";
|
|
4
4
|
export { ProxyProvider } from "./proxy";
|
|
5
|
+
export { CopilotProvider } from "./copilot";
|
|
5
6
|
export type { UsageProvider } from "./base";
|
|
6
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA;AAK3C,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAI5D,CAAA;AAED,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,YAAY,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA"}
|
package/dist/providers/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { CodexProvider } from "./codex";
|
|
2
2
|
import { ProxyProvider } from "./proxy";
|
|
3
|
+
import { CopilotProvider } from "./copilot";
|
|
3
4
|
export const providers = {
|
|
4
5
|
[CodexProvider.id]: CodexProvider,
|
|
5
6
|
[ProxyProvider.id]: ProxyProvider,
|
|
7
|
+
[CopilotProvider.id]: CopilotProvider,
|
|
6
8
|
};
|
|
7
9
|
export { CodexProvider } from "./codex";
|
|
8
10
|
export { ProxyProvider } from "./proxy";
|
|
11
|
+
export { CopilotProvider } from "./copilot";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HTTP client for fetching proxy quota stats.
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
5
|
-
|
|
4
|
+
import type { ProxyResponse } from "./types";
|
|
5
|
+
import type { UsageConfig } from "../../types";
|
|
6
|
+
export declare function fetchProxyLimits(config: UsageConfig): Promise<ProxyResponse>;
|
|
6
7
|
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAoClF"}
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Fetches quota stats from a local/remote proxy server.
|
|
4
4
|
*/
|
|
5
5
|
import type { UsageProvider } from "../base";
|
|
6
|
-
export type {
|
|
7
|
-
export { loadProxyConfig } from "./config";
|
|
6
|
+
export type { ProxyResponse } from "./types";
|
|
8
7
|
export { fetchProxyLimits } from "./fetch";
|
|
9
8
|
export { formatProxyLimits } from "./format";
|
|
10
9
|
export declare const ProxyProvider: UsageProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAM5C,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAM5C,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAiK5C,eAAO,MAAM,aAAa,EAAE,aAwB3B,CAAA"}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* Antigravity Proxy provider for usage tracking.
|
|
3
3
|
* Fetches quota stats from a local/remote proxy server.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { loadUsageConfig } from "../../usage/config";
|
|
6
6
|
import { fetchProxyLimits } from "./fetch";
|
|
7
|
-
export { loadProxyConfig } from "./config";
|
|
8
7
|
export { fetchProxyLimits } from "./fetch";
|
|
9
8
|
export { formatProxyLimits } from "./format";
|
|
10
9
|
const GROUP_MAPPING = {
|
|
@@ -157,7 +156,7 @@ export const ProxyProvider = {
|
|
|
157
156
|
displayName: "Mirrowel Proxy",
|
|
158
157
|
async fetchUsage() {
|
|
159
158
|
try {
|
|
160
|
-
const config = await
|
|
159
|
+
const config = await loadUsageConfig();
|
|
161
160
|
const data = await fetchProxyLimits(config);
|
|
162
161
|
return {
|
|
163
162
|
timestamp: data.timestamp * 1000,
|
|
@@ -2,15 +2,6 @@
|
|
|
2
2
|
* Type definitions for the Antigravity proxy provider.
|
|
3
3
|
*/
|
|
4
4
|
/** Configuration stored in ~/.config/opencode/usage-config.jsonc */
|
|
5
|
-
export type ProxyConfig = {
|
|
6
|
-
endpoint: string;
|
|
7
|
-
apiKey?: string;
|
|
8
|
-
timeout?: number;
|
|
9
|
-
providers?: {
|
|
10
|
-
openai?: boolean;
|
|
11
|
-
proxy?: boolean;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
5
|
/** Token statistics from the proxy */
|
|
15
6
|
export type TokenStats = {
|
|
16
7
|
input_cached?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oEAAoE;AACpE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/types.ts"],"names":[],"mappings":"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"}
|
package/dist/state.d.ts
CHANGED
package/dist/state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C,kBAAkB,EAAE;QAClB,KAAK,EAAE,OAAO,CAAA;QACd,KAAK,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C,kBAAkB,EAAE;QAClB,KAAK,EAAE,OAAO,CAAA;QACd,KAAK,EAAE,OAAO,CAAA;QACd,OAAO,EAAE,OAAO,CAAA;KACjB,CAAA;CACF,CAAA;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CAS7C"}
|
package/dist/state.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -13,6 +13,14 @@ export interface CreditsSnapshot {
|
|
|
13
13
|
unlimited: boolean;
|
|
14
14
|
balance: string | null;
|
|
15
15
|
}
|
|
16
|
+
export interface CopilotQuota {
|
|
17
|
+
used: number;
|
|
18
|
+
total: number;
|
|
19
|
+
percentRemaining: number;
|
|
20
|
+
resetTime?: string | null;
|
|
21
|
+
completionsUsed?: number;
|
|
22
|
+
completionsTotal?: number;
|
|
23
|
+
}
|
|
16
24
|
export interface ProxyQuotaGroup {
|
|
17
25
|
name: string;
|
|
18
26
|
remaining: number;
|
|
@@ -34,6 +42,16 @@ export interface ProxyQuota {
|
|
|
34
42
|
activeCredentials: number;
|
|
35
43
|
dataSource: string;
|
|
36
44
|
}
|
|
45
|
+
export interface UsageConfig {
|
|
46
|
+
endpoint?: string;
|
|
47
|
+
apiKey?: string;
|
|
48
|
+
timeout?: number;
|
|
49
|
+
providers?: {
|
|
50
|
+
openai?: boolean;
|
|
51
|
+
proxy?: boolean;
|
|
52
|
+
copilot?: boolean;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
37
55
|
export interface UsageSnapshot {
|
|
38
56
|
timestamp: number;
|
|
39
57
|
provider: string;
|
|
@@ -43,6 +61,7 @@ export interface UsageSnapshot {
|
|
|
43
61
|
codeReview: RateLimitWindow | null;
|
|
44
62
|
credits: CreditsSnapshot | null;
|
|
45
63
|
proxyQuota?: ProxyQuota;
|
|
64
|
+
copilotQuota?: CopilotQuota;
|
|
46
65
|
updatedAt: number;
|
|
47
66
|
}
|
|
48
67
|
export interface UsageEntry {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,SAAS,0IAcZ,CAAA;AAEV,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAA;AAEjD,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,WAAW,EAAE,eAAe,EAAE,CAAA;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,aAAa,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,iBAAiB,EAAE,CAAA;IAC9B,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,eAAe,GAAG,IAAI,CAAA;IAC/B,SAAS,EAAE,eAAe,GAAG,IAAI,CAAA;IACjC,UAAU,EAAE,eAAe,GAAG,IAAI,CAAA;IAClC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAA;IAE/B,UAAU,CAAC,EAAE,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/status.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/ui/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,KAAK,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAExC,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAAC,IAAI,CAAC,CAwChB;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/ui/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,KAAK,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;AAExC,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAAC,IAAI,CAAC,CAwChB;AAwID,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,UAAU,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,aAAa,EAAE,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BhB"}
|
package/dist/ui/status.js
CHANGED
|
@@ -103,10 +103,31 @@ function formatProxySnapshot(snapshot) {
|
|
|
103
103
|
}
|
|
104
104
|
return lines;
|
|
105
105
|
}
|
|
106
|
+
function formatCopilotSnapshot(snapshot) {
|
|
107
|
+
const copilot = snapshot.copilotQuota;
|
|
108
|
+
if (!copilot)
|
|
109
|
+
return ["→ [copilot] No data"];
|
|
110
|
+
const lines = ["→ [GITHUB] Copilot"];
|
|
111
|
+
const resetSuffix = copilot.resetTime ? formatResetSuffixISO(copilot.resetTime) : "";
|
|
112
|
+
const totalLabel = copilot.total === -1 ? "∞" : copilot.total.toString();
|
|
113
|
+
const chatLabel = "Chat:".padEnd(13);
|
|
114
|
+
lines.push(` ${chatLabel} ${formatBar(copilot.percentRemaining)} ${copilot.used}/${totalLabel}${resetSuffix}`);
|
|
115
|
+
if (copilot.completionsUsed !== undefined && copilot.completionsTotal !== undefined) {
|
|
116
|
+
const compLabel = "Completions:".padEnd(13);
|
|
117
|
+
const compPct = copilot.completionsTotal > 0
|
|
118
|
+
? Math.round(((copilot.completionsTotal - copilot.completionsUsed) / copilot.completionsTotal) * 100)
|
|
119
|
+
: 0;
|
|
120
|
+
lines.push(` ${compLabel} ${formatBar(compPct)} ${copilot.completionsUsed}/${copilot.completionsTotal}`);
|
|
121
|
+
}
|
|
122
|
+
return lines;
|
|
123
|
+
}
|
|
106
124
|
function formatSnapshot(snapshot) {
|
|
107
125
|
if (snapshot.provider === "proxy" && snapshot.proxyQuota) {
|
|
108
126
|
return formatProxySnapshot(snapshot);
|
|
109
127
|
}
|
|
128
|
+
if (snapshot.provider === "copilot" && snapshot.copilotQuota) {
|
|
129
|
+
return formatCopilotSnapshot(snapshot);
|
|
130
|
+
}
|
|
110
131
|
const plan = snapshot.planType ? ` (${formatPlanType(snapshot.planType)})` : "";
|
|
111
132
|
const lines = [`→ [${snapshot.provider.toUpperCase()}]${plan}`];
|
|
112
133
|
const primary = snapshot.primary;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/usage/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAI3C,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,CAsD5D"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Configuration management for the
|
|
2
|
+
* Configuration management for the Usage Plugin.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
const CONFIG_PATH = join(homedir(), ".config", "opencode", "usage-config.jsonc");
|
|
7
|
+
export async function loadUsageConfig() {
|
|
6
8
|
const file = Bun.file(CONFIG_PATH);
|
|
7
9
|
if (!(await file.exists())) {
|
|
8
10
|
const content = `/**
|
|
9
11
|
* Usage Plugin Configuration
|
|
10
12
|
*/
|
|
11
13
|
{
|
|
12
|
-
// Proxy endpoint
|
|
13
|
-
"endpoint": "
|
|
14
|
+
// Proxy endpoint (e.g. http://localhost:8000)
|
|
15
|
+
"endpoint": "",
|
|
14
16
|
|
|
15
17
|
// API key for authentication
|
|
16
|
-
"apiKey": "
|
|
18
|
+
"apiKey": "",
|
|
17
19
|
|
|
18
20
|
// Request timeout in milliseconds
|
|
19
21
|
"timeout": 10000,
|
|
@@ -21,18 +23,20 @@ export async function loadProxyConfig() {
|
|
|
21
23
|
// Provider visibility
|
|
22
24
|
"providers": {
|
|
23
25
|
"openai": true,
|
|
24
|
-
"proxy": true
|
|
26
|
+
"proxy": true,
|
|
27
|
+
"copilot": true
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
`;
|
|
28
31
|
await Bun.write(CONFIG_PATH, content);
|
|
29
32
|
return {
|
|
30
|
-
endpoint: "
|
|
31
|
-
apiKey: "
|
|
33
|
+
endpoint: "",
|
|
34
|
+
apiKey: "",
|
|
32
35
|
timeout: 10000,
|
|
33
36
|
providers: {
|
|
34
37
|
openai: true,
|
|
35
38
|
proxy: true,
|
|
39
|
+
copilot: true,
|
|
36
40
|
},
|
|
37
41
|
};
|
|
38
42
|
}
|
|
@@ -43,9 +47,6 @@ export async function loadProxyConfig() {
|
|
|
43
47
|
// Remove trailing commas before closing brackets/braces
|
|
44
48
|
const cleanJson = withoutComments.replace(/,(\s*[}\]])/g, "$1");
|
|
45
49
|
const config = JSON.parse(cleanJson);
|
|
46
|
-
if (!config.endpoint) {
|
|
47
|
-
throw new Error('Config must contain "endpoint" field');
|
|
48
|
-
}
|
|
49
50
|
return config;
|
|
50
51
|
}
|
|
51
52
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/usage/fetch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAG7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAe5C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/usage/fetch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAG7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAe5C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWlD,CAAA;AAED,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,wBAAsB,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAoCnF;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,CASrD"}
|
package/dist/usage/fetch.js
CHANGED
|
@@ -24,6 +24,9 @@ export const providerAliases = {
|
|
|
24
24
|
agy: "proxy",
|
|
25
25
|
antigravity: "proxy",
|
|
26
26
|
gemini: "proxy",
|
|
27
|
+
copilot: "copilot",
|
|
28
|
+
gh: "copilot",
|
|
29
|
+
github: "copilot",
|
|
27
30
|
};
|
|
28
31
|
export function resolveProviderFilter(filter) {
|
|
29
32
|
if (!filter)
|
|
@@ -47,17 +50,20 @@ export async function fetchUsageSnapshots(filter) {
|
|
|
47
50
|
if (snapshot)
|
|
48
51
|
snapshots.push(snapshot);
|
|
49
52
|
});
|
|
50
|
-
// Always include
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
// Always include special providers (no auth entries needed) if no filter or filter matches
|
|
54
|
+
const specialProviders = ["proxy", "copilot"];
|
|
55
|
+
for (const id of specialProviders) {
|
|
56
|
+
if (!targetProvider || targetProvider === id) {
|
|
57
|
+
const provider = providers[id];
|
|
58
|
+
if (provider?.fetchUsage) {
|
|
59
|
+
fetches.push(provider
|
|
60
|
+
.fetchUsage(undefined)
|
|
61
|
+
.then((snapshot) => {
|
|
62
|
+
if (snapshot)
|
|
63
|
+
snapshots.push(snapshot);
|
|
64
|
+
})
|
|
65
|
+
.catch(() => { }));
|
|
66
|
+
}
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
await Promise.race([Promise.all(fetches), timeout(5000)]);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@howaboua/opencode-usage-plugin",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "opencode plugin for tracking AI provider usage, rate limits, and quotas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/providers/proxy/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAI1C,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,CAwD5D"}
|