@kenkaiiii/gg-core 5.93.0 → 5.95.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.js CHANGED
@@ -1,30 +1,52 @@
1
1
  import {
2
2
  AuthStorage,
3
+ CHATGPT_PLAN_BASE_URL,
4
+ CHATGPT_PLAN_NOT_ENABLED_MESSAGE,
5
+ CHATGPT_PLAN_SCOPE,
6
+ CHATGPT_USAGE_URL,
7
+ CLAUDE_CODE_AUTH_KEY,
8
+ CLAUDE_CODE_AUTH_MARKER,
9
+ CLAUDE_CODE_MANIFEST,
10
+ ChatGPTPlanNotEnabledError,
3
11
  DEFAULT_MAX_VIDEO_BYTES,
4
12
  GEMINI_API_KEY,
5
13
  GEMINI_API_KEY_BASE_URL,
6
14
  HIDDEN_PROVIDERS,
15
+ KIMI_CODE_DEFAULT_BASE_URL,
16
+ KIMI_CODE_KEY,
17
+ KIMI_CODE_OVERSEAS_BASE_URL,
7
18
  LOCAL_AUTH_KEY_PREFIX,
8
19
  MINIMAX_CN_BASE_URL,
9
20
  MINIMAX_GLOBAL_BASE_URL,
10
21
  MODELS,
11
- MOONSHOT_OAUTH_KEY,
12
22
  NotLoggedInError,
13
- XAI_OAUTH_KEY,
23
+ OPENAI_CHATGPT_KEY,
24
+ RETIRED_SIGN_INS,
14
25
  XIAOMI_CREDITS_KEY,
15
26
  XIAOMI_TOKEN_PLAN_BASE_URLS,
27
+ apiKeyStorageKeys,
28
+ claudeCodeAuthStatus,
29
+ claudeCodeBinaryPath,
30
+ claudeCodeCallbackUrl,
31
+ claudeCodeConfigDir,
32
+ claudeCodeEnv,
33
+ claudeCodeHome,
34
+ claudeCodePlatformKey,
16
35
  clearRuntimeModels,
17
36
  closeLogger,
37
+ detectKimiCodeBaseUrl,
18
38
  detectMiniMaxBaseUrl,
19
39
  detectXiaomiTokenPlanBaseUrl,
20
40
  dualAuthProvider,
21
41
  dualAuthProviderByOAuthKey,
42
+ ensureClaudeCodeBinary,
43
+ fetchChatGPTPlanModels,
44
+ formatClaudeCodeInstallProgress,
22
45
  generatePKCE,
23
46
  getAllModels,
24
47
  getAuthStorageKey,
25
48
  getAuthStorageKeys,
26
- getClaudeCliUserAgent,
27
- getClaudeCodeVersion,
49
+ getChatGPTHostId,
28
50
  getContextWindow,
29
51
  getDefaultModel,
30
52
  getDefaultThinkingLevel,
@@ -37,41 +59,36 @@ import {
37
59
  getSummaryModel,
38
60
  getToolResultCharLimit,
39
61
  getVideoByteLimit,
40
- grokCliBaseUrl,
41
- grokCliHeaders,
42
- isGrokCliEndpoint,
62
+ isClaudeCodeAuthMarker,
43
63
  isHiddenProvider,
44
64
  isKimiCodingEndpoint,
65
+ isLegacyClaudeOAuth,
45
66
  isLoggerOpen,
46
67
  isPaidModel,
47
- kimiCodeBaseUrl,
48
- kimiCodingHeaders,
49
68
  log,
50
- loginAnthropic,
51
- loginGemini,
52
- loginKimi,
53
- loginOpenAI,
54
- loginXai,
69
+ loginChatGPT,
70
+ loginClaudeCode,
71
+ logoutClaudeCode,
55
72
  oauthStorageKey,
56
73
  openLog,
57
- pendingClaudeCodeVersionRefresh,
74
+ parseCallbackInput,
58
75
  providerStorageKeys,
59
76
  readStoredBaseUrlSync,
60
- refreshAnthropicToken,
61
- refreshGeminiToken,
62
- refreshKimiToken,
63
- refreshOpenAIToken,
64
- refreshXaiToken,
77
+ refreshChatGPTToken,
65
78
  registerLogCleanup,
66
79
  registerRuntimeModels,
80
+ resolveClaudeCodeBinary,
81
+ revokeChatGPTSignIn,
67
82
  setProviderCatalog,
83
+ storageKeyProvider,
68
84
  usesOpenAICodexTransport,
85
+ verifyIdToken,
69
86
  withFileLock,
70
87
  withoutPaidTier
71
- } from "./chunk-SDUIKPGO.js";
88
+ } from "./chunk-J7W5HS6X.js";
72
89
  import {
73
90
  getAppPaths
74
- } from "./chunk-2X5L6U4Z.js";
91
+ } from "./chunk-GXOFTHM5.js";
75
92
 
76
93
  // src/openrouter-catalog.ts
77
94
  var OPENROUTER_DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
@@ -587,101 +604,238 @@ function findProbedModel(probes, modelId) {
587
604
  return void 0;
588
605
  }
589
606
 
607
+ // src/claude-code/usage.ts
608
+ import fsp from "fs/promises";
609
+ import path from "path";
610
+ var USAGE_FILE = "usage.json";
611
+ var WINDOWS = {
612
+ five_hour: { kind: "current", label: "5-hour" },
613
+ seven_day: { kind: "weekly", label: "Weekly" }
614
+ };
615
+ function finite(value) {
616
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
617
+ }
618
+ function toWindow(key, raw) {
619
+ const shape = WINDOWS[key];
620
+ const fraction = finite(raw?.utilization);
621
+ if (!shape || fraction === void 0) return null;
622
+ const resetsAt = finite(raw?.resetsAt);
623
+ return {
624
+ ...shape,
625
+ usedPercent: Math.min(100, Math.max(0, fraction * 100)),
626
+ ...resetsAt !== void 0 ? { resetsAt: resetsAt * 1e3 } : {}
627
+ };
628
+ }
629
+ function mergeClaudeCodeRateLimit(info, previous, now = Date.now()) {
630
+ const reported = info.unifiedWindows ? Object.entries(info.unifiedWindows).map(([key, raw]) => toWindow(key, raw)) : info.rateLimitType ? [toWindow(info.rateLimitType, info)] : [];
631
+ const byKind = new Map(previous?.windows.map((w) => [w.kind, w]) ?? []);
632
+ for (const window of reported) if (window) byKind.set(window.kind, window);
633
+ const windows = [...byKind.values()].sort(
634
+ (a, b) => a.kind === b.kind ? 0 : a.kind === "current" ? -1 : 1
635
+ );
636
+ return { provider: "anthropic", displayName: "Anthropic", windows, fetchedAt: now };
637
+ }
638
+ function usagePath(opts) {
639
+ return path.join(claudeCodeHome(opts), USAGE_FILE);
640
+ }
641
+ async function readClaudeCodeUsage(opts = {}) {
642
+ let parsed;
643
+ try {
644
+ parsed = JSON.parse(await fsp.readFile(usagePath(opts), "utf8"));
645
+ } catch {
646
+ return null;
647
+ }
648
+ if (!Array.isArray(parsed?.windows) || typeof parsed.fetchedAt !== "number") return null;
649
+ const now = opts.now ?? Date.now();
650
+ const windows = parsed.windows.filter(
651
+ (w) => (w.kind === "current" || w.kind === "weekly") && typeof w.usedPercent === "number" && (w.resetsAt === void 0 || w.resetsAt > now)
652
+ );
653
+ return { provider: "anthropic", displayName: "Anthropic", windows, fetchedAt: parsed.fetchedAt };
654
+ }
655
+ var writeQueue = Promise.resolve();
656
+ function recordClaudeCodeRateLimit(info, opts = {}) {
657
+ const write = async () => {
658
+ const now = opts.now ?? Date.now();
659
+ const next = mergeClaudeCodeRateLimit(info, await readClaudeCodeUsage({ ...opts, now }), now);
660
+ if (next.windows.length === 0) return;
661
+ const file = usagePath(opts);
662
+ await fsp.mkdir(path.dirname(file), { recursive: true });
663
+ await fsp.writeFile(file, JSON.stringify(next), "utf8");
664
+ };
665
+ writeQueue = writeQueue.then(write).catch(() => {
666
+ });
667
+ return writeQueue;
668
+ }
669
+ async function clearClaudeCodeUsage(opts = {}) {
670
+ await writeQueue;
671
+ await fsp.rm(usagePath(opts), { force: true }).catch(() => {
672
+ });
673
+ }
674
+
675
+ // src/claude-code/sign-in.ts
676
+ async function signInWithClaudeCode(auth, callbacks, opts = {}) {
677
+ if (!opts.binary && !resolveClaudeCodeBinary(opts)) {
678
+ callbacks.onStatus("Downloading Claude Code (one time)\u2026");
679
+ await ensureClaudeCodeBinary({
680
+ ...opts,
681
+ onProgress: (progress) => {
682
+ callbacks.onStatus(formatClaudeCodeInstallProgress(progress));
683
+ opts.onProgress?.(progress);
684
+ }
685
+ });
686
+ }
687
+ let status = await claudeCodeAuthStatus(opts);
688
+ if (!status.loggedIn) {
689
+ callbacks.onStatus("Opening Claude sign-in\u2026");
690
+ await loginClaudeCode(callbacks, opts);
691
+ status = await claudeCodeAuthStatus(opts);
692
+ }
693
+ if (!status.loggedIn) throw new Error("Claude sign-in didn't finish. Try again.");
694
+ await auth.setClaudeCodeLogin();
695
+ return status;
696
+ }
697
+ async function signOutOfClaudeCode(auth, opts = {}) {
698
+ await auth.clearClaudeCodeLogin();
699
+ await clearClaudeCodeUsage(opts);
700
+ try {
701
+ await logoutClaudeCode(opts);
702
+ } catch (err) {
703
+ log(
704
+ "WARN",
705
+ "auth",
706
+ `claude auth logout failed: ${err instanceof Error ? err.message : String(err)}`
707
+ );
708
+ }
709
+ }
710
+
590
711
  // src/auth-providers.ts
712
+ function apiKeyDetails(label, billing, when = "") {
713
+ return { apikey: { method: "apikey", label, billing, when } };
714
+ }
591
715
  var ALL_AUTH_PROVIDERS = [
592
716
  {
593
717
  value: "anthropic",
594
718
  label: "Anthropic",
595
719
  description: "Claude Fable 5.1, Opus 5.5, Opus 5.5 Fast, Sonnet 5.5, Haiku 5.5",
596
- methods: ["oauth"]
597
- },
598
- {
599
- value: "openai",
600
- label: "OpenAI",
601
- description: "GPT-6 Astra, GPT-6 Astra Fast, GPT-6.1 Sol, GPT-6.1 Sol Fast, GPT-6 Luna, GPT-6 Luna Fast",
602
- methods: ["oauth"]
603
- },
604
- {
605
- value: "gemini",
606
- label: "Gemini",
607
- description: "Gemini 3.8 Flash, 3.5 Flash Lite, 3.1 Flash Lite, 3.5 Flash, 3.1 Pro (Preview)",
608
720
  methods: ["oauth", "apikey"],
609
- apiKeyLabel: "Gemini",
610
- apiKeyBaseUrl: GEMINI_API_KEY_BASE_URL,
611
- // Stored under its own key so it never overwrites the `gemini` OAuth login.
612
- apiKeyVariants: [
613
- { key: GEMINI_API_KEY, label: "Google AI Studio", baseUrl: GEMINI_API_KEY_BASE_URL }
614
- ],
721
+ apiKeyLabel: "Anthropic",
615
722
  methodDetails: {
616
723
  oauth: {
617
724
  method: "oauth",
618
- label: "Sign in with Google",
619
- billing: "Gemini Code Assist Standard or Enterprise licence.",
620
- when: "Personal Google accounts are no longer served here (Google ended it on June 18, 2026)."
725
+ label: "Sign in with Claude",
726
+ billing: "Uses your Claude Pro or Max plan.",
727
+ when: "Runs through Anthropic's Claude Code, which GG Coder downloads once (about 140 MB) the first time you pick this.",
728
+ requires: "A Claude Pro or Max subscription."
621
729
  },
622
730
  apikey: {
623
731
  method: "apikey",
624
- label: "Gemini API key",
625
- billing: "Pay-per-token from a Google AI Studio key.",
626
- when: "Used first whenever it is set."
732
+ label: "Anthropic API key",
733
+ billing: "Pay-per-token from an Anthropic Console key.",
734
+ when: "No subscription needed. Used only while you are not signed in with Claude."
627
735
  }
628
736
  }
629
737
  },
630
738
  {
631
- value: "xai",
632
- label: "xAI (Grok)",
633
- description: "Grok 4.7 \xB7 OAuth or API key",
739
+ value: "openai",
740
+ label: "OpenAI",
741
+ description: "GPT-6 Astra, GPT-6 Astra Fast, GPT-6.1 Sol, GPT-6.1 Sol Fast, GPT-6.1 Terra, GPT-6.1 Terra Fast, GPT-6 Luna, GPT-6 Luna Fast",
634
742
  methods: ["oauth", "apikey"],
635
- apiKeyLabel: "xAI",
743
+ apiKeyLabel: "OpenAI",
636
744
  methodDetails: {
637
745
  oauth: {
638
746
  method: "oauth",
639
- label: "Sign in with Grok",
640
- billing: "Included with SuperGrok or X Premium.",
641
- when: ""
747
+ label: "Continue with ChatGPT",
748
+ billing: "Uses your ChatGPT plan.",
749
+ when: "Signs in through OpenAI. Manage what GG Coder may use at chatgpt.com/settings/usage.",
750
+ requires: "A ChatGPT plan."
642
751
  },
643
752
  apikey: {
644
753
  method: "apikey",
645
- label: "xAI API key",
646
- billing: "Pay-per-token on console.x.ai credits.",
647
- when: ""
754
+ label: "OpenAI API key",
755
+ billing: "Pay-per-token from an OpenAI Platform key.",
756
+ when: "No subscription needed. Covers you while your ChatGPT plan's usage is out."
648
757
  }
649
758
  }
650
759
  },
760
+ {
761
+ value: "gemini",
762
+ label: "Gemini",
763
+ description: "Gemini 3.8 Flash, 3.5 Flash Lite, 3.1 Flash Lite, 3.5 Flash, 3.1 Pro (Preview)",
764
+ methods: ["apikey"],
765
+ apiKeyLabel: "Gemini",
766
+ apiKeyBaseUrl: GEMINI_API_KEY_BASE_URL,
767
+ // Stored under its own key: `gemini` held the retired Google sign-in.
768
+ apiKeyVariants: [
769
+ {
770
+ key: GEMINI_API_KEY,
771
+ label: "Google AI Studio",
772
+ kind: "payg",
773
+ billing: "Pay-per-token from a Google AI Studio key.",
774
+ baseUrl: GEMINI_API_KEY_BASE_URL
775
+ }
776
+ ],
777
+ methodDetails: apiKeyDetails("Gemini API key", "Pay-per-token from a Google AI Studio key.")
778
+ },
779
+ {
780
+ value: "xai",
781
+ label: "xAI (Grok)",
782
+ description: "Grok 4.7",
783
+ methods: ["apikey"],
784
+ apiKeyLabel: "xAI",
785
+ methodDetails: apiKeyDetails(
786
+ "xAI API key",
787
+ "Pay-per-token from console.x.ai credits.",
788
+ "SuperGrok and X Premium usage is only offered in apps xAI partners with."
789
+ )
790
+ },
651
791
  {
652
792
  value: "moonshot",
653
- label: "Moonshot",
654
- description: "Kimi K3, K2.8 Preview (Kimi sign-in), K2.7 Code, K2.7 Code HighSpeed \xB7 OAuth or API key",
655
- methods: ["oauth", "apikey"],
656
- apiKeyLabel: "Moonshot",
657
- methodDetails: {
658
- oauth: {
659
- method: "oauth",
660
- label: "Sign in with Kimi",
661
- billing: "Included with a Kimi For Coding plan.",
662
- when: ""
793
+ label: "Kimi (Moonshot)",
794
+ description: "Kimi K3, K2.8 Preview (Kimi Code plan), K2.7 Code, K2.7 Code HighSpeed",
795
+ methods: ["apikey"],
796
+ apiKeyLabel: "Kimi",
797
+ apiKeyVariants: [
798
+ {
799
+ key: KIMI_CODE_KEY,
800
+ label: "Kimi Code plan",
801
+ kind: "plan",
802
+ billing: "Uses your Kimi Code plan. Create the key in the Kimi Code Console."
663
803
  },
664
- apikey: {
665
- method: "apikey",
666
- label: "Moonshot API key",
667
- billing: "Pay-per-token on Moonshot credits.",
668
- when: ""
804
+ {
805
+ key: "moonshot",
806
+ label: "Moonshot API",
807
+ kind: "payg",
808
+ billing: "Pay-per-token from platform.moonshot.ai."
669
809
  }
670
- }
810
+ ],
811
+ methodDetails: apiKeyDetails(
812
+ "Kimi API key",
813
+ "A Kimi Code plan key uses your plan; a Moonshot key is pay-per-token."
814
+ )
671
815
  },
672
816
  {
673
817
  value: "glm",
674
818
  label: "Z.AI (GLM)",
675
819
  description: "GLM-5.3, GLM-5.3-Flash",
676
820
  methods: ["apikey"],
677
- apiKeyLabel: "Z.AI"
821
+ apiKeyLabel: "Z.AI",
822
+ methodDetails: apiKeyDetails(
823
+ "Z.AI API key",
824
+ "Pay-per-token from your Z.AI account balance.",
825
+ "GLM Coding Plan quota can't be used here: Z.AI limits the plan to the tools it lists."
826
+ )
678
827
  },
679
828
  {
680
829
  value: "minimax",
681
830
  label: "MiniMax",
682
831
  description: "MiniMax M3.1 Flash, M3",
683
832
  methods: ["apikey"],
684
- apiKeyLabel: "MiniMax"
833
+ apiKeyLabel: "MiniMax",
834
+ methodDetails: apiKeyDetails(
835
+ "MiniMax API key",
836
+ "An M Plan key uses your plan; a pay-as-you-go key is pay-per-token.",
837
+ "The key you paste decides which one is billed."
838
+ )
685
839
  },
686
840
  {
687
841
  value: "xiaomi",
@@ -694,44 +848,66 @@ var ALL_AUTH_PROVIDERS = [
694
848
  {
695
849
  key: "xiaomi",
696
850
  label: "Token Plan",
851
+ kind: "plan",
852
+ billing: "Uses your MiMo Token Plan.",
697
853
  baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1"
698
854
  },
699
855
  {
700
856
  key: XIAOMI_CREDITS_KEY,
701
- label: "API Credits (required for UltraSpeed)",
857
+ label: "API Credits",
858
+ kind: "payg",
859
+ billing: "Pay-per-token from MiMo API Credits. Required for UltraSpeed.",
702
860
  baseUrl: "https://api.xiaomimimo.com/v1"
703
861
  }
704
- ]
862
+ ],
863
+ methodDetails: apiKeyDetails(
864
+ "Xiaomi MiMo API key",
865
+ "A Token Plan key uses your plan; an API Credits key is pay-per-token."
866
+ )
705
867
  },
706
868
  {
707
869
  value: "deepseek",
708
870
  label: "DeepSeek",
709
871
  description: "DeepSeek V4 Pro, V4.1 Flash",
710
872
  methods: ["apikey"],
711
- apiKeyLabel: "DeepSeek"
873
+ apiKeyLabel: "DeepSeek",
874
+ methodDetails: apiKeyDetails("DeepSeek API key", "Pay-per-token from platform.deepseek.com.")
712
875
  },
713
876
  {
714
877
  value: "sakana",
715
878
  label: "Sakana (Fugu)",
716
879
  description: "Fugu, Fugu Max, Fugu Ultra",
717
880
  methods: ["apikey"],
718
- apiKeyLabel: "Sakana"
881
+ apiKeyLabel: "Sakana",
882
+ methodDetails: apiKeyDetails("Sakana API key", "Pay-per-token from your Sakana API account.")
719
883
  },
720
884
  {
721
885
  value: "openrouter",
722
886
  label: "OpenRouter",
723
887
  description: "Qwen3.8 Max \xB7 multi-provider gateway",
724
888
  methods: ["apikey"],
725
- apiKeyLabel: "OpenRouter"
889
+ apiKeyLabel: "OpenRouter",
890
+ methodDetails: apiKeyDetails("OpenRouter API key", "Pay-per-token from OpenRouter credits.")
726
891
  },
727
892
  {
728
893
  value: "huggingface",
729
894
  label: "Hugging Face",
730
895
  description: "Kimi K2.7 Code, DeepSeek V4.1 Flash, GPT-OSS 120B",
731
896
  methods: ["apikey"],
732
- apiKeyLabel: "Hugging Face"
897
+ apiKeyLabel: "Hugging Face",
898
+ methodDetails: apiKeyDetails(
899
+ "Hugging Face token",
900
+ "Pay-per-token from Hugging Face Inference Providers credits."
901
+ )
733
902
  }
734
903
  ];
904
+ function requiredKeyLabel(provider, storageKeys) {
905
+ const variants = ALL_AUTH_PROVIDERS.find((p) => p.value === provider)?.apiKeyVariants ?? [];
906
+ const needed = variants.filter((v) => storageKeys.includes(v.key));
907
+ if (needed.length === 0 || needed.length === variants.length) return void 0;
908
+ const names = needed.map((v) => v.label).join(" or ");
909
+ return `Needs ${/^[aeiou]/i.test(names) ? "an" : "a"} ${names} key`;
910
+ }
735
911
  var AUTH_PROVIDERS = ALL_AUTH_PROVIDERS.filter(
736
912
  (p) => !isHiddenProvider(p.value)
737
913
  );
@@ -758,15 +934,24 @@ function describeAuthMethods(provider) {
758
934
  });
759
935
  }
760
936
  function authPriorityNote(provider) {
761
- if (provider === "gemini") {
762
- return "Uses the Gemini API key first when one is set; otherwise the Google sign-in.";
937
+ if (provider === "anthropic") {
938
+ return "Uses Sign in with Claude while you are signed in; otherwise the Anthropic API key.";
763
939
  }
764
940
  const dual = dualAuthProvider(provider);
765
- if (!dual) return void 0;
766
- return `Uses ${dual.oauthLabel} first; the ${dual.apiKeyLabel} takes over when it runs out, then switches back.`;
941
+ if (dual) {
942
+ return `Uses your ${dual.oauthLabel} first; the ${dual.apiKeyLabel} takes over while its usage is out, then switches back.`;
943
+ }
944
+ const variants = getAuthProvider(provider)?.apiKeyVariants;
945
+ const plan = variants?.find((v) => v.kind === "plan");
946
+ const payg = variants?.find((v) => v.kind === "payg");
947
+ if (plan && payg) {
948
+ return `Uses the ${plan.label} key first when both are set; the ${payg.label} key covers models the plan doesn't include.`;
949
+ }
950
+ return void 0;
767
951
  }
768
952
 
769
953
  // src/provider-usage.ts
954
+ import { GG_CODER_USER_AGENT } from "@kenkaiiii/gg-ai";
770
955
  var SubscriptionUsageError = class extends Error {
771
956
  constructor(message, status, retryAfterMs2) {
772
957
  super(message);
@@ -775,52 +960,14 @@ var SubscriptionUsageError = class extends Error {
775
960
  this.name = "SubscriptionUsageError";
776
961
  }
777
962
  };
778
- var ANTHROPIC_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
779
- var CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
780
963
  function finiteNumber(value) {
781
964
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
782
965
  }
783
- function clampPercent(value) {
784
- const number = finiteNumber(value);
785
- return number === void 0 ? void 0 : Math.min(100, Math.max(0, number));
786
- }
787
966
  function isoTimestamp(value) {
788
967
  if (typeof value !== "string" || !value.trim()) return void 0;
789
968
  const timestamp = Date.parse(value);
790
969
  return Number.isFinite(timestamp) ? timestamp : void 0;
791
970
  }
792
- function unixTimestamp(value) {
793
- const seconds = finiteNumber(value);
794
- return seconds === void 0 ? void 0 : seconds * 1e3;
795
- }
796
- function codexResetAt(window, now) {
797
- const absolute = unixTimestamp(window.reset_at);
798
- if (absolute !== void 0) return absolute;
799
- const afterSeconds = finiteNumber(window.reset_after_seconds);
800
- return afterSeconds === void 0 ? void 0 : now + afterSeconds * 1e3;
801
- }
802
- function currentWindowLabel(seconds, fallbackHours) {
803
- const duration = finiteNumber(seconds);
804
- const hours = Math.max(1, Math.round((duration ?? fallbackHours * 3600) / 3600));
805
- return `${hours}-hour`;
806
- }
807
- function codexWindowKind(window, fallback) {
808
- const duration = finiteNumber(window.limit_window_seconds);
809
- if (duration === void 0) return fallback;
810
- return duration >= 6 * 24 * 60 * 60 ? "weekly" : "current";
811
- }
812
- function normalizedCodexWindow(window, fallbackKind, now) {
813
- if (!window) return null;
814
- const usedPercent = clampPercent(window.used_percent);
815
- if (usedPercent === void 0) return null;
816
- const kind = codexWindowKind(window, fallbackKind);
817
- return {
818
- kind,
819
- label: kind === "weekly" ? "Weekly" : currentWindowLabel(window.limit_window_seconds, 5),
820
- usedPercent,
821
- resetsAt: codexResetAt(window, now)
822
- };
823
- }
824
971
  function retryAfterMs(response, now) {
825
972
  const value = response.headers.get("retry-after")?.trim();
826
973
  if (!value) return void 0;
@@ -843,70 +990,6 @@ async function readUsageResponse(response, now) {
843
990
  throw new SubscriptionUsageError("Subscription usage response was not valid JSON");
844
991
  }
845
992
  }
846
- async function fetchAnthropicUsage(credentials, fetchFn, signal, now) {
847
- const response = await fetchFn(ANTHROPIC_USAGE_URL, {
848
- method: "GET",
849
- signal,
850
- headers: {
851
- Authorization: `Bearer ${credentials.accessToken}`,
852
- Accept: "application/json",
853
- "anthropic-version": "2023-06-01",
854
- "anthropic-beta": "oauth-2025-04-20",
855
- "User-Agent": "ggcoder"
856
- }
857
- });
858
- const data = await readUsageResponse(response, now());
859
- const windows = [];
860
- const currentPercent = clampPercent(data.five_hour?.utilization);
861
- if (currentPercent !== void 0) {
862
- windows.push({
863
- kind: "current",
864
- label: "5-hour",
865
- usedPercent: currentPercent,
866
- resetsAt: isoTimestamp(data.five_hour?.resets_at)
867
- });
868
- }
869
- const weeklyPercent = clampPercent(data.seven_day?.utilization);
870
- if (weeklyPercent !== void 0) {
871
- windows.push({
872
- kind: "weekly",
873
- label: "Weekly",
874
- usedPercent: weeklyPercent,
875
- resetsAt: isoTimestamp(data.seven_day?.resets_at)
876
- });
877
- }
878
- return {
879
- provider: "anthropic",
880
- displayName: "Anthropic",
881
- windows,
882
- fetchedAt: now()
883
- };
884
- }
885
- async function fetchCodexUsage(credentials, fetchFn, signal, now) {
886
- const headers = {
887
- Authorization: `Bearer ${credentials.accessToken}`,
888
- Accept: "application/json",
889
- originator: "ggcoder",
890
- "User-Agent": "ggcoder"
891
- };
892
- if (credentials.accountId) headers["ChatGPT-Account-Id"] = credentials.accountId;
893
- const response = await fetchFn(CODEX_USAGE_URL, { method: "GET", signal, headers });
894
- const data = await readUsageResponse(response, now());
895
- const windows = [
896
- normalizedCodexWindow(data.rate_limit?.primary_window, "current", now()),
897
- normalizedCodexWindow(data.rate_limit?.secondary_window, "weekly", now())
898
- ].filter((window) => window !== null);
899
- windows.sort((left, right) => {
900
- if (left.kind === right.kind) return 0;
901
- return left.kind === "current" ? -1 : 1;
902
- });
903
- return {
904
- provider: "openai",
905
- displayName: "Codex",
906
- windows,
907
- fetchedAt: now()
908
- };
909
- }
910
993
  function kimiNumber(value) {
911
994
  if (typeof value === "string" && value.trim()) {
912
995
  const parsed = Number(value);
@@ -937,15 +1020,14 @@ function kimiWindowMinutes(window) {
937
1020
  }
938
1021
  }
939
1022
  async function fetchKimiUsage(credentials, fetchFn, signal, now) {
940
- const response = await fetchFn(`${kimiCodeBaseUrl()}/usages`, {
1023
+ const baseUrl = (credentials.baseUrl ?? KIMI_CODE_DEFAULT_BASE_URL).replace(/\/+$/, "");
1024
+ const response = await fetchFn(`${baseUrl}/usages`, {
941
1025
  method: "GET",
942
1026
  signal,
943
1027
  headers: {
944
1028
  Authorization: "Bearer " + credentials.accessToken,
945
1029
  Accept: "application/json",
946
- // The managed coding endpoint gates on the kimi-code-cli client identity,
947
- // same as model requests.
948
- ...kimiCodingHeaders()
1030
+ "User-Agent": GG_CODER_USER_AGENT
949
1031
  }
950
1032
  });
951
1033
  const data = await readUsageResponse(response, now());
@@ -997,7 +1079,7 @@ async function fetchSubscriptionUsage(provider, credentials, options = {}) {
997
1079
  const now = options.now ?? Date.now;
998
1080
  const signal = AbortSignal.timeout(options.timeoutMs ?? 8e3);
999
1081
  try {
1000
- return provider === "anthropic" ? await fetchAnthropicUsage(credentials, fetchFn, signal, now) : provider === "openai" ? await fetchCodexUsage(credentials, fetchFn, signal, now) : await fetchKimiUsage(credentials, fetchFn, signal, now);
1082
+ return await fetchKimiUsage(credentials, fetchFn, signal, now);
1001
1083
  } catch (error) {
1002
1084
  if (error instanceof SubscriptionUsageError) throw error;
1003
1085
  const message = error instanceof Error ? error.message : String(error);
@@ -1335,7 +1417,7 @@ async function transcribeVoice(fileUrl) {
1335
1417
  // src/auto-update.ts
1336
1418
  import { spawn } from "child_process";
1337
1419
  import fs from "fs";
1338
- import path from "path";
1420
+ import path2 from "path";
1339
1421
  var CHECK_INTERVAL_MS = 60 * 60 * 1e3;
1340
1422
  var FETCH_TIMEOUT_MS = 1e4;
1341
1423
  function compareVersions(a, b) {
@@ -1377,7 +1459,7 @@ function createAutoUpdater(config) {
1377
1459
  function writeState(state) {
1378
1460
  try {
1379
1461
  const filePath = stateFilePath();
1380
- fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 448 });
1462
+ fs.mkdirSync(path2.dirname(filePath), { recursive: true, mode: 448 });
1381
1463
  fs.writeFileSync(filePath, JSON.stringify(state));
1382
1464
  } catch {
1383
1465
  }
@@ -1503,34 +1585,55 @@ function createAutoUpdater(config) {
1503
1585
  export {
1504
1586
  AUTH_PROVIDERS,
1505
1587
  AuthStorage,
1588
+ CHATGPT_PLAN_BASE_URL,
1589
+ CHATGPT_PLAN_NOT_ENABLED_MESSAGE,
1590
+ CHATGPT_PLAN_SCOPE,
1591
+ CHATGPT_USAGE_URL,
1592
+ CLAUDE_CODE_AUTH_KEY,
1593
+ CLAUDE_CODE_AUTH_MARKER,
1594
+ CLAUDE_CODE_MANIFEST,
1595
+ ChatGPTPlanNotEnabledError,
1506
1596
  DEFAULT_LOCAL_ENDPOINTS,
1507
1597
  DEFAULT_MAX_VIDEO_BYTES,
1508
1598
  FALLBACK_CONTEXT_WINDOW,
1509
1599
  GEMINI_API_KEY,
1510
1600
  GEMINI_API_KEY_BASE_URL,
1511
1601
  HIDDEN_PROVIDERS,
1602
+ KIMI_CODE_DEFAULT_BASE_URL,
1603
+ KIMI_CODE_KEY,
1604
+ KIMI_CODE_OVERSEAS_BASE_URL,
1512
1605
  LOCAL_API_KEY_PLACEHOLDER,
1513
1606
  LOCAL_AUTH_KEY_PREFIX,
1514
1607
  MINIMAX_CN_BASE_URL,
1515
1608
  MINIMAX_GLOBAL_BASE_URL,
1516
1609
  MODELS,
1517
- MOONSHOT_OAUTH_KEY,
1518
1610
  NotLoggedInError,
1611
+ OPENAI_CHATGPT_KEY,
1519
1612
  OPENROUTER_DEFAULT_BASE_URL,
1520
1613
  PLAN_MODE_THINKING_CAP,
1614
+ RETIRED_SIGN_INS,
1521
1615
  SubscriptionUsageError,
1522
1616
  TelegramBot,
1523
- XAI_OAUTH_KEY,
1524
1617
  XIAOMI_CREDITS_KEY,
1525
1618
  XIAOMI_TOKEN_PLAN_BASE_URLS,
1619
+ apiKeyStorageKeys,
1526
1620
  authPriorityNote,
1527
1621
  clampThinkingForPlanMode,
1622
+ claudeCodeAuthStatus,
1623
+ claudeCodeBinaryPath,
1624
+ claudeCodeCallbackUrl,
1625
+ claudeCodeConfigDir,
1626
+ claudeCodeEnv,
1627
+ claudeCodeHome,
1628
+ claudeCodePlatformKey,
1629
+ clearClaudeCodeUsage,
1528
1630
  clearLocalDiscoveryCache,
1529
1631
  clearRuntimeModels,
1530
1632
  closeLogger,
1531
1633
  createAutoUpdater,
1532
1634
  decodeOggOpus,
1533
1635
  describeAuthMethods,
1636
+ detectKimiCodeBaseUrl,
1534
1637
  detectMiniMaxBaseUrl,
1535
1638
  detectXiaomiTokenPlanBaseUrl,
1536
1639
  discoverLocalModels,
@@ -1538,8 +1641,11 @@ export {
1538
1641
  dualAuthProvider,
1539
1642
  dualAuthProviderByOAuthKey,
1540
1643
  endpointRoot,
1644
+ ensureClaudeCodeBinary,
1645
+ fetchChatGPTPlanModels,
1541
1646
  fetchSubscriptionUsage,
1542
1647
  findProbedModel,
1648
+ formatClaudeCodeInstallProgress,
1543
1649
  formatLocalModelId,
1544
1650
  generatePKCE,
1545
1651
  getAllModels,
@@ -1547,8 +1653,7 @@ export {
1547
1653
  getAuthProvider,
1548
1654
  getAuthStorageKey,
1549
1655
  getAuthStorageKeys,
1550
- getClaudeCliUserAgent,
1551
- getClaudeCodeVersion,
1656
+ getChatGPTHostId,
1552
1657
  getContextWindow,
1553
1658
  getDefaultModel,
1554
1659
  getDefaultThinkingLevel,
@@ -1564,48 +1669,49 @@ export {
1564
1669
  getSupportedThinkingLevels,
1565
1670
  getToolResultCharLimit,
1566
1671
  getVideoByteLimit,
1567
- grokCliBaseUrl,
1568
- grokCliHeaders,
1569
- isGrokCliEndpoint,
1672
+ isClaudeCodeAuthMarker,
1570
1673
  isHiddenProvider,
1571
1674
  isKimiCodingEndpoint,
1675
+ isLegacyClaudeOAuth,
1572
1676
  isLocalModelId,
1573
1677
  isLoggerOpen,
1574
1678
  isModelLoaded,
1575
1679
  isPaidModel,
1576
1680
  isThinkingLevelSupported,
1577
- kimiCodeBaseUrl,
1578
- kimiCodingHeaders,
1579
1681
  localAuthStorageKey,
1580
1682
  localModelShortName,
1581
1683
  log,
1582
- loginAnthropic,
1583
- loginGemini,
1584
- loginKimi,
1585
- loginOpenAI,
1586
- loginXai,
1684
+ loginChatGPT,
1685
+ loginClaudeCode,
1686
+ logoutClaudeCode,
1687
+ mergeClaudeCodeRateLimit,
1587
1688
  oauthStorageKey,
1588
1689
  ollamaServedContext,
1589
1690
  openLog,
1691
+ parseCallbackInput,
1590
1692
  parseLocalModelId,
1591
1693
  parseOpenRouterCatalog,
1592
- pendingClaudeCodeVersionRefresh,
1593
1694
  probeEndpoint,
1594
1695
  providerStorageKeys,
1696
+ readClaudeCodeUsage,
1595
1697
  readStoredBaseUrlSync,
1596
- refreshAnthropicToken,
1597
- refreshGeminiToken,
1598
- refreshKimiToken,
1599
- refreshOpenAIToken,
1600
- refreshXaiToken,
1698
+ recordClaudeCodeRateLimit,
1699
+ refreshChatGPTToken,
1601
1700
  registerLogCleanup,
1602
1701
  registerRuntimeModels,
1702
+ requiredKeyLabel,
1603
1703
  resample,
1704
+ resolveClaudeCodeBinary,
1705
+ revokeChatGPTSignIn,
1604
1706
  setProgressCallback,
1605
1707
  setProviderCatalog,
1708
+ signInWithClaudeCode,
1709
+ signOutOfClaudeCode,
1710
+ storageKeyProvider,
1606
1711
  toModelInfo,
1607
1712
  transcribeVoice,
1608
1713
  usesOpenAICodexTransport,
1714
+ verifyIdToken,
1609
1715
  withFileLock,
1610
1716
  withoutPaidTier
1611
1717
  };