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.
- {gemx-0.2.2 → gemx-0.2.4}/PKG-INFO +1 -1
- {gemx-0.2.2 → gemx-0.2.4}/pyproject.toml +1 -1
- {gemx-0.2.2 → gemx-0.2.4}/src/gemx/__init__.py +1 -1
- {gemx-0.2.2 → gemx-0.2.4}/src/gemx/client.py +33 -8
- {gemx-0.2.2 → gemx-0.2.4}/.gitignore +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/LICENSE +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/README.md +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/src/gemx/cli.py +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/src/gemx/errors.py +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/src/gemx/formats.py +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/src/gemx/py.typed +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/tests/__init__.py +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/tests/scripts/TEST_GEMINI.md +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/tests/scripts/gemini_console.js +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/tests/scripts/gemini_console_prompt.js +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/tests/test_cli.py +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/tests/test_client.py +0 -0
- {gemx-0.2.2 → gemx-0.2.4}/tests/test_formats.py +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
578
|
-
|
|
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
|
-
|
|
582
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|