Skip to content

Commit

Permalink
Merge pull request OpenInterpreter#84 from tyfiero/Modifications-to-s…
Browse files Browse the repository at this point in the history
…chedule-function

Modifications to schedule function
  • Loading branch information
KillianLucas authored Mar 21, 2024
2 parents 6fdd2d1 + 310052d commit 8084054
Show file tree
Hide file tree
Showing 12 changed files with 1,474 additions and 1,292 deletions.
4 changes: 2 additions & 2 deletions 01OS/01OS/clients/base_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,9 @@ async def websocket_communication(self, WS_URL):
try:
async with websockets.connect(WS_URL) as websocket:
if CAMERA_ENABLED:
print("Press the spacebar to start/stop recording. Press 'c' to capture an image from the camera. Press CTRL-C to exit.")
print("\nPress the spacebar to start/stop recording. Press 'c' to capture an image from the camera. Press CTRL-C to exit.")
else:
print("Press the spacebar to start/stop recording. Press CTRL-C to exit.")
print("\nPress the spacebar to start/stop recording. Press CTRL-C to exit.")

asyncio.create_task(self.message_sender(websocket))

Expand Down
2 changes: 1 addition & 1 deletion 01OS/01OS/clients/esp32/src/client/client.ino
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <WebSocketsClient.h>

String server_domain = "";
int server_port = 8000;
int server_port = 10001;

// ----------------------- START OF WIFI CAPTIVE PORTAL -------------------

Expand Down
43 changes: 36 additions & 7 deletions 01OS/01OS/server/i.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from dotenv import load_dotenv
load_dotenv() # take environment variables from .env.

from platformdirs import user_data_dir
import os
import glob
import time
import json
from pathlib import Path
from interpreter import OpenInterpreter
import shutil


system_message = r"""
Expand Down Expand Up @@ -46,9 +46,11 @@
The user's current task list (it might be empty) is: {{ tasks }}
When the user completes the current task, you should remove it from the list and read the next item by running `tasks = tasks[1:]\ntasks[0]`. Then, tell the user what the next task is.
When the user tells you about a set of tasks, you should intelligently order tasks, batch similar tasks, and break down large tasks into smaller tasks (for this, you should consult the user and get their permission to break it down). Your goal is to manage the task list as intelligently as possible, to make the user as efficient and non-overwhelmed as possible. They will require a lot of encouragement, support, and kindness. Don't say too much about what's ahead of them— just try to focus them on each step at a time.
After starting a task, you should check in with the user around the estimated completion time to see if the task is completed.
To do this, schedule a reminder based on estimated completion time using the function `schedule(days=0, hours=0, mins=0, secs=0, datetime="valid date time", message="Your message here.")`. You'll receive the message at the time you scheduled it.
THE SCHEDULE FUNCTION HAS ALREADY BEEN IMPORTED. YOU DON'T NEED TO IMPORT THE `schedule` FUNCTION.
After starting a task, you should check in with the user around the estimated completion time to see if the task is completed.
To do this, schedule a reminder based on estimated completion time using the function `schedule(message="Your message here.", start="8am")`, WHICH HAS ALREADY BEEN IMPORTED. YOU DON'T NEED TO IMPORT THE `schedule` FUNCTION. IT IS AVAILABLE. You'll receive the message at the time you scheduled it. If the user says to monitor something, simply schedule it with an interval of a duration that makes sense for the problem by specifying an interval, like this: `schedule(message="Your message here.", interval="5m")`
If there are tasks, you should guide the user through their list one task at a time, convincing them to move forward, giving a pep talk if need be.
# THE COMPUTER API
Expand Down Expand Up @@ -296,9 +298,36 @@ def configure_interpreter(interpreter: OpenInterpreter):

from platformdirs import user_data_dir

directory = os.path.join(user_data_dir("01"), "skills")
interpreter.computer.skills.path = directory
interpreter.computer.skills.import_skills()


# Directory paths
repo_skills_dir = os.path.join(os.path.dirname(__file__), "skills")
user_data_skills_dir = os.path.join(user_data_dir("01"), "skills")

# Create the user data skills directory if it doesn't exist
os.makedirs(user_data_skills_dir, exist_ok=True)

# Copy Python files from the repository skills directory to the user data skills directory, ignoring __init__.py files
for filename in os.listdir(repo_skills_dir):
if filename.endswith(".py") and filename != "__init__.py":
src_file = os.path.join(repo_skills_dir, filename)
dst_file = os.path.join(user_data_skills_dir, filename)
shutil.copy2(src_file, dst_file)

interpreter.computer.debug = True
interpreter.computer.skills.path = user_data_skills_dir

# Import skills
interpreter.computer.save_skills = False

for file in glob.glob(os.path.join(interpreter.computer.skills.path, "*.py")):
code_to_run = ""
with open(file, "r") as f:
code_to_run += f.read() + "\n"

interpreter.computer.run("python", code_to_run)

interpreter.computer.save_skills = True


# Initialize user's task list
Expand Down
19 changes: 13 additions & 6 deletions 01OS/01OS/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import queue
import os
import traceback
import datetime
from .utils.bytes_to_wav import bytes_to_wav
import re
from fastapi import FastAPI, Request
Expand Down Expand Up @@ -47,7 +48,7 @@
app_dir = user_data_dir('01')
conversation_history_path = os.path.join(app_dir, 'conversations', 'user.json')

SERVER_LOCAL_PORT = int(os.getenv('SERVER_LOCAL_PORT', 8000))
SERVER_LOCAL_PORT = int(os.getenv('SERVER_LOCAL_PORT', 10001))


# This is so we only say() full sentences
Expand Down Expand Up @@ -131,10 +132,10 @@ async def add_computer_message(request: Request):
text = body.get("text")
if not text:
return {"error": "Missing 'text' in request body"}, 422
message = {"role": "computer", "type": "console", "format": "output", "content": text}
from_computer.put({"role": "computer", "type": "console", "format": "output", "start": True})
from_computer.put(message)
from_computer.put({"role": "computer", "type": "console", "format": "output", "end": True})
message = {"role": "user", "type": "message", "content": text}
await from_user.put({"role": "user", "type": "message", "start": True})
await from_user.put(message)
await from_user.put({"role": "user", "type": "message", "end": True})


async def receive_messages(websocket: WebSocket):
Expand Down Expand Up @@ -382,7 +383,13 @@ async def main(server_host, server_port, llm_service, model, llm_supports_vision
services_directory = os.path.join(application_directory, 'services')

service_dict = {'llm': llm_service, 'tts': tts_service, 'stt': stt_service}


# Create a temp file with the session number
session_file_path = os.path.join(user_data_dir('01'), '01-session.txt')
with open(session_file_path, 'w') as session_file:
session_id = int(datetime.datetime.now().timestamp() * 1000)
session_file.write(str(session_id))

for service in service_dict:

service_directory = os.path.join(services_directory, service, service_dict[service])
Expand Down
86 changes: 59 additions & 27 deletions 01OS/01OS/server/skills/schedule.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,66 @@
import threading
import os
from datetime import datetime
import json
import subprocess
import requests
from pytimeparse import parse
from crontab import CronTab
from uuid import uuid4
from datetime import datetime
from platformdirs import user_data_dir

def schedule(message="", start=None, interval=None) -> None:
"""
Schedules a task at a particular time, or at a particular interval
"""
if start and interval:
raise ValueError("Cannot specify both start time and interval.")

if not start and not interval:
raise ValueError("Either start time or interval must be specified.")

# Read the temp file to see what the current session is
session_file_path = os.path.join(user_data_dir('01'), '01-session.txt')

with open(session_file_path, 'r') as session_file:
file_session_value = session_file.read().strip()


def send_request(message) -> None:
url = "http://localhost:8000/"
data = {"text": message}
try:
response = requests.post(url, json=data)
response.raise_for_status()
except requests.RequestException as e:
print(f"Request failed: {e}")
prefixed_message = "AUTOMATED MESSAGE FROM SCHEDULER: " + message

# Escape the message and the json, cron is funky with quotes
escaped_question = prefixed_message.replace('"', '\\"')
json_data = f"{{\\\"text\\\": \\\"{escaped_question}\\\"}}"

def schedule(days=0, hours=0, mins=0, secs=0, target_datetime=None, message="") -> None:
"""Schedules a reminder after a specified delay or for a specific datetime. The delay is defined by days, hours, minutes, and seconds. If a target_datetime is provided, it schedules the reminder for that datetime instead."""
command = f'''bash -c 'if [ "$(cat "{session_file_path}")" == "{file_session_value}" ]; then /usr/bin/curl -X POST -H "Content-Type: application/json" -d "{json_data}" http://localhost:10001/; fi' '''

if target_datetime is None:
# Calculate the delay in seconds if no target_datetime is provided
delay = days * 86400 + hours * 3600 + mins * 60 + secs
else:
# Calculate the delay in seconds from now until the target datetime
now = datetime.now()
delay = (target_datetime - now).total_seconds()
# Ensure delay is non-negative
delay = max(0, delay)
cron = CronTab(user=True)
job = cron.new(command=command)
# Prefix with 01 dev preview so we can delete them all in the future
job_id = "01-dev-preview-" + str(uuid4())
job.set_comment(job_id)
if start:
try:
start_time = datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
except ValueError:
raise ValueError(f"Invalid datetime format: {start}.")
job.setall(start_time)
print(f"Task scheduled for {start_time.strftime('%Y-%m-%d %H:%M:%S')}")

# Create a timer
timer = threading.Timer(delay, send_request, args=[message])
elif interval:
seconds = parse(interval)
if seconds <= 60:
job.minute.every(1)
print("Task scheduled every minute")
elif seconds < 3600:
minutes = max(int(seconds / 60), 1)
job.minute.every(minutes)
print(f"Task scheduled every {minutes} minutes")
elif seconds < 86400:
hours = max(int(seconds / 3600), 1)
job.hour.every(hours)
print(f"Task scheduled every {hours} hour(s)")
else:
days = max(int(seconds / 86400), 1)
job.day.every(days)
print(f"Task scheduled every {days} day(s)")

cron.write()

# Start the timer
timer.start()
2 changes: 1 addition & 1 deletion 01OS/01OS/server/tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import time
from ..utils.print_markdown import print_markdown

def create_tunnel(tunnel_method='ngrok', server_host='localhost', server_port=8000):
def create_tunnel(tunnel_method='ngrok', server_host='localhost', server_port=10001):
print_markdown(f"Exposing server to the internet...")

if tunnel_method == "bore":
Expand Down
Loading

0 comments on commit 8084054

Please sign in to comment.