majorchik-api 0.0.3__tar.gz → 0.0.3.2__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.
Files changed (19) hide show
  1. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/PKG-INFO +1 -1
  2. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/pyproject.toml +1 -1
  3. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/browser_ai/deepseek_api.py +6 -8
  4. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/browser_ai/google_ai_studio_api.py +53 -11
  5. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/majorchik_api.egg-info/PKG-INFO +1 -1
  6. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/tests/test_upload.py +20 -2
  7. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/README.md +0 -0
  8. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/setup.cfg +0 -0
  9. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/browser_ai/__init__.py +0 -0
  10. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/browser_ai/base_api.py +0 -0
  11. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/browser_ai/cli.py +0 -0
  12. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/browser_ai/exceptions.py +0 -0
  13. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/browser_ai/factory.py +0 -0
  14. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/majorchik_api.egg-info/SOURCES.txt +0 -0
  15. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/majorchik_api.egg-info/dependency_links.txt +0 -0
  16. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/majorchik_api.egg-info/entry_points.txt +0 -0
  17. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/majorchik_api.egg-info/requires.txt +0 -0
  18. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/src/majorchik_api.egg-info/top_level.txt +0 -0
  19. {majorchik_api-0.0.3 → majorchik_api-0.0.3.2}/tests/test_setup_profile.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: majorchik-api
3
- Version: 0.0.3
3
+ Version: 0.0.3.2
4
4
  Summary: Пакет для взаимодействия с современными нейросетями (Gemini, DeepSeek) через автоматизацию браузера
5
5
  Author-email: GO Software <gosoftware2025@gmail.com>
6
6
  Requires-Python: >=3.8
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "majorchik-api"
7
- version = "0.0.3"
7
+ version = "0.0.3.2"
8
8
  authors = [
9
9
  {name = "GO Software", email = "gosoftware2025@gmail.com"},
10
10
  ]
@@ -134,14 +134,12 @@ class DeepSeekAPI(BaseWebAPI):
134
134
  chat_input.click(delay=30)
135
135
  time.sleep(0.3)
136
136
 
137
- if len(prompt) > 200:
138
- self.page.evaluate("text => navigator.clipboard.writeText(text)", prompt)
139
- modifier = "Meta" if sys.platform == "darwin" else "Control"
140
- chat_input.press(f"{modifier}+v", delay=50)
141
- time.sleep(0.2)
142
- chat_input.press_sequentially(" ", delay=30)
143
- else:
144
- chat_input.press_sequentially(prompt, delay=15)
137
+ self.page.evaluate("text => navigator.clipboard.writeText(text)", prompt)
138
+ modifier = "Meta" if sys.platform == "darwin" else "Control"
139
+ chat_input.press(f"{modifier}+v", delay=50)
140
+ wait_time = max(0.2, min(3.0, len(prompt) / 20000.0))
141
+ time.sleep(wait_time)
142
+ chat_input.press("Space", delay=30)
145
143
 
146
144
  time.sleep(0.5)
147
145
  chat_input.press("Enter", delay=40)
@@ -113,11 +113,18 @@ class GoogleAIStudioAPI(BaseWebAPI):
113
113
 
114
114
  self.page.wait_for_timeout(300)
115
115
 
116
- # Вставка из буфера, как ты делал вручную (это безопаснее, чем эмуляция сотен нажатий без ошибок)
116
+ # Вставка из буфера
117
117
  self.page.evaluate("text => navigator.clipboard.writeText(text)", prompt)
118
118
  modifier = "Meta" if sys.platform == "darwin" else "Control"
119
119
  chat_input.press(f"{modifier}+v", delay=random.randint(40, 90))
120
120
 
121
+ # Динамическая задержка: чем больше текст, тем дольше ждём (чтобы UI отвис)
122
+ wait_time = max(500, min(3000, len(prompt) // 20))
123
+ self.page.wait_for_timeout(wait_time)
124
+
125
+ # Нажимаем пробел, чтобы точно триггернуть событие ввода во фреймворке (Angular/React)
126
+ chat_input.press("Space", delay=random.randint(30, 60))
127
+
121
128
  self.page.wait_for_timeout(random.randint(300, 600))
122
129
 
123
130
  # Делаем случайное движение перед нажатием кнопки отправки
@@ -244,23 +251,58 @@ class GoogleAIStudioAPI(BaseWebAPI):
244
251
  # Попытка 1: найти кнопку меню и скопировать как Markdown
245
252
  copy_success = False
246
253
  try:
247
- options_btn = last_turn.locator('button[aria-label="Open options"], button:has(.material-symbols-outlined:has-text("more_vert"))').last
248
- if options_btn.count() > 0 and options_btn.is_visible():
249
- options_btn.evaluate("el => el.click()")
254
+ self.page.evaluate("navigator.clipboard.writeText('').catch(() => {})")
255
+
256
+ # Принудительно делаем видимыми все скрытые кнопки меню (снимаем opacity: 0)
257
+ self.page.evaluate("""() => {
258
+ document.querySelectorAll('.hover-or-edit').forEach(el => {
259
+ el.style.opacity = '1';
260
+ el.style.pointerEvents = 'auto';
261
+ });
262
+ }""")
263
+ self.page.wait_for_timeout(200)
264
+
265
+ # Ищем последнюю кнопку "more_vert" глобально на странице,
266
+ # так как last_turn мог захватить внутренний div без кнопок
267
+ options_btn = self.page.locator('button[aria-label="Open options"], button:has(span:has-text("more_vert"))').last
268
+
269
+ if options_btn.count() > 0:
270
+ options_btn.scroll_into_view_if_needed()
271
+ try:
272
+ options_btn.click(delay=50, timeout=2000)
273
+ except:
274
+ options_btn.evaluate("el => el.click()")
275
+
276
+ # Ждем появления меню в DOM
277
+ try:
278
+ self.page.wait_for_selector('button[role="menuitem"]', timeout=3000)
279
+ except:
280
+ pass
250
281
  self.page.wait_for_timeout(500)
251
282
 
252
- copy_btn = self.page.locator('button[role="menuitem"]:has-text("Copy as markdown"), button[role="menuitem"]:has-text("Copy")').first
253
- if copy_btn.count() > 0 and copy_btn.is_visible():
254
- copy_btn.evaluate("el => el.click()")
283
+ # Ищем кнопку копирования Markdown по уникальной системной иконке (не зависит от языка)
284
+ copy_btn = self.page.locator('button[role="menuitem"]:has(span:has-text("markdown_copy"))').first
285
+ if copy_btn.count() == 0:
286
+ # Резервный поиск по тексту
287
+ copy_btn = self.page.locator('button[role="menuitem"]:has-text("Copy as markdown")').first
288
+
289
+ if copy_btn.count() > 0:
290
+ try:
291
+ copy_btn.click(delay=50, timeout=2000)
292
+ except:
293
+ copy_btn.evaluate("el => el.click()")
294
+
255
295
  self.page.wait_for_timeout(1000)
256
296
  copy_success = True
257
- except:
258
- pass
297
+ except Exception as e:
298
+ print(f"Ошибка при попытке скопировать через меню: {e}")
259
299
 
260
300
  if copy_success:
261
301
  clip_val = self.page.evaluate("navigator.clipboard.readText().catch(() => '')")
262
- if clip_val or extracted_images:
263
- return clip_val + image_append_text
302
+ if clip_val and clip_val.strip() != "":
303
+ if extracted_images:
304
+ return clip_val + image_append_text
305
+ return clip_val
264
306
 
265
307
  # Попытка 2: Читаем текст прямо из DOM
266
308
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: majorchik-api
3
- Version: 0.0.3
3
+ Version: 0.0.3.2
4
4
  Summary: Пакет для взаимодействия с современными нейросетями (Gemini, DeepSeek) через автоматизацию браузера
5
5
  Author-email: GO Software <gosoftware2025@gmail.com>
6
6
  Requires-Python: >=3.8
@@ -9,7 +9,25 @@ from browser_ai import get_ai_client, AuthRequiredError, SUPPORTED_MODELS
9
9
  def create_dummy_file():
10
10
  filename = "test_dummy_file.txt"
11
11
  with open(filename, "w", encoding="utf-8") as f:
12
- f.write("Привет! Это тестовый файл. Если ты можешь это прочитать, значит прикрепление файлов работает успешно!")
12
+ f.write("""Белая берёза
13
+ Под моим окном
14
+ Принакрылась снегом,
15
+ Точно серебром.
16
+
17
+ На пушистых ветках
18
+ Снежною каймой
19
+ Распустились кисти
20
+ Белой бахромой.
21
+
22
+ И стоит берёза
23
+ В сонной тишине,
24
+ И горят снежинки
25
+ В золотом огне.
26
+
27
+ А заря, лениво
28
+ Обходя кругом,
29
+ Обсыпает ветки
30
+ Новым серебром.""")
13
31
  return filename
14
32
 
15
33
  def main():
@@ -41,7 +59,7 @@ def main():
41
59
 
42
60
  print("Отправляем файл и промпт...")
43
61
  abs_path = os.path.abspath(dummy_file)
44
- response = ai.ask("Прочитай прикрепленный файл и скажи, что в нем написано.", files=[abs_path])
62
+ response = ai.ask("Что в файле", files=[abs_path])
45
63
 
46
64
  print("\n[Ответ модели]:")
47
65
  print(response)
File without changes
File without changes