JARVIS / tools /system_control.py
Khanna, Videh Rakesh Rakesh
feat: JARVIS security, cross-device, intelligence & polish overhaul
e2a2dda
"""JARVIS System Control β€” full laptop/phone control like Siri."""
import subprocess
import os
import platform
from tools import tool
# ─── Volume ──────────────────────────────────────
@tool(
name="set_volume",
description="Set system volume (0-100) or mute/unmute",
parameters={
"type": "object",
"properties": {
"level": {"type": "integer", "description": "Volume 0-100, or -1 to mute, -2 to unmute"},
},
"required": ["level"],
},
)
def set_volume(level: int) -> str:
if level == -1:
subprocess.run(["osascript", "-e", "set volume with output muted"])
return "Muted"
elif level == -2:
subprocess.run(["osascript", "-e", "set volume without output muted"])
return "Unmuted"
else:
level = max(0, min(100, level))
subprocess.run(["osascript", "-e", f"set volume output volume {level}"])
return f"Volume set to {level}%"
@tool(
name="get_volume",
description="Get current system volume level",
parameters={"type": "object", "properties": {}},
)
def get_volume() -> str:
result = subprocess.run(
["osascript", "-e", "output volume of (get volume settings)"],
capture_output=True, text=True,
)
return f"Volume: {result.stdout.strip()}%"
# ─── Brightness ──────────────────────────────────
@tool(
name="set_brightness",
description="Set screen brightness (0.0 to 1.0)",
parameters={
"type": "object",
"properties": {
"level": {"type": "number", "description": "Brightness 0.0-1.0"},
},
"required": ["level"],
},
)
def set_brightness(level: float) -> str:
level = max(0.0, min(1.0, level))
# Use brightness command if available
try:
subprocess.run(["brightness", str(level)], capture_output=True, timeout=5)
return f"Brightness set to {int(level*100)}%"
except Exception:
subprocess.run([
"osascript", "-e",
f'''
tell application "System Preferences"
reveal anchor "displaysDisplayTab" of pane id "com.apple.preference.displays"
end tell
'''
], stderr=subprocess.DEVNULL)
return f"Brightness control requires 'brightness' CLI. Install: brew install brightness"
# ─── Dark Mode ───────────────────────────────────
@tool(
name="toggle_dark_mode",
description="Toggle dark mode on/off",
parameters={
"type": "object",
"properties": {
"enable": {"type": "boolean", "description": "True for dark, False for light"},
},
"required": ["enable"],
},
)
def toggle_dark_mode(enable: bool) -> str:
mode = "true" if enable else "false"
subprocess.run([
"osascript", "-e",
f'tell application "System Events" to tell appearance preferences to set dark mode to {mode}'
])
return f"Dark mode {'enabled' if enable else 'disabled'}"
# ─── WiFi ────────────────────────────────────────
@tool(
name="wifi_control",
description="Turn WiFi on/off or get status",
parameters={
"type": "object",
"properties": {
"action": {"type": "string", "description": "'on', 'off', or 'status'"},
},
"required": ["action"],
},
)
def wifi_control(action: str) -> str:
if action == "on":
subprocess.run(["networksetup", "-setairportpower", "en0", "on"])
return "WiFi turned on"
elif action == "off":
subprocess.run(["networksetup", "-setairportpower", "en0", "off"])
return "WiFi turned off"
else:
result = subprocess.run(
["networksetup", "-getairportnetwork", "en0"],
capture_output=True, text=True,
)
return result.stdout.strip()
# ─── Bluetooth ───────────────────────────────────
@tool(
name="bluetooth_control",
description="Turn Bluetooth on/off",
parameters={
"type": "object",
"properties": {
"action": {"type": "string", "description": "'on' or 'off'"},
},
"required": ["action"],
},
)
def bluetooth_control(action: str) -> str:
try:
if action == "on":
subprocess.run(["blueutil", "--power", "1"], capture_output=True, timeout=5)
return "Bluetooth on"
else:
subprocess.run(["blueutil", "--power", "0"], capture_output=True, timeout=5)
return "Bluetooth off"
except Exception:
return "Install blueutil: brew install blueutil"
# ─── Do Not Disturb ──────────────────────────────
@tool(
name="do_not_disturb",
description="Toggle Do Not Disturb / Focus mode",
parameters={
"type": "object",
"properties": {
"enable": {"type": "boolean", "description": "True to enable DND"},
},
"required": ["enable"],
},
)
def do_not_disturb(enable: bool) -> str:
if enable:
subprocess.run([
"osascript", "-e",
'''
tell application "System Events"
tell process "ControlCenter"
-- Toggle Focus via menu bar
end tell
end tell
'''
], stderr=subprocess.DEVNULL)
# Alternative: use shortcuts
subprocess.run(["shortcuts", "run", "Focus On"], capture_output=True, timeout=5)
return "Do Not Disturb enabled"
else:
subprocess.run(["shortcuts", "run", "Focus Off"], capture_output=True, timeout=5)
return "Do Not Disturb disabled"
# ─── Screenshots ─────────────────────────────────
@tool(
name="screenshot",
description="Take a screenshot",
parameters={
"type": "object",
"properties": {
"area": {"type": "string", "description": "'full' for fullscreen, 'select' for selection"},
},
"required": [],
},
)
def screenshot(area: str = "full") -> str:
path = os.path.expanduser(f"~/Desktop/jarvis_screenshot_{int(__import__('time').time())}.png")
if area == "select":
subprocess.run(["screencapture", "-i", path])
else:
subprocess.run(["screencapture", path])
return f"Screenshot saved: {path}"
# ─── Music / Media Control ───────────────────────
@tool(
name="media_control",
description="Control music/media playback (play, pause, next, previous, now playing)",
parameters={
"type": "object",
"properties": {
"action": {"type": "string", "description": "'play', 'pause', 'next', 'previous', 'now_playing'"},
},
"required": ["action"],
},
)
def media_control(action: str) -> str:
if action == "now_playing":
result = subprocess.run([
"osascript", "-e",
'''
try
tell application "Music"
set trackName to name of current track
set artistName to artist of current track
return trackName & " by " & artistName
end tell
on error
try
tell application "Spotify"
return name of current track & " by " & artist of current track
end tell
on error
return "Nothing playing"
end try
end try
'''
], capture_output=True, text=True, timeout=5)
return result.stdout.strip()
key_map = {
"play": "play",
"pause": "pause",
"next": "next track",
"previous": "previous track",
}
cmd = key_map.get(action, "play")
# Try Music app first, then Spotify
subprocess.run([
"osascript", "-e",
f'''
try
tell application "Music" to {cmd}
on error
try
tell application "Spotify" to {cmd}
end try
end try
'''
], capture_output=True, timeout=5)
return f"Media: {action}"
# ─── Clipboard ───────────────────────────────────
@tool(
name="clipboard",
description="Read or write the clipboard",
parameters={
"type": "object",
"properties": {
"action": {"type": "string", "description": "'read' to get clipboard, 'write' to set it"},
"text": {"type": "string", "description": "Text to write (only for 'write')"},
},
"required": ["action"],
},
)
def clipboard(action: str, text: str = "") -> str:
if action == "read":
result = subprocess.run(["pbpaste"], capture_output=True, text=True)
return f"Clipboard: {result.stdout[:500]}"
elif action == "write":
proc = subprocess.Popen(["pbcopy"], stdin=subprocess.PIPE)
proc.communicate(text.encode())
return f"Copied to clipboard"
return "Unknown action"
# ─── Notifications / Alerts ──────────────────────
@tool(
name="send_notification",
description="Send a macOS notification/alert",
parameters={
"type": "object",
"properties": {
"title": {"type": "string", "description": "Notification title"},
"message": {"type": "string", "description": "Notification body"},
},
"required": ["title", "message"],
},
)
def send_notification(title: str, message: str) -> str:
safe_title = title.replace('\\', '').replace('"', '').replace("'", '')[:80]
safe_msg = message.replace('\\', '').replace('"', '').replace("'", '')[:120]
subprocess.run([
"osascript", "-e",
f'display notification "{safe_msg}" with title "{safe_title}" sound name "default"'
])
return f"Notification sent: {title}"
# ─── App Management ──────────────────────────────
@tool(
name="list_running_apps",
description="List all running applications",
parameters={"type": "object", "properties": {}},
)
def list_running_apps() -> str:
result = subprocess.run([
"osascript", "-e",
'tell application "System Events" to get name of every process whose background only is false'
], capture_output=True, text=True, timeout=5)
return f"Running apps: {result.stdout.strip()}"
@tool(
name="quit_app",
description="Quit/close an application",
parameters={
"type": "object",
"properties": {
"app_name": {"type": "string", "description": "App name to quit"},
},
"required": ["app_name"],
},
)
def quit_app(app_name: str) -> str:
safe_name = app_name.replace('\\', '').replace('"', '').replace("'", '').replace('`', '')
subprocess.run([
"osascript", "-e",
f'tell application "{safe_name}" to quit'
], capture_output=True, timeout=5)
return f"Quit {app_name}"
# ─── Timer / Alarm ───────────────────────────────
@tool(
name="set_timer",
description="Set a timer that alerts after N seconds/minutes",
parameters={
"type": "object",
"properties": {
"seconds": {"type": "integer", "description": "Timer duration in seconds"},
"label": {"type": "string", "description": "What the timer is for"},
},
"required": ["seconds"],
},
)
def set_timer(seconds: int, label: str = "Timer") -> str:
import threading
def timer_alert():
import time
time.sleep(seconds)
subprocess.run([
"osascript", "-e",
f'display dialog "Timer: {label}" with title "JARVIS Timer" buttons {{"OK"}} default button "OK" giving up after 30'
])
subprocess.run(["say", "-v", "Daniel", f"Sir, your {label} timer is done."])
threading.Thread(target=timer_alert, daemon=True).start()
mins = seconds // 60
secs = seconds % 60
if mins:
return f"Timer set: {label} β€” {mins}m {secs}s"
return f"Timer set: {label} β€” {secs}s"
# ─── Lock Screen / Sleep ─────────────────────────
@tool(
name="lock_screen",
description="Lock the screen",
parameters={"type": "object", "properties": {}},
)
def lock_screen() -> str:
subprocess.run([
"osascript", "-e",
'tell application "System Events" to keystroke "q" using {control down, command down}'
])
return "Screen locked"
@tool(
name="sleep_display",
description="Put the display to sleep",
parameters={"type": "object", "properties": {}},
)
def sleep_display() -> str:
subprocess.run(["pmset", "displaysleepnow"])
return "Display sleeping"
# ─── Trash ───────────────────────────────────────
@tool(
name="empty_trash",
description="Empty the trash",
parameters={"type": "object", "properties": {}},
)
def empty_trash() -> str:
subprocess.run([
"osascript", "-e",
'tell application "Finder" to empty trash'
], capture_output=True, timeout=10)
return "Trash emptied"
# ─── Text to Speech (announce) ───────────────────
@tool(
name="announce",
description="Speak a message out loud through the speakers",
parameters={
"type": "object",
"properties": {
"message": {"type": "string", "description": "Message to speak"},
},
"required": ["message"],
},
)
def announce(message: str) -> str:
subprocess.run(["say", "-v", "Daniel", "-r", "180", message])
return f"Announced: {message}"
# ─── Open URL ────────────────────────────────────
@tool(
name="open_url",
description="Open a URL in the default browser",
parameters={
"type": "object",
"properties": {
"url": {"type": "string", "description": "URL to open"},
},
"required": ["url"],
},
)
def open_url(url: str) -> str:
subprocess.run(["open", url])
return f"Opened: {url}"
# ─── Spotlight Search ────────────────────────────
@tool(
name="search_files",
description="Search for files on the system using Spotlight",
parameters={
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"},
},
"required": ["query"],
},
)
def search_files(query: str) -> str:
result = subprocess.run(
["mdfind", query, "-limit", "10"],
capture_output=True, text=True, timeout=10,
)
files = result.stdout.strip().split("\n")[:10]
return "\n".join(files) if files[0] else "No files found"
# ─── Create Reminder ─────────────────────────────
@tool(
name="create_reminder",
description="Create a reminder in the Reminders app",
parameters={
"type": "object",
"properties": {
"title": {"type": "string", "description": "Reminder text"},
},
"required": ["title"],
},
)
def create_reminder(title: str) -> str:
subprocess.run([
"osascript", "-e",
f'''
tell application "Reminders"
make new reminder with properties {{name:"{title}"}}
end tell
'''
], capture_output=True, timeout=5)
return f"Reminder created: {title}"
# ─── Calendar ────────────────────────────────────
@tool(
name="get_events",
description="Get today's calendar events",
parameters={"type": "object", "properties": {}},
)
def get_events() -> str:
result = subprocess.run([
"osascript", "-e",
'''
set today to current date
set time of today to 0
set tomorrow to today + 86400
tell application "Calendar"
set output to ""
repeat with cal in calendars
set evts to (every event of cal whose start date >= today and start date < tomorrow)
repeat with evt in evts
set output to output & summary of evt & " at " & time string of start date of evt & "\\n"
end repeat
end repeat
if output is "" then
return "No events today"
end if
return output
end tell
'''
], capture_output=True, text=True, timeout=10)
return result.stdout.strip()