Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -17,104 +17,98 @@ if API_KEY:
|
|
17 |
else:
|
18 |
print("FATAL: MISTRAL_API_KEY is not set in Space Secrets.")
|
19 |
|
20 |
-
# --- 2. ๋ฐฑ์๋ ํต์ฌ ๊ธฐ๋ฅ ---
|
21 |
def generate_c_code(description: str) -> str:
|
22 |
if not CLIENT: return "Error: Mistral API key not configured."
|
23 |
-
prompt = f"Generate a complete, compilable C code for this request: '{description}'. ONLY output the raw C code
|
24 |
messages = [{"role": "user", "content": prompt}]
|
25 |
response = CLIENT.chat(model="codestral-latest", messages=messages)
|
26 |
-
|
27 |
-
if "```c" in code:
|
28 |
-
code = code.split("```c")[1].split("```")[0].strip()
|
29 |
-
elif "```" in code:
|
30 |
-
code = code.split("```")[1].split("```")[0].strip()
|
31 |
-
return code
|
32 |
|
33 |
def compile_and_run_c_code(code: str) -> str:
|
34 |
try:
|
35 |
-
with open("main.c", "w", encoding='utf-8') as f:
|
36 |
-
|
37 |
-
compile_proc
|
38 |
-
|
39 |
-
|
40 |
-
)
|
41 |
-
if compile_proc.returncode != 0:
|
42 |
-
return f"--- COMPILATION FAILED ---\n{compile_proc.stderr}"
|
43 |
-
run_proc = subprocess.run(
|
44 |
-
["./main.out"], capture_output=True, text=True, timeout=15
|
45 |
-
)
|
46 |
-
if run_proc.returncode != 0:
|
47 |
-
return f"--- RUNTIME ERROR ---\n{run_proc.stderr}"
|
48 |
output = run_proc.stdout
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
def agent_chat(history: list[dict[str, str]]):
|
57 |
-
if not CLIENT:
|
58 |
-
history.append({"role": "assistant", "content": "MISTRAL_API_KEY๊ฐ Space Secrets์ ์ค์ ๋์ง ์์์ต๋๋ค."})
|
59 |
-
return history
|
60 |
-
|
61 |
-
# ์ฌ์ฉ์์ ๋ง์ง๋ง ๋ฉ์์ง๊ฐ history์ ๋ง์ง๋ง์ ์์ต๋๋ค.
|
62 |
-
message = history[-1]["content"]
|
63 |
-
lower_message = message.lower()
|
64 |
-
bot_response = ""
|
65 |
-
|
66 |
-
# API์ ๋ณด๋ผ ๋ฉ์์ง๋ ํ์ฌ ๋ํ ์ ์ฒด์
๋๋ค.
|
67 |
-
messages_for_api = history
|
68 |
-
|
69 |
-
if "compile" in lower_message or "run" in lower_message or "์คํ" in lower_message:
|
70 |
-
code_to_run = ""
|
71 |
-
# ์์ ์ ์ ์ธํ ์ด์ ๋ํ์์ ์ฝ๋ ์ฐพ๊ธฐ
|
72 |
-
for item in reversed(history[:-1]):
|
73 |
-
if item.get("role") == "assistant" and "```c" in item.get("content", ""):
|
74 |
-
code_to_run = item["content"].split("```c")[1].split("```")[0].strip()
|
75 |
-
break
|
76 |
-
if not code_to_run:
|
77 |
-
bot_response = "์ปดํ์ผํ ์ฝ๋๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ๋จผ์ ์ฝ๋๋ฅผ ์์ฑํด์ฃผ์ธ์."
|
78 |
-
else:
|
79 |
-
bot_response = compile_and_run_c_code(code_to_run)
|
80 |
-
|
81 |
-
elif "generate" in lower_message or "create" in lower_message or "๋ง๋ค์ด์ค" in lower_message or "์ง์ค" in lower_message:
|
82 |
-
generated_code = generate_c_code(message)
|
83 |
-
bot_response = f"์ฝ๋๊ฐ ์์ฑ๋์์ต๋๋ค.\n\n```c\n{generated_code}\n```"
|
84 |
-
|
85 |
-
else:
|
86 |
-
response = CLIENT.chat(model="codestral-latest", messages=messages_for_api)
|
87 |
-
bot_response = response.choices[0].message.content
|
88 |
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
-
# ---
|
93 |
-
|
94 |
-
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
with gr.Tabs():
|
97 |
-
with gr.TabItem("
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
|
112 |
with gr.TabItem("๐ ๏ธ MCP Tools API"):
|
113 |
gr.Markdown("## Available MCP Tools\nThese APIs can be used by any MCP-compliant client.")
|
114 |
with gr.Accordion("Tool: Generate C Code", open=False):
|
115 |
gr.Interface(fn=generate_c_code, inputs="text", outputs=gr.Code(language="c", label="Generated C Code"))
|
116 |
with gr.Accordion("Tool: Compile & Run C Code", open=False):
|
117 |
-
gr.Interface(fn=compile_and_run_c_code, inputs=gr.Code(language="c"
|
|
|
|
|
118 |
|
119 |
if __name__ == "__main__":
|
120 |
-
demo.
|
|
|
17 |
else:
|
18 |
print("FATAL: MISTRAL_API_KEY is not set in Space Secrets.")
|
19 |
|
20 |
+
# --- 2. ๋ฐฑ์๋ ํต์ฌ ๊ธฐ๋ฅ ํจ์ ---
|
21 |
def generate_c_code(description: str) -> str:
|
22 |
if not CLIENT: return "Error: Mistral API key not configured."
|
23 |
+
prompt = f"You are a C programming expert. Generate a complete, compilable C code for this request: '{description}'. ONLY output the raw C code, without any markdown formatting or explanations."
|
24 |
messages = [{"role": "user", "content": prompt}]
|
25 |
response = CLIENT.chat(model="codestral-latest", messages=messages)
|
26 |
+
return response.choices[0].message.content.strip()
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
def compile_and_run_c_code(code: str) -> str:
|
29 |
try:
|
30 |
+
with open("main.c", "w", encoding='utf-8') as f: f.write(code)
|
31 |
+
compile_proc = subprocess.run(["gcc", "main.c", "-o", "main.out", "-lm", "-w"], capture_output=True, text=True, timeout=15)
|
32 |
+
if compile_proc.returncode != 0: return f"--- COMPILATION FAILED ---\n{compile_proc.stderr}"
|
33 |
+
run_proc = subprocess.run(["./main.out"], capture_output=True, text=True, timeout=15)
|
34 |
+
if run_proc.returncode != 0: return f"--- RUNTIME ERROR ---\n{run_proc.stderr}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
output = run_proc.stdout
|
36 |
+
return f"--- EXECUTION SUCCEEDED ---\n{output}" if output.strip() else "--- EXECUTION SUCCEEDED ---\n(No output was produced)"
|
37 |
+
except Exception as e: return f"--- SYSTEM ERROR ---\nAn unexpected error occurred: {str(e)}"
|
38 |
+
|
39 |
+
def analyze_and_refactor_code(code: str, instruction: str) -> str:
|
40 |
+
if not CLIENT: return "Error: Mistral API key not configured."
|
41 |
+
prompt = f"""You are a senior C code reviewer. Analyze the following C code based on the user's instruction.
|
42 |
+
Provide a clear, concise response. If refactoring, provide the complete improved code in a C code block.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
+
Instruction: '{instruction}'
|
45 |
+
|
46 |
+
C Code to Analyze:
|
47 |
+
```c
|
48 |
+
{code}
|
49 |
+
```"""
|
50 |
+
messages = [{"role": "user", "content": prompt}]
|
51 |
+
response = CLIENT.chat(model="codestral-latest", messages=messages)
|
52 |
+
return response.choices[0].message.content
|
53 |
|
54 |
+
# --- 3. ๋ฉ์ธ ์์ด์ ํธ ๋ก์ง ---
|
55 |
+
def agent_logic(code: str, instruction: str):
|
56 |
+
if not instruction: return "Error: Instruction cannot be empty."
|
57 |
|
58 |
+
lower_instruction = instruction.lower()
|
59 |
+
|
60 |
+
if "compile" in lower_instruction or "run" in lower_instruction:
|
61 |
+
if not code: return "Error: Code editor is empty. Nothing to compile."
|
62 |
+
return compile_and_run_c_code(code)
|
63 |
+
|
64 |
+
elif "generate" in lower_instruction or "create" in lower_instruction or "๋ง๋ค์ด์ค" in lower_instruction:
|
65 |
+
# ์๋ก์ด ์ฝ๋๋ฅผ ์์ฑํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ฝ๋ ์๋ํฐ์ ์ง์ ๋ฐํ
|
66 |
+
new_code = generate_c_code(instruction)
|
67 |
+
# ์ถ๋ ฅ์ ์ฝ๋ ์๋ํฐ๋ก, ๊ฒฐ๊ณผ์ฐฝ์๋ ์ฑ๊ณต ๋ฉ์์ง
|
68 |
+
return new_code, f"Code generation successful. The new code is now in the editor."
|
69 |
+
|
70 |
+
else: # Refactor, analyze, add comments, etc.
|
71 |
+
if not code: return "Error: Code editor is empty. Nothing to analyze."
|
72 |
+
# ๋ถ์/๋ฆฌํฉํ ๋ง ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐ๊ณผ์ฐฝ์ ๋ฐํ
|
73 |
+
analysis_result = analyze_and_refactor_code(code, instruction)
|
74 |
+
# ์ฝ๋ ์๋ํฐ๋ ๊ทธ๋๋ก ๋๊ณ , ๊ฒฐ๊ณผ์ฐฝ๋ง ์
๋ฐ์ดํธ
|
75 |
+
return code, analysis_result
|
76 |
+
|
77 |
+
# --- 4. Gradio UI ๊ตฌ์ฑ (IDE ํํ) ---
|
78 |
+
with gr.Blocks(theme=gr.themes.Monochrome(primary_hue="indigo", secondary_hue="blue"), css="footer {visibility: hidden}") as demo:
|
79 |
+
gr.Markdown("# ๐ป The C-Codestral IDE Agent")
|
80 |
+
|
81 |
with gr.Tabs():
|
82 |
+
with gr.TabItem("๐จโ๐ป IDE"):
|
83 |
+
with gr.Row():
|
84 |
+
with gr.Column(scale=2):
|
85 |
+
code_editor = gr.Code(label="C Code Editor", language="c", lines=25, interactive=True)
|
86 |
+
with gr.Column(scale=1):
|
87 |
+
instruction_box = gr.Textbox(label="Instruction", placeholder="e.g., 'Compile and run', 'Find bugs', 'Add comments', 'Generate a factorial function'...")
|
88 |
+
execute_btn = gr.Button("Execute Instruction", variant="primary")
|
89 |
+
output_box = gr.Markdown(label="Output / Console")
|
90 |
+
|
91 |
+
def handle_ide_submit(code, instruction):
|
92 |
+
# ์์ฑ ์์ฒญ ์ ๋์์ ๋ถ๊ธฐ
|
93 |
+
if "generate" in instruction.lower() or "create" in instruction.lower():
|
94 |
+
new_code, message = agent_logic(code, instruction)
|
95 |
+
return new_code, message
|
96 |
+
else:
|
97 |
+
# ์ปดํ์ผ ๋๋ ๋ถ์
|
98 |
+
result = agent_logic(code, instruction)
|
99 |
+
# ์ด ๊ฒฝ์ฐ, agent_logic์ ํ๋์ ๊ฐ๋ง ๋ฐํํ๋ฏ๋ก, ์ฝ๋ ์๋ํฐ๋ ๊ทธ๋๋ก ์ ์ง
|
100 |
+
return code, result
|
101 |
+
|
102 |
+
execute_btn.click(handle_ide_submit, inputs=[code_editor, instruction_box], outputs=[code_editor, output_box])
|
103 |
|
104 |
with gr.TabItem("๐ ๏ธ MCP Tools API"):
|
105 |
gr.Markdown("## Available MCP Tools\nThese APIs can be used by any MCP-compliant client.")
|
106 |
with gr.Accordion("Tool: Generate C Code", open=False):
|
107 |
gr.Interface(fn=generate_c_code, inputs="text", outputs=gr.Code(language="c", label="Generated C Code"))
|
108 |
with gr.Accordion("Tool: Compile & Run C Code", open=False):
|
109 |
+
gr.Interface(fn=compile_and_run_c_code, inputs=gr.Code(language="c"), outputs=gr.Textbox(label="Output"))
|
110 |
+
with gr.Accordion("Tool: Analyze & Refactor C Code", open=False):
|
111 |
+
gr.Interface(fn=analyze_and_refactor_code, inputs=[gr.Code(language="c"), "text"], outputs=gr.Markdown())
|
112 |
|
113 |
if __name__ == "__main__":
|
114 |
+
demo.launch()
|