wuhp commited on
Commit
851efc4
·
verified ·
1 Parent(s): 53d7d01

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -101
app.py CHANGED
@@ -229,48 +229,51 @@ 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
- # MODIFIED to return gr.update
233
- # FIX: Added *args, **kwargs to accept any extra arguments passed by Gradio chaining
234
- def check_send_button_ready(profile: gr.OAuthProfile | None, token: gr.OAuthToken | None, api_key: str | None, model_name: str | None, *args, **kwargs) -> gr.update:
 
235
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
236
  # --- START ENHANCED DEBUGGING LOGS ---
237
  print("\n--- check_send_button_ready START ---")
238
- print(f" Received profile type: {type(profile)}, is None: {profile is None}")
239
- print(f" Received token type: {type(token)}, is None: {token is None}")
240
- # For api_key, print part of the key if not None for verification, be careful with full key
241
- # Also check for empty string for printing
242
- api_key_display = api_key[:5] if isinstance(api_key, str) and api_key else ('Empty String' if isinstance(api_key, str) and api_key == "" else 'None')
243
- print(f" Received api_key: Type={type(api_key)}, Value={api_key_display}")
244
- print(f" Received model_name: Type={type(model_name)}, Value={model_name}")
245
  # --- END ENHANCED DEBUGGING LOGS ---
246
 
247
- is_logged_in = profile is not None and token is not None
248
- # Gemini is ready if api_key is a non-empty string AND model_name is set
249
- is_gemini_ready = isinstance(api_key, str) and api_key != "" and model_name is not None
250
 
251
  # --- CONTINUED DEBUGGING LOGS ---
252
- print(f" HF check: {profile is not None} and {token is not None} = {is_logged_in}")
253
- print(f" Gemini check: {isinstance(api_key, str)} and {api_key != ''} and {model_name is not None} = {is_gemini_ready}")
254
- # --- END CONTINUED DEBUGGING LOGS ---
255
 
256
  is_ready = is_logged_in and is_gemini_ready
257
  print(f"check_send_button_ready - HF Ready: {is_logged_in}, Gemini Ready: {is_gemini_ready}, Button Ready (boolean): {is_ready}")
258
  print("--- check_send_button_ready END ---\n")
259
 
260
- return gr.update(interactive=is_ready)
 
261
 
262
 
263
  # This is the main generator function for the workflow, triggered by the 'Send' button
264
  # NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
265
  # It MUST also yield/return ALL state variables in the same order they appear in the `outputs` list of the `.click()` event.
 
 
266
  def ai_workflow_chat(
267
  message: str,
268
  history: list[dict],
269
  hf_profile: gr.OAuthProfile | None,
270
  hf_token: gr.OAuthToken | None,
271
- # Pass gemini_api_key and gemini_model as inputs - these come from the State variables
272
- gemini_api_key: str | None,
273
- gemini_model: str | None,
274
  repo_id_state: str | None,
275
  workflow_state: str,
276
  space_sdk: str,
@@ -298,8 +301,8 @@ def ai_workflow_chat(
298
  str | None, # 8: Updated repo name (for repo_name_state state)
299
  str | None, # 9: Updated generated code (for generated_code_state state)
300
  bool, # 10: Updated use_grounding_state (for use_grounding_state state)
301
- str | None, # 11: Explicitly yield gemini_api_key State
302
- str | None, # 12: Explicitly yield gemini_model State
303
  ]:
304
  """
305
  Generator function to handle the AI workflow state machine.
@@ -313,6 +316,10 @@ def ai_workflow_chat(
313
  repo_name = repo_name_state
314
  generated_code = generated_code_state
315
  use_grounding = use_grounding_state # Unpack grounding state
 
 
 
 
316
 
317
  # Keep copies of potentially updated UI elements passed as inputs to update them later
318
  # These are the *current values* of the UI components as of the button click
@@ -330,10 +337,10 @@ def ai_workflow_chat(
330
  # Yield immediately to update the chat UI with the user's message
331
  # This provides immediate feedback to the user while the AI processes
332
  # Ensure all state variables and UI outputs are yielded back in the correct order
333
- # Include gemini_api_key and gemini_model in the yield tuple
334
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
335
  attempts, app_desc, repo_name, generated_code, use_grounding,
336
- gemini_api_key, gemini_model) # Explicitly pass back current state values
337
 
338
  try:
339
  # --- State Machine Logic based on the current 'state' variable ---
@@ -344,15 +351,16 @@ def ai_workflow_chat(
344
  history = add_bot_message(history, "Workflow paused: Please log in to Hugging Face first.")
345
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
346
  attempts, app_desc, repo_name, generated_code, use_grounding,
347
- gemini_api_key, gemini_model) # Explicitly pass back current state values
348
  return # Stop workflow execution for this click
349
 
350
  # Check if API key is non-empty string and model is set
351
- if not (isinstance(gemini_api_key, str) and gemini_api_key != "" and gemini_model):
 
352
  history = add_bot_message(history, "Workflow cannot start: Please ensure your Gemini API key is entered and a model is selected.")
353
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
354
  attempts, app_desc, repo_name, generated_code, use_grounding,
355
- gemini_api_key, gemini_model) # Explicitly pass back current state values
356
  return # Stop workflow execution for this click
357
 
358
 
@@ -371,8 +379,8 @@ def ai_workflow_chat(
371
  # Also reset UI outputs to their initial state
372
  # gemini_key and gemini_model are passed back with their *current* (likely valid) state
373
  yield (history, None, STATE_IDLE, "<p>No Space created yet.</p>", "", "", 0,
374
- None, None, None, False,
375
- gemini_api_key, gemini_model) # Reset use_grounding to default False, other states to None/default
376
  # No return needed after yield in this generator pattern; execution for this click ends here.
377
 
378
  elif generate_match:
@@ -387,7 +395,7 @@ def ai_workflow_chat(
387
  # Yield updated history and state variables (pass UI outputs through)
388
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
389
  attempts, app_desc, repo_name, generated_code, use_grounding,
390
- gemini_api_key, gemini_model)
391
  # No return needed
392
 
393
  elif create_match:
@@ -399,7 +407,7 @@ def ai_workflow_chat(
399
  # Yield updated history and state variables (pass UI outputs through)
400
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
401
  attempts, app_desc, repo_name, generated_code, use_grounding,
402
- gemini_api_key, gemini_model)
403
  # No return needed
404
 
405
  elif "create" in message.lower() and not repo_id:
@@ -409,7 +417,7 @@ def ai_workflow_chat(
409
  # Yield updated history and state (pass UI outputs through)
410
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
411
  attempts, app_desc, repo_name, generated_code, use_grounding,
412
- gemini_api_key, gemini_model)
413
  # No return needed
414
 
415
  else:
@@ -418,7 +426,7 @@ def ai_workflow_chat(
418
  # Yield updated history and current state (pass UI outputs through)
419
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
420
  attempts, app_desc, repo_name, generated_code, use_grounding,
421
- gemini_api_key, gemini_model)
422
  # No return needed
423
 
424
 
@@ -432,7 +440,7 @@ def ai_workflow_chat(
432
  # Stay in AWAITING_REPO_NAME state and yield message (pass UI outputs through)
433
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
434
  attempts, app_desc, repo_name, generated_code, use_grounding,
435
- gemini_api_key, gemini_model)
436
  # No return needed
437
 
438
  else:
@@ -443,7 +451,7 @@ def ai_workflow_chat(
443
  # The next click will proceed from the STATE_CREATING_SPACE block.
444
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
445
  attempts, app_desc, repo_name, generated_code, use_grounding,
446
- gemini_api_key, gemini_model)
447
  # No return needed
448
 
449
  # Note: Each 'elif' block below represents a distinct step in the workflow triggered
@@ -456,7 +464,7 @@ def ai_workflow_chat(
456
  # Reset relevant states and UI outputs on critical error
457
  yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
458
  None, None, None, use_grounding,
459
- gemini_api_key, gemini_model) # Pass grounding state through
460
  # No return needed
461
 
462
  else:
@@ -470,7 +478,7 @@ def ai_workflow_chat(
470
  # Yield updated state variables and history, and the new iframe HTML
471
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
472
  attempts, app_desc, repo_name, generated_code, use_grounding,
473
- gemini_api_key, gemini_model) # Pass logs and grounding through
474
  # No return needed
475
 
476
  except Exception as e:
@@ -478,7 +486,7 @@ def ai_workflow_chat(
478
  # Yield error message and reset state on failure
479
  yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
480
  None, None, None, use_grounding,
481
- gemini_api_key, gemini_model) # Pass logs and grounding through
482
  # No return needed
483
 
484
 
@@ -499,11 +507,11 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
499
  # Yield to show message before the potentially time-consuming API call
500
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
501
  attempts, app_desc, repo_name, generated_code, use_grounding,
502
- gemini_api_key, gemini_model)
503
 
504
  # Perform the Gemini API call to generate code, optionally using grounding
505
- # Use the gemini_api_key and gemini_model inputs directly (which come from state)
506
- code = call_gemini(prompt, gemini_api_key, gemini_model, use_grounding=use_grounding)
507
  code = code.strip()
508
  # Clean up common markdown code block formatting if present
509
  if code.startswith("```python"):
@@ -522,7 +530,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
522
  # Yield updated state variables and history (pass UI outputs and other states through)
523
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
524
  attempts, app_desc, repo_name, generated_code, use_grounding,
525
- gemini_api_key, gemini_model)
526
  # No return needed
527
 
528
  except Exception as e:
@@ -530,7 +538,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
530
  # Yield error message and reset state on failure
531
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
532
  None, None, None, use_grounding,
533
- gemini_api_key, gemini_model)
534
  # No return needed
535
 
536
 
@@ -541,7 +549,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
541
  history = add_bot_message(history, "Internal error: No code to upload. Resetting.")
542
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
543
  None, None, None, use_grounding,
544
- gemini_api_key, gemini_model)
545
  # No return needed
546
 
547
  else:
@@ -549,7 +557,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
549
  # Yield to show message before the upload action (pass UI outputs and states through)
550
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
551
  attempts, app_desc, repo_name, generated_code, use_grounding,
552
- gemini_api_key, gemini_model)
553
 
554
  try:
555
  # Perform the file upload action
@@ -560,7 +568,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
560
  # Yield updated state variables and history (pass UI outputs and other states through)
561
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
562
  attempts, app_desc, repo_name, generated_code, use_grounding,
563
- gemini_api_key, gemini_model)
564
  # No return needed
565
 
566
  except Exception as e:
@@ -568,7 +576,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
568
  # Yield error message and reset state on failure
569
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
570
  None, None, None, use_grounding,
571
- gemini_api_key, gemini_model)
572
  # No return needed
573
 
574
 
@@ -577,7 +585,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
577
  # Yield to show message before generating requirements (pass UI outputs and states through)
578
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
579
  attempts, app_desc, repo_name, generated_code, use_grounding,
580
- gemini_api_key, gemini_model)
581
 
582
  # Logic to determine required packages based on SDK and keywords in the app description
583
  reqs_list = ["gradio"] if space_sdk == "gradio" else ["streamlit"]
@@ -620,7 +628,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
620
  # Yield updated state variables and history (pass UI outputs and other states through)
621
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
622
  attempts, app_desc, repo_name, generated_code, use_grounding,
623
- gemini_api_key, gemini_model)
624
  # No return needed
625
 
626
 
@@ -631,7 +639,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
631
  history = add_bot_message(history, "Internal error: No requirements content to upload. Resetting.")
632
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
633
  None, None, None, use_grounding,
634
- gemini_api_key, gemini_model)
635
  # No return needed
636
 
637
  else:
@@ -639,7 +647,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
639
  # Yield message before upload (pass UI outputs and states through)
640
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
641
  attempts, app_desc, repo_name, generated_code, use_grounding,
642
- gemini_api_key, gemini_model)
643
 
644
  try:
645
  # Perform requirements file upload
@@ -650,7 +658,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
650
  # Yield updated state variables and history (pass UI outputs and other states through)
651
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
652
  attempts, app_desc, repo_name, generated_code, use_grounding,
653
- gemini_api_key, gemini_model)
654
  # No return needed
655
 
656
  except Exception as e:
@@ -658,7 +666,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
658
  # Yield error message and reset state on failure
659
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
660
  None, None, None, use_grounding,
661
- gemini_api_key, gemini_model)
662
  # No return needed
663
 
664
  elif state == STATE_GENERATING_README:
@@ -666,7 +674,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
666
  # Yield message before generating README (pass UI outputs and states through)
667
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
668
  attempts, app_desc, repo_name, generated_code, use_grounding,
669
- gemini_api_key, gemini_model)
670
 
671
  # Generate simple README content with Space metadata header
672
  readme_title = repo_name if repo_name else "My Awesome Space"
@@ -695,7 +703,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
695
  # Yield updated state variables and history (pass UI outputs and other states through)
696
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
697
  attempts, app_desc, repo_name, generated_code, use_grounding,
698
- gemini_api_key, gemini_model)
699
  # No return needed
700
 
701
 
@@ -706,7 +714,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
706
  history = add_bot_message(history, "Internal error: No README content to upload. Resetting.")
707
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
708
  None, None, None, use_grounding,
709
- gemini_api_key, gemini_model)
710
  # No return needed
711
 
712
  else:
@@ -714,7 +722,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
714
  # Yield message before upload (pass UI outputs and states through)
715
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
716
  attempts, app_desc, repo_name, generated_code, use_grounding,
717
- gemini_api_key, gemini_model)
718
 
719
  try:
720
  # Perform README file upload
@@ -725,7 +733,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
725
  # Yield updated state variables and history (pass UI outputs and other states through)
726
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
727
  attempts, app_desc, repo_name, generated_code, use_grounding,
728
- gemini_api_key, gemini_model)
729
  # No return needed
730
 
731
  except Exception as e:
@@ -733,7 +741,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
733
  # Yield error message and reset state on failure
734
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
735
  None, None, None, use_grounding,
736
- gemini_api_key, gemini_model)
737
  # No return needed
738
 
739
  elif state == STATE_CHECKING_LOGS_BUILD:
@@ -741,7 +749,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
741
  # Yield message before fetching logs (which includes a delay) (pass UI outputs and states through)
742
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
743
  attempts, app_desc, repo_name, generated_code, use_grounding,
744
- gemini_api_key, gemini_model)
745
 
746
  # Fetch build logs from HF Space
747
  build_logs_text = get_build_logs_action(repo_id, hf_profile, hf_token)
@@ -754,7 +762,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
754
  # Yield updated state, logs, and variables
755
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
756
  attempts, app_desc, repo_name, generated_code, use_grounding,
757
- gemini_api_key, gemini_model)
758
  # No return needed
759
 
760
  else:
@@ -763,7 +771,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
763
  # Yield updated state, logs, and variables
764
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
765
  attempts, app_desc, repo_name, generated_code, use_grounding,
766
- gemini_api_key, gemini_model)
767
  # No return needed
768
 
769
 
@@ -772,7 +780,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
772
  # Yield message before fetching logs (includes a delay) (pass UI outputs and states through)
773
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
774
  attempts, app_desc, repo_name, generated_code, use_grounding,
775
- gemini_api_key, gemini_model)
776
 
777
  # Fetch container logs from HF Space
778
  container_logs_text = get_container_logs_action(repo_id, hf_profile, hf_token)
@@ -786,7 +794,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
786
  # Yield updated state, logs, attempts, and variables
787
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
788
  attempts, app_desc, repo_name, generated_code, use_grounding,
789
- gemini_api_key, gemini_model)
790
  # No return needed
791
 
792
  elif ("error" in updated_run.lower() or "exception" in updated_run.lower()) and attempts >= MAX_DEBUG_ATTEMPTS:
@@ -796,7 +804,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
796
  # Yield updated state, logs, attempts, and variables
797
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
798
  attempts, app_desc, repo_name, generated_code, use_grounding,
799
- gemini_api_key, gemini_model)
800
  # No return needed
801
 
802
  else:
@@ -806,7 +814,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
806
  # Yield updated state, logs, attempts, and variables
807
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
808
  attempts, app_desc, repo_name, generated_code, use_grounding,
809
- gemini_api_key, gemini_model)
810
  # No return needed
811
 
812
 
@@ -817,7 +825,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
817
  # Yield message before Gemini API call (pass UI outputs and states through)
818
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
819
  attempts, app_desc, repo_name, generated_code, use_grounding,
820
- gemini_api_key, gemini_model)
821
 
822
  # Construct prompt for Gemini including the container logs
823
  debug_prompt = f"""
@@ -834,8 +842,8 @@ Return **only** the python code block for app.py. Do not include any extra text,
834
  # Call Gemini to generate the corrected code, optionally using grounding
835
  # Note: Grounding might be less effective for debugging based *only* on logs,
836
  # but we include the option as requested.
837
- # Use the gemini_api_key and gemini_model inputs directly (which come from state)
838
- fix_code = call_gemini(debug_prompt, gemini_api_key, gemini_model, use_grounding=use_grounding)
839
  fix_code = fix_code.strip()
840
  # Clean up potential markdown formatting
841
  if fix_code.startswith("```python"):
@@ -854,7 +862,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
854
  # Yield updated state, code, and variables (pass UI outputs and states through)
855
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
856
  attempts, app_desc, repo_name, generated_code, use_grounding,
857
- gemini_api_key, gemini_model)
858
  # No return needed
859
 
860
  except Exception as e:
@@ -862,7 +870,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
862
  # Yield error message and reset state on failure
863
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
864
  None, None, None, use_grounding,
865
- gemini_api_key, gemini_model)
866
  # No return needed
867
 
868
  elif state == STATE_UPLOADING_FIXED_APP_PY:
@@ -872,7 +880,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
872
  history = add_bot_message(history, "Internal error: No fixed code available to upload. Resetting.")
873
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
874
  None, None, None, use_grounding,
875
- gemini_api_key, gemini_model)
876
  # No return needed
877
 
878
  else:
@@ -880,7 +888,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
880
  # Yield message before upload (pass UI outputs and states through)
881
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
882
  attempts, app_desc, repo_name, generated_code, use_grounding,
883
- gemini_api_key, gemini_model)
884
 
885
  try:
886
  # Perform the upload of the fixed app.py
@@ -891,7 +899,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
891
  # Yield updated state, code, and variables (pass UI outputs and states through)
892
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
893
  attempts, app_desc, repo_name, generated_code, use_grounding,
894
- gemini_api_key, gemini_model)
895
  # No return needed
896
 
897
  except Exception as e:
@@ -899,7 +907,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
899
  # Yield error message and reset state on failure
900
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
901
  None, None, None, use_grounding,
902
- gemini_api_key, gemini_model)
903
  # No return needed
904
 
905
  elif state == STATE_COMPLETE:
@@ -907,7 +915,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
907
  # Subsequent clicks just add user messages; we simply yield the current state.
908
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
909
  attempts, app_desc, repo_name, generated_code, use_grounding,
910
- gemini_api_key, gemini_model)
911
  # No return needed
912
 
913
 
@@ -919,7 +927,7 @@ Return **only** the python code block for app.py. Do not include any extra text,
919
  # Yield an error state and reset essential workflow variables on critical failure
920
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
921
  None, None, None, use_grounding,
922
- gemini_api_key, gemini_model) # Include use_grounding and Gemini states
923
  # No return needed after yield
924
 
925
 
@@ -930,9 +938,11 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
930
  # Define these first as they might be used in default values for components
931
  hf_profile = gr.State(None)
932
  hf_token = gr.State(None)
933
- # CHANGED: Initialize gemini_key state to empty string, not from env var
934
- gemini_key = gr.State("") # start with no key
935
- gemini_model = gr.State("gemini-1.5-flash") # Default selected model
 
 
936
  repo_id = gr.State(None) # Stores the ID of the created Space
937
  workflow = gr.State(STATE_IDLE) # Stores the current state of the AI workflow
938
  sdk_state = gr.State("gradio") # Stores the selected Space SDK (Gradio or Streamlit)
@@ -943,6 +953,16 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
943
  # New State variable for grounding checkbox
944
  use_grounding_state = gr.State(False)
945
 
 
 
 
 
 
 
 
 
 
 
946
  with gr.Row():
947
  # Sidebar column for inputs and status displays
948
  with gr.Column(scale=1, min_width=300):
@@ -1013,8 +1033,6 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1013
 
1014
  # --- Define Event Handlers and Chains AFTER all components are defined ---
1015
 
1016
- # Define the inputs used for checking prerequisites
1017
- send_button_interactive_binding_inputs = [hf_profile, hf_token, gemini_key, gemini_model]
1018
 
1019
  # Handle login button click: Update profile/token state -> Check prereqs and update button interactivity
1020
  # LoginButton outputs a tuple (OAuthProfile, OAuthToken) on success
@@ -1025,34 +1043,44 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1025
  ).then( # Chain the next action after state is updated
1026
  # Call the update function and bind its output to the button component
1027
  check_send_button_ready,
1028
- inputs=send_button_interactive_binding_inputs,
1029
- outputs=[send_btn] # Update button interactivity using gr.update return value
1030
  )
1031
 
1032
  # Handle Gemini Key Input change: Update key state -> Configure Gemini status -> Check prereqs and update button interactivity
1033
  # This chain is crucial for the new key handling logic
1034
  gemini_input.change(
1035
- lambda k: k, inputs=[gemini_input], outputs=[gemini_key] # Update gemini_key state with textbox value
 
 
1036
  ).then(
1037
- configure_gemini, inputs=[gemini_key, gemini_model], outputs=[gemini_status] # Update Gemini status based on new key
 
 
 
1038
  ).then(
1039
  # Call the update function and bind its output to the button component
1040
  check_send_button_ready,
1041
- inputs=send_button_interactive_binding_inputs,
1042
- outputs=[send_btn] # Update button interactivity using gr.update return value
1043
  )
1044
 
1045
  # Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> Check prereqs and update button interactivity
1046
  # This chain is crucial for the new key handling logic
1047
  model_selector.change(
1048
- lambda m: m, inputs=[model_selector], outputs=[gemini_model] # Update gemini_model state with selected model
 
 
1049
  ).then(
1050
- configure_gemini, inputs=[gemini_key, gemini_model], outputs=[gemini_status] # Update Gemini status based on new model
 
 
 
1051
  ).then(
1052
  # Call the update function and bind its output to the button component
1053
  check_send_button_ready,
1054
- inputs=send_button_interactive_binding_inputs,
1055
- outputs=[send_btn] # Update button interactivity using gr.update return value
1056
  )
1057
 
1058
  # Handle Grounding checkbox change: update grounding state
@@ -1076,13 +1104,15 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1076
  # This .click() event triggers the ai_workflow_chat generator function
1077
  # Inputs are read from UI components AND State variables
1078
  # Outputs are updated by the values yielded from the generator
 
 
1079
  send_btn.click(
1080
  ai_workflow_chat, # The generator function to run
1081
  inputs=[
1082
  user_input, chatbot, # UI component inputs (message, current chat history)
1083
  hf_profile, hf_token, # HF State variables
1084
- # Pass gemini_key and gemini_model as inputs (their state is read here)
1085
- gemini_key, gemini_model,
1086
  repo_id, workflow, sdk_state, # Workflow State variables
1087
  # UI component inputs whose *current values* are needed by the generator
1088
  iframe, run_txt, build_txt, # UI component inputs (current values)
@@ -1095,8 +1125,8 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1095
  iframe, run_txt, build_txt, # Update UI component outputs
1096
  debug_attempts, app_description, repo_name_state, generated_code_state, # Update other State variables
1097
  use_grounding_state, # Update the grounding state output
1098
- # ADDED BACK: gemini_key, gemini_model to outputs to ensure state consistency
1099
- gemini_key, gemini_model
1100
  ]
1101
  ).success( # Chain a .success() event to run *after* the .click() handler completes without error
1102
  # Clear the user input textbox after the message is sent and processed
@@ -1115,16 +1145,17 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1115
  outputs=login_status # Update login status markdown
1116
  ).then(
1117
  # Action 2: Configure Gemini using the initial state values.
1118
- # Since gemini_key state starts as "", this will initially show a "key is not set" message.
 
1119
  configure_gemini,
1120
- inputs=[gemini_key, gemini_model],
1121
  outputs=[gemini_status] # Update Gemini status display
1122
  ).then(
1123
  # Action 3: Check prereqs and update send button interactivity based on initial states.
1124
- # Since gemini_key state starts as "", button will initially be disabled.
1125
  check_send_button_ready,
1126
- inputs=send_button_interactive_binding_inputs,
1127
- outputs=[send_btn] # Update button interactivity using gr.update return value
1128
  ).then(
1129
  # Action 4: Add the initial welcome message to the chatbot
1130
  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
+ # MODIFIED: Signature takes exactly 4 inputs, removed *args, **kwargs
233
+ # MODIFIED: Return type hint changed to gr.Button.update
234
+ # MODIFIED: Internal logic uses bool() check for simplicity
235
+ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None) -> gr.Button.update:
236
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
237
  # --- START ENHANCED DEBUGGING LOGS ---
238
  print("\n--- check_send_button_ready START ---")
239
+ print(f" Received hf_profile: Type={type(hf_profile)}, Value={'present' if hf_profile else 'None'}")
240
+ print(f" Received hf_token: Type={type(hf_token)}, Value={'present' if hf_token else 'None'}")
241
+ # For api_key, print part of the key if not None/empty for verification
242
+ 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')
243
+ print(f" Received gemini_key: Type={type(gemini_key)}, Value={api_key_display}")
244
+ print(f" Received gemini_model: Type={type(gemini_model)}, Value={gemini_model}")
 
245
  # --- END ENHANCED DEBUGGING LOGS ---
246
 
247
+ is_logged_in = hf_profile is not None and hf_token is not None
248
+ # Use bool() check for simplicity - handles None and "" correctly
249
+ is_gemini_ready = bool(gemini_key) and bool(gemini_model)
250
 
251
  # --- CONTINUED DEBUGGING LOGS ---
252
+ print(f" HF check: ({hf_profile is not None} and {hf_token is not None}) = {is_logged_in}")
253
+ print(f" Gemini check: ({bool(gemini_key)} and {bool(gemini_model)}) = {is_gemini_ready}")
254
+ print("--- END CONTINUED DEBUGGING LOGS ---")
255
 
256
  is_ready = is_logged_in and is_gemini_ready
257
  print(f"check_send_button_ready - HF Ready: {is_logged_in}, Gemini Ready: {is_gemini_ready}, Button Ready (boolean): {is_ready}")
258
  print("--- check_send_button_ready END ---\n")
259
 
260
+ # Use gr.Button.update for clearer intent, although gr.update works
261
+ return gr.Button.update(interactive=is_ready)
262
 
263
 
264
  # This is the main generator function for the workflow, triggered by the 'Send' button
265
  # NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
266
  # It MUST also yield/return ALL state variables in the same order they appear in the `outputs` list of the `.click()` event.
267
+ # MODIFIED: Input parameter names align with renamed states for clarity
268
+ # MODIFIED: Output tuple includes renamed gemini state variables
269
  def ai_workflow_chat(
270
  message: str,
271
  history: list[dict],
272
  hf_profile: gr.OAuthProfile | None,
273
  hf_token: gr.OAuthToken | None,
274
+ # Input parameters corresponding to the State variables read by .click
275
+ gemini_api_key_state: str | None,
276
+ gemini_model_state: str | None,
277
  repo_id_state: str | None,
278
  workflow_state: str,
279
  space_sdk: str,
 
301
  str | None, # 8: Updated repo name (for repo_name_state state)
302
  str | None, # 9: Updated generated code (for generated_code_state state)
303
  bool, # 10: Updated use_grounding_state (for use_grounding_state state)
304
+ str | None, # 11: Explicitly yield gemini_api_key_state
305
+ str | None, # 12: Explicitly yield gemini_model_state
306
  ]:
307
  """
308
  Generator function to handle the AI workflow state machine.
 
316
  repo_name = repo_name_state
317
  generated_code = generated_code_state
318
  use_grounding = use_grounding_state # Unpack grounding state
319
+ # Use the input parameters for Gemini key/model directly in the generator
320
+ current_gemini_key = gemini_api_key_state
321
+ current_gemini_model = gemini_model_state
322
+
323
 
324
  # Keep copies of potentially updated UI elements passed as inputs to update them later
325
  # These are the *current values* of the UI components as of the button click
 
337
  # Yield immediately to update the chat UI with the user's message
338
  # This provides immediate feedback to the user while the AI processes
339
  # Ensure all state variables and UI outputs are yielded back in the correct order
340
+ # Include gemini_api_key_state and gemini_model_state in the yield tuple
341
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
342
  attempts, app_desc, repo_name, generated_code, use_grounding,
343
+ current_gemini_key, current_gemini_model) # Explicitly pass back current state values
344
 
345
  try:
346
  # --- State Machine Logic based on the current 'state' variable ---
 
351
  history = add_bot_message(history, "Workflow paused: Please log in to Hugging Face first.")
352
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
353
  attempts, app_desc, repo_name, generated_code, use_grounding,
354
+ current_gemini_key, current_gemini_model) # Explicitly pass back current state values
355
  return # Stop workflow execution for this click
356
 
357
  # Check if API key is non-empty string and model is set
358
+ # Use the local variables derived from state inputs
359
+ if not (isinstance(current_gemini_key, str) and current_gemini_key != "" and current_gemini_model):
360
  history = add_bot_message(history, "Workflow cannot start: Please ensure your Gemini API key is entered and a model is selected.")
361
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
362
  attempts, app_desc, repo_name, generated_code, use_grounding,
363
+ current_gemini_key, current_gemini_model) # Explicitly pass back current state values
364
  return # Stop workflow execution for this click
365
 
366
 
 
379
  # Also reset UI outputs to their initial state
380
  # gemini_key and gemini_model are passed back with their *current* (likely valid) state
381
  yield (history, None, STATE_IDLE, "<p>No Space created yet.</p>", "", "", 0,
382
+ None, None, None, False, # Reset use_grounding to default False, other states to None/default
383
+ current_gemini_key, current_gemini_model) # Explicitly pass back current state values
384
  # No return needed after yield in this generator pattern; execution for this click ends here.
385
 
386
  elif generate_match:
 
395
  # Yield updated history and state variables (pass UI outputs through)
396
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
397
  attempts, app_desc, repo_name, generated_code, use_grounding,
398
+ current_gemini_key, current_gemini_model)
399
  # No return needed
400
 
401
  elif create_match:
 
407
  # Yield updated history and state variables (pass UI outputs through)
408
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
409
  attempts, app_desc, repo_name, generated_code, use_grounding,
410
+ current_gemini_key, current_gemini_model)
411
  # No return needed
412
 
413
  elif "create" in message.lower() and not repo_id:
 
417
  # Yield updated history and state (pass UI outputs through)
418
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
419
  attempts, app_desc, repo_name, generated_code, use_grounding,
420
+ current_gemini_key, current_gemini_model)
421
  # No return needed
422
 
423
  else:
 
426
  # Yield updated history and current state (pass UI outputs through)
427
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
428
  attempts, app_desc, repo_name, generated_code, use_grounding,
429
+ current_gemini_key, current_gemini_model)
430
  # No return needed
431
 
432
 
 
440
  # Stay in AWAITING_REPO_NAME state and yield message (pass UI outputs through)
441
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
442
  attempts, app_desc, repo_name, generated_code, use_grounding,
443
+ current_gemini_key, current_gemini_model)
444
  # No return needed
445
 
446
  else:
 
451
  # The next click will proceed from the STATE_CREATING_SPACE block.
452
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
453
  attempts, app_desc, repo_name, generated_code, use_grounding,
454
+ current_gemini_key, current_gemini_model)
455
  # No return needed
456
 
457
  # Note: Each 'elif' block below represents a distinct step in the workflow triggered
 
464
  # Reset relevant states and UI outputs on critical error
465
  yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
466
  None, None, None, use_grounding,
467
+ current_gemini_key, current_gemini_model) # Pass grounding state through
468
  # No return needed
469
 
470
  else:
 
478
  # Yield updated state variables and history, and the new iframe HTML
479
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
480
  attempts, app_desc, repo_name, generated_code, use_grounding,
481
+ current_gemini_key, current_gemini_model) # Pass logs and grounding through
482
  # No return needed
483
 
484
  except Exception as e:
 
486
  # Yield error message and reset state on failure
487
  yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
488
  None, None, None, use_grounding,
489
+ current_gemini_key, current_gemini_model) # Pass logs and grounding through
490
  # No return needed
491
 
492
 
 
507
  # Yield to show message before the potentially time-consuming API call
508
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
509
  attempts, app_desc, repo_name, generated_code, use_grounding,
510
+ current_gemini_key, current_gemini_model)
511
 
512
  # Perform the Gemini API call to generate code, optionally using grounding
513
+ # Use the current_gemini_key and current_gemini_model derived from state inputs
514
+ code = call_gemini(prompt, current_gemini_key, current_gemini_model, use_grounding=use_grounding)
515
  code = code.strip()
516
  # Clean up common markdown code block formatting if present
517
  if code.startswith("```python"):
 
530
  # Yield updated state variables and history (pass UI outputs and other states through)
531
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
532
  attempts, app_desc, repo_name, generated_code, use_grounding,
533
+ current_gemini_key, current_gemini_model)
534
  # No return needed
535
 
536
  except Exception as e:
 
538
  # Yield error message and reset state on failure
539
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
540
  None, None, None, use_grounding,
541
+ current_gemini_key, current_gemini_model)
542
  # No return needed
543
 
544
 
 
549
  history = add_bot_message(history, "Internal error: No code to upload. Resetting.")
550
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
551
  None, None, None, use_grounding,
552
+ current_gemini_key, current_gemini_model)
553
  # No return needed
554
 
555
  else:
 
557
  # Yield to show message before the upload action (pass UI outputs and states through)
558
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
559
  attempts, app_desc, repo_name, generated_code, use_grounding,
560
+ current_gemini_key, current_gemini_model)
561
 
562
  try:
563
  # Perform the file upload action
 
568
  # Yield updated state variables and history (pass UI outputs and other states through)
569
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
570
  attempts, app_desc, repo_name, generated_code, use_grounding,
571
+ current_gemini_key, current_gemini_model)
572
  # No return needed
573
 
574
  except Exception as e:
 
576
  # Yield error message and reset state on failure
577
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
578
  None, None, None, use_grounding,
579
+ current_gemini_key, current_gemini_model)
580
  # No return needed
581
 
582
 
 
585
  # Yield to show message before generating requirements (pass UI outputs and states through)
586
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
587
  attempts, app_desc, repo_name, generated_code, use_grounding,
588
+ current_gemini_key, current_gemini_model)
589
 
590
  # Logic to determine required packages based on SDK and keywords in the app description
591
  reqs_list = ["gradio"] if space_sdk == "gradio" else ["streamlit"]
 
628
  # Yield updated state variables and history (pass UI outputs and other states through)
629
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
630
  attempts, app_desc, repo_name, generated_code, use_grounding,
631
+ current_gemini_key, current_gemini_model)
632
  # No return needed
633
 
634
 
 
639
  history = add_bot_message(history, "Internal error: No requirements content to upload. Resetting.")
640
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
641
  None, None, None, use_grounding,
642
+ current_gemini_key, current_gemini_model)
643
  # No return needed
644
 
645
  else:
 
647
  # Yield message before upload (pass UI outputs and states through)
648
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
649
  attempts, app_desc, repo_name, generated_code, use_grounding,
650
+ current_gemini_key, current_gemini_model)
651
 
652
  try:
653
  # Perform requirements file upload
 
658
  # Yield updated state variables and history (pass UI outputs and other states through)
659
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
660
  attempts, app_desc, repo_name, generated_code, use_grounding,
661
+ current_gemini_key, current_gemini_model)
662
  # No return needed
663
 
664
  except Exception as e:
 
666
  # Yield error message and reset state on failure
667
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
668
  None, None, None, use_grounding,
669
+ current_gemini_key, current_gemini_model)
670
  # No return needed
671
 
672
  elif state == STATE_GENERATING_README:
 
674
  # Yield message before generating README (pass UI outputs and states through)
675
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
676
  attempts, app_desc, repo_name, generated_code, use_grounding,
677
+ current_gemini_key, current_gemini_model)
678
 
679
  # Generate simple README content with Space metadata header
680
  readme_title = repo_name if repo_name else "My Awesome Space"
 
703
  # Yield updated state variables and history (pass UI outputs and other states through)
704
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
705
  attempts, app_desc, repo_name, generated_code, use_grounding,
706
+ current_gemini_key, current_gemini_model)
707
  # No return needed
708
 
709
 
 
714
  history = add_bot_message(history, "Internal error: No README content to upload. Resetting.")
715
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
716
  None, None, None, use_grounding,
717
+ current_gemini_key, current_gemini_model)
718
  # No return needed
719
 
720
  else:
 
722
  # Yield message before upload (pass UI outputs and states through)
723
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
724
  attempts, app_desc, repo_name, generated_code, use_grounding,
725
+ current_gemini_key, current_gemini_model)
726
 
727
  try:
728
  # Perform README file upload
 
733
  # Yield updated state variables and history (pass UI outputs and other states through)
734
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
735
  attempts, app_desc, repo_name, generated_code, use_grounding,
736
+ current_gemini_key, current_gemini_model)
737
  # No return needed
738
 
739
  except Exception as e:
 
741
  # Yield error message and reset state on failure
742
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
743
  None, None, None, use_grounding,
744
+ current_gemini_key, current_gemini_model)
745
  # No return needed
746
 
747
  elif state == STATE_CHECKING_LOGS_BUILD:
 
749
  # Yield message before fetching logs (which includes a delay) (pass UI outputs and states through)
750
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
751
  attempts, app_desc, repo_name, generated_code, use_grounding,
752
+ current_gemini_key, current_gemini_model)
753
 
754
  # Fetch build logs from HF Space
755
  build_logs_text = get_build_logs_action(repo_id, hf_profile, hf_token)
 
762
  # Yield updated state, logs, and variables
763
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
764
  attempts, app_desc, repo_name, generated_code, use_grounding,
765
+ current_gemini_key, current_gemini_model)
766
  # No return needed
767
 
768
  else:
 
771
  # Yield updated state, logs, and variables
772
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
773
  attempts, app_desc, repo_name, generated_code, use_grounding,
774
+ current_gemini_key, current_gemini_model)
775
  # No return needed
776
 
777
 
 
780
  # Yield message before fetching logs (includes a delay) (pass UI outputs and states through)
781
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
782
  attempts, app_desc, repo_name, generated_code, use_grounding,
783
+ current_gemini_key, current_gemini_model)
784
 
785
  # Fetch container logs from HF Space
786
  container_logs_text = get_container_logs_action(repo_id, hf_profile, hf_token)
 
794
  # Yield updated state, logs, attempts, and variables
795
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
796
  attempts, app_desc, repo_name, generated_code, use_grounding,
797
+ current_gemini_key, current_gemini_model)
798
  # No return needed
799
 
800
  elif ("error" in updated_run.lower() or "exception" in updated_run.lower()) and attempts >= MAX_DEBUG_ATTEMPTS:
 
804
  # Yield updated state, logs, attempts, and variables
805
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
806
  attempts, app_desc, repo_name, generated_code, use_grounding,
807
+ current_gemini_key, current_gemini_model)
808
  # No return needed
809
 
810
  else:
 
814
  # Yield updated state, logs, attempts, and variables
815
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
816
  attempts, app_desc, repo_name, generated_code, use_grounding,
817
+ current_gemini_key, current_gemini_model)
818
  # No return needed
819
 
820
 
 
825
  # Yield message before Gemini API call (pass UI outputs and states through)
826
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
827
  attempts, app_desc, repo_name, generated_code, use_grounding,
828
+ current_gemini_key, current_gemini_model)
829
 
830
  # Construct prompt for Gemini including the container logs
831
  debug_prompt = f"""
 
842
  # Call Gemini to generate the corrected code, optionally using grounding
843
  # Note: Grounding might be less effective for debugging based *only* on logs,
844
  # but we include the option as requested.
845
+ # Use the current_gemini_key and current_gemini_model derived from state inputs
846
+ fix_code = call_gemini(debug_prompt, current_gemini_key, current_gemini_model, use_grounding=use_grounding)
847
  fix_code = fix_code.strip()
848
  # Clean up potential markdown formatting
849
  if fix_code.startswith("```python"):
 
862
  # Yield updated state, code, and variables (pass UI outputs and states through)
863
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
864
  attempts, app_desc, repo_name, generated_code, use_grounding,
865
+ current_gemini_key, current_gemini_model)
866
  # No return needed
867
 
868
  except Exception as e:
 
870
  # Yield error message and reset state on failure
871
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
872
  None, None, None, use_grounding,
873
+ current_gemini_key, current_gemini_model)
874
  # No return needed
875
 
876
  elif state == STATE_UPLOADING_FIXED_APP_PY:
 
880
  history = add_bot_message(history, "Internal error: No fixed code available to upload. Resetting.")
881
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
882
  None, None, None, use_grounding,
883
+ current_gemini_key, current_gemini_model)
884
  # No return needed
885
 
886
  else:
 
888
  # Yield message before upload (pass UI outputs and states through)
889
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
890
  attempts, app_desc, repo_name, generated_code, use_grounding,
891
+ current_gemini_key, current_gemini_model)
892
 
893
  try:
894
  # Perform the upload of the fixed app.py
 
899
  # Yield updated state, code, and variables (pass UI outputs and states through)
900
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
901
  attempts, app_desc, repo_name, generated_code, use_grounding,
902
+ current_gemini_key, current_gemini_model)
903
  # No return needed
904
 
905
  except Exception as e:
 
907
  # Yield error message and reset state on failure
908
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
909
  None, None, None, use_grounding,
910
+ current_gemini_key, current_gemini_model)
911
  # No return needed
912
 
913
  elif state == STATE_COMPLETE:
 
915
  # Subsequent clicks just add user messages; we simply yield the current state.
916
  yield (history, repo_id, state, updated_preview, updated_run, updated_build,
917
  attempts, app_desc, repo_name, generated_code, use_grounding,
918
+ current_gemini_key, current_gemini_model)
919
  # No return needed
920
 
921
 
 
927
  # Yield an error state and reset essential workflow variables on critical failure
928
  yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
929
  None, None, None, use_grounding,
930
+ current_gemini_key, current_gemini_model) # Include use_grounding and Gemini states
931
  # No return needed after yield
932
 
933
 
 
938
  # Define these first as they might be used in default values for components
939
  hf_profile = gr.State(None)
940
  hf_token = gr.State(None)
941
+ # RENAMED: Initialize gemini_api_key_state to empty string
942
+ gemini_api_key_state = gr.State("") # start with no key
943
+ # RENAMED: Initialize gemini_model_state
944
+ gemini_model_state = gr.State("gemini-1.5-flash") # Default selected model
945
+
946
  repo_id = gr.State(None) # Stores the ID of the created Space
947
  workflow = gr.State(STATE_IDLE) # Stores the current state of the AI workflow
948
  sdk_state = gr.State("gradio") # Stores the selected Space SDK (Gradio or Streamlit)
 
953
  # New State variable for grounding checkbox
954
  use_grounding_state = gr.State(False)
955
 
956
+ # Define the inputs used for checking prerequisites using the RENAMED states
957
+ # Moved definition *after* the state variables are defined
958
+ send_button_interactive_binding_inputs = [
959
+ hf_profile,
960
+ hf_token,
961
+ gemini_api_key_state, # Use new state name
962
+ gemini_model_state # Use new state name
963
+ ]
964
+
965
+
966
  with gr.Row():
967
  # Sidebar column for inputs and status displays
968
  with gr.Column(scale=1, min_width=300):
 
1033
 
1034
  # --- Define Event Handlers and Chains AFTER all components are defined ---
1035
 
 
 
1036
 
1037
  # Handle login button click: Update profile/token state -> Check prereqs and update button interactivity
1038
  # LoginButton outputs a tuple (OAuthProfile, OAuthToken) on success
 
1043
  ).then( # Chain the next action after state is updated
1044
  # Call the update function and bind its output to the button component
1045
  check_send_button_ready,
1046
+ inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1047
+ outputs=[send_btn] # Update button interactivity using gr.Button.update return value
1048
  )
1049
 
1050
  # Handle Gemini Key Input change: Update key state -> Configure Gemini status -> Check prereqs and update button interactivity
1051
  # This chain is crucial for the new key handling logic
1052
  gemini_input.change(
1053
+ lambda k: k,
1054
+ inputs=[gemini_input],
1055
+ outputs=[gemini_api_key_state] # Update RENAMED gemini_api_key_state with textbox value
1056
  ).then(
1057
+ # Use RENAMED state variables as inputs to configure_gemini
1058
+ configure_gemini,
1059
+ inputs=[gemini_api_key_state, gemini_model_state],
1060
+ outputs=[gemini_status] # Update Gemini status based on new key
1061
  ).then(
1062
  # Call the update function and bind its output to the button component
1063
  check_send_button_ready,
1064
+ inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1065
+ outputs=[send_btn] # Update button interactivity using gr.Button.update return value
1066
  )
1067
 
1068
  # Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> Check prereqs and update button interactivity
1069
  # This chain is crucial for the new key handling logic
1070
  model_selector.change(
1071
+ lambda m: m,
1072
+ inputs=[model_selector],
1073
+ outputs=[gemini_model_state] # Update RENAMED gemini_model_state with selected model
1074
  ).then(
1075
+ # Use RENAMED state variables as inputs to configure_gemini
1076
+ configure_gemini,
1077
+ inputs=[gemini_api_key_state, gemini_model_state],
1078
+ outputs=[gemini_status] # Update Gemini status based on new model
1079
  ).then(
1080
  # Call the update function and bind its output to the button component
1081
  check_send_button_ready,
1082
+ inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1083
+ outputs=[send_btn] # Update button interactivity using gr.Button.update return value
1084
  )
1085
 
1086
  # Handle Grounding checkbox change: update grounding state
 
1104
  # This .click() event triggers the ai_workflow_chat generator function
1105
  # Inputs are read from UI components AND State variables
1106
  # Outputs are updated by the values yielded from the generator
1107
+ # MODIFIED: Inputs use renamed gemini state variables
1108
+ # MODIFIED: Outputs include renamed gemini state variables
1109
  send_btn.click(
1110
  ai_workflow_chat, # The generator function to run
1111
  inputs=[
1112
  user_input, chatbot, # UI component inputs (message, current chat history)
1113
  hf_profile, hf_token, # HF State variables
1114
+ # Pass RENAMED gemini state variables as inputs
1115
+ gemini_api_key_state, gemini_model_state,
1116
  repo_id, workflow, sdk_state, # Workflow State variables
1117
  # UI component inputs whose *current values* are needed by the generator
1118
  iframe, run_txt, build_txt, # UI component inputs (current values)
 
1125
  iframe, run_txt, build_txt, # Update UI component outputs
1126
  debug_attempts, app_description, repo_name_state, generated_code_state, # Update other State variables
1127
  use_grounding_state, # Update the grounding state output
1128
+ # Include RENAMED gemini state variables in outputs to ensure consistency
1129
+ gemini_api_key_state, gemini_model_state
1130
  ]
1131
  ).success( # Chain a .success() event to run *after* the .click() handler completes without error
1132
  # Clear the user input textbox after the message is sent and processed
 
1145
  outputs=login_status # Update login status markdown
1146
  ).then(
1147
  # Action 2: Configure Gemini using the initial state values.
1148
+ # Since gemini_api_key_state state starts as "", this will initially show a "key is not set" message.
1149
+ # Use RENAMED state variables as inputs
1150
  configure_gemini,
1151
+ inputs=[gemini_api_key_state, gemini_model_state],
1152
  outputs=[gemini_status] # Update Gemini status display
1153
  ).then(
1154
  # Action 3: Check prereqs and update send button interactivity based on initial states.
1155
+ # Since gemini_api_key_state state starts as "", button will initially be disabled.
1156
  check_send_button_ready,
1157
+ inputs=send_button_interactive_binding_inputs, # Use the explicit list with renamed states
1158
+ outputs=[send_btn] # Update button interactivity using gr.Button.update return value
1159
  ).then(
1160
  # Action 4: Add the initial welcome message to the chatbot
1161
  greet,