@kenkaiiii/gg-core 5.89.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,
@@ -99,6 +104,7 @@ __export(index_exports, {
99
104
  kimiCodeBaseUrl: () => kimiCodeBaseUrl,
100
105
  kimiCodingHeaders: () => kimiCodingHeaders,
101
106
  localAuthStorageKey: () => localAuthStorageKey,
107
+ localModelShortName: () => localModelShortName,
102
108
  log: () => log,
103
109
  loginAnthropic: () => loginAnthropic,
104
110
  loginGemini: () => loginGemini,
@@ -106,6 +112,7 @@ __export(index_exports, {
106
112
  loginOpenAI: () => loginOpenAI,
107
113
  loginXai: () => loginXai,
108
114
  oauthStorageKey: () => oauthStorageKey,
115
+ ollamaServedContext: () => ollamaServedContext,
109
116
  openLog: () => openLog,
110
117
  parseLocalModelId: () => parseLocalModelId,
111
118
  pendingClaudeCodeVersionRefresh: () => import_gg_ai.pendingClaudeCodeVersionRefresh,
@@ -1524,6 +1531,91 @@ function isHiddenProvider(provider) {
1524
1531
  return HIDDEN_PROVIDERS.includes(provider);
1525
1532
  }
1526
1533
 
1534
+ // src/auth-storage.ts
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
+
1527
1619
  // src/auth-storage.ts
1528
1620
  var MOONSHOT_OAUTH_KEY = "moonshot-oauth";
1529
1621
  var XAI_OAUTH_KEY = "xai-oauth";
@@ -1574,6 +1666,15 @@ function activeBaseUrlEntry(data, provider) {
1574
1666
  }
1575
1667
  return data[provider];
1576
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
+ }
1577
1678
  function readStoredBaseUrlSync(authFile, provider) {
1578
1679
  try {
1579
1680
  const data = JSON.parse((0, import_node_fs3.readFileSync)(authFile, "utf-8"));
@@ -1620,8 +1721,12 @@ var AuthStorage = class {
1620
1721
  snapshotIno = 0;
1621
1722
  /** Per-provider lock to serialize concurrent refresh calls. */
1622
1723
  refreshLocks = /* @__PURE__ */ new Map();
1623
- constructor(filePath) {
1724
+ detectMiniMaxRegion;
1725
+ detectXiaomiCluster;
1726
+ constructor(filePath, options) {
1624
1727
  this.filePath = filePath ?? getAppPaths().authFile;
1728
+ this.detectMiniMaxRegion = options?.detectMiniMaxBaseUrl ?? cachedMiniMaxRegion;
1729
+ this.detectXiaomiCluster = options?.detectXiaomiTokenPlanBaseUrl ?? detectXiaomiTokenPlanBaseUrl;
1625
1730
  }
1626
1731
  /** Path to the on-disk auth file. Useful for status output. */
1627
1732
  get path() {
@@ -1683,7 +1788,7 @@ var AuthStorage = class {
1683
1788
  */
1684
1789
  async setLocalEndpoint(endpointId, baseUrl, apiKey) {
1685
1790
  await this.setCredentials(`${LOCAL_AUTH_KEY_PREFIX}${endpointId}`, {
1686
- accessToken: apiKey && apiKey.length > 0 ? apiKey : "local",
1791
+ accessToken: apiKey && apiKey.length > 0 ? apiKey : import_gg_ai3.LOCAL_NO_API_KEY,
1687
1792
  refreshToken: "",
1688
1793
  expiresAt: Date.now() + LOCAL_CREDENTIAL_LIFETIME_MS,
1689
1794
  baseUrl
@@ -1820,11 +1925,54 @@ var AuthStorage = class {
1820
1925
  await this.ensureFresh();
1821
1926
  return this.data[provider];
1822
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
+ }
1823
1946
  async setCredentials(provider, creds) {
1824
1947
  await this.mutateLatest((latest) => {
1825
1948
  latest[provider] = creds;
1826
1949
  });
1827
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
+ }
1970
+ // Keeps local-endpoint keys: they're the user's own config, and a 401 there is often a busy gateway.
1971
+ async clearRejectedApiKey(storageKey) {
1972
+ if (storageKey.startsWith(LOCAL_AUTH_KEY_PREFIX)) return false;
1973
+ await this.clearCredentials(storageKey);
1974
+ return true;
1975
+ }
1828
1976
  async clearCredentials(provider) {
1829
1977
  await this.mutateLatest((latest) => {
1830
1978
  delete latest[provider];
@@ -1938,6 +2086,7 @@ var AuthStorage = class {
1938
2086
  throw new NotLoggedInError(provider);
1939
2087
  }
1940
2088
  if (STATIC_API_KEY_PROVIDERS.has(provider)) {
2089
+ if (provider === "minimax" && !creds.baseUrl) return await this.withMiniMaxRegion(creds);
1941
2090
  return creds;
1942
2091
  }
1943
2092
  if (!opts?.forceRefresh && Date.now() < creds.expiresAt - refreshThresholdMs(creds)) {
@@ -2588,6 +2737,23 @@ var MODELS = [
2588
2737
  maxThinkingLevel: "max"
2589
2738
  },
2590
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
+ },
2591
2757
  {
2592
2758
  id: "MiniMax-M3",
2593
2759
  name: "MiniMax M3",
@@ -2838,7 +3004,7 @@ var DEFAULT_MODEL_IDS = {
2838
3004
  gemini: "gemini-3.1-flash-lite",
2839
3005
  glm: "glm-5.3",
2840
3006
  moonshot: "kimi-k3",
2841
- minimax: "MiniMax-M3",
3007
+ minimax: "MiniMax-M3.1-Flash",
2842
3008
  deepseek: "deepseek-v4-pro",
2843
3009
  huggingface: "moonshotai/Kimi-K2.7-Code",
2844
3010
  openrouter: "qwen/qwen3.8-max",
@@ -2932,6 +3098,13 @@ var ANTHROPIC_ADAPTIVE_THINKING_LEVELS = [
2932
3098
  ];
2933
3099
  var MOONSHOT_K3_THINKING_LEVELS = ["low", "high", "max"];
2934
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
+ ];
2935
3108
  var LOCAL_THINKING_LEVELS = ["low", "medium", "high", "max"];
2936
3109
  function isOpenAIGptModel(provider, model) {
2937
3110
  return provider === "openai" && model.startsWith("gpt-");
@@ -2948,6 +3121,9 @@ function isMoonshotK3Model(provider, model) {
2948
3121
  function isGlmModel(provider) {
2949
3122
  return provider === "glm";
2950
3123
  }
3124
+ function isMiniMaxEffortModel(provider, model) {
3125
+ return provider === "minimax" && model.startsWith("MiniMax-M3.1");
3126
+ }
2951
3127
  function isAnthropicXhighModel(provider, model) {
2952
3128
  return provider === "anthropic" && /opus-5|opus-4-8|opus-4-7|sonnet-5[-.]5|haiku-5[-.]5/.test(model);
2953
3129
  }
@@ -2980,6 +3156,7 @@ function getSupportedThinkingLevels(provider, model) {
2980
3156
  }
2981
3157
  if (isMoonshotK3Model(provider, model)) return MOONSHOT_K3_THINKING_LEVELS;
2982
3158
  if (provider === "deepseek") return DEEPSEEK_THINKING_LEVELS;
3159
+ if (isMiniMaxEffortModel(provider, model)) return MINIMAX_EFFORT_THINKING_LEVELS;
2983
3160
  if (isGlmModel(provider)) {
2984
3161
  const maxIndex2 = GLM_THINKING_LEVELS.indexOf(maxLevel);
2985
3162
  if (maxIndex2 === -1) return GLM_THINKING_LEVELS;
@@ -3000,7 +3177,7 @@ function isThinkingLevelSupported(provider, model, level) {
3000
3177
  }
3001
3178
  function getNextThinkingLevel(provider, model, current) {
3002
3179
  const supportedLevels = getSupportedThinkingLevels(provider, model);
3003
- 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
3004
3181
  // low/medium/high on `reasoning_effort` (verified against 0.32) and the
3005
3182
  // other OpenAI-compatible servers use the same three. A model that can't
3006
3183
  // reason at all already has no supported levels, so it never gets here.
@@ -3028,11 +3205,12 @@ function clampThinkingForPlanMode(level) {
3028
3205
  }
3029
3206
 
3030
3207
  // src/local-models.ts
3208
+ var import_gg_ai4 = require("@kenkaiiii/gg-ai");
3031
3209
  var DEFAULT_LOCAL_ENDPOINTS = [
3032
3210
  { id: "ollama", label: "Ollama", baseUrl: "http://127.0.0.1:11434/v1", kind: "ollama" }
3033
3211
  ];
3034
3212
  var FALLBACK_CONTEXT_WINDOW = 4096;
3035
- var LOCAL_API_KEY_PLACEHOLDER = "local";
3213
+ var LOCAL_API_KEY_PLACEHOLDER = import_gg_ai4.LOCAL_NO_API_KEY;
3036
3214
  var DEFAULT_PROBE_TIMEOUT_MS = 1200;
3037
3215
  var ENRICH_CONCURRENCY = 6;
3038
3216
  var CACHE_TTL_MS = 3e4;
@@ -3048,6 +3226,9 @@ function parseLocalModelId(id) {
3048
3226
  if (slash <= 0 || slash === rest.length - 1) return void 0;
3049
3227
  return { endpointId: rest.slice(0, slash), rawId: rest.slice(slash + 1) };
3050
3228
  }
3229
+ function localModelShortName(rawId) {
3230
+ return rawId.slice(rawId.lastIndexOf("/") + 1) || rawId;
3231
+ }
3051
3232
  function isLocalModelId(id) {
3052
3233
  return parseLocalModelId(id) !== void 0;
3053
3234
  }
@@ -3058,8 +3239,9 @@ function endpointRoot(baseUrl) {
3058
3239
  return baseUrl.replace(/\/+$/, "").replace(/\/v1$/, "");
3059
3240
  }
3060
3241
  function authHeaders(endpoint) {
3242
+ const key = (0, import_gg_ai4.localBearerKey)(endpoint.apiKey);
3061
3243
  return {
3062
- Authorization: `Bearer ${endpoint.apiKey ?? LOCAL_API_KEY_PLACEHOLDER}`,
3244
+ ...key ? { Authorization: `Bearer ${key}` } : {},
3063
3245
  Accept: "application/json"
3064
3246
  };
3065
3247
  }
@@ -3121,10 +3303,22 @@ async function enrich(endpoint, entries, options) {
3121
3303
  if (endpoint.kind === "lmstudio") return enrichLmStudio(endpoint, entries, options);
3122
3304
  if (endpoint.kind === "ollama") return enrichOllama(endpoint, entries, options);
3123
3305
  if (endpoint.kind === "llamacpp") return enrichLlamaCpp(endpoint, entries, options);
3306
+ if (endpoint.kind === "custom") return enrichCustom(endpoint, entries, options);
3124
3307
  return entries.map((entry) => genericModel(endpoint, entry));
3125
3308
  }
3309
+ async function enrichCustom(endpoint, entries, options) {
3310
+ const generic = entries.map((entry) => genericModel(endpoint, entry));
3311
+ if (generic.every((model) => model.contextWindowKnown)) return generic;
3312
+ const root = endpointRoot(endpoint.baseUrl);
3313
+ const props = await fetchJson(`${root}/props`, endpoint, options);
3314
+ const nCtx = contextLength(props?.default_generation_settings?.n_ctx);
3315
+ if (nCtx !== void 0) return llamaCppModels(endpoint, entries, nCtx);
3316
+ const lmStudio = await fetchJson(`${root}/api/v1/models`, endpoint, options);
3317
+ if (Array.isArray(lmStudio?.models)) return enrichLmStudio(endpoint, entries, options, lmStudio);
3318
+ return generic;
3319
+ }
3126
3320
  function genericModel(endpoint, entry) {
3127
- const declared = contextLength(entry.max_model_len);
3321
+ const declared = contextLength(entry.max_model_len) ?? contextLength(entry.context_length);
3128
3322
  return {
3129
3323
  rawId: entry.id,
3130
3324
  endpointId: endpoint.id,
@@ -3151,9 +3345,7 @@ async function enrichOllama(endpoint, entries, options) {
3151
3345
  });
3152
3346
  const caps = Array.isArray(show?.capabilities) ? show.capabilities : [];
3153
3347
  if (caps.includes("embedding") && !caps.includes("completion")) return void 0;
3154
- const ctx = contextLength(
3155
- runningModels.find((model) => model?.name === entry.id || model?.model === entry.id)?.context_length
3156
- );
3348
+ const ctx = runningContext(runningModels, entry.id) ?? modelfileNumCtx(show?.parameters);
3157
3349
  return {
3158
3350
  rawId: entry.id,
3159
3351
  endpointId: endpoint.id,
@@ -3168,12 +3360,41 @@ async function enrichOllama(endpoint, entries, options) {
3168
3360
  });
3169
3361
  return enriched.filter((model) => model !== void 0);
3170
3362
  }
3363
+ function runningContext(models, rawId) {
3364
+ return contextLength(
3365
+ models.find((model) => model?.name === rawId || model?.model === rawId)?.context_length
3366
+ );
3367
+ }
3368
+ function modelfileNumCtx(parameters) {
3369
+ const match = /^num_ctx\s+(\d+)\s*$/m.exec(parameters ?? "");
3370
+ return match ? contextLength(Number(match[1])) : void 0;
3371
+ }
3372
+ async function ollamaServedContext(endpoint, rawId, {
3373
+ load = false,
3374
+ timeoutMs = 12e4,
3375
+ signal
3376
+ } = {}) {
3377
+ const root = endpointRoot(endpoint.baseUrl);
3378
+ if (load) {
3379
+ await fetchJson(`${root}/api/generate`, endpoint, {
3380
+ timeoutMs,
3381
+ signal,
3382
+ method: "POST",
3383
+ body: { model: rawId }
3384
+ });
3385
+ }
3386
+ const running = await fetchJson(`${root}/api/ps`, endpoint, {
3387
+ timeoutMs: DEFAULT_PROBE_TIMEOUT_MS,
3388
+ signal
3389
+ });
3390
+ return runningContext(Array.isArray(running?.models) ? running.models : [], rawId);
3391
+ }
3171
3392
  function contextLength(value) {
3172
3393
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
3173
3394
  }
3174
- async function enrichLmStudio(endpoint, entries, options) {
3395
+ async function enrichLmStudio(endpoint, entries, options, fetched) {
3175
3396
  const root = endpointRoot(endpoint.baseUrl);
3176
- const detail = await fetchJson(`${root}/api/v1/models`, endpoint, options);
3397
+ const detail = fetched ?? await fetchJson(`${root}/api/v1/models`, endpoint, options);
3177
3398
  const byId = /* @__PURE__ */ new Map();
3178
3399
  if (Array.isArray(detail?.models)) {
3179
3400
  for (const model of detail.models) {
@@ -3231,12 +3452,17 @@ async function enrichLlamaCpp(endpoint, entries, options) {
3231
3452
  endpoint,
3232
3453
  options
3233
3454
  );
3234
- const nCtx = contextLength(props?.default_generation_settings?.n_ctx);
3235
- const known = nCtx !== void 0;
3455
+ return llamaCppModels(
3456
+ endpoint,
3457
+ entries,
3458
+ contextLength(props?.default_generation_settings?.n_ctx)
3459
+ );
3460
+ }
3461
+ function llamaCppModels(endpoint, entries, nCtx) {
3236
3462
  return entries.map((entry) => ({
3237
3463
  ...genericModel(endpoint, entry),
3238
- contextWindow: known ? nCtx : FALLBACK_CONTEXT_WINDOW,
3239
- contextWindowKnown: known
3464
+ contextWindow: nCtx ?? FALLBACK_CONTEXT_WINDOW,
3465
+ contextWindowKnown: nCtx !== void 0
3240
3466
  }));
3241
3467
  }
3242
3468
  async function mapLimited(items, limit, fn) {
@@ -3393,7 +3619,7 @@ var ALL_AUTH_PROVIDERS = [
3393
3619
  {
3394
3620
  value: "minimax",
3395
3621
  label: "MiniMax",
3396
- description: "MiniMax M3",
3622
+ description: "MiniMax M3.1 Flash, M3",
3397
3623
  methods: ["apikey"],
3398
3624
  apiKeyLabel: "MiniMax"
3399
3625
  },
@@ -4226,6 +4452,8 @@ function createAutoUpdater(config) {
4226
4452
  HIDDEN_PROVIDERS,
4227
4453
  LOCAL_API_KEY_PLACEHOLDER,
4228
4454
  LOCAL_AUTH_KEY_PREFIX,
4455
+ MINIMAX_CN_BASE_URL,
4456
+ MINIMAX_GLOBAL_BASE_URL,
4229
4457
  MODELS,
4230
4458
  MOONSHOT_OAUTH_KEY,
4231
4459
  NotLoggedInError,
@@ -4234,6 +4462,7 @@ function createAutoUpdater(config) {
4234
4462
  TelegramBot,
4235
4463
  XAI_OAUTH_KEY,
4236
4464
  XIAOMI_CREDITS_KEY,
4465
+ XIAOMI_TOKEN_PLAN_BASE_URLS,
4237
4466
  authPriorityNote,
4238
4467
  clampThinkingForPlanMode,
4239
4468
  clearLocalDiscoveryCache,
@@ -4242,6 +4471,8 @@ function createAutoUpdater(config) {
4242
4471
  createAutoUpdater,
4243
4472
  decodeOggOpus,
4244
4473
  describeAuthMethods,
4474
+ detectMiniMaxBaseUrl,
4475
+ detectXiaomiTokenPlanBaseUrl,
4245
4476
  discoverLocalModels,
4246
4477
  downmixToMono,
4247
4478
  dualAuthProvider,
@@ -4285,6 +4516,7 @@ function createAutoUpdater(config) {
4285
4516
  kimiCodeBaseUrl,
4286
4517
  kimiCodingHeaders,
4287
4518
  localAuthStorageKey,
4519
+ localModelShortName,
4288
4520
  log,
4289
4521
  loginAnthropic,
4290
4522
  loginGemini,
@@ -4292,6 +4524,7 @@ function createAutoUpdater(config) {
4292
4524
  loginOpenAI,
4293
4525
  loginXai,
4294
4526
  oauthStorageKey,
4527
+ ollamaServedContext,
4295
4528
  openLog,
4296
4529
  parseLocalModelId,
4297
4530
  pendingClaudeCodeVersionRefresh,