@kenkaiiii/gg-core 5.9.7 → 5.10.0

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/index.cjs CHANGED
@@ -35,12 +35,14 @@ __export(index_exports, {
35
35
  MODELS: () => MODELS,
36
36
  MOONSHOT_OAUTH_KEY: () => MOONSHOT_OAUTH_KEY,
37
37
  NotLoggedInError: () => NotLoggedInError,
38
+ SubscriptionUsageError: () => SubscriptionUsageError,
38
39
  TelegramBot: () => TelegramBot,
39
40
  XIAOMI_CREDITS_KEY: () => XIAOMI_CREDITS_KEY,
40
41
  closeLogger: () => closeLogger,
41
42
  createAutoUpdater: () => createAutoUpdater,
42
43
  decodeOggOpus: () => decodeOggOpus,
43
44
  downmixToMono: () => downmixToMono,
45
+ fetchSubscriptionUsage: () => fetchSubscriptionUsage,
44
46
  generatePKCE: () => generatePKCE,
45
47
  getAppPaths: () => getAppPaths,
46
48
  getAuthStorageKey: () => getAuthStorageKey,
@@ -1962,6 +1964,147 @@ function getNextThinkingLevel(provider, model, current) {
1962
1964
  return supportedLevels[index + 1];
1963
1965
  }
1964
1966
 
1967
+ // src/provider-usage.ts
1968
+ var SubscriptionUsageError = class extends Error {
1969
+ constructor(message, status) {
1970
+ super(message);
1971
+ this.status = status;
1972
+ this.name = "SubscriptionUsageError";
1973
+ }
1974
+ };
1975
+ var ANTHROPIC_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
1976
+ var CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
1977
+ function finiteNumber(value) {
1978
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1979
+ }
1980
+ function clampPercent(value) {
1981
+ const number = finiteNumber(value);
1982
+ return number === void 0 ? void 0 : Math.min(100, Math.max(0, number));
1983
+ }
1984
+ function isoTimestamp(value) {
1985
+ if (typeof value !== "string" || !value.trim()) return void 0;
1986
+ const timestamp = Date.parse(value);
1987
+ return Number.isFinite(timestamp) ? timestamp : void 0;
1988
+ }
1989
+ function unixTimestamp(value) {
1990
+ const seconds = finiteNumber(value);
1991
+ return seconds === void 0 ? void 0 : seconds * 1e3;
1992
+ }
1993
+ function codexResetAt(window, now) {
1994
+ const absolute = unixTimestamp(window.reset_at);
1995
+ if (absolute !== void 0) return absolute;
1996
+ const afterSeconds = finiteNumber(window.reset_after_seconds);
1997
+ return afterSeconds === void 0 ? void 0 : now + afterSeconds * 1e3;
1998
+ }
1999
+ function currentWindowLabel(seconds, fallbackHours) {
2000
+ const duration = finiteNumber(seconds);
2001
+ const hours = Math.max(1, Math.round((duration ?? fallbackHours * 3600) / 3600));
2002
+ return `${hours}-hour`;
2003
+ }
2004
+ async function readUsageResponse(response) {
2005
+ const text = await response.text();
2006
+ if (!response.ok) {
2007
+ throw new SubscriptionUsageError(
2008
+ `Subscription usage request failed with HTTP ${response.status}`,
2009
+ response.status
2010
+ );
2011
+ }
2012
+ try {
2013
+ return JSON.parse(text);
2014
+ } catch {
2015
+ throw new SubscriptionUsageError("Subscription usage response was not valid JSON");
2016
+ }
2017
+ }
2018
+ async function fetchAnthropicUsage(credentials, fetchFn, signal, now) {
2019
+ const response = await fetchFn(ANTHROPIC_USAGE_URL, {
2020
+ method: "GET",
2021
+ signal,
2022
+ headers: {
2023
+ Authorization: `Bearer ${credentials.accessToken}`,
2024
+ Accept: "application/json",
2025
+ "anthropic-version": "2023-06-01",
2026
+ "anthropic-beta": "oauth-2025-04-20",
2027
+ "User-Agent": "ggcoder"
2028
+ }
2029
+ });
2030
+ const data = await readUsageResponse(response);
2031
+ const windows = [];
2032
+ const currentPercent = clampPercent(data.five_hour?.utilization);
2033
+ if (currentPercent !== void 0) {
2034
+ windows.push({
2035
+ kind: "current",
2036
+ label: "5-hour",
2037
+ usedPercent: currentPercent,
2038
+ resetsAt: isoTimestamp(data.five_hour?.resets_at)
2039
+ });
2040
+ }
2041
+ const weeklyPercent = clampPercent(data.seven_day?.utilization);
2042
+ if (weeklyPercent !== void 0) {
2043
+ windows.push({
2044
+ kind: "weekly",
2045
+ label: "Weekly",
2046
+ usedPercent: weeklyPercent,
2047
+ resetsAt: isoTimestamp(data.seven_day?.resets_at)
2048
+ });
2049
+ }
2050
+ return {
2051
+ provider: "anthropic",
2052
+ displayName: "Anthropic",
2053
+ windows,
2054
+ fetchedAt: now()
2055
+ };
2056
+ }
2057
+ async function fetchCodexUsage(credentials, fetchFn, signal, now) {
2058
+ const headers = {
2059
+ Authorization: `Bearer ${credentials.accessToken}`,
2060
+ Accept: "application/json",
2061
+ originator: "ggcoder",
2062
+ "User-Agent": "ggcoder"
2063
+ };
2064
+ if (credentials.accountId) headers["ChatGPT-Account-Id"] = credentials.accountId;
2065
+ const response = await fetchFn(CODEX_USAGE_URL, { method: "GET", signal, headers });
2066
+ const data = await readUsageResponse(response);
2067
+ const windows = [];
2068
+ const current = data.rate_limit?.primary_window;
2069
+ const currentPercent = clampPercent(current?.used_percent);
2070
+ if (current && currentPercent !== void 0) {
2071
+ windows.push({
2072
+ kind: "current",
2073
+ label: currentWindowLabel(current.limit_window_seconds, 5),
2074
+ usedPercent: currentPercent,
2075
+ resetsAt: codexResetAt(current, now())
2076
+ });
2077
+ }
2078
+ const weekly = data.rate_limit?.secondary_window;
2079
+ const weeklyPercent = clampPercent(weekly?.used_percent);
2080
+ if (weekly && weeklyPercent !== void 0) {
2081
+ windows.push({
2082
+ kind: "weekly",
2083
+ label: "Weekly",
2084
+ usedPercent: weeklyPercent,
2085
+ resetsAt: codexResetAt(weekly, now())
2086
+ });
2087
+ }
2088
+ return {
2089
+ provider: "openai",
2090
+ displayName: "Codex",
2091
+ windows,
2092
+ fetchedAt: now()
2093
+ };
2094
+ }
2095
+ async function fetchSubscriptionUsage(provider, credentials, options = {}) {
2096
+ const fetchFn = options.fetchFn ?? fetch;
2097
+ const now = options.now ?? Date.now;
2098
+ const signal = AbortSignal.timeout(options.timeoutMs ?? 8e3);
2099
+ try {
2100
+ return provider === "anthropic" ? await fetchAnthropicUsage(credentials, fetchFn, signal, now) : await fetchCodexUsage(credentials, fetchFn, signal, now);
2101
+ } catch (error) {
2102
+ if (error instanceof SubscriptionUsageError) throw error;
2103
+ const message = error instanceof Error ? error.message : String(error);
2104
+ throw new SubscriptionUsageError(message);
2105
+ }
2106
+ }
2107
+
1965
2108
  // src/telegram.ts
1966
2109
  var TELEGRAM_API = "https://api.telegram.org";
1967
2110
  var MAX_MESSAGE_LENGTH = 4096;
@@ -2444,12 +2587,14 @@ function createAutoUpdater(config) {
2444
2587
  MODELS,
2445
2588
  MOONSHOT_OAUTH_KEY,
2446
2589
  NotLoggedInError,
2590
+ SubscriptionUsageError,
2447
2591
  TelegramBot,
2448
2592
  XIAOMI_CREDITS_KEY,
2449
2593
  closeLogger,
2450
2594
  createAutoUpdater,
2451
2595
  decodeOggOpus,
2452
2596
  downmixToMono,
2597
+ fetchSubscriptionUsage,
2453
2598
  generatePKCE,
2454
2599
  getAppPaths,
2455
2600
  getAuthStorageKey,