Spaces:
Running
Running
| import streamlit as st | |
| import openai | |
| import os | |
| import re | |
| import json | |
| # ββ Page config ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| st.set_page_config( | |
| page_title="CodeShift Β· AI Code Converter", | |
| page_icon="β‘", | |
| layout="wide", | |
| ) | |
| # ββ Styling ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| st.markdown(""" | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Syne:wght@700;800&display=swap'); | |
| html, body, [class*="css"] { font-family: 'Syne', sans-serif; } | |
| .header { | |
| background: linear-gradient(135deg, #1a1040, #0d1a2a); | |
| padding: 24px 32px; | |
| border-radius: 12px; | |
| margin-bottom: 24px; | |
| } | |
| .header h1 { | |
| font-size: 2rem; font-weight: 800; margin: 0; | |
| background: linear-gradient(90deg, #7c6af7, #3ecfcf); | |
| -webkit-background-clip: text; -webkit-text-fill-color: transparent; | |
| } | |
| .header p { color: #7a7f94; margin: 4px 0 0; font-size: 0.9rem; } | |
| .status-box { padding: 10px 16px; border-radius: 8px; font-size: 0.88rem; margin-top: 8px; } | |
| .status-ok { background: #0d2b1f; border-left: 3px solid #3ecf8e; color: #3ecf8e; } | |
| .status-err { background: #2b0d0d; border-left: 3px solid #f76464; color: #f76464; } | |
| .status-info { background: #1a1a2e; border-left: 3px solid #7c6af7; color: #a99ff7; } | |
| textarea { font-family: 'JetBrains Mono', monospace !important; font-size: 0.82rem !important; } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # ββ OpenAI client ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) | |
| LANGUAGES = [ | |
| "Python", "JavaScript", "TypeScript", "Java", "C", "C++", "C#", | |
| "Go", "Rust", "Ruby", "PHP", "Swift", "Kotlin", "Bash/Shell", "SQL", | |
| ] | |
| # ββ AI helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def validate_language(code: str, selected: str): | |
| resp = client.chat.completions.create( | |
| model="gpt-4o", temperature=0, | |
| messages=[ | |
| {"role": "system", "content": 'Detect the programming language. Reply ONLY with JSON: {"language":"X","confidence":"high/medium/low","reason":"..."}'}, | |
| {"role": "user", "content": code[:3000]}, | |
| ], | |
| ) | |
| raw = re.sub(r"```[a-z]*\n?|```", "", resp.choices[0].message.content).strip() | |
| data = json.loads(raw) | |
| detected = data.get("language", "Unknown") | |
| match = detected.lower() == selected.lower() | |
| return detected, data.get("confidence", "?"), data.get("reason", ""), match | |
| def convert_code(code: str, src: str, tgt: str, notes: str): | |
| prompt = ( | |
| f"Convert the {src} code to idiomatic {tgt}. " | |
| f"Preserve all logic. Add comments for non-obvious parts. " | |
| f"Return ONLY raw code β no markdown fences, no preamble." | |
| + (f" Style notes: {notes}" if notes.strip() else "") | |
| ) | |
| resp = client.chat.completions.create( | |
| model="gpt-4o", temperature=0.2, | |
| messages=[ | |
| {"role": "system", "content": prompt}, | |
| {"role": "user", "content": code}, | |
| ], | |
| ) | |
| return re.sub(r"```[a-z]*\n?|```", "", resp.choices[0].message.content).strip() | |
| def explain_code(code: str, lang: str): | |
| resp = client.chat.completions.create( | |
| model="gpt-4o", temperature=0.3, | |
| messages=[ | |
| {"role": "system", "content": "Explain this code clearly in plain English using bullet points. Be concise."}, | |
| {"role": "user", "content": f"{lang} code:\n\n{code[:4000]}"}, | |
| ], | |
| ) | |
| return resp.choices[0].message.content.strip() | |
| # ββ Header βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| st.markdown(""" | |
| <div class="header"> | |
| <h1>β‘ CodeShift</h1> | |
| <p>AI-powered code converter & analyser Β· GPT-4o</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # ββ Tabs βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| tab1, tab2, tab3 = st.tabs(["π Convert", "π‘ Explain", "π Detect"]) | |
| # ββββββββββββββββββββββββ | |
| # TAB 1 β CONVERT | |
| # ββββββββββββββββββββββββ | |
| with tab1: | |
| col_l, col_r = st.columns(2, gap="medium") | |
| with col_l: | |
| st.markdown("### Source Code") | |
| src_lang = st.selectbox("Source Language", LANGUAGES, index=0, key="src_lang") | |
| src_code = st.text_area("", height=380, placeholder="# Paste your source code hereβ¦", key="src_code") | |
| style_notes = st.text_input("Style notes (optional)", placeholder="e.g. 'use async/await', 'add type hints'β¦") | |
| c1, c2, c3 = st.columns(3) | |
| validate_btn = c1.button("π Validate", use_container_width=True) | |
| convert_btn = c2.button("β‘ Convert", use_container_width=True, type="primary") | |
| clear_btn = c3.button("π Clear", use_container_width=True) | |
| if validate_btn: | |
| if not src_code.strip(): | |
| st.markdown('<div class="status-box status-info">βͺ Paste some code first.</div>', unsafe_allow_html=True) | |
| else: | |
| with st.spinner("Detecting languageβ¦"): | |
| detected, conf, reason, match = validate_language(src_code, src_lang) | |
| if match: | |
| st.markdown(f'<div class="status-box status-ok">β Detected <b>{detected}</b> β matches your selection! (Confidence: {conf})<br><small>{reason}</small></div>', unsafe_allow_html=True) | |
| else: | |
| st.markdown(f'<div class="status-box status-err">β Detected <b>{detected}</b> but you selected <b>{src_lang}</b> (Confidence: {conf})<br><small>{reason}</small></div>', unsafe_allow_html=True) | |
| if clear_btn: | |
| st.session_state["src_code"] = "" | |
| st.session_state["converted"] = "" | |
| st.rerun() | |
| with col_r: | |
| st.markdown("### Converted Code") | |
| tgt_lang = st.selectbox("Target Language", LANGUAGES, index=1, key="tgt_lang") | |
| if convert_btn: | |
| if not src_code.strip(): | |
| st.warning("Paste some source code first.") | |
| elif src_lang == tgt_lang: | |
| st.info("Source and target languages are the same.") | |
| else: | |
| with st.spinner(f"Converting {src_lang} β {tgt_lang}β¦"): | |
| result = convert_code(src_code, src_lang, tgt_lang, style_notes) | |
| st.session_state["converted"] = result | |
| st.session_state["conv_langs"] = (src_lang, tgt_lang) | |
| converted = st.session_state.get("converted", "") | |
| langs = st.session_state.get("conv_langs", ("", "")) | |
| if converted: | |
| st.success(f"β Converted {langs[0]} β {langs[1]}") | |
| st.text_area("", value=converted, height=380, | |
| placeholder="# Converted code appears hereβ¦", | |
| key="tgt_code") | |
| # ββββββββββββββββββββββββ | |
| # TAB 2 β EXPLAIN | |
| # ββββββββββββββββββββββββ | |
| with tab2: | |
| col_l, col_r = st.columns(2, gap="medium") | |
| with col_l: | |
| st.markdown("### Paste Code to Explain") | |
| exp_lang = st.selectbox("Language", LANGUAGES, key="exp_lang") | |
| exp_code = st.text_area("", height=380, placeholder="# Paste code hereβ¦", key="exp_code") | |
| exp_btn = st.button("π‘ Explain", type="primary", use_container_width=True) | |
| with col_r: | |
| st.markdown("### AI Explanation") | |
| if exp_btn: | |
| if not exp_code.strip(): | |
| st.warning("Paste some code first.") | |
| else: | |
| with st.spinner("Explainingβ¦"): | |
| st.session_state["explanation"] = explain_code(exp_code, exp_lang) | |
| if st.session_state.get("explanation"): | |
| st.markdown(st.session_state["explanation"]) | |
| else: | |
| st.caption("Explanation will appear here after you click Explain.") | |
| # ββββββββββββββββββββββββ | |
| # TAB 3 β DETECT | |
| # ββββββββββββββββββββββββ | |
| with tab3: | |
| col_l, col_r = st.columns(2, gap="medium") | |
| with col_l: | |
| st.markdown("### Mystery Code") | |
| det_code = st.text_area("", height=380, placeholder="# Paste any code hereβ¦", key="det_code") | |
| det_btn = st.button("π Detect Language", type="primary", use_container_width=True) | |
| with col_r: | |
| st.markdown("### Detection Result") | |
| if det_btn: | |
| if not det_code.strip(): | |
| st.warning("Paste some code first.") | |
| else: | |
| with st.spinner("Analysingβ¦"): | |
| detected, conf, reason, _ = validate_language(det_code, "") | |
| st.metric("Detected Language", detected) | |
| st.metric("Confidence", conf.capitalize()) | |
| st.info(reason) | |
| else: | |
| st.caption("Results will appear here after detection.") | |
| st.markdown("---") | |
| st.markdown("<center style='color:#4a5068;font-size:0.78rem'>CodeShift Β· GPT-4o Β· Built with Streamlit</center>", unsafe_allow_html=True) |