@kenkaiiii/gg-core 5.90.0 → 5.91.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
@@ -40,6 +40,8 @@ __export(index_exports, {
40
40
  HIDDEN_PROVIDERS: () => HIDDEN_PROVIDERS,
41
41
  LOCAL_API_KEY_PLACEHOLDER: () => LOCAL_API_KEY_PLACEHOLDER,
42
42
  LOCAL_AUTH_KEY_PREFIX: () => LOCAL_AUTH_KEY_PREFIX,
43
+ MINIMAX_CN_BASE_URL: () => MINIMAX_CN_BASE_URL,
44
+ MINIMAX_GLOBAL_BASE_URL: () => MINIMAX_GLOBAL_BASE_URL,
43
45
  MODELS: () => MODELS,
44
46
  MOONSHOT_OAUTH_KEY: () => MOONSHOT_OAUTH_KEY,
45
47
  NotLoggedInError: () => NotLoggedInError,
@@ -48,6 +50,7 @@ __export(index_exports, {
48
50
  TelegramBot: () => TelegramBot,
49
51
  XAI_OAUTH_KEY: () => XAI_OAUTH_KEY,
50
52
  XIAOMI_CREDITS_KEY: () => XIAOMI_CREDITS_KEY,
53
+ XIAOMI_TOKEN_PLAN_BASE_URLS: () => XIAOMI_TOKEN_PLAN_BASE_URLS,
51
54
  authPriorityNote: () => authPriorityNote,
52
55
  clampThinkingForPlanMode: () => clampThinkingForPlanMode,
53
56
  clearLocalDiscoveryCache: () => clearLocalDiscoveryCache,
@@ -56,6 +59,8 @@ __export(index_exports, {
56
59
  createAutoUpdater: () => createAutoUpdater,
57
60
  decodeOggOpus: () => decodeOggOpus,
58
61
  describeAuthMethods: () => describeAuthMethods,
62
+ detectMiniMaxBaseUrl: () => detectMiniMaxBaseUrl,
63
+ detectXiaomiTokenPlanBaseUrl: () => detectXiaomiTokenPlanBaseUrl,
59
64
  discoverLocalModels: () => discoverLocalModels,
60
65
  downmixToMono: () => downmixToMono,
61
66
  dualAuthProvider: () => dualAuthProvider,
@@ -1528,6 +1533,90 @@ function isHiddenProvider(provider) {
1528
1533
 
1529
1534
  // src/auth-storage.ts
1530
1535
  var import_gg_ai3 = require("@kenkaiiii/gg-ai");
1536
+
1537
+ // src/minimax-region.ts
1538
+ var MINIMAX_GLOBAL_BASE_URL = "https://api.minimax.io/anthropic";
1539
+ var MINIMAX_CN_BASE_URL = "https://api.minimax.cn/anthropic";
1540
+ var REGION_HOSTS = [
1541
+ { host: "https://api.minimax.io", baseUrl: MINIMAX_GLOBAL_BASE_URL },
1542
+ { host: "https://api.minimax.cn", baseUrl: MINIMAX_CN_BASE_URL }
1543
+ ];
1544
+ var KEY_KNOWN_CODES = /* @__PURE__ */ new Set([0, 2062]);
1545
+ var KEY_REJECTED_CODES = /* @__PURE__ */ new Set([1004, 2049]);
1546
+ async function probeRegion(host, apiKey, fetchImpl, timeoutMs) {
1547
+ const url = apiKey.startsWith("sk-api-") ? `${host}/account/query_balance` : `${host}/v1/token_plan/remains`;
1548
+ let sawRejection = false;
1549
+ const authHeaders2 = [
1550
+ { Authorization: `Bearer ${apiKey}` },
1551
+ { "x-api-key": apiKey }
1552
+ ];
1553
+ for (const auth of authHeaders2) {
1554
+ let res;
1555
+ try {
1556
+ res = await fetchImpl(url, {
1557
+ headers: { ...auth, "Content-Type": "application/json" },
1558
+ signal: AbortSignal.timeout(timeoutMs)
1559
+ });
1560
+ } catch {
1561
+ return "inconclusive";
1562
+ }
1563
+ if (res.status === 401 || res.status === 403) {
1564
+ sawRejection = true;
1565
+ continue;
1566
+ }
1567
+ if (!res.ok) return "inconclusive";
1568
+ let code;
1569
+ try {
1570
+ code = (await res.json()).base_resp?.status_code;
1571
+ } catch {
1572
+ return "inconclusive";
1573
+ }
1574
+ if (typeof code === "number" && KEY_KNOWN_CODES.has(code)) return "authorized";
1575
+ if (typeof code === "number" && KEY_REJECTED_CODES.has(code)) {
1576
+ sawRejection = true;
1577
+ continue;
1578
+ }
1579
+ return "inconclusive";
1580
+ }
1581
+ return sawRejection ? "unauthorized" : "inconclusive";
1582
+ }
1583
+ async function detectMiniMaxBaseUrl(apiKey, options = {}) {
1584
+ const fetchImpl = options.fetch ?? fetch;
1585
+ const timeoutMs = options.timeoutMs ?? 5e3;
1586
+ const results = await Promise.all(
1587
+ REGION_HOSTS.map((r) => probeRegion(r.host, apiKey, fetchImpl, timeoutMs))
1588
+ );
1589
+ const index = results.indexOf("authorized");
1590
+ return index === -1 ? void 0 : REGION_HOSTS[index].baseUrl;
1591
+ }
1592
+
1593
+ // src/xiaomi-region.ts
1594
+ var XIAOMI_TOKEN_PLAN_BASE_URLS = [
1595
+ "https://token-plan-sgp.xiaomimimo.com/v1",
1596
+ "https://token-plan-ams.xiaomimimo.com/v1",
1597
+ "https://token-plan-cn.xiaomimimo.com/v1"
1598
+ ];
1599
+ async function detectXiaomiTokenPlanBaseUrl(apiKey, options = {}) {
1600
+ const fetchImpl = options.fetch ?? fetch;
1601
+ const timeoutMs = options.timeoutMs ?? 5e3;
1602
+ const accepted = await Promise.all(
1603
+ XIAOMI_TOKEN_PLAN_BASE_URLS.map(async (baseUrl) => {
1604
+ try {
1605
+ const res = await fetchImpl(`${baseUrl}/models`, {
1606
+ headers: { Authorization: `Bearer ${apiKey}` },
1607
+ signal: AbortSignal.timeout(timeoutMs)
1608
+ });
1609
+ return res.ok;
1610
+ } catch {
1611
+ return false;
1612
+ }
1613
+ })
1614
+ );
1615
+ const index = accepted.indexOf(true);
1616
+ return index === -1 ? void 0 : XIAOMI_TOKEN_PLAN_BASE_URLS[index];
1617
+ }
1618
+
1619
+ // src/auth-storage.ts
1531
1620
  var MOONSHOT_OAUTH_KEY = "moonshot-oauth";
1532
1621
  var XAI_OAUTH_KEY = "xai-oauth";
1533
1622
  var DUAL_AUTH_PROVIDERS = [
@@ -1577,6 +1666,15 @@ function activeBaseUrlEntry(data, provider) {
1577
1666
  }
1578
1667
  return data[provider];
1579
1668
  }
1669
+ var MINIMAX_REGION_RETRY_MS = 5 * 60 * 1e3;
1670
+ var miniMaxRegionProbes = /* @__PURE__ */ new Map();
1671
+ function cachedMiniMaxRegion(apiKey) {
1672
+ const cached = miniMaxRegionProbes.get(apiKey);
1673
+ if (cached && Date.now() - cached.at < MINIMAX_REGION_RETRY_MS) return cached.result;
1674
+ const result = detectMiniMaxBaseUrl(apiKey).catch(() => void 0);
1675
+ miniMaxRegionProbes.set(apiKey, { at: Date.now(), result });
1676
+ return result;
1677
+ }
1580
1678
  function readStoredBaseUrlSync(authFile, provider) {
1581
1679
  try {
1582
1680
  const data = JSON.parse((0, import_node_fs3.readFileSync)(authFile, "utf-8"));
@@ -1623,8 +1721,12 @@ var AuthStorage = class {
1623
1721
  snapshotIno = 0;
1624
1722
  /** Per-provider lock to serialize concurrent refresh calls. */
1625
1723
  refreshLocks = /* @__PURE__ */ new Map();
1626
- constructor(filePath) {
1724
+ detectMiniMaxRegion;
1725
+ detectXiaomiCluster;
1726
+ constructor(filePath, options) {
1627
1727
  this.filePath = filePath ?? getAppPaths().authFile;
1728
+ this.detectMiniMaxRegion = options?.detectMiniMaxBaseUrl ?? cachedMiniMaxRegion;
1729
+ this.detectXiaomiCluster = options?.detectXiaomiTokenPlanBaseUrl ?? detectXiaomiTokenPlanBaseUrl;
1628
1730
  }
1629
1731
  /** Path to the on-disk auth file. Useful for status output. */
1630
1732
  get path() {
@@ -1823,11 +1925,48 @@ var AuthStorage = class {
1823
1925
  await this.ensureFresh();
1824
1926
  return this.data[provider];
1825
1927
  }
1928
+ /**
1929
+ * A MiniMax key saved without an endpoint (every key, until its first use)
1930
+ * gets the endpoint of the region that issued it, saved so the check runs
1931
+ * once. Without this a Mainland China key went to the Global API, got a 401,
1932
+ * and was deleted as invalid.
1933
+ */
1934
+ async withMiniMaxRegion(creds) {
1935
+ const baseUrl = await this.detectMiniMaxRegion(creds.accessToken);
1936
+ if (!baseUrl) return creds;
1937
+ log("INFO", "auth", `MiniMax key belongs to ${baseUrl} \u2014 saved for future requests`);
1938
+ await this.mutateLatest((latest) => {
1939
+ const current = latest["minimax"];
1940
+ if (current?.accessToken === creds.accessToken && !current.baseUrl) {
1941
+ current.baseUrl = baseUrl;
1942
+ }
1943
+ });
1944
+ return { ...creds, baseUrl };
1945
+ }
1826
1946
  async setCredentials(provider, creds) {
1827
1947
  await this.mutateLatest((latest) => {
1828
1948
  latest[provider] = creds;
1829
1949
  });
1830
1950
  }
1951
+ /**
1952
+ * After a 401, move a regional key to the cluster that issued it instead of
1953
+ * treating it as invalid. Only the Xiaomi Token Plan is regional: every key
1954
+ * used to go to Singapore, so Europe and China keys were rejected and deleted.
1955
+ * Returns the new base URL, or undefined when no other cluster accepts the key.
1956
+ */
1957
+ async relocateRegionalApiKey(storageKeys) {
1958
+ const key = await this.pickStorageKey(storageKeys);
1959
+ const creds = key === "xiaomi" ? this.data[key] : void 0;
1960
+ if (!creds) return void 0;
1961
+ const baseUrl = await this.detectXiaomiCluster(creds.accessToken);
1962
+ if (!baseUrl || baseUrl === creds.baseUrl) return void 0;
1963
+ await this.mutateLatest((latest) => {
1964
+ const current = latest["xiaomi"];
1965
+ if (current?.accessToken === creds.accessToken) current.baseUrl = baseUrl;
1966
+ });
1967
+ log("INFO", "auth", `Xiaomi Token Plan key belongs to ${baseUrl} \u2014 saved for future requests`);
1968
+ return baseUrl;
1969
+ }
1831
1970
  // Keeps local-endpoint keys: they're the user's own config, and a 401 there is often a busy gateway.
1832
1971
  async clearRejectedApiKey(storageKey) {
1833
1972
  if (storageKey.startsWith(LOCAL_AUTH_KEY_PREFIX)) return false;
@@ -1947,6 +2086,7 @@ var AuthStorage = class {
1947
2086
  throw new NotLoggedInError(provider);
1948
2087
  }
1949
2088
  if (STATIC_API_KEY_PROVIDERS.has(provider)) {
2089
+ if (provider === "minimax" && !creds.baseUrl) return await this.withMiniMaxRegion(creds);
1950
2090
  return creds;
1951
2091
  }
1952
2092
  if (!opts?.forceRefresh && Date.now() < creds.expiresAt - refreshThresholdMs(creds)) {
@@ -2597,6 +2737,23 @@ var MODELS = [
2597
2737
  maxThinkingLevel: "max"
2598
2738
  },
2599
2739
  // ── MiniMax ────────────────────────────────────────────
2740
+ {
2741
+ // The only text model M Plan / Token Plan keys cover; MiniMax-M3 on those
2742
+ // keys fails with "insufficient balance (1008)". Pay-as-you-go serves both.
2743
+ // Always thinks (`thinking: disabled` 400s; omitted = on) with a real
2744
+ // low→max effort ladder on output_config.effort, API default max.
2745
+ id: "MiniMax-M3.1-Flash",
2746
+ name: "MiniMax M3.1 Flash",
2747
+ provider: "minimax",
2748
+ contextWindow: 1e6,
2749
+ maxOutputTokens: 131072,
2750
+ supportsThinking: true,
2751
+ supportsImages: true,
2752
+ supportsVideo: true,
2753
+ maxVideoBytes: 50 * 1024 * 1024,
2754
+ costTier: "low",
2755
+ maxThinkingLevel: "max"
2756
+ },
2600
2757
  {
2601
2758
  id: "MiniMax-M3",
2602
2759
  name: "MiniMax M3",
@@ -2847,7 +3004,7 @@ var DEFAULT_MODEL_IDS = {
2847
3004
  gemini: "gemini-3.1-flash-lite",
2848
3005
  glm: "glm-5.3",
2849
3006
  moonshot: "kimi-k3",
2850
- minimax: "MiniMax-M3",
3007
+ minimax: "MiniMax-M3.1-Flash",
2851
3008
  deepseek: "deepseek-v4-pro",
2852
3009
  huggingface: "moonshotai/Kimi-K2.7-Code",
2853
3010
  openrouter: "qwen/qwen3.8-max",
@@ -2941,6 +3098,13 @@ var ANTHROPIC_ADAPTIVE_THINKING_LEVELS = [
2941
3098
  ];
2942
3099
  var MOONSHOT_K3_THINKING_LEVELS = ["low", "high", "max"];
2943
3100
  var GLM_THINKING_LEVELS = ["low", "medium", "high", "xhigh", "max"];
3101
+ var MINIMAX_EFFORT_THINKING_LEVELS = [
3102
+ "low",
3103
+ "medium",
3104
+ "high",
3105
+ "xhigh",
3106
+ "max"
3107
+ ];
2944
3108
  var LOCAL_THINKING_LEVELS = ["low", "medium", "high", "max"];
2945
3109
  function isOpenAIGptModel(provider, model) {
2946
3110
  return provider === "openai" && model.startsWith("gpt-");
@@ -2957,6 +3121,9 @@ function isMoonshotK3Model(provider, model) {
2957
3121
  function isGlmModel(provider) {
2958
3122
  return provider === "glm";
2959
3123
  }
3124
+ function isMiniMaxEffortModel(provider, model) {
3125
+ return provider === "minimax" && model.startsWith("MiniMax-M3.1");
3126
+ }
2960
3127
  function isAnthropicXhighModel(provider, model) {
2961
3128
  return provider === "anthropic" && /opus-5|opus-4-8|opus-4-7|sonnet-5[-.]5|haiku-5[-.]5/.test(model);
2962
3129
  }
@@ -2989,6 +3156,7 @@ function getSupportedThinkingLevels(provider, model) {
2989
3156
  }
2990
3157
  if (isMoonshotK3Model(provider, model)) return MOONSHOT_K3_THINKING_LEVELS;
2991
3158
  if (provider === "deepseek") return DEEPSEEK_THINKING_LEVELS;
3159
+ if (isMiniMaxEffortModel(provider, model)) return MINIMAX_EFFORT_THINKING_LEVELS;
2992
3160
  if (isGlmModel(provider)) {
2993
3161
  const maxIndex2 = GLM_THINKING_LEVELS.indexOf(maxLevel);
2994
3162
  if (maxIndex2 === -1) return GLM_THINKING_LEVELS;
@@ -3009,7 +3177,7 @@ function isThinkingLevelSupported(provider, model, level) {
3009
3177
  }
3010
3178
  function getNextThinkingLevel(provider, model, current) {
3011
3179
  const supportedLevels = getSupportedThinkingLevels(provider, model);
3012
- const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider) || isMoonshotK3Model(provider, model) || isGlmModel(provider) || provider === "deepseek" || // Local servers take a real effort level, not just on/off: Ollama accepts
3180
+ const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider) || isMoonshotK3Model(provider, model) || isGlmModel(provider) || isMiniMaxEffortModel(provider, model) || provider === "deepseek" || // Local servers take a real effort level, not just on/off: Ollama accepts
3013
3181
  // low/medium/high on `reasoning_effort` (verified against 0.32) and the
3014
3182
  // other OpenAI-compatible servers use the same three. A model that can't
3015
3183
  // reason at all already has no supported levels, so it never gets here.
@@ -3451,7 +3619,7 @@ var ALL_AUTH_PROVIDERS = [
3451
3619
  {
3452
3620
  value: "minimax",
3453
3621
  label: "MiniMax",
3454
- description: "MiniMax M3",
3622
+ description: "MiniMax M3.1 Flash, M3",
3455
3623
  methods: ["apikey"],
3456
3624
  apiKeyLabel: "MiniMax"
3457
3625
  },
@@ -4284,6 +4452,8 @@ function createAutoUpdater(config) {
4284
4452
  HIDDEN_PROVIDERS,
4285
4453
  LOCAL_API_KEY_PLACEHOLDER,
4286
4454
  LOCAL_AUTH_KEY_PREFIX,
4455
+ MINIMAX_CN_BASE_URL,
4456
+ MINIMAX_GLOBAL_BASE_URL,
4287
4457
  MODELS,
4288
4458
  MOONSHOT_OAUTH_KEY,
4289
4459
  NotLoggedInError,
@@ -4292,6 +4462,7 @@ function createAutoUpdater(config) {
4292
4462
  TelegramBot,
4293
4463
  XAI_OAUTH_KEY,
4294
4464
  XIAOMI_CREDITS_KEY,
4465
+ XIAOMI_TOKEN_PLAN_BASE_URLS,
4295
4466
  authPriorityNote,
4296
4467
  clampThinkingForPlanMode,
4297
4468
  clearLocalDiscoveryCache,
@@ -4300,6 +4471,8 @@ function createAutoUpdater(config) {
4300
4471
  createAutoUpdater,
4301
4472
  decodeOggOpus,
4302
4473
  describeAuthMethods,
4474
+ detectMiniMaxBaseUrl,
4475
+ detectXiaomiTokenPlanBaseUrl,
4303
4476
  discoverLocalModels,
4304
4477
  downmixToMono,
4305
4478
  dualAuthProvider,