Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -161,7 +161,6 @@ Return ONLY valid JSON with these exact keys:
|
|
| 161 |
- requirements_txt: All necessary dependencies including gradio>=5.35.0
|
| 162 |
- summary: Brief description of what the app does"""
|
| 163 |
|
| 164 |
-
# Fireworks AI API ์๋
|
| 165 |
fireworks_key = os.getenv("FIREWORKS_API_KEY")
|
| 166 |
if fireworks_key:
|
| 167 |
try:
|
|
@@ -722,7 +721,7 @@ Deployed from: {repo_git}
|
|
| 722 |
yield f"""
|
| 723 |
โ
**Successfully created Space!**
|
| 724 |
|
| 725 |
-
๐ **Your Space URL**: {space_url}
|
| 726 |
|
| 727 |
๐ **Summary:**
|
| 728 |
- Space ID: `{repo_id}`
|
|
@@ -747,7 +746,7 @@ Deployed from: {repo_git}
|
|
| 747 |
shutil.rmtree(folder)
|
| 748 |
yield f"โ Error: {str(e)}"
|
| 749 |
|
| 750 |
-
def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
| 751 |
"""Clone HuggingFace Space and push to GitHub"""
|
| 752 |
tmp_dir = None
|
| 753 |
try:
|
|
@@ -782,9 +781,15 @@ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
|
| 782 |
# ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
|
| 783 |
user_response = requests.get("https://api.github.com/user", headers=headers)
|
| 784 |
if user_response.status_code != 200:
|
| 785 |
-
raise Exception("GitHub authentication failed")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 786 |
|
| 787 |
-
github_username = user_response.json()["login"]
|
| 788 |
yield f"โ
Authenticated as GitHub user: {github_username}"
|
| 789 |
|
| 790 |
# ๋ ํฌ์งํ ๋ฆฌ ์์ฑ
|
|
@@ -792,7 +797,8 @@ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
|
| 792 |
create_data = {
|
| 793 |
"name": github_repo_name,
|
| 794 |
"private": False,
|
| 795 |
-
"auto_init": False
|
|
|
|
| 796 |
}
|
| 797 |
|
| 798 |
create_response = requests.post(
|
|
@@ -803,13 +809,15 @@ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
|
| 803 |
|
| 804 |
if create_response.status_code == 201:
|
| 805 |
repo_info = create_response.json()
|
| 806 |
-
|
|
|
|
| 807 |
elif create_response.status_code == 422:
|
| 808 |
# ๋ ํฌ๊ฐ ์ด๋ฏธ ์กด์ฌํจ
|
| 809 |
-
|
| 810 |
-
yield f"โน๏ธ Repository already exists: {
|
| 811 |
else:
|
| 812 |
-
|
|
|
|
| 813 |
|
| 814 |
# Git remote ๋ณ๊ฒฝ ๋ฐ ํธ์
|
| 815 |
yield "๐ค Pushing to GitHub..."
|
|
@@ -826,7 +834,7 @@ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
|
| 826 |
|
| 827 |
# main ๋ธ๋์น๋ก ํธ์
|
| 828 |
push_result = subprocess.run(
|
| 829 |
-
['git', 'push', '-u', 'origin', 'HEAD:main'],
|
| 830 |
capture_output=True,
|
| 831 |
text=True
|
| 832 |
)
|
|
@@ -834,7 +842,7 @@ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
|
| 834 |
if push_result.returncode != 0:
|
| 835 |
# master ๋ธ๋์น๋ก ์ฌ์๋
|
| 836 |
push_result = subprocess.run(
|
| 837 |
-
['git', 'push', '-u', 'origin', 'HEAD:master'],
|
| 838 |
capture_output=True,
|
| 839 |
text=True
|
| 840 |
)
|
|
@@ -843,8 +851,24 @@ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
|
| 843 |
raise Exception(f"Push failed: {push_result.stderr}")
|
| 844 |
|
| 845 |
yield "โ
Successfully pushed to GitHub!"
|
| 846 |
-
|
| 847 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 848 |
|
| 849 |
except Exception as e:
|
| 850 |
yield f"โ Error: {str(e)}"
|
|
@@ -853,72 +877,331 @@ def space_to_github(hf_username, hf_space_name, github_repo_name, github_token):
|
|
| 853 |
if tmp_dir and os.path.exists(tmp_dir):
|
| 854 |
os.chdir("/") # ๋๋ ํ ๋ฆฌ ๋ฐ์ผ๋ก ์ด๋
|
| 855 |
shutil.rmtree(tmp_dir)
|
| 856 |
-
yield "๐งน Cleaned up temporary files"
|
| 857 |
|
| 858 |
css = """
|
|
|
|
| 859 |
.container {
|
| 860 |
-
max-width:
|
| 861 |
margin: auto;
|
| 862 |
padding: 20px;
|
| 863 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 864 |
.output-box {
|
| 865 |
-
min-height:
|
| 866 |
-
max-height:
|
| 867 |
-
overflow-y: auto;
|
| 868 |
-
font-family: monospace;
|
| 869 |
-
font-size:
|
| 870 |
-
line-height: 1.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 871 |
}
|
| 872 |
-
|
| 873 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 874 |
}
|
| 875 |
"""
|
| 876 |
|
| 877 |
-
with gr.Blocks(css=css, theme=gr.themes.Soft(
|
| 878 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 879 |
|
| 880 |
-
with gr.Tabs():
|
| 881 |
-
with gr.Tab("GitHub โ HF Space"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 882 |
if not os.getenv("HF_TOKEN"):
|
| 883 |
-
gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 884 |
else:
|
| 885 |
-
gr.
|
| 886 |
-
|
| 887 |
-
|
| 888 |
-
|
| 889 |
-
|
| 890 |
-
|
| 891 |
-
placeholder="https://github.com/username/repository"
|
| 892 |
-
)
|
| 893 |
-
repo_hf = gr.Textbox(
|
| 894 |
-
label="Hugging Face Space Name",
|
| 895 |
-
placeholder="my-awesome-space"
|
| 896 |
-
)
|
| 897 |
-
sdk_choices = gr.Radio(
|
| 898 |
-
["gradio", "streamlit", "docker", "static"],
|
| 899 |
-
label="Space SDK",
|
| 900 |
-
value="gradio"
|
| 901 |
-
)
|
| 902 |
-
skip_lfs = gr.Checkbox(
|
| 903 |
-
label="Skip Git LFS files",
|
| 904 |
-
value=True
|
| 905 |
-
)
|
| 906 |
-
enable_smart_generation = gr.Checkbox(
|
| 907 |
-
label="๐ค Enable Smart app.py Generation",
|
| 908 |
-
value=False,
|
| 909 |
-
info="Requires FIREWORKS_API_KEY in environment variables"
|
| 910 |
-
)
|
| 911 |
-
|
| 912 |
-
btn_to_hf = gr.Button("๐ Deploy to HF Space", variant="primary")
|
| 913 |
-
|
| 914 |
-
with gr.Column():
|
| 915 |
-
output_to_hf = gr.Textbox(
|
| 916 |
-
label="Progress",
|
| 917 |
-
lines=15,
|
| 918 |
-
elem_classes=["output-box"],
|
| 919 |
-
interactive=False,
|
| 920 |
-
show_copy_button=True
|
| 921 |
-
)
|
| 922 |
|
| 923 |
btn_to_hf.click(
|
| 924 |
fn=clone,
|
|
@@ -926,69 +1209,90 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 926 |
outputs=output_to_hf
|
| 927 |
)
|
| 928 |
|
| 929 |
-
with gr.Tab("HF Space โ GitHub"):
|
| 930 |
-
gr.Markdown("""
|
| 931 |
-
๐ **Export your HuggingFace Space to GitHub**
|
| 932 |
-
|
| 933 |
-
Create a GitHub repository from your existing HuggingFace Space.
|
| 934 |
-
""")
|
| 935 |
-
|
| 936 |
with gr.Row():
|
| 937 |
-
with gr.Column():
|
| 938 |
-
|
| 939 |
-
|
| 940 |
-
|
| 941 |
-
|
| 942 |
-
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
|
| 947 |
-
|
| 948 |
-
|
| 949 |
-
|
| 950 |
-
|
| 951 |
-
|
| 952 |
-
|
| 953 |
-
|
| 954 |
-
|
| 955 |
-
|
| 956 |
-
|
| 957 |
-
|
| 958 |
-
|
| 959 |
-
|
| 960 |
-
|
| 961 |
-
|
| 962 |
-
|
| 963 |
-
|
| 964 |
-
|
| 965 |
-
|
| 966 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 967 |
|
| 968 |
btn_to_github.click(
|
| 969 |
fn=space_to_github,
|
| 970 |
-
inputs=[hf_username, hf_space_name, github_repo_name, github_token],
|
| 971 |
outputs=output_to_github
|
| 972 |
)
|
| 973 |
|
| 974 |
gr.Markdown("""
|
| 975 |
---
|
| 976 |
-
|
| 977 |
-
|
| 978 |
-
|
| 979 |
-
|
| 980 |
-
|
| 981 |
-
|
| 982 |
-
|
| 983 |
-
|
| 984 |
-
|
| 985 |
-
|
| 986 |
-
|
| 987 |
-
|
| 988 |
-
|
| 989 |
-
|
| 990 |
-
|
| 991 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 992 |
""")
|
| 993 |
|
| 994 |
if __name__ == "__main__":
|
|
|
|
| 161 |
- requirements_txt: All necessary dependencies including gradio>=5.35.0
|
| 162 |
- summary: Brief description of what the app does"""
|
| 163 |
|
|
|
|
| 164 |
fireworks_key = os.getenv("FIREWORKS_API_KEY")
|
| 165 |
if fireworks_key:
|
| 166 |
try:
|
|
|
|
| 721 |
yield f"""
|
| 722 |
โ
**Successfully created Space!**
|
| 723 |
|
| 724 |
+
๐ **Your Space URL**: [{space_url}]({space_url})
|
| 725 |
|
| 726 |
๐ **Summary:**
|
| 727 |
- Space ID: `{repo_id}`
|
|
|
|
| 746 |
shutil.rmtree(folder)
|
| 747 |
yield f"โ Error: {str(e)}"
|
| 748 |
|
| 749 |
+
def space_to_github(hf_username, hf_space_name, github_username, github_repo_name, github_token):
|
| 750 |
"""Clone HuggingFace Space and push to GitHub"""
|
| 751 |
tmp_dir = None
|
| 752 |
try:
|
|
|
|
| 781 |
# ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
|
| 782 |
user_response = requests.get("https://api.github.com/user", headers=headers)
|
| 783 |
if user_response.status_code != 200:
|
| 784 |
+
raise Exception("GitHub authentication failed. Please check your token.")
|
| 785 |
+
|
| 786 |
+
actual_github_username = user_response.json()["login"]
|
| 787 |
+
|
| 788 |
+
# ์
๋ ฅ๋ username๊ณผ ์ค์ username์ด ๋ค๋ฅธ ๊ฒฝ์ฐ ์ฒ๋ฆฌ
|
| 789 |
+
if github_username.lower() != actual_github_username.lower():
|
| 790 |
+
yield f"โ ๏ธ Note: Using authenticated user '{actual_github_username}' instead of '{github_username}'"
|
| 791 |
+
github_username = actual_github_username
|
| 792 |
|
|
|
|
| 793 |
yield f"โ
Authenticated as GitHub user: {github_username}"
|
| 794 |
|
| 795 |
# ๋ ํฌ์งํ ๋ฆฌ ์์ฑ
|
|
|
|
| 797 |
create_data = {
|
| 798 |
"name": github_repo_name,
|
| 799 |
"private": False,
|
| 800 |
+
"auto_init": False,
|
| 801 |
+
"description": f"Exported from HuggingFace Space: {hf_username}/{hf_space_name}"
|
| 802 |
}
|
| 803 |
|
| 804 |
create_response = requests.post(
|
|
|
|
| 809 |
|
| 810 |
if create_response.status_code == 201:
|
| 811 |
repo_info = create_response.json()
|
| 812 |
+
github_url = repo_info['html_url']
|
| 813 |
+
yield f"โ
GitHub repository created: {github_url}"
|
| 814 |
elif create_response.status_code == 422:
|
| 815 |
# ๋ ํฌ๊ฐ ์ด๋ฏธ ์กด์ฌํจ
|
| 816 |
+
github_url = f"https://github.com/{github_username}/{github_repo_name}"
|
| 817 |
+
yield f"โน๏ธ Repository already exists: {github_url}"
|
| 818 |
else:
|
| 819 |
+
error_msg = create_response.json().get('message', 'Unknown error')
|
| 820 |
+
raise Exception(f"Failed to create repository: {error_msg}")
|
| 821 |
|
| 822 |
# Git remote ๋ณ๊ฒฝ ๋ฐ ํธ์
|
| 823 |
yield "๐ค Pushing to GitHub..."
|
|
|
|
| 834 |
|
| 835 |
# main ๋ธ๋์น๋ก ํธ์
|
| 836 |
push_result = subprocess.run(
|
| 837 |
+
['git', 'push', '-u', 'origin', 'HEAD:main', '--force'],
|
| 838 |
capture_output=True,
|
| 839 |
text=True
|
| 840 |
)
|
|
|
|
| 842 |
if push_result.returncode != 0:
|
| 843 |
# master ๋ธ๋์น๋ก ์ฌ์๋
|
| 844 |
push_result = subprocess.run(
|
| 845 |
+
['git', 'push', '-u', 'origin', 'HEAD:master', '--force'],
|
| 846 |
capture_output=True,
|
| 847 |
text=True
|
| 848 |
)
|
|
|
|
| 851 |
raise Exception(f"Push failed: {push_result.stderr}")
|
| 852 |
|
| 853 |
yield "โ
Successfully pushed to GitHub!"
|
| 854 |
+
|
| 855 |
+
# ์ต์ข
๊ฒฐ๊ณผ ์ถ๋ ฅ - ํด๋ฆญ ๊ฐ๋ฅํ ๋งํฌ
|
| 856 |
+
final_url = f"https://github.com/{github_username}/{github_repo_name}"
|
| 857 |
+
yield f"""
|
| 858 |
+
๐ **Export Complete!**
|
| 859 |
+
|
| 860 |
+
๐ฆ **GitHub Repository**: [{final_url}]({final_url})
|
| 861 |
+
|
| 862 |
+
๐ **Details:**
|
| 863 |
+
- Source: HuggingFace Space `{hf_username}/{hf_space_name}`
|
| 864 |
+
- Destination: GitHub `{github_username}/{github_repo_name}`
|
| 865 |
+
|
| 866 |
+
๐ง **Next Steps:**
|
| 867 |
+
```bash
|
| 868 |
+
git clone {final_url}.git
|
| 869 |
+
cd {github_repo_name}
|
| 870 |
+
```
|
| 871 |
+
"""
|
| 872 |
|
| 873 |
except Exception as e:
|
| 874 |
yield f"โ Error: {str(e)}"
|
|
|
|
| 877 |
if tmp_dir and os.path.exists(tmp_dir):
|
| 878 |
os.chdir("/") # ๋๋ ํ ๋ฆฌ ๋ฐ์ผ๋ก ์ด๋
|
| 879 |
shutil.rmtree(tmp_dir)
|
|
|
|
| 880 |
|
| 881 |
css = """
|
| 882 |
+
/* Modern Professional UI */
|
| 883 |
.container {
|
| 884 |
+
max-width: 1200px !important;
|
| 885 |
margin: auto;
|
| 886 |
padding: 20px;
|
| 887 |
}
|
| 888 |
+
|
| 889 |
+
/* Gradient backgrounds */
|
| 890 |
+
.main-header {
|
| 891 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 892 |
+
padding: 2rem;
|
| 893 |
+
border-radius: 15px;
|
| 894 |
+
margin-bottom: 2rem;
|
| 895 |
+
color: white;
|
| 896 |
+
text-align: center;
|
| 897 |
+
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
| 898 |
+
}
|
| 899 |
+
|
| 900 |
+
/* Tab styling */
|
| 901 |
+
.tabs {
|
| 902 |
+
box-shadow: 0 4px 6px rgba(0,0,0,0.07);
|
| 903 |
+
border-radius: 12px;
|
| 904 |
+
overflow: hidden;
|
| 905 |
+
}
|
| 906 |
+
|
| 907 |
+
/* Card-like sections */
|
| 908 |
+
.input-section {
|
| 909 |
+
background: white;
|
| 910 |
+
padding: 25px;
|
| 911 |
+
border-radius: 12px;
|
| 912 |
+
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
| 913 |
+
margin-bottom: 20px;
|
| 914 |
+
border: 1px solid rgba(0,0,0,0.05);
|
| 915 |
+
}
|
| 916 |
+
|
| 917 |
+
/* Output box styling */
|
| 918 |
.output-box {
|
| 919 |
+
min-height: 400px !important;
|
| 920 |
+
max-height: 600px !important;
|
| 921 |
+
overflow-y: auto !important;
|
| 922 |
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;
|
| 923 |
+
font-size: 13px !important;
|
| 924 |
+
line-height: 1.6 !important;
|
| 925 |
+
background: linear-gradient(to bottom, #1e1e1e, #2d2d30) !important;
|
| 926 |
+
color: #d4d4d4 !important;
|
| 927 |
+
padding: 20px !important;
|
| 928 |
+
border-radius: 10px !important;
|
| 929 |
+
border: 1px solid rgba(255,255,255,0.1) !important;
|
| 930 |
+
}
|
| 931 |
+
|
| 932 |
+
/* Custom button styling */
|
| 933 |
+
.primary-btn {
|
| 934 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
| 935 |
+
color: white !important;
|
| 936 |
+
border: none !important;
|
| 937 |
+
padding: 12px 30px !important;
|
| 938 |
+
font-size: 16px !important;
|
| 939 |
+
font-weight: 600 !important;
|
| 940 |
+
border-radius: 8px !important;
|
| 941 |
+
cursor: pointer !important;
|
| 942 |
+
transition: all 0.3s ease !important;
|
| 943 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4) !important;
|
| 944 |
+
}
|
| 945 |
+
|
| 946 |
+
.primary-btn:hover {
|
| 947 |
+
transform: translateY(-2px) !important;
|
| 948 |
+
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6) !important;
|
| 949 |
+
}
|
| 950 |
+
|
| 951 |
+
/* Input field styling */
|
| 952 |
+
input[type="text"], input[type="password"], textarea {
|
| 953 |
+
border: 2px solid #e2e8f0 !important;
|
| 954 |
+
border-radius: 8px !important;
|
| 955 |
+
padding: 10px 15px !important;
|
| 956 |
+
font-size: 14px !important;
|
| 957 |
+
transition: all 0.3s ease !important;
|
| 958 |
+
background: #f8fafc !important;
|
| 959 |
+
}
|
| 960 |
+
|
| 961 |
+
input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
|
| 962 |
+
border-color: #667eea !important;
|
| 963 |
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
|
| 964 |
+
background: white !important;
|
| 965 |
+
}
|
| 966 |
+
|
| 967 |
+
/* Radio button group styling */
|
| 968 |
+
.radio-group {
|
| 969 |
+
background: #f8fafc;
|
| 970 |
+
padding: 15px;
|
| 971 |
+
border-radius: 8px;
|
| 972 |
+
border: 1px solid #e2e8f0;
|
| 973 |
+
}
|
| 974 |
+
|
| 975 |
+
/* Checkbox styling */
|
| 976 |
+
input[type="checkbox"] {
|
| 977 |
+
width: 20px !important;
|
| 978 |
+
height: 20px !important;
|
| 979 |
+
cursor: pointer !important;
|
| 980 |
+
}
|
| 981 |
+
|
| 982 |
+
/* Label styling */
|
| 983 |
+
label {
|
| 984 |
+
font-weight: 600 !important;
|
| 985 |
+
color: #334155 !important;
|
| 986 |
+
margin-bottom: 8px !important;
|
| 987 |
+
display: block !important;
|
| 988 |
+
font-size: 14px !important;
|
| 989 |
+
}
|
| 990 |
+
|
| 991 |
+
/* Info text styling */
|
| 992 |
+
.info-text {
|
| 993 |
+
color: #64748b !important;
|
| 994 |
+
font-size: 13px !important;
|
| 995 |
+
margin-top: 5px !important;
|
| 996 |
+
}
|
| 997 |
+
|
| 998 |
+
/* Status badges */
|
| 999 |
+
.status-badge {
|
| 1000 |
+
display: inline-block;
|
| 1001 |
+
padding: 6px 12px;
|
| 1002 |
+
border-radius: 20px;
|
| 1003 |
+
font-size: 13px;
|
| 1004 |
+
font-weight: 600;
|
| 1005 |
+
margin: 5px 0;
|
| 1006 |
+
}
|
| 1007 |
+
|
| 1008 |
+
.status-success {
|
| 1009 |
+
background: #10b981;
|
| 1010 |
+
color: white;
|
| 1011 |
+
}
|
| 1012 |
+
|
| 1013 |
+
.status-error {
|
| 1014 |
+
background: #ef4444;
|
| 1015 |
+
color: white;
|
| 1016 |
+
}
|
| 1017 |
+
|
| 1018 |
+
.status-warning {
|
| 1019 |
+
background: #f59e0b;
|
| 1020 |
+
color: white;
|
| 1021 |
+
}
|
| 1022 |
+
|
| 1023 |
+
/* Tab button styling */
|
| 1024 |
+
button.tab-nav {
|
| 1025 |
+
padding: 12px 24px !important;
|
| 1026 |
+
font-weight: 600 !important;
|
| 1027 |
+
font-size: 15px !important;
|
| 1028 |
+
border-bottom: 3px solid transparent !important;
|
| 1029 |
+
transition: all 0.3s ease !important;
|
| 1030 |
+
}
|
| 1031 |
+
|
| 1032 |
+
button.tab-nav:hover {
|
| 1033 |
+
background: rgba(102, 126, 234, 0.05) !important;
|
| 1034 |
+
}
|
| 1035 |
+
|
| 1036 |
+
button.tab-nav.selected {
|
| 1037 |
+
border-bottom-color: #667eea !important;
|
| 1038 |
+
color: #667eea !important;
|
| 1039 |
+
}
|
| 1040 |
+
|
| 1041 |
+
/* Markdown styling */
|
| 1042 |
+
.markdown-text h1 {
|
| 1043 |
+
color: #1e293b !important;
|
| 1044 |
+
font-size: 28px !important;
|
| 1045 |
+
font-weight: 700 !important;
|
| 1046 |
+
margin-bottom: 10px !important;
|
| 1047 |
+
}
|
| 1048 |
+
|
| 1049 |
+
.markdown-text h2 {
|
| 1050 |
+
color: #334155 !important;
|
| 1051 |
+
font-size: 20px !important;
|
| 1052 |
+
font-weight: 600 !important;
|
| 1053 |
+
margin-top: 20px !important;
|
| 1054 |
+
}
|
| 1055 |
+
|
| 1056 |
+
.markdown-text a {
|
| 1057 |
+
color: #667eea !important;
|
| 1058 |
+
text-decoration: none !important;
|
| 1059 |
+
font-weight: 500 !important;
|
| 1060 |
}
|
| 1061 |
+
|
| 1062 |
+
.markdown-text a:hover {
|
| 1063 |
+
text-decoration: underline !important;
|
| 1064 |
+
}
|
| 1065 |
+
|
| 1066 |
+
.markdown-text code {
|
| 1067 |
+
background: #f1f5f9 !important;
|
| 1068 |
+
padding: 2px 6px !important;
|
| 1069 |
+
border-radius: 4px !important;
|
| 1070 |
+
font-size: 13px !important;
|
| 1071 |
+
color: #e11d48 !important;
|
| 1072 |
+
}
|
| 1073 |
+
|
| 1074 |
+
/* Scrollbar styling */
|
| 1075 |
+
.output-box::-webkit-scrollbar {
|
| 1076 |
+
width: 10px;
|
| 1077 |
+
}
|
| 1078 |
+
|
| 1079 |
+
.output-box::-webkit-scrollbar-track {
|
| 1080 |
+
background: #2d2d30;
|
| 1081 |
+
border-radius: 5px;
|
| 1082 |
+
}
|
| 1083 |
+
|
| 1084 |
+
.output-box::-webkit-scrollbar-thumb {
|
| 1085 |
+
background: #555;
|
| 1086 |
+
border-radius: 5px;
|
| 1087 |
+
}
|
| 1088 |
+
|
| 1089 |
+
.output-box::-webkit-scrollbar-thumb:hover {
|
| 1090 |
+
background: #666;
|
| 1091 |
+
}
|
| 1092 |
+
|
| 1093 |
+
/* Animation */
|
| 1094 |
+
@keyframes fadeIn {
|
| 1095 |
+
from { opacity: 0; transform: translateY(10px); }
|
| 1096 |
+
to { opacity: 1; transform: translateY(0); }
|
| 1097 |
+
}
|
| 1098 |
+
|
| 1099 |
+
.input-section {
|
| 1100 |
+
animation: fadeIn 0.5s ease;
|
| 1101 |
+
}
|
| 1102 |
+
|
| 1103 |
+
/* Responsive design */
|
| 1104 |
+
@media (max-width: 768px) {
|
| 1105 |
+
.container {
|
| 1106 |
+
padding: 10px;
|
| 1107 |
+
}
|
| 1108 |
+
|
| 1109 |
+
.main-header {
|
| 1110 |
+
padding: 1.5rem;
|
| 1111 |
+
}
|
| 1112 |
+
|
| 1113 |
+
.input-section {
|
| 1114 |
+
padding: 15px;
|
| 1115 |
+
}
|
| 1116 |
}
|
| 1117 |
"""
|
| 1118 |
|
| 1119 |
+
with gr.Blocks(css=css, theme=gr.themes.Soft(
|
| 1120 |
+
primary_hue="purple",
|
| 1121 |
+
secondary_hue="purple",
|
| 1122 |
+
neutral_hue="slate"
|
| 1123 |
+
)) as demo:
|
| 1124 |
+
gr.HTML("""
|
| 1125 |
+
<div class="main-header">
|
| 1126 |
+
<h1 style="font-size: 2.5rem; margin: 0; font-weight: 700;">
|
| 1127 |
+
๐ Repository Converter Pro
|
| 1128 |
+
</h1>
|
| 1129 |
+
<p style="font-size: 1.1rem; margin-top: 10px; opacity: 0.95;">
|
| 1130 |
+
Seamlessly transfer repositories between GitHub and HuggingFace
|
| 1131 |
+
</p>
|
| 1132 |
+
</div>
|
| 1133 |
+
""")
|
| 1134 |
|
| 1135 |
+
with gr.Tabs(elem_classes="tabs"):
|
| 1136 |
+
with gr.Tab("๐ GitHub โ HF Space", elem_id="tab1"):
|
| 1137 |
+
with gr.Row():
|
| 1138 |
+
with gr.Column(scale=5):
|
| 1139 |
+
with gr.Group(elem_classes="input-section"):
|
| 1140 |
+
gr.Markdown("### ๐ฆ Source Repository")
|
| 1141 |
+
repo_git = gr.Textbox(
|
| 1142 |
+
label="GitHub Repository URL",
|
| 1143 |
+
placeholder="https://github.com/username/repository",
|
| 1144 |
+
info="Enter the full GitHub repository URL"
|
| 1145 |
+
)
|
| 1146 |
+
|
| 1147 |
+
gr.Markdown("### ๐ฏ Destination Settings")
|
| 1148 |
+
repo_hf = gr.Textbox(
|
| 1149 |
+
label="HuggingFace Space Name",
|
| 1150 |
+
placeholder="my-awesome-space",
|
| 1151 |
+
info="Choose a unique name for your Space"
|
| 1152 |
+
)
|
| 1153 |
+
|
| 1154 |
+
sdk_choices = gr.Radio(
|
| 1155 |
+
["gradio", "streamlit", "docker", "static"],
|
| 1156 |
+
label="Space SDK Type",
|
| 1157 |
+
value="gradio",
|
| 1158 |
+
elem_classes="radio-group"
|
| 1159 |
+
)
|
| 1160 |
+
|
| 1161 |
+
gr.Markdown("### โ๏ธ Advanced Options")
|
| 1162 |
+
with gr.Row():
|
| 1163 |
+
skip_lfs = gr.Checkbox(
|
| 1164 |
+
label="Skip Large Files (LFS)",
|
| 1165 |
+
value=True,
|
| 1166 |
+
info="Recommended for faster deployment"
|
| 1167 |
+
)
|
| 1168 |
+
enable_smart_generation = gr.Checkbox(
|
| 1169 |
+
label="๐ค AI-Powered App Generation",
|
| 1170 |
+
value=False,
|
| 1171 |
+
info="Generate app.py automatically"
|
| 1172 |
+
)
|
| 1173 |
+
|
| 1174 |
+
btn_to_hf = gr.Button("๐ Deploy to HuggingFace",
|
| 1175 |
+
variant="primary",
|
| 1176 |
+
elem_classes="primary-btn",
|
| 1177 |
+
size="lg")
|
| 1178 |
+
|
| 1179 |
+
with gr.Column(scale=7):
|
| 1180 |
+
with gr.Group(elem_classes="input-section"):
|
| 1181 |
+
gr.Markdown("### ๐ Deployment Progress")
|
| 1182 |
+
output_to_hf = gr.Textbox(
|
| 1183 |
+
label="",
|
| 1184 |
+
lines=20,
|
| 1185 |
+
elem_classes="output-box",
|
| 1186 |
+
interactive=False,
|
| 1187 |
+
show_copy_button=True
|
| 1188 |
+
)
|
| 1189 |
+
|
| 1190 |
+
# Status indicator
|
| 1191 |
if not os.getenv("HF_TOKEN"):
|
| 1192 |
+
gr.HTML("""
|
| 1193 |
+
<div style="background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; padding: 12px; margin-top: 10px;">
|
| 1194 |
+
<span style="color: #dc2626; font-weight: 600;">โ ๏ธ Configuration Required:</span>
|
| 1195 |
+
<span style="color: #7f1d1d;"> Please set HF_TOKEN in Space settings</span>
|
| 1196 |
+
</div>
|
| 1197 |
+
""")
|
| 1198 |
else:
|
| 1199 |
+
gr.HTML("""
|
| 1200 |
+
<div style="background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 12px; margin-top: 10px;">
|
| 1201 |
+
<span style="color: #16a34a; font-weight: 600;">โ
Ready:</span>
|
| 1202 |
+
<span style="color: #14532d;"> HF_TOKEN configured successfully</span>
|
| 1203 |
+
</div>
|
| 1204 |
+
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1205 |
|
| 1206 |
btn_to_hf.click(
|
| 1207 |
fn=clone,
|
|
|
|
| 1209 |
outputs=output_to_hf
|
| 1210 |
)
|
| 1211 |
|
| 1212 |
+
with gr.Tab("๐ค HF Space โ GitHub", elem_id="tab2"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1213 |
with gr.Row():
|
| 1214 |
+
with gr.Column(scale=5):
|
| 1215 |
+
with gr.Group(elem_classes="input-section"):
|
| 1216 |
+
gr.Markdown("### ๐ฏ Source Space")
|
| 1217 |
+
hf_username = gr.Textbox(
|
| 1218 |
+
label="HuggingFace Username",
|
| 1219 |
+
placeholder="your-hf-username",
|
| 1220 |
+
info="Your HuggingFace account name"
|
| 1221 |
+
)
|
| 1222 |
+
hf_space_name = gr.Textbox(
|
| 1223 |
+
label="Space Name",
|
| 1224 |
+
placeholder="your-space-name",
|
| 1225 |
+
info="Name of the Space to export"
|
| 1226 |
+
)
|
| 1227 |
+
|
| 1228 |
+
gr.Markdown("### ๐ฆ GitHub Destination")
|
| 1229 |
+
github_username = gr.Textbox(
|
| 1230 |
+
label="GitHub Username",
|
| 1231 |
+
placeholder="your-github-username",
|
| 1232 |
+
info="Your GitHub account name"
|
| 1233 |
+
)
|
| 1234 |
+
github_repo_name = gr.Textbox(
|
| 1235 |
+
label="Repository Name",
|
| 1236 |
+
placeholder="new-repo-name",
|
| 1237 |
+
info="Name for the new GitHub repository"
|
| 1238 |
+
)
|
| 1239 |
+
|
| 1240 |
+
gr.Markdown("### ๐ Authentication")
|
| 1241 |
+
github_token = gr.Textbox(
|
| 1242 |
+
label="GitHub Personal Access Token",
|
| 1243 |
+
type="password",
|
| 1244 |
+
placeholder="ghp_xxxxxxxxxxxxxxxxxxxx",
|
| 1245 |
+
info="Generate at: github.com/settings/tokens (needs 'repo' scope)"
|
| 1246 |
+
)
|
| 1247 |
+
|
| 1248 |
+
btn_to_github = gr.Button("๐ค Export to GitHub",
|
| 1249 |
+
variant="primary",
|
| 1250 |
+
elem_classes="primary-btn",
|
| 1251 |
+
size="lg")
|
| 1252 |
+
|
| 1253 |
+
with gr.Column(scale=7):
|
| 1254 |
+
with gr.Group(elem_classes="input-section"):
|
| 1255 |
+
gr.Markdown("### ๐ Export Progress")
|
| 1256 |
+
output_to_github = gr.Textbox(
|
| 1257 |
+
label="",
|
| 1258 |
+
lines=20,
|
| 1259 |
+
elem_classes="output-box",
|
| 1260 |
+
interactive=False,
|
| 1261 |
+
show_copy_button=True
|
| 1262 |
+
)
|
| 1263 |
|
| 1264 |
btn_to_github.click(
|
| 1265 |
fn=space_to_github,
|
| 1266 |
+
inputs=[hf_username, hf_space_name, github_username, github_repo_name, github_token],
|
| 1267 |
outputs=output_to_github
|
| 1268 |
)
|
| 1269 |
|
| 1270 |
gr.Markdown("""
|
| 1271 |
---
|
| 1272 |
+
<div style="text-align: center; margin-top: 30px; color: #64748b;">
|
| 1273 |
+
<h3 style="color: #334155;">๐ ๏ธ Quick Start Guide</h3>
|
| 1274 |
+
|
| 1275 |
+
<div style="display: flex; justify-content: space-around; margin-top: 20px; flex-wrap: wrap;">
|
| 1276 |
+
<div style="flex: 1; min-width: 250px; margin: 10px; padding: 20px; background: #f8fafc; border-radius: 10px;">
|
| 1277 |
+
<h4 style="color: #667eea;">GitHub โ HuggingFace</h4>
|
| 1278 |
+
<p>Deploy any GitHub repository as a HuggingFace Space with automatic LFS handling and optional AI-powered interface generation.</p>
|
| 1279 |
+
</div>
|
| 1280 |
+
|
| 1281 |
+
<div style="flex: 1; min-width: 250px; margin: 10px; padding: 20px; background: #f8fafc; border-radius: 10px;">
|
| 1282 |
+
<h4 style="color: #667eea;">HuggingFace โ GitHub</h4>
|
| 1283 |
+
<p>Export your HuggingFace Spaces to GitHub for version control, collaboration, and backup.</p>
|
| 1284 |
+
</div>
|
| 1285 |
+
</div>
|
| 1286 |
+
|
| 1287 |
+
<div style="margin-top: 30px;">
|
| 1288 |
+
<h4 style="color: #334155;">Required Tokens</h4>
|
| 1289 |
+
<p>
|
| 1290 |
+
<code style="background: #e2e8f0; padding: 4px 8px; border-radius: 4px;">HF_TOKEN</code> for GitHub โ HF |
|
| 1291 |
+
<code style="background: #e2e8f0; padding: 4px 8px; border-radius: 4px;">GitHub PAT</code> for HF โ GitHub |
|
| 1292 |
+
<code style="background: #e2e8f0; padding: 4px 8px; border-radius: 4px;">FIREWORKS_API_KEY</code> for AI features
|
| 1293 |
+
</p>
|
| 1294 |
+
</div>
|
| 1295 |
+
</div>
|
| 1296 |
""")
|
| 1297 |
|
| 1298 |
if __name__ == "__main__":
|