rccopilot / app.py
drixo's picture
Update app.py
0b5541e verified
import os
import gradio as gr
from openai import OpenAI
import subprocess
import tempfile
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# --- Core logic ---
def analyze_code(language, code):
error_output = ""
if language.lower() == "python":
with tempfile.NamedTemporaryFile(delete=False, suffix=".py") as tmp:
tmp.write(code.encode("utf-8"))
tmp.flush()
try:
subprocess.run(
["python3", tmp.name],
check=True,
capture_output=True,
text=True,
timeout=5,
)
except subprocess.CalledProcessError as e:
error_output = e.stderr
except Exception as e:
error_output = str(e)
else:
error_output = "Automatic execution only supported for Python. Please paste your error manually."
if not error_output.strip():
error_output = "βœ… No runtime error detected. Let's review for logic or syntax improvements."
return help_with_code(language, code, error_output)
def help_with_code(language, code, error):
prompt = f"""
You are a skilled coding instructor identifying skill gaps in students learning {language}.
--- CODE START ---
{code}
--- CODE END ---
--- ERROR ---
{error}
--- END ERROR ---
Your task:
1. Identify my coding skill gaps (syntax, logic, structure, or language fundamentals).
2. Explain clearly what went wrong and why.
3. Suggest one or two short, focused practice exercises to improve that specific skill.
4. Do NOT rewrite or fix the code.
"""
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.4,
)
return response.choices[0].message.content.strip()
except Exception as e:
err_msg = str(e)
# βœ… Handle inactive billing error cleanly
if "billing_not_active" in err_msg or "Error code: 429" in err_msg:
return (
"⚠️ Please contact an RC staff member β€” the billing is currently not active."
)
# Generic fallback
return "⚠️ An unexpected error occurred. Please try again later or verify your API key."
# --- Gradio UI ---
with gr.Blocks(
theme="soft",
css="""
/* === Apply theme colors immediately === */
body, .gradio-container, .dark, [data-theme="dark"] {
background-color: var(--body-background-fill) !important;
color: var(--body-text-color) !important;
transition: none !important;
}
/* === Base Theme Variables (Light Mode) === */
:root {
--body-background-fill: #ffffff;
--body-text-color: #1a1a1a;
--codebox-background: #f8f8f8;
--codebox-border: #EDEBEB;
--scrollbar-thumb: #c1c1c1;
--scrollbar-track: #f8f8f8;
}
/* πŸŒ™ Dark Mode Theme */
:root .dark, [data-theme="dark"] {
--body-background-fill: #1e1e1f !important;
--body-text-color: #e5e5e5 !important;
--codebox-background: #2a2a2b !important;
--codebox-border: #3a3a3b !important;
--scrollbar-thumb: #555 !important;
--scrollbar-track: #2a2a2b !important;
}
/* 🧱 Code boxes, dropdowns, textareas unified */
#code-box,
select,
textarea,
pre,
code {
background-color: var(--codebox-background) !important;
border: 1px solid var(--codebox-border) !important;
border-radius: 6px !important;
color: var(--body-text-color) !important;
transition: none !important;
}
/* ✨ Consistent scrollbar theme */
#code-box::-webkit-scrollbar,
textarea::-webkit-scrollbar,
pre::-webkit-scrollbar {
width: 8px;
height: 8px;
}
#code-box::-webkit-scrollbar-thumb,
textarea::-webkit-scrollbar-thumb,
pre::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb);
border-radius: 10px;
}
#code-box::-webkit-scrollbar-track,
textarea::-webkit-scrollbar-track,
pre::-webkit-scrollbar-track {
background-color: var(--scrollbar-track);
}
/* 🎯 Submit button */
#submit-btn {
background-color: #e40014 !important;
color: white !important;
border: none !important;
border-radius: 6px !important;
transition: background-color 0.2s ease-in-out;
margin-top: 6px !important;
width: 100%;
}
#submit-btn:hover {
background-color: #c00010 !important;
}
/* 🧩 Compact layout */
.gr-block, .gr-form, .gr-column, .gr-row {
gap: 4px !important;
padding: 0 !important;
margin: 0 !important;
}
.gr-markdown {
margin: 0 !important;
padding: 2px !important;
line-height: 1.4 !important;
}
/* βœ… Feedback area spacing */
.gr-markdown p {
margin-top: 0 !important;
margin-bottom: 4px !important;
}
/* Prevent reflow on feedback render */
.gr-column > *:not(:last-child) {
margin-bottom: 4px !important;
}
"""
) as demo:
with gr.Row(equal_height=True):
with gr.Column(scale=2):
# Removed markdown labels to reduce vertical spacing
language = gr.Dropdown(
["JavaScript", "HTML", "CSS", "Python"],
value="Python",
show_label=True,
label="Language",
)
code_input = gr.Code(
language="python",
lines=22,
show_label=True,
label="Your Code",
elem_id="code-box",
)
analyze_button = gr.Button("Submit", variant="secondary", elem_id="submit-btn")
with gr.Column(scale=1):
output = gr.Markdown("*Feedback will show here!*")
analyze_button.click(analyze_code, inputs=[language, code_input], outputs=output)
demo.launch()