visualizar-rate-limit 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # visualizar-r-l
2
2
 
3
- (banner_visualizar.png)
3
+ ![Banner de visualizar-r-l](banner_visualizar.png)
4
4
 
5
5
  Una CLI liviana para ver los rate limits de Codex sin salir de la terminal. Si eres de los que revisan su uso con `tmux`, `weechat` o cualquier terminal de la vieja escuela, este mini panel te da dos barras limpias y un `watch` para mantener el pulso del consumo.
6
6
 
7
7
  ## Qué se ve
8
8
 
9
- (example.png)
9
+ ![Ejemplo de uso de visualizar-r-l](example.png)
10
10
 
11
11
  1. **Dos ventanas**: carga de 5h y semanal con porcentajes coloreados (verde/amarillo/rojo según urgencia).
12
12
  2. **Reset automático**: el parser extrae etiquetas como `Reset:` y muestra cuándo se renueva cada cuota.
Binary file
package/example.png ADDED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "visualizar-rate-limit",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "TUI para ver el rate limit de Codex desde chatgpt.com/codex/settings/usage",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,9 @@
11
11
  "src",
12
12
  "scripts",
13
13
  "README.md",
14
- "LICENSE"
14
+ "LICENSE",
15
+ "banner_visualizar.png",
16
+ "example.png"
15
17
  ],
16
18
  "scripts": {
17
19
  "postinstall": "chmod +x ./bin/visualizar-r-l ./src/fetch-usage.mjs ./scripts/install.sh",
@@ -98,8 +98,8 @@ function fallbackWindows(text) {
98
98
 
99
99
  function colorize(percent, value) {
100
100
  if (!process.stdout.isTTY) return value;
101
- if (percent >= 90) return `\x1b[31m${value}\x1b[0m`;
102
- if (percent >= 70) return `\x1b[33m${value}\x1b[0m`;
101
+ if (percent < 20) return `\x1b[31m${value}\x1b[0m`;
102
+ if (percent <= 50) return `\x1b[33m${value}\x1b[0m`;
103
103
  return `\x1b[32m${value}\x1b[0m`;
104
104
  }
105
105
 
@@ -153,6 +153,44 @@ function render(text) {
153
153
  }
154
154
  }
155
155
 
156
+ async function readPagePayload(page) {
157
+ return page.evaluate(() => ({
158
+ href: location.href,
159
+ title: document.title,
160
+ text: document.body?.innerText || '',
161
+ html: document.documentElement?.outerHTML || '',
162
+ }));
163
+ }
164
+
165
+ function looksUsablePayload(payload) {
166
+ const text = stripHtml(payload.text || payload.html);
167
+ if (!text) return false;
168
+ if (/just a moment|enable javascript and cookies to continue/i.test(text)) return false;
169
+ return /codex|usage|limit|rate|chatgpt/i.test(text);
170
+ }
171
+
172
+ async function ensureUsagePage(page) {
173
+ const currentUrl = page.url();
174
+
175
+ if (currentUrl === url) {
176
+ const payload = await readPagePayload(page);
177
+ if (looksUsablePayload(payload)) {
178
+ logDebug('Reutilizando pestaña existente ya cargada');
179
+ return payload;
180
+ }
181
+ }
182
+
183
+ logDebug(`Abriendo ${url}`);
184
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 20000 });
185
+ logDebug('DOM content loaded');
186
+ await page.waitForFunction(() => document.body && document.body.innerText.length > 50, { timeout: 5000 }).catch(() => {});
187
+ logDebug('Paso waitForFunction');
188
+ await page.waitForNetworkIdle({ idleTime: 350, timeout: 2500 }).catch(() => {});
189
+ logDebug('Paso waitForNetworkIdle');
190
+
191
+ return readPagePayload(page);
192
+ }
193
+
156
194
  let browser;
157
195
  let hardTimeout;
158
196
 
@@ -160,7 +198,7 @@ try {
160
198
  hardTimeout = setTimeout(() => {
161
199
  console.error('Timeout duro alcanzado mientras intentaba extraer la página.');
162
200
  process.exit(124);
163
- }, 45000);
201
+ }, 15000);
164
202
 
165
203
  logDebug(`Conectando a Chrome visible en 127.0.0.1:${debugPort}`);
166
204
  browser = await puppeteer.connect({
@@ -181,22 +219,7 @@ try {
181
219
  page.on('framenavigated', (frame) => {
182
220
  if (frame === page.mainFrame()) logDebug(`navegacion: ${frame.url()}`);
183
221
  });
184
- logDebug(`Abriendo ${url}`);
185
- await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
186
- logDebug('DOM content loaded');
187
- await page.waitForFunction(() => document.body && document.body.innerText.length > 50, { timeout: 30000 }).catch(() => {});
188
- logDebug('Paso waitForFunction');
189
- await page.waitForNetworkIdle({ idleTime: 1200, timeout: 15000 }).catch(() => {});
190
- logDebug('Paso waitForNetworkIdle');
191
- await new Promise((resolve) => setTimeout(resolve, 1500));
192
- logDebug('Pausa final completada');
193
-
194
- const payload = await page.evaluate(() => ({
195
- href: location.href,
196
- title: document.title,
197
- text: document.body?.innerText || '',
198
- html: document.documentElement?.outerHTML || '',
199
- }));
222
+ const payload = await ensureUsagePage(page);
200
223
 
201
224
  const text = stripHtml(payload.text || payload.html);
202
225
  logDebug(`Título detectado: ${payload.title}`);