wuhp commited on
Commit
d1b242d
·
verified ·
1 Parent(s): 680f26f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -49
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
- # Use the passed-in state variable values for checks
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 login is required.")
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 # Exit the generator for this click
316
 
317
  if not (gemini_api_key and gemini_model):
318
- # The button is *enabled* if HF is logged in, but we still need Gemini for the workflow
319
- history = add_bot_message(history, "Workflow cannot start: Google AI Studio / Gemini configuration is required.")
320
- # Yield updated history and current state, then exit for this click
321
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
322
  attempts, app_desc, repo_name, generated_code, use_grounding)
323
- return # Exit the generator for this click
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
- send_btn = gr.Button("Send", interactive=False) # Starts disabled until prereqs are met
 
 
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
- # Helper function to update send button interactivity based on prereqs
934
- # Defined outside Block but used inside event handlers
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 -> Update send button interactivity
 
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
- update_send_button_interactivity,
951
- # Pass required state variables to determine interactivity
952
- inputs=[hf_profile, hf_token, gemini_key, gemini_model],
953
- outputs=[send_btn] # Update button interactivity
954
  )
955
 
956
- # Handle Gemini Key Input change: Update key state -> Configure Gemini status -> Update send button interactivity
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
- update_send_button_interactivity,
963
- # Pass required state variables to determine interactivity
964
- inputs=[hf_profile, hf_token, gemini_key, gemini_model],
965
- outputs=[send_btn] # Update button interactivity
966
  )
967
 
968
- # Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> Update send button interactivity
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
- update_send_button_interactivity,
975
- # Pass required state variables to determine interactivity
976
- inputs=[hf_profile, hf_token, gemini_key, gemini_model],
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: Update the send button interactivity based on initial states
1044
  # This uses the *initial* values of hf_profile, hf_token, gemini_key, and gemini_model states
1045
- update_send_button_interactivity, # Use the dedicated helper
1046
- inputs=[hf_profile, hf_token, gemini_key, gemini_model],
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,