openfree commited on
Commit
d3302fd
ยท
verified ยท
1 Parent(s): 9f5c15f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +424 -120
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
- yield f"โœ… GitHub repository created: {repo_info['html_url']}"
 
807
  elif create_response.status_code == 422:
808
  # ๋ ˆํฌ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•จ
809
- repo_info = {"html_url": f"https://github.com/{github_username}/{github_repo_name}"}
810
- yield f"โ„น๏ธ Repository already exists: {repo_info['html_url']}"
811
  else:
812
- raise Exception(f"Failed to create repository: {create_response.json().get('message', 'Unknown error')}")
 
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
- yield f"\n๐Ÿ”— GitHub Repository: https://github.com/{github_username}/{github_repo_name}"
847
- yield f"\nโœจ Clone command: `git clone https://github.com/{github_username}/{github_repo_name}.git`"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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: 900px;
861
  margin: auto;
862
  padding: 20px;
863
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
864
  .output-box {
865
- min-height: 100px;
866
- max-height: 400px;
867
- overflow-y: auto;
868
- font-family: monospace;
869
- font-size: 14px;
870
- line-height: 1.5;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
871
  }
872
- .tab-content {
873
- margin-top: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
874
  }
875
  """
876
 
877
- with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
878
- gr.Markdown("# ๐Ÿ”„ GitHub โ†” HuggingFace Space Converter")
 
 
 
 
 
 
 
 
 
 
 
 
 
879
 
880
- with gr.Tabs():
881
- with gr.Tab("GitHub โ†’ HF Space"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
882
  if not os.getenv("HF_TOKEN"):
883
- gr.Markdown("โŒ HF_TOKEN Required - Set it in Space settings")
 
 
 
 
 
884
  else:
885
- gr.Markdown("โœ… HF_TOKEN Found")
886
-
887
- with gr.Row():
888
- with gr.Column():
889
- repo_git = gr.Textbox(
890
- label="GitHub Repository URL",
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
- hf_username = gr.Textbox(
939
- label="HuggingFace Username",
940
- placeholder="e.g., john_doe"
941
- )
942
- hf_space_name = gr.Textbox(
943
- label="HuggingFace Space Name",
944
- placeholder="e.g., my-space"
945
- )
946
- github_repo_name = gr.Textbox(
947
- label="GitHub Repository Name",
948
- placeholder="e.g., my-new-repo"
949
- )
950
- github_token = gr.Textbox(
951
- label="GitHub Personal Access Token",
952
- type="password",
953
- placeholder="ghp_xxxxxxxxxxxx",
954
- info="Token needs 'repo' scope. Get it from: https://github.com/settings/tokens"
955
- )
956
-
957
- btn_to_github = gr.Button("๐Ÿ“ค Export to GitHub", variant="primary")
958
-
959
- with gr.Column():
960
- output_to_github = gr.Textbox(
961
- label="Progress",
962
- lines=15,
963
- elem_classes=["output-box"],
964
- interactive=False,
965
- show_copy_button=True
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
- ### ๐Ÿ“– Instructions
977
-
978
- **GitHub โ†’ HF Space:**
979
- - Clone any public GitHub repository to your HuggingFace account
980
- - Automatically handles LFS issues
981
- - Optional AI-powered app.py generation
982
-
983
- **HF Space โ†’ GitHub:**
984
- - Export your HuggingFace Space to a new GitHub repository
985
- - Requires GitHub Personal Access Token with 'repo' scope
986
- - Preserves all files and structure
987
-
988
- ### ๐Ÿ”‘ Required Tokens
989
- - **HF_TOKEN**: Set in Space settings for GitHub โ†’ HF
990
- - **GitHub Token**: Required for HF โ†’ GitHub (create at [GitHub Settings](https://github.com/settings/tokens))
991
- - **FIREWORKS_API_KEY**: Optional, for smart app generation
 
 
 
 
 
 
 
 
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__":