Spaces:
Sleeping
Sleeping
File size: 9,503 Bytes
ad7ea0d 09becbc ad7ea0d a49ab03 ad7ea0d 09becbc ad7ea0d 09becbc ad7ea0d 09becbc ad7ea0d 09becbc ad7ea0d 09becbc ad7ea0d a49ab03 b27d2f2 ad7ea0d a49ab03 ad7ea0d a49ab03 ad7ea0d 09becbc ad7ea0d 09becbc b27d2f2 93db0b6 b27d2f2 09becbc 93db0b6 09becbc 93db0b6 09becbc b27d2f2 09becbc b27d2f2 09becbc a49ab03 09becbc b27d2f2 09becbc b27d2f2 09becbc b27d2f2 09becbc b27d2f2 09becbc ad7ea0d 09becbc ad7ea0d 09becbc ad7ea0d 09becbc ad7ea0d 93db0b6 ad7ea0d 09becbc ad7ea0d b27d2f2 09becbc ad7ea0d 09becbc b27d2f2 09becbc b27d2f2 93db0b6 b27d2f2 09becbc b27d2f2 09becbc 93db0b6 09becbc 93db0b6 09becbc 93db0b6 09becbc 93db0b6 ad7ea0d 93db0b6 ad7ea0d 93db0b6 ad7ea0d 09becbc 93db0b6 ad7ea0d 93db0b6 09becbc ad7ea0d b27d2f2 09becbc ad7ea0d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | import streamlit as st
import os
import zipfile
import subprocess
import shutil
import requests
import re
import time
# --- CONFIGURATION ---
API_ENDPOINT = "https://gen.pollinations.ai/v1/chat/completions"
API_KEY = "sk_qDYtDvntvqzjmp23XKVzr9lBXYwYndaR"
AI_MODEL = "claude"
MAX_RETRIES = 10 # AI 10 baar koshish karega haar manne se pehle
st.set_page_config(page_title="AI Terminator Builder", layout="centered")
st.title("π€ AI Terminator Builder")
st.markdown("This AI will **Hunt & Fix** errors recursively until the APK is built.")
# --- HELPER: AI API ---
def ask_claude(system_prompt, user_message):
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
payload = {
"model": AI_MODEL,
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
"temperature": 0.1 # High precision
}
try:
response = requests.post(API_ENDPOINT, json=payload, headers=headers, timeout=60)
if response.status_code == 200:
return True, response.json()['choices'][0]['message']['content']
return False, f"API Error: {response.text}"
except Exception as e:
return False, f"Connection Error: {str(e)}"
# --- HELPER: KEYSTORE ---
def generate_keystore():
keystore_path = "debug.keystore"
if not os.path.exists(keystore_path):
subprocess.run([
"keytool", "-genkey", "-v", "-keystore", keystore_path,
"-storepass", "android", "-alias", "androiddebugkey",
"-keypass", "android", "-keyalg", "RSA", "-keysize", "2048",
"-validity", "10000", "-dname", "CN=AndroidDebug,O=Android,C=US"
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return keystore_path
# --- STEP 1: FORCE UPGRADE (Base Setup) ---
def initial_modernization(project_root, status_box):
status_box.write("π οΈ AI is modernizing project engine first...")
# 1. Gradle Wrapper Upgrade to 8.0
wrapper_props = os.path.join(project_root, "gradle", "wrapper", "gradle-wrapper.properties")
os.makedirs(os.path.dirname(wrapper_props), exist_ok=True)
new_props = """distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
"""
with open(wrapper_props, "w") as f: f.write(new_props)
# 2. Root Build.gradle Fix
root_gradle = None
for root, dirs, files in os.walk(project_root):
if "build.gradle" in files and "app" not in root:
root_gradle = os.path.join(root, "build.gradle")
break
if root_gradle:
with open(root_gradle, 'r') as f: content = f.read()
# AI se kaho dependencies update kare
p = "Update 'classpath' dependencies to be compatible with Gradle 8. Use 'com.android.tools.build:gradle:8.0.0'. Output full code."
ok, fix = ask_claude(p, content)
if ok:
clean = fix.replace("```gradle","").replace("```","").strip()
with open(root_gradle, 'w') as f: f.write(clean)
status_box.write("β
AI updated root build.gradle configuration.")
# --- STEP 2: THE FIXER LOOP ---
def analyze_and_fix_errors(project_root, error_log, status_box):
# Regex to find file paths in error logs (Java, Kotlin, XML, Gradle)
# Pattern looks for: /path/to/file.ext:line_number: error
match = re.search(r'(/[\w/-]+\.(java|kt|xml|gradle))', error_log)
target_file = None
if match:
extracted_path = match.group(1)
# Verify path exists (Handle relative/absolute mismatch)
if os.path.exists(extracted_path):
target_file = extracted_path
else:
# Try to find by filename
filename = os.path.basename(extracted_path)
for root, dirs, files in os.walk(project_root):
if filename in files:
target_file = os.path.join(root, filename)
break
# Agar Logs se file nahi mili, to fallback 'build.gradle' (App Level) par jao
if not target_file:
for root, dirs, files in os.walk(project_root):
if "build.gradle" in files and "app" in root:
target_file = os.path.join(root, "build.gradle")
break
if target_file:
file_name = os.path.basename(target_file)
status_box.write(f"π§ AI identified issue in: **{file_name}**")
with open(target_file, 'r', errors='ignore') as f: current_code = f.read()
system_prompt = """
You are an elite Android debugger.
Analyze the Error Log and the File Content.
Fix the code to resolve the build error.
Ensure Java 17 / Gradle 8 compatibility.
RETURN ONLY THE CORRECTED CODE. NO EXPLANATION.
"""
user_message = f"""
ERROR LOG:
{error_log[-2000:]}
FILE CONTENT ({file_name}):
{current_code}
"""
success, ai_fix = ask_claude(system_prompt, user_message)
if success:
# Clean response
cleaned_code = ai_fix.replace("```java", "").replace("```kotlin", "").replace("```xml", "").replace("```gradle", "").replace("```", "").strip()
with open(target_file, 'w', encoding='utf-8') as f:
f.write(cleaned_code)
status_box.write(f"π€ **AI Message:** I have corrected `{file_name}` to fix the reported error.")
return True
else:
status_box.error("AI API Failed to respond.")
return False
else:
status_box.warning("Could not identify specific broken file from logs. Trying generic fix...")
return False
# --- MAIN UI ---
uploaded_file = st.file_uploader("Project ZIP Upload", type=["zip"])
if uploaded_file:
if st.button("π Start Terminator Build"):
status_box = st.status("Initializing System...", expanded=True)
# 1. EXTRACT
if os.path.exists("project_extract"): shutil.rmtree("project_extract")
os.makedirs("project_extract", exist_ok=True)
with open("uploaded.zip", "wb") as f: f.write(uploaded_file.getbuffer())
with zipfile.ZipFile("uploaded.zip", "r") as z: z.extractall("project_extract")
project_root = None
for root, dirs, files in os.walk("project_extract"):
if "gradlew" in files:
project_root = root
break
if not project_root:
st.error("Gradlew not found.")
st.stop()
subprocess.run(["chmod", "+x", os.path.join(project_root, "gradlew")])
# 2. PRE-BUILD MODERNIZATION
initial_modernization(project_root, status_box)
# 3. THE LOOP (MAX RETRIES)
build_success = False
cmd = ["./gradlew", "assembleRelease", "--no-daemon", "--stacktrace"]
for attempt in range(1, MAX_RETRIES + 1):
status_box.write(f"π **Build Attempt {attempt}/{MAX_RETRIES}** is running...")
result = subprocess.run(cmd, cwd=project_root, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if result.returncode == 0:
build_success = True
break # Loop khatam, kaam ho gaya
else:
status_box.write(f"β Build Failed (Attempt {attempt}). AI is analyzing logs...")
# AI FIXING LOGIC
fixed = analyze_and_fix_errors(project_root, result.stderr, status_box)
if not fixed:
# Agar AI file nahi dhoond paya, to shayad "clean" ki zaroorat hai
subprocess.run(["./gradlew", "clean"], cwd=project_root)
status_box.write("π§Ή AI cleaned the project cache.")
# Thora saans lene do system ko
time.sleep(1)
# 4. FINAL OUTCOME
if build_success:
status_box.update(label="β
Build Successful! Signing APK...", state="complete")
target_apk = None
for root, dirs, files in os.walk(project_root):
for file in files:
if file.endswith(".apk") and "release" in file:
target_apk = os.path.join(root, file)
break
if target_apk:
keystore = generate_keystore()
signed = "AI_Terminator_App.apk"
subprocess.run(["zipalign", "-v", "-p", "4", target_apk, "aligned.apk"], stdout=subprocess.DEVNULL)
subprocess.run(["apksigner", "sign", "--ks", keystore, "--ks-pass", "pass:android", "--out", signed, "aligned.apk"])
with open(signed, "rb") as f:
st.download_button("β¬οΈ Download Final APK", f, file_name=signed)
else:
status_box.update(label="β Mission Failed", state="error")
st.error(f"AI tried {MAX_RETRIES} times but could not fix all errors.")
st.text_area("Last Error Log", result.stderr[-2000:], height=300)
if os.path.exists("uploaded.zip"): os.remove("uploaded.zip") |