captchakraken 2.0.0__py3-none-any.whl

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.
@@ -0,0 +1,61 @@
1
+ """
2
+ CaptchaKraken — OpenCV grid detection + a fine-tuned Qwen3.5-9B vision LoRA
3
+ served on vLLM.
4
+
5
+ Usage:
6
+ from captchakraken import CaptchaSolver
7
+ solver = CaptchaSolver() # auto-starts / connects to a local vLLM server
8
+ actions = solver.solve("captcha.png")
9
+
10
+ Model/endpoint defaults live in `captchakraken.config` and are fully
11
+ env-overridable (VLLM_BASE_URL, CAPTCHA_LORA_ADAPTER, …); the solver itself is
12
+ model-agnostic. The legacy v1 stack (SAM3 grounding, multi-provider planner,
13
+ detect/segment/drag-refine) lives on the `v1-old-architecture` branch.
14
+ """
15
+
16
+ from pathlib import Path
17
+
18
+ try: # pragma: no cover
19
+ from dotenv import load_dotenv
20
+
21
+ project_root = Path(__file__).resolve().parent.parent
22
+ load_dotenv(project_root / ".env")
23
+ except Exception:
24
+ pass
25
+
26
+ from .action_types import (
27
+ CaptchaAction,
28
+ ClickAction,
29
+ DragAction,
30
+ TypeAction,
31
+ WaitAction,
32
+ )
33
+ from .image_processor import ImageProcessor
34
+ from .overlay import add_overlays_to_image
35
+
36
+ # The planner (requests) and solver (torch/vllm/transformers) pull in the heavy
37
+ # serving stack. Keep them optional so leaf modules — e.g. tool_calls.find_grid,
38
+ # which needs only cv2 + numpy + pillow — can be imported in a minimal env (CI's
39
+ # hermetic grid-detection test) without the full GPU dependency set installed.
40
+ try: # pragma: no cover - exercised only when the serving stack is installed
41
+ from .planner import ActionPlanner
42
+ from .solver import CaptchaSolver, solve_captcha
43
+ except ModuleNotFoundError:
44
+ ActionPlanner = None # type: ignore[assignment,misc]
45
+ CaptchaSolver = None # type: ignore[assignment,misc]
46
+ solve_captcha = None # type: ignore[assignment]
47
+
48
+ __all__ = [
49
+ "CaptchaSolver",
50
+ "solve_captcha",
51
+ "ActionPlanner",
52
+ "ImageProcessor",
53
+ "CaptchaAction",
54
+ "ClickAction",
55
+ "DragAction",
56
+ "TypeAction",
57
+ "WaitAction",
58
+ "add_overlays_to_image",
59
+ ]
60
+
61
+ __version__ = "2.0.0"
@@ -0,0 +1,56 @@
1
+ from typing import List, Literal, Optional, Union, Tuple
2
+
3
+ from pydantic import BaseModel, RootModel
4
+
5
+
6
+ class BoundingBox(RootModel):
7
+ """
8
+ Strongly typed bounding box: [x1, y1, x2, y2] in percentages (0.0 to 1.0).
9
+ Acts like a list for convenience but ensures exactly 4 float elements.
10
+ """
11
+ root: Tuple[float, float, float, float]
12
+
13
+ def __iter__(self):
14
+ return iter(self.root)
15
+
16
+ def __getitem__(self, item):
17
+ return self.root[item]
18
+
19
+ def __len__(self):
20
+ return len(self.root)
21
+
22
+
23
+ class Action(BaseModel):
24
+ action: str
25
+
26
+
27
+ class ClickAction(Action):
28
+ action: Literal["click"]
29
+ target_bounding_boxes: List[BoundingBox] # List of [x1, y1, x2, y2] in percentages
30
+
31
+
32
+ class DragAction(Action):
33
+ action: Literal["drag"]
34
+ source_bounding_box: BoundingBox = None # [x1, y1, x2, y2] in percentages
35
+ target_bounding_box: BoundingBox = None # [x1, y1, x2, y2] in percentages
36
+
37
+
38
+ class TypeAction(Action):
39
+ """Type text into an input."""
40
+ action: Literal["type"]
41
+ text: str
42
+ target_bounding_box: BoundingBox = None # [x1, y1, x2, y2] in percentages
43
+
44
+
45
+ class WaitAction(Action):
46
+ """Wait for a specified duration."""
47
+ action: Literal["wait"]
48
+ duration_ms: int
49
+
50
+
51
+ class DoneAction(Action):
52
+ """Signal that the captcha is solved or no further actions are needed."""
53
+ action: Literal["done"]
54
+
55
+
56
+ CaptchaAction = Union[ClickAction, DragAction, TypeAction, WaitAction, DoneAction]