569 lines
18 KiB
Python
569 lines
18 KiB
Python
import subprocess
|
||||
|
|
import sys
|
|||
|
|
import json
|
|||
|
|
import re
|
|||
|
|
import time
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_base_dir():
|
|||
|
|
if getattr(sys, "frozen", False):
|
|||
|
|
return Path(sys.executable).parent
|
|||
|
|
return Path(__file__).resolve().parent.parent
|
|||
|
|
|
|||
|
|
BASE_DIR = get_base_dir()
|
|||
|
|
API_CONFIG_PATH = BASE_DIR / "config" / "api_keys.json"
|
|||
|
|
DESKTOP = Path.home() / "Desktop"
|
|||
|
|
MAX_BUILD_ATTEMPTS = 3
|
|||
|
|
GEMINI_MODEL = "gemini-2.5-flash"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _get_api_key() -> str:
|
|||
|
|
with open(API_CONFIG_PATH, "r", encoding="utf-8") as f:
|
|||
|
|
return json.load(f)["gemini_api_key"]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _get_gemini(model: str = GEMINI_MODEL):
|
|||
|
|
import google.generativeai as genai
|
|||
|
|
genai.configure(api_key=_get_api_key())
|
|||
|
|
return genai.GenerativeModel(model)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _clean_code(text: str) -> str:
|
|||
|
|
text = text.strip()
|
|||
|
|
text = re.sub(r"^```[a-zA-Z]*\n?", "", text)
|
|||
|
|
text = re.sub(r"\n?```$", "", text)
|
|||
|
|
return text.strip()
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _resolve_save_path(output_path: str, language: str) -> Path:
|
|||
|
|
ext_map = {
|
|||
|
|
"python": ".py", "py": ".py",
|
|||
|
|
"javascript": ".js", "js": ".js",
|
|||
|
|
"typescript": ".ts", "ts": ".ts",
|
|||
|
|
"html": ".html", "css": ".css",
|
|||
|
|
"java": ".java", "cpp": ".cpp", "c": ".c",
|
|||
|
|
"bash": ".sh", "shell": ".sh", "powershell": ".ps1",
|
|||
|
|
"sql": ".sql", "json": ".json", "rust": ".rs", "go": ".go",
|
|||
|
|
}
|
|||
|
|
if output_path:
|
|||
|
|
p = Path(output_path)
|
|||
|
|
return p if p.is_absolute() else DESKTOP / p
|
|||
|
|
ext = ext_map.get((language or "python").lower(), ".py")
|
|||
|
|
return DESKTOP / f"jarvis_code{ext}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _read_file(file_path: str) -> tuple[str, str]:
|
|||
|
|
if not file_path:
|
|||
|
|
return "", "No file path provided."
|
|||
|
|
p = Path(file_path)
|
|||
|
|
if not p.exists():
|
|||
|
|
return "", f"File not found: {file_path}"
|
|||
|
|
try:
|
|||
|
|
return p.read_text(encoding="utf-8"), ""
|
|||
|
|
except Exception as e:
|
|||
|
|
return "", f"Could not read file: {e}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _save_file(path: Path, content: str) -> str:
|
|||
|
|
try:
|
|||
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|||
|
|
path.write_text(content, encoding="utf-8")
|
|||
|
|
return f"Saved to: {path}"
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"Could not save: {e}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _preview(code: str, lines: int = 10) -> str:
|
|||
|
|
all_lines = code.splitlines()
|
|||
|
|
preview = "\n".join(all_lines[:lines])
|
|||
|
|
suffix = f"\n... ({len(all_lines) - lines} more lines)" if len(all_lines) > lines else ""
|
|||
|
|
return preview + suffix
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _has_error(output: str) -> bool:
|
|||
|
|
error_signals = ["error", "exception", "traceback", "syntaxerror",
|
|||
|
|
"nameerror", "typeerror", "stderr", "failed", "crash"]
|
|||
|
|
return any(s in output.lower() for s in error_signals)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _take_screenshot() -> Path | None:
|
|||
|
|
try:
|
|||
|
|
import pyautogui
|
|||
|
|
screenshot_path = Path.home() / "Desktop" / f"jarvis_debug_{int(time.time())}.png"
|
|||
|
|
screenshot = pyautogui.screenshot()
|
|||
|
|
screenshot.save(str(screenshot_path))
|
|||
|
|
print(f"[Code] 📸 Screenshot: {screenshot_path}")
|
|||
|
|
return screenshot_path
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"[Code] ⚠️ Screenshot failed: {e}")
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _image_to_base64(path: Path) -> str:
|
|||
|
|
import base64
|
|||
|
|
return base64.b64encode(path.read_bytes()).decode("utf-8")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _detect_intent(description: str, file_path: str, code: str) -> str:
|
|||
|
|
desc = (description or "").lower()
|
|||
|
|
|
|||
|
|
screen_kw = ["ekrandaki", "screen", "ekranda", "bu hatayı", "why am i getting",
|
|||
|
|
"neden hata", "what's wrong", "ne yanlış", "screenshot", "görüntü"]
|
|||
|
|
if any(k in desc for k in screen_kw):
|
|||
|
|
return "screen_debug"
|
|||
|
|
|
|||
|
|
optimize_kw = ["optimize", "refactor", "clean up", "improve", "temizle",
|
|||
|
|
"iyileştir", "daha iyi", "make it better", "hızlandır"]
|
|||
|
|
if any(k in desc for k in optimize_kw) and (code or file_path):
|
|||
|
|
return "optimize"
|
|||
|
|
|
|||
|
|
if file_path:
|
|||
|
|
p = Path(file_path)
|
|||
|
|
edit_kw = ["edit", "update", "modify", "change", "add", "remove",
|
|||
|
|
"refactor", "fix", "rename", "replace", "düzenle", "değiştir"]
|
|||
|
|
run_kw = ["run", "execute", "launch", "start", "çalıştır"]
|
|||
|
|
build_kw = ["build", "make it work", "try", "attempt"]
|
|||
|
|
|
|||
|
|
if p.exists() and any(k in desc for k in edit_kw):
|
|||
|
|
return "edit"
|
|||
|
|
if p.exists() and any(k in desc for k in run_kw):
|
|||
|
|
return "run"
|
|||
|
|
if any(k in desc for k in build_kw):
|
|||
|
|
return "build"
|
|||
|
|
if p.exists():
|
|||
|
|
return "explain"
|
|||
|
|
|
|||
|
|
explain_kw = ["explain", "what does", "describe", "analyze", "açıkla", "ne yapıyor"]
|
|||
|
|
if any(k in desc for k in explain_kw) and (code or file_path):
|
|||
|
|
return "explain"
|
|||
|
|
|
|||
|
|
build_kw = ["build", "make it work", "try and", "attempt"]
|
|||
|
|
if any(k in desc for k in build_kw):
|
|||
|
|
return "build"
|
|||
|
|
|
|||
|
|
return "write"
|
|||
|
|
|
|||
|
|
def _write(description: str, language: str, output_path: str, player=None) -> tuple[str, Path]:
|
|||
|
|
lang = language or "python"
|
|||
|
|
model = _get_gemini()
|
|||
|
|
|
|||
|
|
prompt = f"""You are an expert {lang} developer.
|
|||
|
|
Write clean, working, well-commented {lang} code for the description below.
|
|||
|
|
|
|||
|
|
Rules:
|
|||
|
|
- Output ONLY the code. No explanation, no markdown, no backticks.
|
|||
|
|
- Add helpful inline comments.
|
|||
|
|
- Handle errors and edge cases properly.
|
|||
|
|
- Use modern best practices.
|
|||
|
|
|
|||
|
|
Description: {description}
|
|||
|
|
|
|||
|
|
Code:"""
|
|||
|
|
|
|||
|
|
response = model.generate_content(prompt)
|
|||
|
|
code = _clean_code(response.text)
|
|||
|
|
path = _resolve_save_path(output_path, lang)
|
|||
|
|
_save_file(path, code)
|
|||
|
|
return code, path
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _fix_code(code: str, error_output: str, description: str) -> str:
|
|||
|
|
model = _get_gemini()
|
|||
|
|
prompt = f"""You are an expert debugger.
|
|||
|
|
The code below failed with the following error. Fix it.
|
|||
|
|
Return ONLY the corrected code — no explanation, no markdown, no backticks.
|
|||
|
|
|
|||
|
|
Original goal: {description}
|
|||
|
|
|
|||
|
|
Error:
|
|||
|
|
{error_output[:2000]}
|
|||
|
|
|
|||
|
|
Broken code:
|
|||
|
|
{code}
|
|||
|
|
|
|||
|
|
Fixed code:"""
|
|||
|
|
|
|||
|
|
response = model.generate_content(prompt)
|
|||
|
|
return _clean_code(response.text)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _run_file(path: Path, args: list, timeout: int) -> str:
|
|||
|
|
interpreters = {
|
|||
|
|
".py": [sys.executable],
|
|||
|
|
".js": ["node"],
|
|||
|
|
".ts": ["ts-node"],
|
|||
|
|
".sh": ["bash"],
|
|||
|
|
".ps1": ["powershell", "-File"],
|
|||
|
|
".rb": ["ruby"],
|
|||
|
|
".php": ["php"],
|
|||
|
|
}
|
|||
|
|
interp = interpreters.get(path.suffix.lower())
|
|||
|
|
if not interp:
|
|||
|
|
return f"No interpreter for {path.suffix}."
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
result = subprocess.run(
|
|||
|
|
interp + [str(path)] + (args or []),
|
|||
|
|
capture_output=True, text=True,
|
|||
|
|
encoding="utf-8", errors="replace",
|
|||
|
|
timeout=timeout, cwd=str(path.parent)
|
|||
|
|
)
|
|||
|
|
output = result.stdout.strip()
|
|||
|
|
error = result.stderr.strip()
|
|||
|
|
parts = []
|
|||
|
|
if output: parts.append(f"Output:\n{output}")
|
|||
|
|
if error: parts.append(f"Stderr:\n{error}")
|
|||
|
|
return "\n\n".join(parts) if parts else "Executed with no output."
|
|||
|
|
|
|||
|
|
except subprocess.TimeoutExpired:
|
|||
|
|
return f"Timed out after {timeout}s."
|
|||
|
|
except FileNotFoundError:
|
|||
|
|
return f"Interpreter not found: {interp[0]}."
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"Execution error: {e}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _build(description, language, output_path, args, timeout, speak=None, player=None) -> str:
|
|||
|
|
if not description:
|
|||
|
|
return "Please describe what you want me to build, sir."
|
|||
|
|
|
|||
|
|
if player:
|
|||
|
|
player.write_log("[Code] Build started...")
|
|||
|
|
|
|||
|
|
lang = language or "python"
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
code, path = _write(description, lang, output_path, player)
|
|||
|
|
print(f"[Code] ✅ Written: {path}")
|
|||
|
|
except Exception as e:
|
|||
|
|
msg = f"Could not write initial code: {e}"
|
|||
|
|
if speak: speak(msg)
|
|||
|
|
return msg
|
|||
|
|
|
|||
|
|
last_output = ""
|
|||
|
|
for attempt in range(1, MAX_BUILD_ATTEMPTS + 1):
|
|||
|
|
print(f"[Code] 🔄 Attempt {attempt}/{MAX_BUILD_ATTEMPTS}")
|
|||
|
|
if player:
|
|||
|
|
player.write_log(f"[Code] Attempt {attempt}...")
|
|||
|
|
|
|||
|
|
last_output = _run_file(path, args, timeout)
|
|||
|
|
|
|||
|
|
if not _has_error(last_output):
|
|||
|
|
msg = (
|
|||
|
|
f"Build complete, sir. "
|
|||
|
|
f"The code is working after {attempt} attempt{'s' if attempt > 1 else ''}. "
|
|||
|
|
f"Saved to {path}."
|
|||
|
|
)
|
|||
|
|
if speak: speak(msg)
|
|||
|
|
return f"{msg}\n\nOutput:\n{last_output}"
|
|||
|
|
|
|||
|
|
print(f"[Code] ⚠️ Error on attempt {attempt}, fixing...")
|
|||
|
|
if player:
|
|||
|
|
player.write_log(f"[Code] Fixing (attempt {attempt})...")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
code = _fix_code(code, last_output, description)
|
|||
|
|
_save_file(path, code)
|
|||
|
|
except Exception as e:
|
|||
|
|
msg = f"Could not fix code on attempt {attempt}: {e}"
|
|||
|
|
if speak: speak(msg)
|
|||
|
|
return msg
|
|||
|
|
|
|||
|
|
msg = (
|
|||
|
|
f"I was unable to build a working version after {MAX_BUILD_ATTEMPTS} attempts, sir. "
|
|||
|
|
f"The last error was: {last_output[:200]}"
|
|||
|
|
)
|
|||
|
|
if speak: speak(msg)
|
|||
|
|
return f"{msg}\n\nLast code saved to: {path}"
|
|||
|
|
|
|||
|
|
def _write_action(description, language, output_path, player) -> str:
|
|||
|
|
if not description:
|
|||
|
|
return "Please describe what you want me to write, sir."
|
|||
|
|
if player:
|
|||
|
|
player.write_log("[Code] Writing code...")
|
|||
|
|
try:
|
|||
|
|
code, path = _write(description, language, output_path, player)
|
|||
|
|
print(f"[Code] ✅ Written: {path}")
|
|||
|
|
return f"Code written. Saved to: {path}\n\nPreview:\n{_preview(code)}"
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"Could not generate code: {e}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _edit_action(file_path, instruction, player) -> str:
|
|||
|
|
if not file_path:
|
|||
|
|
return "Please provide a file path to edit, sir."
|
|||
|
|
if not instruction:
|
|||
|
|
return "Please describe what change to make, sir."
|
|||
|
|
|
|||
|
|
content, err = _read_file(file_path)
|
|||
|
|
if err:
|
|||
|
|
return err
|
|||
|
|
|
|||
|
|
if player:
|
|||
|
|
player.write_log("[Code] Editing file...")
|
|||
|
|
|
|||
|
|
model = _get_gemini()
|
|||
|
|
prompt = f"""You are an expert code editor.
|
|||
|
|
Apply the following change to the code below.
|
|||
|
|
Return ONLY the complete updated code — no explanation, no markdown, no backticks.
|
|||
|
|
|
|||
|
|
Change: {instruction}
|
|||
|
|
|
|||
|
|
Original code:
|
|||
|
|
{content}
|
|||
|
|
|
|||
|
|
Updated code:"""
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
response = model.generate_content(prompt)
|
|||
|
|
edited = _clean_code(response.text)
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"Could not edit code: {e}"
|
|||
|
|
|
|||
|
|
status = _save_file(Path(file_path), edited)
|
|||
|
|
print(f"[Code] ✅ Edited: {file_path}")
|
|||
|
|
return f"File edited. {status}\n\nPreview:\n{_preview(edited)}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _explain_action(file_path, code, player) -> str:
|
|||
|
|
if file_path and not code:
|
|||
|
|
code, err = _read_file(file_path)
|
|||
|
|
if err:
|
|||
|
|
return err
|
|||
|
|
if not code:
|
|||
|
|
return "Please provide code or a file path to explain, sir."
|
|||
|
|
|
|||
|
|
if player:
|
|||
|
|
player.write_log("[Code] Analyzing code...")
|
|||
|
|
|
|||
|
|
model = _get_gemini()
|
|||
|
|
prompt = f"""Explain what this code does in simple, clear language.
|
|||
|
|
Focus on: what it does, how it works, and any important details.
|
|||
|
|
Be concise — 3 to 6 sentences maximum.
|
|||
|
|
|
|||
|
|
Code:
|
|||
|
|
{code[:4000]}
|
|||
|
|
|
|||
|
|
Explanation:"""
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
response = model.generate_content(prompt)
|
|||
|
|
return response.text.strip()
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"Could not explain code: {e}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _run_action(file_path, args, timeout, player) -> str:
|
|||
|
|
if not file_path:
|
|||
|
|
return "Please provide a file path to run, sir."
|
|||
|
|
p = Path(file_path)
|
|||
|
|
if not p.exists():
|
|||
|
|
return f"File not found: {file_path}"
|
|||
|
|
if player:
|
|||
|
|
player.write_log(f"[Code] Running {p.name}...")
|
|||
|
|
return _run_file(p, args, timeout)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _optimize_action(file_path, code, language, output_path, player) -> str:
|
|||
|
|
|
|||
|
|
if file_path and not code:
|
|||
|
|
code, err = _read_file(file_path)
|
|||
|
|
if err:
|
|||
|
|
return err
|
|||
|
|
if not code:
|
|||
|
|
return "Please provide code or a file path to optimize, sir."
|
|||
|
|
|
|||
|
|
if player:
|
|||
|
|
player.write_log("[Code] Optimizing code...")
|
|||
|
|
|
|||
|
|
lang = language or "python"
|
|||
|
|
model = _get_gemini()
|
|||
|
|
|
|||
|
|
prompt = f"""You are an expert {lang} developer and code reviewer.
|
|||
|
|
Optimize the following code for:
|
|||
|
|
1. Performance — eliminate unnecessary operations, use efficient data structures
|
|||
|
|
2. Readability — clear variable names, proper formatting, logical structure
|
|||
|
|
3. Best practices — modern {lang} patterns, error handling, type hints if applicable
|
|||
|
|
4. Remove dead code, redundant comments, and unnecessary complexity
|
|||
|
|
|
|||
|
|
Return ONLY the optimized code — no explanation, no markdown, no backticks.
|
|||
|
|
|
|||
|
|
Original code:
|
|||
|
|
{code[:6000]}
|
|||
|
|
|
|||
|
|
Optimized code:"""
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
response = model.generate_content(prompt)
|
|||
|
|
optimized = _clean_code(response.text)
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"Could not optimize code: {e}"
|
|||
|
|
|
|||
|
|
# Kaydet
|
|||
|
|
if file_path:
|
|||
|
|
save_path = Path(file_path)
|
|||
|
|
else:
|
|||
|
|
save_path = _resolve_save_path(output_path, lang)
|
|||
|
|
|
|||
|
|
status = _save_file(save_path, optimized)
|
|||
|
|
print(f"[Code] ✅ Optimized: {save_path}")
|
|||
|
|
|
|||
|
|
original_lines = len(code.splitlines())
|
|||
|
|
optimized_lines = len(optimized.splitlines())
|
|||
|
|
diff = original_lines - optimized_lines
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
f"Code optimized. {status}\n"
|
|||
|
|
f"Lines: {original_lines} → {optimized_lines} "
|
|||
|
|
f"({'−' if diff > 0 else '+'}{abs(diff)} lines)\n\n"
|
|||
|
|
f"Preview:\n{_preview(optimized)}"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _screen_debug_action(description, file_path, player, speak=None) -> str:
|
|||
|
|
|
|||
|
|
if player:
|
|||
|
|
player.write_log("[Code] Taking screenshot for analysis...")
|
|||
|
|
|
|||
|
|
print("[Code] 📸 Capturing screen for debug...")
|
|||
|
|
|
|||
|
|
|
|||
|
|
screenshot_path = _take_screenshot()
|
|||
|
|
if not screenshot_path:
|
|||
|
|
return "Could not take screenshot, sir. Please make sure PyAutoGUI is installed."
|
|||
|
|
|
|||
|
|
|
|||
|
|
file_content = ""
|
|||
|
|
if file_path:
|
|||
|
|
file_content, err = _read_file(file_path)
|
|||
|
|
if err:
|
|||
|
|
print(f"[Code] ⚠️ Could not read file: {err}")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
from google import genai
|
|||
|
|
from google.genai import types
|
|||
|
|
|
|||
|
|
client = genai.Client(api_key=_get_api_key())
|
|||
|
|
|
|||
|
|
image_bytes = screenshot_path.read_bytes()
|
|||
|
|
image_base64 = _image_to_base64(screenshot_path)
|
|||
|
|
|
|||
|
|
user_question = description or "What error or problem do you see on the screen? How can it be fixed?"
|
|||
|
|
|
|||
|
|
context = ""
|
|||
|
|
if file_content:
|
|||
|
|
context = f"\n\nAdditionally, here is the related file content:\n```\n{file_content[:4000]}\n```"
|
|||
|
|
|
|||
|
|
analysis_prompt = f"""You are an expert programmer and debugger analyzing a screenshot.
|
|||
|
|
|
|||
|
|
User's question: {user_question}{context}
|
|||
|
|
|
|||
|
|
Please:
|
|||
|
|
1. Identify any errors, exceptions, or problems visible on the screen
|
|||
|
|
2. Explain what is causing the problem in simple terms
|
|||
|
|
3. Provide a concrete fix or solution
|
|||
|
|
4. If there's code visible, show the corrected version
|
|||
|
|
|
|||
|
|
Be specific and actionable. If you see an error message, quote it exactly."""
|
|||
|
|
|
|||
|
|
contents = [
|
|||
|
|
types.Part.from_bytes(data=image_bytes, mime_type="image/png"),
|
|||
|
|
analysis_prompt,
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
response = client.models.generate_content(
|
|||
|
|
model="gemini-2.5-flash",
|
|||
|
|
contents=contents,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
analysis = response.text.strip()
|
|||
|
|
print(f"[Code] ✅ Screen analysis complete")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
screenshot_path.unlink()
|
|||
|
|
except Exception:
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
if file_path and file_content:
|
|||
|
|
|
|||
|
|
code_match = re.search(r"```[a-zA-Z]*\n(.*?)```", analysis, re.DOTALL)
|
|||
|
|
if code_match:
|
|||
|
|
fixed_code = code_match.group(1).strip()
|
|||
|
|
save_path = Path(file_path)
|
|||
|
|
_save_file(save_path, fixed_code)
|
|||
|
|
analysis += f"\n\n✅ Fixed code has been saved to: {file_path}"
|
|||
|
|
print(f"[Code] ✅ Fixed code saved: {file_path}")
|
|||
|
|
|
|||
|
|
return analysis
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
screenshot_path.unlink()
|
|||
|
|
except Exception:
|
|||
|
|
pass
|
|||
|
|
return f"Screen analysis failed: {e}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def code_helper(
|
|||
|
|
parameters: dict,
|
|||
|
|
response=None,
|
|||
|
|
player=None,
|
|||
|
|
session_memory=None,
|
|||
|
|
speak=None
|
|||
|
|
) -> str:
|
|||
|
|
"""
|
|||
|
|
Called from main.py.
|
|||
|
|
|
|||
|
|
parameters:
|
|||
|
|
action : write | edit | explain | run | build | screen_debug | optimize | auto
|
|||
|
|
description : What the code should do / what change to make / what problem to analyze
|
|||
|
|
language : Programming language (default: python)
|
|||
|
|
output_path : Where to save — user specifies full path or filename
|
|||
|
|
file_path : Path to existing file (edit / explain / run / build / optimize)
|
|||
|
|
code : Raw code string (explain/optimize without a file)
|
|||
|
|
args : CLI argument list for run/build
|
|||
|
|
timeout : Execution timeout in seconds (default: 30)
|
|||
|
|
"""
|
|||
|
|
p = parameters or {}
|
|||
|
|
action = p.get("action", "auto").lower().strip()
|
|||
|
|
description = p.get("description", "").strip()
|
|||
|
|
language = p.get("language", "python").strip()
|
|||
|
|
output_path = p.get("output_path", "").strip()
|
|||
|
|
file_path = p.get("file_path", "").strip()
|
|||
|
|
code = p.get("code", "").strip()
|
|||
|
|
args = p.get("args", [])
|
|||
|
|
timeout = int(p.get("timeout", 30))
|
|||
|
|
|
|||
|
|
if action == "auto":
|
|||
|
|
action = _detect_intent(description, file_path, code)
|
|||
|
|
print(f"[Code] 🤖 Auto-detected: {action}")
|
|||
|
|
|
|||
|
|
if action == "write":
|
|||
|
|
return _write_action(description, language, output_path, player)
|
|||
|
|
|
|||
|
|
elif action == "edit":
|
|||
|
|
return _edit_action(
|
|||
|
|
file_path,
|
|||
|
|
description or p.get("instruction", ""),
|
|||
|
|
player
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
elif action == "explain":
|
|||
|
|
return _explain_action(file_path, code, player)
|
|||
|
|
|
|||
|
|
elif action == "run":
|
|||
|
|
return _run_action(file_path, args, timeout, player)
|
|||
|
|
|
|||
|
|
elif action == "build":
|
|||
|
|
return _build(description, language, output_path, args, timeout, speak, player)
|
|||
|
|
|
|||
|
|
elif action == "optimize":
|
|||
|
|
return _optimize_action(file_path, code, language, output_path, player)
|
|||
|
|
|
|||
|
|
elif action == "screen_debug":
|
|||
|
|
return _screen_debug_action(description, file_path, player, speak)
|
|||
|
|
|
|||
|
|
else:
|
|||
|
|
return f"Unknown action: '{action}'. Use write, edit, explain, run, build, optimize, or screen_debug."
|