Merge pull request #84 from tyfiero/Modifications-to-schedule-function
Modifications to schedule function
This commit is contained in:
commit
80840544ef
|
@ -255,9 +255,9 @@ class Device:
|
|||
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))
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <WebSocketsClient.h>
|
||||
|
||||
String server_domain = "";
|
||||
int server_port = 8000;
|
||||
int server_port = 10001;
|
||||
|
||||
// ----------------------- START OF WIFI CAPTIVE PORTAL -------------------
|
||||
|
||||
|
|
|
@ -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"""
|
||||
|
@ -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 }}
|
||||
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
|
||||
|
@ -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
|
||||
|
|
|
@ -8,6 +8,7 @@ import json
|
|||
import queue
|
||||
import os
|
||||
import traceback
|
||||
import datetime
|
||||
from .utils.bytes_to_wav import bytes_to_wav
|
||||
import re
|
||||
from fastapi import FastAPI, Request
|
||||
|
@ -47,7 +48,7 @@ app = FastAPI()
|
|||
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
|
||||
|
@ -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):
|
||||
|
@ -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])
|
||||
|
|
|
@ -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 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}")
|
||||
|
||||
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."""
|
||||
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 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)
|
||||
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()
|
||||
|
||||
# Create a timer
|
||||
timer = threading.Timer(delay, send_request, args=[message])
|
||||
|
||||
# Start the timer
|
||||
timer.start()
|
||||
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}\\\"}}"
|
||||
|
||||
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' '''
|
||||
|
||||
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')}")
|
||||
|
||||
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()
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import shutil
|
|||
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":
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -29,6 +29,9 @@ typer = "^0.9.0"
|
|||
platformdirs = "^4.2.0"
|
||||
rich = "^13.7.1"
|
||||
open-interpreter = {extras = ["os"], version = "^0.2.3"}
|
||||
dateparser = "^1.2.0"
|
||||
pytimeparse = "^1.1.8"
|
||||
python-crontab = "^3.0.0"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
|
|
|
@ -13,7 +13,7 @@ app = typer.Typer()
|
|||
def run(
|
||||
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_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"),
|
||||
expose: bool = typer.Option(False, "--expose", help="Expose server to internet"),
|
||||
|
@ -62,7 +62,7 @@ def run(
|
|||
def _run(
|
||||
server: bool = False,
|
||||
server_host: str = "0.0.0.0",
|
||||
server_port: int = 8000,
|
||||
server_port: int = 10001,
|
||||
|
||||
tunnel_service: str = "bore",
|
||||
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 CLIENT_START, this is where the client expects the server to be.
|
||||
# SERVER_URL=ws://localhost:8000/
|
||||
SERVER_URL=ws://0.0.0.0:8000/
|
||||
# SERVER_URL=ws://localhost:10001/
|
||||
SERVER_URL=ws://0.0.0.0:10001/
|
||||
SERVER_START=True
|
||||
CLIENT_START=True
|
||||
|
||||
# The port to start the local server on
|
||||
SERVER_LOCAL_PORT=8000
|
||||
SERVER_LOCAL_PORT=10001
|
||||
|
||||
# Explicitly set the client type (macos, rpi)
|
||||
CLIENT_TYPE=auto
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
# - ngrok
|
||||
TUNNEL_METHOD=${TUNNEL_METHOD:-bore}
|
||||
|
||||
# Get the SERVER_PORT environment variable, but default to 8000
|
||||
SERVER_LOCAL_PORT=${SERVER_LOCAL_PORT:-8000}
|
||||
# Get the SERVER_PORT environment variable, but default to 10001
|
||||
SERVER_LOCAL_PORT=${SERVER_LOCAL_PORT:-10001}
|
||||
|
||||
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`
|
||||
Specify the server port where the server will deploy.
|
||||
Default: `8000`.
|
||||
Default: `10001`.
|
||||
|
||||
- `--tunnel-service TEXT`
|
||||
Specify the tunnel service.
|
||||
|
|
Loading…
Reference in New Issue