oagi 0.4.2__tar.gz → 0.4.3__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.

Potentially problematic release.


This version of oagi might be problematic. Click here for more details.

Files changed (57) hide show
  1. {oagi-0.4.2 → oagi-0.4.3}/.github/workflows/release.yml +10 -3
  2. {oagi-0.4.2 → oagi-0.4.3}/PKG-INFO +1 -1
  3. {oagi-0.4.2 → oagi-0.4.3}/pyproject.toml +1 -1
  4. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/pyautogui_action_handler.py +18 -1
  5. {oagi-0.4.2 → oagi-0.4.3}/tests/test_pyautogui_action_handler.py +70 -0
  6. {oagi-0.4.2 → oagi-0.4.3}/uv.lock +1 -1
  7. {oagi-0.4.2 → oagi-0.4.3}/.github/workflows/ci.yml +0 -0
  8. {oagi-0.4.2 → oagi-0.4.3}/.gitignore +0 -0
  9. {oagi-0.4.2 → oagi-0.4.3}/.python-version +0 -0
  10. {oagi-0.4.2 → oagi-0.4.3}/CONTRIBUTING.md +0 -0
  11. {oagi-0.4.2 → oagi-0.4.3}/LICENSE +0 -0
  12. {oagi-0.4.2 → oagi-0.4.3}/Makefile +0 -0
  13. {oagi-0.4.2 → oagi-0.4.3}/README.md +0 -0
  14. {oagi-0.4.2 → oagi-0.4.3}/examples/async_google_weather.py +0 -0
  15. {oagi-0.4.2 → oagi-0.4.3}/examples/execute_task_auto.py +0 -0
  16. {oagi-0.4.2 → oagi-0.4.3}/examples/execute_task_manual.py +0 -0
  17. {oagi-0.4.2 → oagi-0.4.3}/examples/google_weather.py +0 -0
  18. {oagi-0.4.2 → oagi-0.4.3}/examples/hotel_booking.py +0 -0
  19. {oagi-0.4.2 → oagi-0.4.3}/examples/screenshot_with_config.py +0 -0
  20. {oagi-0.4.2 → oagi-0.4.3}/examples/single_step.py +0 -0
  21. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/__init__.py +0 -0
  22. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/async_client.py +0 -0
  23. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/async_pyautogui_action_handler.py +0 -0
  24. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/async_screenshot_maker.py +0 -0
  25. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/async_short_task.py +0 -0
  26. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/async_single_step.py +0 -0
  27. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/async_task.py +0 -0
  28. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/exceptions.py +0 -0
  29. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/logging.py +0 -0
  30. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/pil_image.py +0 -0
  31. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/screenshot_maker.py +0 -0
  32. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/short_task.py +0 -0
  33. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/single_step.py +0 -0
  34. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/sync_client.py +0 -0
  35. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/task.py +0 -0
  36. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/__init__.py +0 -0
  37. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/action_handler.py +0 -0
  38. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/async_action_handler.py +0 -0
  39. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/async_image_provider.py +0 -0
  40. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/image.py +0 -0
  41. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/image_provider.py +0 -0
  42. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/models/__init__.py +0 -0
  43. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/models/action.py +0 -0
  44. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/models/image_config.py +0 -0
  45. {oagi-0.4.2 → oagi-0.4.3}/src/oagi/types/models/step.py +0 -0
  46. {oagi-0.4.2 → oagi-0.4.3}/tests/__init__.py +0 -0
  47. {oagi-0.4.2 → oagi-0.4.3}/tests/conftest.py +0 -0
  48. {oagi-0.4.2 → oagi-0.4.3}/tests/test_async_client.py +0 -0
  49. {oagi-0.4.2 → oagi-0.4.3}/tests/test_async_handlers.py +0 -0
  50. {oagi-0.4.2 → oagi-0.4.3}/tests/test_async_task.py +0 -0
  51. {oagi-0.4.2 → oagi-0.4.3}/tests/test_logging.py +0 -0
  52. {oagi-0.4.2 → oagi-0.4.3}/tests/test_pil_image.py +0 -0
  53. {oagi-0.4.2 → oagi-0.4.3}/tests/test_screenshot_maker.py +0 -0
  54. {oagi-0.4.2 → oagi-0.4.3}/tests/test_short_task.py +0 -0
  55. {oagi-0.4.2 → oagi-0.4.3}/tests/test_single_step.py +0 -0
  56. {oagi-0.4.2 → oagi-0.4.3}/tests/test_sync_client.py +0 -0
  57. {oagi-0.4.2 → oagi-0.4.3}/tests/test_task.py +0 -0
@@ -32,10 +32,17 @@ jobs:
32
32
  password: ${{ secrets.PYPI_API_TOKEN }}
33
33
  # Another option: Use Trusted Publishing (recommended, no token needed)
34
34
  # Configure at: https://pypi.org/manage/project/oagi/settings/publishing/
35
-
35
+
36
+ - name: Get commit message
37
+ id: commit_message
38
+ run: |
39
+ # Get the commit message for the tagged commit
40
+ echo "message<<EOF" >> $GITHUB_OUTPUT
41
+ git log -1 --pretty=%B >> $GITHUB_OUTPUT
42
+ echo "EOF" >> $GITHUB_OUTPUT
36
43
 
37
44
  - name: Create GitHub Release
38
45
  uses: softprops/action-gh-release@v1
39
46
  with:
40
- files: dist/*
41
- generate_release_notes: true
47
+ body: ${{ steps.commit_message.outputs.message }}
48
+ files: dist/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: oagi
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: Official API of OpenAGI Foundation
5
5
  Project-URL: Homepage, https://github.com/agiopen-org/oagi
6
6
  Author-email: OpenAGI Foundation <contact@agiopen.org>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "oagi"
7
- version = "0.4.2"
7
+ version = "0.4.3"
8
8
  description = "Official API of OpenAGI Foundation"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -101,9 +101,26 @@ class PyautoguiActionHandler:
101
101
  self.caps_manager = CapsLockManager(mode=self.config.capslock_mode)
102
102
 
103
103
  def _denormalize_coords(self, x: float, y: float) -> tuple[int, int]:
104
- """Convert coordinates from 0-1000 range to actual screen coordinates."""
104
+ """Convert coordinates from 0-1000 range to actual screen coordinates.
105
+
106
+ Also handles corner coordinates to prevent PyAutoGUI fail-safe trigger.
107
+ Corner coordinates (0,0), (0,max), (max,0), (max,max) are offset by 1 pixel.
108
+ """
105
109
  screen_x = int(x * self.screen_width / 1000)
106
110
  screen_y = int(y * self.screen_height / 1000)
111
+
112
+ # Prevent fail-safe by adjusting corner coordinates
113
+ # Check if coordinates are at screen corners (with small tolerance)
114
+ if screen_x < 1:
115
+ screen_x = 1
116
+ elif screen_x > self.screen_width - 1:
117
+ screen_x = self.screen_width - 1
118
+
119
+ if screen_y < 1:
120
+ screen_y = 1
121
+ elif screen_y > self.screen_height - 1:
122
+ screen_y = self.screen_height - 1
123
+
107
124
  return screen_x, screen_y
108
125
 
109
126
  def _parse_coords(self, args_str: str) -> tuple[int, int]:
@@ -196,6 +196,76 @@ class TestCapsLockManager:
196
196
  assert system_manager.should_use_system_capslock() is True
197
197
 
198
198
 
199
+ class TestCornerCoordinatesHandling:
200
+ """Test that corner coordinates are adjusted to prevent PyAutoGUI fail-safe."""
201
+
202
+ @pytest.mark.parametrize(
203
+ "input_coords,expected_coords",
204
+ [
205
+ # Top-left corner
206
+ ("0, 0", (1, 1)),
207
+ ("1, 1", (1, 1)),
208
+ # Top-right corner (assuming 1920x1080 screen)
209
+ ("1000, 0", (1919, 1)),
210
+ ("999, 1", (1918, 1)),
211
+ # Bottom-left corner
212
+ ("0, 1000", (1, 1079)),
213
+ ("1, 999", (1, 1078)),
214
+ # Bottom-right corner
215
+ ("1000, 1000", (1919, 1079)),
216
+ ("999, 999", (1918, 1078)),
217
+ # Middle coordinates should not be affected
218
+ ("500, 500", (960, 540)),
219
+ ("250, 750", (480, 810)),
220
+ ],
221
+ )
222
+ def test_corner_coordinate_adjustment(
223
+ self, mock_pyautogui, input_coords, expected_coords
224
+ ):
225
+ handler = PyautoguiActionHandler()
226
+ action = Action(type=ActionType.CLICK, argument=input_coords, count=1)
227
+ handler([action])
228
+ mock_pyautogui.click.assert_called_once_with(*expected_coords)
229
+
230
+ def test_drag_with_corner_coordinates(self, mock_pyautogui, config):
231
+ """Test drag operations with corner coordinates."""
232
+ handler = PyautoguiActionHandler()
233
+ # Drag from top-left corner to bottom-right corner
234
+ action = Action(type=ActionType.DRAG, argument="0, 0, 1000, 1000", count=1)
235
+ handler([action])
236
+
237
+ # Should adjust corner coordinates to prevent fail-safe
238
+ mock_pyautogui.moveTo.assert_called_once_with(1, 1)
239
+ mock_pyautogui.dragTo.assert_called_once_with(
240
+ 1919, 1079, duration=config.drag_duration, button="left"
241
+ )
242
+
243
+ def test_scroll_with_corner_coordinates(self, mock_pyautogui, config):
244
+ """Test scroll operations at corner coordinates."""
245
+ handler = PyautoguiActionHandler()
246
+ action = Action(type=ActionType.SCROLL, argument="0, 0, up", count=1)
247
+ handler([action])
248
+
249
+ # Should adjust corner coordinates
250
+ mock_pyautogui.moveTo.assert_called_once_with(1, 1)
251
+ mock_pyautogui.scroll.assert_called_once_with(config.scroll_amount)
252
+
253
+ def test_multiple_clicks_at_corners(self, mock_pyautogui):
254
+ """Test multiple clicks at corner positions."""
255
+ handler = PyautoguiActionHandler()
256
+ actions = [
257
+ Action(type=ActionType.LEFT_DOUBLE, argument="0, 0", count=1),
258
+ Action(type=ActionType.LEFT_TRIPLE, argument="1000, 0", count=1),
259
+ Action(type=ActionType.RIGHT_SINGLE, argument="0, 1000", count=1),
260
+ ]
261
+ handler(actions)
262
+
263
+ # All corner coordinates should be adjusted
264
+ mock_pyautogui.doubleClick.assert_called_once_with(1, 1)
265
+ mock_pyautogui.tripleClick.assert_called_once_with(1919, 1)
266
+ mock_pyautogui.rightClick.assert_called_once_with(1, 1079)
267
+
268
+
199
269
  class TestCapsLockIntegration:
200
270
  def test_caps_lock_key_normalization(self, mock_pyautogui):
201
271
  handler = PyautoguiActionHandler()
@@ -138,7 +138,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/28/fa/b2ba8229b9381e8f6
138
138
 
139
139
  [[package]]
140
140
  name = "oagi"
141
- version = "0.4.2"
141
+ version = "0.4.3"
142
142
  source = { editable = "." }
143
143
  dependencies = [
144
144
  { name = "httpx" },
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
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
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