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.
Files changed (69) hide show
  1. cudag/__init__.py +334 -0
  2. cudag/annotation/__init__.py +77 -0
  3. cudag/annotation/codegen.py +648 -0
  4. cudag/annotation/config.py +545 -0
  5. cudag/annotation/loader.py +342 -0
  6. cudag/annotation/scaffold.py +121 -0
  7. cudag/annotation/transcription.py +296 -0
  8. cudag/cli/__init__.py +5 -0
  9. cudag/cli/main.py +315 -0
  10. cudag/cli/new.py +873 -0
  11. cudag/core/__init__.py +364 -0
  12. cudag/core/button.py +137 -0
  13. cudag/core/canvas.py +222 -0
  14. cudag/core/config.py +70 -0
  15. cudag/core/coords.py +233 -0
  16. cudag/core/data_grid.py +804 -0
  17. cudag/core/dataset.py +678 -0
  18. cudag/core/distribution.py +136 -0
  19. cudag/core/drawing.py +75 -0
  20. cudag/core/fonts.py +156 -0
  21. cudag/core/generator.py +163 -0
  22. cudag/core/grid.py +367 -0
  23. cudag/core/grounding_task.py +247 -0
  24. cudag/core/icon.py +207 -0
  25. cudag/core/iconlist_task.py +301 -0
  26. cudag/core/models.py +1251 -0
  27. cudag/core/random.py +130 -0
  28. cudag/core/renderer.py +190 -0
  29. cudag/core/screen.py +402 -0
  30. cudag/core/scroll_task.py +254 -0
  31. cudag/core/scrollable_grid.py +447 -0
  32. cudag/core/state.py +110 -0
  33. cudag/core/task.py +293 -0
  34. cudag/core/taskbar.py +350 -0
  35. cudag/core/text.py +212 -0
  36. cudag/core/utils.py +82 -0
  37. cudag/data/surnames.txt +5000 -0
  38. cudag/modal_apps/__init__.py +4 -0
  39. cudag/modal_apps/archive.py +103 -0
  40. cudag/modal_apps/extract.py +138 -0
  41. cudag/modal_apps/preprocess.py +529 -0
  42. cudag/modal_apps/upload.py +317 -0
  43. cudag/prompts/SYSTEM_PROMPT.txt +104 -0
  44. cudag/prompts/__init__.py +33 -0
  45. cudag/prompts/system.py +43 -0
  46. cudag/prompts/tools.py +382 -0
  47. cudag/py.typed +0 -0
  48. cudag/schemas/filesystem.json +90 -0
  49. cudag/schemas/test_record.schema.json +113 -0
  50. cudag/schemas/train_record.schema.json +90 -0
  51. cudag/server/__init__.py +21 -0
  52. cudag/server/app.py +232 -0
  53. cudag/server/services/__init__.py +9 -0
  54. cudag/server/services/generator.py +128 -0
  55. cudag/templates/scripts/archive.sh +35 -0
  56. cudag/templates/scripts/build.sh +13 -0
  57. cudag/templates/scripts/extract.sh +54 -0
  58. cudag/templates/scripts/generate.sh +116 -0
  59. cudag/templates/scripts/pre-commit.sh +44 -0
  60. cudag/templates/scripts/preprocess.sh +46 -0
  61. cudag/templates/scripts/upload.sh +63 -0
  62. cudag/templates/scripts/verify.py +428 -0
  63. cudag/validation/__init__.py +35 -0
  64. cudag/validation/validate.py +508 -0
  65. cudag-0.3.10.dist-info/METADATA +570 -0
  66. cudag-0.3.10.dist-info/RECORD +69 -0
  67. cudag-0.3.10.dist-info/WHEEL +4 -0
  68. cudag-0.3.10.dist-info/entry_points.txt +2 -0
  69. 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)