cudag 0.3.10__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.
- cudag/__init__.py +334 -0
- cudag/annotation/__init__.py +77 -0
- cudag/annotation/codegen.py +648 -0
- cudag/annotation/config.py +545 -0
- cudag/annotation/loader.py +342 -0
- cudag/annotation/scaffold.py +121 -0
- cudag/annotation/transcription.py +296 -0
- cudag/cli/__init__.py +5 -0
- cudag/cli/main.py +315 -0
- cudag/cli/new.py +873 -0
- cudag/core/__init__.py +364 -0
- cudag/core/button.py +137 -0
- cudag/core/canvas.py +222 -0
- cudag/core/config.py +70 -0
- cudag/core/coords.py +233 -0
- cudag/core/data_grid.py +804 -0
- cudag/core/dataset.py +678 -0
- cudag/core/distribution.py +136 -0
- cudag/core/drawing.py +75 -0
- cudag/core/fonts.py +156 -0
- cudag/core/generator.py +163 -0
- cudag/core/grid.py +367 -0
- cudag/core/grounding_task.py +247 -0
- cudag/core/icon.py +207 -0
- cudag/core/iconlist_task.py +301 -0
- cudag/core/models.py +1251 -0
- cudag/core/random.py +130 -0
- cudag/core/renderer.py +190 -0
- cudag/core/screen.py +402 -0
- cudag/core/scroll_task.py +254 -0
- cudag/core/scrollable_grid.py +447 -0
- cudag/core/state.py +110 -0
- cudag/core/task.py +293 -0
- cudag/core/taskbar.py +350 -0
- cudag/core/text.py +212 -0
- cudag/core/utils.py +82 -0
- cudag/data/surnames.txt +5000 -0
- cudag/modal_apps/__init__.py +4 -0
- cudag/modal_apps/archive.py +103 -0
- cudag/modal_apps/extract.py +138 -0
- cudag/modal_apps/preprocess.py +529 -0
- cudag/modal_apps/upload.py +317 -0
- cudag/prompts/SYSTEM_PROMPT.txt +104 -0
- cudag/prompts/__init__.py +33 -0
- cudag/prompts/system.py +43 -0
- cudag/prompts/tools.py +382 -0
- cudag/py.typed +0 -0
- cudag/schemas/filesystem.json +90 -0
- cudag/schemas/test_record.schema.json +113 -0
- cudag/schemas/train_record.schema.json +90 -0
- cudag/server/__init__.py +21 -0
- cudag/server/app.py +232 -0
- cudag/server/services/__init__.py +9 -0
- cudag/server/services/generator.py +128 -0
- cudag/templates/scripts/archive.sh +35 -0
- cudag/templates/scripts/build.sh +13 -0
- cudag/templates/scripts/extract.sh +54 -0
- cudag/templates/scripts/generate.sh +116 -0
- cudag/templates/scripts/pre-commit.sh +44 -0
- cudag/templates/scripts/preprocess.sh +46 -0
- cudag/templates/scripts/upload.sh +63 -0
- cudag/templates/scripts/verify.py +428 -0
- cudag/validation/__init__.py +35 -0
- cudag/validation/validate.py +508 -0
- cudag-0.3.10.dist-info/METADATA +570 -0
- cudag-0.3.10.dist-info/RECORD +69 -0
- cudag-0.3.10.dist-info/WHEEL +4 -0
- cudag-0.3.10.dist-info/entry_points.txt +2 -0
- cudag-0.3.10.dist-info/licenses/LICENSE +66 -0
cudag/core/config.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Copyright (c) 2025 Tylt LLC. All rights reserved.
|
|
2
|
+
# CONFIDENTIAL AND PROPRIETARY. Unauthorized use, copying, or distribution
|
|
3
|
+
# is strictly prohibited. For licensing inquiries: hello@claimhawk.app
|
|
4
|
+
|
|
5
|
+
"""Configuration loading utilities for CUDAG framework."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
import yaml
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_yaml_config(
|
|
16
|
+
config_path: Path | str | None = None,
|
|
17
|
+
default_filename: str = "canvas.yaml",
|
|
18
|
+
config_dir: str = "config",
|
|
19
|
+
) -> dict[str, Any]:
|
|
20
|
+
"""Load YAML configuration file.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
config_path: Explicit path to config file. If None, uses default location.
|
|
24
|
+
default_filename: Default config filename if path not specified.
|
|
25
|
+
config_dir: Directory name for config files (relative to caller).
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Parsed YAML configuration as dictionary.
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
>>> # Load from default location (config/canvas.yaml)
|
|
32
|
+
>>> config = load_yaml_config()
|
|
33
|
+
>>> # Load from explicit path
|
|
34
|
+
>>> config = load_yaml_config("my_config.yaml")
|
|
35
|
+
>>> # Load with custom default
|
|
36
|
+
>>> config = load_yaml_config(default_filename="screen.yaml")
|
|
37
|
+
"""
|
|
38
|
+
if config_path is not None:
|
|
39
|
+
path = Path(config_path)
|
|
40
|
+
else:
|
|
41
|
+
# Get caller's directory by walking up from this file
|
|
42
|
+
# Note: Caller should pass explicit path or use get_config_path()
|
|
43
|
+
path = Path(config_dir) / default_filename
|
|
44
|
+
|
|
45
|
+
with open(path) as f:
|
|
46
|
+
result: dict[str, Any] = yaml.safe_load(f)
|
|
47
|
+
return result
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_config_path(
|
|
51
|
+
caller_file: str,
|
|
52
|
+
filename: str = "canvas.yaml",
|
|
53
|
+
config_dir: str = "config",
|
|
54
|
+
) -> Path:
|
|
55
|
+
"""Get path to config file relative to caller's location.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
caller_file: The __file__ of the calling module.
|
|
59
|
+
filename: Config filename.
|
|
60
|
+
config_dir: Directory name for config files.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Absolute path to config file.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> # In screen.py
|
|
67
|
+
>>> config_path = get_config_path(__file__, "canvas.yaml")
|
|
68
|
+
>>> config = load_yaml_config(config_path)
|
|
69
|
+
"""
|
|
70
|
+
return Path(caller_file).parent / config_dir / filename
|
cudag/core/coords.py
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Copyright (c) 2025 Tylt LLC. All rights reserved.
|
|
2
|
+
# CONFIDENTIAL AND PROPRIETARY. Unauthorized use, copying, or distribution
|
|
3
|
+
# is strictly prohibited. For licensing inquiries: hello@claimhawk.app
|
|
4
|
+
|
|
5
|
+
"""Coordinate system utilities for RU (Resolution Units) normalization.
|
|
6
|
+
|
|
7
|
+
All coordinates in CUDAG use RU normalized with independent axis scaling.
|
|
8
|
+
Both X and Y axes map independently to [0, 1000], matching Qwen3-VL's
|
|
9
|
+
coordinate system.
|
|
10
|
+
|
|
11
|
+
For a 1920x1080 image:
|
|
12
|
+
- X range: [0, 1000] (pixel_x / 1920 * 1000)
|
|
13
|
+
- Y range: [0, 1000] (pixel_y / 1080 * 1000)
|
|
14
|
+
|
|
15
|
+
Conversion formulas (independent scaling per axis):
|
|
16
|
+
normalized_x = pixel_x / width * 1000
|
|
17
|
+
normalized_y = pixel_y / height * 1000
|
|
18
|
+
|
|
19
|
+
To convert back to pixels:
|
|
20
|
+
pixel_x = normalized_x / 1000 * width
|
|
21
|
+
pixel_y = normalized_y / 1000 * height
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import math
|
|
27
|
+
|
|
28
|
+
# Resolution Units max value for the larger dimension
|
|
29
|
+
RU_MAX = 1000
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def normalize_coord(
|
|
33
|
+
pixel: tuple[int, int],
|
|
34
|
+
image_size: tuple[int, int],
|
|
35
|
+
) -> tuple[int, int]:
|
|
36
|
+
"""Convert pixel coordinates to RU (Resolution Units) with independent scaling.
|
|
37
|
+
|
|
38
|
+
Both X and Y axes map independently to [0, 1000], matching Qwen3-VL's
|
|
39
|
+
coordinate system where coordinates are normalized to a 1000x1000 grid
|
|
40
|
+
regardless of the original image dimensions.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
pixel: (x, y) pixel coordinates
|
|
44
|
+
image_size: (width, height) of the image
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
(x, y) normalized coordinates in [0, 1000] range for both axes
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
For 1920x1080 image, point (960, 540):
|
|
51
|
+
- x_norm = 960 / 1920 * 1000 = 500
|
|
52
|
+
- y_norm = 540 / 1080 * 1000 = 500
|
|
53
|
+
"""
|
|
54
|
+
width, height = image_size
|
|
55
|
+
if width <= 0 or height <= 0:
|
|
56
|
+
raise ValueError(f"Invalid image size: {image_size}")
|
|
57
|
+
|
|
58
|
+
# Independent scaling per axis (Qwen3-VL format)
|
|
59
|
+
x_norm = int(round(pixel[0] / width * RU_MAX))
|
|
60
|
+
y_norm = int(round(pixel[1] / height * RU_MAX))
|
|
61
|
+
return (x_norm, y_norm)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def pixel_from_normalized(
|
|
65
|
+
normalized: tuple[int, int],
|
|
66
|
+
image_size: tuple[int, int],
|
|
67
|
+
) -> tuple[int, int]:
|
|
68
|
+
"""Convert RU (Resolution Units) coordinates back to pixels.
|
|
69
|
+
|
|
70
|
+
Reverses the independent axis scaling used in normalize_coord().
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
normalized: (x, y) coordinates in RU [0, 1000]
|
|
74
|
+
image_size: (width, height) of the image
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
(x, y) pixel coordinates
|
|
78
|
+
|
|
79
|
+
Example:
|
|
80
|
+
For 1920x1080 image, RU point (500, 500):
|
|
81
|
+
- x_pixel = 500 / 1000 * 1920 = 960
|
|
82
|
+
- y_pixel = 500 / 1000 * 1080 = 540
|
|
83
|
+
"""
|
|
84
|
+
width, height = image_size
|
|
85
|
+
if width <= 0 or height <= 0:
|
|
86
|
+
raise ValueError(f"Invalid image size: {image_size}")
|
|
87
|
+
|
|
88
|
+
# Reverse independent scaling per axis
|
|
89
|
+
x_pixel = int(round(normalized[0] / RU_MAX * width))
|
|
90
|
+
y_pixel = int(round(normalized[1] / RU_MAX * height))
|
|
91
|
+
return (x_pixel, y_pixel)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def get_normalized_bounds(image_size: tuple[int, int]) -> tuple[int, int]:
|
|
95
|
+
"""Get the maximum normalized coordinates for an image.
|
|
96
|
+
|
|
97
|
+
With independent axis scaling, both axes always map to [0, 1000].
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
image_size: (width, height) of the image
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
(max_x, max_y) in RU coordinates - always (1000, 1000)
|
|
104
|
+
|
|
105
|
+
Example:
|
|
106
|
+
For 1920x1080: returns (1000, 1000)
|
|
107
|
+
For 1080x1920: returns (1000, 1000)
|
|
108
|
+
"""
|
|
109
|
+
width, height = image_size
|
|
110
|
+
if width <= 0 or height <= 0:
|
|
111
|
+
raise ValueError(f"Invalid image size: {image_size}")
|
|
112
|
+
|
|
113
|
+
# Both axes always map to 1000 with independent scaling
|
|
114
|
+
return (RU_MAX, RU_MAX)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def clamp_coord(coord: tuple[int, int], max_val: int = RU_MAX) -> tuple[int, int]:
|
|
118
|
+
"""Clamp coordinates to valid range [0, max_val].
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
coord: (x, y) coordinates
|
|
122
|
+
max_val: Maximum value (default: 1000)
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Clamped (x, y) coordinates
|
|
126
|
+
"""
|
|
127
|
+
x = max(0, min(coord[0], max_val))
|
|
128
|
+
y = max(0, min(coord[1], max_val))
|
|
129
|
+
return (x, y)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def coord_distance(a: tuple[int, int], b: tuple[int, int]) -> float:
|
|
133
|
+
"""Calculate Euclidean distance between two coordinates.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
a: First (x, y) coordinate
|
|
137
|
+
b: Second (x, y) coordinate
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Euclidean distance
|
|
141
|
+
"""
|
|
142
|
+
return math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def coord_within_tolerance(
|
|
146
|
+
actual: tuple[int, int],
|
|
147
|
+
expected: tuple[int, int],
|
|
148
|
+
tolerance: int,
|
|
149
|
+
) -> bool:
|
|
150
|
+
"""Check if actual coordinate is within tolerance of expected.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
actual: Actual (x, y) coordinate
|
|
154
|
+
expected: Expected (x, y) coordinate
|
|
155
|
+
tolerance: Maximum allowed distance
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
True if within tolerance
|
|
159
|
+
"""
|
|
160
|
+
return coord_distance(actual, expected) <= tolerance
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def tolerance_to_ru(
|
|
164
|
+
tolerance_pixels: tuple[int, int],
|
|
165
|
+
image_size: tuple[int, int],
|
|
166
|
+
) -> tuple[int, int]:
|
|
167
|
+
"""Convert pixel tolerance to normalized RU units.
|
|
168
|
+
|
|
169
|
+
Uses independent axis scaling to match normalize_coord().
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
tolerance_pixels: (width, height) tolerance in pixels
|
|
173
|
+
image_size: (width, height) of the image
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
Tolerance in RU units [0, 1000]
|
|
177
|
+
|
|
178
|
+
Example:
|
|
179
|
+
>>> tolerance_to_ru((50, 30), (1920, 1080))
|
|
180
|
+
(26, 28)
|
|
181
|
+
"""
|
|
182
|
+
width, height = image_size
|
|
183
|
+
return (
|
|
184
|
+
int(round(tolerance_pixels[0] / width * RU_MAX)),
|
|
185
|
+
int(round(tolerance_pixels[1] / height * RU_MAX)),
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def bounds_to_tolerance(
|
|
190
|
+
bounds: tuple[int, int, int, int],
|
|
191
|
+
scale: float = 0.5,
|
|
192
|
+
) -> tuple[int, int]:
|
|
193
|
+
"""Calculate tolerance from bounding box dimensions.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
bounds: (x, y, width, height) bounding box
|
|
197
|
+
scale: Fraction of dimensions to use (default 0.5 = half size)
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
(tolerance_x, tolerance_y) in pixels
|
|
201
|
+
|
|
202
|
+
Example:
|
|
203
|
+
>>> bounds_to_tolerance((0, 0, 100, 50), scale=0.5)
|
|
204
|
+
(50, 25)
|
|
205
|
+
"""
|
|
206
|
+
_, _, width, height = bounds
|
|
207
|
+
return (int(width * scale), int(height * scale))
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def calculate_tolerance_ru(
|
|
211
|
+
element_size: tuple[int, int],
|
|
212
|
+
image_size: tuple[int, int],
|
|
213
|
+
scale: float = 0.7,
|
|
214
|
+
) -> tuple[int, int]:
|
|
215
|
+
"""Calculate normalized tolerance for an element.
|
|
216
|
+
|
|
217
|
+
This is a convenience function combining bounds_to_tolerance and tolerance_to_ru.
|
|
218
|
+
The default scale of 0.7 means clicks within 70% of the element size are accepted.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
element_size: (width, height) of the clickable element in pixels
|
|
222
|
+
image_size: (width, height) of the full image in pixels
|
|
223
|
+
scale: Fraction of element size to use as tolerance (default 0.7 = 70%)
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Tolerance in RU units [0, 1000]
|
|
227
|
+
|
|
228
|
+
Example:
|
|
229
|
+
>>> calculate_tolerance_ru((100, 50), (1920, 1080), scale=0.7)
|
|
230
|
+
(36, 32)
|
|
231
|
+
"""
|
|
232
|
+
pixel_tol = (int(element_size[0] * scale), int(element_size[1] * scale))
|
|
233
|
+
return tolerance_to_ru(pixel_tol, image_size)
|