AURA-Backend / overlay_context.py
Vijayadhith7's picture
Upload 2 files
06b8dd4 verified
Raw
History Blame Contribute Delete
12 kB
import os
import json
import re
from typing import Dict, Any
GROQ_VISION_MODEL = "meta-llama/llama-4-scout-17b-16e-instruct"
OVERLAY_SLM_MODEL = "llama-3.1-8b-instant"
def parse_json_robust(text: str) -> Dict[str, Any]:
text = text.strip()
# Remove markdown code block wrappers if present
if text.startswith("```"):
text = re.sub(r"^```(?:json)?\n", "", text)
text = re.sub(r"\n```$", "", text)
text = text.strip()
try:
return json.loads(text)
except Exception:
# Fallback regex extraction
match = re.search(r"(\{.*\})", text, re.DOTALL)
if match:
try:
return json.loads(match.group(1))
except Exception:
pass
raise ValueError("Failed to parse JSON response from LLM")
def get_local_fallback_context(active_app: str, window_title: str, accessibility_text: str) -> dict:
try:
from overlay_engine import classify_workflow
workflow = classify_workflow(active_app, window_title, accessibility_text)
except ImportError:
workflow = "general"
app_display = (active_app or "Desktop").split(".")[0].capitalize()
detected = [f"App: {app_display}"]
if window_title:
title_clean = window_title.strip()
if len(title_clean) > 25:
title_clean = title_clean[:22] + "..."
detected.append(title_clean)
suggestions = []
if workflow == "vscode":
detected.append("VS Code")
suggestions = [
{"label": "Explain Code", "prompt": "Analyze the active code block on screen and explain it step-by-step."},
{"label": "Find Syntax Errors", "prompt": "Check the visible code for syntax errors or anti-patterns."},
{"label": "Refactor Function", "prompt": "Suggest clean optimization and refactoring for the active function."}
]
elif workflow == "photoshop":
detected.append("Photoshop")
suggestions = [
{"label": "Blending Guide", "prompt": "How do I use layer styles and masks for seamless blending?"},
{"label": "Selection Tools", "prompt": "Explain which selection tools are best for complex cutouts."},
{"label": "Color Correction", "prompt": "Suggest step-by-step curves adjustments for a moody photo."}
]
elif workflow == "excel":
detected.append("Excel")
suggestions = [
{"label": "Lookup Formulas", "prompt": "Explain VLOOKUP and XLOOKUP parameters with examples."},
{"label": "Create Pivot Table", "prompt": "How do I build a dynamic pivot table from raw data?"},
{"label": "Write Macro", "prompt": "Write a basic VBA script to format new rows automatically."}
]
elif workflow == "browser":
detected.append("Browser Page")
suggestions = [
{"label": "Summarize Article", "prompt": "Provide a high-level summary of the active webpage/article."},
{"label": "Explain Page", "prompt": "Explain the key concepts of the visible web page in simple terms."},
{"label": "Extract Actions", "prompt": "Extract the key action items or guides from this page."}
]
else:
detected.append("AI Copilot")
suggestions = [
{"label": "Analyze Screen", "prompt": "Explain what's currently visible on this screen and suggest next steps."},
{"label": "Summarize Context", "prompt": "Draft a concise summary of the active task on my screen."},
{"label": "Optimize Layout", "prompt": "How can I improve my workspace structure to boost focus?"}
]
return {
"detected_items": detected,
"suggestions": suggestions
}
async def analyze_screen_context(
active_app: str,
window_title: str,
accessibility_text: str,
screenshot_b64: str = None
) -> dict:
import asyncio
import tempfile
import base64
import sys
# 1. Attempt to delegate to Hermes Agent CLI
current_dir = os.path.dirname(os.path.abspath(__file__))
hermes_dir = os.path.abspath(os.path.join(current_dir, "..", "..", "hermes-agent"))
venv_python = os.path.join(hermes_dir, ".venv", "Scripts", "python.exe")
cli_script = os.path.join(hermes_dir, "cli.py")
if not os.path.exists(venv_python):
venv_python = sys.executable
temp_img_path = None
if screenshot_b64:
try:
clean_b64 = screenshot_b64
if "," in clean_b64:
clean_b64 = clean_b64.split(",")[1]
img_data = base64.b64decode(clean_b64)
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as temp_file:
temp_file.write(img_data)
temp_img_path = temp_file.name
except Exception as e:
print(f"AURA Hermes Context Bridge: Failed to decode/save screenshot: {e}")
prompt_query = (
f"Analyze active screen context:\n"
f"Active App: {active_app or 'Unknown'}\n"
f"Window Title: {window_title or 'Unknown'}\n"
f"Accessibility Text: {accessibility_text or ''}\n\n"
f"You MUST return a JSON object with this exact schema:\n"
f"{{\n"
f" \"detected_items\": [\"tag1\", \"tag2\", \"tag3\"],\n"
f" \"suggestions\": [\n"
f" {{\"label\": \"Short Action Button Label\", \"prompt\": \"The detailed query that is executed when user clicks this button\"}}\n"
f" ]\n"
f"}}\n"
f"Do not write any markdown wrappers, preambles, or postambles. Output ONLY valid JSON."
)
args = [
cli_script,
"--skills", "aura_overlay",
"--model", "nousresearch/hermes-3-llama-3.1-70b",
"--toolsets", "none",
"--quiet",
"-q", prompt_query
]
if temp_img_path:
args.extend(["--image", temp_img_path])
env = os.environ.copy()
env["HERMES_HOME"] = hermes_dir
try:
print(f"AURA Hermes Context Bridge: Invoking Hermes Agent context scan...")
process = await asyncio.create_subprocess_exec(
venv_python,
*args,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
env=env
)
stdout_bytes, stderr_bytes = await process.communicate()
stdout_text = stdout_bytes.decode("utf-8", errors="ignore")
stderr_text = stderr_bytes.decode("utf-8", errors="ignore")
if process.returncode == 0:
res = parse_json_robust(stdout_text)
if "detected_items" in res and "suggestions" in res:
res["detected_items"] = [str(x)[:25] for x in res["detected_items"]][:4]
clean_sug = []
for item in res["suggestions"]:
if isinstance(item, dict) and "label" in item and "prompt" in item:
item["label"] = str(item["label"])[:25]
clean_sug.append(item)
elif isinstance(item, str):
clean_sug.append({"label": item[:25], "prompt": item})
res["suggestions"] = clean_sug[:4]
print("AURA Hermes Context Bridge: Successfully analyzed screen context via Hermes Agent.")
return res
else:
print("AURA Hermes Context Bridge: Invalid structure returned by Hermes Agent. Falling back.")
else:
print(f"AURA Hermes Context Bridge: CLI run failed (exit {process.returncode}). Stderr: {stderr_text}. Falling back.")
except Exception as e:
print(f"AURA Hermes Context Bridge Error: {e}. Falling back.")
finally:
if temp_img_path and os.path.exists(temp_img_path):
try:
os.remove(temp_img_path)
except Exception:
pass
# 2. Fallback to Groq/OpenRouter API Client
try:
from main import async_groq_client, map_model_for_backend
client = async_groq_client
except ImportError:
client = None
map_model_for_backend = lambda x: x
if not client:
print("AURA Context Engine: API client unavailable. Using local rule-based fallback.")
return get_local_fallback_context(active_app, window_title, accessibility_text)
system_prompt = """You are AURA Context Engine, a system-level real-time screen analysis service.
Your job is to analyze the user's active screen/window context and return a structured JSON response.
Detect:
1. The active application and sub-elements (e.g., active page title, current form fields, code errors, edit tools, etc.).
2. The user's likely intent or current problem based on the visual screen content, accessibility text, or window title.
Generate 3-4 highly action-oriented, contextual suggestions (short chips) that the user can tap to execute a task.
Be exceptionally direct, helpful, and premium. Avoid generic options.
Suggestions must be tailored to what is visible. For example:
- In VS Code with a syntax error: suggestion "Explain error in auth_service.ts"
- In Chrome reading an article: suggestion "Summarize this article"
- In Photoshop editing: suggestion "Blend layers smoothly"
- In a Login form: suggestion "Auto-generate secure password" or "Resolve password error"
Output MUST be a JSON object with this exact schema:
{
"detected_items": ["tag1", "tag2", "tag3"],
"suggestions": [
{"label": "Short Action Button Label", "prompt": "The detailed query that is executed when user clicks this button"}
]
}
Do not write any markdown wrappers, preambles, or postambles. Output ONLY valid JSON."""
try:
has_img = bool(screenshot_b64)
model = GROQ_VISION_MODEL if has_img else OVERLAY_SLM_MODEL
user_content = f"Active App: {active_app or 'Unknown'}\nWindow Title: {window_title or 'Unknown'}\nAccessibility Text: {accessibility_text or ''}"
if has_img:
clean_b64 = screenshot_b64.split(",")[1] if "," in screenshot_b64 else screenshot_b64
messages = [
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": [
{"type": "text", "text": user_content},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{clean_b64}"
}
}
]
}
]
else:
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_content}
]
# Call API client
response = await client.chat.completions.create(
model=map_model_for_backend(model),
messages=messages,
temperature=0.2,
max_tokens=600,
response_format={"type": "json_object"} if not has_img else None
)
raw_text = response.choices[0].message.content
res = parse_json_robust(raw_text)
if "detected_items" in res and "suggestions" in res:
res["detected_items"] = [str(x)[:25] for x in res["detected_items"]][:4]
clean_sug = []
for item in res["suggestions"]:
if isinstance(item, dict) and "label" in item and "prompt" in item:
item["label"] = str(item["label"])[:25]
clean_sug.append(item)
elif isinstance(item, str):
clean_sug.append({"label": item[:25], "prompt": item})
res["suggestions"] = clean_sug[:4]
return res
except Exception as e:
print(f"AURA Context Engine fallback error: {e}. Using local rule-based fallback.")
return get_local_fallback_context(active_app, window_title, accessibility_text)