gemx 0.2.2__tar.gz → 0.2.4__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gemx
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Drive the Gemini web UI from Python via Playwright
5
5
  Project-URL: Homepage, https://github.com/ra0x3/gemx
6
6
  Project-URL: Repository, https://github.com/ra0x3/gemx
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "gemx"
3
- version = "0.2.2"
3
+ version = "0.2.4"
4
4
  description = "Drive the Gemini web UI from Python via Playwright"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -28,4 +28,4 @@ __all__ = [
28
28
  "parse_output",
29
29
  ]
30
30
 
31
- __version__ = "0.2.2"
31
+ __version__ = "0.2.4"
@@ -26,6 +26,7 @@ from pathlib import Path
26
26
  from typing import Any, AsyncIterator
27
27
 
28
28
  from playwright.async_api import Page, async_playwright
29
+ from playwright.async_api import TimeoutError as PlaywrightTimeoutError
29
30
 
30
31
  from .errors import InputError, ProfileBusyError, ResponseTimeoutError
31
32
  from .formats import OutputFormat, format_instruction, parse_output
@@ -95,6 +96,7 @@ CANNED_REPLIES = (
95
96
  "i'm having a hard time fulfilling your request",
96
97
  "i seem to be encountering an error",
97
98
  "i encountered an error doing what you asked",
99
+ "something went wrong. please try your request again",
98
100
  )
99
101
 
100
102
 
@@ -180,6 +182,20 @@ _LONGEST_RESPONSE_JS = """(args) => {
180
182
  return { text: best, selector, length: best.length };
181
183
  }"""
182
184
 
185
+ _LIVE_RESPONSES_JS = """(args) => {
186
+ const [selectors, initialCounts] = args;
187
+ const texts = [];
188
+ selectors.forEach(sel => {
189
+ const els = Array.from(document.querySelectorAll(sel));
190
+ const initial = initialCounts[sel] || 0;
191
+ els.slice(initial).forEach(el => {
192
+ const t = el.innerText || el.textContent || '';
193
+ if (t) texts.push(t);
194
+ });
195
+ });
196
+ return texts;
197
+ }"""
198
+
183
199
  _PAGE_ELEMENTS_JS = """() => {
184
200
  return {
185
201
  hasTextarea: document.querySelector('textarea') !== null,
@@ -337,7 +353,7 @@ class Gemx:
337
353
  for attempt in range(1, attempts + 1):
338
354
  try:
339
355
  return await self._ask_raw_once(prompt, expected_format)
340
- except ResponseTimeoutError:
356
+ except (ResponseTimeoutError, PlaywrightTimeoutError):
341
357
  if attempt >= attempts:
342
358
  raise
343
359
  logger.warning(
@@ -421,7 +437,10 @@ class Gemx:
421
437
  logger.debug("navigating to %s", GEMINI_URL)
422
438
  await page.goto(GEMINI_URL, wait_until="load", timeout=cfg.nav_timeout_ms)
423
439
  await page.wait_for_load_state("domcontentloaded")
424
- await page.wait_for_load_state("networkidle", timeout=30_000)
440
+ try:
441
+ await page.wait_for_load_state("networkidle", timeout=30_000)
442
+ except PlaywrightTimeoutError:
443
+ logger.debug("network never went idle; continuing")
425
444
  await page.wait_for_timeout(5_000)
426
445
 
427
446
  await page.wait_for_timeout(cfg.post_load_settle_ms)
@@ -573,14 +592,20 @@ class Gemx:
573
592
  current_length,
574
593
  len(best),
575
594
  )
576
- if (
577
- stable >= cfg.stable_ticks
578
- and expected_format in (OutputFormat.JSON, OutputFormat.XML)
579
- and is_canned_reply(best)
595
+ if stable >= cfg.stable_ticks and expected_format in (
596
+ OutputFormat.JSON,
597
+ OutputFormat.XML,
580
598
  ):
581
- raise ResponseTimeoutError(
582
- f"Gemini returned a canned reply: {best[:200]!r}"
599
+ live = await page.evaluate(
600
+ _LIVE_RESPONSES_JS, [list(RESPONSE_SELECTORS), initial_counts]
601
+ )
602
+ canned = next(
603
+ (t for t in [best, *live] if is_canned_reply(t)), None
583
604
  )
605
+ if canned is not None:
606
+ raise ResponseTimeoutError(
607
+ f"Gemini returned a canned reply: {canned[:200]!r}"
608
+ )
584
609
  if stable >= cfg.stable_ticks and len(best) > cfg.min_response_chars:
585
610
  if expected_format in (OutputFormat.JSON, OutputFormat.XML):
586
611
  try:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes