ok-script 2.0.19__tar.gz → 2.0.21__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.
- {ok_script-2.0.19 → ok_script-2.0.21}/PKG-INFO +3 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/README.md +2 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/docs/mcp.md +10 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/code_runner.py +1 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/mcp_runner.py +66 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/mcp_server.py +4 -2
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/base.py +2 -2
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/keys.py +30 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/post_message.py +24 -2
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/pydirect.py +26 -7
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/pynput.py +13 -9
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/task/TaskExecutor.py +10 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/task/task.py +2 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/test/__init__.py +4 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/about/AboutTab.py +2 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/en_US.qm +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/en_US.ts +8 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/es_ES.qm +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/es_ES.ts +8 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/ja_JP.qm +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/ja_JP.ts +9 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/ko_KR.qm +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/ko_KR.ts +9 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/zh_CN.qm +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/zh_CN.ts +8 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/zh_TW.qm +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/zh_TW.ts +8 -0
- ok_script-2.0.21/ok/ui/qt/resources.py +17921 -0
- ok_script-2.0.21/ok/ui/qt/tasks/LabelAndLineEdit.py +83 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok_script.egg-info/PKG-INFO +3 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/ok_script.egg-info/SOURCES.txt +3 -0
- ok_script-2.0.21/tests/test_mcp_cleanup.py +166 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_mcp_runner.py +1 -1
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_mcp_server.py +35 -0
- ok_script-2.0.21/tests/test_mouse_buttons.py +205 -0
- ok_script-2.0.21/tests/test_task_executor_next_frame.py +83 -0
- ok_script-2.0.19/ok/ui/qt/resources.py +0 -17886
- ok_script-2.0.19/ok/ui/qt/tasks/LabelAndLineEdit.py +0 -39
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/develop/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/develop/agents/openai.yaml +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/develop/references/windows-input.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/generate-templates/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/reload-tasks/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/reload-tasks/agents/openai.yaml +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/setup-env/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/setup-env/agents/openai.yaml +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/setup-env/assets/ok-script-develop/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/setup-project/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/setup-project/agents/openai.yaml +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/use_venv/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/write-test/SKILL.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/.agents/skills/write-test/agents/openai.yaml +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/LICENSE.txt +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/MANIFEST.in +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/diagnostics/qq_trace.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/docs/agent-setup.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/docs/feature-crops.md +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/examples/mcp_observe.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/__main__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/alas/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/alas/emulator_base.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/alas/emulator_windows.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/alas/platform_windows.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/alas/utils.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/assets/default-icon.png +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/deep.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/minitouch.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/nemu_ipc.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/nemu_utils.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/pool.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/timer.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/adb/util.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/windows/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/windows/d3d11.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/capture/windows/dump.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/cli.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/capture_labels.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/config_schema.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/downloads.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/events.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/icons.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/notifications.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/plugin_staging.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/plugins.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/screenshot.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/script_editing.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/script_packager.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/script_templates.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/skills.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/start_controller.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/task_manager.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/template_store.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/translation.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/core/ui_config.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/DeviceManager.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/adb.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/bitblt.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/bitblt_utils.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/browser.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/desktop_duplication.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/hwnd_window.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/image.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/nemu_ipc.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/types.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/update.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/windows_graphics.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/capture_methods/windows_graphics_hdr.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/adb.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/base.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/browser.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/do_nothing.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/foreground_post_message.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/genshin.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/interaction_methods/swipe.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/device/intercation.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/feature/Box.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/feature/Feature.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/feature/FeatureSet.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/feature/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/gui/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/gui/util/pyappify_startup.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/manager.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/messenger_images.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/pipeline.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/ppocr.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/providers.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/system.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/notification/windows_messenger.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ocr/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ocr/download_paddle_model.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/UI/ViewManagement/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/UI/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/Windows/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/delegate.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/export.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/idldsl.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/inspectable.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/roapi.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/types.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/rotypes/winstring.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/task/DiagnosisTask.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/task/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/task/exceptions.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/test/OKTestRunner.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/test/RunTests.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/test/TaskTestCase.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/third_party/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/third_party/paperclip.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/overlay/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/overlay/win32_gdi.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/Communicate.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/MainWindow.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/MessageWindow.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/StartController.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/TabTitles.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/about/HttpTextEdit.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/about/LinksBar.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/about/ProjectCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/about/UpdateCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/about/VersionCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/about/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/common/OKIcon.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/common/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/common/accent_color.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/common/config.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/common/design_system.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/common/icons.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/common/style_sheet.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/debug/DebugTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/debug/JobControls.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/debug/OverlayWidget.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/debug/RunCodeTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/debug/Screenshot.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/debug/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/events.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/GettextTranslator.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/path.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/i18n/update.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/overlay/OverlayWindow.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/overlay/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/plugins/PluginTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/plugins/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/plugins/imported_tabs.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/card.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/discord.svg +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/heart.svg +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/message_window.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/setting_interface.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/status_bar.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/stop.svg +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/dark/tab.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/card.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/discord.svg +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/heart.svg +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/message_window.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/setting_interface.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/status_bar.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/stop.svg +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qss/light/tab.qss +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/qt.qrc +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/settings/GlobalConfigCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/settings/GlobalConfigTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/settings/SettingTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/settings/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/start/LogWindow.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/start/SelectCaptureListView.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/start/SelectInteractionListView.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/start/StartCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/start/StartTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/start/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/ConfigCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/ConfigItemFactory.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/ConfigLabelAndWidget.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/EditTaskTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndButtons.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndDropDown.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndFileSelector.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndGlobal.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndList.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndMcpServer.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndMultiSelection.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndSpinBox.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndSwitchButton.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndTextEdit.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/LabelAndWidget.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/MarkUpWindow.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/ModifyListDialog.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/ModifyListItem.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/OneTimeTaskTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/PythonHighlighter.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/RecordScript.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/ScheduleTaskTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/ScriptPackager.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/StartButton.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TaskCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TaskManger.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TaskOpButton.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TaskTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TemplateFactory.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TemplateTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TooltipTableWidget.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/TriggerTaskTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/tasks/schedule_index_sync.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/Alert.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/InitWorker.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/app.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/download.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/pip_util.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/pyappify_startup.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/touch_scroll.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/util/windows_thumbnail.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/BaseLoading.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/BaseWindow.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/Card.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/CustomTab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/EmptyCard.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/ExpandCardLayout.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/FlowLayout.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/FramelessDialog.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/ImageWidget.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/ImportWarningDialog.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/ListTableWidgetItem.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/NumericTableWidgetItem.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/OkCompactSpinBox.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/SortingTableWidgetItem.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/StartLoadingDialog.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/StatusBar.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/Tab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/TabWidget.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/UpdateConfigWidgetItem.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/WidgetWithVLabel.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/YesNonWidgetItem.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/ui/qt/widget/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/update/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/update/copy_ok_folder.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/update/inline_ok_requirements.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/Analytics.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/GlobalConfig.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/__init__.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/blur.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/clazz.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/collection.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/color.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/config.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/explorer.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/file.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/gpu_driver_settings.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/handler.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/i18n.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/logger.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/partial_sync_repo.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/print_hwnd.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/process.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/version.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/window.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok/util/windows_schedule.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok_script.egg-info/entry_points.txt +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok_script.egg-info/not-zip-safe +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok_script.egg-info/requires.txt +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/ok_script.egg-info/top_level.txt +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/pyproject.toml +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/setup.cfg +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/setup.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_accent_color.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_app.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_base_interaction.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_blur.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_box.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_capture_update.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_cli.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_config_card.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_core_events.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_core_ui_services.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_debug_job_controls.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_device_manager.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_executor_jobs.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_expand_card_layout.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_explorer.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_global_config.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_gpu_driver_settings.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_handler.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_headless_imports.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_inline_ok_requirements.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_logger.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_main_window_notifications.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_main_window_startup_tab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_main_window_system_theme.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_mcp_setting.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_missing_frame.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_navigation_state.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_nemu_ipc_capture.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_notifications.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_ok_mutex.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_overlay_custom_draw.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_overlay_lifecycle.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_package_metadata.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_plugin_staging.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_plugin_tabs.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_plugins.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_process.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_process_mutex.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_pyappify_startup_update.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_qt_events.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_qt_legacy_imports.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_qt_page_layout.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_runtime_startup.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_schedule_startup.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_schedule_task_index_sync.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_screenshot_naming.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_screenshot_rendering.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_skills.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_start_controller.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_start_tab_overlay.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_task_executor_queue.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_task_reloading.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_task_ui.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_template_compression.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_template_generation.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_template_tab.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_touch_scroll.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_translation_fallback.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_ui_config.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_version.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_windows_graphics_capture.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_windows_graphics_hdr.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_windows_schedule_target_parse.py +0 -0
- {ok_script-2.0.19 → ok_script-2.0.21}/tests/test_windows_schedule_xml.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ok-script
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.21
|
|
4
4
|
Summary: Automation with Computer Vision for Python
|
|
5
5
|
Author-email: ok-oldking <firedcto@gmail.com>
|
|
6
6
|
License: ok-script License
|
|
@@ -212,6 +212,8 @@ python -m venv .venv
|
|
|
212
212
|
- [白荆回廊](https://github.com/ok-oldking/ok-baijing)(停止维护)
|
|
213
213
|
- [明日方舟:终末地](https://github.com/AliceJump/ok-end-field)
|
|
214
214
|
- [异环](https://github.com/BnanZ0/ok-nte)
|
|
215
|
+
- [棕色尘埃 2](https://github.com/GodRaymond233/ok-bd2)
|
|
216
|
+
- [蓝色星原:旅谣](https://github.com/longer-sausage/OK-AzurPromilia)
|
|
215
217
|
|
|
216
218
|
## 社区与发布
|
|
217
219
|
|
|
@@ -85,6 +85,8 @@ python -m venv .venv
|
|
|
85
85
|
- [白荆回廊](https://github.com/ok-oldking/ok-baijing)(停止维护)
|
|
86
86
|
- [明日方舟:终末地](https://github.com/AliceJump/ok-end-field)
|
|
87
87
|
- [异环](https://github.com/BnanZ0/ok-nte)
|
|
88
|
+
- [棕色尘埃 2](https://github.com/GodRaymond233/ok-bd2)
|
|
89
|
+
- [蓝色星原:旅谣](https://github.com/longer-sausage/OK-AzurPromilia)
|
|
88
90
|
|
|
89
91
|
## 社区与发布
|
|
90
92
|
|
|
@@ -72,6 +72,15 @@ Applications using `OK(config).start()` can enable MCP through their config:
|
|
|
72
72
|
"mcp": {"enabled": True, "port": 8765, "artifact_directory": "logs/mcp"}
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
MCP artifacts use a seven-day retention period by default. Set `mcp.retention_days`
|
|
76
|
+
to a nonnegative number of days, or `0` to disable cleanup. Cleanup runs on startup
|
|
77
|
+
and at most once per hour when submitting runs/reloads or requesting screenshots.
|
|
78
|
+
It removes expired completed run directories (including their logs, status and
|
|
79
|
+
custom artifacts), their in-memory status records, and old observation images.
|
|
80
|
+
Run age is measured from `finished_at`; observation age uses the image file's
|
|
81
|
+
modification time. Active/nonterminal runs, unrecognized files and connection
|
|
82
|
+
records are preserved. Copy evidence elsewhere if it must outlive retention.
|
|
83
|
+
|
|
75
84
|
The server binds only to IPv4 loopback and validates HTTP Host and Origin.
|
|
76
85
|
Each instance writes `logs/mcp/connections/<pid>-<port>.json` containing its URL,
|
|
77
86
|
bearer token, process ID, process start time and project directory. These records
|
|
@@ -143,7 +152,7 @@ Clients supporting MCP resources can also discover these skills through
|
|
|
143
152
|
|
|
144
153
|
States are `queued`, `running`, `stopping`, `succeeded`, `failed`, and
|
|
145
154
|
`cancelled`. Only the last three are terminal. Run IDs are scoped to the current
|
|
146
|
-
process; saved artifacts remain available after restarting it.
|
|
155
|
+
process; saved artifacts remain available after restarting it until retention cleanup.
|
|
147
156
|
|
|
148
157
|
## Preferred workflow for existing tasks
|
|
149
158
|
|
|
@@ -24,7 +24,7 @@ from typing import Any
|
|
|
24
24
|
|
|
25
25
|
from ok.task.exceptions import TaskDisabledException
|
|
26
26
|
|
|
27
|
-
_log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
|
|
27
|
+
_log_formatter = logging.Formatter('%(asctime)s.%(msecs)03d %(levelname)s %(message)s', datefmt='%H:%M:%S')
|
|
28
28
|
_capture_lock = threading.Lock()
|
|
29
29
|
_run_ids = itertools.count(1)
|
|
30
30
|
|
|
@@ -4,6 +4,9 @@ import hashlib
|
|
|
4
4
|
import importlib.util
|
|
5
5
|
import inspect
|
|
6
6
|
import json
|
|
7
|
+
import math
|
|
8
|
+
import re
|
|
9
|
+
import shutil
|
|
7
10
|
import sys
|
|
8
11
|
import threading
|
|
9
12
|
import time
|
|
@@ -15,9 +18,11 @@ from pathlib import Path
|
|
|
15
18
|
from ok.core.code_runner import capture_output
|
|
16
19
|
from ok.task.exceptions import TaskDisabledException
|
|
17
20
|
from ok.task.task import BaseTask, TriggerTask
|
|
21
|
+
from ok.util.logger import Logger
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
TERMINAL_STATES = {'succeeded', 'failed', 'cancelled'}
|
|
25
|
+
logger = Logger.get_logger(__name__)
|
|
21
26
|
|
|
22
27
|
|
|
23
28
|
class McpTaskRunner:
|
|
@@ -30,7 +35,10 @@ class McpTaskRunner:
|
|
|
30
35
|
"""
|
|
31
36
|
|
|
32
37
|
def __init__(self, executor, app, screenshot_service, artifact_directory='logs/mcp', prepare=None,
|
|
33
|
-
task_manager=None):
|
|
38
|
+
task_manager=None, retention_days=7):
|
|
39
|
+
if (isinstance(retention_days, bool) or not isinstance(retention_days, (int, float))
|
|
40
|
+
or not math.isfinite(retention_days) or retention_days < 0):
|
|
41
|
+
raise ValueError('mcp.retention_days must be a finite nonnegative number')
|
|
34
42
|
self.executor = executor
|
|
35
43
|
self.app = app
|
|
36
44
|
self.screenshot_service = screenshot_service
|
|
@@ -42,8 +50,63 @@ class McpTaskRunner:
|
|
|
42
50
|
self._active = None
|
|
43
51
|
self._observation_job = None
|
|
44
52
|
self._closed = False
|
|
53
|
+
self.retention_days = retention_days
|
|
54
|
+
self._next_cleanup = 0
|
|
55
|
+
self._cleanup_artifacts()
|
|
45
56
|
self.executor.enable_frame_snapshots()
|
|
46
57
|
|
|
58
|
+
def _cleanup_artifacts(self):
|
|
59
|
+
"""Expire completed runs and observations, at most hourly during activity."""
|
|
60
|
+
with self._lock:
|
|
61
|
+
now = time.monotonic()
|
|
62
|
+
if self.retention_days == 0 or now < self._next_cleanup:
|
|
63
|
+
return
|
|
64
|
+
self._next_cleanup = now + 3600
|
|
65
|
+
cutoff = time.time() - self.retention_days * 86400
|
|
66
|
+
try:
|
|
67
|
+
paths = list(self.artifact_directory.iterdir())
|
|
68
|
+
except FileNotFoundError:
|
|
69
|
+
return
|
|
70
|
+
except OSError as error:
|
|
71
|
+
logger.warning(f'Could not scan MCP artifacts: {error}')
|
|
72
|
+
return
|
|
73
|
+
for path in paths:
|
|
74
|
+
try:
|
|
75
|
+
# Only operate on framework-owned entries inside this root.
|
|
76
|
+
# In particular, never follow directory links or junctions.
|
|
77
|
+
if path.is_symlink() or path.resolve() != path:
|
|
78
|
+
continue
|
|
79
|
+
if path.name == 'observations' and path.is_dir():
|
|
80
|
+
for image in path.iterdir():
|
|
81
|
+
if (re.fullmatch(r'[0-9a-f]{32}\.png', image.name)
|
|
82
|
+
and not image.is_symlink() and image.is_file()
|
|
83
|
+
and image.resolve() == image
|
|
84
|
+
and image.stat().st_mtime < cutoff):
|
|
85
|
+
try:
|
|
86
|
+
image.unlink()
|
|
87
|
+
except OSError as error:
|
|
88
|
+
logger.warning(f'Could not remove MCP observation {image}: {error}')
|
|
89
|
+
elif (re.fullmatch(r'[0-9a-f]{32}', path.name) and path.is_dir()
|
|
90
|
+
and path.name != self._active):
|
|
91
|
+
try:
|
|
92
|
+
record = json.loads((path / 'status.json').read_text(encoding='utf-8'))
|
|
93
|
+
except (ValueError, UnicodeError):
|
|
94
|
+
continue
|
|
95
|
+
if not isinstance(record, dict):
|
|
96
|
+
continue
|
|
97
|
+
finished = record.get('finished_at')
|
|
98
|
+
if (record.get('run_id') == path.name
|
|
99
|
+
and isinstance(record.get('state'), str)
|
|
100
|
+
and record['state'] in TERMINAL_STATES
|
|
101
|
+
and isinstance(finished, (int, float)) and not isinstance(finished, bool)
|
|
102
|
+
and math.isfinite(finished) and finished < cutoff):
|
|
103
|
+
shutil.rmtree(path)
|
|
104
|
+
self._runs.pop(path.name, None)
|
|
105
|
+
except FileNotFoundError:
|
|
106
|
+
pass # Another server sharing this directory may have removed it.
|
|
107
|
+
except OSError as error:
|
|
108
|
+
logger.warning(f'Could not clean MCP artifacts {path}: {error}')
|
|
109
|
+
|
|
47
110
|
def _save(self, record):
|
|
48
111
|
path = Path(record['artifact_directory']) / 'status.json'
|
|
49
112
|
temporary = path.with_suffix('.tmp')
|
|
@@ -135,6 +198,7 @@ class McpTaskRunner:
|
|
|
135
198
|
raise RuntimeError('MCP task runner is shutting down')
|
|
136
199
|
if self._active is not None:
|
|
137
200
|
raise RuntimeError(f'Run {self._active} is still active; wait until it has stopped')
|
|
201
|
+
self._cleanup_artifacts()
|
|
138
202
|
run_id = uuid.uuid4().hex
|
|
139
203
|
owner = f'mcp:{run_id}'
|
|
140
204
|
self.executor.acquire_exclusive(owner)
|
|
@@ -282,6 +346,7 @@ class McpTaskRunner:
|
|
|
282
346
|
with self._lock:
|
|
283
347
|
if self._closed:
|
|
284
348
|
raise RuntimeError('MCP task runner is shutting down')
|
|
349
|
+
self._cleanup_artifacts()
|
|
285
350
|
if (self._active is None and self._observation_job is None and self.executor.current_job is None
|
|
286
351
|
and self.executor.current_task is None and self.executor.exclusive_owner is None):
|
|
287
352
|
def capture():
|
|
@@ -232,7 +232,7 @@ class LocalMcpServer:
|
|
|
232
232
|
app = runtime.headless_app if runtime.should_init_task_manager_headless() else runtime.app
|
|
233
233
|
self.runner = McpTaskRunner(runtime.task_executor, app, runtime.screenshot,
|
|
234
234
|
config.get('artifact_directory', 'logs/mcp'), self._prepare_device,
|
|
235
|
-
task_manager=og.task_manager)
|
|
235
|
+
task_manager=og.task_manager, retention_days=config.get('retention_days', 7))
|
|
236
236
|
self._server = None
|
|
237
237
|
self._socket = None
|
|
238
238
|
self._thread = None
|
|
@@ -289,9 +289,11 @@ class LocalMcpServer:
|
|
|
289
289
|
self.port = self._socket.getsockname()[1]
|
|
290
290
|
app = create_mcp_app(self.runner, self.token, self.port, self.exit_process)
|
|
291
291
|
import uvicorn
|
|
292
|
+
# uvicorn's default log_config goes through dictConfig, which closes every
|
|
293
|
+
# existing handler in the process, including the ok-script.log file handler.
|
|
292
294
|
self._server = uvicorn.Server(uvicorn.Config(
|
|
293
295
|
app, host='127.0.0.1', port=self.port, log_level='warning', access_log=False,
|
|
294
|
-
timeout_graceful_shutdown=5))
|
|
296
|
+
log_config=None, timeout_graceful_shutdown=5))
|
|
295
297
|
|
|
296
298
|
def serve():
|
|
297
299
|
try:
|
|
@@ -36,8 +36,8 @@ class BaseCaptureMethod:
|
|
|
36
36
|
"""Capture a frame.
|
|
37
37
|
|
|
38
38
|
:param busy_wait: Seconds to wait when another caller owns the capture.
|
|
39
|
-
The default 0 returns None immediately
|
|
40
|
-
|
|
39
|
+
The default 0 returns None immediately. The task executor waits
|
|
40
|
+
briefly; one-off captures should wait longer.
|
|
41
41
|
"""
|
|
42
42
|
if self.exit_event.is_set():
|
|
43
43
|
return
|
|
@@ -151,3 +151,33 @@ ADB_KEY_MAP = {
|
|
|
151
151
|
'printscreen': 'KEYCODE_SYSRQ',
|
|
152
152
|
'print_screen': 'KEYCODE_SYSRQ',
|
|
153
153
|
}
|
|
154
|
+
|
|
155
|
+
XBUTTON1 = 0x0001
|
|
156
|
+
XBUTTON2 = 0x0002
|
|
157
|
+
MOUSEEVENTF_XDOWN = 0x0080
|
|
158
|
+
MOUSEEVENTF_XUP = 0x0100
|
|
159
|
+
|
|
160
|
+
WM_XBUTTONDOWN = 0x020B
|
|
161
|
+
WM_XBUTTONUP = 0x020C
|
|
162
|
+
MK_XBUTTON1 = 0x0020
|
|
163
|
+
MK_XBUTTON2 = 0x0040
|
|
164
|
+
|
|
165
|
+
MOUSE_BUTTON_MAP = {
|
|
166
|
+
'mouse4': XBUTTON1,
|
|
167
|
+
'xbutton1': XBUTTON1,
|
|
168
|
+
'mouse5': XBUTTON2,
|
|
169
|
+
'xbutton2': XBUTTON2,
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def is_mouse_button(key) -> bool:
|
|
174
|
+
if not isinstance(key, str):
|
|
175
|
+
return False
|
|
176
|
+
return key.strip().lower() in MOUSE_BUTTON_MAP
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def get_mouse_button(key) -> int:
|
|
180
|
+
if not isinstance(key, str):
|
|
181
|
+
return 0
|
|
182
|
+
return MOUSE_BUTTON_MAP.get(key.strip().lower(), 0)
|
|
183
|
+
|
|
@@ -6,7 +6,10 @@ import win32gui
|
|
|
6
6
|
|
|
7
7
|
from ok.device.capture_methods.base import BaseCaptureMethod
|
|
8
8
|
from ok.device.interaction_methods.base import BaseInteraction
|
|
9
|
-
from ok.device.interaction_methods.keys import
|
|
9
|
+
from ok.device.interaction_methods.keys import (
|
|
10
|
+
vk_key_dict, is_mouse_button, get_mouse_button,
|
|
11
|
+
XBUTTON1, MK_XBUTTON1, MK_XBUTTON2, WM_XBUTTONDOWN, WM_XBUTTONUP
|
|
12
|
+
)
|
|
10
13
|
from ok.util.logger import Logger
|
|
11
14
|
|
|
12
15
|
logger = Logger.get_logger(__name__)
|
|
@@ -37,12 +40,27 @@ class PostMessageInteraction(BaseInteraction):
|
|
|
37
40
|
def send_key_down(self, key, activate=True):
|
|
38
41
|
if activate:
|
|
39
42
|
self.try_activate()
|
|
43
|
+
if is_mouse_button(key):
|
|
44
|
+
btn = get_mouse_button(key)
|
|
45
|
+
mk = MK_XBUTTON1 if btn == XBUTTON1 else MK_XBUTTON2
|
|
46
|
+
wparam = win32api.MAKELONG(mk, btn)
|
|
47
|
+
pos = getattr(self, 'mouse_pos', (0, 0))
|
|
48
|
+
lparam = win32api.MAKELONG(int(pos[0]), int(pos[1]))
|
|
49
|
+
self.post(WM_XBUTTONDOWN, wparam, lparam)
|
|
50
|
+
return
|
|
40
51
|
vk_code = self.get_key_by_str(key)
|
|
41
52
|
lparam = self.make_lparam(vk_code, is_up=False)
|
|
42
53
|
self.post(win32con.WM_KEYDOWN, vk_code, lparam)
|
|
43
54
|
|
|
44
55
|
def send_key_up(self, key):
|
|
45
56
|
# logger.debug(f'send_key_up {key}')
|
|
57
|
+
if is_mouse_button(key):
|
|
58
|
+
btn = get_mouse_button(key)
|
|
59
|
+
wparam = win32api.MAKELONG(0, btn)
|
|
60
|
+
pos = getattr(self, 'mouse_pos', (0, 0))
|
|
61
|
+
lparam = win32api.MAKELONG(int(pos[0]), int(pos[1]))
|
|
62
|
+
self.post(WM_XBUTTONUP, wparam, lparam)
|
|
63
|
+
return
|
|
46
64
|
vk_code = self.get_key_by_str(key)
|
|
47
65
|
lparam = self.make_lparam(vk_code, is_up=True)
|
|
48
66
|
self.post(win32con.WM_KEYUP, vk_code, lparam)
|
|
@@ -215,6 +233,9 @@ class PostMessageInteraction(BaseInteraction):
|
|
|
215
233
|
self._dynamic_target_hwnd = target_hwnd
|
|
216
234
|
|
|
217
235
|
local_x, local_y = win32gui.ScreenToClient(target_hwnd, (abs_x, abs_y))
|
|
236
|
+
# Button messages must use the same target-client coordinates as
|
|
237
|
+
# the preceding move, including when a child window is selected.
|
|
238
|
+
self.mouse_pos = (local_x, local_y)
|
|
218
239
|
|
|
219
240
|
hwnd_descriptions = []
|
|
220
241
|
for index, hwnd_info in enumerate(hwnds):
|
|
@@ -233,7 +254,8 @@ class PostMessageInteraction(BaseInteraction):
|
|
|
233
254
|
except Exception as e:
|
|
234
255
|
logger.error(f'update_mouse_pos conversion error targeting {base_hwnd}', e)
|
|
235
256
|
self._dynamic_target_hwnd = base_hwnd
|
|
236
|
-
|
|
257
|
+
self.mouse_pos = (int(x), int(y))
|
|
258
|
+
return win32api.MAKELONG(*self.mouse_pos)
|
|
237
259
|
|
|
238
260
|
def mouse_up(self, key="left"):
|
|
239
261
|
if key == "left":
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
import ctypes
|
|
1
2
|
import time
|
|
2
3
|
|
|
3
4
|
import pydirectinput
|
|
4
5
|
|
|
5
6
|
from ok.device.capture_methods.base import BaseCaptureMethod
|
|
6
7
|
from ok.device.interaction_methods.base import BaseInteraction
|
|
7
|
-
from ok.device.interaction_methods.keys import
|
|
8
|
+
from ok.device.interaction_methods.keys import (
|
|
9
|
+
normalize_pydirect_key, is_mouse_button, get_mouse_button,
|
|
10
|
+
MOUSEEVENTF_XDOWN, MOUSEEVENTF_XUP
|
|
11
|
+
)
|
|
8
12
|
from ok.util.logger import Logger
|
|
9
13
|
from ok.util.process import is_admin
|
|
10
14
|
|
|
11
15
|
logger = Logger.get_logger(__name__)
|
|
16
|
+
user32 = ctypes.windll.user32
|
|
12
17
|
|
|
13
18
|
class PyDirectInteraction(BaseInteraction):
|
|
14
19
|
|
|
@@ -35,6 +40,12 @@ class PyDirectInteraction(BaseInteraction):
|
|
|
35
40
|
if not self.clickable():
|
|
36
41
|
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
37
42
|
return
|
|
43
|
+
if is_mouse_button(key):
|
|
44
|
+
btn = get_mouse_button(key)
|
|
45
|
+
user32.mouse_event(MOUSEEVENTF_XDOWN, 0, 0, btn, 0)
|
|
46
|
+
time.sleep(down_time)
|
|
47
|
+
user32.mouse_event(MOUSEEVENTF_XUP, 0, 0, btn, 0)
|
|
48
|
+
return
|
|
38
49
|
key = normalize_pydirect_key(key)
|
|
39
50
|
pydirectinput.keyDown(key)
|
|
40
51
|
time.sleep(down_time)
|
|
@@ -44,8 +55,22 @@ class PyDirectInteraction(BaseInteraction):
|
|
|
44
55
|
if not self.clickable():
|
|
45
56
|
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
46
57
|
return
|
|
58
|
+
if is_mouse_button(key):
|
|
59
|
+
btn = get_mouse_button(key)
|
|
60
|
+
user32.mouse_event(MOUSEEVENTF_XDOWN, 0, 0, btn, 0)
|
|
61
|
+
return
|
|
47
62
|
pydirectinput.keyDown(normalize_pydirect_key(key))
|
|
48
63
|
|
|
64
|
+
def send_key_up(self, key):
|
|
65
|
+
if not self.clickable():
|
|
66
|
+
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
67
|
+
return
|
|
68
|
+
if is_mouse_button(key):
|
|
69
|
+
btn = get_mouse_button(key)
|
|
70
|
+
user32.mouse_event(MOUSEEVENTF_XUP, 0, 0, btn, 0)
|
|
71
|
+
return
|
|
72
|
+
pydirectinput.keyUp(normalize_pydirect_key(key))
|
|
73
|
+
|
|
49
74
|
def scroll(self, x, y, scroll_amount):
|
|
50
75
|
import mouse
|
|
51
76
|
if scroll_amount < 0:
|
|
@@ -62,12 +87,6 @@ class PyDirectInteraction(BaseInteraction):
|
|
|
62
87
|
time.sleep(0.001)
|
|
63
88
|
time.sleep(0.02)
|
|
64
89
|
|
|
65
|
-
def send_key_up(self, key):
|
|
66
|
-
if not self.clickable():
|
|
67
|
-
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
68
|
-
return
|
|
69
|
-
pydirectinput.keyUp(normalize_pydirect_key(key))
|
|
70
|
-
|
|
71
90
|
def move(self, x, y):
|
|
72
91
|
import mouse
|
|
73
92
|
if not self.clickable():
|
|
@@ -2,6 +2,7 @@ import time
|
|
|
2
2
|
|
|
3
3
|
from ok.device.capture_methods.base import BaseCaptureMethod
|
|
4
4
|
from ok.device.interaction_methods.base import BaseInteraction
|
|
5
|
+
from ok.device.interaction_methods.keys import is_mouse_button, get_mouse_button, XBUTTON1
|
|
5
6
|
from ok.util.logger import Logger
|
|
6
7
|
from ok.util.process import is_admin
|
|
7
8
|
|
|
@@ -53,36 +54,37 @@ class PynputInteraction(BaseInteraction):
|
|
|
53
54
|
except KeyError:
|
|
54
55
|
return key
|
|
55
56
|
|
|
56
|
-
def
|
|
57
|
+
def _key_controller(self, key):
|
|
58
|
+
if is_mouse_button(key):
|
|
59
|
+
from pynput import mouse
|
|
60
|
+
return mouse.Controller(), self.get_mouse_button(key)
|
|
57
61
|
from pynput import keyboard
|
|
62
|
+
return keyboard.Controller(), self._parse_key(str(key))
|
|
63
|
+
|
|
64
|
+
def send_key(self, key, down_time=0.01):
|
|
58
65
|
if not self.clickable():
|
|
59
66
|
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
60
67
|
return
|
|
61
68
|
|
|
62
|
-
controller =
|
|
63
|
-
parsed_key = self._parse_key(str(key))
|
|
69
|
+
controller, parsed_key = self._key_controller(key)
|
|
64
70
|
controller.press(parsed_key)
|
|
65
71
|
time.sleep(down_time)
|
|
66
72
|
controller.release(parsed_key)
|
|
67
73
|
|
|
68
74
|
def send_key_down(self, key):
|
|
69
|
-
from pynput import keyboard
|
|
70
75
|
if not self.clickable():
|
|
71
76
|
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
72
77
|
return
|
|
73
78
|
|
|
74
|
-
controller =
|
|
75
|
-
parsed_key = self._parse_key(str(key))
|
|
79
|
+
controller, parsed_key = self._key_controller(key)
|
|
76
80
|
controller.press(parsed_key)
|
|
77
81
|
|
|
78
82
|
def send_key_up(self, key):
|
|
79
|
-
from pynput import keyboard
|
|
80
83
|
if not self.clickable():
|
|
81
84
|
logger.error(f"can't click on {key}, because capture is not clickable")
|
|
82
85
|
return
|
|
83
86
|
|
|
84
|
-
controller =
|
|
85
|
-
parsed_key = self._parse_key(str(key))
|
|
87
|
+
controller, parsed_key = self._key_controller(key)
|
|
86
88
|
controller.release(parsed_key)
|
|
87
89
|
|
|
88
90
|
def scroll(self, x, y, scroll_amount):
|
|
@@ -184,6 +186,8 @@ class PynputInteraction(BaseInteraction):
|
|
|
184
186
|
|
|
185
187
|
def get_mouse_button(self, key):
|
|
186
188
|
from pynput import mouse
|
|
189
|
+
if is_mouse_button(key):
|
|
190
|
+
return mouse.Button.x1 if get_mouse_button(key) == XBUTTON1 else mouse.Button.x2
|
|
187
191
|
if key == "right":
|
|
188
192
|
return mouse.Button.right
|
|
189
193
|
if key == "middle":
|
|
@@ -15,6 +15,9 @@ from ok.util.window import ratio_text_to_number
|
|
|
15
15
|
|
|
16
16
|
logger = Logger.get_logger(__name__)
|
|
17
17
|
|
|
18
|
+
# How long next_frame() waits for another caller to finish its capture request.
|
|
19
|
+
NEXT_FRAME_BUSY_WAIT = 0.1
|
|
20
|
+
|
|
18
21
|
|
|
19
22
|
class ExecutorJob:
|
|
20
23
|
"""A callable that runs once on the executor thread, outside the task queue.
|
|
@@ -321,7 +324,13 @@ class TaskExecutor:
|
|
|
321
324
|
if time_out is not None and time.time() - start >= time_out:
|
|
322
325
|
return None
|
|
323
326
|
if self.can_capture():
|
|
324
|
-
|
|
327
|
+
# A one-off capture on another thread (debug screenshot,
|
|
328
|
+
# template capture) owns the request for about one frame.
|
|
329
|
+
# Waiting for it is far cheaper than the retry sleep below.
|
|
330
|
+
busy_wait = NEXT_FRAME_BUSY_WAIT
|
|
331
|
+
if time_out is not None:
|
|
332
|
+
busy_wait = min(busy_wait, max(0, time_out - (time.time() - start)))
|
|
333
|
+
frame = self.method.get_frame(busy_wait=busy_wait)
|
|
325
334
|
if frame is not None:
|
|
326
335
|
height, width = frame.shape[:2]
|
|
327
336
|
if height <= 0 or width <= 0:
|
|
@@ -29,7 +29,8 @@ VALID_NAMED_KEYS = {
|
|
|
29
29
|
'caps_lock', 'num_lock', 'scroll_lock', 'print_screen',
|
|
30
30
|
'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12',
|
|
31
31
|
'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'num9',
|
|
32
|
-
'windows', 'win', 'command', 'cmd', 'cmd_l', 'cmd_r', 'meta'
|
|
32
|
+
'windows', 'win', 'command', 'cmd', 'cmd_l', 'cmd_r', 'meta',
|
|
33
|
+
'mouse4', 'mouse5', 'xbutton1', 'xbutton2'
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
logger = Logger.get_logger(__name__)
|
|
@@ -12,7 +12,10 @@ def init_ok(config):
|
|
|
12
12
|
config['debug'] = True
|
|
13
13
|
config['analytics'] = None
|
|
14
14
|
config['check_mutex'] = False
|
|
15
|
-
|
|
15
|
+
try:
|
|
16
|
+
print(f'OKTestRunner init_ok config: {config}')
|
|
17
|
+
except UnicodeEncodeError:
|
|
18
|
+
print(f'OKTestRunner init_ok config: {str(config).encode("ascii", errors="replace").decode("ascii")}')
|
|
16
19
|
ok = OK(config)
|
|
17
20
|
ok.task_executor.debug_mode = True
|
|
18
21
|
ok.device_manager.capture_method = ImageCaptureMethod(
|
|
@@ -66,6 +66,8 @@ class AboutTab(Tab):
|
|
|
66
66
|
{"name": self.tr("Onmyoji"), "url": "https://github.com/YunLiuZ/ok-Onmyoji", "website": "https://ok-script.com/ok-onmyoji/"},
|
|
67
67
|
{"name": self.tr("Arknights: Endfield"), "url": "https://github.com/AliceJump/ok-end-field", "website": "https://ok-script.com/ok-end-field/"},
|
|
68
68
|
{"name": self.tr("Neverness to Everness"), "url": "https://github.com/BnanZ0/ok-neverness-to-everness", "website": "https://ok-script.com/ok-nte/"},
|
|
69
|
+
{"name": self.tr("BrownDust II"), "url": "https://github.com/GodRaymond233/ok-bd2"},
|
|
70
|
+
{"name": self.tr("Azur Promilia"), "url": "https://github.com/longer-sausage/OK-AzurPromilia"},
|
|
69
71
|
]
|
|
70
72
|
|
|
71
73
|
def normalize_url(url):
|
|
Binary file
|
|
@@ -93,6 +93,14 @@
|
|
|
93
93
|
<source>Disclaimer</source>
|
|
94
94
|
<translation>Disclaimer</translation>
|
|
95
95
|
</message>
|
|
96
|
+
<message>
|
|
97
|
+
<source>BrownDust II</source>
|
|
98
|
+
<translation>BrownDust II</translation>
|
|
99
|
+
</message>
|
|
100
|
+
<message>
|
|
101
|
+
<source>Azur Promilia</source>
|
|
102
|
+
<translation>Azur Promilia</translation>
|
|
103
|
+
</message>
|
|
96
104
|
</context>
|
|
97
105
|
<context>
|
|
98
106
|
<name>ActWindow</name>
|
|
Binary file
|
|
@@ -93,6 +93,14 @@
|
|
|
93
93
|
<source>Disclaimer</source>
|
|
94
94
|
<translation>Aviso legal</translation>
|
|
95
95
|
</message>
|
|
96
|
+
<message>
|
|
97
|
+
<source>BrownDust II</source>
|
|
98
|
+
<translation>BrownDust II</translation>
|
|
99
|
+
</message>
|
|
100
|
+
<message>
|
|
101
|
+
<source>Azur Promilia</source>
|
|
102
|
+
<translation>Azur Promilia</translation>
|
|
103
|
+
</message>
|
|
96
104
|
</context>
|
|
97
105
|
<context>
|
|
98
106
|
<name>ActWindow</name>
|
|
Binary file
|
|
@@ -93,6 +93,14 @@
|
|
|
93
93
|
<source>Disclaimer</source>
|
|
94
94
|
<translation>免責事項</translation>
|
|
95
95
|
</message>
|
|
96
|
+
<message>
|
|
97
|
+
<source>BrownDust II</source>
|
|
98
|
+
<translation>ブラウンダスト2</translation>
|
|
99
|
+
</message>
|
|
100
|
+
<message>
|
|
101
|
+
<source>Azur Promilia</source>
|
|
102
|
+
<translation>アズールプロミリア</translation>
|
|
103
|
+
</message>
|
|
96
104
|
</context>
|
|
97
105
|
<context>
|
|
98
106
|
<name>ActWindow</name>
|
|
@@ -3284,4 +3292,4 @@
|
|
|
3284
3292
|
<translation>いいえ</translation>
|
|
3285
3293
|
</message>
|
|
3286
3294
|
</context>
|
|
3287
|
-
</TS>
|
|
3295
|
+
</TS>
|
|
Binary file
|
|
@@ -93,6 +93,14 @@
|
|
|
93
93
|
<source>Disclaimer</source>
|
|
94
94
|
<translation>면책 조항</translation>
|
|
95
95
|
</message>
|
|
96
|
+
<message>
|
|
97
|
+
<source>BrownDust II</source>
|
|
98
|
+
<translation>브라운더스트2</translation>
|
|
99
|
+
</message>
|
|
100
|
+
<message>
|
|
101
|
+
<source>Azur Promilia</source>
|
|
102
|
+
<translation>아주르 프로밀리아</translation>
|
|
103
|
+
</message>
|
|
96
104
|
</context>
|
|
97
105
|
<context>
|
|
98
106
|
<name>ActWindow</name>
|
|
@@ -3293,4 +3301,4 @@
|
|
|
3293
3301
|
<translation>아니요</translation>
|
|
3294
3302
|
</message>
|
|
3295
3303
|
</context>
|
|
3296
|
-
</TS>
|
|
3304
|
+
</TS>
|
|
Binary file
|
|
@@ -93,6 +93,14 @@
|
|
|
93
93
|
<source>Disclaimer</source>
|
|
94
94
|
<translation>免责声明</translation>
|
|
95
95
|
</message>
|
|
96
|
+
<message>
|
|
97
|
+
<source>BrownDust II</source>
|
|
98
|
+
<translation>棕色尘埃 2</translation>
|
|
99
|
+
</message>
|
|
100
|
+
<message>
|
|
101
|
+
<source>Azur Promilia</source>
|
|
102
|
+
<translation>蓝色星原:旅谣</translation>
|
|
103
|
+
</message>
|
|
96
104
|
</context>
|
|
97
105
|
<context>
|
|
98
106
|
<name>ActWindow</name>
|
|
Binary file
|
|
@@ -93,6 +93,14 @@
|
|
|
93
93
|
<source>Disclaimer</source>
|
|
94
94
|
<translation>免責聲明</translation>
|
|
95
95
|
</message>
|
|
96
|
+
<message>
|
|
97
|
+
<source>BrownDust II</source>
|
|
98
|
+
<translation>棕色塵埃 2</translation>
|
|
99
|
+
</message>
|
|
100
|
+
<message>
|
|
101
|
+
<source>Azur Promilia</source>
|
|
102
|
+
<translation>藍色星原:旅謠</translation>
|
|
103
|
+
</message>
|
|
96
104
|
</context>
|
|
97
105
|
<context>
|
|
98
106
|
<name>ActWindow</name>
|