Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions plugins/example/ahda/client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from fastapi import APIRouter, Request, HTTPException, Form, Query, BackgroundTasks, Body
from fastapi import APIRouter, HTTPException, Query, BackgroundTasks, Body, Request, Form
from fastapi.responses import HTMLResponse, FileResponse, JSONResponse
from db import get_ahda_url, store_ahda, get_ahda_os
import os
import requests
from models import RealtimePluginRequest, EndpointResponse
import time
import asyncio
import logging
Expand All @@ -14,7 +13,7 @@
active_sessions = {}

KEYWORD = "computer"
COMMAND_TIMEOUT = 5 # Seconds to wait after the last word to finalize the command
COMMAND_TIMEOUT = 8 # Seconds to wait after the last word to finalize the command

# Path to the directory containing `index.html`
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
Expand All @@ -39,13 +38,12 @@ def sendToPC(uid, response):
'response': response
}
try:
resp = requests.post(ahda_url+"/recieve", json=payload)
resp = requests.post(ahda_url + "/recieve", json=payload)
resp.raise_for_status()
return {'message': 'Webhook sent successfully'}
except requests.RequestException as e:
logger.error(f"Error sending webhook: {e}")
raise
return {'message': 'Webhook sent successfully'}

return {'message': f'Failed to send webhook: {e}'}
Comment on lines +41 to +46
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure consistent error handling in sendToPC

The sendToPC function now returns a dictionary with a message on success and failure instead of raising exceptions. Verify that all callers of this function handle these return values appropriately, and consider whether returning error messages aligns with the overall error-handling strategy of your codebase.


@router.post('/ahda/send-webhook', tags=['ahda', 'realtime'])
async def send_ahda_webhook(
Expand All @@ -71,7 +69,8 @@ async def send_ahda_webhook(

async def schedule_finalize_command(uid, delay):
await asyncio.sleep(delay)
await finalize_command(uid)
if time.time() - active_sessions[uid]["last_received_time"] >= delay:
await finalize_command(uid)

async def finalize_command(uid):
final_command = active_sessions[uid]["command"].strip()
Expand All @@ -82,48 +81,54 @@ async def finalize_command(uid):
active_sessions[uid]["active"] = False
active_sessions[uid]["timer"] = None

# Adjusted to handle segments as dictionaries
# Process each segment
for segment in segments:
text = segment.get("text", "").strip().lower()
logger.info(f"Received segment: {text} (session_id: {uid})")

if KEYWORD in text:
logger.info("Activation keyword detected!")
active_sessions[uid]["active"] = True

# Reset command aggregation and update last received time
active_sessions[uid]["last_received_time"] = time.time()
active_sessions[uid]["command"] = text

# Cancel the previous timer if any
if active_sessions[uid]["timer"]:
pass
active_sessions[uid]["timer"].cancel()

active_sessions[uid]["timer"] = background_tasks.add_task(
schedule_finalize_command, uid, COMMAND_TIMEOUT
# Schedule a new timer for finalizing the command
active_sessions[uid]["timer"] = asyncio.create_task(
schedule_finalize_command(uid, COMMAND_TIMEOUT)
)
continue

# Append to the existing command if active
if active_sessions[uid]["active"]:
active_sessions[uid]["command"] += " " + text
active_sessions[uid]["last_received_time"] = time.time()
logger.info(f"Aggregating command: {active_sessions[uid]['command'].strip()}")

# Cancel the previous timer and set a new one
if active_sessions[uid]["timer"]:
pass
active_sessions[uid]["timer"].cancel()

active_sessions[uid]["timer"] = background_tasks.add_task(
schedule_finalize_command, uid, COMMAND_TIMEOUT
active_sessions[uid]["timer"] = asyncio.create_task(
schedule_finalize_command(uid, COMMAND_TIMEOUT)
)

return {"status": "success"}


async def call_chatgpt_to_generate_code(command, uid):
try:
ahda_os = get_ahda_os(uid)
messages = [
("system", prompt.replace("{os_name}",ahda_os)),
("system", prompt.replace("{os_name}", ahda_os)),
("human", command),
]
ai_msg = chat.invoke(messages)
sendToPC(uid, ai_msg)
ai_msg = await chat.invoke(messages) # Ensure this is awaited
return sendToPC(uid, ai_msg)
Comment on lines +130 to +131
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle exceptions from sendToPC in call_chatgpt_to_generate_code

The function now awaits chat.invoke(messages) and returns the result of sendToPC(uid, ai_msg). Since sendToPC returns a message dictionary instead of raising exceptions, ensure that any errors are properly handled and that the calling functions account for this change in error handling.

except Exception as e:
logger.error(f"Error calling ChatGPT-4: {e}")
return {"type": "error", "content": str(e)}
Expand All @@ -132,6 +137,7 @@ async def call_chatgpt_to_generate_code(command, uid):
async def get_ahda_index(request: Request, uid: str = Query(None)):
if not uid:
raise HTTPException(status_code=400, detail="UID is required")

return FileResponse(INDEX_PATH)

@router.post('/ahda/configure', tags=['ahda'])
Expand Down
8 changes: 6 additions & 2 deletions plugins/example/ahda/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@
</div>
<p class="plugin-text">AHDA Integration Plugin</p>
<h1>AHDA Integration</h1>
<h1>Install https://github.com/ActuallyAdvanced/OMI-AHDA first</h1>
Install https://github.com/ActuallyAdvanced/OMI-AHDA first
<br>
<form id="ahda-form">
<input type="text" id="url" placeholder="Enter AHDA URL" required>
<input type="text" id="os" placeholder="Enter Operating System" required>
Expand All @@ -103,6 +104,9 @@ <h1>Install https://github.com/ActuallyAdvanced/OMI-AHDA first</h1>
const urlParams = new URLSearchParams(window.location.search);
const uid = urlParams.get('uid');

const url = urlParams.get('url');
const os = urlParams.get('os');

Comment on lines +107 to +109
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance usability and security for URL parameters.

While the 'url' and 'os' parameters are correctly extracted from the URL, they are not being utilized to pre-fill the form inputs. Additionally, there's no validation or sanitization of these parameters.

Consider implementing the following improvements:

  1. Pre-fill the form inputs with the extracted values:
if (url) document.getElementById('url').value = url;
if (os) document.getElementById('os').value = os;
  1. Implement basic validation and sanitization for the URL and OS parameters:
function sanitizeInput(input) {
    return input.replace(/[&<>"']/g, function(m) {
        return {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#39;'
        }[m]
    });
}

const url = sanitizeInput(urlParams.get('url') || '');
const os = sanitizeInput(urlParams.get('os') || '');

These changes will improve both usability and security of the form.

if (!uid) {
document.getElementById('response-message').textContent = "UID is missing. Please check the URL.";
document.getElementById('response-message').style.color = 'red';
Expand Down Expand Up @@ -135,4 +139,4 @@ <h1>Install https://github.com/ActuallyAdvanced/OMI-AHDA first</h1>
</script>
</body>

</html>
</html>