Update app.py
Browse files
app.py
CHANGED
@@ -1,3 +1,5 @@
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
import re
|
3 |
import json
|
@@ -98,7 +100,7 @@ def escape_html_for_markdown(text):
|
|
98 |
return text.replace("&", "&").replace("<", "<").replace(">", ">")
|
99 |
|
100 |
def _infer_lang_from_filename(filename):
|
101 |
-
if not filename: return "text"
|
102 |
if '.' in filename:
|
103 |
ext = filename.split('.')[-1].lower()
|
104 |
mapping = {
|
@@ -110,17 +112,17 @@ def _infer_lang_from_filename(filename):
|
|
110 |
'c': 'c', 'h': 'c', 'cpp': 'cpp', 'hpp': 'cpp', 'cs': 'csharp', 'java': 'java',
|
111 |
'rb': 'ruby', 'php': 'php', 'go': 'go', 'rs': 'rust', 'swift': 'swift', 'kt': 'kotlin', 'kts': 'kotlin',
|
112 |
'sql': 'sql', 'dockerfile': 'docker', 'tf': 'terraform', 'hcl': 'terraform',
|
113 |
-
'txt': 'text', 'log': 'text', 'ini': 'ini', 'conf': 'text', 'cfg': 'text',
|
114 |
-
'csv': 'text', 'tsv': 'text', 'err': 'text',
|
115 |
-
'.env': 'text', '.gitignore': 'text', '.npmrc': 'text', '.gitattributes': 'text',
|
116 |
'makefile': 'makefile',
|
117 |
}
|
118 |
-
return mapping.get(ext, "text")
|
119 |
base_filename = os.path.basename(filename)
|
120 |
if base_filename == 'Dockerfile': return 'docker'
|
121 |
if base_filename == 'Makefile': return 'makefile'
|
122 |
-
if base_filename.startswith('.'): return 'text'
|
123 |
-
return "text"
|
124 |
|
125 |
def _clean_filename(filename_line_content):
|
126 |
text = filename_line_content.strip()
|
@@ -141,7 +143,7 @@ def _parse_and_update_state_cache(latest_bot_message_content, current_files_stat
|
|
141 |
|
142 |
structure_match = structure_pattern.search(content)
|
143 |
if structure_match:
|
144 |
-
structure_block_state = {"filename": "File Structure (from AI)", "language": structure_match.group("struct_lang") or "text", "code": structure_match.group("structure_code").strip(), "is_binary": False, "is_structure_block": True}
|
145 |
|
146 |
current_message_proposed_filenames = []
|
147 |
for match in file_pattern.finditer(content):
|
@@ -200,7 +202,7 @@ def _export_selected_logic(selected_filenames, space_line_name_for_md, parsed_bl
|
|
200 |
if block.get('is_binary') or content.startswith(("[Binary file", "[Error loading content:", "[Binary or Skipped file]")):
|
201 |
output_lines.append(content)
|
202 |
else:
|
203 |
-
lang = block.get('language', 'text') or 'text'
|
204 |
output_lines.extend([f"{bbb}{lang}", content, bbb])
|
205 |
output_lines.append("")
|
206 |
exported_content_count += 1
|
@@ -257,7 +259,7 @@ def _generate_ui_outputs_from_cache(owner, space_name):
|
|
257 |
if block.get('is_binary') or content.startswith(("[Binary file", "[Error loading content:", "[Binary or Skipped file]")):
|
258 |
preview_md_lines.append(f"\n`{escape_html_for_markdown(content.strip())}`\n")
|
259 |
else:
|
260 |
-
lang = block.get('language', 'text') or 'text'
|
261 |
preview_md_lines.append(f"\n{bbb}{lang}\n{content.strip()}\n{bbb}\n")
|
262 |
preview_md_val = "\n".join(preview_md_lines)
|
263 |
|
@@ -593,12 +595,21 @@ def handle_confirm_changes(hf_api_key, owner_name, space_name, changeset):
|
|
593 |
global parsed_code_blocks_state_cache
|
594 |
|
595 |
_status = "Applying changes..."
|
|
|
596 |
yield _status, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(value="*Applying changes...*")
|
597 |
-
#
|
598 |
-
yield None, None, None, None, None, None, None, None, None, None, None, None, None, None, None #
|
|
|
599 |
|
600 |
if not changeset:
|
601 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
602 |
|
603 |
first_action = changeset[0] if changeset else None
|
604 |
is_exclusive_duplicate = first_action and first_action.get('type') == 'DUPLICATE_SPACE'
|
@@ -615,8 +626,10 @@ def handle_confirm_changes(hf_api_key, owner_name, space_name, changeset):
|
|
615 |
private=change.get("private", False)
|
616 |
)
|
617 |
_status_reload = f"{status_message} | Attempting to load the new Space [{change['target_repo_id']}]..."
|
|
|
618 |
yield gr.update(value=_status_reload), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
619 |
|
|
|
620 |
target_repo_id = change['target_repo_id']
|
621 |
new_owner, new_space_name = target_repo_id.split('/', 1) if '/' in target_repo_id else (None, target_repo_id)
|
622 |
|
@@ -664,18 +677,20 @@ def handle_confirm_changes(hf_api_key, owner_name, space_name, changeset):
|
|
664 |
|
665 |
runtime_status_md = handle_refresh_space_status(hf_api_key, new_owner, new_space_name)
|
666 |
|
|
|
667 |
yield (
|
668 |
-
gr.update(value=final_overall_status), gr.update(value=_formatted), gr.update(value=_detected), _download,
|
669 |
-
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
670 |
-
[], gr.update(value="*No changes proposed.*"),
|
671 |
-
owner_update, space_update, file_browser_update, iframe_update,
|
672 |
-
gr.update(value=runtime_status_md)
|
673 |
)
|
674 |
|
675 |
else:
|
676 |
reload_error = "Cannot load new Space state: Owner or Space Name missing after duplication."
|
677 |
_formatted, _detected, _download = _generate_ui_outputs_from_cache(None, None)
|
678 |
final_overall_status = status_message + f" | Reload Status: {reload_error}"
|
|
|
679 |
yield (
|
680 |
gr.update(value=final_overall_status), gr.update(value=_formatted), gr.update(value=_detected), _download,
|
681 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
@@ -705,10 +720,18 @@ def handle_confirm_changes(hf_api_key, owner_name, space_name, changeset):
|
|
705 |
if not delete_repo_id_target or delete_repo_id_target != current_repo_id:
|
706 |
final_overall_status = f"DELETE_SPACE Error: Action blocked. Cannot delete '{delete_repo_id_target}'. Only deletion of the currently loaded space ('{current_repo_id}') is permitted via AI action."
|
707 |
print(f"Blocked DELETE_SPACE action via confirm: requested '{delete_repo_id_target}', current '{current_repo_id}'.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
708 |
else:
|
709 |
status_message = build_logic_delete_space(hf_api_key, delete_owner, delete_space)
|
710 |
final_overall_status = status_message
|
711 |
if "Successfully" in status_message:
|
|
|
712 |
parsed_code_blocks_state_cache = []
|
713 |
_formatted, _detected, _download = _generate_ui_outputs_from_cache(None, None)
|
714 |
owner_update = gr.update(value="")
|
@@ -722,7 +745,7 @@ def handle_confirm_changes(hf_api_key, owner_name, space_name, changeset):
|
|
722 |
space_update = gr.update()
|
723 |
file_browser_update = gr.update()
|
724 |
iframe_update = gr.update()
|
725 |
-
runtime_status_update = handle_refresh_space_status(hf_api_key, owner_name, space_name)
|
726 |
|
727 |
|
728 |
cleared_changeset = []
|
@@ -883,14 +906,15 @@ def update_models_dropdown(provider_select):
|
|
883 |
def handle_detect_user_and_list_spaces(hf_api_key_ui):
|
884 |
_status = "Detecting user from token..."
|
885 |
# Yield initial state: update status, clear owner/space fields, clear list display, clear duplicate fields
|
886 |
-
|
|
|
887 |
|
888 |
|
889 |
token, token_err = build_logic_get_api_token(hf_api_key_ui)
|
890 |
if token_err:
|
891 |
_status = f"Detection Error: {token_err}"
|
892 |
# Yield error status, keep fields cleared, update list display error
|
893 |
-
yield (gr.update(value=_status), gr.update(), gr.update(), gr.update(value="*Could not list spaces due to token error
|
894 |
return
|
895 |
|
896 |
try:
|
@@ -907,7 +931,8 @@ def handle_detect_user_and_list_spaces(hf_api_key_ui):
|
|
907 |
else:
|
908 |
list_spaces_update = gr.update(value=list_spaces_md)
|
909 |
|
910 |
-
|
|
|
911 |
|
912 |
|
913 |
except Exception as e:
|
@@ -915,7 +940,8 @@ def handle_detect_user_and_list_spaces(hf_api_key_ui):
|
|
915 |
print(f"Error in handle_detect_user: {e}")
|
916 |
import traceback
|
917 |
traceback.print_exc()
|
918 |
-
|
|
|
919 |
|
920 |
|
921 |
def handle_load_existing_space(hf_api_key_ui, ui_owner_name, ui_space_name):
|
@@ -926,56 +952,64 @@ def handle_load_existing_space(hf_api_key_ui, ui_owner_name, ui_space_name):
|
|
926 |
_changeset_clear = []
|
927 |
_changeset_summary_clear = "*No changes proposed.*"
|
928 |
_confirm_ui_hidden = gr.update(visible=False)
|
929 |
-
_list_spaces_display_placeholder = "*List of spaces will appear here.*"
|
930 |
_target_owner_clear, _target_space_clear, _target_private_clear = gr.update(value=""), gr.update(value=""), gr.update(value=False)
|
931 |
|
932 |
|
|
|
933 |
yield (
|
934 |
gr.update(value=_formatted_md_val), gr.update(value=_detected_preview_val), gr.update(value=_status_val), _file_browser_update,
|
935 |
gr.update(value=ui_owner_name), gr.update(value=ui_space_name),
|
936 |
_iframe_html_update, _download_btn_update, gr.update(value=_build_status_clear),
|
937 |
gr.update(value=_edit_status_clear), gr.update(value=_runtime_status_clear),
|
938 |
_changeset_clear, gr.update(value=_changeset_summary_clear), _confirm_ui_hidden, _confirm_ui_hidden, _confirm_ui_hidden,
|
939 |
-
|
940 |
)
|
941 |
|
942 |
owner_to_use = ui_owner_name
|
943 |
token, token_err = build_logic_get_api_token(hf_api_key_ui)
|
944 |
if token_err:
|
945 |
_status_val = f"Load Error: {token_err}"
|
946 |
-
|
|
|
947 |
return
|
948 |
if not owner_to_use:
|
949 |
try:
|
950 |
user_info = build_logic_whoami(token=token)
|
951 |
owner_to_use = user_info.get('name')
|
952 |
if not owner_to_use: raise Exception("Could not find user name from token.")
|
953 |
-
|
|
|
954 |
except Exception as e:
|
955 |
_status_val = f"Load Error: Error auto-detecting owner: {e}"
|
956 |
-
|
|
|
957 |
return
|
958 |
|
959 |
if not owner_to_use or not ui_space_name:
|
960 |
_status_val = "Load Error: Owner and Space Name are required."
|
961 |
-
|
|
|
962 |
return
|
963 |
|
964 |
sdk, file_list, err = get_space_repository_info(hf_api_key_ui, ui_space_name, owner_to_use)
|
965 |
|
966 |
-
|
|
|
|
|
967 |
|
968 |
if err:
|
969 |
_status_val = f"Load Error: {err}"
|
970 |
parsed_code_blocks_state_cache = []
|
971 |
_formatted, _detected, _download = _generate_ui_outputs_from_cache(owner_to_use, ui_space_name)
|
|
|
972 |
yield (
|
973 |
gr.update(value=_formatted), gr.update(value=_detected), gr.update(value=_status_val),
|
974 |
-
gr.update(visible=False, choices=[], value=None),
|
975 |
-
gr.update(), gr.update(),
|
976 |
-
gr.update(value=None, visible=False),
|
977 |
-
_download, gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(),
|
978 |
-
gr.update(value=
|
979 |
)
|
980 |
return
|
981 |
|
@@ -1004,13 +1038,16 @@ def handle_load_existing_space(hf_api_key_ui, ui_owner_name, ui_space_name):
|
|
1004 |
|
1005 |
runtime_status_md = handle_refresh_space_status(hf_api_key_ui, owner_to_use, ui_space_name)
|
1006 |
|
|
|
1007 |
yield (
|
1008 |
-
gr.update(value=_formatted), gr.update(value=_detected), gr.update(value=_status_val),
|
1009 |
-
file_browser_update,
|
1010 |
-
gr.update(), gr.update(),
|
1011 |
-
iframe_update,
|
1012 |
-
_download,
|
1013 |
-
gr.update(
|
|
|
|
|
1014 |
)
|
1015 |
|
1016 |
def handle_build_space_button(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, space_sdk_ui, is_private_ui, formatted_markdown_content):
|
@@ -1021,10 +1058,10 @@ def handle_build_space_button(hf_api_key_ui, ui_space_name_part, ui_owner_name_p
|
|
1021 |
_changeset_summary_clear = "*Manual build initiated, changes plan cleared.*"
|
1022 |
_confirm_ui_hidden = gr.update(visible=False)
|
1023 |
|
|
|
1024 |
yield (gr.update(value=_build_status), _iframe_html, _file_browser_update, gr.update(value=ui_owner_name_part), gr.update(value=ui_space_name_part),
|
1025 |
_changeset_clear, gr.update(value=_changeset_summary_clear), _confirm_ui_hidden, _confirm_ui_hidden, _confirm_ui_hidden,
|
1026 |
-
gr.update(), gr.update(), gr.update(), gr.update())
|
1027 |
-
|
1028 |
|
1029 |
if not ui_space_name_part or "/" in ui_space_name_part:
|
1030 |
_build_status = f"Build Error: Invalid Space Name '{ui_space_name_part}'."
|
@@ -1129,11 +1166,11 @@ def handle_build_space_button(hf_api_key_ui, ui_space_name_part, ui_owner_name_p
|
|
1129 |
|
1130 |
def handle_load_file_for_editing(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, selected_file_path):
|
1131 |
if not selected_file_path:
|
1132 |
-
return "", "Select a file.", "", gr.update(language="text")
|
1133 |
|
1134 |
content, err = get_space_file_content(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, selected_file_path)
|
1135 |
if err:
|
1136 |
-
return "", f"Load Error: {err}", "", gr.update(language="text")
|
1137 |
|
1138 |
lang = _infer_lang_from_filename(selected_file_path)
|
1139 |
commit_msg = f"Update {selected_file_path}"
|
@@ -1176,9 +1213,9 @@ def handle_commit_file_changes(hf_api_key_ui, ui_space_name_part, ui_owner_name_
|
|
1176 |
|
1177 |
def handle_delete_file(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, file_to_delete_path):
|
1178 |
if not ui_owner_name_part or not ui_space_name_part:
|
1179 |
-
return "Delete Error: Cannot delete file. Please load a space first.", gr.update(), "", "", "text", gr.update(), gr.update(), gr.update()
|
1180 |
if not file_to_delete_path:
|
1181 |
-
return "Delete Error: No file selected to delete.", gr.update(), "", "", "text", gr.update(), gr.update(), gr.update()
|
1182 |
|
1183 |
status_msg = build_logic_delete_space_file(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, file_to_delete_path)
|
1184 |
|
@@ -1192,7 +1229,7 @@ def handle_delete_file(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, fi
|
|
1192 |
parsed_code_blocks_state_cache = [b for b in parsed_code_blocks_state_cache if b["filename"] != file_to_delete_path]
|
1193 |
file_content_editor_update = gr.update(value="")
|
1194 |
commit_message_update = gr.update(value="")
|
1195 |
-
editor_lang_update = gr.update(language="text")
|
1196 |
file_list, _ = list_space_files_for_browsing(hf_api_key_ui, ui_space_name_part, ui_owner_name_part)
|
1197 |
file_browser_update = gr.update(choices=sorted(file_list or []), value=None)
|
1198 |
|
@@ -1290,7 +1327,7 @@ def handle_manual_duplicate_space(hf_api_key_ui, source_owner, source_space_name
|
|
1290 |
return "Duplicate Error: Target Owner and Target Space Name are required.", gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
1291 |
if "/" in target_space_name:
|
1292 |
return "Duplicate Error: Target Space Name should not contain '/'. Use Target Owner field for the owner part.", gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
1293 |
-
|
1294 |
|
1295 |
source_repo_id = f"{source_owner}/{source_space_name}"
|
1296 |
target_repo_id = f"{target_owner}/{target_space_name}"
|
@@ -1312,6 +1349,7 @@ def handle_manual_duplicate_space(hf_api_key_ui, source_owner, source_space_name
|
|
1312 |
|
1313 |
if err_list:
|
1314 |
reload_error = f"Error reloading file list after duplication: {err_list}"
|
|
|
1315 |
parsed_code_blocks_state_cache = []
|
1316 |
_file_browser_update = gr.update(visible=False, choices=[], value=None)
|
1317 |
_iframe_html_update = gr.update(value=None, visible=False)
|
@@ -1323,6 +1361,7 @@ def handle_manual_duplicate_space(hf_api_key_ui, source_owner, source_space_name
|
|
1323 |
is_binary = lang == "binary" or (err_get is not None)
|
1324 |
code = f"[Error loading content: {err_get}]" if err_get else (content or "")
|
1325 |
loaded_files.append({"filename": file_path, "code": code, "language": lang, "is_binary": is_binary, "is_structure_block": False})
|
|
|
1326 |
parsed_code_blocks_state_cache = loaded_files
|
1327 |
|
1328 |
_file_browser_update = gr.update(visible=True, choices=sorted([f["filename"] for f in parsed_code_blocks_state_cache if not f.get("is_structure_block")] or []), value=None)
|
|
|
1 |
+
### File: app.py
|
2 |
+
```python
|
3 |
import gradio as gr
|
4 |
import re
|
5 |
import json
|
|
|
100 |
return text.replace("&", "&").replace("<", "<").replace(">", ">")
|
101 |
|
102 |
def _infer_lang_from_filename(filename):
|
103 |
+
if not filename: return "text"
|
104 |
if '.' in filename:
|
105 |
ext = filename.split('.')[-1].lower()
|
106 |
mapping = {
|
|
|
112 |
'c': 'c', 'h': 'c', 'cpp': 'cpp', 'hpp': 'cpp', 'cs': 'csharp', 'java': 'java',
|
113 |
'rb': 'ruby', 'php': 'php', 'go': 'go', 'rs': 'rust', 'swift': 'swift', 'kt': 'kotlin', 'kts': 'kotlin',
|
114 |
'sql': 'sql', 'dockerfile': 'docker', 'tf': 'terraform', 'hcl': 'terraform',
|
115 |
+
'txt': 'text', 'log': 'text', 'ini': 'ini', 'conf': 'text', 'cfg': 'text',
|
116 |
+
'csv': 'text', 'tsv': 'text', 'err': 'text',
|
117 |
+
'.env': 'text', '.gitignore': 'text', '.npmrc': 'text', '.gitattributes': 'text',
|
118 |
'makefile': 'makefile',
|
119 |
}
|
120 |
+
return mapping.get(ext, "text")
|
121 |
base_filename = os.path.basename(filename)
|
122 |
if base_filename == 'Dockerfile': return 'docker'
|
123 |
if base_filename == 'Makefile': return 'makefile'
|
124 |
+
if base_filename.startswith('.'): return 'text'
|
125 |
+
return "text"
|
126 |
|
127 |
def _clean_filename(filename_line_content):
|
128 |
text = filename_line_content.strip()
|
|
|
143 |
|
144 |
structure_match = structure_pattern.search(content)
|
145 |
if structure_match:
|
146 |
+
structure_block_state = {"filename": "File Structure (from AI)", "language": structure_match.group("struct_lang") or "text", "code": structure_match.group("structure_code").strip(), "is_binary": False, "is_structure_block": True}
|
147 |
|
148 |
current_message_proposed_filenames = []
|
149 |
for match in file_pattern.finditer(content):
|
|
|
202 |
if block.get('is_binary') or content.startswith(("[Binary file", "[Error loading content:", "[Binary or Skipped file]")):
|
203 |
output_lines.append(content)
|
204 |
else:
|
205 |
+
lang = block.get('language', 'text') or 'text'
|
206 |
output_lines.extend([f"{bbb}{lang}", content, bbb])
|
207 |
output_lines.append("")
|
208 |
exported_content_count += 1
|
|
|
259 |
if block.get('is_binary') or content.startswith(("[Binary file", "[Error loading content:", "[Binary or Skipped file]")):
|
260 |
preview_md_lines.append(f"\n`{escape_html_for_markdown(content.strip())}`\n")
|
261 |
else:
|
262 |
+
lang = block.get('language', 'text') or 'text'
|
263 |
preview_md_lines.append(f"\n{bbb}{lang}\n{content.strip()}\n{bbb}\n")
|
264 |
preview_md_val = "\n".join(preview_md_lines)
|
265 |
|
|
|
595 |
global parsed_code_blocks_state_cache
|
596 |
|
597 |
_status = "Applying changes..."
|
598 |
+
# Yield initial status, hide confirm UI, clear summary
|
599 |
yield _status, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(value="*Applying changes...*")
|
600 |
+
# Yield None for the other 15 outputs that are part of this generator's outputs list
|
601 |
+
yield None, None, None, None, None, None, None, None, None, None, None, None, None, None, None # 15 None values
|
602 |
+
|
603 |
|
604 |
if not changeset:
|
605 |
+
# This case should be prevented by hiding the button, but safety first
|
606 |
+
yield (
|
607 |
+
"No changes to apply.", # status_output
|
608 |
+
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(value="No changes were staged."), # Hide confirm UI, clear summary
|
609 |
+
None, None, None, None, None, None, None, None, None, None, None # 15 None values
|
610 |
+
)
|
611 |
+
return
|
612 |
+
|
613 |
|
614 |
first_action = changeset[0] if changeset else None
|
615 |
is_exclusive_duplicate = first_action and first_action.get('type') == 'DUPLICATE_SPACE'
|
|
|
626 |
private=change.get("private", False)
|
627 |
)
|
628 |
_status_reload = f"{status_message} | Attempting to load the new Space [{change['target_repo_id']}]..."
|
629 |
+
# Yield status update only
|
630 |
yield gr.update(value=_status_reload), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
631 |
|
632 |
+
|
633 |
target_repo_id = change['target_repo_id']
|
634 |
new_owner, new_space_name = target_repo_id.split('/', 1) if '/' in target_repo_id else (None, target_repo_id)
|
635 |
|
|
|
677 |
|
678 |
runtime_status_md = handle_refresh_space_status(hf_api_key, new_owner, new_space_name)
|
679 |
|
680 |
+
# Final yield after loading the new space
|
681 |
yield (
|
682 |
+
gr.update(value=final_overall_status), gr.update(value=_formatted), gr.update(value=_detected), _download, # Status, markdown, preview, download
|
683 |
+
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), # Hide confirm UI
|
684 |
+
[], gr.update(value="*No changes proposed.*"), # Clear changeset state and display
|
685 |
+
owner_update, space_update, file_browser_update, iframe_update, # Update space/owner fields, file browser, iframe
|
686 |
+
gr.update(value=runtime_status_md) # Update runtime status
|
687 |
)
|
688 |
|
689 |
else:
|
690 |
reload_error = "Cannot load new Space state: Owner or Space Name missing after duplication."
|
691 |
_formatted, _detected, _download = _generate_ui_outputs_from_cache(None, None)
|
692 |
final_overall_status = status_message + f" | Reload Status: {reload_error}"
|
693 |
+
# Keep old UI fields, clear file browser/iframe
|
694 |
yield (
|
695 |
gr.update(value=final_overall_status), gr.update(value=_formatted), gr.update(value=_detected), _download,
|
696 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
|
|
720 |
if not delete_repo_id_target or delete_repo_id_target != current_repo_id:
|
721 |
final_overall_status = f"DELETE_SPACE Error: Action blocked. Cannot delete '{delete_repo_id_target}'. Only deletion of the currently loaded space ('{current_repo_id}') is permitted via AI action."
|
722 |
print(f"Blocked DELETE_SPACE action via confirm: requested '{delete_repo_id_target}', current '{current_repo_id}'.")
|
723 |
+
_formatted, _detected, _download = _generate_ui_outputs_from_cache(owner_name, space_name)
|
724 |
+
owner_update = gr.update()
|
725 |
+
space_update = gr.update()
|
726 |
+
file_browser_update = gr.update()
|
727 |
+
iframe_update = gr.update()
|
728 |
+
runtime_status_update = handle_refresh_space_status(hf_api_key, owner_name, space_name) # Refresh status after failed delete attempt
|
729 |
+
|
730 |
else:
|
731 |
status_message = build_logic_delete_space(hf_api_key, delete_owner, delete_space)
|
732 |
final_overall_status = status_message
|
733 |
if "Successfully" in status_message:
|
734 |
+
global parsed_code_blocks_state_cache
|
735 |
parsed_code_blocks_state_cache = []
|
736 |
_formatted, _detected, _download = _generate_ui_outputs_from_cache(None, None)
|
737 |
owner_update = gr.update(value="")
|
|
|
745 |
space_update = gr.update()
|
746 |
file_browser_update = gr.update()
|
747 |
iframe_update = gr.update()
|
748 |
+
runtime_status_update = handle_refresh_space_status(hf_api_key, owner_name, space_name) # Refresh status after failed delete attempt
|
749 |
|
750 |
|
751 |
cleared_changeset = []
|
|
|
906 |
def handle_detect_user_and_list_spaces(hf_api_key_ui):
|
907 |
_status = "Detecting user from token..."
|
908 |
# Yield initial state: update status, clear owner/space fields, clear list display, clear duplicate fields
|
909 |
+
# outputs list: [status_output, owner_name_input, space_name_input, list_spaces_display, file_browser_dropdown, space_iframe_display, formatted_space_output_display, detected_files_display, build_status_display, edit_status_display, space_runtime_status_display, changeset_state, changeset_display, confirm_accordion, confirm_button, cancel_button, target_owner_input, target_space_name_input, target_private_checkbox] (19 items)
|
910 |
+
yield (gr.update(value=_status), gr.update(value=""), gr.update(value=""), gr.update(value="*Listing spaces...*"), gr.update(visible=False, choices=[], value=None), gr.update(value=None, visible=False), gr.update(value="*Load or create a space to see its definition.*"), gr.update(value="*A preview of the latest file versions will appear here.*"), gr.update(value="*Manual build status...*"), gr.update(value="*Select a file...*"), gr.update(value="*Runtime/Repo status will appear here.*"), [], gr.update(value="*No changes proposed.*"), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(value=""), gr.update(value=""), gr.update(value=False))
|
911 |
|
912 |
|
913 |
token, token_err = build_logic_get_api_token(hf_api_key_ui)
|
914 |
if token_err:
|
915 |
_status = f"Detection Error: {token_err}"
|
916 |
# Yield error status, keep fields cleared, update list display error
|
917 |
+
yield (gr.update(value=_status), gr.update(), gr.update(), gr.update(value=f"*Could not list spaces due to token error: {token_err}*"), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update())
|
918 |
return
|
919 |
|
920 |
try:
|
|
|
931 |
else:
|
932 |
list_spaces_update = gr.update(value=list_spaces_md)
|
933 |
|
934 |
+
# Final yield: Update status, owner, list spaces, keep others cleared/defaulted
|
935 |
+
yield (gr.update(value=_status), owner_update, gr.update(value=""), list_spaces_update, gr.update(visible=False, choices=[], value=None), gr.update(value=None, visible=False), gr.update(value="*Load or create a space to see its definition.*"), gr.update(value="*A preview of the latest file versions will appear here.*"), gr.update(value="*Manual build status...*"), gr.update(value="*Select a file...*"), gr.update(value="*Runtime/Repo status will appear here.*"), [], gr.update(value="*No changes proposed.*"), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(value=""), gr.update(value=""), gr.update(value=False))
|
936 |
|
937 |
|
938 |
except Exception as e:
|
|
|
940 |
print(f"Error in handle_detect_user: {e}")
|
941 |
import traceback
|
942 |
traceback.print_exc()
|
943 |
+
# Final yield on error: Update status, keep others cleared/defaulted, list spaces error
|
944 |
+
yield (gr.update(value=_status), gr.update(), gr.update(), gr.update(value=f"*Could not list spaces due to user detection error: {e}*"), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update())
|
945 |
|
946 |
|
947 |
def handle_load_existing_space(hf_api_key_ui, ui_owner_name, ui_space_name):
|
|
|
952 |
_changeset_clear = []
|
953 |
_changeset_summary_clear = "*No changes proposed.*"
|
954 |
_confirm_ui_hidden = gr.update(visible=False)
|
955 |
+
_list_spaces_display_placeholder = gr.update(value="*List of spaces will appear here.*")
|
956 |
_target_owner_clear, _target_space_clear, _target_private_clear = gr.update(value=""), gr.update(value=""), gr.update(value=False)
|
957 |
|
958 |
|
959 |
+
# outputs list: [formatted_space_output_display, detected_files_preview, status_output, file_browser_dropdown, owner_name_input, space_name_input, space_iframe_display, download_button, build_status_display, edit_status_display, space_runtime_status_display, changeset_state, changeset_display, confirm_accordion, confirm_button, cancel_button, list_spaces_display, target_owner_input, target_space_name_input, target_private_checkbox] (20 items)
|
960 |
yield (
|
961 |
gr.update(value=_formatted_md_val), gr.update(value=_detected_preview_val), gr.update(value=_status_val), _file_browser_update,
|
962 |
gr.update(value=ui_owner_name), gr.update(value=ui_space_name),
|
963 |
_iframe_html_update, _download_btn_update, gr.update(value=_build_status_clear),
|
964 |
gr.update(value=_edit_status_clear), gr.update(value=_runtime_status_clear),
|
965 |
_changeset_clear, gr.update(value=_changeset_summary_clear), _confirm_ui_hidden, _confirm_ui_hidden, _confirm_ui_hidden,
|
966 |
+
_list_spaces_display_placeholder, _target_owner_clear, _target_space_clear, _target_private_clear
|
967 |
)
|
968 |
|
969 |
owner_to_use = ui_owner_name
|
970 |
token, token_err = build_logic_get_api_token(hf_api_key_ui)
|
971 |
if token_err:
|
972 |
_status_val = f"Load Error: {token_err}"
|
973 |
+
# Yield only status and keep others as initial state
|
974 |
+
yield (gr.update(), gr.update(), gr.update(value=_status_val), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update())
|
975 |
return
|
976 |
if not owner_to_use:
|
977 |
try:
|
978 |
user_info = build_logic_whoami(token=token)
|
979 |
owner_to_use = user_info.get('name')
|
980 |
if not owner_to_use: raise Exception("Could not find user name from token.")
|
981 |
+
# Yield updated owner and status, keep others as initial state
|
982 |
+
yield (gr.update(), gr.update(), gr.update(value=f"Loading Space: {owner_to_use}/{ui_space_name} (Auto-detected owner)..."), gr.update(), gr.update(value=owner_to_use), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update())
|
983 |
except Exception as e:
|
984 |
_status_val = f"Load Error: Error auto-detecting owner: {e}"
|
985 |
+
# Yield only status and keep others as initial state
|
986 |
+
yield (gr.update(), gr.update(), gr.update(value=_status_val), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update())
|
987 |
return
|
988 |
|
989 |
if not owner_to_use or not ui_space_name:
|
990 |
_status_val = "Load Error: Owner and Space Name are required."
|
991 |
+
# Yield only status and keep others as initial state
|
992 |
+
yield (gr.update(), gr.update(), gr.update(value=_status_val), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update())
|
993 |
return
|
994 |
|
995 |
sdk, file_list, err = get_space_repository_info(hf_api_key_ui, ui_space_name, owner_to_use)
|
996 |
|
997 |
+
# Yield updated owner and space textboxes, keep others as initial state
|
998 |
+
yield (gr.update(), gr.update(), gr.update(), gr.update(), gr.update(value=owner_to_use), gr.update(value=ui_space_name), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update())
|
999 |
+
|
1000 |
|
1001 |
if err:
|
1002 |
_status_val = f"Load Error: {err}"
|
1003 |
parsed_code_blocks_state_cache = []
|
1004 |
_formatted, _detected, _download = _generate_ui_outputs_from_cache(owner_to_use, ui_space_name)
|
1005 |
+
# Yield final state on error
|
1006 |
yield (
|
1007 |
gr.update(value=_formatted), gr.update(value=_detected), gr.update(value=_status_val),
|
1008 |
+
gr.update(visible=False, choices=[], value=None), # Clear and hide file browser
|
1009 |
+
gr.update(), gr.update(), # Keep owner/space textboxes
|
1010 |
+
gr.update(value=None, visible=False), # Hide iframe
|
1011 |
+
_download, gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), # Build/Edit/Runtime status (from initial clear state), Changeset, Confirm UI
|
1012 |
+
gr.update(value="*List of spaces will appear here.*"), gr.update(value=""), gr.update(value=""), gr.update(value=False) # List Spaces and Duplicate fields (from initial clear state)
|
1013 |
)
|
1014 |
return
|
1015 |
|
|
|
1038 |
|
1039 |
runtime_status_md = handle_refresh_space_status(hf_api_key_ui, owner_to_use, ui_space_name)
|
1040 |
|
1041 |
+
# Final yield after success
|
1042 |
yield (
|
1043 |
+
gr.update(value=_formatted), gr.update(value=_detected), gr.update(value=_status_val), # Markdown, preview, status
|
1044 |
+
file_browser_update, # File browser
|
1045 |
+
gr.update(), gr.update(), # Keep owner/space textboxes
|
1046 |
+
iframe_update, # Iframe
|
1047 |
+
_download, # Download button
|
1048 |
+
gr.update(), gr.update(), gr.update(value=runtime_status_md), # Build/Edit status (from initial clear state), Runtime status
|
1049 |
+
gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), # Changeset, Confirm UI (from initial clear state)
|
1050 |
+
gr.update(value="*List of spaces will appear here.*"), gr.update(value=""), gr.update(value=""), gr.update(value=False) # List Spaces and Duplicate fields (from initial clear state)
|
1051 |
)
|
1052 |
|
1053 |
def handle_build_space_button(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, space_sdk_ui, is_private_ui, formatted_markdown_content):
|
|
|
1058 |
_changeset_summary_clear = "*Manual build initiated, changes plan cleared.*"
|
1059 |
_confirm_ui_hidden = gr.update(visible=False)
|
1060 |
|
1061 |
+
# Outputs list: [build_status_display, space_iframe_display, file_browser_dropdown, owner_name_input, space_name_input, changeset_state, changeset_display, confirm_accordion, confirm_button, cancel_button, formatted_space_output_display, detected_files_preview, download_button, space_runtime_status_display] (14 items)
|
1062 |
yield (gr.update(value=_build_status), _iframe_html, _file_browser_update, gr.update(value=ui_owner_name_part), gr.update(value=ui_space_name_part),
|
1063 |
_changeset_clear, gr.update(value=_changeset_summary_clear), _confirm_ui_hidden, _confirm_ui_hidden, _confirm_ui_hidden,
|
1064 |
+
gr.update(), gr.update(), gr.update(), gr.update()) # Initial yield
|
|
|
1065 |
|
1066 |
if not ui_space_name_part or "/" in ui_space_name_part:
|
1067 |
_build_status = f"Build Error: Invalid Space Name '{ui_space_name_part}'."
|
|
|
1166 |
|
1167 |
def handle_load_file_for_editing(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, selected_file_path):
|
1168 |
if not selected_file_path:
|
1169 |
+
return "", "Select a file.", "", gr.update(language="text")
|
1170 |
|
1171 |
content, err = get_space_file_content(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, selected_file_path)
|
1172 |
if err:
|
1173 |
+
return "", f"Load Error: {err}", "", gr.update(language="text")
|
1174 |
|
1175 |
lang = _infer_lang_from_filename(selected_file_path)
|
1176 |
commit_msg = f"Update {selected_file_path}"
|
|
|
1213 |
|
1214 |
def handle_delete_file(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, file_to_delete_path):
|
1215 |
if not ui_owner_name_part or not ui_space_name_part:
|
1216 |
+
return "Delete Error: Cannot delete file. Please load a space first.", gr.update(), "", "", "text", gr.update(), gr.update(), gr.update()
|
1217 |
if not file_to_delete_path:
|
1218 |
+
return "Delete Error: No file selected to delete.", gr.update(), "", "", "text", gr.update(), gr.update(), gr.update()
|
1219 |
|
1220 |
status_msg = build_logic_delete_space_file(hf_api_key_ui, ui_space_name_part, ui_owner_name_part, file_to_delete_path)
|
1221 |
|
|
|
1229 |
parsed_code_blocks_state_cache = [b for b in parsed_code_blocks_state_cache if b["filename"] != file_to_delete_path]
|
1230 |
file_content_editor_update = gr.update(value="")
|
1231 |
commit_message_update = gr.update(value="")
|
1232 |
+
editor_lang_update = gr.update(language="text")
|
1233 |
file_list, _ = list_space_files_for_browsing(hf_api_key_ui, ui_space_name_part, ui_owner_name_part)
|
1234 |
file_browser_update = gr.update(choices=sorted(file_list or []), value=None)
|
1235 |
|
|
|
1327 |
return "Duplicate Error: Target Owner and Target Space Name are required.", gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
1328 |
if "/" in target_space_name:
|
1329 |
return "Duplicate Error: Target Space Name should not contain '/'. Use Target Owner field for the owner part.", gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
|
1330 |
+
|
1331 |
|
1332 |
source_repo_id = f"{source_owner}/{source_space_name}"
|
1333 |
target_repo_id = f"{target_owner}/{target_space_name}"
|
|
|
1349 |
|
1350 |
if err_list:
|
1351 |
reload_error = f"Error reloading file list after duplication: {err_list}"
|
1352 |
+
global parsed_code_blocks_state_cache
|
1353 |
parsed_code_blocks_state_cache = []
|
1354 |
_file_browser_update = gr.update(visible=False, choices=[], value=None)
|
1355 |
_iframe_html_update = gr.update(value=None, visible=False)
|
|
|
1361 |
is_binary = lang == "binary" or (err_get is not None)
|
1362 |
code = f"[Error loading content: {err_get}]" if err_get else (content or "")
|
1363 |
loaded_files.append({"filename": file_path, "code": code, "language": lang, "is_binary": is_binary, "is_structure_block": False})
|
1364 |
+
global parsed_code_blocks_state_cache
|
1365 |
parsed_code_blocks_state_cache = loaded_files
|
1366 |
|
1367 |
_file_browser_update = gr.update(visible=True, choices=sorted([f["filename"] for f in parsed_code_blocks_state_cache if not f.get("is_structure_block")] or []), value=None)
|