oagi 0.4.0__py3-none-any.whl → 0.4.2__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.

Potentially problematic release.


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

oagi/async_short_task.py CHANGED
@@ -41,14 +41,14 @@ class AsyncShortTask(AsyncTask):
41
41
  logger.debug(f"Async auto mode step {i + 1}/{max_steps}")
42
42
  image = await image_provider()
43
43
  step = await self.step(image)
44
+ if executor:
45
+ logger.debug(f"Executing {len(step.actions)} actions asynchronously")
46
+ await executor(step.actions)
44
47
  if step.stop:
45
48
  logger.info(
46
49
  f"Async auto mode completed successfully after {i + 1} steps"
47
50
  )
48
51
  return True
49
- if executor:
50
- logger.debug(f"Executing {len(step.actions)} actions asynchronously")
51
- await executor(step.actions)
52
52
 
53
53
  logger.warning(
54
54
  f"Async auto mode reached max steps ({max_steps}) without completion"
@@ -15,6 +15,42 @@ from pydantic import BaseModel, Field
15
15
  from .types import Action, ActionType
16
16
 
17
17
 
18
+ class CapsLockManager:
19
+ """Manages caps lock state for text transformation."""
20
+
21
+ def __init__(self, mode: str = "session"):
22
+ """Initialize caps lock manager.
23
+
24
+ Args:
25
+ mode: Either "session" (internal state) or "system" (OS-level)
26
+ """
27
+ self.mode = mode
28
+ self.caps_enabled = False
29
+
30
+ def toggle(self):
31
+ """Toggle caps lock state in session mode."""
32
+ if self.mode == "session":
33
+ self.caps_enabled = not self.caps_enabled
34
+
35
+ def transform_text(self, text: str) -> str:
36
+ """Transform text based on caps lock state.
37
+
38
+ Args:
39
+ text: Input text to transform
40
+
41
+ Returns:
42
+ Transformed text (uppercase if caps enabled in session mode)
43
+ """
44
+ if self.mode == "session" and self.caps_enabled:
45
+ # Transform letters to uppercase, preserve special characters
46
+ return "".join(c.upper() if c.isalpha() else c for c in text)
47
+ return text
48
+
49
+ def should_use_system_capslock(self) -> bool:
50
+ """Check if system-level caps lock should be used."""
51
+ return self.mode == "system"
52
+
53
+
18
54
  class PyautoguiConfig(BaseModel):
19
55
  """Configuration for PyautoguiActionHandler."""
20
56
 
@@ -30,6 +66,13 @@ class PyautoguiConfig(BaseModel):
30
66
  action_pause: float = Field(
31
67
  default=0.1, description="Pause between PyAutoGUI actions in seconds"
32
68
  )
69
+ hotkey_interval: float = Field(
70
+ default=0.1, description="Interval between key presses in hotkey combinations"
71
+ )
72
+ capslock_mode: str = Field(
73
+ default="session",
74
+ description="Caps lock handling mode: 'session' (internal state) or 'system' (OS-level)",
75
+ )
33
76
 
34
77
 
35
78
  class PyautoguiActionHandler:
@@ -54,6 +97,8 @@ class PyautoguiActionHandler:
54
97
  self.screen_width, self.screen_height = pyautogui.size()
55
98
  # Set default delay between actions
56
99
  pyautogui.PAUSE = self.config.action_pause
100
+ # Initialize caps lock manager
101
+ self.caps_manager = CapsLockManager(mode=self.config.capslock_mode)
57
102
 
58
103
  def _denormalize_coords(self, x: float, y: float) -> tuple[int, int]:
59
104
  """Convert coordinates from 0-1000 range to actual screen coordinates."""
@@ -94,12 +139,20 @@ class PyautoguiActionHandler:
94
139
  direction = match.group(3).lower()
95
140
  return x, y, direction
96
141
 
142
+ def _normalize_key(self, key: str) -> str:
143
+ """Normalize key names for consistency."""
144
+ key = key.strip().lower()
145
+ # Normalize caps lock variations
146
+ if key in ["caps_lock", "caps", "capslock"]:
147
+ return "capslock"
148
+ return key
149
+
97
150
  def _parse_hotkey(self, args_str: str) -> list[str]:
98
151
  """Parse hotkey string into list of keys."""
99
152
  # Remove parentheses if present
100
153
  args_str = args_str.strip("()")
101
154
  # Split by '+' to get individual keys
102
- keys = [key.strip() for key in args_str.split("+")]
155
+ keys = [self._normalize_key(key) for key in args_str.split("+")]
103
156
  return keys
104
157
 
105
158
  def _execute_single_action(self, action: Action) -> None:
@@ -115,6 +168,10 @@ class PyautoguiActionHandler:
115
168
  x, y = self._parse_coords(arg)
116
169
  pyautogui.doubleClick(x, y)
117
170
 
171
+ case ActionType.LEFT_TRIPLE:
172
+ x, y = self._parse_coords(arg)
173
+ pyautogui.tripleClick(x, y)
174
+
118
175
  case ActionType.RIGHT_SINGLE:
119
176
  x, y = self._parse_coords(arg)
120
177
  pyautogui.rightClick(x, y)
@@ -128,11 +185,25 @@ class PyautoguiActionHandler:
128
185
 
129
186
  case ActionType.HOTKEY:
130
187
  keys = self._parse_hotkey(arg)
131
- pyautogui.hotkey(*keys)
188
+ # Check if this is a caps lock key press
189
+ if len(keys) == 1 and keys[0] == "capslock":
190
+ if self.caps_manager.should_use_system_capslock():
191
+ # System mode: use OS-level caps lock
192
+ pyautogui.hotkey(
193
+ "capslock", interval=self.config.hotkey_interval
194
+ )
195
+ else:
196
+ # Session mode: toggle internal state
197
+ self.caps_manager.toggle()
198
+ else:
199
+ # Regular hotkey combination
200
+ pyautogui.hotkey(*keys, interval=self.config.hotkey_interval)
132
201
 
133
202
  case ActionType.TYPE:
134
203
  # Remove quotes if present
135
204
  text = arg.strip("\"'")
205
+ # Apply caps lock transformation if needed
206
+ text = self.caps_manager.transform_text(text)
136
207
  pyautogui.typewrite(text)
137
208
 
138
209
  case ActionType.SCROLL:
oagi/short_task.py CHANGED
@@ -41,12 +41,12 @@ class ShortTask(Task):
41
41
  logger.debug(f"Auto mode step {i + 1}/{max_steps}")
42
42
  image = image_provider()
43
43
  step = self.step(image)
44
- if step.stop:
45
- logger.info(f"Auto mode completed successfully after {i + 1} steps")
46
- return True
47
44
  if executor:
48
45
  logger.debug(f"Executing {len(step.actions)} actions")
49
46
  executor(step.actions)
47
+ if step.stop:
48
+ logger.info(f"Auto mode completed successfully after {i + 1} steps")
49
+ return True
50
50
 
51
51
  logger.warning(f"Auto mode reached max steps ({max_steps}) without completion")
52
52
  return False
@@ -14,6 +14,7 @@ from pydantic import BaseModel, Field
14
14
  class ActionType(str, Enum):
15
15
  CLICK = "click"
16
16
  LEFT_DOUBLE = "left_double"
17
+ LEFT_TRIPLE = "left_triple"
17
18
  RIGHT_SINGLE = "right_single"
18
19
  DRAG = "drag"
19
20
  HOTKEY = "hotkey"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: oagi
3
- Version: 0.4.0
3
+ Version: 0.4.2
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>
@@ -93,6 +93,8 @@ config = PyautoguiConfig(
93
93
  scroll_amount=50, # Larger scroll steps (default: 30)
94
94
  wait_duration=2.0, # Longer waits (default: 1.0)
95
95
  action_pause=0.2, # More pause between actions (default: 0.1)
96
+ hotkey_interval=0.1, # Interval between keys in hotkey combinations (default: 0.1)
97
+ capslock_mode="session" # Caps lock mode: 'session' or 'system' (default: 'session')
96
98
  )
97
99
 
98
100
  executor = PyautoguiActionHandler(config=config)
@@ -2,15 +2,15 @@ oagi/__init__.py,sha256=m-Z121YCIwQOPXpTC8kd_UIJizcX8QuHyrSSguQ0KE0,2187
2
2
  oagi/async_client.py,sha256=oDj4kIdtaV37uopoAeClCFQTxrYRwHV2HwMAcMdVYwE,8455
3
3
  oagi/async_pyautogui_action_handler.py,sha256=F-lKyePCONWI03WnSxpX_QwxONbvnfdQu51wTod6mdw,1614
4
4
  oagi/async_screenshot_maker.py,sha256=pI-dbLcYOzcO1ffgTmozAdbYJQNBPKA7hmqj1RxEmIY,1688
5
- oagi/async_short_task.py,sha256=Pn3ggSWfPaxBPuMLox-WnIeD0JdmupxMojXybA8SbtE,1961
5
+ oagi/async_short_task.py,sha256=jvFTbmXTxFlkpAwmWeZlxbTSv_RB7V561hxw6gUcigw,1961
6
6
  oagi/async_single_step.py,sha256=QawXO4GyfMz6O9jV8QBC1vKxFuS9vjKQxxJ1nwgHBzI,2838
7
7
  oagi/async_task.py,sha256=bclqtgg7mI2WAp-62jOz044tVk4wruycpn9NYDncnA8,4145
8
8
  oagi/exceptions.py,sha256=VMwVS8ouE9nHhBpN3AZMYt5_U2kGcihWaTnBhoQLquo,1662
9
9
  oagi/logging.py,sha256=CWe89mA5MKTipIvfrqSYkv2CAFNBSwHMDQMDkG_g64g,1350
10
10
  oagi/pil_image.py,sha256=Zp7YNwyE_AT25ZEFsWKbzMxbO8JOQsJ1Espph5ye8k8,3804
11
- oagi/pyautogui_action_handler.py,sha256=T6acM0ZVIOEC8TTI-Qeoxp-B7HHF9xZK7s0HWuGW564,6477
11
+ oagi/pyautogui_action_handler.py,sha256=11-xObprbuJYjoLD1AKbR_4OTdjvXO5ixKaTi_I4gwA,9211
12
12
  oagi/screenshot_maker.py,sha256=sVuW7jn-K4FmLhmYI-akdNI-UVcTeBzh9P1_qJhoq1s,1282
13
- oagi/short_task.py,sha256=fJcirqD7X3_GyINTGdOoe6wi-VFHfP-C8m-zxCvgY5M,1779
13
+ oagi/short_task.py,sha256=9l1PDX70vDUEX2CIJ66yaAtb96P3mK_m95JffspnYFI,1779
14
14
  oagi/single_step.py,sha256=djhGOHzA5Y3-9_ity9QiJr_ObZZ04blSmNZsLXXXfkg,2939
15
15
  oagi/sync_client.py,sha256=E6EgFIe-H91rdsPhF1puwrBTpOnKaL6JA1WHR4R-CLY,9395
16
16
  oagi/task.py,sha256=JfsugIhBrwDmi1xOEVQdqmXsGFK-H4p17-B4rM8kbWs,4001
@@ -21,10 +21,10 @@ oagi/types/async_image_provider.py,sha256=wnhRyPtTmuALt45Qore74-RCkP5yxU9sZGjvOz
21
21
  oagi/types/image.py,sha256=KgPCCTJ6D5vHIaGZdbTE7eQEa1WlT6G9tf59ZuUCV2U,537
22
22
  oagi/types/image_provider.py,sha256=oYFdOYznrK_VOR9egzOjw5wFM5w8EY2sY01pH0ANAgU,1112
23
23
  oagi/types/models/__init__.py,sha256=bVzzGxb6lVxAQyJpy0Z1QknSe-xC3g4OIDr7t-p_3Ys,467
24
- oagi/types/models/action.py,sha256=8Xd3IcH32ENq7uXczo-mbQ736yUOGxO_TaZTfHVRY7w,935
24
+ oagi/types/models/action.py,sha256=hh6mRRSSWgrW4jpZo71zGMCOcZpV5_COu4148uG6G48,967
25
25
  oagi/types/models/image_config.py,sha256=tl6abVg_-IAPLwpaWprgknXu7wRWriMg-AEVyUX73v0,1567
26
26
  oagi/types/models/step.py,sha256=RSI4H_2rrUBq_xyCoWKaq7JHdJWNobtQppaKC1l0aWU,471
27
- oagi-0.4.0.dist-info/METADATA,sha256=haW2dK-avlwzfyw6WjWEm0GwwAEfChy-dhdE2ksk2qk,4620
28
- oagi-0.4.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
29
- oagi-0.4.0.dist-info/licenses/LICENSE,sha256=sy5DLA2M29jFT4UfWsuBF9BAr3FnRkYtnAu6oDZiIf8,1075
30
- oagi-0.4.0.dist-info/RECORD,,
27
+ oagi-0.4.2.dist-info/METADATA,sha256=6s93KoSnU41E_vp-CVyPykBA2zxHrTatFs-Ru5OztBc,4799
28
+ oagi-0.4.2.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
29
+ oagi-0.4.2.dist-info/licenses/LICENSE,sha256=sy5DLA2M29jFT4UfWsuBF9BAr3FnRkYtnAu6oDZiIf8,1075
30
+ oagi-0.4.2.dist-info/RECORD,,
File without changes