@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/README.md +11 -11
- package/dist/{chunk-2X5L6U4Z.js → chunk-GXOFTHM5.js} +4 -2
- package/dist/chunk-GXOFTHM5.js.map +1 -0
- package/dist/{chunk-SDUIKPGO.js → chunk-J7W5HS6X.js} +1191 -1189
- package/dist/chunk-J7W5HS6X.js.map +1 -0
- package/dist/index.cjs +1472 -1368
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +338 -187
- package/dist/index.d.ts +338 -187
- package/dist/index.js +319 -213
- package/dist/index.js.map +1 -1
- package/dist/model-registry.cjs +96 -77
- package/dist/model-registry.cjs.map +1 -1
- package/dist/model-registry.d.cts +11 -15
- package/dist/model-registry.d.ts +11 -15
- package/dist/model-registry.js +2 -2
- package/dist/paths.cjs +3 -1
- package/dist/paths.cjs.map +1 -1
- package/dist/paths.d.cts +4 -0
- package/dist/paths.d.ts +4 -0
- package/dist/paths.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-2X5L6U4Z.js.map +0 -1
- package/dist/chunk-SDUIKPGO.js.map +0 -1
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
loginOpenAI,
|
|
54
|
-
loginXai,
|
|
69
|
+
loginChatGPT,
|
|
70
|
+
loginClaudeCode,
|
|
71
|
+
logoutClaudeCode,
|
|
55
72
|
oauthStorageKey,
|
|
56
73
|
openLog,
|
|
57
|
-
|
|
74
|
+
parseCallbackInput,
|
|
58
75
|
providerStorageKeys,
|
|
59
76
|
readStoredBaseUrlSync,
|
|
60
|
-
|
|
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-
|
|
88
|
+
} from "./chunk-J7W5HS6X.js";
|
|
72
89
|
import {
|
|
73
90
|
getAppPaths
|
|
74
|
-
} from "./chunk-
|
|
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: "
|
|
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
|
|
619
|
-
billing: "
|
|
620
|
-
when: "
|
|
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: "
|
|
625
|
-
billing: "Pay-per-token from
|
|
626
|
-
when: "Used
|
|
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: "
|
|
632
|
-
label: "
|
|
633
|
-
description: "
|
|
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: "
|
|
743
|
+
apiKeyLabel: "OpenAI",
|
|
636
744
|
methodDetails: {
|
|
637
745
|
oauth: {
|
|
638
746
|
method: "oauth",
|
|
639
|
-
label: "
|
|
640
|
-
billing: "
|
|
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: "
|
|
646
|
-
billing: "Pay-per-token
|
|
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
|
|
655
|
-
methods: ["
|
|
656
|
-
apiKeyLabel: "
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
label: "
|
|
661
|
-
|
|
662
|
-
|
|
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
|
-
|
|
665
|
-
|
|
666
|
-
label: "Moonshot API
|
|
667
|
-
|
|
668
|
-
|
|
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
|
|
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 === "
|
|
762
|
-
return "Uses
|
|
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 (
|
|
766
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
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
|
-
|
|
1597
|
-
|
|
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
|
};
|