computer-use-ootb-internal 0.0.136__py3-none-any.whl → 0.0.137__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,87 +1,87 @@
1
- # src/computer_use_ootb_internal/preparation/star_rail_prepare.py
2
- import time
3
- import platform
4
- import subprocess # Added for taskkill
5
- import pyautogui
6
- import webbrowser
7
- import logging # Use logging instead of print for better practice
8
-
9
- # Set up logging for this module if needed, or rely on root logger
10
- log = logging.getLogger(__name__)
11
-
12
- def run_preparation(state):
13
- """
14
- Performs environment preparation specific to Star Rail on Windows.
15
- Closes existing Edge browsers, opens the specified URL in a new Edge instance,
16
- and performs initial clicks.
17
- """
18
- if platform.system() != "Windows":
19
- log.info("Star Rail preparation skipped: Not running on Windows.")
20
- return
21
-
22
- log.info("Star Rail preparation: Starting environment setup on Windows...")
23
- url = "https://sr.mihoyo.com/cloud/#/" # Consider making this configurable later
24
- browser_opened = False
25
- try:
26
- # Attempt to close existing Microsoft Edge processes
27
- log.info("Attempting to close existing Microsoft Edge processes...")
28
- try:
29
- # /F forces termination, /IM specifies image name
30
- result = subprocess.run(['taskkill', '/F', '/IM', 'msedge.exe'],
31
- capture_output=True, text=True, check=False)
32
- if result.returncode == 0:
33
- log.info("Successfully sent termination signal to msedge.exe processes.")
34
- elif "not found" in result.stderr.lower() or "not found" in result.stdout.lower():
35
- log.info("No running msedge.exe processes found to close.")
36
- else:
37
- log.warning(f"taskkill command finished with return code {result.returncode}. Output: {result.stdout} Stderr: {result.stderr}")
38
- time.sleep(2) # Give processes time to close
39
- except FileNotFoundError:
40
- log.error("Error: 'taskkill' command not found. Make sure it's in the system PATH.")
41
- except Exception as e:
42
- log.error(f"Error occurred while trying to close Edge: {e}", exc_info=True)
43
-
44
- # Use only webbrowser.open
45
- log.info(f"Attempting to open {url} using webbrowser.open()...")
46
- if webbrowser.open(url):
47
- log.info(f"Successfully requested browser to open {url} via webbrowser.open().")
48
- browser_opened = True
49
- # Keep original sleep time for browser load before clicks
50
- time.sleep(5)
51
- else:
52
- log.warning("webbrowser.open() returned False, indicating potential failure.")
53
-
54
- if not browser_opened:
55
- log.error("Failed to confirm browser opening via webbrowser.open(). Will still attempt clicks.")
56
-
57
- # Add pyautogui click after attempting to open the browser
58
- log.info("Proceeding with pyautogui actions...")
59
- time.sleep(5) # Wait time for the browser to load
60
-
61
- # Get screen size
62
- screen_width, screen_height = pyautogui.size()
63
- log.info(f"Detected screen size: {screen_width}x{screen_height}")
64
-
65
- # Calculate click coordinates based on a reference resolution (e.g., 1280x720)
66
- # TODO: Make these coordinates more robust or configurable
67
- click_x = int(screen_width * (1036 / 1280))
68
- click_y = int(screen_height * (500 / 720))
69
- log.info(f"Calculated click coordinates: ({click_x}, {click_y})")
70
-
71
- # Disable failsafe before clicking
72
- pyautogui.FAILSAFE = False
73
- log.info("PyAutoGUI failsafe temporarily disabled.")
74
-
75
- log.info(f"Clicking at coordinates: ({click_x}, {click_y})")
76
- pyautogui.click(click_x, click_y)
77
- time.sleep(2)
78
- pyautogui.click(click_x, click_y) # Double click?
79
-
80
- log.info("Star Rail preparation clicks completed.")
81
-
82
- except Exception as e:
83
- log.error(f"Error during Star Rail preparation (browser/click): {e}", exc_info=True)
84
- finally:
85
- # Ensure failsafe is re-enabled
86
- pyautogui.FAILSAFE = True
1
+ # src/computer_use_ootb_internal/preparation/star_rail_prepare.py
2
+ import time
3
+ import platform
4
+ import subprocess # Added for taskkill
5
+ import pyautogui
6
+ import webbrowser
7
+ import logging # Use logging instead of print for better practice
8
+
9
+ # Set up logging for this module if needed, or rely on root logger
10
+ log = logging.getLogger(__name__)
11
+
12
+ def run_preparation(state):
13
+ """
14
+ Performs environment preparation specific to Star Rail on Windows.
15
+ Closes existing Edge browsers, opens the specified URL in a new Edge instance,
16
+ and performs initial clicks.
17
+ """
18
+ if platform.system() != "Windows":
19
+ log.info("Star Rail preparation skipped: Not running on Windows.")
20
+ return
21
+
22
+ log.info("Star Rail preparation: Starting environment setup on Windows...")
23
+ url = "https://sr.mihoyo.com/cloud/#/" # Consider making this configurable later
24
+ browser_opened = False
25
+ try:
26
+ # Attempt to close existing Microsoft Edge processes
27
+ log.info("Attempting to close existing Microsoft Edge processes...")
28
+ try:
29
+ # /F forces termination, /IM specifies image name
30
+ result = subprocess.run(['taskkill', '/F', '/IM', 'msedge.exe'],
31
+ capture_output=True, text=True, check=False)
32
+ if result.returncode == 0:
33
+ log.info("Successfully sent termination signal to msedge.exe processes.")
34
+ elif "not found" in result.stderr.lower() or "not found" in result.stdout.lower():
35
+ log.info("No running msedge.exe processes found to close.")
36
+ else:
37
+ log.warning(f"taskkill command finished with return code {result.returncode}. Output: {result.stdout} Stderr: {result.stderr}")
38
+ time.sleep(2) # Give processes time to close
39
+ except FileNotFoundError:
40
+ log.error("Error: 'taskkill' command not found. Make sure it's in the system PATH.")
41
+ except Exception as e:
42
+ log.error(f"Error occurred while trying to close Edge: {e}", exc_info=True)
43
+
44
+ # Use only webbrowser.open
45
+ log.info(f"Attempting to open {url} using webbrowser.open()...")
46
+ if webbrowser.open(url):
47
+ log.info(f"Successfully requested browser to open {url} via webbrowser.open().")
48
+ browser_opened = True
49
+ # Keep original sleep time for browser load before clicks
50
+ time.sleep(5)
51
+ else:
52
+ log.warning("webbrowser.open() returned False, indicating potential failure.")
53
+
54
+ if not browser_opened:
55
+ log.error("Failed to confirm browser opening via webbrowser.open(). Will still attempt clicks.")
56
+
57
+ # Add pyautogui click after attempting to open the browser
58
+ log.info("Proceeding with pyautogui actions...")
59
+ time.sleep(5) # Wait time for the browser to load
60
+
61
+ # Get screen size
62
+ screen_width, screen_height = pyautogui.size()
63
+ log.info(f"Detected screen size: {screen_width}x{screen_height}")
64
+
65
+ # Calculate click coordinates based on a reference resolution (e.g., 1280x720)
66
+ # TODO: Make these coordinates more robust or configurable
67
+ click_x = int(screen_width * (1036 / 1280))
68
+ click_y = int(screen_height * (500 / 720))
69
+ log.info(f"Calculated click coordinates: ({click_x}, {click_y})")
70
+
71
+ # Disable failsafe before clicking
72
+ pyautogui.FAILSAFE = False
73
+ log.info("PyAutoGUI failsafe temporarily disabled.")
74
+
75
+ log.info(f"Clicking at coordinates: ({click_x}, {click_y})")
76
+ pyautogui.click(click_x, click_y)
77
+ time.sleep(2)
78
+ pyautogui.click(click_x, click_y) # Double click?
79
+
80
+ log.info("Star Rail preparation clicks completed.")
81
+
82
+ except Exception as e:
83
+ log.error(f"Error during Star Rail preparation (browser/click): {e}", exc_info=True)
84
+ finally:
85
+ # Ensure failsafe is re-enabled
86
+ pyautogui.FAILSAFE = True
87
87
  log.info("PyAutoGUI failsafe re-enabled.")
@@ -3,6 +3,7 @@ import time
3
3
  import json
4
4
  import platform
5
5
  import uuid
6
+ import base64
6
7
  import datetime
7
8
  from datetime import datetime, timedelta, timezone
8
9
 
@@ -74,7 +75,10 @@ def simple_teachmode_sampling_loop(
74
75
  # yield {"role": "assistant", "content": "screenshot", "type": "action", "action_type": "screenshot"}
75
76
 
76
77
  if is_image_path(sc_path):
77
- yield {"role": "assistant", "content": sc_path, "type": "image", "action_type": "screenshot"}
78
+ # yield {"role": "assistant", "content": sc_path, "type": "image", "action_type": "screenshot"}
79
+ with open(sc_path, "rb") as image_file:
80
+ sc_base64 = base64.b64encode(image_file.read()).decode('utf-8')
81
+ yield {"role": "assistant", "content": sc_base64, "type": "image_base64", "action_type": "screenshot"}
78
82
 
79
83
  payload = {
80
84
  "task_id": unique_task_id,
@@ -1,195 +1,195 @@
1
- # src/computer_use_ootb_internal/service_manager.py
2
- import sys
3
- import os
4
- import inspect
5
- import subprocess
6
- import ctypes
7
- import platform
8
- import time
9
-
10
- # Constants need to match guard_service.py
11
- _SERVICE_NAME = "OOTBGuardService"
12
- _SERVICE_DISPLAY_NAME = "OOTB Guard Service"
13
- _TASK_NAME_PREFIX = "OOTB_UserLogon_" # Must match guard_service.py
14
-
15
- def is_admin():
16
- """Check if the script is running with administrative privileges."""
17
- if platform.system() != "Windows":
18
- return False # Only applicable on Windows
19
- try:
20
- return ctypes.windll.shell32.IsUserAnAdmin()
21
- except:
22
- return False
23
-
24
- def get_service_module_path():
25
- """Gets the absolute path to the guard_service.py module."""
26
- # Find the path relative to this script's location
27
- # This assumes service_manager.py and guard_service.py are in the same installed package directory
28
- try:
29
- current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
30
- service_module = os.path.join(current_dir, "guard_service.py")
31
- if not os.path.exists(service_module):
32
- raise FileNotFoundError(f"guard_service.py not found adjacent to service_manager.py in {current_dir}")
33
- return service_module
34
- except Exception as e:
35
- # Fallback if inspect fails (e.g., in some frozen environments)
36
- # Try finding it relative to the script itself? Unreliable.
37
- # Let's try sys.prefix - might work in standard venv/conda installs
38
- try:
39
- # sys.prefix points to the environment root (e.g., C:\path\to\env)
40
- # Package likely installed in Lib\site-packages\<package_name>
41
- # This depends heavily on installation layout
42
- package_name = __name__.split('.')[0] # Should be 'computer_use_ootb_internal'
43
- site_packages_path = os.path.join(sys.prefix, 'Lib', 'site-packages')
44
- module_dir = os.path.join(site_packages_path, package_name)
45
- service_module = os.path.join(module_dir, "guard_service.py")
46
- if os.path.exists(service_module):
47
- print(f"Warning: Found service module via sys.prefix fallback: {service_module}")
48
- return service_module
49
- else:
50
- raise FileNotFoundError(f"guard_service.py not found via inspect or sys.prefix fallback (checked {module_dir})")
51
- except Exception as fallback_e:
52
- raise FileNotFoundError(f"Could not find guard_service.py using inspect ({e}) or sys.prefix ({fallback_e}). Check installation.")
53
-
54
-
55
- def run_service_command(command_args, check_errors=True):
56
- """Runs the guard_service.py script with specified command-line args."""
57
- if not is_admin():
58
- print("Error: Administrative privileges are required to manage the service.", file=sys.stderr)
59
- print("Please run this command from an Administrator Command Prompt or PowerShell.", file=sys.stderr)
60
- return False
61
-
62
- try:
63
- python_exe = sys.executable # Use the same python that's running this script
64
- service_script = get_service_module_path()
65
- except FileNotFoundError as e:
66
- print(f"Error: {e}", file=sys.stderr)
67
- return False
68
-
69
- # Quote paths if they contain spaces
70
- if " " in python_exe and not python_exe.startswith('"'):
71
- python_exe = f'"{python_exe}"'
72
- if " " in service_script and not service_script.startswith('"'):
73
- service_script = f'"{service_script}"'
74
-
75
- # Construct command using list to avoid shell quoting issues
76
- cmd = [sys.executable, get_service_module_path()] + command_args
77
- print(f"Executing command: {' '.join(cmd)}")
78
-
79
- try:
80
- # Run the command. Use shell=False with list of args.
81
- # Capture output to check for specific errors if needed, but print it too.
82
- result = subprocess.run(cmd, capture_output=True, text=True, check=check_errors, encoding='utf-8')
83
- if result.stdout:
84
- print("Command STDOUT:")
85
- print(result.stdout)
86
- if result.stderr:
87
- print("Command STDERR:")
88
- print(result.stderr)
89
- print(f"Command {' '.join(command_args)} executed successfully.")
90
- return True
91
- except FileNotFoundError as e:
92
- print(f"Error: Could not find Python executable or service script during execution.", file=sys.stderr)
93
- print(f" Details: {e}", file=sys.stderr)
94
- return False
95
- except subprocess.CalledProcessError as e:
96
- print(f"Error executing service command {' '.join(command_args)} (Exit Code {e.returncode}).", file=sys.stderr)
97
- if e.stdout:
98
- print("Subprocess STDOUT:")
99
- print(e.stdout)
100
- if e.stderr:
101
- print("Subprocess STDERR:")
102
- print(e.stderr)
103
- return False
104
- except Exception as e:
105
- print(f"An unexpected error occurred running service command: {e}", file=sys.stderr)
106
- return False
107
-
108
- # --- Add cleanup helpers ---
109
- def _run_powershell_cleanup_command(command):
110
- """Executes a PowerShell command specifically for cleanup, ignoring most errors."""
111
- if platform.system() != "Windows": return True # Skip on non-windows
112
- print(f"Executing PowerShell Cleanup: {command}")
113
- try:
114
- # Use check=False, don't capture output unless needed for debug
115
- subprocess.run(
116
- ["powershell.exe", "-NoProfile", "-NonInteractive", "-Command", command],
117
- check=False, # Don't throw error if command fails (e.g., no tasks found)
118
- stdout=subprocess.DEVNULL, # Suppress stdout
119
- stderr=subprocess.DEVNULL # Suppress stderr
120
- )
121
- return True # Assume success for cleanup flow
122
- except Exception as e:
123
- print(f"Warning: PowerShell cleanup command failed: {e}", file=sys.stderr)
124
- return False # Indicate potential issue
125
-
126
- def _cleanup_scheduled_tasks():
127
- """Removes all OOTB user logon scheduled tasks."""
128
- print("Attempting to remove any existing OOTB user logon scheduled tasks...")
129
- # Use -like operator and wildcard
130
- # Use try-catch within PowerShell for robustness
131
- command = f"""
132
- $tasks = Get-ScheduledTask | Where-Object {{ $_.TaskName -like '{_TASK_NAME_PREFIX}*' }}
133
- if ($tasks) {{
134
- Write-Host "Found $($tasks.Count) OOTB logon tasks to remove."
135
- $tasks | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue
136
- Write-Host "OOTB logon task removal attempted."
137
- }} else {{
138
- Write-Host "No OOTB logon tasks found to remove."
139
- }}
140
- """
141
- _run_powershell_cleanup_command(command)
142
- # --- End cleanup helpers ---
143
-
144
- def install_and_start():
145
- """Installs and starts the Guard Service."""
146
- print(f"Attempting to install service: '{_SERVICE_NAME}' ('{_SERVICE_DISPLAY_NAME}')")
147
- # Call 'install' command first.
148
- # We pass check_errors=True to stop if installation fails fundamentally.
149
- install_success = run_service_command(['--startup', 'auto', 'install'], check_errors=True)
150
-
151
- if install_success:
152
- # Note: Even if install_success is True, pywin32 might have printed internal errors
153
- # like 'service already installed'. We proceed to start anyway in that case.
154
- print(f"\nInstallation command finished. Attempting to start service: '{_SERVICE_NAME}' (waiting a few seconds first)")
155
- time.sleep(3) # Give SCM time to register the install/update
156
- start_success = run_service_command(['start'], check_errors=True)
157
-
158
- if start_success:
159
- # Similar caveat: start might succeed according to subprocess, but pywin32 could print internal errors.
160
- print(f"\nService '{_SERVICE_NAME}' install command executed and start command executed.")
161
- print(f"Please verify service status in 'services.msc' and check logs.")
162
- else:
163
- # This path is taken if run_service_command returned False (subprocess error occurred)
164
- print(f"\nService '{_SERVICE_NAME}' installed/updated but the 'start' command failed with an error.", file=sys.stderr)
165
- print(f" Check output above, service logs ('C:\ProgramData\OOTBGuardService\guard_post_mode.log'), or Windows Event Viewer.", file=sys.stderr)
166
- else:
167
- # This path is taken if the initial 'install' command failed critically (subprocess error)
168
- print(f"\nService '{_SERVICE_NAME}' installation failed critically. See errors above.", file=sys.stderr)
169
-
170
-
171
- def stop_and_remove():
172
- """Stops and removes the Guard Service and associated scheduled tasks."""
173
- print(f"Attempting to stop service: '{_SERVICE_NAME}' (will ignore errors if not running)")
174
- # Run stop first, ignore errors (check_errors=False)
175
- run_service_command(['stop'], check_errors=False)
176
- time.sleep(2) # Give service time to stop
177
-
178
- print(f"\nAttempting to remove service: '{_SERVICE_NAME}'")
179
- remove_success = run_service_command(['remove']) # Check if removal command itself failed
180
-
181
- # Always attempt task cleanup, even if service removal had issues
182
- _cleanup_scheduled_tasks()
183
-
184
- if remove_success:
185
- print(f"\nService '{_SERVICE_NAME}' stopped (if running) and removed successfully. Associated logon tasks cleanup attempted.")
186
- else:
187
- print(f"\nService '{_SERVICE_NAME}' removal command failed.", file=sys.stderr)
188
- # Make sure to mention cleanup was still attempted
189
- print(f" Associated logon tasks cleanup attempted.", file=sys.stderr)
190
- print(f" Ensure the service was stopped first, or check permissions.", file=sys.stderr)
191
-
192
- if __name__ == '__main__':
193
- # Allow calling functions directly for testing if needed
194
- print("This script provides service management commands.")
1
+ # src/computer_use_ootb_internal/service_manager.py
2
+ import sys
3
+ import os
4
+ import inspect
5
+ import subprocess
6
+ import ctypes
7
+ import platform
8
+ import time
9
+
10
+ # Constants need to match guard_service.py
11
+ _SERVICE_NAME = "OOTBGuardService"
12
+ _SERVICE_DISPLAY_NAME = "OOTB Guard Service"
13
+ _TASK_NAME_PREFIX = "OOTB_UserLogon_" # Must match guard_service.py
14
+
15
+ def is_admin():
16
+ """Check if the script is running with administrative privileges."""
17
+ if platform.system() != "Windows":
18
+ return False # Only applicable on Windows
19
+ try:
20
+ return ctypes.windll.shell32.IsUserAnAdmin()
21
+ except:
22
+ return False
23
+
24
+ def get_service_module_path():
25
+ """Gets the absolute path to the guard_service.py module."""
26
+ # Find the path relative to this script's location
27
+ # This assumes service_manager.py and guard_service.py are in the same installed package directory
28
+ try:
29
+ current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
30
+ service_module = os.path.join(current_dir, "guard_service.py")
31
+ if not os.path.exists(service_module):
32
+ raise FileNotFoundError(f"guard_service.py not found adjacent to service_manager.py in {current_dir}")
33
+ return service_module
34
+ except Exception as e:
35
+ # Fallback if inspect fails (e.g., in some frozen environments)
36
+ # Try finding it relative to the script itself? Unreliable.
37
+ # Let's try sys.prefix - might work in standard venv/conda installs
38
+ try:
39
+ # sys.prefix points to the environment root (e.g., C:\path\to\env)
40
+ # Package likely installed in Lib\site-packages\<package_name>
41
+ # This depends heavily on installation layout
42
+ package_name = __name__.split('.')[0] # Should be 'computer_use_ootb_internal'
43
+ site_packages_path = os.path.join(sys.prefix, 'Lib', 'site-packages')
44
+ module_dir = os.path.join(site_packages_path, package_name)
45
+ service_module = os.path.join(module_dir, "guard_service.py")
46
+ if os.path.exists(service_module):
47
+ print(f"Warning: Found service module via sys.prefix fallback: {service_module}")
48
+ return service_module
49
+ else:
50
+ raise FileNotFoundError(f"guard_service.py not found via inspect or sys.prefix fallback (checked {module_dir})")
51
+ except Exception as fallback_e:
52
+ raise FileNotFoundError(f"Could not find guard_service.py using inspect ({e}) or sys.prefix ({fallback_e}). Check installation.")
53
+
54
+
55
+ def run_service_command(command_args, check_errors=True):
56
+ """Runs the guard_service.py script with specified command-line args."""
57
+ if not is_admin():
58
+ print("Error: Administrative privileges are required to manage the service.", file=sys.stderr)
59
+ print("Please run this command from an Administrator Command Prompt or PowerShell.", file=sys.stderr)
60
+ return False
61
+
62
+ try:
63
+ python_exe = sys.executable # Use the same python that's running this script
64
+ service_script = get_service_module_path()
65
+ except FileNotFoundError as e:
66
+ print(f"Error: {e}", file=sys.stderr)
67
+ return False
68
+
69
+ # Quote paths if they contain spaces
70
+ if " " in python_exe and not python_exe.startswith('"'):
71
+ python_exe = f'"{python_exe}"'
72
+ if " " in service_script and not service_script.startswith('"'):
73
+ service_script = f'"{service_script}"'
74
+
75
+ # Construct command using list to avoid shell quoting issues
76
+ cmd = [sys.executable, get_service_module_path()] + command_args
77
+ print(f"Executing command: {' '.join(cmd)}")
78
+
79
+ try:
80
+ # Run the command. Use shell=False with list of args.
81
+ # Capture output to check for specific errors if needed, but print it too.
82
+ result = subprocess.run(cmd, capture_output=True, text=True, check=check_errors, encoding='utf-8')
83
+ if result.stdout:
84
+ print("Command STDOUT:")
85
+ print(result.stdout)
86
+ if result.stderr:
87
+ print("Command STDERR:")
88
+ print(result.stderr)
89
+ print(f"Command {' '.join(command_args)} executed successfully.")
90
+ return True
91
+ except FileNotFoundError as e:
92
+ print(f"Error: Could not find Python executable or service script during execution.", file=sys.stderr)
93
+ print(f" Details: {e}", file=sys.stderr)
94
+ return False
95
+ except subprocess.CalledProcessError as e:
96
+ print(f"Error executing service command {' '.join(command_args)} (Exit Code {e.returncode}).", file=sys.stderr)
97
+ if e.stdout:
98
+ print("Subprocess STDOUT:")
99
+ print(e.stdout)
100
+ if e.stderr:
101
+ print("Subprocess STDERR:")
102
+ print(e.stderr)
103
+ return False
104
+ except Exception as e:
105
+ print(f"An unexpected error occurred running service command: {e}", file=sys.stderr)
106
+ return False
107
+
108
+ # --- Add cleanup helpers ---
109
+ def _run_powershell_cleanup_command(command):
110
+ """Executes a PowerShell command specifically for cleanup, ignoring most errors."""
111
+ if platform.system() != "Windows": return True # Skip on non-windows
112
+ print(f"Executing PowerShell Cleanup: {command}")
113
+ try:
114
+ # Use check=False, don't capture output unless needed for debug
115
+ subprocess.run(
116
+ ["powershell.exe", "-NoProfile", "-NonInteractive", "-Command", command],
117
+ check=False, # Don't throw error if command fails (e.g., no tasks found)
118
+ stdout=subprocess.DEVNULL, # Suppress stdout
119
+ stderr=subprocess.DEVNULL # Suppress stderr
120
+ )
121
+ return True # Assume success for cleanup flow
122
+ except Exception as e:
123
+ print(f"Warning: PowerShell cleanup command failed: {e}", file=sys.stderr)
124
+ return False # Indicate potential issue
125
+
126
+ def _cleanup_scheduled_tasks():
127
+ """Removes all OOTB user logon scheduled tasks."""
128
+ print("Attempting to remove any existing OOTB user logon scheduled tasks...")
129
+ # Use -like operator and wildcard
130
+ # Use try-catch within PowerShell for robustness
131
+ command = f"""
132
+ $tasks = Get-ScheduledTask | Where-Object {{ $_.TaskName -like '{_TASK_NAME_PREFIX}*' }}
133
+ if ($tasks) {{
134
+ Write-Host "Found $($tasks.Count) OOTB logon tasks to remove."
135
+ $tasks | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue
136
+ Write-Host "OOTB logon task removal attempted."
137
+ }} else {{
138
+ Write-Host "No OOTB logon tasks found to remove."
139
+ }}
140
+ """
141
+ _run_powershell_cleanup_command(command)
142
+ # --- End cleanup helpers ---
143
+
144
+ def install_and_start():
145
+ """Installs and starts the Guard Service."""
146
+ print(f"Attempting to install service: '{_SERVICE_NAME}' ('{_SERVICE_DISPLAY_NAME}')")
147
+ # Call 'install' command first.
148
+ # We pass check_errors=True to stop if installation fails fundamentally.
149
+ install_success = run_service_command(['--startup', 'auto', 'install'], check_errors=True)
150
+
151
+ if install_success:
152
+ # Note: Even if install_success is True, pywin32 might have printed internal errors
153
+ # like 'service already installed'. We proceed to start anyway in that case.
154
+ print(f"\nInstallation command finished. Attempting to start service: '{_SERVICE_NAME}' (waiting a few seconds first)")
155
+ time.sleep(3) # Give SCM time to register the install/update
156
+ start_success = run_service_command(['start'], check_errors=True)
157
+
158
+ if start_success:
159
+ # Similar caveat: start might succeed according to subprocess, but pywin32 could print internal errors.
160
+ print(f"\nService '{_SERVICE_NAME}' install command executed and start command executed.")
161
+ print(f"Please verify service status in 'services.msc' and check logs.")
162
+ else:
163
+ # This path is taken if run_service_command returned False (subprocess error occurred)
164
+ print(f"\nService '{_SERVICE_NAME}' installed/updated but the 'start' command failed with an error.", file=sys.stderr)
165
+ print(f" Check output above, service logs ('C:\ProgramData\OOTBGuardService\guard_post_mode.log'), or Windows Event Viewer.", file=sys.stderr)
166
+ else:
167
+ # This path is taken if the initial 'install' command failed critically (subprocess error)
168
+ print(f"\nService '{_SERVICE_NAME}' installation failed critically. See errors above.", file=sys.stderr)
169
+
170
+
171
+ def stop_and_remove():
172
+ """Stops and removes the Guard Service and associated scheduled tasks."""
173
+ print(f"Attempting to stop service: '{_SERVICE_NAME}' (will ignore errors if not running)")
174
+ # Run stop first, ignore errors (check_errors=False)
175
+ run_service_command(['stop'], check_errors=False)
176
+ time.sleep(2) # Give service time to stop
177
+
178
+ print(f"\nAttempting to remove service: '{_SERVICE_NAME}'")
179
+ remove_success = run_service_command(['remove']) # Check if removal command itself failed
180
+
181
+ # Always attempt task cleanup, even if service removal had issues
182
+ _cleanup_scheduled_tasks()
183
+
184
+ if remove_success:
185
+ print(f"\nService '{_SERVICE_NAME}' stopped (if running) and removed successfully. Associated logon tasks cleanup attempted.")
186
+ else:
187
+ print(f"\nService '{_SERVICE_NAME}' removal command failed.", file=sys.stderr)
188
+ # Make sure to mention cleanup was still attempted
189
+ print(f" Associated logon tasks cleanup attempted.", file=sys.stderr)
190
+ print(f" Ensure the service was stopped first, or check permissions.", file=sys.stderr)
191
+
192
+ if __name__ == '__main__':
193
+ # Allow calling functions directly for testing if needed
194
+ print("This script provides service management commands.")
195
195
  print("Use 'ootb-install-service' or 'ootb-remove-service' as Administrator.")
@@ -1,30 +1,29 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: computer-use-ootb-internal
3
- Version: 0.0.136
3
+ Version: 0.0.137
4
4
  Summary: Computer Use OOTB
5
5
  Author-email: Siyuan Hu <siyuan.hu.sg@gmail.com>
6
6
  Requires-Python: >=3.11
7
7
  Requires-Dist: anthropic[bedrock,vertex]>=0.37.1
8
8
  Requires-Dist: boto3>=1.28.57
9
- Requires-Dist: flask>=2.0
10
9
  Requires-Dist: google-auth<3,>=2
11
10
  Requires-Dist: gradio>=5.6.0
12
11
  Requires-Dist: jsonschema==4.22.0
13
12
  Requires-Dist: litellm
14
13
  Requires-Dist: matplotlib
15
14
  Requires-Dist: opencv-python
16
- Requires-Dist: psutil>=5.0; sys_platform == 'win32'
15
+ Requires-Dist: pre-commit==3.8.0
17
16
  Requires-Dist: pyautogui==0.9.54
18
- Requires-Dist: pywin32>=306; sys_platform == 'win32'
19
- Requires-Dist: pywinauto; sys_platform == 'win32'
20
- Requires-Dist: requests>=2.0
17
+ Requires-Dist: pyside6
18
+ Requires-Dist: pytest-asyncio==0.23.6
19
+ Requires-Dist: pytest==8.3.3
20
+ Requires-Dist: pywinauto
21
+ Requires-Dist: ruff==0.6.7
21
22
  Requires-Dist: screeninfo
22
23
  Requires-Dist: streamlit>=1.38.0
23
24
  Requires-Dist: textdistance
24
- Requires-Dist: uiautomation; sys_platform == 'win32'
25
- Requires-Dist: waitress>=2.0
25
+ Requires-Dist: uiautomation
26
26
  Provides-Extra: dev
27
- Requires-Dist: pre-commit>=3.8.0; extra == 'dev'
28
27
  Requires-Dist: pytest-asyncio>=0.23.6; extra == 'dev'
29
28
  Requires-Dist: pytest>=8.3.3; extra == 'dev'
30
29
  Requires-Dist: ruff>=0.6.7; extra == 'dev'