Merge pull request #84 from tyfiero/Modifications-to-schedule-function

Modifications to schedule function
pull/89/head
killian 10 months ago committed by GitHub
commit 80840544ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -255,9 +255,9 @@ class Device:
try: try:
async with websockets.connect(WS_URL) as websocket: async with websockets.connect(WS_URL) as websocket:
if CAMERA_ENABLED: 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: 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)) asyncio.create_task(self.message_sender(websocket))

@ -13,7 +13,7 @@
#include <WebSocketsClient.h> #include <WebSocketsClient.h>
String server_domain = ""; String server_domain = "";
int server_port = 8000; int server_port = 10001;
// ----------------------- START OF WIFI CAPTIVE PORTAL ------------------- // ----------------------- START OF WIFI CAPTIVE PORTAL -------------------

@ -1,13 +1,13 @@
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() # take environment variables from .env. load_dotenv() # take environment variables from .env.
from platformdirs import user_data_dir
import os import os
import glob import glob
import time import time
import json import json
from pathlib import Path from pathlib import Path
from interpreter import OpenInterpreter from interpreter import OpenInterpreter
import shutil
system_message = r""" system_message = r"""
@ -46,9 +46,11 @@ Store the user's tasks in a Python list called `tasks`.
The user's current task list (it might be empty) is: {{ tasks }} 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 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. 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. After starting a task, you should check in with the user around the estimated completion time to see if the task is completed.
THE SCHEDULE FUNCTION HAS ALREADY BEEN IMPORTED. YOU DON'T NEED TO IMPORT THE `schedule` FUNCTION. 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. 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 # THE COMPUTER API
@ -296,9 +298,36 @@ def configure_interpreter(interpreter: OpenInterpreter):
from platformdirs import user_data_dir 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 # Initialize user's task list

@ -8,6 +8,7 @@ import json
import queue import queue
import os import os
import traceback import traceback
import datetime
from .utils.bytes_to_wav import bytes_to_wav from .utils.bytes_to_wav import bytes_to_wav
import re import re
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
@ -47,7 +48,7 @@ app = FastAPI()
app_dir = user_data_dir('01') app_dir = user_data_dir('01')
conversation_history_path = os.path.join(app_dir, 'conversations', 'user.json') 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 # This is so we only say() full sentences
@ -131,10 +132,10 @@ async def add_computer_message(request: Request):
text = body.get("text") text = body.get("text")
if not text: if not text:
return {"error": "Missing 'text' in request body"}, 422 return {"error": "Missing 'text' in request body"}, 422
message = {"role": "computer", "type": "console", "format": "output", "content": text} message = {"role": "user", "type": "message", "content": text}
from_computer.put({"role": "computer", "type": "console", "format": "output", "start": True}) await from_user.put({"role": "user", "type": "message", "start": True})
from_computer.put(message) await from_user.put(message)
from_computer.put({"role": "computer", "type": "console", "format": "output", "end": True}) await from_user.put({"role": "user", "type": "message", "end": True})
async def receive_messages(websocket: WebSocket): async def receive_messages(websocket: WebSocket):
@ -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') services_directory = os.path.join(application_directory, 'services')
service_dict = {'llm': llm_service, 'tts': tts_service, 'stt': stt_service} 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: for service in service_dict:
service_directory = os.path.join(services_directory, service, service_dict[service]) service_directory = os.path.join(services_directory, service, service_dict[service])

@ -1,34 +1,66 @@
import threading import os
from datetime import datetime from datetime import datetime
import json from pytimeparse import parse
import subprocess from crontab import CronTab
import requests 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: prefixed_message = "AUTOMATED MESSAGE FROM SCHEDULER: " + message
url = "http://localhost:8000/"
data = {"text": message} # Escape the message and the json, cron is funky with quotes
try: escaped_question = prefixed_message.replace('"', '\\"')
response = requests.post(url, json=data) json_data = f"{{\\\"text\\\": \\\"{escaped_question}\\\"}}"
response.raise_for_status()
except requests.RequestException as e:
print(f"Request failed: {e}")
def schedule(days=0, hours=0, mins=0, secs=0, target_datetime=None, message="") -> None: 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' '''
"""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."""
if target_datetime is None: cron = CronTab(user=True)
# Calculate the delay in seconds if no target_datetime is provided job = cron.new(command=command)
delay = days * 86400 + hours * 3600 + mins * 60 + secs # Prefix with 01 dev preview so we can delete them all in the future
else: job_id = "01-dev-preview-" + str(uuid4())
# Calculate the delay in seconds from now until the target datetime job.set_comment(job_id)
now = datetime.now() if start:
delay = (target_datetime - now).total_seconds() try:
# Ensure delay is non-negative start_time = datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
delay = max(0, delay) 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 elif interval:
timer = threading.Timer(delay, send_request, args=[message]) 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()

@ -5,7 +5,7 @@ import shutil
import time import time
from ..utils.print_markdown import print_markdown 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...") print_markdown(f"Exposing server to the internet...")
if tunnel_method == "bore": if tunnel_method == "bore":

2591
01OS/poetry.lock generated

File diff suppressed because one or more lines are too long

@ -29,6 +29,9 @@ typer = "^0.9.0"
platformdirs = "^4.2.0" platformdirs = "^4.2.0"
rich = "^13.7.1" rich = "^13.7.1"
open-interpreter = {extras = ["os"], version = "^0.2.3"} open-interpreter = {extras = ["os"], version = "^0.2.3"}
dateparser = "^1.2.0"
pytimeparse = "^1.1.8"
python-crontab = "^3.0.0"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]

@ -13,7 +13,7 @@ app = typer.Typer()
def run( def run(
server: bool = typer.Option(False, "--server", help="Run server"), server: bool = typer.Option(False, "--server", help="Run server"),
server_host: str = typer.Option("0.0.0.0", "--server-host", help="Specify the server host where the server will deploy"), server_host: str = typer.Option("0.0.0.0", "--server-host", help="Specify the server host where the server will deploy"),
server_port: int = typer.Option(8000, "--server-port", help="Specify the server port where the server will deploy"), server_port: int = typer.Option(10001, "--server-port", help="Specify the server port where the server will deploy"),
tunnel_service: str = typer.Option("ngrok", "--tunnel-service", help="Specify the tunnel service"), tunnel_service: str = typer.Option("ngrok", "--tunnel-service", help="Specify the tunnel service"),
expose: bool = typer.Option(False, "--expose", help="Expose server to internet"), expose: bool = typer.Option(False, "--expose", help="Expose server to internet"),
@ -62,7 +62,7 @@ def run(
def _run( def _run(
server: bool = False, server: bool = False,
server_host: str = "0.0.0.0", server_host: str = "0.0.0.0",
server_port: int = 8000, server_port: int = 10001,
tunnel_service: str = "bore", tunnel_service: str = "bore",
expose: bool = False, expose: bool = False,

@ -18,13 +18,13 @@ PIPER_VOICE_NAME="en_US-lessac-medium.onnx"
# If SERVER_START, this is where we'll serve the server. # If SERVER_START, this is where we'll serve the server.
# If CLIENT_START, this is where the client expects the server to be. # If CLIENT_START, this is where the client expects the server to be.
# SERVER_URL=ws://localhost:8000/ # SERVER_URL=ws://localhost:10001/
SERVER_URL=ws://0.0.0.0:8000/ SERVER_URL=ws://0.0.0.0:10001/
SERVER_START=True SERVER_START=True
CLIENT_START=True CLIENT_START=True
# The port to start the local server on # The port to start the local server on
SERVER_LOCAL_PORT=8000 SERVER_LOCAL_PORT=10001
# Explicitly set the client type (macos, rpi) # Explicitly set the client type (macos, rpi)
CLIENT_TYPE=auto CLIENT_TYPE=auto

@ -7,8 +7,8 @@
# - ngrok # - ngrok
TUNNEL_METHOD=${TUNNEL_METHOD:-bore} TUNNEL_METHOD=${TUNNEL_METHOD:-bore}
# Get the SERVER_PORT environment variable, but default to 8000 # Get the SERVER_PORT environment variable, but default to 10001
SERVER_LOCAL_PORT=${SERVER_LOCAL_PORT:-8000} SERVER_LOCAL_PORT=${SERVER_LOCAL_PORT:-10001}
echo "Using $TUNNEL_METHOD to expose port $SERVER_LOCAL_PORT on localhost..." echo "Using $TUNNEL_METHOD to expose port $SERVER_LOCAL_PORT on localhost..."

@ -53,7 +53,7 @@ For more information, please read about <a href="/services/speech-to-text">speec
- `--server-port INTEGER` - `--server-port INTEGER`
Specify the server port where the server will deploy. Specify the server port where the server will deploy.
Default: `8000`. Default: `10001`.
- `--tunnel-service TEXT` - `--tunnel-service TEXT`
Specify the tunnel service. Specify the tunnel service.

Loading…
Cancel
Save