diff --git a/requirements.txt b/requirements.txt index cc29f6b..63e7bb8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ botocore==1.37.11 pandas==2.2.3 prettytable==3.16.0 tqdm==4.62.3 +python-socketio[client] \ No newline at end of file diff --git a/src/mindcraft-py/example.py b/src/mindcraft-py/example.py new file mode 100644 index 0000000..dde5610 --- /dev/null +++ b/src/mindcraft-py/example.py @@ -0,0 +1,21 @@ +import mindcraft +import json +import os + +# Initialize Mindcraft, starting the Node.js server +# This will also connect to the MindServer via websockets +mindcraft.init() + +# Get the directory of the current script +script_dir = os.path.dirname(os.path.abspath(__file__)) +profile_path = os.path.abspath(os.path.join(script_dir, '..', '..', 'andy.json')) + +# Load agent settings from a JSON file +try: + with open(profile_path, 'r') as f: + profile_data = json.load(f) + + settings = {"profile": profile_data} + mindcraft.create_agent(settings) +except FileNotFoundError: + print(f"Error: Could not find andy.json at {profile_path}") diff --git a/src/mindcraft-py/init-mindcraft.js b/src/mindcraft-py/init-mindcraft.js new file mode 100644 index 0000000..2ba8399 --- /dev/null +++ b/src/mindcraft-py/init-mindcraft.js @@ -0,0 +1,30 @@ +import * as Mindcraft from '../mindcraft/mindcraft.js'; +import settings from '../../settings.js'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; + +function parseArguments() { + return yargs(hideBin(process.argv)) + .option('mindserver_host', { + type: 'string', + describe: 'Mindserver host', + default: settings.mindserver_host + }) + .option('mindserver_port', { + type: 'number', + describe: 'Mindserver port', + default: settings.mindserver_port + }) + .help() + .alias('help', 'h') + .parse(); +} + +const args = parseArguments(); + +settings.mindserver_host = args.mindserver_host; +settings.mindserver_port = args.mindserver_port; + +Mindcraft.init(settings.mindserver_host, settings.mindserver_port); + +console.log(`Mindcraft initialized with MindServer at ${settings.mindserver_host}:${settings.mindserver_port}`); \ No newline at end of file diff --git a/src/mindcraft-py/mindcraft.py b/src/mindcraft-py/mindcraft.py new file mode 100644 index 0000000..911caa8 --- /dev/null +++ b/src/mindcraft-py/mindcraft.py @@ -0,0 +1,91 @@ +import subprocess +import socketio +import time +import json +import os +import atexit +import threading +import sys + +class Mindcraft: + def __init__(self): + self.sio = socketio.Client() + self.process = None + self.connected = False + self.log_thread = None + + def _log_reader(self): + for line in iter(self.process.stdout.readline, ''): + sys.stdout.write(f'[Node.js] {line}') + sys.stdout.flush() + + def init(self, host='localhost', port=8080): + if self.process: + return + + self.host = host + self.port = port + + node_script_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'init-mindcraft.js')) + + self.process = subprocess.Popen([ + 'node', + node_script_path, + '--mindserver_host', self.host, + '--mindserver_port', str(self.port) + ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1) + + self.log_thread = threading.Thread(target=self._log_reader) + self.log_thread.daemon = True + self.log_thread.start() + + atexit.register(self.shutdown) + time.sleep(2) + + try: + self.sio.connect(f'http://{self.host}:{self.port}') + self.connected = True + print("Connected to MindServer") + except socketio.exceptions.ConnectionError as e: + print(f"Failed to connect to MindServer: {e}") + self.shutdown() + raise + + def create_agent(self, settings_json): + if not self.connected: + raise Exception("Not connected to MindServer. Call init() first.") + + profile_data = settings_json.get('profile', {}) + + def callback(response): + if response.get('success'): + print(f"Agent '{profile_data.get('name')}' created successfully") + else: + print(f"Error creating agent: {response.get('error', 'Unknown error')}") + + self.sio.emit('create-agent', settings_json, callback=callback) + self.sio.wait() + + def shutdown(self): + if self.sio.connected: + self.sio.disconnect() + self.connected = False + if self.process: + self.process.terminate() + self.process.wait() + self.process = None + print("Mindcraft shut down.") + +mindcraft_instance = Mindcraft() + +def init(host='localhost', port=8080): + mindcraft_instance.init(host, port) + +def create_agent(settings_json): + mindcraft_instance.create_agent(settings_json) + +def shutdown(): + mindcraft_instance.shutdown() + +def wait(): + mindcraft_instance.wait() \ No newline at end of file