Files
dark_hal/agent_mode.py

374 lines
13 KiB
Python
Raw Permalink Normal View History

2026-03-13 12:56:43 -07:00
#!/usr/bin/env python3
"""
Agent Mode for DarkHal 2.0
Integrates Hal's unrestricted capabilities into the chat interface
"""
import os
import sys
import json
import asyncio
import threading
from typing import Optional, Callable, Dict, Any, List
from dataclasses import dataclass
import tkinter as tk
from tkinter import messagebox
# Add agent_dhal to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'agent_dhal'))
# Import Hal components
try:
from agent_dhal.hal import create_dhal, DhalConfig, HalModelClient
except ImportError:
# Fallback for testing
create_dhal = None
DhalConfig = None
HalModelClient = None
print("[Agent Mode] Warning: Could not import Hal components")
@dataclass
class AgentModeConfig:
"""Configuration for agent mode"""
enabled: bool = False
allow_file_operations: bool = True
allow_shell_commands: bool = True
allow_system_control: bool = True # mouse, keyboard
allow_elevated_commands: bool = False # sudo, admin powershell
require_confirmation: bool = True # Ask before dangerous operations
model_name: str = "gpt-4"
class AgentModeHandler:
"""Handles agent mode functionality for the chat interface"""
def __init__(self, output_callback: Callable[[str], None] = None):
"""
Initialize agent mode handler
Args:
output_callback: Function to call with output text
"""
self.config = AgentModeConfig()
self.output_callback = output_callback or print
self.agent = None
self.is_initialized = False
self._init_lock = threading.Lock()
def initialize_agent(self, model_path: str = None) -> bool:
"""
Initialize the Hal agent
Args:
model_path: Path to model file or model name
Returns:
True if initialized successfully
"""
with self._init_lock:
if self.is_initialized:
return True
try:
if not create_dhal:
self.output_callback("[Agent Mode] Hal components not available\n")
return False
# Configure agent based on settings
config = DhalConfig(
name="Hal",
system_message=self._get_system_prompt(),
model=model_path or "gpt-4",
temperature=0.7,
max_tokens=2000
)
# Create model client
model_client = HalModelClient(model_name=model_path or "gpt-4")
# Create agent
self.agent = create_dhal(
name="Hal",
system_message=self._get_system_prompt(),
model=model_path or "gpt-4",
model_client=model_client
)
self.is_initialized = True
self.output_callback("[Agent Mode] Hal agent initialized successfully\n")
return True
except Exception as e:
self.output_callback(f"[Agent Mode] Failed to initialize: {e}\n")
return False
def _get_system_prompt(self) -> str:
"""Generate system prompt based on current permissions"""
prompt = """You are Hal, an advanced AI assistant with direct system access.
You can execute commands and control the system based on user requests.
Available capabilities:"""
if self.config.allow_file_operations:
prompt += "\n- Read, write, and list files"
if self.config.allow_shell_commands:
prompt += "\n- Execute shell commands (bash, PowerShell)"
prompt += "\n- Run Python code"
if self.config.allow_system_control:
prompt += "\n- Control mouse and keyboard"
prompt += "\n- Send keystrokes and type text"
if self.config.allow_elevated_commands:
prompt += "\n- Execute elevated/admin commands"
prompt += "\n\nAlways explain what you're doing before executing commands."
if self.config.require_confirmation:
prompt += "\nWait for user confirmation before destructive operations."
return prompt
async def process_message_async(self, message: str) -> str:
"""
Process a message through the agent asynchronously
Args:
message: User message to process
Returns:
Agent response
"""
if not self.is_initialized:
return "[Agent Mode] Not initialized. Please enable agent mode first."
try:
# Get response from agent
from agent_dhal.hal import MessageContext
# Create a mock context for standalone usage
class MockContext:
def __init__(self):
self.agent_id = "user"
ctx = MockContext()
# Process message through agent
response = await self.agent.handle_user_message(message, ctx)
return response
except Exception as e:
return f"[Agent Mode] Error processing message: {e}"
def process_message(self, message: str) -> str:
"""
Process a message through the agent (synchronous wrapper)
Args:
message: User message to process
Returns:
Agent response
"""
# Run async function in new event loop
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(self.process_message_async(message))
finally:
loop.close()
def enable(self, model_path: str = None) -> bool:
"""
Enable agent mode
Args:
model_path: Path to model or model name
Returns:
True if enabled successfully
"""
if not self.is_initialized:
if not self.initialize_agent(model_path):
return False
self.config.enabled = True
self.output_callback("[Agent Mode] ENABLED - Hal has full system access\n")
self._show_capabilities()
return True
def disable(self):
"""Disable agent mode"""
self.config.enabled = False
self.output_callback("[Agent Mode] DISABLED - Normal chat mode\n")
def _show_capabilities(self):
"""Show current capabilities to user"""
caps = []
if self.config.allow_file_operations:
caps.append("• File operations (read/write/list)")
if self.config.allow_shell_commands:
caps.append("• Shell commands (bash/PowerShell/Python)")
if self.config.allow_system_control:
caps.append("• Mouse & keyboard control")
if self.config.allow_elevated_commands:
caps.append("• Elevated/admin commands")
if caps:
self.output_callback("Enabled capabilities:\n" + "\n".join(caps) + "\n")
def update_config(self, **kwargs):
"""Update configuration settings"""
for key, value in kwargs.items():
if hasattr(self.config, key):
setattr(self.config, key, value)
# Reinitialize agent if needed
if self.is_initialized:
self.agent.update_config(system_message=self._get_system_prompt())
class AgentModeUI:
"""UI components for agent mode"""
def __init__(self, parent_frame: tk.Frame, handler: AgentModeHandler):
"""
Create agent mode UI controls
Args:
parent_frame: Parent tkinter frame
handler: AgentModeHandler instance
"""
self.handler = handler
self.parent = parent_frame
# Create control frame
self.control_frame = tk.LabelFrame(parent_frame, text="🤖 Agent Mode", relief=tk.RIDGE, borderwidth=2)
self.control_frame.pack(fill=tk.X, padx=5, pady=5)
# Main toggle
self.enabled_var = tk.BooleanVar(value=False)
self.enable_check = tk.Checkbutton(
self.control_frame,
text="Enable Agent Mode (FULL SYSTEM ACCESS)",
variable=self.enabled_var,
command=self._toggle_agent_mode,
font=('Arial', 10, 'bold'),
fg='red'
)
self.enable_check.grid(row=0, column=0, columnspan=3, sticky=tk.W, padx=5, pady=5)
# Permission toggles
self.file_ops_var = tk.BooleanVar(value=True)
tk.Checkbutton(
self.control_frame,
text="File Operations",
variable=self.file_ops_var,
command=self._update_permissions
).grid(row=1, column=0, sticky=tk.W, padx=20, pady=2)
self.shell_var = tk.BooleanVar(value=True)
tk.Checkbutton(
self.control_frame,
text="Shell Commands",
variable=self.shell_var,
command=self._update_permissions
).grid(row=1, column=1, sticky=tk.W, padx=20, pady=2)
self.system_var = tk.BooleanVar(value=True)
tk.Checkbutton(
self.control_frame,
text="Mouse/Keyboard",
variable=self.system_var,
command=self._update_permissions
).grid(row=1, column=2, sticky=tk.W, padx=20, pady=2)
self.elevated_var = tk.BooleanVar(value=False)
tk.Checkbutton(
self.control_frame,
text="Elevated Commands (DANGEROUS)",
variable=self.elevated_var,
command=self._update_permissions,
fg='orange'
).grid(row=2, column=0, columnspan=2, sticky=tk.W, padx=20, pady=2)
self.confirm_var = tk.BooleanVar(value=True)
tk.Checkbutton(
self.control_frame,
text="Require Confirmation",
variable=self.confirm_var,
command=self._update_permissions
).grid(row=2, column=2, sticky=tk.W, padx=20, pady=2)
# Status label
self.status_label = tk.Label(
self.control_frame,
text="Status: DISABLED",
font=('Arial', 9),
fg='gray'
)
self.status_label.grid(row=3, column=0, columnspan=3, pady=5)
def _toggle_agent_mode(self):
"""Toggle agent mode on/off"""
if self.enabled_var.get():
# Show warning
result = messagebox.askyesno(
"⚠️ Enable Agent Mode",
"WARNING: Agent mode gives the AI unrestricted access to:\n\n"
"• Your file system\n"
"• Shell commands\n"
"• Mouse and keyboard control\n"
"• System settings\n\n"
"Only enable if you understand the risks.\n\n"
"Continue?",
icon='warning'
)
if result:
# Get model path from parent if available
model_path = None
if hasattr(self.parent.master, 'model_var'):
model_path = self.parent.master.model_var.get()
if self.handler.enable(model_path):
self.status_label.config(text="Status: ACTIVE", fg='red')
self._update_permissions()
else:
self.enabled_var.set(False)
messagebox.showerror("Error", "Failed to initialize agent mode")
else:
self.enabled_var.set(False)
else:
self.handler.disable()
self.status_label.config(text="Status: DISABLED", fg='gray')
def _update_permissions(self):
"""Update handler permissions based on UI settings"""
self.handler.update_config(
allow_file_operations=self.file_ops_var.get(),
allow_shell_commands=self.shell_var.get(),
allow_system_control=self.system_var.get(),
allow_elevated_commands=self.elevated_var.get(),
require_confirmation=self.confirm_var.get()
)
def is_enabled(self) -> bool:
"""Check if agent mode is enabled"""
return self.enabled_var.get() and self.handler.config.enabled
# Example usage
if __name__ == "__main__":
# Test agent mode
handler = AgentModeHandler()
print("Testing agent mode...")
if handler.enable():
response = handler.process_message("List files in the current directory")
print(f"Response: {response}")
response = handler.process_message("What's 2+2? Calculate with Python")
print(f"Response: {response}")
handler.disable()