| import gradio as gr |
| import requests |
| import json |
| import os |
| import zipfile |
| from pathlib import Path |
| from github import Github |
| from github.GithubException import GithubException |
|
|
| |
| |
| OPENROUTER_API_KEY = "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" |
| OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions" |
| |
| MODEL_NAME = "cognitivecomputations/dolphin-2.9.1-llama-3-8b" |
|
|
| |
| def call_ai(prompt): |
| """Kirim prompt ke AI via OpenRouter""" |
| headers = { |
| "Authorization": f"Bearer {OPENROUTER_API_KEY}", |
| "Content-Type": "application/json" |
| } |
| data = { |
| "model": MODEL_NAME, |
| "messages": [ |
| {"role": "system", "content": "Kamu adalah AI coding expert yang membantu membuat aplikasi full-stack. Keluarkan kode dalam format yang rapi."}, |
| {"role": "user", "content": prompt} |
| ], |
| "temperature": 0.7, |
| } |
| try: |
| response = requests.post(OPENROUTER_URL, headers=headers, json=data, timeout=120) |
| response.raise_for_status() |
| result = response.json() |
| return result['choices'][0]['message']['content'] |
| except Exception as e: |
| return f"Error: {str(e)}" |
|
|
| |
| def generate_project(description): |
| """Minta AI buat struktur project""" |
| prompt = f""" |
| Buatkan struktur project aplikasi web berdasarkan deskripsi ini: {description} |
| |
| Keluarkan output dalam format JSON seperti ini: |
| {{ |
| "files": [ |
| {{"path": "index.html", "content": "... konten HTML ..."}}, |
| {{"path": "style.css", "content": "... konten CSS ..."}}, |
| {{"path": "script.js", "content": "... konten JavaScript ..."}} |
| ] |
| }} |
| |
| Hanya output JSON, tanpa teks lain. Pastikan konten file sesuai deskripsi. |
| """ |
| response = call_ai(prompt) |
| |
| try: |
| |
| start = response.find('{') |
| end = response.rfind('}') + 1 |
| json_str = response[start:end] |
| return json.loads(json_str) |
| except: |
| return {"error": "Gagal parse JSON dari AI", "raw": response} |
|
|
| |
| BASE_DIR = "/tmp/project" |
| def save_files(project_data): |
| """Simpan file dari JSON ke folder sementara""" |
| if "error" in project_data: |
| return None, project_data["error"] |
| |
| |
| Path(BASE_DIR).mkdir(parents=True, exist_ok=True) |
| for f in Path(BASE_DIR).glob("*"): |
| if f.is_file(): |
| f.unlink() |
| |
| file_list = [] |
| for file_info in project_data.get("files", []): |
| file_path = Path(BASE_DIR) / file_info["path"] |
| file_path.parent.mkdir(parents=True, exist_ok=True) |
| with open(file_path, "w") as f: |
| f.write(file_info["content"]) |
| file_list.append(file_info["path"]) |
| |
| return BASE_DIR, file_list |
|
|
| |
| def create_zip(): |
| """Buat file ZIP dari folder project""" |
| zip_path = "/tmp/project.zip" |
| with zipfile.ZipFile(zip_path, 'w') as zipf: |
| for file in Path(BASE_DIR).rglob("*"): |
| if file.is_file(): |
| zipf.write(file, file.relative_to(BASE_DIR)) |
| return zip_path |
|
|
| |
| def get_preview(): |
| """Ambil konten index.html untuk preview""" |
| index_path = Path(BASE_DIR) / "index.html" |
| if index_path.exists(): |
| with open(index_path, "r") as f: |
| return f.read() |
| return "<p>File index.html tidak ditemukan.</p>" |
|
|
| |
| def push_to_github(repo_name, github_token, commit_msg): |
| """Buat repo di GitHub dan push file""" |
| try: |
| g = Github(github_token) |
| user = g.get_user() |
| repo = user.create_repo(repo_name, private=False) |
| |
| for file_path in Path(BASE_DIR).rglob("*"): |
| if file_path.is_file(): |
| with open(file_path, 'r') as f: |
| content = f.read() |
| rel_path = file_path.relative_to(BASE_DIR) |
| repo.create_file(str(rel_path), commit_msg or "Initial commit", content) |
| |
| return f"β
Berhasil! Repo: {repo.html_url}" |
| except GithubException as e: |
| return f"β Error GitHub: {e.data.get('message', str(e))}" |
| except Exception as e: |
| return f"β Error: {str(e)}" |
|
|
| |
| def process(description, github_token, repo_name, commit_msg): |
| |
| project = generate_project(description) |
| |
| |
| base, file_list = save_files(project) |
| if base is None: |
| return project, file_list, "", None, "" |
| |
| |
| files_str = "\n".join(file_list) |
| preview_html = get_preview() |
| zip_path = create_zip() |
| |
| |
| github_status = "" |
| if github_token and repo_name: |
| github_status = push_to_github(repo_name, github_token, commit_msg) |
| |
| return project, files_str, preview_html, zip_path, github_status |
|
|
| |
| with gr.Blocks(title="AI Full-Stack Generator (Uncensored)", theme=gr.themes.Soft()) as demo: |
| gr.Markdown(""" |
| # π AI Full-Stack Generator |
| **Uncensored | Gratis | Jago Coding** |
| Masukkan deskripsi aplikasi yang lo mau, AI akan generate struktur project. |
| """) |
| |
| with gr.Row(): |
| with gr.Column(scale=2): |
| desc = gr.Textbox( |
| label="π Deskripsi Aplikasi", |
| placeholder="Contoh: Buat aplikasi kalkulator dengan HTML, CSS, dan JavaScript.", |
| lines=5 |
| ) |
| generate_btn = gr.Button("β¨ Generate Project", variant="primary") |
| |
| with gr.Column(scale=1): |
| github_token = gr.Textbox( |
| label="π GitHub Token (opsional)", |
| placeholder="ghp_xxxxxx", |
| type="password" |
| ) |
| repo_name = gr.Textbox( |
| label="π¦ Nama Repo GitHub", |
| placeholder="my-ai-app" |
| ) |
| commit_msg = gr.Textbox( |
| label="βοΈ Commit Message", |
| value="Initial commit from AI" |
| ) |
| |
| with gr.Row(): |
| with gr.Column(): |
| gr.Markdown("### π File Explorer") |
| file_list_output = gr.Textbox(label="", lines=10, interactive=False) |
| |
| with gr.Column(): |
| gr.Markdown("### ποΈ Preview (index.html)") |
| preview_output = gr.HTML(label="") |
| |
| with gr.Row(): |
| download_output = gr.File(label="π₯ Download ZIP") |
| github_output = gr.Textbox(label="π€ GitHub Status", lines=3, interactive=False) |
| |
| with gr.Row(): |
| gr.Markdown("### π Raw JSON Output") |
| json_output = gr.JSON(label="") |
| |
| |
| generate_btn.click( |
| fn=process, |
| inputs=[desc, github_token, repo_name, commit_msg], |
| outputs=[json_output, file_list_output, preview_output, download_output, github_output] |
| ) |
|
|
| |
| if __name__ == "__main__": |
| demo.launch() |