Kiy-K commited on
Commit
e49254c
·
verified ·
1 Parent(s): 71085a9

New UI animations!

Browse files
Files changed (1) hide show
  1. app.py +40 -30
app.py CHANGED
@@ -8,6 +8,7 @@ import json
8
  import time
9
  import base64
10
  import tempfile
 
11
  from datetime import datetime, timedelta
12
  from openai import OpenAI
13
 
@@ -46,7 +47,12 @@ SESSION_TIMEOUT_SEC = 15 * 60
46
  def clean_thought_process(text):
47
  """Removes the <think>...</think> blocks from the text to prevent leaks."""
48
  if not text: return ""
49
- return re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL).strip()
 
 
 
 
 
50
 
51
  def export_script(code):
52
  if not code.strip(): return None
@@ -67,44 +73,37 @@ def detect_language(filename):
67
  return "python"
68
 
69
  def robust_search(query):
70
- if not SEARCH_AVAILABLE: return json.dumps({"error": "Missing duckduckgo-search"})
71
  try:
72
  results = []
73
  with DDGS() as ddgs:
74
- # Fetch 5 results
75
  ddg_gen = ddgs.text(query, max_results=5)
76
  if ddg_gen:
77
  for r in ddg_gen:
78
- results.append({
79
- "title": r.get('title'),
80
- "link": r.get('href'),
81
- "snippet": r.get('body')
82
- })
83
- return json.dumps(results, indent=2)
84
  except Exception as e:
85
- return json.dumps({"error": str(e)})
86
 
87
  # ==================== TOOL: E2B SANDBOX (POLYGLOT) ====================
88
 
89
  def execute_code_e2b(project_state, mode="Code Mode"):
90
  """
91
  Polymorphic execution engine with Mode-Gated Internet Access.
92
- - Web Mode: Internet ON
93
- - Other Modes: Internet OFF (Air-gapped)
94
  """
95
  if not E2B_AVAILABLE or not E2B_API_KEY:
96
  return "❌ Error: E2B API Key missing. Cannot execute code."
97
 
98
- # Gate Internet Access based on Mode
99
  enable_internet = (mode == "Web Mode")
100
-
101
  logger.info(f"⚡ Executing in E2B Sandbox (Mode: {mode}, Internet: {enable_internet})...")
102
 
103
  try:
104
  with Sandbox.create(allow_internet_access=enable_internet) as sandbox:
105
  # 1. Write all auxiliary files to the sandbox filesystem
106
  for filename, content in project_state.items():
107
- if filename not in ["main.py", "main.cpp"]: # Write aux files first
108
  sandbox.files.write(filename, content)
109
 
110
  output_log = ""
@@ -115,7 +114,7 @@ def execute_code_e2b(project_state, mode="Code Mode"):
115
  if "main.cpp" in project_state:
116
  logger.info("⚙️ Detected C++ Project. Compiling via Python wrapper...")
117
 
118
- # Write C++ source
119
  sandbox.files.write("main.cpp", project_state["main.cpp"])
120
 
121
  # Trojan Horse: Use Python to manage the compilation process reliably
@@ -140,7 +139,7 @@ else:
140
  """
141
  execution = sandbox.run_code(cpp_runner_script)
142
 
143
- # FIXED: Properly join list of strings into a single string
144
  if execution.logs.stdout:
145
  output_log += "".join(execution.logs.stdout) + "\n"
146
  if execution.logs.stderr:
@@ -155,7 +154,6 @@ else:
155
 
156
  execution = sandbox.run_code(code_to_run)
157
 
158
- # FIXED: Properly join list of strings
159
  if execution.logs.stdout:
160
  log_str = "".join(execution.logs.stdout)
161
  output_log += f"📄 **STDOUT**:\n```\n{log_str}\n```"
@@ -202,7 +200,7 @@ CRITICAL INSTRUCTIONS:
202
  elif mode == "Visualization Mode":
203
  return base_prompt + "\n\nMODE: VISUALIZATION\n- Focus on matplotlib/seaborn.\n- Create visually striking plots.\n- NO INTERNET ACCESS."
204
  elif mode == "Web Mode":
205
- return base_prompt + "\n\nMODE: WEB ARCHITECT\n- Focus on modern web technologies (Flask, HTML, CSS).\n- **YOU HAVE INTERNET ACCESS**. You can use `requests` to fetch real data.\n- Structure code for web servers or API clients."
206
  elif mode == "C++ Mode":
207
  return base_prompt + "\n\nMODE: C++ DEVELOPER\n- Focus on modern C++ (17/20).\n- Use iostream, vector, string.\n- Ensure code compiles with g++.\n- NO INTERNET ACCESS."
208
  else: # Code Mode
@@ -215,7 +213,8 @@ def parse_code_update(text, current_project, active_file):
215
  """
216
  clean_text = clean_thought_process(text)
217
 
218
- # Matches ```lang ... ```
 
219
  pattern = (
220
  r"```" # Opening backticks
221
  r"(?:python|cpp|c\+\+|javascript|html|css)?" # Optional language identifier
@@ -247,11 +246,14 @@ def process_query(user_input, session_data, project_state, active_file, mode):
247
  yield history, project_state, project_state[active_file], session_data
248
  return
249
 
 
250
  history.append({"role": "user", "content": user_input})
251
  history.append({"role": "assistant", "content": f"🧠 *Fyodor is thinking in {mode}...*"})
252
 
 
253
  yield history, project_state, project_state[active_file], session_data
254
 
 
255
  sys_prompt = get_system_prompt(mode)
256
 
257
  project_context = "\n\n=== CURRENT PROJECT FILES ===\n"
@@ -260,6 +262,7 @@ def process_query(user_input, session_data, project_state, active_file, mode):
260
 
261
  messages = [{"role": "system", "content": sys_prompt + project_context}]
262
 
 
263
  for msg in history[:-2][-8:]:
264
  if isinstance(msg, dict):
265
  if msg['role'] == 'user':
@@ -312,7 +315,6 @@ def manual_run_project(project_state, session_data, mode):
312
  if session_data is None: session_data = init_session()
313
  history = session_data["history"]
314
  history.append({"role": "user", "content": "▶️ **Run Project (Manual)**"})
315
- # PASS MODE TO EXECUTOR
316
  result = execute_code_e2b(project_state, mode=mode)
317
  history.append({"role": "assistant", "content": f"**Execution Result:**\n\n{result}"})
318
  return history, session_data
@@ -324,7 +326,7 @@ def run_code_review(code, session_data):
324
  history.append({"role": "assistant", "content": "🤔 *Reviewing...*"})
325
 
326
  messages = [
327
- {"role": "system", "content": "You are a Senior Architect. Review the code for security and efficiency."},
328
  {"role": "user", "content": code}
329
  ]
330
  try:
@@ -336,6 +338,11 @@ def run_code_review(code, session_data):
336
  history[-1]["content"] = f"❌ Review Failed: {e}"
337
  return history, session_data
338
 
 
 
 
 
 
339
  def update_active_file(selected_file, project_data):
340
  lang = detect_language(selected_file)
341
  return gr.update(value=project_data.get(selected_file, ""), language=lang)
@@ -379,10 +386,11 @@ body, .gradio-container { background-color: var(--bg-dark) !important; color: va
379
  .chatbot .bot.message { background-color: transparent !important; border-left: 2px solid #333 !important; }
380
  textarea, input[type="text"] { background-color: #3c3c3c !important; border: 1px solid #3c3c3c !important; color: #fff !important; border-radius: 2px !important; }
381
  textarea:focus, input[type="text"]:focus { border-color: var(--accent) !important; box-shadow: 0 0 0 1px var(--accent) !important; }
382
- button { border-radius: 2px !important; text-transform: uppercase; font-weight: 600; letter-spacing: 0.5px; font-size: 12px !important; }
383
  button.primary { background: var(--accent) !important; color: #fff !important; border: none !important; }
 
384
  button.secondary { background: #333 !important; color: #fff !important; border: 1px solid #444 !important; }
385
- button:hover { filter: brightness(1.1); }
386
  .cm-editor { border: 1px solid var(--border-col) !important; border-radius: 0 !important; }
387
  #top-bar { background-color: var(--sidebar-bg); border-bottom: 1px solid var(--border-col); min-height: 50px; padding: 0 10px !important; display: flex; align-items: center; justify-content: space-between; }
388
  h1 { font-size: 1.2rem !important; color: var(--text-main) !important; font-weight: normal !important; margin: 0 !important; padding: 0 !important; background-color: transparent !important; border: none !important; display: flex; align-items: center; }
@@ -404,14 +412,16 @@ def run_app():
404
  sidebar_visible = gr.State(True)
405
 
406
  with gr.Column(elem_classes="main-panel"):
 
407
  with gr.Row(elem_id="top-bar"):
408
  with gr.Row(scale=1): gr.Markdown("# FYODOR IDE // PRO")
409
  with gr.Row(scale=1):
410
  sidebar_toggle_btn = gr.Button("👁️ Toggle Sidebar", size="sm", variant="secondary")
411
  timer_display = gr.Textbox(value="READY", show_label=False, interactive=False, container=False, elem_classes="status-label")
412
 
 
413
  with gr.Row():
414
- # LEFT: EDITOR
415
  with gr.Column(scale=4):
416
  with gr.Row(elem_classes="file-tabs"):
417
  file_dropdown = gr.Dropdown(choices=["main.py"], value="main.py", show_label=False, container=False, scale=2)
@@ -425,13 +435,14 @@ def run_app():
425
  run_manual_btn = gr.Button("▶ EXECUTE SCRIPT", variant="primary")
426
  review_btn = gr.Button("🕵 REVIEW CODE", size="sm", variant="secondary")
427
 
428
- # CENTER: TERMINAL
429
  with gr.Column(scale=2):
430
  mode_radio = gr.Radio(choices=["Code Mode", "C++ Mode", "Data Mode", "Web Mode"], value="Code Mode", label="SYSTEM MODE", elem_classes="mode-radio")
431
  chatbot = gr.Chatbot(label="TERMINAL", height=600, render_markdown=True, elem_classes="chatbot", show_label=False)
432
  with gr.Row():
433
  msg_input = gr.Textbox(placeholder="Type command...", show_label=False, scale=4, container=False)
434
  run_btn = gr.Button("RUN", variant="primary", scale=1)
 
435
 
436
  # RIGHT: SIDEBAR
437
  with gr.Column(scale=1, min_width=250, visible=True) as sidebar_col:
@@ -465,17 +476,16 @@ def run_app():
465
  run_btn.click(process_query, [msg_input, session_state, project_state, active_file_state, mode_radio], [chatbot, project_state, code_editor, session_state])
466
 
467
  file_dropdown.change(update_active_file, [file_dropdown, project_state], [code_editor]).then(lambda f: f, [file_dropdown], [active_file_state])
468
-
469
  code_editor.change(save_file_change, [code_editor, active_file_state, project_state], [project_state])
470
  save_btn.click(manual_save_file, [code_editor, active_file_state, project_state], [project_state])
471
-
472
- # New File: Updates Dropdown, Project State, and Code Editor (Value+Lang)
473
  new_file_btn.click(create_new_file, [new_file_txt, project_state], [file_dropdown, project_state, code_editor])
474
 
475
- # PASS MODE RADIO TO MANUAL RUN
476
  run_manual_btn.click(manual_run_project, [project_state, session_state, mode_radio], [chatbot, session_state])
477
  review_btn.click(run_code_review, [code_editor, session_state], [chatbot, session_state])
478
 
 
 
 
479
  mini_input.submit(lambda m, h: (h or []) + [{"role": "user", "content": m}, {"role": "assistant", "content": robust_search(m)}], [mini_input, mini_chat], [mini_chat])
480
  mini_btn.click(lambda m, h: (h or []) + [{"role": "user", "content": m}, {"role": "assistant", "content": robust_search(m)}], [mini_input, mini_chat], [mini_chat])
481
 
 
8
  import time
9
  import base64
10
  import tempfile
11
+ import subprocess
12
  from datetime import datetime, timedelta
13
  from openai import OpenAI
14
 
 
47
  def clean_thought_process(text):
48
  """Removes the <think>...</think> blocks from the text to prevent leaks."""
49
  if not text: return ""
50
+ # Remove completed blocks
51
+ text = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL)
52
+ # Remove pending/unclosed blocks
53
+ if "<think>" in text:
54
+ text = text.split("<think>")[0]
55
+ return text.strip()
56
 
57
  def export_script(code):
58
  if not code.strip(): return None
 
73
  return "python"
74
 
75
  def robust_search(query):
76
+ if not SEARCH_AVAILABLE: return "Error: Missing duckduckgo-search"
77
  try:
78
  results = []
79
  with DDGS() as ddgs:
 
80
  ddg_gen = ddgs.text(query, max_results=5)
81
  if ddg_gen:
82
  for r in ddg_gen:
83
+ results.append(f"### [{r.get('title')}]({r.get('href')})\n{r.get('body')}\n")
84
+
85
+ if not results: return "⚠️ No results found."
86
+ return "\n".join(results)
 
 
87
  except Exception as e:
88
+ return f"❌ Search Error: {str(e)}"
89
 
90
  # ==================== TOOL: E2B SANDBOX (POLYGLOT) ====================
91
 
92
  def execute_code_e2b(project_state, mode="Code Mode"):
93
  """
94
  Polymorphic execution engine with Mode-Gated Internet Access.
 
 
95
  """
96
  if not E2B_AVAILABLE or not E2B_API_KEY:
97
  return "❌ Error: E2B API Key missing. Cannot execute code."
98
 
 
99
  enable_internet = (mode == "Web Mode")
 
100
  logger.info(f"⚡ Executing in E2B Sandbox (Mode: {mode}, Internet: {enable_internet})...")
101
 
102
  try:
103
  with Sandbox.create(allow_internet_access=enable_internet) as sandbox:
104
  # 1. Write all auxiliary files to the sandbox filesystem
105
  for filename, content in project_state.items():
106
+ if filename not in ["main.py", "main.cpp"]:
107
  sandbox.files.write(filename, content)
108
 
109
  output_log = ""
 
114
  if "main.cpp" in project_state:
115
  logger.info("⚙️ Detected C++ Project. Compiling via Python wrapper...")
116
 
117
+ # Write C++ source explicitly ensures it's fresh
118
  sandbox.files.write("main.cpp", project_state["main.cpp"])
119
 
120
  # Trojan Horse: Use Python to manage the compilation process reliably
 
139
  """
140
  execution = sandbox.run_code(cpp_runner_script)
141
 
142
+ # Properly join list of strings into a single string
143
  if execution.logs.stdout:
144
  output_log += "".join(execution.logs.stdout) + "\n"
145
  if execution.logs.stderr:
 
154
 
155
  execution = sandbox.run_code(code_to_run)
156
 
 
157
  if execution.logs.stdout:
158
  log_str = "".join(execution.logs.stdout)
159
  output_log += f"📄 **STDOUT**:\n```\n{log_str}\n```"
 
200
  elif mode == "Visualization Mode":
201
  return base_prompt + "\n\nMODE: VISUALIZATION\n- Focus on matplotlib/seaborn.\n- Create visually striking plots.\n- NO INTERNET ACCESS."
202
  elif mode == "Web Mode":
203
+ return base_prompt + "\n\nMODE: WEB ARCHITECT\n- Focus on modern web technologies (Flask, HTML, CSS).\n- **YOU HAVE INTERNET ACCESS**. Use `requests` to fetch real data.\n- Structure code for web servers or API clients."
204
  elif mode == "C++ Mode":
205
  return base_prompt + "\n\nMODE: C++ DEVELOPER\n- Focus on modern C++ (17/20).\n- Use iostream, vector, string.\n- Ensure code compiles with g++.\n- NO INTERNET ACCESS."
206
  else: # Code Mode
 
213
  """
214
  clean_text = clean_thought_process(text)
215
 
216
+ # Robust Regex for code blocks (Python, C++, JS, HTML, CSS)
217
+ # Using multi-line string construction to prevent truncation errors
218
  pattern = (
219
  r"```" # Opening backticks
220
  r"(?:python|cpp|c\+\+|javascript|html|css)?" # Optional language identifier
 
246
  yield history, project_state, project_state[active_file], session_data
247
  return
248
 
249
+ # Update Internal State
250
  history.append({"role": "user", "content": user_input})
251
  history.append({"role": "assistant", "content": f"🧠 *Fyodor is thinking in {mode}...*"})
252
 
253
+ # Yield UI Update
254
  yield history, project_state, project_state[active_file], session_data
255
 
256
+ # Context Construction
257
  sys_prompt = get_system_prompt(mode)
258
 
259
  project_context = "\n\n=== CURRENT PROJECT FILES ===\n"
 
262
 
263
  messages = [{"role": "system", "content": sys_prompt + project_context}]
264
 
265
+ # Build Chat History for API
266
  for msg in history[:-2][-8:]:
267
  if isinstance(msg, dict):
268
  if msg['role'] == 'user':
 
315
  if session_data is None: session_data = init_session()
316
  history = session_data["history"]
317
  history.append({"role": "user", "content": "▶️ **Run Project (Manual)**"})
 
318
  result = execute_code_e2b(project_state, mode=mode)
319
  history.append({"role": "assistant", "content": f"**Execution Result:**\n\n{result}"})
320
  return history, session_data
 
326
  history.append({"role": "assistant", "content": "🤔 *Reviewing...*"})
327
 
328
  messages = [
329
+ {"role": "system", "content": "Senior Architect Code Review. Check for security and efficiency."},
330
  {"role": "user", "content": code}
331
  ]
332
  try:
 
338
  history[-1]["content"] = f"❌ Review Failed: {e}"
339
  return history, session_data
340
 
341
+ def clear_session_chat(session_data):
342
+ if session_data is None: session_data = init_session()
343
+ session_data["history"] = []
344
+ return [], session_data
345
+
346
  def update_active_file(selected_file, project_data):
347
  lang = detect_language(selected_file)
348
  return gr.update(value=project_data.get(selected_file, ""), language=lang)
 
386
  .chatbot .bot.message { background-color: transparent !important; border-left: 2px solid #333 !important; }
387
  textarea, input[type="text"] { background-color: #3c3c3c !important; border: 1px solid #3c3c3c !important; color: #fff !important; border-radius: 2px !important; }
388
  textarea:focus, input[type="text"]:focus { border-color: var(--accent) !important; box-shadow: 0 0 0 1px var(--accent) !important; }
389
+ button { border-radius: 2px !important; text-transform: uppercase; font-weight: 600; letter-spacing: 0.5px; font-size: 12px !important; transition: all 0.2s ease-in-out !important; }
390
  button.primary { background: var(--accent) !important; color: #fff !important; border: none !important; }
391
+ button.primary:hover { background-color: #4DA2E5 !important; box-shadow: 0 0 8px rgba(58, 150, 221, 0.4); }
392
  button.secondary { background: #333 !important; color: #fff !important; border: 1px solid #444 !important; }
393
+ button.secondary:hover { background-color: #444 !important; border-color: #555 !important; }
394
  .cm-editor { border: 1px solid var(--border-col) !important; border-radius: 0 !important; }
395
  #top-bar { background-color: var(--sidebar-bg); border-bottom: 1px solid var(--border-col); min-height: 50px; padding: 0 10px !important; display: flex; align-items: center; justify-content: space-between; }
396
  h1 { font-size: 1.2rem !important; color: var(--text-main) !important; font-weight: normal !important; margin: 0 !important; padding: 0 !important; background-color: transparent !important; border: none !important; display: flex; align-items: center; }
 
412
  sidebar_visible = gr.State(True)
413
 
414
  with gr.Column(elem_classes="main-panel"):
415
+ # Top Bar
416
  with gr.Row(elem_id="top-bar"):
417
  with gr.Row(scale=1): gr.Markdown("# FYODOR IDE // PRO")
418
  with gr.Row(scale=1):
419
  sidebar_toggle_btn = gr.Button("👁️ Toggle Sidebar", size="sm", variant="secondary")
420
  timer_display = gr.Textbox(value="READY", show_label=False, interactive=False, container=False, elem_classes="status-label")
421
 
422
+ # Workspace
423
  with gr.Row():
424
+ # Editor (Left)
425
  with gr.Column(scale=4):
426
  with gr.Row(elem_classes="file-tabs"):
427
  file_dropdown = gr.Dropdown(choices=["main.py"], value="main.py", show_label=False, container=False, scale=2)
 
435
  run_manual_btn = gr.Button("▶ EXECUTE SCRIPT", variant="primary")
436
  review_btn = gr.Button("🕵 REVIEW CODE", size="sm", variant="secondary")
437
 
438
+ # Terminal (Right)
439
  with gr.Column(scale=2):
440
  mode_radio = gr.Radio(choices=["Code Mode", "C++ Mode", "Data Mode", "Web Mode"], value="Code Mode", label="SYSTEM MODE", elem_classes="mode-radio")
441
  chatbot = gr.Chatbot(label="TERMINAL", height=600, render_markdown=True, elem_classes="chatbot", show_label=False)
442
  with gr.Row():
443
  msg_input = gr.Textbox(placeholder="Type command...", show_label=False, scale=4, container=False)
444
  run_btn = gr.Button("RUN", variant="primary", scale=1)
445
+ clear_btn = gr.Button("🗑️", variant="secondary", scale=0, min_width=40)
446
 
447
  # RIGHT: SIDEBAR
448
  with gr.Column(scale=1, min_width=250, visible=True) as sidebar_col:
 
476
  run_btn.click(process_query, [msg_input, session_state, project_state, active_file_state, mode_radio], [chatbot, project_state, code_editor, session_state])
477
 
478
  file_dropdown.change(update_active_file, [file_dropdown, project_state], [code_editor]).then(lambda f: f, [file_dropdown], [active_file_state])
 
479
  code_editor.change(save_file_change, [code_editor, active_file_state, project_state], [project_state])
480
  save_btn.click(manual_save_file, [code_editor, active_file_state, project_state], [project_state])
 
 
481
  new_file_btn.click(create_new_file, [new_file_txt, project_state], [file_dropdown, project_state, code_editor])
482
 
 
483
  run_manual_btn.click(manual_run_project, [project_state, session_state, mode_radio], [chatbot, session_state])
484
  review_btn.click(run_code_review, [code_editor, session_state], [chatbot, session_state])
485
 
486
+ clear_btn.click(clear_session_chat, [session_state], [chatbot, session_state])
487
+
488
+ # Mini Agent: DICT FORMAT (Gradio 6)
489
  mini_input.submit(lambda m, h: (h or []) + [{"role": "user", "content": m}, {"role": "assistant", "content": robust_search(m)}], [mini_input, mini_chat], [mini_chat])
490
  mini_btn.click(lambda m, h: (h or []) + [{"role": "user", "content": m}, {"role": "assistant", "content": robust_search(m)}], [mini_input, mini_chat], [mini_chat])
491