wuhp commited on
Commit
49af09b
·
verified ·
1 Parent(s): 53265b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -52
app.py CHANGED
@@ -229,8 +229,11 @@ 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
  # Helper function to update send button interactivity based on prereqs
232
- # FIXED: Added *args, **kwargs back for debugging purposes to see what is passed
233
- def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None, *args, **kwargs) -> gr.update:
 
 
 
234
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
235
  # --- START ENHANCED DEBUGGING LOGS ---
236
  print("\n--- check_send_button_ready START ---")
@@ -240,9 +243,6 @@ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAu
240
  api_key_display = gemini_key[:5] if isinstance(gemini_key, str) and gemini_key else ('Empty String' if isinstance(gemini_key, str) and gemini_key == "" else 'None')
241
  print(f" Received gemini_key: Type={type(gemini_key)}, Value={api_key_display}")
242
  print(f" Received gemini_model: Type={type(gemini_model)}, Value={gemini_model}")
243
- # DEBUG PRINTS for unexpected args/kwargs
244
- print(f" Received *args: {args}")
245
- print(f" Received **kwargs: {kwargs}")
246
  # --- END ENHANCED DEBUGGING LOGS ---
247
 
248
  is_logged_in = hf_profile is not None and hf_token is not None
@@ -267,6 +267,7 @@ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAu
267
  # It MUST also yield/return ALL state variables in the same order they appear in the `outputs` list of the `.click()` event.
268
  # MODIFIED: Input parameter names align with renamed states for clarity
269
  # MODIFIED: Output tuple includes renamed gemini state variables
 
270
  def ai_workflow_chat(
271
  message: str,
272
  history: list[dict],
@@ -287,7 +288,7 @@ def ai_workflow_chat(
287
  repo_name_state: str | None,
288
  generated_code_state: str | None,
289
  use_grounding_state: bool, # Value from use_grounding_checkbox
290
- # Absorb potential extra args passed by Gradio event listeners (e.g. old value, event data)
291
  *args,
292
  **kwargs
293
  ) -> tuple[
@@ -925,7 +926,6 @@ Return **only** the python code block for app.py. Do not include any extra text,
925
  error_message = f"Workflow step failed unexpectedly ({state}): {e}. Click 'Send' to re-attempt this step or 'reset'."
926
  history = add_bot_message(history, error_message)
927
  print(f"Critical Error in state {state}: {e}") # Log the error for debugging purposes
928
- # Yield an error state and reset essential workflow variables on critical failure
929
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
930
  None, None, None, use_grounding,
931
  current_gemini_key, current_gemini_model) # Include use_grounding and Gemini states
@@ -962,6 +962,8 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
962
  gemini_api_key_state, # Use new state name
963
  gemini_model_state # Use new state name
964
  ]
 
 
965
 
966
 
967
  with gr.Row():
@@ -1034,55 +1036,75 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1034
 
1035
  # --- Define Event Handlers and Chains AFTER all components are defined ---
1036
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1037
 
1038
- # Handle login button click: Update profile/token state -> Check prereqs and update button interactivity
1039
- # LoginButton outputs a tuple (OAuthProfile, OAuthToken) on success
1040
  login_btn.click(
1041
  lambda x: (x[0], x[1]),
1042
  inputs=[login_btn],
1043
- outputs=[hf_profile, hf_token] # Update HF State variables
1044
- ).then( # Chain the next action after state is updated
1045
- # Call the update function and bind its output to the button component
1046
- check_send_button_ready,
1047
- inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1048
- outputs=[send_btn] # Update button interactivity using gr.update return value
1049
- )
1050
 
1051
- # Handle Gemini Key Input change: Update key state -> Configure Gemini status -> Check prereqs and update button interactivity
1052
- # This chain is crucial for the new key handling logic
1053
  gemini_input.change(
1054
  lambda k: k,
1055
  inputs=[gemini_input],
1056
- outputs=[gemini_api_key_state] # Update RENAMED gemini_api_key_state with textbox value
1057
  ).then(
1058
  # Use RENAMED state variables as inputs to configure_gemini
1059
  configure_gemini,
1060
  inputs=[gemini_api_key_state, gemini_model_state],
1061
  outputs=[gemini_status] # Update Gemini status based on new key
1062
- ).then(
1063
- # Call the update function and bind its output to the button component
1064
- check_send_button_ready,
1065
- inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1066
- outputs=[send_btn] # Update button interactivity using gr.update return value
1067
- )
1068
 
1069
- # Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> Check prereqs and update button interactivity
1070
- # This chain is crucial for the new key handling logic
1071
  model_selector.change(
1072
  lambda m: m,
1073
  inputs=[model_selector],
1074
- outputs=[gemini_model_state] # Update RENAMED gemini_model_state with selected model
1075
  ).then(
1076
  # Use RENAMED state variables as inputs to configure_gemini
1077
  configure_gemini,
1078
  inputs=[gemini_api_key_state, gemini_model_state],
1079
  outputs=[gemini_status] # Update Gemini status based on new model
1080
- ).then(
1081
- # Call the update function and bind its output to the button component
1082
- check_send_button_ready,
1083
- inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1084
- outputs=[send_btn] # Update button interactivity using gr.update return value
1085
- )
1086
 
1087
  # Handle Grounding checkbox change: update grounding state
1088
  use_grounding_checkbox.change(
@@ -1107,6 +1129,8 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1107
  # Outputs are updated by the values yielded from the generator
1108
  # MODIFIED: Inputs use renamed gemini state variables
1109
  # MODIFIED: Outputs include renamed gemini state variables
 
 
1110
  send_btn.click(
1111
  ai_workflow_chat, # The generator function to run
1112
  inputs=[
@@ -1140,29 +1164,19 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1140
  # --- Initial Load Event Chain (Defined INSIDE gr.Blocks, AFTER components and initial bindings) ---
1141
  # This chain runs once when the app loads
1142
  ai_builder_tab.load(
1143
- # Action 1: Show profile (loads cached login if available), does NOT need inputs
 
 
1144
  show_profile,
1145
  inputs=None,
1146
- outputs=login_status # Update login status markdown
1147
  ).then(
1148
- # Action 2: Configure Gemini using the initial state values.
1149
- # Since gemini_api_key_state state starts as "", this will initially show a "key is not set" message.
1150
- # Use RENAMED state variables as inputs
1151
  configure_gemini,
1152
- inputs=[gemini_api_key_state, gemini_model_state],
1153
  outputs=[gemini_status] # Update Gemini status display
1154
- ).then(
1155
- # Action 3: Check prereqs and update send button interactivity based on initial states.
1156
- # Since gemini_api_key_state state starts as "", button will initially be disabled.
1157
- check_send_button_ready,
1158
- inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1159
- outputs=[send_btn] # Update button interactivity using gr.update return value
1160
- ).then(
1161
- # Action 4: Add the initial welcome message to the chatbot
1162
- greet,
1163
- inputs=None,
1164
- outputs=chatbot
1165
- )
1166
 
1167
 
1168
  # The main workflow function and other helper functions are correctly defined OUTSIDE the gr.Blocks context
 
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
  # Helper function to update send button interactivity based on prereqs
232
+ # MODIFIED: Signature takes exactly 4 inputs, removed *args, **kwargs
233
+ # FIXED: Return type hint corrected to gr.update
234
+ # MODIFIED: Internal logic uses bool() check for simplicity
235
+ # REMOVED: problematic debug prints involving *args, **kwargs
236
+ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None) -> gr.update:
237
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
238
  # --- START ENHANCED DEBUGGING LOGS ---
239
  print("\n--- check_send_button_ready START ---")
 
243
  api_key_display = gemini_key[:5] if isinstance(gemini_key, str) and gemini_key else ('Empty String' if isinstance(gemini_key, str) and gemini_key == "" else 'None')
244
  print(f" Received gemini_key: Type={type(gemini_key)}, Value={api_key_display}")
245
  print(f" Received gemini_model: Type={type(gemini_model)}, Value={gemini_model}")
 
 
 
246
  # --- END ENHANCED DEBUGGING LOGS ---
247
 
248
  is_logged_in = hf_profile is not None and hf_token is not None
 
267
  # It MUST also yield/return ALL state variables in the same order they appear in the `outputs` list of the `.click()` event.
268
  # MODIFIED: Input parameter names align with renamed states for clarity
269
  # MODIFIED: Output tuple includes renamed gemini state variables
270
+ # REMOVED: *args, **kwargs from signature
271
  def ai_workflow_chat(
272
  message: str,
273
  history: list[dict],
 
288
  repo_name_state: str | None,
289
  generated_code_state: str | None,
290
  use_grounding_state: bool, # Value from use_grounding_checkbox
291
+ # Absorb potential extra args passed by Gradio event listeners (e.g. old value, event data) - RE-ADDED for safety in generator context
292
  *args,
293
  **kwargs
294
  ) -> tuple[
 
926
  error_message = f"Workflow step failed unexpectedly ({state}): {e}. Click 'Send' to re-attempt this step or 'reset'."
927
  history = add_bot_message(history, error_message)
928
  print(f"Critical Error in state {state}: {e}") # Log the error for debugging purposes
 
929
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
930
  None, None, None, use_grounding,
931
  current_gemini_key, current_gemini_model) # Include use_grounding and Gemini states
 
962
  gemini_api_key_state, # Use new state name
963
  gemini_model_state # Use new state name
964
  ]
965
+ # Define the output for updating the send button interactivity
966
+ send_button_update_output = [send_btn]
967
 
968
 
969
  with gr.Row():
 
1036
 
1037
  # --- Define Event Handlers and Chains AFTER all components are defined ---
1038
 
1039
+ # Define the inputs used for checking prerequisites using the RENAMED states
1040
+ # Moved definition *after* the state variables are defined
1041
+ send_button_interactive_binding_inputs = [
1042
+ hf_profile,
1043
+ hf_token,
1044
+ gemini_api_key_state, # Use new state name
1045
+ gemini_model_state # Use new state name
1046
+ ]
1047
+ # Define the output for updating the send button interactivity
1048
+ send_button_update_output = [send_btn]
1049
+
1050
+ # Trigger check_send_button_ready whenever any prerequisite state changes
1051
+ hf_profile.change(
1052
+ check_send_button_ready,
1053
+ inputs=send_button_interactive_binding_inputs,
1054
+ outputs=send_button_update_output,
1055
+ # run_as_event=True # Added this as a precaution if .change doesn't trigger correctly
1056
+ )
1057
+ hf_token.change(
1058
+ check_send_button_ready,
1059
+ inputs=send_button_interactive_binding_inputs,
1060
+ outputs=send_button_update_output,
1061
+ # run_as_event=True # Added this as a precaution
1062
+ )
1063
+ gemini_api_key_state.change(
1064
+ check_send_button_ready,
1065
+ inputs=send_button_interactive_binding_inputs,
1066
+ outputs=send_button_update_output,
1067
+ # run_as_event=True # Added this as a precaution
1068
+ )
1069
+ gemini_model_state.change(
1070
+ check_send_button_ready,
1071
+ inputs=send_button_interactive_binding_inputs,
1072
+ outputs=send_button_update_output,
1073
+ # run_as_event=True # Added this as a precaution
1074
+ )
1075
 
1076
+
1077
+ # Handle login button click: Update profile/token state -> *Now rely on .change handlers to trigger check_send_button_ready*
1078
  login_btn.click(
1079
  lambda x: (x[0], x[1]),
1080
  inputs=[login_btn],
1081
+ outputs=[hf_profile, hf_token] # Updating these states will trigger their .change handlers
1082
+ ) # Removed .then(check_send_button_ready, ...)
 
 
 
 
 
1083
 
1084
+ # Handle Gemini Key Input change: Update key state -> Configure Gemini status -> *Now rely on .change handlers to trigger check_send_button_ready*
 
1085
  gemini_input.change(
1086
  lambda k: k,
1087
  inputs=[gemini_input],
1088
+ outputs=[gemini_api_key_state] # Updating this state will trigger its .change handler
1089
  ).then(
1090
  # Use RENAMED state variables as inputs to configure_gemini
1091
  configure_gemini,
1092
  inputs=[gemini_api_key_state, gemini_model_state],
1093
  outputs=[gemini_status] # Update Gemini status based on new key
1094
+ ) # Removed .then(check_send_button_ready, ...)
 
 
 
 
 
1095
 
1096
+ # Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> *Now rely on .change handlers to trigger check_send_button_ready*
 
1097
  model_selector.change(
1098
  lambda m: m,
1099
  inputs=[model_selector],
1100
+ outputs=[gemini_model_state] # Updating this state will trigger its .change handler
1101
  ).then(
1102
  # Use RENAMED state variables as inputs to configure_gemini
1103
  configure_gemini,
1104
  inputs=[gemini_api_key_state, gemini_model_state],
1105
  outputs=[gemini_status] # Update Gemini status based on new model
1106
+ ) # Removed .then(check_send_button_ready, ...)
1107
+
 
 
 
 
1108
 
1109
  # Handle Grounding checkbox change: update grounding state
1110
  use_grounding_checkbox.change(
 
1129
  # Outputs are updated by the values yielded from the generator
1130
  # MODIFIED: Inputs use renamed gemini state variables
1131
  # MODIFIED: Outputs include renamed gemini state variables
1132
+ # Added back *args, **kwargs to the generator function signature and yield for robustness,
1133
+ # as the previous attempt suggested this might be necessary for state consistency within the generator's lifecycle.
1134
  send_btn.click(
1135
  ai_workflow_chat, # The generator function to run
1136
  inputs=[
 
1164
  # --- Initial Load Event Chain (Defined INSIDE gr.Blocks, AFTER components and initial bindings) ---
1165
  # This chain runs once when the app loads
1166
  ai_builder_tab.load(
1167
+ # Action 1: Show profile (loads cached login if available)
1168
+ # This calls show_profile, which updates the login_status UI.
1169
+ # The LoginButton component itself implicitly handles updating hf_profile/hf_token states on load if cached creds exist.
1170
  show_profile,
1171
  inputs=None,
1172
+ outputs=login_status # Updates UI
1173
  ).then(
1174
+ # Action 2: Configure Gemini using initial state (gemini_api_key_state is "", model_state is default)
 
 
1175
  configure_gemini,
1176
+ inputs=[gemini_api_key_state, gemini_model_state], # Use RENAMED state variables as inputs
1177
  outputs=[gemini_status] # Update Gemini status display
1178
+ ) # Removed .then(check_send_button_ready, ...). The state changes from LoginButton/Gemini init *should* trigger the .change handlers above.
1179
+ # The greet message will be added automatically by the chat UI initialization.
 
 
 
 
 
 
 
 
 
 
1180
 
1181
 
1182
  # The main workflow function and other helper functions are correctly defined OUTSIDE the gr.Blocks context