Grok ratelimit indicator

Shows ratelimit information on Grok

当前为 2025-03-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Grok ratelimit indicator
  3. // @namespace https://6942020.xyz/
  4. // @version 1.0
  5. // @description Shows ratelimit information on Grok
  6. // @author WadeGrimridge
  7. // @match https://grok.com/*
  8. // @license MIT
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. "use strict";
  14.  
  15. let rateInfoElement = null;
  16. const modelRateLimits = {
  17. "grok-latest": null,
  18. "grok-3": null,
  19. };
  20. const modelDisplayNames = {
  21. "grok-latest": "Grok 2",
  22. "grok-3": "Grok 3",
  23. };
  24.  
  25. function formatTime(seconds) {
  26. const minutes = Math.floor(seconds / 60);
  27. const remainingSeconds = seconds % 60;
  28. return remainingSeconds > 0
  29. ? `${minutes}m ${remainingSeconds}s`
  30. : `${minutes}m`;
  31. }
  32.  
  33. async function fetchRateLimit(modelName, attempt = 1) {
  34. try {
  35. const response = await fetch("/rest/rate-limits", {
  36. method: "POST",
  37. headers: { "Content-Type": "application/json" },
  38. body: JSON.stringify({ requestKind: "DEFAULT", modelName }),
  39. });
  40.  
  41. if (response.status === 401 && attempt <= 10) {
  42. await new Promise((resolve) => setTimeout(resolve, 2500));
  43. return fetchRateLimit(modelName, attempt + 1);
  44. }
  45.  
  46. const data = await response.json();
  47. if (
  48. data.remainingQueries !== undefined &&
  49. data.totalQueries !== undefined
  50. ) {
  51. updateRateInfo(data, modelName);
  52. }
  53. } catch (error) {
  54. console.error(`[grok-ratelimit] Rate limit fetch failed:`, error);
  55. if (attempt > 10 && rateInfoElement) {
  56. rateInfoElement.textContent = "Couldn't fetch ratelimit info";
  57. }
  58. }
  59. }
  60.  
  61. function createRateInfoElement() {
  62. const targetDiv = document.querySelector(
  63. 'main div:has(> a[aria-label="Home page"])'
  64. );
  65. if (targetDiv && !rateInfoElement) {
  66. rateInfoElement = document.createElement("div");
  67. rateInfoElement.className = "ml-2 text-sm";
  68. rateInfoElement.textContent = "Fetching ratelimit info...";
  69. targetDiv.appendChild(rateInfoElement);
  70.  
  71. (async () => {
  72. await fetchRateLimit("grok-3");
  73. await fetchRateLimit("grok-latest");
  74. })();
  75. }
  76. }
  77.  
  78. function updateRateInfo(data, modelName) {
  79. if (rateInfoElement) {
  80. modelRateLimits[modelName] = data;
  81.  
  82. const lines = [];
  83. const displayOrder = ["grok-3", "grok-latest"];
  84.  
  85. for (const model of displayOrder) {
  86. const data = modelRateLimits[model];
  87. if (data) {
  88. const timeStr = formatTime(data.windowSizeSeconds);
  89. lines.push(
  90. `${modelDisplayNames[model]}: ${data.remainingQueries}/${data.totalQueries} (${timeStr})`
  91. );
  92. }
  93. }
  94.  
  95. rateInfoElement.textContent = lines.join(" | ");
  96. }
  97. }
  98.  
  99. const originalFetch = window.fetch;
  100. window.fetch = async function (...args) {
  101. const [resource, options] = args;
  102.  
  103. const url =
  104. resource instanceof Request ? resource.url : resource.toString();
  105.  
  106. if (url.includes("/rest/rate-limits")) {
  107. const requestBody = JSON.parse(options.body);
  108. const modelName = requestBody.modelName;
  109.  
  110. const response = await originalFetch.apply(this, args);
  111. const clone = response.clone();
  112. clone.json().then((data) => {
  113. if (
  114. data.remainingQueries !== undefined &&
  115. data.totalQueries !== undefined
  116. ) {
  117. updateRateInfo(data, modelName);
  118. }
  119. });
  120. return response;
  121. }
  122.  
  123. return originalFetch.apply(this, args);
  124. };
  125.  
  126. function waitForElement() {
  127. const targetDiv = document.querySelector(
  128. 'main div:has(> a[aria-label="Home page"])'
  129. );
  130. if (targetDiv) {
  131. createRateInfoElement();
  132. } else {
  133. requestAnimationFrame(waitForElement);
  134. }
  135. }
  136.  
  137. waitForElement();
  138. })();