Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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
|
233 |
-
#
|
234 |
-
|
|
|
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
|
239 |
-
print(f" Received
|
240 |
-
# For api_key, print part of the key if not None for verification
|
241 |
-
|
242 |
-
|
243 |
-
print(f" Received
|
244 |
-
print(f" Received model_name: Type={type(model_name)}, Value={model_name}")
|
245 |
# --- END ENHANCED DEBUGGING LOGS ---
|
246 |
|
247 |
-
is_logged_in =
|
248 |
-
#
|
249 |
-
is_gemini_ready =
|
250 |
|
251 |
# --- CONTINUED DEBUGGING LOGS ---
|
252 |
-
print(f" HF check: {
|
253 |
-
print(f" Gemini check: {
|
254 |
-
|
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 |
-
|
|
|
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 |
-
#
|
272 |
-
|
273 |
-
|
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
|
302 |
-
str | None, # 12: Explicitly yield
|
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
|
334 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
335 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
336 |
-
|
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 |
-
|
348 |
return # Stop workflow execution for this click
|
349 |
|
350 |
# Check if API key is non-empty string and model is set
|
351 |
-
|
|
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
503 |
|
504 |
# Perform the Gemini API call to generate code, optionally using grounding
|
505 |
-
# Use the
|
506 |
-
code = call_gemini(prompt,
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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
|
838 |
-
fix_code = call_gemini(debug_prompt,
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
#
|
934 |
-
|
935 |
-
|
|
|
|
|
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,
|
|
|
|
|
1036 |
).then(
|
1037 |
-
|
|
|
|
|
|
|
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,
|
|
|
|
|
1049 |
).then(
|
1050 |
-
|
|
|
|
|
|
|
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
|
1085 |
-
|
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 |
-
#
|
1099 |
-
|
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
|
|
|
1119 |
configure_gemini,
|
1120 |
-
inputs=[
|
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
|
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,
|