Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -22,8 +22,6 @@ def show_profile(profile: gr.OAuthProfile | None) -> str:
|
|
22 |
"""Displays the logged-in Hugging Face profile username."""
|
23 |
if profile is None:
|
24 |
return "*Not logged in.*"
|
25 |
-
# More robust check: ensure token is also present for "logged in" status for actions
|
26 |
-
# However, the LoginButton itself updates profile/token state. Let's rely on the State check.
|
27 |
return f"✅ Logged in as **{profile.username}**"
|
28 |
|
29 |
def list_private_models(
|
@@ -228,6 +226,16 @@ def add_bot_message(history: list[dict], bot_message: str) -> list[dict]:
|
|
228 |
def greet():
|
229 |
return [{"role": "assistant", "content": "Welcome! Please log in to Hugging Face and provide your Google AI Studio API key to start building Spaces. Once ready, type 'generate me a gradio app called myapp' or 'create' to begin."}]
|
230 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
|
232 |
# This is the main generator function for the workflow, triggered by the 'Send' button
|
233 |
# NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
|
@@ -303,25 +311,21 @@ def ai_workflow_chat(
|
|
303 |
# --- State Machine Logic based on the current 'state' variable ---
|
304 |
|
305 |
if state == STATE_IDLE:
|
306 |
-
# Check prerequisites before starting any workflow actions
|
307 |
-
#
|
308 |
-
# Note: Button interactivity should prevent reaching here if HF login or Gemini isn't ready
|
309 |
-
# But this check is a safeguard.
|
310 |
if not (hf_profile and hf_token):
|
311 |
-
history = add_bot_message(history, "Workflow paused: Hugging Face
|
312 |
-
# Yield updated history and current state, then exit for this click
|
313 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
314 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
315 |
-
return
|
316 |
|
317 |
if not (gemini_api_key and gemini_model):
|
318 |
-
# The button is *enabled* if HF is logged in
|
319 |
-
|
320 |
-
|
321 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
322 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
323 |
-
return
|
324 |
-
|
325 |
|
326 |
# Look for specific commands in the user's message
|
327 |
reset_match = "reset" in message.lower()
|
@@ -530,6 +534,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
|
|
530 |
reqs_list = ["gradio"] if space_sdk == "gradio" else ["streamlit"]
|
531 |
# Add essential libraries regardless of description keywords or grounding
|
532 |
essential_libs = ["google-generativeai", "huggingface_hub"]
|
|
|
533 |
# If we are here, key and model are available based on STATE_IDLE checks
|
534 |
reqs_list.extend(essential_libs)
|
535 |
|
@@ -632,7 +637,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
632 |
history = add_bot_message(history, "✅ `README.md` generated. Click 'Send' to upload.")
|
633 |
state = STATE_UPLOADING_README # Transition state
|
634 |
generated_code = readme_content # Store README content
|
635 |
-
# Yield updated state variables and history (pass UI outputs and states through)
|
636 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
637 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
638 |
# No return needed
|
@@ -659,7 +664,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
659 |
history = add_bot_message(history, "✅ Uploaded `README.md`. All files uploaded. Space is now building. Click 'Send' to check build logs.")
|
660 |
state = STATE_CHECKING_LOGS_BUILD # Transition to checking build logs
|
661 |
generated_code = None # Clear content after use
|
662 |
-
# Yield updated state variables and history (pass UI outputs and states through)
|
663 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
664 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
665 |
# No return needed
|
@@ -910,8 +915,6 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
910 |
status_text = gr.Textbox(label="Current State", value=STATE_IDLE, interactive=False)
|
911 |
repo_id_text = gr.Textbox(label="Current Space ID", value="None", interactive=False)
|
912 |
|
913 |
-
# Removed prereq_status markdown component
|
914 |
-
|
915 |
|
916 |
# Main content area column
|
917 |
with gr.Column(scale=3):
|
@@ -919,7 +922,9 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
919 |
chatbot = gr.Chatbot(type='messages', label="AI Workflow Chat")
|
920 |
user_input = gr.Textbox(placeholder="Type your message…", interactive=True)
|
921 |
# Define send_btn before its click handler
|
922 |
-
|
|
|
|
|
923 |
|
924 |
# Define iframe, build_txt, run_txt before they are used in send_btn.click inputs/outputs
|
925 |
# These are UI components, NOT State variables
|
@@ -930,51 +935,44 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
930 |
|
931 |
# --- Define Event Handlers and Chains AFTER all components are defined ---
|
932 |
|
933 |
-
#
|
934 |
-
|
935 |
-
def update_send_button_interactivity(profile, token, api_key, model_name):
|
936 |
-
is_logged_in = profile is not None and token is not None
|
937 |
-
is_gemini_ready = api_key is not None and model_name is not None
|
938 |
-
is_ready = is_logged_in and is_gemini_ready
|
939 |
-
print(f"update_send_button_interactivity - HF Ready: {is_logged_in}, Gemini Ready: {is_gemini_ready}, Button Ready: {is_ready}")
|
940 |
-
return gr.update(interactive=is_ready)
|
941 |
-
|
942 |
|
943 |
-
# Handle login button click: Update profile/token state ->
|
|
|
944 |
login_btn.click(
|
945 |
-
# The LoginButton outputs a tuple (OAuthProfile, OAuthToken) on success
|
946 |
lambda x: (x[0], x[1]),
|
947 |
inputs=[login_btn],
|
948 |
outputs=[hf_profile, hf_token] # Update HF State variables
|
949 |
-
).then(
|
950 |
-
|
951 |
-
|
952 |
-
inputs=
|
953 |
-
outputs=[send_btn] # Update button interactivity
|
954 |
)
|
955 |
|
956 |
-
# Handle Gemini Key Input change: Update key state -> Configure Gemini status ->
|
957 |
gemini_input.change(
|
958 |
lambda k: k, inputs=[gemini_input], outputs=[gemini_key] # Update gemini_key state
|
959 |
).then(
|
960 |
configure_gemini, inputs=[gemini_key, gemini_model], outputs=[gemini_status] # Update Gemini status
|
961 |
).then(
|
962 |
-
|
963 |
-
|
964 |
-
inputs=
|
965 |
-
outputs=[send_btn] # Update button interactivity
|
966 |
)
|
967 |
|
968 |
-
# Handle Gemini Model Selector change: Update model state -> Configure Gemini status ->
|
969 |
model_selector.change(
|
970 |
lambda m: m, inputs=[model_selector], outputs=[gemini_model] # Update gemini_model state
|
971 |
).then(
|
972 |
configure_gemini, inputs=[gemini_key, gemini_model], outputs=[gemini_status] # Update Gemini status
|
973 |
).then(
|
974 |
-
|
975 |
-
|
976 |
-
inputs=
|
977 |
-
outputs=[send_btn] # Update button interactivity
|
978 |
)
|
979 |
|
980 |
# Handle Grounding checkbox change: update grounding state
|
@@ -1040,11 +1038,11 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
1040 |
inputs=[gemini_key, gemini_model],
|
1041 |
outputs=[gemini_status] # Update Gemini status display
|
1042 |
).then(
|
1043 |
-
# Action 3:
|
1044 |
# This uses the *initial* values of hf_profile, hf_token, gemini_key, and gemini_model states
|
1045 |
-
|
1046 |
-
inputs=
|
1047 |
-
outputs=[send_btn] # Update button interactivity
|
1048 |
).then(
|
1049 |
# Action 4: Add the initial welcome message to the chatbot
|
1050 |
greet,
|
|
|
22 |
"""Displays the logged-in Hugging Face profile username."""
|
23 |
if profile is None:
|
24 |
return "*Not logged in.*"
|
|
|
|
|
25 |
return f"✅ Logged in as **{profile.username}**"
|
26 |
|
27 |
def list_private_models(
|
|
|
226 |
def greet():
|
227 |
return [{"role": "assistant", "content": "Welcome! Please log in to Hugging Face and provide your Google AI Studio API key to start building Spaces. Once ready, type 'generate me a gradio app called myapp' or 'create' to begin."}]
|
228 |
|
229 |
+
# Helper function to check if the send button should be interactive
|
230 |
+
# Returns a boolean: True if ready, False otherwise
|
231 |
+
def check_send_button_ready(profile: gr.OAuthProfile | None, token: gr.OAuthToken | None, api_key: str | None, model_name: str | None) -> bool:
|
232 |
+
"""Checks if HF login and Gemini configuration are complete."""
|
233 |
+
is_logged_in = profile is not None and token is not None
|
234 |
+
is_gemini_ready = api_key is not None and model_name is not None
|
235 |
+
is_ready = is_logged_in and is_gemini_ready
|
236 |
+
print(f"check_send_button_ready - HF Ready: {is_logged_in}, Gemini Ready: {is_gemini_ready}, Button Ready (boolean): {is_ready}")
|
237 |
+
return is_ready
|
238 |
+
|
239 |
|
240 |
# This is the main generator function for the workflow, triggered by the 'Send' button
|
241 |
# NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
|
|
|
311 |
# --- State Machine Logic based on the current 'state' variable ---
|
312 |
|
313 |
if state == STATE_IDLE:
|
314 |
+
# Check workflow prerequisites before starting any workflow actions
|
315 |
+
# The Send button should already be disabled if these aren't met, but double-check
|
|
|
|
|
316 |
if not (hf_profile and hf_token):
|
317 |
+
history = add_bot_message(history, "Workflow paused: Please log in to Hugging Face first.")
|
|
|
318 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
319 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
320 |
+
return
|
321 |
|
322 |
if not (gemini_api_key and gemini_model):
|
323 |
+
# The button is *enabled* if HF is logged in and Gemini shows configured,
|
324 |
+
# but we still need the key/model for the workflow itself.
|
325 |
+
history = add_bot_message(history, "Workflow cannot start: Please ensure your Gemini API key is entered and a model is selected.")
|
326 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
327 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
328 |
+
return
|
|
|
329 |
|
330 |
# Look for specific commands in the user's message
|
331 |
reset_match = "reset" in message.lower()
|
|
|
534 |
reqs_list = ["gradio"] if space_sdk == "gradio" else ["streamlit"]
|
535 |
# Add essential libraries regardless of description keywords or grounding
|
536 |
essential_libs = ["google-generativeai", "huggingface_hub"]
|
537 |
+
# Only add if Gemini is actually needed for the app (determined by description or if key is present)
|
538 |
# If we are here, key and model are available based on STATE_IDLE checks
|
539 |
reqs_list.extend(essential_libs)
|
540 |
|
|
|
637 |
history = add_bot_message(history, "✅ `README.md` generated. Click 'Send' to upload.")
|
638 |
state = STATE_UPLOADING_README # Transition state
|
639 |
generated_code = readme_content # Store README content
|
640 |
+
# Yield updated state variables and history (pass UI outputs and other states through)
|
641 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
642 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
643 |
# No return needed
|
|
|
664 |
history = add_bot_message(history, "✅ Uploaded `README.md`. All files uploaded. Space is now building. Click 'Send' to check build logs.")
|
665 |
state = STATE_CHECKING_LOGS_BUILD # Transition to checking build logs
|
666 |
generated_code = None # Clear content after use
|
667 |
+
# Yield updated state variables and history (pass UI outputs and other states through)
|
668 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
669 |
attempts, app_desc, repo_name, generated_code, use_grounding)
|
670 |
# No return needed
|
|
|
915 |
status_text = gr.Textbox(label="Current State", value=STATE_IDLE, interactive=False)
|
916 |
repo_id_text = gr.Textbox(label="Current Space ID", value="None", interactive=False)
|
917 |
|
|
|
|
|
918 |
|
919 |
# Main content area column
|
920 |
with gr.Column(scale=3):
|
|
|
922 |
chatbot = gr.Chatbot(type='messages', label="AI Workflow Chat")
|
923 |
user_input = gr.Textbox(placeholder="Type your message…", interactive=True)
|
924 |
# Define send_btn before its click handler
|
925 |
+
# Initial interactive state will be handled by the load event chain
|
926 |
+
send_btn = gr.Button("Send") # Starts disabled by default (interactive=False)
|
927 |
+
|
928 |
|
929 |
# Define iframe, build_txt, run_txt before they are used in send_btn.click inputs/outputs
|
930 |
# These are UI components, NOT State variables
|
|
|
935 |
|
936 |
# --- Define Event Handlers and Chains AFTER all components are defined ---
|
937 |
|
938 |
+
# Define the inputs used for checking prerequisites
|
939 |
+
send_button_interactive_binding_inputs = [hf_profile, hf_token, gemini_key, gemini_model]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
940 |
|
941 |
+
# Handle login button click: Update profile/token state -> Check prereqs and update button interactivity
|
942 |
+
# LoginButton outputs a tuple (OAuthProfile, OAuthToken) on success
|
943 |
login_btn.click(
|
|
|
944 |
lambda x: (x[0], x[1]),
|
945 |
inputs=[login_btn],
|
946 |
outputs=[hf_profile, hf_token] # Update HF State variables
|
947 |
+
).then( # Chain the next action after state is updated
|
948 |
+
# Call the boolean check function and bind its output to the button's interactive property
|
949 |
+
check_send_button_ready,
|
950 |
+
inputs=send_button_interactive_binding_inputs,
|
951 |
+
outputs=[send_btn.interactive] # Update button interactivity directly
|
952 |
)
|
953 |
|
954 |
+
# Handle Gemini Key Input change: Update key state -> Configure Gemini status -> Check prereqs and update button interactivity
|
955 |
gemini_input.change(
|
956 |
lambda k: k, inputs=[gemini_input], outputs=[gemini_key] # Update gemini_key state
|
957 |
).then(
|
958 |
configure_gemini, inputs=[gemini_key, gemini_model], outputs=[gemini_status] # Update Gemini status
|
959 |
).then(
|
960 |
+
# Call the boolean check function and bind its output to the button's interactive property
|
961 |
+
check_send_button_ready,
|
962 |
+
inputs=send_button_interactive_binding_inputs,
|
963 |
+
outputs=[send_btn.interactive] # Update button interactivity directly
|
964 |
)
|
965 |
|
966 |
+
# Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> Check prereqs and update button interactivity
|
967 |
model_selector.change(
|
968 |
lambda m: m, inputs=[model_selector], outputs=[gemini_model] # Update gemini_model state
|
969 |
).then(
|
970 |
configure_gemini, inputs=[gemini_key, gemini_model], outputs=[gemini_status] # Update Gemini status
|
971 |
).then(
|
972 |
+
# Call the boolean check function and bind its output to the button's interactive property
|
973 |
+
check_send_button_ready,
|
974 |
+
inputs=send_button_interactive_binding_inputs,
|
975 |
+
outputs=[send_btn.interactive] # Update button interactivity directly
|
976 |
)
|
977 |
|
978 |
# Handle Grounding checkbox change: update grounding state
|
|
|
1038 |
inputs=[gemini_key, gemini_model],
|
1039 |
outputs=[gemini_status] # Update Gemini status display
|
1040 |
).then(
|
1041 |
+
# Action 3: Check prereqs and update send button interactivity based on initial states
|
1042 |
# This uses the *initial* values of hf_profile, hf_token, gemini_key, and gemini_model states
|
1043 |
+
check_send_button_ready, # Use the simpler boolean helper
|
1044 |
+
inputs=send_button_interactive_binding_inputs,
|
1045 |
+
outputs=[send_btn.interactive] # Update button interactivity directly
|
1046 |
).then(
|
1047 |
# Action 4: Add the initial welcome message to the chatbot
|
1048 |
greet,
|