Compare commits

...

3 Commits

4 changed files with 80 additions and 2 deletions

View File

@ -0,0 +1,55 @@
#////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: <ProjectRoot>/Data/Agent/Python_API_Endpoints/macro_engines.py
import platform
if platform.system().lower().startswith('win'):
# pywinauto is only available/supported on Windows
try:
from pywinauto import Desktop, Application
except ImportError:
Desktop = None
Application = None
print("[macro_engines] pywinauto not installed!")
else:
Desktop = None
Application = None
def list_windows():
"""List all visible windows with titles (for dropdown in UI)."""
if Desktop is None:
return []
windows = []
for w in Desktop(backend="uia").windows():
try:
title = w.window_text()
handle = w.handle
if title.strip():
windows.append({"title": title, "handle": handle})
except Exception:
continue
return windows
def send_keypress_to_window(handle, key):
"""Send a single keypress to the specified window handle."""
if Application is None:
raise RuntimeError("Macro engine not supported on this OS")
try:
app = Application(backend="uia").connect(handle=handle)
win = app.window(handle=handle)
win.set_focus() # pywinauto still needs focus for most key sends
win.type_keys(key, with_spaces=True, set_foreground=True)
return True
except Exception as e:
return False, str(e)
def type_text_to_window(handle, text):
"""Type a string into the window (as if pasted or typed)."""
if Application is None:
raise RuntimeError("Macro engine not supported on this OS")
try:
app = Application(backend="uia").connect(handle=handle)
win = app.window(handle=handle)
win.set_focus()
win.type_keys(text, with_spaces=True, set_foreground=True)
return True
except Exception as e:
return False, str(e)

View File

@ -17,4 +17,7 @@ Pillow # Image processing (Windows)
# WebRTC Video Libraries # WebRTC Video Libraries
###aiortc # Python library for WebRTC in async environments ###aiortc # Python library for WebRTC in async environments
###av # Required by aiortc for video/audio codecs ###av # Required by aiortc for video/audio codecs
# Macro Automation
pywinauto # Windows-based Macro Automation Library

View File

@ -10,6 +10,7 @@ from functools import partial
from io import BytesIO from io import BytesIO
import base64 import base64
import traceback import traceback
import platform # OS Detection
import socketio import socketio
from qasync import QEventLoop from qasync import QEventLoop
@ -77,6 +78,25 @@ class ConfigManager:
CONFIG = ConfigManager(CONFIG_PATH) CONFIG = ConfigManager(CONFIG_PATH)
CONFIG.load() CONFIG.load()
# //////////////////////////////////////////////////////////////////////////
# CORE SECTION: OPERATING SYSTEM DETECTION
# //////////////////////////////////////////////////////////////////////////
def detect_agent_os():
plat = platform.system().lower()
if plat.startswith('win'):
return 'windows'
elif plat.startswith('linux'):
return 'linux'
elif plat.startswith('darwin'):
return 'macos'
else:
return 'unknown'
CONFIG.data['agent_operating_system'] = detect_agent_os()
CONFIG._write()
# //////////////////////////////////////////////////////////////////////////
def init_agent_id(): def init_agent_id():
if not CONFIG.data.get('agent_id'): if not CONFIG.data.get('agent_id'):
CONFIG.data['agent_id'] = f"{socket.gethostname().lower()}-agent-{uuid.uuid4().hex[:8]}" CONFIG.data['agent_id'] = f"{socket.gethostname().lower()}-agent-{uuid.uuid4().hex[:8]}"

View File

@ -1,4 +1,4 @@
////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: <ProjectRoot>/Data/WebUI/src/nodes/Macro Automation/Node_Macro_KeyPress.jsx ////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: <ProjectRoot>/Data/WebUI/src/nodes/Automation/Node_Macro_KeyPress.jsx
import React, { useState, useRef } from "react"; import React, { useState, useRef } from "react";
import { Handle, Position } from "reactflow"; import { Handle, Position } from "reactflow";
import Keyboard from "react-simple-keyboard"; import Keyboard from "react-simple-keyboard";