@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.
@@ -1376,6 +1376,90 @@ function isHiddenProvider(provider) {
1376
1376
 
1377
1377
  // src/auth-storage.ts
1378
1378
  import { LOCAL_NO_API_KEY } from "@kenkaiiii/gg-ai";
1379
+
1380
+ // src/minimax-region.ts
1381
+ var MINIMAX_GLOBAL_BASE_URL = "https://api.minimax.io/anthropic";
1382
+ var MINIMAX_CN_BASE_URL = "https://api.minimax.cn/anthropic";
1383
+ var REGION_HOSTS = [
1384
+ { host: "https://api.minimax.io", baseUrl: MINIMAX_GLOBAL_BASE_URL },
1385
+ { host: "https://api.minimax.cn", baseUrl: MINIMAX_CN_BASE_URL }
1386
+ ];
1387
+ var KEY_KNOWN_CODES = /* @__PURE__ */ new Set([0, 2062]);
1388
+ var KEY_REJECTED_CODES = /* @__PURE__ */ new Set([1004, 2049]);
1389
+ async function probeRegion(host, apiKey, fetchImpl, timeoutMs) {
1390
+ const url = apiKey.startsWith("sk-api-") ? `${host}/account/query_balance` : `${host}/v1/token_plan/remains`;
1391
+ let sawRejection = false;
1392
+ const authHeaders = [
1393
+ { Authorization: `Bearer ${apiKey}` },
1394
+ { "x-api-key": apiKey }
1395
+ ];
1396
+ for (const auth of authHeaders) {
1397
+ let res;
1398
+ try {
1399
+ res = await fetchImpl(url, {
1400
+ headers: { ...auth, "Content-Type": "application/json" },
1401
+ signal: AbortSignal.timeout(timeoutMs)
1402
+ });
1403
+ } catch {
1404
+ return "inconclusive";
1405
+ }
1406
+ if (res.status === 401 || res.status === 403) {
1407
+ sawRejection = true;
1408
+ continue;
1409
+ }
1410
+ if (!res.ok) return "inconclusive";
1411
+ let code;
1412
+ try {
1413
+ code = (await res.json()).base_resp?.status_code;
1414
+ } catch {
1415
+ return "inconclusive";
1416
+ }
1417
+ if (typeof code === "number" && KEY_KNOWN_CODES.has(code)) return "authorized";
1418
+ if (typeof code === "number" && KEY_REJECTED_CODES.has(code)) {
1419
+ sawRejection = true;
1420
+ continue;
1421
+ }
1422
+ return "inconclusive";
1423
+ }
1424
+ return sawRejection ? "unauthorized" : "inconclusive";
1425
+ }
1426
+ async function detectMiniMaxBaseUrl(apiKey, options = {}) {
1427
+ const fetchImpl = options.fetch ?? fetch;
1428
+ const timeoutMs = options.timeoutMs ?? 5e3;
1429
+ const results = await Promise.all(
1430
+ REGION_HOSTS.map((r) => probeRegion(r.host, apiKey, fetchImpl, timeoutMs))
1431
+ );
1432
+ const index = results.indexOf("authorized");
1433
+ return index === -1 ? void 0 : REGION_HOSTS[index].baseUrl;
1434
+ }
1435
+
1436
+ // src/xiaomi-region.ts
1437
+ var XIAOMI_TOKEN_PLAN_BASE_URLS = [
1438
+ "https://token-plan-sgp.xiaomimimo.com/v1",
1439
+ "https://token-plan-ams.xiaomimimo.com/v1",
1440
+ "https://token-plan-cn.xiaomimimo.com/v1"
1441
+ ];
1442
+ async function detectXiaomiTokenPlanBaseUrl(apiKey, options = {}) {
1443
+ const fetchImpl = options.fetch ?? fetch;
1444
+ const timeoutMs = options.timeoutMs ?? 5e3;
1445
+ const accepted = await Promise.all(
1446
+ XIAOMI_TOKEN_PLAN_BASE_URLS.map(async (baseUrl) => {
1447
+ try {
1448
+ const res = await fetchImpl(`${baseUrl}/models`, {
1449
+ headers: { Authorization: `Bearer ${apiKey}` },
1450
+ signal: AbortSignal.timeout(timeoutMs)
1451
+ });
1452
+ return res.ok;
1453
+ } catch {
1454
+ return false;
1455
+ }
1456
+ })
1457
+ );
1458
+ const index = accepted.indexOf(true);
1459
+ return index === -1 ? void 0 : XIAOMI_TOKEN_PLAN_BASE_URLS[index];
1460
+ }
1461
+
1462
+ // src/auth-storage.ts
1379
1463
  var MOONSHOT_OAUTH_KEY = "moonshot-oauth";
1380
1464
  var XAI_OAUTH_KEY = "xai-oauth";
1381
1465
  var DUAL_AUTH_PROVIDERS = [
@@ -1425,6 +1509,15 @@ function activeBaseUrlEntry(data, provider) {
1425
1509
  }
1426
1510
  return data[provider];
1427
1511
  }
1512
+ var MINIMAX_REGION_RETRY_MS = 5 * 60 * 1e3;
1513
+ var miniMaxRegionProbes = /* @__PURE__ */ new Map();
1514
+ function cachedMiniMaxRegion(apiKey) {
1515
+ const cached = miniMaxRegionProbes.get(apiKey);
1516
+ if (cached && Date.now() - cached.at < MINIMAX_REGION_RETRY_MS) return cached.result;
1517
+ const result = detectMiniMaxBaseUrl(apiKey).catch(() => void 0);
1518
+ miniMaxRegionProbes.set(apiKey, { at: Date.now(), result });
1519
+ return result;
1520
+ }
1428
1521
  function readStoredBaseUrlSync(authFile, provider) {
1429
1522
  try {
1430
1523
  const data = JSON.parse(readFileSync2(authFile, "utf-8"));
@@ -1471,8 +1564,12 @@ var AuthStorage = class {
1471
1564
  snapshotIno = 0;
1472
1565
  /** Per-provider lock to serialize concurrent refresh calls. */
1473
1566
  refreshLocks = /* @__PURE__ */ new Map();
1474
- constructor(filePath) {
1567
+ detectMiniMaxRegion;
1568
+ detectXiaomiCluster;
1569
+ constructor(filePath, options) {
1475
1570
  this.filePath = filePath ?? getAppPaths().authFile;
1571
+ this.detectMiniMaxRegion = options?.detectMiniMaxBaseUrl ?? cachedMiniMaxRegion;
1572
+ this.detectXiaomiCluster = options?.detectXiaomiTokenPlanBaseUrl ?? detectXiaomiTokenPlanBaseUrl;
1476
1573
  }
1477
1574
  /** Path to the on-disk auth file. Useful for status output. */
1478
1575
  get path() {
@@ -1671,11 +1768,48 @@ var AuthStorage = class {
1671
1768
  await this.ensureFresh();
1672
1769
  return this.data[provider];
1673
1770
  }
1771
+ /**
1772
+ * A MiniMax key saved without an endpoint (every key, until its first use)
1773
+ * gets the endpoint of the region that issued it, saved so the check runs
1774
+ * once. Without this a Mainland China key went to the Global API, got a 401,
1775
+ * and was deleted as invalid.
1776
+ */
1777
+ async withMiniMaxRegion(creds) {
1778
+ const baseUrl = await this.detectMiniMaxRegion(creds.accessToken);
1779
+ if (!baseUrl) return creds;
1780
+ log("INFO", "auth", `MiniMax key belongs to ${baseUrl} \u2014 saved for future requests`);
1781
+ await this.mutateLatest((latest) => {
1782
+ const current = latest["minimax"];
1783
+ if (current?.accessToken === creds.accessToken && !current.baseUrl) {
1784
+ current.baseUrl = baseUrl;
1785
+ }
1786
+ });
1787
+ return { ...creds, baseUrl };
1788
+ }
1674
1789
  async setCredentials(provider, creds) {
1675
1790
  await this.mutateLatest((latest) => {
1676
1791
  latest[provider] = creds;
1677
1792
  });
1678
1793
  }
1794
+ /**
1795
+ * After a 401, move a regional key to the cluster that issued it instead of
1796
+ * treating it as invalid. Only the Xiaomi Token Plan is regional: every key
1797
+ * used to go to Singapore, so Europe and China keys were rejected and deleted.
1798
+ * Returns the new base URL, or undefined when no other cluster accepts the key.
1799
+ */
1800
+ async relocateRegionalApiKey(storageKeys) {
1801
+ const key = await this.pickStorageKey(storageKeys);
1802
+ const creds = key === "xiaomi" ? this.data[key] : void 0;
1803
+ if (!creds) return void 0;
1804
+ const baseUrl = await this.detectXiaomiCluster(creds.accessToken);
1805
+ if (!baseUrl || baseUrl === creds.baseUrl) return void 0;
1806
+ await this.mutateLatest((latest) => {
1807
+ const current = latest["xiaomi"];
1808
+ if (current?.accessToken === creds.accessToken) current.baseUrl = baseUrl;
1809
+ });
1810
+ log("INFO", "auth", `Xiaomi Token Plan key belongs to ${baseUrl} \u2014 saved for future requests`);
1811
+ return baseUrl;
1812
+ }
1679
1813
  // Keeps local-endpoint keys: they're the user's own config, and a 401 there is often a busy gateway.
1680
1814
  async clearRejectedApiKey(storageKey) {
1681
1815
  if (storageKey.startsWith(LOCAL_AUTH_KEY_PREFIX)) return false;
@@ -1795,6 +1929,7 @@ var AuthStorage = class {
1795
1929
  throw new NotLoggedInError(provider);
1796
1930
  }
1797
1931
  if (STATIC_API_KEY_PROVIDERS.has(provider)) {
1932
+ if (provider === "minimax" && !creds.baseUrl) return await this.withMiniMaxRegion(creds);
1798
1933
  return creds;
1799
1934
  }
1800
1935
  if (!opts?.forceRefresh && Date.now() < creds.expiresAt - refreshThresholdMs(creds)) {
@@ -2445,6 +2580,23 @@ var MODELS = [
2445
2580
  maxThinkingLevel: "max"
2446
2581
  },
2447
2582
  // ── MiniMax ────────────────────────────────────────────
2583
+ {
2584
+ // The only text model M Plan / Token Plan keys cover; MiniMax-M3 on those
2585
+ // keys fails with "insufficient balance (1008)". Pay-as-you-go serves both.
2586
+ // Always thinks (`thinking: disabled` 400s; omitted = on) with a real
2587
+ // low→max effort ladder on output_config.effort, API default max.
2588
+ id: "MiniMax-M3.1-Flash",
2589
+ name: "MiniMax M3.1 Flash",
2590
+ provider: "minimax",
2591
+ contextWindow: 1e6,
2592
+ maxOutputTokens: 131072,
2593
+ supportsThinking: true,
2594
+ supportsImages: true,
2595
+ supportsVideo: true,
2596
+ maxVideoBytes: 50 * 1024 * 1024,
2597
+ costTier: "low",
2598
+ maxThinkingLevel: "max"
2599
+ },
2448
2600
  {
2449
2601
  id: "MiniMax-M3",
2450
2602
  name: "MiniMax M3",
@@ -2695,7 +2847,7 @@ var DEFAULT_MODEL_IDS = {
2695
2847
  gemini: "gemini-3.1-flash-lite",
2696
2848
  glm: "glm-5.3",
2697
2849
  moonshot: "kimi-k3",
2698
- minimax: "MiniMax-M3",
2850
+ minimax: "MiniMax-M3.1-Flash",
2699
2851
  deepseek: "deepseek-v4-pro",
2700
2852
  huggingface: "moonshotai/Kimi-K2.7-Code",
2701
2853
  openrouter: "qwen/qwen3.8-max",
@@ -2791,6 +2943,11 @@ export {
2791
2943
  closeLogger,
2792
2944
  HIDDEN_PROVIDERS,
2793
2945
  isHiddenProvider,
2946
+ MINIMAX_GLOBAL_BASE_URL,
2947
+ MINIMAX_CN_BASE_URL,
2948
+ detectMiniMaxBaseUrl,
2949
+ XIAOMI_TOKEN_PLAN_BASE_URLS,
2950
+ detectXiaomiTokenPlanBaseUrl,
2794
2951
  MOONSHOT_OAUTH_KEY,
2795
2952
  XAI_OAUTH_KEY,
2796
2953
  dualAuthProvider,
@@ -2825,4 +2982,4 @@ export {
2825
2982
  getDefaultThinkingLevel,
2826
2983
  getSummaryModel
2827
2984
  };
2828
- //# sourceMappingURL=chunk-QL5357JB.js.map
2985
+ //# sourceMappingURL=chunk-M53JVW2V.js.map