oagi-core 0.14.0__tar.gz → 0.14.1__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.
- {oagi_core-0.14.0 → oagi_core-0.14.1}/PKG-INFO +14 -10
- {oagi_core-0.14.0 → oagi_core-0.14.1}/README.md +13 -9
- {oagi_core-0.14.0 → oagi_core-0.14.1}/metapackage/pyproject.toml +2 -2
- {oagi_core-0.14.0 → oagi_core-0.14.1}/metapackage/uv.lock +15 -5
- {oagi_core-0.14.0 → oagi_core-0.14.1}/pyproject.toml +1 -1
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/default.py +4 -6
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/tasker/taskee_agent.py +4 -6
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/async_pyautogui_action_handler.py +2 -1
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/pyautogui_action_handler.py +11 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/utils.py +14 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/ydotool_action_handler.py +11 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_mac_double_click.py +6 -3
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_pyautogui_action_handler.py +47 -19
- {oagi_core-0.14.0 → oagi_core-0.14.1}/uv.lock +1 -1
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.github/workflows/ci.yml +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.github/workflows/release.yml +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.gitignore +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/.python-version +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/CONTRIBUTING.md +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/LICENSE +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/Makefile +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/async_google_weather.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/execute_task_auto.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/execute_task_manual.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/google_weather.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/multi_screen_execution.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/openai_agent_loop_example.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/screenshot_with_config.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/examples/tasker_agent_example.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/actor/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/actor/async_.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/actor/async_short.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/actor/base.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/actor/short.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/actor/sync.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/factories.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/observer/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/observer/agent_observer.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/observer/events.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/observer/exporters.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/observer/protocol.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/observer/report_template.html +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/protocol.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/registry.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/tasker/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/tasker/memory.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/tasker/models.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/tasker/planner.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/agent/tasker/tasker_agent.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/cli/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/cli/agent.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/cli/display.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/cli/main.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/cli/server.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/cli/tracking.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/cli/utils.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/client/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/client/async_.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/client/base.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/client/sync.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/constants.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/exceptions.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/_macos.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/_windows.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/_ydotool.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/async_screenshot_maker.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/async_ydotool_action_handler.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/capslock_manager.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/pil_image.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/screen_manager.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/screenshot_maker.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/handler/wayland_support.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/logging.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/platform_info.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/server/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/server/agent_wrappers.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/server/config.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/server/main.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/server/models.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/server/session_store.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/server/socketio_server.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/task/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/action_handler.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/async_action_handler.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/async_image_provider.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/image.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/image_provider.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/models/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/models/action.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/models/client.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/models/image_config.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/models/step.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/step_observer.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/types/url.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/utils/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/utils/output_parser.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/src/oagi/utils/prompt_builder.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/conftest.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_action_parsing.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_actor.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_agent/test_agent_wrappers.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_agent/test_default_agent.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_agent_registry.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_async_actor.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_async_client.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_async_handlers.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_cli.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_logging.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_observer.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_pil_image.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_planner.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_planner_memory.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_screenshot_maker.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_server/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_server/test_config.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_server/test_session_store.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_server/test_socketio_integration.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_sync_client.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_taskee_agent.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/test_tasker_agent.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/utils/__init__.py +0 -0
- {oagi_core-0.14.0 → oagi_core-0.14.1}/tests/utils/test_output_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: oagi-core
|
|
3
|
-
Version: 0.14.
|
|
3
|
+
Version: 0.14.1
|
|
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>
|
|
@@ -154,12 +154,15 @@ from oagi import AsyncPyautoguiActionHandler, PyautoguiConfig
|
|
|
154
154
|
|
|
155
155
|
# Customize action behavior
|
|
156
156
|
config = PyautoguiConfig(
|
|
157
|
-
drag_duration=1.0,
|
|
158
|
-
scroll_amount=50,
|
|
159
|
-
wait_duration=2.0,
|
|
160
|
-
action_pause=0.2,
|
|
161
|
-
hotkey_interval=0.1,
|
|
162
|
-
capslock_mode="session" # Caps lock mode: 'session' or 'system' (default: 'session')
|
|
157
|
+
drag_duration=1.0, # Slower drags for precision (default: 0.5)
|
|
158
|
+
scroll_amount=50, # Larger scroll steps (default: 2 on macOS, 100 on others)
|
|
159
|
+
wait_duration=2.0, # Longer waits for WAIT action (default: 1.0)
|
|
160
|
+
action_pause=0.2, # Pause between PyAutoGUI calls (default: 0.1)
|
|
161
|
+
hotkey_interval=0.1, # Interval between keys in hotkey combos (default: 0.1)
|
|
162
|
+
capslock_mode="session", # Caps lock mode: 'session' or 'system' (default: 'session')
|
|
163
|
+
macos_ctrl_to_cmd=True, # Replace ctrl with cmd on macOS (default: True)
|
|
164
|
+
click_pre_delay=0.1, # Delay after move before click (default: 0.1)
|
|
165
|
+
post_batch_delay=1.0, # Delay after actions before next screenshot (default: 1.0)
|
|
163
166
|
)
|
|
164
167
|
|
|
165
168
|
action_handler = AsyncPyautoguiActionHandler(config=config)
|
|
@@ -279,10 +282,11 @@ from oagi import AsyncYdotoolActionHandler, YdotoolConfig
|
|
|
279
282
|
# Customize action behavior
|
|
280
283
|
config = YdotoolConfig(
|
|
281
284
|
scroll_amount=50, # Larger scroll steps (default: 20)
|
|
282
|
-
wait_duration=2.0, # Longer waits (default: 1.0)
|
|
283
|
-
action_pause=1.0, #
|
|
285
|
+
wait_duration=2.0, # Longer waits for WAIT action (default: 1.0)
|
|
286
|
+
action_pause=1.0, # Pause between Ydotool calls (default: 0.5)
|
|
284
287
|
capslock_mode="session", # Caps lock mode: 'session' or 'system' (default: 'session')
|
|
285
|
-
socket_address="/tmp/ydotool.sock" #
|
|
288
|
+
socket_address="/tmp/ydotool.sock", # Custom socket address (default: YDOTOOL_SOCKET env var)
|
|
289
|
+
post_batch_delay=1.0, # Delay after actions before next screenshot (default: 1.0)
|
|
286
290
|
)
|
|
287
291
|
|
|
288
292
|
action_handler = AsyncYdotoolActionHandler(config=config)
|
|
@@ -108,12 +108,15 @@ from oagi import AsyncPyautoguiActionHandler, PyautoguiConfig
|
|
|
108
108
|
|
|
109
109
|
# Customize action behavior
|
|
110
110
|
config = PyautoguiConfig(
|
|
111
|
-
drag_duration=1.0,
|
|
112
|
-
scroll_amount=50,
|
|
113
|
-
wait_duration=2.0,
|
|
114
|
-
action_pause=0.2,
|
|
115
|
-
hotkey_interval=0.1,
|
|
116
|
-
capslock_mode="session" # Caps lock mode: 'session' or 'system' (default: 'session')
|
|
111
|
+
drag_duration=1.0, # Slower drags for precision (default: 0.5)
|
|
112
|
+
scroll_amount=50, # Larger scroll steps (default: 2 on macOS, 100 on others)
|
|
113
|
+
wait_duration=2.0, # Longer waits for WAIT action (default: 1.0)
|
|
114
|
+
action_pause=0.2, # Pause between PyAutoGUI calls (default: 0.1)
|
|
115
|
+
hotkey_interval=0.1, # Interval between keys in hotkey combos (default: 0.1)
|
|
116
|
+
capslock_mode="session", # Caps lock mode: 'session' or 'system' (default: 'session')
|
|
117
|
+
macos_ctrl_to_cmd=True, # Replace ctrl with cmd on macOS (default: True)
|
|
118
|
+
click_pre_delay=0.1, # Delay after move before click (default: 0.1)
|
|
119
|
+
post_batch_delay=1.0, # Delay after actions before next screenshot (default: 1.0)
|
|
117
120
|
)
|
|
118
121
|
|
|
119
122
|
action_handler = AsyncPyautoguiActionHandler(config=config)
|
|
@@ -233,10 +236,11 @@ from oagi import AsyncYdotoolActionHandler, YdotoolConfig
|
|
|
233
236
|
# Customize action behavior
|
|
234
237
|
config = YdotoolConfig(
|
|
235
238
|
scroll_amount=50, # Larger scroll steps (default: 20)
|
|
236
|
-
wait_duration=2.0, # Longer waits (default: 1.0)
|
|
237
|
-
action_pause=1.0, #
|
|
239
|
+
wait_duration=2.0, # Longer waits for WAIT action (default: 1.0)
|
|
240
|
+
action_pause=1.0, # Pause between Ydotool calls (default: 0.5)
|
|
238
241
|
capslock_mode="session", # Caps lock mode: 'session' or 'system' (default: 'session')
|
|
239
|
-
socket_address="/tmp/ydotool.sock" #
|
|
242
|
+
socket_address="/tmp/ydotool.sock", # Custom socket address (default: YDOTOOL_SOCKET env var)
|
|
243
|
+
post_batch_delay=1.0, # Delay after actions before next screenshot (default: 1.0)
|
|
240
244
|
)
|
|
241
245
|
|
|
242
246
|
action_handler = AsyncYdotoolActionHandler(config=config)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "oagi"
|
|
7
|
-
version = "0.14.
|
|
7
|
+
version = "0.14.1"
|
|
8
8
|
description = "Official API of OpenAGI Foundation (metapackage with all features)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -16,7 +16,7 @@ authors = [
|
|
|
16
16
|
requires-python = ">= 3.10"
|
|
17
17
|
|
|
18
18
|
dependencies = [
|
|
19
|
-
"oagi-core[desktop,server]==0.14.
|
|
19
|
+
"oagi-core[desktop,server]==0.14.1",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[project.urls]
|
|
@@ -516,20 +516,29 @@ dependencies = [
|
|
|
516
516
|
]
|
|
517
517
|
sdist = { url = "https://files.pythonhosted.org/packages/28/fa/b2ba8229b9381e8f6381c1dcae6f4159a7f72349e414ed19cfbbd1817173/MouseInfo-0.1.3.tar.gz", hash = "sha256:2c62fb8885062b8e520a3cce0a297c657adcc08c60952eb05bc8256ef6f7f6e7", size = 10850, upload-time = "2020-03-27T21:20:10.136Z" }
|
|
518
518
|
|
|
519
|
+
[[package]]
|
|
520
|
+
name = "mss"
|
|
521
|
+
version = "10.1.0"
|
|
522
|
+
source = { registry = "https://pypi.org/simple" }
|
|
523
|
+
sdist = { url = "https://files.pythonhosted.org/packages/40/ca/49b67437a8c46d9732c9c274d7b1fc0c181cfe290d699a0c5e94701dfe79/mss-10.1.0.tar.gz", hash = "sha256:7182baf7ee16ca569e2804028b6ab9bcbf6be5c46fc2880840f33b513b9cb4f8", size = 84200, upload-time = "2025-08-16T12:11:00.119Z" }
|
|
524
|
+
wheels = [
|
|
525
|
+
{ url = "https://files.pythonhosted.org/packages/23/28/1e3e5cd1d677cca68b26166f704f72e35b1e8b6d5076d8ebeebc4e40a649/mss-10.1.0-py3-none-any.whl", hash = "sha256:9179c110cadfef5dc6dc4a041a0cd161c74c379218648e6640b48c6b5cfe8918", size = 24525, upload-time = "2025-08-16T12:10:59.111Z" },
|
|
526
|
+
]
|
|
527
|
+
|
|
519
528
|
[[package]]
|
|
520
529
|
name = "oagi"
|
|
521
|
-
version = "0.14.
|
|
530
|
+
version = "0.14.1"
|
|
522
531
|
source = { editable = "." }
|
|
523
532
|
dependencies = [
|
|
524
533
|
{ name = "oagi-core", extra = ["desktop", "server"] },
|
|
525
534
|
]
|
|
526
535
|
|
|
527
536
|
[package.metadata]
|
|
528
|
-
requires-dist = [{ name = "oagi-core", extras = ["desktop", "server"], specifier = "==0.
|
|
537
|
+
requires-dist = [{ name = "oagi-core", extras = ["desktop", "server"], specifier = "==0.14.0" }]
|
|
529
538
|
|
|
530
539
|
[[package]]
|
|
531
540
|
name = "oagi-core"
|
|
532
|
-
version = "0.
|
|
541
|
+
version = "0.14.0"
|
|
533
542
|
source = { registry = "https://pypi.org/simple" }
|
|
534
543
|
dependencies = [
|
|
535
544
|
{ name = "httpx" },
|
|
@@ -537,13 +546,14 @@ dependencies = [
|
|
|
537
546
|
{ name = "pydantic" },
|
|
538
547
|
{ name = "rich" },
|
|
539
548
|
]
|
|
540
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
549
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4d/2f/74a0a8df68ad16e66f5d84df40c439d4de059b9d2cce8b95972f7e9ff7a6/oagi_core-0.14.0.tar.gz", hash = "sha256:d72f0e81b6427ec08642678df297ff1b73b40c856d4c78df33d7e541af3bd6fd", size = 309074, upload-time = "2026-01-20T15:24:11.961Z" }
|
|
541
550
|
wheels = [
|
|
542
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
551
|
+
{ url = "https://files.pythonhosted.org/packages/22/c7/8061f05bf2f5225a0424ec890f50b8b38dc1e44489232a82a2405ea4a1c5/oagi_core-0.14.0-py3-none-any.whl", hash = "sha256:011a33b641dd5a881e9322bbb82e3394921574b8ce840e99b21f2de02f2d71c5", size = 114399, upload-time = "2026-01-20T15:24:10.801Z" },
|
|
543
552
|
]
|
|
544
553
|
|
|
545
554
|
[package.optional-dependencies]
|
|
546
555
|
desktop = [
|
|
556
|
+
{ name = "mss", marker = "sys_platform == 'win32'" },
|
|
547
557
|
{ name = "pillow" },
|
|
548
558
|
{ name = "pyautogui" },
|
|
549
559
|
{ name = "pyobjc-framework-applicationservices", marker = "sys_platform == 'darwin'" },
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
# Licensed under the MIT License.
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
|
|
9
|
-
import asyncio
|
|
10
9
|
import logging
|
|
11
10
|
|
|
12
11
|
from .. import AsyncActor
|
|
@@ -16,7 +15,7 @@ from ..constants import (
|
|
|
16
15
|
DEFAULT_TEMPERATURE,
|
|
17
16
|
MODEL_ACTOR,
|
|
18
17
|
)
|
|
19
|
-
from ..handler.utils import reset_handler
|
|
18
|
+
from ..handler.utils import configure_handler_delay, reset_handler
|
|
20
19
|
from ..types import (
|
|
21
20
|
ActionEvent,
|
|
22
21
|
AsyncActionHandler,
|
|
@@ -72,6 +71,9 @@ class AsyncDefaultAgent:
|
|
|
72
71
|
# Reset handler state at automation start
|
|
73
72
|
reset_handler(action_handler)
|
|
74
73
|
|
|
74
|
+
# Configure handler's post_batch_delay from agent's step_delay
|
|
75
|
+
configure_handler_delay(action_handler, self.step_delay)
|
|
76
|
+
|
|
75
77
|
for i in range(self.max_steps):
|
|
76
78
|
step_num = i + 1
|
|
77
79
|
logger.debug(f"Executing step {step_num}/{self.max_steps}")
|
|
@@ -127,10 +129,6 @@ class AsyncDefaultAgent:
|
|
|
127
129
|
)
|
|
128
130
|
)
|
|
129
131
|
|
|
130
|
-
# Wait after actions before next screenshot
|
|
131
|
-
if self.step_delay > 0:
|
|
132
|
-
await asyncio.sleep(self.step_delay)
|
|
133
|
-
|
|
134
132
|
# Check if task is complete
|
|
135
133
|
if step.stop:
|
|
136
134
|
logger.info(f"Task completed successfully after {step_num} steps")
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
# Licensed under the MIT License.
|
|
7
7
|
# -----------------------------------------------------------------------------
|
|
8
8
|
|
|
9
|
-
import asyncio
|
|
10
9
|
import logging
|
|
11
10
|
from datetime import datetime
|
|
12
11
|
from typing import Any
|
|
@@ -19,7 +18,7 @@ from oagi.constants import (
|
|
|
19
18
|
DEFAULT_TEMPERATURE,
|
|
20
19
|
MODEL_ACTOR,
|
|
21
20
|
)
|
|
22
|
-
from oagi.handler.utils import reset_handler
|
|
21
|
+
from oagi.handler.utils import configure_handler_delay, reset_handler
|
|
23
22
|
from oagi.types import (
|
|
24
23
|
URL,
|
|
25
24
|
ActionEvent,
|
|
@@ -126,6 +125,9 @@ class TaskeeAgent(AsyncAgent):
|
|
|
126
125
|
# Reset handler state at todo execution start
|
|
127
126
|
reset_handler(action_handler)
|
|
128
127
|
|
|
128
|
+
# Configure handler's post_batch_delay from agent's step_delay
|
|
129
|
+
configure_handler_delay(action_handler, self.step_delay)
|
|
130
|
+
|
|
129
131
|
self.current_todo = instruction
|
|
130
132
|
self.actions = []
|
|
131
133
|
self.total_actions = 0
|
|
@@ -355,10 +357,6 @@ class TaskeeAgent(AsyncAgent):
|
|
|
355
357
|
self.total_actions += len(step.actions)
|
|
356
358
|
self.since_reflection += len(step.actions)
|
|
357
359
|
|
|
358
|
-
# Wait after actions before next screenshot
|
|
359
|
-
if self.step_delay > 0:
|
|
360
|
-
await asyncio.sleep(self.step_delay)
|
|
361
|
-
|
|
362
360
|
steps_taken += 1
|
|
363
361
|
|
|
364
362
|
# Check if task is complete
|
|
@@ -29,7 +29,8 @@ class AsyncPyautoguiActionHandler:
|
|
|
29
29
|
config: PyautoguiConfig instance for customizing behavior
|
|
30
30
|
"""
|
|
31
31
|
self.sync_handler = PyautoguiActionHandler(config=config)
|
|
32
|
-
|
|
32
|
+
# Share the same config object so configure_handler_delay() works
|
|
33
|
+
self.config = self.sync_handler.config
|
|
33
34
|
|
|
34
35
|
def set_target_screen(self, screen: Screen) -> None:
|
|
35
36
|
"""Set the target screen for the action handler.
|
|
@@ -13,6 +13,7 @@ from pydantic import BaseModel, Field
|
|
|
13
13
|
|
|
14
14
|
from oagi.handler.screen_manager import Screen
|
|
15
15
|
|
|
16
|
+
from ..constants import DEFAULT_STEP_DELAY
|
|
16
17
|
from ..exceptions import check_optional_dependency
|
|
17
18
|
from ..types import Action, ActionType, parse_coords, parse_drag_coords, parse_scroll
|
|
18
19
|
from .capslock_manager import CapsLockManager
|
|
@@ -57,6 +58,12 @@ class PyautoguiConfig(BaseModel):
|
|
|
57
58
|
default=0.1,
|
|
58
59
|
description="Delay in seconds after moving to position before clicking",
|
|
59
60
|
)
|
|
61
|
+
post_batch_delay: float = Field(
|
|
62
|
+
default=DEFAULT_STEP_DELAY,
|
|
63
|
+
ge=0,
|
|
64
|
+
description="Delay after executing all actions in a batch (seconds). "
|
|
65
|
+
"Allows UI to settle before next screenshot.",
|
|
66
|
+
)
|
|
60
67
|
|
|
61
68
|
|
|
62
69
|
class PyautoguiActionHandler:
|
|
@@ -292,3 +299,7 @@ class PyautoguiActionHandler:
|
|
|
292
299
|
except Exception as e:
|
|
293
300
|
print(f"Error executing action {action.type}: {e}")
|
|
294
301
|
raise
|
|
302
|
+
|
|
303
|
+
# Wait after batch for UI to settle before next screenshot
|
|
304
|
+
if self.config.post_batch_delay > 0:
|
|
305
|
+
time.sleep(self.config.post_batch_delay)
|
|
@@ -19,3 +19,17 @@ def reset_handler(handler) -> None:
|
|
|
19
19
|
"""
|
|
20
20
|
if hasattr(handler, "reset"):
|
|
21
21
|
handler.reset()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def configure_handler_delay(handler, step_delay: float) -> None:
|
|
25
|
+
"""Configure handler's post_batch_delay from agent's step_delay.
|
|
26
|
+
|
|
27
|
+
Uses duck-typing to check if the handler has a config with post_batch_delay.
|
|
28
|
+
This allows agents to control the delay after action execution.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
handler: The action handler to configure
|
|
32
|
+
step_delay: The delay in seconds to set
|
|
33
|
+
"""
|
|
34
|
+
if hasattr(handler, "config") and hasattr(handler.config, "post_batch_delay"):
|
|
35
|
+
handler.config.post_batch_delay = step_delay
|
|
@@ -12,6 +12,7 @@ from pydantic import BaseModel, Field
|
|
|
12
12
|
|
|
13
13
|
from oagi.handler.screen_manager import Screen
|
|
14
14
|
|
|
15
|
+
from ..constants import DEFAULT_STEP_DELAY
|
|
15
16
|
from ..types import Action, ActionType, parse_coords, parse_drag_coords, parse_scroll
|
|
16
17
|
from .capslock_manager import CapsLockManager
|
|
17
18
|
from .wayland_support import Ydotool, get_screen_size
|
|
@@ -38,6 +39,12 @@ class YdotoolConfig(BaseModel):
|
|
|
38
39
|
default="",
|
|
39
40
|
description="Custom socket address for ydotool (e.g., '/tmp/ydotool.sock')",
|
|
40
41
|
)
|
|
42
|
+
post_batch_delay: float = Field(
|
|
43
|
+
default=DEFAULT_STEP_DELAY,
|
|
44
|
+
ge=0,
|
|
45
|
+
description="Delay after executing all actions in a batch (seconds). "
|
|
46
|
+
"Allows UI to settle before next screenshot.",
|
|
47
|
+
)
|
|
41
48
|
|
|
42
49
|
|
|
43
50
|
class YdotoolActionHandler(Ydotool):
|
|
@@ -241,3 +248,7 @@ class YdotoolActionHandler(Ydotool):
|
|
|
241
248
|
except Exception as e:
|
|
242
249
|
print(f"Error executing action {action.type}: {e}")
|
|
243
250
|
raise
|
|
251
|
+
|
|
252
|
+
# Wait after batch for UI to settle before next screenshot
|
|
253
|
+
if self.config.post_batch_delay > 0:
|
|
254
|
+
time.sleep(self.config.post_batch_delay)
|
|
@@ -17,7 +17,10 @@ if sys.platform != "darwin":
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from oagi.handler import _macos # noqa: E402
|
|
20
|
-
from oagi.handler.pyautogui_action_handler import
|
|
20
|
+
from oagi.handler.pyautogui_action_handler import (
|
|
21
|
+
PyautoguiActionHandler,
|
|
22
|
+
PyautoguiConfig,
|
|
23
|
+
)
|
|
21
24
|
from oagi.types import Action, ActionType
|
|
22
25
|
|
|
23
26
|
|
|
@@ -77,7 +80,7 @@ def test_macos_click_implementation(mock_quartz):
|
|
|
77
80
|
|
|
78
81
|
def test_handler_calls_macos_click_double(mock_pyautogui):
|
|
79
82
|
"""Test that handler calls macos_click for double click on macOS."""
|
|
80
|
-
handler = PyautoguiActionHandler()
|
|
83
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
81
84
|
action = Action(type=ActionType.LEFT_DOUBLE, argument="500, 500", count=1)
|
|
82
85
|
|
|
83
86
|
with (
|
|
@@ -92,7 +95,7 @@ def test_handler_calls_macos_click_double(mock_pyautogui):
|
|
|
92
95
|
|
|
93
96
|
def test_handler_calls_macos_click_triple(mock_pyautogui):
|
|
94
97
|
"""Test that handler calls macos_click for triple click on macOS."""
|
|
95
|
-
handler = PyautoguiActionHandler()
|
|
98
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
96
99
|
action = Action(type=ActionType.LEFT_TRIPLE, argument="500, 500", count=1)
|
|
97
100
|
|
|
98
101
|
with (
|
|
@@ -17,6 +17,7 @@ from oagi.handler.pyautogui_action_handler import (
|
|
|
17
17
|
PyautoguiActionHandler,
|
|
18
18
|
PyautoguiConfig,
|
|
19
19
|
)
|
|
20
|
+
from oagi.handler.utils import configure_handler_delay
|
|
20
21
|
from oagi.types import Action, ActionType
|
|
21
22
|
|
|
22
23
|
|
|
@@ -29,12 +30,14 @@ def mock_pyautogui():
|
|
|
29
30
|
|
|
30
31
|
@pytest.fixture
|
|
31
32
|
def config():
|
|
32
|
-
|
|
33
|
+
# Disable post_batch_delay to avoid sleeping in tests
|
|
34
|
+
return PyautoguiConfig(post_batch_delay=0)
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
@pytest.fixture
|
|
36
38
|
def handler(mock_pyautogui):
|
|
37
|
-
|
|
39
|
+
# Disable post_batch_delay to avoid sleeping in tests
|
|
40
|
+
return PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
38
41
|
|
|
39
42
|
|
|
40
43
|
@pytest.mark.parametrize(
|
|
@@ -109,6 +112,7 @@ def test_wait_action(handler, mock_pyautogui, config):
|
|
|
109
112
|
with patch("time.sleep") as mock_sleep:
|
|
110
113
|
action = Action(type=ActionType.WAIT, argument="", count=1)
|
|
111
114
|
handler([action])
|
|
115
|
+
# wait_duration calls time.sleep (post_batch_delay is 0 in test fixture)
|
|
112
116
|
mock_sleep.assert_called_once_with(config.wait_duration)
|
|
113
117
|
|
|
114
118
|
|
|
@@ -259,7 +263,7 @@ class TestCornerCoordinatesHandling:
|
|
|
259
263
|
def test_corner_coordinate_adjustment(
|
|
260
264
|
self, mock_pyautogui, input_coords, expected_coords
|
|
261
265
|
):
|
|
262
|
-
handler = PyautoguiActionHandler()
|
|
266
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
263
267
|
action = Action(type=ActionType.CLICK, argument=input_coords, count=1)
|
|
264
268
|
handler([action])
|
|
265
269
|
# Click actions now use moveTo first, then click without coordinates
|
|
@@ -268,7 +272,7 @@ class TestCornerCoordinatesHandling:
|
|
|
268
272
|
|
|
269
273
|
def test_drag_with_corner_coordinates(self, mock_pyautogui, config):
|
|
270
274
|
"""Test drag operations with corner coordinates."""
|
|
271
|
-
handler = PyautoguiActionHandler()
|
|
275
|
+
handler = PyautoguiActionHandler(config=config)
|
|
272
276
|
# Drag from top-left corner to bottom-right corner
|
|
273
277
|
action = Action(type=ActionType.DRAG, argument="0, 0, 1000, 1000", count=1)
|
|
274
278
|
handler([action])
|
|
@@ -281,7 +285,7 @@ class TestCornerCoordinatesHandling:
|
|
|
281
285
|
|
|
282
286
|
def test_scroll_with_corner_coordinates(self, mock_pyautogui, config):
|
|
283
287
|
"""Test scroll operations at corner coordinates."""
|
|
284
|
-
handler = PyautoguiActionHandler()
|
|
288
|
+
handler = PyautoguiActionHandler(config=config)
|
|
285
289
|
action = Action(type=ActionType.SCROLL, argument="0, 0, up", count=1)
|
|
286
290
|
handler([action])
|
|
287
291
|
|
|
@@ -291,7 +295,7 @@ class TestCornerCoordinatesHandling:
|
|
|
291
295
|
|
|
292
296
|
def test_multiple_clicks_at_corners(self, mock_pyautogui):
|
|
293
297
|
"""Test multiple clicks at corner positions."""
|
|
294
|
-
handler = PyautoguiActionHandler()
|
|
298
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
295
299
|
actions = [
|
|
296
300
|
Action(type=ActionType.LEFT_DOUBLE, argument="0, 0", count=1),
|
|
297
301
|
Action(type=ActionType.LEFT_TRIPLE, argument="1000, 0", count=1),
|
|
@@ -316,7 +320,7 @@ class TestCornerCoordinatesHandling:
|
|
|
316
320
|
|
|
317
321
|
class TestCapsLockIntegration:
|
|
318
322
|
def test_caps_lock_key_normalization(self, mock_pyautogui):
|
|
319
|
-
handler = PyautoguiActionHandler()
|
|
323
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
320
324
|
|
|
321
325
|
# Test different caps lock variations
|
|
322
326
|
for variant in ["caps", "caps_lock", "capslock"]:
|
|
@@ -324,7 +328,7 @@ class TestCapsLockIntegration:
|
|
|
324
328
|
assert keys == ["capslock"]
|
|
325
329
|
|
|
326
330
|
def test_caps_lock_session_mode(self, mock_pyautogui):
|
|
327
|
-
config = PyautoguiConfig(capslock_mode="session")
|
|
331
|
+
config = PyautoguiConfig(capslock_mode="session", post_batch_delay=0)
|
|
328
332
|
handler = PyautoguiActionHandler(config=config)
|
|
329
333
|
|
|
330
334
|
# Mock platform as Linux to use pyautogui.typewrite fallback
|
|
@@ -347,7 +351,7 @@ class TestCapsLockIntegration:
|
|
|
347
351
|
mock_pyautogui.typewrite.assert_called_with("TEST")
|
|
348
352
|
|
|
349
353
|
def test_caps_lock_system_mode(self, mock_pyautogui):
|
|
350
|
-
config = PyautoguiConfig(capslock_mode="system")
|
|
354
|
+
config = PyautoguiConfig(capslock_mode="system", post_batch_delay=0)
|
|
351
355
|
handler = PyautoguiActionHandler(config=config)
|
|
352
356
|
|
|
353
357
|
# Toggle caps lock in system mode
|
|
@@ -366,7 +370,7 @@ class TestCapsLockIntegration:
|
|
|
366
370
|
|
|
367
371
|
def test_regular_hotkey_not_affected(self, mock_pyautogui):
|
|
368
372
|
# Disable macos_ctrl_to_cmd to test basic hotkey functionality
|
|
369
|
-
config = PyautoguiConfig(macos_ctrl_to_cmd=False)
|
|
373
|
+
config = PyautoguiConfig(macos_ctrl_to_cmd=False, post_batch_delay=0)
|
|
370
374
|
handler = PyautoguiActionHandler(config=config)
|
|
371
375
|
|
|
372
376
|
# Regular hotkeys should work normally
|
|
@@ -378,14 +382,14 @@ class TestCapsLockIntegration:
|
|
|
378
382
|
class TestMacosCtrlToCmd:
|
|
379
383
|
@pytest.mark.skipif(sys.platform != "darwin", reason="macOS-specific test")
|
|
380
384
|
def test_ctrl_remapped_to_command_on_macos_by_default(self, mock_pyautogui):
|
|
381
|
-
handler = PyautoguiActionHandler()
|
|
385
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
382
386
|
action = Action(type=ActionType.HOTKEY, argument="ctrl+c", count=1)
|
|
383
387
|
handler([action])
|
|
384
388
|
mock_pyautogui.hotkey.assert_called_once_with("command", "c", interval=0.1)
|
|
385
389
|
|
|
386
390
|
@pytest.mark.skipif(sys.platform != "darwin", reason="macOS-specific test")
|
|
387
391
|
def test_ctrl_not_remapped_when_disabled(self, mock_pyautogui):
|
|
388
|
-
config = PyautoguiConfig(macos_ctrl_to_cmd=False)
|
|
392
|
+
config = PyautoguiConfig(macos_ctrl_to_cmd=False, post_batch_delay=0)
|
|
389
393
|
handler = PyautoguiActionHandler(config=config)
|
|
390
394
|
action = Action(type=ActionType.HOTKEY, argument="ctrl+c", count=1)
|
|
391
395
|
handler([action])
|
|
@@ -393,7 +397,7 @@ class TestMacosCtrlToCmd:
|
|
|
393
397
|
|
|
394
398
|
@pytest.mark.skipif(sys.platform != "darwin", reason="macOS-specific test")
|
|
395
399
|
def test_multiple_keys_with_ctrl_remapped(self, mock_pyautogui):
|
|
396
|
-
handler = PyautoguiActionHandler()
|
|
400
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
397
401
|
action = Action(type=ActionType.HOTKEY, argument="ctrl+shift+a", count=1)
|
|
398
402
|
handler([action])
|
|
399
403
|
mock_pyautogui.hotkey.assert_called_once_with(
|
|
@@ -402,20 +406,20 @@ class TestMacosCtrlToCmd:
|
|
|
402
406
|
|
|
403
407
|
@pytest.mark.skipif(sys.platform != "darwin", reason="macOS-specific test")
|
|
404
408
|
def test_cmd_not_affected_on_macos(self, mock_pyautogui):
|
|
405
|
-
handler = PyautoguiActionHandler()
|
|
409
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
406
410
|
action = Action(type=ActionType.HOTKEY, argument="cmd+v", count=1)
|
|
407
411
|
handler([action])
|
|
408
412
|
mock_pyautogui.hotkey.assert_called_once_with("cmd", "v", interval=0.1)
|
|
409
413
|
|
|
410
414
|
def test_ctrl_not_remapped_on_non_macos(self, mock_pyautogui):
|
|
411
415
|
with patch.object(sys, "platform", "linux"):
|
|
412
|
-
handler = PyautoguiActionHandler()
|
|
416
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
413
417
|
action = Action(type=ActionType.HOTKEY, argument="ctrl+c", count=1)
|
|
414
418
|
handler([action])
|
|
415
419
|
mock_pyautogui.hotkey.assert_called_once_with("ctrl", "c", interval=0.1)
|
|
416
420
|
|
|
417
421
|
def test_other_keys_not_affected(self, mock_pyautogui):
|
|
418
|
-
handler = PyautoguiActionHandler()
|
|
422
|
+
handler = PyautoguiActionHandler(config=PyautoguiConfig(post_batch_delay=0))
|
|
419
423
|
action = Action(type=ActionType.HOTKEY, argument="shift+tab", count=1)
|
|
420
424
|
handler([action])
|
|
421
425
|
mock_pyautogui.hotkey.assert_called_once_with("shift", "tab", interval=0.1)
|
|
@@ -423,7 +427,7 @@ class TestMacosCtrlToCmd:
|
|
|
423
427
|
|
|
424
428
|
class TestHandlerReset:
|
|
425
429
|
def test_handler_reset_resets_capslock_state(self, mock_pyautogui):
|
|
426
|
-
config = PyautoguiConfig(capslock_mode="session")
|
|
430
|
+
config = PyautoguiConfig(capslock_mode="session", post_batch_delay=0)
|
|
427
431
|
handler = PyautoguiActionHandler(config=config)
|
|
428
432
|
|
|
429
433
|
# Enable caps lock via hotkey
|
|
@@ -436,7 +440,7 @@ class TestHandlerReset:
|
|
|
436
440
|
assert handler.caps_manager.caps_enabled is False
|
|
437
441
|
|
|
438
442
|
def test_finish_action_resets_handler(self, mock_pyautogui):
|
|
439
|
-
config = PyautoguiConfig(capslock_mode="session")
|
|
443
|
+
config = PyautoguiConfig(capslock_mode="session", post_batch_delay=0)
|
|
440
444
|
handler = PyautoguiActionHandler(config=config)
|
|
441
445
|
|
|
442
446
|
# Enable caps lock
|
|
@@ -452,7 +456,7 @@ class TestHandlerReset:
|
|
|
452
456
|
|
|
453
457
|
class TestAsyncHandlerReset:
|
|
454
458
|
def test_async_handler_reset_delegates_to_sync_handler(self, mock_pyautogui):
|
|
455
|
-
config = PyautoguiConfig(capslock_mode="session")
|
|
459
|
+
config = PyautoguiConfig(capslock_mode="session", post_batch_delay=0)
|
|
456
460
|
handler = AsyncPyautoguiActionHandler(config=config)
|
|
457
461
|
|
|
458
462
|
# Enable caps lock on the underlying sync handler
|
|
@@ -462,3 +466,27 @@ class TestAsyncHandlerReset:
|
|
|
462
466
|
# Reset via async handler
|
|
463
467
|
handler.reset()
|
|
464
468
|
assert handler.sync_handler.caps_manager.caps_enabled is False
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class TestConfigureHandlerDelay:
|
|
472
|
+
def test_configure_handler_delay(self, mock_pyautogui):
|
|
473
|
+
handler = PyautoguiActionHandler()
|
|
474
|
+
original_delay = handler.config.post_batch_delay
|
|
475
|
+
|
|
476
|
+
configure_handler_delay(handler, 3.0)
|
|
477
|
+
assert handler.config.post_batch_delay == 3.0
|
|
478
|
+
assert handler.config.post_batch_delay != original_delay
|
|
479
|
+
|
|
480
|
+
def test_configure_handler_delay_with_zero(self, mock_pyautogui):
|
|
481
|
+
handler = PyautoguiActionHandler()
|
|
482
|
+
configure_handler_delay(handler, 0)
|
|
483
|
+
assert handler.config.post_batch_delay == 0
|
|
484
|
+
|
|
485
|
+
def test_configure_handler_delay_ignores_incompatible_handler(self):
|
|
486
|
+
# A handler without config attribute
|
|
487
|
+
class DummyHandler:
|
|
488
|
+
pass
|
|
489
|
+
|
|
490
|
+
handler = DummyHandler()
|
|
491
|
+
# Should not raise
|
|
492
|
+
configure_handler_delay(handler, 1.0)
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|