@prestyj/core 5.24.0 → 5.25.1

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
@@ -48,6 +48,7 @@ __export(index_exports, {
48
48
  clearLocalDiscoveryCache: () => clearLocalDiscoveryCache,
49
49
  clearRuntimeModels: () => clearRuntimeModels,
50
50
  closeLogger: () => closeLogger,
51
+ compareClaudeCodeVersions: () => compareClaudeCodeVersions,
51
52
  createAutoUpdater: () => createAutoUpdater,
52
53
  decodeOggOpus: () => decodeOggOpus,
53
54
  discoverLocalModels: () => discoverLocalModels,
@@ -101,6 +102,7 @@ __export(index_exports, {
101
102
  probeEndpoint: () => probeEndpoint,
102
103
  providerStorageKeys: () => providerStorageKeys,
103
104
  readStoredBaseUrlSync: () => readStoredBaseUrlSync,
105
+ recordRequiredClaudeCodeVersion: () => recordRequiredClaudeCodeVersion,
104
106
  refreshAnthropicToken: () => refreshAnthropicToken,
105
107
  refreshGeminiToken: () => refreshGeminiToken,
106
108
  refreshKimiToken: () => refreshKimiToken,
@@ -365,7 +367,7 @@ async function refreshKimiToken(refreshToken) {
365
367
 
366
368
  // src/auth-storage.ts
367
369
  var import_promises4 = __toESM(require("fs/promises"), 1);
368
- var import_node_fs3 = require("fs");
370
+ var import_node_fs4 = require("fs");
369
371
  var import_node_crypto6 = __toESM(require("crypto"), 1);
370
372
 
371
373
  // src/oauth/anthropic.ts
@@ -391,6 +393,7 @@ async function generatePKCE() {
391
393
 
392
394
  // src/claude-code-version.ts
393
395
  var import_promises = __toESM(require("fs/promises"), 1);
396
+ var import_node_fs3 = require("fs");
394
397
  var import_node_path4 = __toESM(require("path"), 1);
395
398
 
396
399
  // src/logger.ts
@@ -518,19 +521,41 @@ function closeLogger(opts) {
518
521
 
519
522
  // src/claude-code-version.ts
520
523
  var NPM_LATEST_URL = "https://registry.npmjs.org/@anthropic-ai/claude-code/latest";
521
- var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
524
+ var CACHE_FRESH_MS = 60 * 60 * 1e3;
525
+ var CACHE_HARD_MS = 24 * 60 * 60 * 1e3;
522
526
  var FETCH_TIMEOUT_MS = 3e3;
523
- var FALLBACK_VERSION = "2.1.88";
527
+ var FALLBACK_VERSION = "2.1.280";
524
528
  var memoryCache = null;
525
529
  var inflight = null;
530
+ var backgroundRefresh = null;
531
+ var versionFloor = null;
526
532
  function cachePath() {
527
533
  return import_node_path4.default.join(getAppPaths().agentDir, "claude-code-version.json");
528
534
  }
535
+ function compareClaudeCodeVersions(a, b) {
536
+ const parse = (v) => v.split(".").map((part) => Number.parseInt(part, 10)).map((n) => Number.isFinite(n) ? n : 0);
537
+ const left = parse(a);
538
+ const right = parse(b);
539
+ for (let i = 0; i < Math.max(left.length, right.length); i += 1) {
540
+ const diff = (left[i] ?? 0) - (right[i] ?? 0);
541
+ if (diff !== 0) return diff;
542
+ }
543
+ return 0;
544
+ }
545
+ function applyFloor(version) {
546
+ if (!versionFloor) return version;
547
+ return compareClaudeCodeVersions(versionFloor, version) > 0 ? versionFloor : version;
548
+ }
529
549
  async function readDiskCache() {
530
550
  try {
531
551
  const raw = await import_promises.default.readFile(cachePath(), "utf-8");
532
552
  const parsed = JSON.parse(raw);
533
553
  if (typeof parsed.version === "string" && typeof parsed.fetchedAt === "number") {
554
+ if (typeof parsed.minVersion === "string") {
555
+ if (!versionFloor || compareClaudeCodeVersions(parsed.minVersion, versionFloor) > 0) {
556
+ versionFloor = parsed.minVersion;
557
+ }
558
+ }
534
559
  return parsed;
535
560
  }
536
561
  return null;
@@ -541,7 +566,11 @@ async function readDiskCache() {
541
566
  async function writeDiskCache(data) {
542
567
  try {
543
568
  await import_promises.default.mkdir(getAppPaths().agentDir, { recursive: true, mode: 448 });
544
- await import_promises.default.writeFile(cachePath(), JSON.stringify(data), { mode: 384 });
569
+ await import_promises.default.writeFile(
570
+ cachePath(),
571
+ JSON.stringify({ ...data, ...versionFloor ? { minVersion: versionFloor } : {} }),
572
+ { mode: 384 }
573
+ );
545
574
  } catch (err) {
546
575
  log(
547
576
  "WARN",
@@ -567,6 +596,19 @@ async function fetchLatest() {
567
596
  clearTimeout(timer);
568
597
  }
569
598
  }
599
+ function refreshInBackground() {
600
+ if (backgroundRefresh) return;
601
+ backgroundRefresh = (async () => {
602
+ const fetched = await fetchLatest();
603
+ if (fetched) {
604
+ await writeDiskCache({ version: fetched, fetchedAt: Date.now() });
605
+ memoryCache = { version: applyFloor(fetched), expiresAt: Date.now() + CACHE_FRESH_MS };
606
+ }
607
+ })().catch(() => {
608
+ }).finally(() => {
609
+ backgroundRefresh = null;
610
+ });
611
+ }
570
612
  async function getClaudeCodeVersion() {
571
613
  if (memoryCache && Date.now() < memoryCache.expiresAt) {
572
614
  return memoryCache.version;
@@ -574,18 +616,26 @@ async function getClaudeCodeVersion() {
574
616
  if (inflight) return inflight;
575
617
  inflight = (async () => {
576
618
  const disk = await readDiskCache();
577
- const diskFresh = disk && Date.now() - disk.fetchedAt < CACHE_TTL_MS;
578
- if (disk && diskFresh) {
579
- memoryCache = { version: disk.version, expiresAt: Date.now() + CACHE_TTL_MS };
580
- return disk.version;
619
+ const age = disk ? Date.now() - disk.fetchedAt : Infinity;
620
+ if (disk && age < CACHE_FRESH_MS) {
621
+ const version = applyFloor(disk.version);
622
+ memoryCache = { version, expiresAt: Date.now() + CACHE_FRESH_MS };
623
+ return version;
624
+ }
625
+ if (disk && age < CACHE_HARD_MS) {
626
+ const version = applyFloor(disk.version);
627
+ memoryCache = { version, expiresAt: Date.now() + 5 * 60 * 1e3 };
628
+ refreshInBackground();
629
+ return version;
581
630
  }
582
631
  const fetched = await fetchLatest();
583
632
  if (fetched) {
584
633
  await writeDiskCache({ version: fetched, fetchedAt: Date.now() });
585
- memoryCache = { version: fetched, expiresAt: Date.now() + CACHE_TTL_MS };
586
- return fetched;
634
+ const version = applyFloor(fetched);
635
+ memoryCache = { version, expiresAt: Date.now() + CACHE_FRESH_MS };
636
+ return version;
587
637
  }
588
- const resolved = disk?.version ?? FALLBACK_VERSION;
638
+ const resolved = applyFloor(disk?.version ?? FALLBACK_VERSION);
589
639
  memoryCache = { version: resolved, expiresAt: Date.now() + 5 * 60 * 1e3 };
590
640
  log(
591
641
  "WARN",
@@ -600,6 +650,44 @@ async function getClaudeCodeVersion() {
600
650
  inflight = null;
601
651
  }
602
652
  }
653
+ var REQUIRED_VERSION_PATTERN = /version\s+(\d+(?:\.\d+)+)\s+or\s+newer\s+is\s+required/i;
654
+ function recordRequiredClaudeCodeVersion(message) {
655
+ const required = REQUIRED_VERSION_PATTERN.exec(message ?? "")?.[1];
656
+ if (!required) return null;
657
+ if (versionFloor && compareClaudeCodeVersions(required, versionFloor) <= 0) return versionFloor;
658
+ versionFloor = required;
659
+ memoryCache = null;
660
+ log(
661
+ "WARN",
662
+ "claude-code-version",
663
+ `Provider requires Claude Code >= ${required}; pinning User-Agent floor`
664
+ );
665
+ try {
666
+ const dir = getAppPaths().agentDir;
667
+ (0, import_node_fs3.mkdirSync)(dir, { recursive: true, mode: 448 });
668
+ let existing = {};
669
+ try {
670
+ existing = JSON.parse((0, import_node_fs3.readFileSync)(cachePath(), "utf-8"));
671
+ } catch {
672
+ }
673
+ (0, import_node_fs3.writeFileSync)(
674
+ cachePath(),
675
+ JSON.stringify({
676
+ version: existing.version ?? required,
677
+ fetchedAt: existing.fetchedAt ?? 0,
678
+ minVersion: required
679
+ }),
680
+ { mode: 384 }
681
+ );
682
+ } catch (err) {
683
+ log(
684
+ "WARN",
685
+ "claude-code-version",
686
+ `Failed to persist required version: ${err instanceof Error ? err.message : String(err)}`
687
+ );
688
+ }
689
+ return required;
690
+ }
603
691
  async function getClaudeCliUserAgent() {
604
692
  const version = await getClaudeCodeVersion();
605
693
  return `claude-cli/${version} (external, cli)`;
@@ -1587,7 +1675,7 @@ function activeBaseUrlEntry(data, provider) {
1587
1675
  }
1588
1676
  function readStoredBaseUrlSync(authFile, provider) {
1589
1677
  try {
1590
- const data = JSON.parse((0, import_node_fs3.readFileSync)(authFile, "utf-8"));
1678
+ const data = JSON.parse((0, import_node_fs4.readFileSync)(authFile, "utf-8"));
1591
1679
  return activeBaseUrlEntry(data, provider)?.baseUrl;
1592
1680
  } catch {
1593
1681
  return void 0;
@@ -2078,11 +2166,37 @@ var MODELS = [
2078
2166
  // costTier: "high",
2079
2167
  // maxThinkingLevel: "max",
2080
2168
  // },
2169
+ {
2170
+ // Released 2026-09-22 — "For long-running agentic coding and knowledge
2171
+ // work". Fable-class capability at $4/$20 MTok (cheaper than the Opus 5 it
2172
+ // replaces, $5/$25). Adaptive thinking with the full effort ladder
2173
+ // (low→max, xhigh included), but thinking can no longer be disabled: a
2174
+ // `thinking: {type: "disabled"}` or budget_tokens request 400s. @prestyj/ai
2175
+ // omits the field entirely when thinking is off, so that path is safe.
2176
+ // Forced tool use (`tool_choice` any/tool) also 400s — see
2177
+ // `toAnthropicToolChoice`, which downgrades it to `auto` for this model.
2178
+ // Anthropic declares the server-side default effort as `medium` (Opus 5
2179
+ // ran `high`), and 5.5 thinks more per turn at a given level, so a fresh
2180
+ // session starts at `medium` rather than the ladder ceiling.
2181
+ id: "claude-opus-5-5",
2182
+ name: "Claude Opus 5.5",
2183
+ provider: "anthropic",
2184
+ contextWindow: 1e6,
2185
+ maxOutputTokens: 128e3,
2186
+ supportsThinking: true,
2187
+ defaultThinkingLevel: "medium",
2188
+ supportsImages: true,
2189
+ supportsVideo: false,
2190
+ costTier: "high",
2191
+ maxThinkingLevel: "max"
2192
+ },
2081
2193
  {
2082
2194
  // Released 2026-07-24 — "For complex agentic coding and enterprise work".
2083
2195
  // Near-Fable capability at half the price ($5/$25 vs $10/$50). Adaptive
2084
2196
  // thinking with the full effort ladder (low→max, xhigh included); dateless
2085
- // ID is the canonical pinned snapshot (post-4.6 naming scheme).
2197
+ // ID is the canonical pinned snapshot (post-4.6 naming scheme). Kept as a
2198
+ // legacy option now that Opus 5.5 leads the line: it's the last Opus that
2199
+ // accepts disabled thinking and forced tool use.
2086
2200
  id: "claude-opus-5",
2087
2201
  name: "Claude Opus 5",
2088
2202
  provider: "anthropic",
@@ -2231,16 +2345,21 @@ var MODELS = [
2231
2345
  maxThinkingLevel: "max"
2232
2346
  },
2233
2347
  // ── xAI (Grok) ─────────────────────────────────────────
2234
- // Grok 4.6 (released 2026-08-12) is xAI's flagship for coding, agentic tasks,
2235
- // and knowledge work, with a focus on long-running agents — 500K context,
2236
- // text+image input, and a `reasoning_effort` ladder that adds a new `xhigh`
2237
- // top rung (low/medium/high default/xhigh; reasoning still can't be fully
2348
+ // Grok 4.7 (released 2026-09-21) — xAI's flagship for coding, agentic tasks,
2349
+ // and knowledge work: a new, larger base model with a longer RL run weighted
2350
+ // toward hours-long tasks, plus stronger self-verification and long-context
2351
+ // management. 500K context, text+image input, and a `reasoning_effort`
2352
+ // ladder of low/medium/high default/xhigh (reasoning still can't be fully
2238
2353
  // disabled). $2/$6 per MTok under 200K prompt tokens ($4/$12 at or above),
2239
- // and it's the default model of the Grok Build coding agent. xAI advertises "no text output limit"; we keep the same
2240
- // 131K practical cap as 4.5 for budget predictability and input headroom.
2354
+ // and it's the default model of the Grok Build coding agent. xAI advertises
2355
+ // "no fixed text output limit"; we keep the 131K practical cap for budget
2356
+ // predictability and input headroom. (A faster "Grok 4.7 Fast" variant
2357
+ // exists but is Cursor/Grok Build-only — not on the public API — so it isn't
2358
+ // registered.) Only the newest Grok ships — 4.6/4.5 are superseded and
2359
+ // retired; saved sessions on them fall back to this default.
2241
2360
  {
2242
- id: "grok-4.6",
2243
- name: "Grok 4.6",
2361
+ id: "grok-4.7",
2362
+ name: "Grok 4.7",
2244
2363
  provider: "xai",
2245
2364
  contextWindow: 5e5,
2246
2365
  maxOutputTokens: 131072,
@@ -2250,24 +2369,6 @@ var MODELS = [
2250
2369
  costTier: "medium",
2251
2370
  maxThinkingLevel: "xhigh"
2252
2371
  },
2253
- // Grok 4.5 (released 2026-07-08) — superseded by 4.6 but retained as an explicit option. 500K context, text+image input,
2254
- // configurable `reasoning_effort` (low/medium/high, server default high;
2255
- // reasoning can't be fully disabled). Served over the OpenAI-compatible API
2256
- // at https://api.x.ai/v1 (API key from console.x.ai). xAI hasn't published an
2257
- // official max-output cap for 4.5; 131K matches the Grok Responses ceiling
2258
- // third-party integrations use.
2259
- {
2260
- id: "grok-4.5",
2261
- name: "Grok 4.5",
2262
- provider: "xai",
2263
- contextWindow: 5e5,
2264
- maxOutputTokens: 131072,
2265
- supportsThinking: true,
2266
- supportsImages: true,
2267
- supportsVideo: false,
2268
- costTier: "medium",
2269
- maxThinkingLevel: "high"
2270
- },
2271
2372
  // ── Gemini ─────────────────────────────────────────
2272
2373
  {
2273
2374
  id: "gemini-3.1-flash-lite",
@@ -2456,11 +2557,15 @@ var MODELS = [
2456
2557
  maxThinkingLevel: "high"
2457
2558
  },
2458
2559
  // ── Xiaomi (MiMo) ──────────────────────────────────────
2459
- // V2.6 series (2026-09) supersedes V2.5 one-for-one: pro → pro, the omni
2460
- // `mimo-v2.5` → flash, ultraspeed → ultraspeed. The whole series is now
2461
- // full-modality, so unlike V2.5-Pro the flagship no longer needs a separate
2462
- // omni sibling for attachments. V2.5 entries are retired here — a session
2463
- // that still has one saved falls back to the provider default on next start.
2560
+ // V2.6 series (released 2026-09-22, open-weight: Pro 1.02T/42B-A, Flash
2561
+ // 309B/15B-A, plus a 9B Qwen distill not served over the API) supersedes V2.5
2562
+ // one-for-one: pro → pro, the omni `mimo-v2.5` → flash, ultraspeed →
2563
+ // ultraspeed. Every V2.6 text model is natively full-modality, so unlike
2564
+ // V2.5-Pro the flagship no longer needs a separate omni sibling for
2565
+ // attachments — image/video ride the same OpenAI-compatible base64 transport
2566
+ // the old omni model used. API prices are unchanged from V2.5. The V2.5 ids
2567
+ // deprecate on the platform 2026-10-21 and are retired here — a session that
2568
+ // still has one saved falls back to the provider default on next start.
2464
2569
  //
2465
2570
  // Capabilities below are measured against the Token Plan host, not taken
2466
2571
  // from marketing copy: image and video both come back with `image_tokens` /
@@ -2470,6 +2575,8 @@ var MODELS = [
2470
2575
  // binary 1M below (2^20) and not the decimal 1e6 V2.5 was listed with — the
2471
2576
  // few-token gap is the chat envelope the server adds on top of the content.
2472
2577
  {
2578
+ // Coding/agentic flagship — highest open-weight score on Artificial
2579
+ // Analysis at launch (46, tied with Grok 4.7).
2473
2580
  id: "mimo-v2.6-pro",
2474
2581
  name: "MiMo-V2.6-Pro",
2475
2582
  provider: "xiaomi",
@@ -2483,9 +2590,10 @@ var MODELS = [
2483
2590
  maxThinkingLevel: "high",
2484
2591
  authStorageKeys: ["xiaomi", XIAOMI_CREDITS_KEY]
2485
2592
  },
2486
- // Flash: the cheap, high-frequency sibling at the same modality surface and
2487
- // window as Pro. It is the provider's `low` tier, so scout sub-agents and
2488
- // compaction summaries route here instead of paying Pro rates.
2593
+ // Flash: the cheap, high-frequency sibling (~10% of Pro's price class) at the
2594
+ // same modality surface and window as Pro. It is the provider's `low` tier,
2595
+ // so scout sub-agents and compaction summaries route here instead of paying
2596
+ // Pro rates.
2489
2597
  {
2490
2598
  id: "mimo-v2.6-flash",
2491
2599
  name: "MiMo-V2.6-Flash",
@@ -2506,9 +2614,9 @@ var MODELS = [
2506
2614
  // authStorageKeys doc). The Token Plan host rejects it with "Not supported
2507
2615
  // model" — the known-model/wrong-host reply — where an invented id gets
2508
2616
  // "Unsupported model", which is how this id was confirmed without a
2509
- // Credits key. Attachment support is inferred from the series announcement
2510
- // ("full modality across the series") rather than measured: images are
2511
- // enabled, video stays off until it can be verified on the platform host.
2617
+ // Credits key. Attachments can't be probed directly for the same reason, so
2618
+ // this entry tracks the rest of the V2.6 series ("full modality across the
2619
+ // series") and mirrors Pro's verified image+video surface.
2512
2620
  {
2513
2621
  id: "mimo-v2.6-pro-ultraspeed",
2514
2622
  name: "MiMo-V2.6-Pro-UltraSpeed",
@@ -2517,7 +2625,8 @@ var MODELS = [
2517
2625
  maxOutputTokens: 131072,
2518
2626
  supportsThinking: true,
2519
2627
  supportsImages: true,
2520
- supportsVideo: false,
2628
+ supportsVideo: true,
2629
+ maxVideoBytes: 36 * 1024 * 1024,
2521
2630
  costTier: "high",
2522
2631
  maxThinkingLevel: "high",
2523
2632
  authStorageKeys: [XIAOMI_CREDITS_KEY]
@@ -2667,7 +2776,7 @@ function getDefaultModel(provider) {
2667
2776
  return MODELS.find((m) => m.id === "Qwen/Qwen3-Coder-480B-A35B-Instruct");
2668
2777
  if (provider === "openrouter") return MODELS.find((m) => m.id === "qwen/qwen3.6-plus");
2669
2778
  if (provider === "sakana") return MODELS.find((m) => m.id === "fugu");
2670
- if (provider === "xai") return MODELS.find((m) => m.id === "grok-4.6");
2779
+ if (provider === "xai") return MODELS.find((m) => m.id === "grok-4.7");
2671
2780
  if (provider === "local") {
2672
2781
  return getModelsForProvider("local")[0] ?? PLACEHOLDER_LOCAL_MODEL;
2673
2782
  }
@@ -2849,7 +2958,7 @@ var FALLBACK_CONTEXT_WINDOW = 4096;
2849
2958
  var LOCAL_API_KEY_PLACEHOLDER = "local";
2850
2959
  var DEFAULT_PROBE_TIMEOUT_MS = 1200;
2851
2960
  var ENRICH_CONCURRENCY = 6;
2852
- var CACHE_TTL_MS2 = 3e4;
2961
+ var CACHE_TTL_MS = 3e4;
2853
2962
  var NON_CHAT_ID_PATTERN = /(?:^|[-_/])(?:embed|embedding|rerank|reranker|bge|nomic-embed)/i;
2854
2963
  var LOCAL_ID_PREFIX = "local/";
2855
2964
  function formatLocalModelId(endpointId, rawId) {
@@ -3090,7 +3199,7 @@ function cacheKey(endpoints) {
3090
3199
  }
3091
3200
  async function discoverLocalModels(endpoints = DEFAULT_LOCAL_ENDPOINTS, options = {}) {
3092
3201
  const key = cacheKey(endpoints);
3093
- if (!options.force && cache && cache.key === key && Date.now() - cache.at < CACHE_TTL_MS2) {
3202
+ if (!options.force && cache && cache.key === key && Date.now() - cache.at < CACHE_TTL_MS) {
3094
3203
  return cache.result;
3095
3204
  }
3096
3205
  const probes = await Promise.all(endpoints.map((endpoint) => probeEndpoint(endpoint, options)));
@@ -3663,7 +3772,7 @@ async function transcribeVoice(fileUrl) {
3663
3772
 
3664
3773
  // src/auto-update.ts
3665
3774
  var import_node_child_process2 = require("child_process");
3666
- var import_node_fs4 = __toESM(require("fs"), 1);
3775
+ var import_node_fs5 = __toESM(require("fs"), 1);
3667
3776
  var import_node_path5 = __toESM(require("path"), 1);
3668
3777
  var CHECK_INTERVAL_MS = 60 * 60 * 1e3;
3669
3778
  var FETCH_TIMEOUT_MS2 = 1e4;
@@ -3697,7 +3806,7 @@ function createAutoUpdater(config) {
3697
3806
  }
3698
3807
  function readState() {
3699
3808
  try {
3700
- const raw = import_node_fs4.default.readFileSync(stateFilePath(), "utf-8");
3809
+ const raw = import_node_fs5.default.readFileSync(stateFilePath(), "utf-8");
3701
3810
  return JSON.parse(raw);
3702
3811
  } catch {
3703
3812
  return null;
@@ -3706,8 +3815,8 @@ function createAutoUpdater(config) {
3706
3815
  function writeState(state) {
3707
3816
  try {
3708
3817
  const filePath = stateFilePath();
3709
- import_node_fs4.default.mkdirSync(import_node_path5.default.dirname(filePath), { recursive: true, mode: 448 });
3710
- import_node_fs4.default.writeFileSync(filePath, JSON.stringify(state));
3818
+ import_node_fs5.default.mkdirSync(import_node_path5.default.dirname(filePath), { recursive: true, mode: 448 });
3819
+ import_node_fs5.default.writeFileSync(filePath, JSON.stringify(state));
3711
3820
  } catch {
3712
3821
  }
3713
3822
  }
@@ -3849,6 +3958,7 @@ function createAutoUpdater(config) {
3849
3958
  clearLocalDiscoveryCache,
3850
3959
  clearRuntimeModels,
3851
3960
  closeLogger,
3961
+ compareClaudeCodeVersions,
3852
3962
  createAutoUpdater,
3853
3963
  decodeOggOpus,
3854
3964
  discoverLocalModels,
@@ -3902,6 +4012,7 @@ function createAutoUpdater(config) {
3902
4012
  probeEndpoint,
3903
4013
  providerStorageKeys,
3904
4014
  readStoredBaseUrlSync,
4015
+ recordRequiredClaudeCodeVersion,
3905
4016
  refreshAnthropicToken,
3906
4017
  refreshGeminiToken,
3907
4018
  refreshKimiToken,