Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -229,54 +229,35 @@ 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 |
-
#
|
233 |
-
# FIXED: Return type hint corrected to gr.update
|
234 |
-
# MODIFIED: Internal logic uses bool() check for simplicity
|
235 |
-
# REMOVED: problematic debug prints involving *args, **kwargs
|
236 |
def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None) -> gr.update:
|
237 |
"""Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
|
238 |
# --- START ENHANCED DEBUGGING LOGS ---
|
239 |
print("\n--- check_send_button_ready START ---")
|
240 |
-
print(f" Received hf_profile:
|
241 |
-
print(f" Received hf_token:
|
242 |
# For api_key, print part of the key if not None/empty for verification
|
243 |
api_key_display = gemini_key[:5] if isinstance(gemini_key, str) and gemini_key else ('Empty String' if isinstance(gemini_key, str) and gemini_key == "" else 'None')
|
244 |
-
print(f" Received gemini_key:
|
245 |
-
print(f" Received gemini_model:
|
246 |
# --- END ENHANCED DEBUGGING LOGS ---
|
247 |
|
248 |
is_logged_in = hf_profile is not None and hf_token is not None
|
249 |
# Use bool() check for simplicity - handles None and "" correctly
|
250 |
is_gemini_ready = bool(gemini_key) and bool(gemini_model)
|
251 |
|
252 |
-
# --- CONTINUED DEBUGGING LOGS ---
|
253 |
-
print(f" HF check: ({hf_profile is not None} and {hf_token is not None}) = {is_logged_in}")
|
254 |
-
print(f" Gemini check: ({bool(gemini_key)} and {bool(gemini_model)}) = {is_gemini_ready}")
|
255 |
-
print("--- END CONTINUED DEBUGGING LOGS ---")
|
256 |
-
|
257 |
is_ready = is_logged_in and is_gemini_ready
|
258 |
-
print(f"check_send_button_ready - HF Ready: {is_logged_in}, Gemini Ready: {is_gemini_ready}, Button Ready
|
259 |
print("--- check_send_button_ready END ---\n")
|
260 |
|
261 |
-
# FIXED: Call gr.update instead of gr.Button.update
|
262 |
return gr.update(interactive=is_ready)
|
263 |
|
264 |
-
# --- New wrapper function to handle the state updates and call the checker ---
|
265 |
-
# This function takes the required state variables as inputs and calls the logic.
|
266 |
-
# This function will be called by the .change() events of the state variables.
|
267 |
-
def update_send_button_state(profile: gr.OAuthProfile | None, token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None) -> gr.update:
|
268 |
-
"""Wrapper function to read states and update button interactivity."""
|
269 |
-
# Pass the received values directly to the core check function
|
270 |
-
return check_send_button_ready(profile, token, gemini_key, gemini_model)
|
271 |
-
# --- End of new wrapper function ---
|
272 |
-
|
273 |
|
274 |
# This is the main generator function for the workflow, triggered by the 'Send' button
|
275 |
# NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
|
276 |
# It MUST also yield/return ALL state variables in the same order they appear in the `outputs` list of the `.click()` event.
|
277 |
-
#
|
278 |
-
#
|
279 |
-
# REMOVED: *args, **kwargs from signature
|
280 |
def ai_workflow_chat(
|
281 |
message: str,
|
282 |
history: list[dict],
|
@@ -297,7 +278,7 @@ def ai_workflow_chat(
|
|
297 |
repo_name_state: str | None,
|
298 |
generated_code_state: str | None,
|
299 |
use_grounding_state: bool, # Value from use_grounding_checkbox
|
300 |
-
# Absorb potential extra args passed by Gradio event listeners
|
301 |
*args,
|
302 |
**kwargs
|
303 |
) -> tuple[
|
@@ -331,6 +312,27 @@ def ai_workflow_chat(
|
|
331 |
current_gemini_key = gemini_api_key_state
|
332 |
current_gemini_model = gemini_model_state
|
333 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
|
335 |
# Keep copies of potentially updated UI elements passed as inputs to update them later
|
336 |
# These are the *current values* of the UI components as of the button click
|
@@ -349,6 +351,7 @@ def ai_workflow_chat(
|
|
349 |
# This provides immediate feedback to the user while the AI processes
|
350 |
# Ensure all state variables and UI outputs are yielded back in the correct order
|
351 |
# Include gemini_api_key_state and gemini_model_state in the yield tuple
|
|
|
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
|
@@ -358,20 +361,21 @@ def ai_workflow_chat(
|
|
358 |
|
359 |
# Although button interactivity prevents reaching here without key/model,
|
360 |
# the checks remain as a safeguard for the workflow logic itself.
|
|
|
361 |
if not (hf_profile and hf_token):
|
362 |
history = add_bot_message(history, "Workflow paused: Please log in to Hugging Face first.")
|
|
|
363 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
364 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
365 |
-
current_gemini_key, current_gemini_model)
|
366 |
return # Stop workflow execution for this click
|
367 |
|
368 |
-
# Check if API key is non-empty string and model is set
|
369 |
-
# Use the local variables derived from state inputs
|
370 |
if not (isinstance(current_gemini_key, str) and current_gemini_key != "" and current_gemini_model):
|
371 |
history = add_bot_message(history, "Workflow cannot start: Please ensure your Gemini API key is entered and a model is selected.")
|
|
|
372 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
373 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
374 |
-
current_gemini_key, current_gemini_model) #
|
375 |
return # Stop workflow execution for this click
|
376 |
|
377 |
|
@@ -384,15 +388,10 @@ def ai_workflow_chat(
|
|
384 |
create_match = re.search(r'create (?:a|an)? space called (\w+)', message, re.I)
|
385 |
|
386 |
if reset_match:
|
387 |
-
# Reset the workflow state and associated variables
|
388 |
history = add_bot_message(history, "Workflow reset.")
|
389 |
-
#
|
390 |
-
# Also reset UI outputs to their initial state
|
391 |
-
# gemini_key and gemini_model are passed back with their *current* (likely valid) state
|
392 |
yield (history, None, STATE_IDLE, "<p>No Space created yet.</p>", "", "", 0,
|
393 |
-
None, None, None, False, #
|
394 |
-
current_gemini_key, current_gemini_model) # Explicitly pass back current state values
|
395 |
-
# No return needed after yield in this generator pattern; execution for this click ends here.
|
396 |
|
397 |
elif generate_match:
|
398 |
# User requested generation with description and name
|
@@ -403,11 +402,10 @@ def ai_workflow_chat(
|
|
403 |
state = STATE_CREATING_SPACE
|
404 |
repo_name = new_repo_name
|
405 |
app_desc = new_app_desc
|
406 |
-
# Yield updated
|
407 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
408 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
409 |
-
current_gemini_key, current_gemini_model)
|
410 |
-
# No return needed
|
411 |
|
412 |
elif create_match:
|
413 |
# User requested simple space creation with a name
|
@@ -415,30 +413,27 @@ def ai_workflow_chat(
|
|
415 |
history = add_bot_message(history, f"Acknowledged: '{message}'. Starting workflow to create Space `{hf_profile.username}/{new_repo_name}`.")
|
416 |
state = STATE_CREATING_SPACE # Transition state to creation
|
417 |
repo_name = new_repo_name # Store the validated repo name
|
418 |
-
# Yield updated
|
419 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
420 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
421 |
-
current_gemini_key, current_gemini_model)
|
422 |
-
# No return needed
|
423 |
|
424 |
elif "create" in message.lower() and not repo_id:
|
425 |
# User wants to create but didn't specify a name yet
|
426 |
history = add_bot_message(history, "Okay, what should the Space be called? (e.g., `my-awesome-app`)")
|
427 |
state = STATE_AWAITING_REPO_NAME # Transition to the state where we wait for the name
|
428 |
-
# Yield updated
|
429 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
430 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
431 |
-
current_gemini_key, current_gemini_model)
|
432 |
-
# No return needed
|
433 |
|
434 |
else:
|
435 |
# Command not recognized in IDLE state
|
436 |
history = add_bot_message(history, "Command not recognized. Try 'generate me a gradio app called myapp', or 'reset'.")
|
437 |
-
# Yield
|
438 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
439 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
440 |
-
current_gemini_key, current_gemini_model)
|
441 |
-
# No return needed
|
442 |
|
443 |
|
444 |
elif state == STATE_AWAITING_REPO_NAME:
|
@@ -451,54 +446,41 @@ def ai_workflow_chat(
|
|
451 |
# Stay in AWAITING_REPO_NAME state and yield message (pass UI outputs through)
|
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 |
else:
|
458 |
history = add_bot_message(history, f"Using Space name `{new_repo_name}`. Creating Space `{hf_profile.username}/{new_repo_name}`...")
|
459 |
state = STATE_CREATING_SPACE # Transition state to creation
|
460 |
repo_name = new_repo_name # Store the validated repo name
|
461 |
-
# Yield updated
|
462 |
-
# The next click will proceed from the STATE_CREATING_SPACE block.
|
463 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
464 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
465 |
-
current_gemini_key, current_gemini_model)
|
466 |
-
# No return needed
|
467 |
|
468 |
-
# Note: Each 'elif' block below represents a distinct step in the workflow triggered
|
469 |
-
# when the 'state' variable matches its condition on a button click.
|
470 |
|
471 |
elif state == STATE_CREATING_SPACE:
|
472 |
# Ensure repo_name is available (it should have been set in the previous step)
|
473 |
if not repo_name:
|
474 |
history = add_bot_message(history, "Internal error: Repo name missing for creation. Resetting.")
|
475 |
-
# Reset
|
476 |
yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
|
477 |
-
None, None, None, use_grounding,
|
478 |
-
current_gemini_key, current_gemini_model) # Pass grounding state through
|
479 |
-
# No return needed
|
480 |
-
|
481 |
else:
|
482 |
try:
|
483 |
-
# Perform the action to create the Space on Hugging Face
|
484 |
new_repo_id, iframe_html = create_space_action(repo_name, space_sdk, hf_profile, hf_token)
|
485 |
-
updated_preview = iframe_html
|
486 |
-
repo_id = new_repo_id #
|
487 |
history = add_bot_message(history, f"✅ Space `{repo_id}` created. Click 'Send' to generate and upload code.")
|
488 |
-
state = STATE_GENERATING_CODE
|
489 |
-
# Yield updated state variables
|
490 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
491 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
492 |
-
current_gemini_key, current_gemini_model) #
|
493 |
-
# No return needed
|
494 |
-
|
495 |
except Exception as e:
|
496 |
history = add_bot_message(history, f"❌ Error creating space: {e}. Click 'reset'.")
|
497 |
-
#
|
498 |
yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
|
499 |
-
None, None, None, use_grounding,
|
500 |
-
current_gemini_key, current_gemini_model) # Pass logs and grounding through
|
501 |
-
# No return needed
|
502 |
|
503 |
|
504 |
elif state == STATE_GENERATING_CODE:
|
@@ -515,42 +497,33 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
|
|
515 |
history = add_bot_message(history, f"🧠 Generating `{prompt_desc}` `{space_sdk}` app (`app.py`) code with Gemini...")
|
516 |
if use_grounding:
|
517 |
history = add_bot_message(history, "(Using Grounding with Google Search)")
|
518 |
-
# Yield
|
519 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
520 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
521 |
-
current_gemini_key, current_gemini_model)
|
522 |
|
523 |
-
# Perform the Gemini API call to generate code, optionally using grounding
|
524 |
-
# Use the current_gemini_key and current_gemini_model derived from state inputs
|
525 |
code = call_gemini(prompt, current_gemini_key, current_gemini_model, use_grounding=use_grounding)
|
526 |
code = code.strip()
|
527 |
-
# Clean up
|
528 |
-
if code.startswith("```python"):
|
529 |
-
|
530 |
-
if code.
|
531 |
-
code = code[len("```"):].strip()
|
532 |
-
if code.endswith("```"):
|
533 |
-
code = code[:-len("```")].strip()
|
534 |
|
535 |
-
if not code:
|
536 |
-
raise ValueError("Gemini returned empty code.")
|
537 |
|
538 |
history = add_bot_message(history, "✅ `app.py` code generated. Click 'Send' to upload.")
|
539 |
-
state = STATE_UPLOADING_APP_PY
|
540 |
-
generated_code = code
|
541 |
-
# Yield updated state variables
|
542 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
543 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
544 |
-
current_gemini_key, current_gemini_model)
|
545 |
-
# No return needed
|
546 |
|
547 |
except Exception as e:
|
548 |
history = add_bot_message(history, f"❌ Error generating code: {e}. Click 'reset'.")
|
549 |
-
#
|
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 |
|
556 |
elif state == STATE_UPLOADING_APP_PY:
|
@@ -559,44 +532,35 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
|
|
559 |
if not code_to_upload:
|
560 |
history = add_bot_message(history, "Internal error: No code to upload. Resetting.")
|
561 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
562 |
-
None, None, None, use_grounding,
|
563 |
-
current_gemini_key, current_gemini_model)
|
564 |
-
# No return needed
|
565 |
-
|
566 |
else:
|
567 |
history = add_bot_message(history, "☁️ Uploading `app.py`...")
|
568 |
-
# Yield
|
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 |
-
|
573 |
try:
|
574 |
-
# Perform the file upload action
|
575 |
upload_file_to_space_action(io.StringIO(code_to_upload), "app.py", repo_id, hf_profile, hf_token)
|
576 |
history = add_bot_message(history, "✅ Uploaded `app.py`. Click 'Send' to generate requirements.")
|
577 |
-
state = STATE_GENERATING_REQUIREMENTS
|
578 |
-
generated_code = None
|
579 |
-
# Yield updated state variables
|
580 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
581 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
582 |
-
current_gemini_key, current_gemini_model)
|
583 |
-
# No return needed
|
584 |
-
|
585 |
except Exception as e:
|
586 |
history = add_bot_message(history, f"❌ Error uploading `app.py`: {e}. Click 'reset'.")
|
587 |
-
#
|
588 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
589 |
-
None, None, None, use_grounding,
|
590 |
-
current_gemini_key, current_gemini_model)
|
591 |
-
# No return needed
|
592 |
|
593 |
|
594 |
elif state == STATE_GENERATING_REQUIREMENTS:
|
595 |
history = add_bot_message(history, "📄 Generating `requirements.txt`...")
|
596 |
-
# Yield
|
597 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
598 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
599 |
-
current_gemini_key, current_gemini_model)
|
600 |
|
601 |
# Logic to determine required packages based on SDK and keywords in the app description
|
602 |
reqs_list = ["gradio"] if space_sdk == "gradio" else ["streamlit"]
|
@@ -639,8 +603,7 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
|
|
639 |
# Yield updated state variables and history (pass UI outputs and other 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 |
-
current_gemini_key, current_gemini_model)
|
643 |
-
# No return needed
|
644 |
|
645 |
|
646 |
elif state == STATE_UPLOADING_REQUIREMENTS:
|
@@ -649,17 +612,13 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
|
|
649 |
if not reqs_content_to_upload:
|
650 |
history = add_bot_message(history, "Internal error: No requirements content to upload. Resetting.")
|
651 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
652 |
-
None, None, None, use_grounding,
|
653 |
-
current_gemini_key, current_gemini_model)
|
654 |
-
# No return needed
|
655 |
-
|
656 |
else:
|
657 |
history = add_bot_message(history, "☁️ Uploading `requirements.txt`...")
|
658 |
# Yield message before upload (pass UI outputs and 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 |
-
|
663 |
try:
|
664 |
# Perform requirements file upload
|
665 |
upload_file_to_space_action(io.StringIO(reqs_content_to_upload), "requirements.txt", repo_id, hf_profile, hf_token)
|
@@ -669,23 +628,19 @@ Return **only** the python code block for `app.py`. Do not include any extra tex
|
|
669 |
# Yield updated state variables and history (pass UI outputs and other states through)
|
670 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
671 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
672 |
-
current_gemini_key, current_gemini_model)
|
673 |
-
# No return needed
|
674 |
-
|
675 |
except Exception as e:
|
676 |
history = add_bot_message(history, f"❌ Error uploading `requirements.txt`: {e}. Click 'reset'.")
|
677 |
# Yield error message and reset state on failure
|
678 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
679 |
-
None, None, None, use_grounding,
|
680 |
-
current_gemini_key, current_gemini_model)
|
681 |
-
# No return needed
|
682 |
|
683 |
elif state == STATE_GENERATING_README:
|
684 |
history = add_bot_message(history, "📝 Generating `README.md`...")
|
685 |
# Yield message before generating README (pass UI outputs and states through)
|
686 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
687 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
688 |
-
current_gemini_key, current_gemini_model)
|
689 |
|
690 |
# Generate simple README content with Space metadata header
|
691 |
readme_title = repo_name if repo_name else "My Awesome Space"
|
@@ -714,8 +669,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
714 |
# Yield updated state variables and history (pass UI outputs and other 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 |
-
current_gemini_key, current_gemini_model)
|
718 |
-
# No return needed
|
719 |
|
720 |
|
721 |
elif state == STATE_UPLOADING_README:
|
@@ -724,17 +678,13 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
724 |
if not readme_content_to_upload:
|
725 |
history = add_bot_message(history, "Internal error: No README content to upload. Resetting.")
|
726 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
727 |
-
None, None, None, use_grounding,
|
728 |
-
current_gemini_key, current_gemini_model)
|
729 |
-
# No return needed
|
730 |
-
|
731 |
else:
|
732 |
history = add_bot_message(history, "☁️ Uploading `README.md`...")
|
733 |
# Yield message before upload (pass UI outputs and 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 |
-
|
738 |
try:
|
739 |
# Perform README file upload
|
740 |
upload_file_to_space_action(io.StringIO(readme_content_to_upload), "README.md", repo_id, hf_profile, hf_token)
|
@@ -744,23 +694,19 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
744 |
# Yield updated state variables and history (pass UI outputs and other states through)
|
745 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
746 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
747 |
-
current_gemini_key, current_gemini_model)
|
748 |
-
# No return needed
|
749 |
-
|
750 |
except Exception as e:
|
751 |
history = add_bot_message(history, f"❌ Error uploading `README.md`: {e}. Click 'reset'.")
|
752 |
# Yield error message and reset state on failure
|
753 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
754 |
-
None, None, None, use_grounding,
|
755 |
-
current_gemini_key, current_gemini_model)
|
756 |
-
# No return needed
|
757 |
|
758 |
elif state == STATE_CHECKING_LOGS_BUILD:
|
759 |
history = add_bot_message(history, "🔍 Fetching build logs...")
|
760 |
# Yield message before fetching logs (which includes a delay) (pass UI outputs and states through)
|
761 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
762 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
763 |
-
current_gemini_key, current_gemini_model)
|
764 |
|
765 |
# Fetch build logs from HF Space
|
766 |
build_logs_text = get_build_logs_action(repo_id, hf_profile, hf_token)
|
@@ -773,8 +719,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
773 |
# Yield updated state, logs, and variables
|
774 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
775 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
776 |
-
current_gemini_key, current_gemini_model)
|
777 |
-
# No return needed
|
778 |
|
779 |
else:
|
780 |
history = add_bot_message(history, "✅ Build logs fetched. Click 'Send' to check container logs.")
|
@@ -782,8 +727,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
782 |
# Yield updated state, logs, and variables
|
783 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
784 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
785 |
-
current_gemini_key, current_gemini_model)
|
786 |
-
# No return needed
|
787 |
|
788 |
|
789 |
elif state == STATE_CHECKING_LOGS_RUN:
|
@@ -791,7 +735,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
791 |
# Yield message before fetching logs (includes a delay) (pass UI outputs and states through)
|
792 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
793 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
794 |
-
current_gemini_key, current_gemini_model)
|
795 |
|
796 |
# Fetch container logs from HF Space
|
797 |
container_logs_text = get_container_logs_action(repo_id, hf_profile, hf_token)
|
@@ -805,8 +749,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
805 |
# Yield updated state, logs, attempts, and variables
|
806 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
807 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
808 |
-
current_gemini_key, current_gemini_model)
|
809 |
-
# No return needed
|
810 |
|
811 |
elif ("error" in updated_run.lower() or "exception" in updated_run.lower()) and attempts >= MAX_DEBUG_ATTEMPTS:
|
812 |
# Max debug attempts reached
|
@@ -815,8 +758,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
815 |
# Yield updated state, logs, attempts, and variables
|
816 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
817 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
818 |
-
current_gemini_key, current_gemini_model)
|
819 |
-
# No return needed
|
820 |
|
821 |
else:
|
822 |
# No significant errors found in logs, assume success
|
@@ -825,8 +767,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
825 |
# Yield updated state, logs, attempts, and variables
|
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 |
-
# No return needed
|
830 |
|
831 |
|
832 |
elif state == STATE_DEBUGGING_CODE:
|
@@ -836,7 +777,7 @@ This Space was automatically generated by an AI workflow using Google Gemini and
|
|
836 |
# Yield message before Gemini API call (pass UI outputs and states through)
|
837 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
838 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
839 |
-
current_gemini_key, current_gemini_model)
|
840 |
|
841 |
# Construct prompt for Gemini including the container logs
|
842 |
debug_prompt = f"""
|
@@ -873,16 +814,14 @@ Return **only** the python code block for app.py. Do not include any extra text,
|
|
873 |
# Yield updated state, code, and variables (pass UI outputs and states through)
|
874 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
875 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
876 |
-
current_gemini_key, current_gemini_model)
|
877 |
-
# No return needed
|
878 |
|
879 |
except Exception as e:
|
880 |
history = add_bot_message(history, f"❌ Error generating debug code: {e}. Click 'reset'.")
|
881 |
# Yield error message and reset state on failure
|
882 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
883 |
None, None, None, use_grounding,
|
884 |
-
current_gemini_key, current_gemini_model)
|
885 |
-
# No return needed
|
886 |
|
887 |
elif state == STATE_UPLOADING_FIXED_APP_PY:
|
888 |
# Retrieve the fixed code from the state variable
|
@@ -890,16 +829,13 @@ Return **only** the python code block for app.py. Do not include any extra text,
|
|
890 |
if not fixed_code_to_upload:
|
891 |
history = add_bot_message(history, "Internal error: No fixed code available to upload. Resetting.")
|
892 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
893 |
-
None, None, None, use_grounding,
|
894 |
-
current_gemini_key, current_gemini_model)
|
895 |
-
# No return needed
|
896 |
-
|
897 |
else:
|
898 |
history = add_bot_message(history, "☁️ Uploading fixed `app.py`...")
|
899 |
# Yield message before upload (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 |
|
904 |
try:
|
905 |
# Perform the upload of the fixed app.py
|
@@ -910,24 +846,20 @@ Return **only** the python code block for app.py. Do not include any extra text,
|
|
910 |
# Yield updated state, code, and variables (pass UI outputs and states through)
|
911 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
912 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
913 |
-
current_gemini_key, current_gemini_model)
|
914 |
-
# No return needed
|
915 |
|
916 |
except Exception as e:
|
917 |
history = add_bot_message(history, f"❌ Error uploading fixed `app.py`: {e}. Click 'reset'.")
|
918 |
# Yield error message and reset state on failure
|
919 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
920 |
-
None, None, None, use_grounding,
|
921 |
-
current_gemini_key, current_gemini_model)
|
922 |
-
# No return needed
|
923 |
|
924 |
elif state == STATE_COMPLETE:
|
925 |
# If in the complete state, the workflow is finished for this project.
|
926 |
# Subsequent clicks just add user messages; we simply yield the current state.
|
927 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
928 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
929 |
-
current_gemini_key, current_gemini_model)
|
930 |
-
# No return needed
|
931 |
|
932 |
|
933 |
except Exception as e:
|
@@ -935,10 +867,10 @@ Return **only** the python code block for app.py. Do not include any extra text,
|
|
935 |
error_message = f"Workflow step failed unexpectedly ({state}): {e}. Click 'Send' to re-attempt this step or 'reset'."
|
936 |
history = add_bot_message(history, error_message)
|
937 |
print(f"Critical Error in state {state}: {e}") # Log the error for debugging purposes
|
|
|
938 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
939 |
None, None, None, use_grounding,
|
940 |
-
current_gemini_key, current_gemini_model) #
|
941 |
-
# No return needed after yield
|
942 |
|
943 |
|
944 |
# --- Build the Gradio UI ---
|
@@ -948,9 +880,9 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
948 |
# Define these first as they might be used in default values for components
|
949 |
hf_profile = gr.State(None)
|
950 |
hf_token = gr.State(None)
|
951 |
-
#
|
952 |
gemini_api_key_state = gr.State("") # start with no key
|
953 |
-
#
|
954 |
gemini_model_state = gr.State("gemini-1.5-flash") # Default selected model
|
955 |
|
956 |
repo_id = gr.State(None) # Stores the ID of the created Space
|
@@ -975,7 +907,7 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
975 |
|
976 |
gr.Markdown("## Google AI Studio / Gemini")
|
977 |
# Define gemini_input and gemini_status before they are used in change handlers
|
978 |
-
#
|
979 |
gemini_input = gr.Textbox(
|
980 |
label="Your Google AI Studio API Key", # Changed label
|
981 |
type="password", # Hides input for security
|
@@ -1021,7 +953,7 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
1021 |
chatbot = gr.Chatbot(type='messages', label="AI Workflow Chat")
|
1022 |
user_input = gr.Textbox(placeholder="Type your message…", interactive=True)
|
1023 |
# Define send_btn here, BEFORE it's used in send_button_update_output
|
1024 |
-
send_btn = gr.Button("Send") #
|
1025 |
|
1026 |
|
1027 |
# Define iframe, build_txt, run_txt after send_btn
|
@@ -1033,75 +965,73 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
1033 |
|
1034 |
# --- Define Event Handlers and Chains AFTER all components and required lists are defined ---
|
1035 |
|
1036 |
-
# Define the inputs used for checking prerequisites
|
1037 |
-
# This list
|
1038 |
send_button_interactive_binding_inputs = [
|
1039 |
hf_profile,
|
1040 |
hf_token,
|
1041 |
-
gemini_api_key_state,
|
1042 |
-
gemini_model_state
|
1043 |
]
|
1044 |
# Define the output for updating the send button interactivity
|
1045 |
-
# FIXED: Moved definition to *after* send_btn is defined
|
1046 |
send_button_update_output = [send_btn]
|
1047 |
|
1048 |
|
1049 |
-
# Trigger
|
1050 |
-
#
|
1051 |
-
# The inputs list ensures those 4 state values are passed.
|
1052 |
hf_profile.change(
|
1053 |
-
|
1054 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
1055 |
outputs=send_button_update_output, # Update only the send button
|
1056 |
)
|
1057 |
hf_token.change(
|
1058 |
-
|
1059 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
1060 |
outputs=send_button_update_output, # Update only the send button
|
1061 |
)
|
1062 |
# gemini_input.change updates gemini_api_key_state, which triggers gemini_api_key_state.change
|
1063 |
gemini_api_key_state.change(
|
1064 |
-
|
1065 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
1066 |
outputs=send_button_update_output, # Update only the send button
|
1067 |
)
|
1068 |
# model_selector.change updates gemini_model_state, which triggers gemini_model_state.change
|
1069 |
gemini_model_state.change(
|
1070 |
-
|
1071 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
1072 |
outputs=send_button_update_output, # Update only the send button
|
1073 |
)
|
1074 |
|
1075 |
|
1076 |
-
# Handle login button click: Update profile/token state -> Their .change handlers trigger
|
1077 |
login_btn.click(
|
1078 |
-
lambda x: (x[0], x[1]),
|
1079 |
inputs=[login_btn],
|
1080 |
-
outputs=[hf_profile, hf_token] #
|
1081 |
)
|
1082 |
|
1083 |
-
# Handle Gemini Key Input change: Update key state -> Configure Gemini status -> State .change handler triggers
|
1084 |
gemini_input.change(
|
1085 |
-
lambda k: k,
|
1086 |
inputs=[gemini_input],
|
1087 |
-
outputs=[gemini_api_key_state] #
|
1088 |
).then(
|
1089 |
-
#
|
1090 |
configure_gemini,
|
1091 |
inputs=[gemini_api_key_state, gemini_model_state],
|
1092 |
-
outputs=[gemini_status] # Update Gemini status
|
1093 |
)
|
1094 |
|
1095 |
-
# Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> State .change handler triggers
|
1096 |
model_selector.change(
|
1097 |
-
lambda m: m,
|
1098 |
inputs=[model_selector],
|
1099 |
-
outputs=[gemini_model_state] #
|
1100 |
).then(
|
1101 |
-
#
|
1102 |
configure_gemini,
|
1103 |
inputs=[gemini_api_key_state, gemini_model_state],
|
1104 |
-
outputs=[gemini_status] # Update Gemini status
|
1105 |
)
|
1106 |
|
1107 |
|
@@ -1119,6 +1049,8 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
1119 |
workflow.change(lambda s: s, inputs=workflow, outputs=status_text)
|
1120 |
|
1121 |
# Link Repo ID State variable change to UI status display
|
|
|
|
|
1122 |
repo_id.change(lambda r: r if r else "None", inputs=repo_id, outputs=repo_id_text)
|
1123 |
|
1124 |
|
@@ -1126,31 +1058,25 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
1126 |
# This .click() event triggers the ai_workflow_chat generator function
|
1127 |
# Inputs are read from UI components AND State variables
|
1128 |
# Outputs are updated by the values yielded from the generator
|
1129 |
-
#
|
1130 |
-
# MODIFIED: Outputs include renamed gemini state variables
|
1131 |
-
# Added back *args, **kwargs to the generator function signature and yield for robustness,
|
1132 |
-
# as the previous attempt suggested this might be necessary for state consistency within the generator's lifecycle.
|
1133 |
send_btn.click(
|
1134 |
ai_workflow_chat, # The generator function to run
|
1135 |
inputs=[
|
1136 |
user_input, chatbot, # UI component inputs (message, current chat history)
|
1137 |
hf_profile, hf_token, # HF State variables
|
1138 |
-
|
1139 |
-
gemini_api_key_state, gemini_model_state,
|
1140 |
repo_id, workflow, sdk_state, # Workflow State variables
|
1141 |
-
# UI component inputs whose *current values* are needed by the generator
|
1142 |
iframe, run_txt, build_txt, # UI component inputs (current values)
|
1143 |
debug_attempts, app_description, repo_name_state, generated_code_state, # Other State variables
|
1144 |
use_grounding_state # Grounding state input
|
1145 |
],
|
1146 |
outputs=[
|
1147 |
-
chatbot, #
|
1148 |
-
repo_id, workflow, #
|
1149 |
-
iframe, run_txt, build_txt, #
|
1150 |
-
debug_attempts, app_description, repo_name_state, generated_code_state, #
|
1151 |
-
use_grounding_state, #
|
1152 |
-
#
|
1153 |
-
gemini_api_key_state, gemini_model_state
|
1154 |
]
|
1155 |
).success( # Chain a .success() event to run *after* the .click() handler completes without error
|
1156 |
# Clear the user input textbox after the message is sent and processed
|
@@ -1164,20 +1090,18 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
|
|
1164 |
# This chain runs once when the app loads
|
1165 |
ai_builder_tab.load(
|
1166 |
# Action 1: Show profile (loads cached login if available)
|
1167 |
-
# This calls show_profile, which updates the login_status UI.
|
1168 |
-
# The LoginButton component itself implicitly handles updating hf_profile/hf_token states on load if cached creds exist.
|
1169 |
show_profile,
|
1170 |
inputs=None,
|
1171 |
outputs=login_status # Updates UI
|
1172 |
).then(
|
1173 |
# Action 2: Configure Gemini using initial state (gemini_api_key_state is "", model_state is default)
|
1174 |
configure_gemini,
|
1175 |
-
inputs=[gemini_api_key_state, gemini_model_state],
|
1176 |
outputs=[gemini_status] # Update Gemini status display
|
1177 |
).then(
|
1178 |
# Action 3: After initial load checks, update the button state based on initial states
|
1179 |
-
#
|
1180 |
-
|
1181 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
1182 |
outputs=send_button_update_output, # Update the send button
|
1183 |
).then(
|
|
|
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 |
+
# Now takes explicit arguments, intended to be called with all necessary states.
|
|
|
|
|
|
|
233 |
def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None) -> gr.update:
|
234 |
"""Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
|
235 |
# --- START ENHANCED DEBUGGING LOGS ---
|
236 |
print("\n--- check_send_button_ready START ---")
|
237 |
+
print(f" Received hf_profile: {hf_profile is not None}")
|
238 |
+
print(f" Received hf_token: {hf_token is not None}")
|
239 |
# For api_key, print part of the key if not None/empty for verification
|
240 |
api_key_display = gemini_key[:5] if isinstance(gemini_key, str) and gemini_key else ('Empty String' if isinstance(gemini_key, str) and gemini_key == "" else 'None')
|
241 |
+
print(f" Received gemini_key: Value starts with '{api_key_display}'")
|
242 |
+
print(f" Received gemini_model: {gemini_model}")
|
243 |
# --- END ENHANCED DEBUGGING LOGS ---
|
244 |
|
245 |
is_logged_in = hf_profile is not None and hf_token is not None
|
246 |
# Use bool() check for simplicity - handles None and "" correctly
|
247 |
is_gemini_ready = bool(gemini_key) and bool(gemini_model)
|
248 |
|
|
|
|
|
|
|
|
|
|
|
249 |
is_ready = is_logged_in and is_gemini_ready
|
250 |
+
print(f"check_send_button_ready - HF Ready: {is_logged_in}, Gemini Ready: {is_gemini_ready}, Button Ready: {is_ready}")
|
251 |
print("--- check_send_button_ready END ---\n")
|
252 |
|
|
|
253 |
return gr.update(interactive=is_ready)
|
254 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
|
256 |
# This is the main generator function for the workflow, triggered by the 'Send' button
|
257 |
# NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
|
258 |
# It MUST also yield/return ALL state variables in the same order they appear in the `outputs` list of the `.click()` event.
|
259 |
+
# Added back *args, **kwargs to the generator function signature and yield for robustness,
|
260 |
+
# as the previous attempt suggested this might be necessary for state consistency within the generator's lifecycle.
|
|
|
261 |
def ai_workflow_chat(
|
262 |
message: str,
|
263 |
history: list[dict],
|
|
|
278 |
repo_name_state: str | None,
|
279 |
generated_code_state: str | None,
|
280 |
use_grounding_state: bool, # Value from use_grounding_checkbox
|
281 |
+
# Absorb potential extra args passed by Gradio event listeners
|
282 |
*args,
|
283 |
**kwargs
|
284 |
) -> tuple[
|
|
|
312 |
current_gemini_key = gemini_api_key_state
|
313 |
current_gemini_model = gemini_model_state
|
314 |
|
315 |
+
# --- START DEBUGGING ai_workflow_chat inputs ---
|
316 |
+
print("\n--- ai_workflow_chat START (Inputs received) ---")
|
317 |
+
print(f" message: {message}")
|
318 |
+
print(f" history len: {len(history)}")
|
319 |
+
print(f" hf_profile: {hf_profile is not None}")
|
320 |
+
print(f" hf_token: {hf_token is not None}")
|
321 |
+
api_key_display = current_gemini_key[:5] if isinstance(current_gemini_key, str) and current_gemini_key else ('Empty String' if isinstance(current_gemini_key, str) and current_gemini_key == "" else 'None')
|
322 |
+
print(f" gemini_api_key_state: Value starts with '{api_key_display}'")
|
323 |
+
print(f" gemini_model_state: {current_gemini_model}")
|
324 |
+
print(f" repo_id_state: {repo_id_state}") # Check value here
|
325 |
+
print(f" workflow_state: {workflow_state}")
|
326 |
+
print(f" space_sdk: {space_sdk}")
|
327 |
+
print(f" use_grounding_state: {use_grounding_state}")
|
328 |
+
print(f" debug_attempts_state: {debug_attempts_state}")
|
329 |
+
print(f" app_description_state: {app_description_state}")
|
330 |
+
print(f" repo_name_state: {repo_name_state}")
|
331 |
+
print(f" generated_code_state: {'Present' if generated_code_state is not None else 'None'}")
|
332 |
+
# print(f" *args: {args}") # Optional: print extra args if needed
|
333 |
+
# print(f" **kwargs: {kwargs}") # Optional: print extra kwargs if needed
|
334 |
+
print("--- END DEBUGGING ai_workflow_chat inputs ---\n")
|
335 |
+
|
336 |
|
337 |
# Keep copies of potentially updated UI elements passed as inputs to update them later
|
338 |
# These are the *current values* of the UI components as of the button click
|
|
|
351 |
# This provides immediate feedback to the user while the AI processes
|
352 |
# Ensure all state variables and UI outputs are yielded back in the correct order
|
353 |
# Include gemini_api_key_state and gemini_model_state in the yield tuple
|
354 |
+
# The yielded tuple must match the send_btn.click outputs list exactly.
|
355 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
356 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
357 |
current_gemini_key, current_gemini_model) # Explicitly pass back current state values
|
|
|
361 |
|
362 |
# Although button interactivity prevents reaching here without key/model,
|
363 |
# the checks remain as a safeguard for the workflow logic itself.
|
364 |
+
# Use the local variables derived from state inputs (current_gemini_key, current_gemini_model)
|
365 |
if not (hf_profile and hf_token):
|
366 |
history = add_bot_message(history, "Workflow paused: Please log in to Hugging Face first.")
|
367 |
+
# Re-yield state to update chat and keep current state values
|
368 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
369 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
370 |
+
current_gemini_key, current_gemini_model)
|
371 |
return # Stop workflow execution for this click
|
372 |
|
|
|
|
|
373 |
if not (isinstance(current_gemini_key, str) and current_gemini_key != "" and current_gemini_model):
|
374 |
history = add_bot_message(history, "Workflow cannot start: Please ensure your Gemini API key is entered and a model is selected.")
|
375 |
+
# Re-yield state to update chat and keep current state values
|
376 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
377 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
378 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received (likely empty/None) Gemini states
|
379 |
return # Stop workflow execution for this click
|
380 |
|
381 |
|
|
|
388 |
create_match = re.search(r'create (?:a|an)? space called (\w+)', message, re.I)
|
389 |
|
390 |
if reset_match:
|
|
|
391 |
history = add_bot_message(history, "Workflow reset.")
|
392 |
+
# Reset relevant states and UI outputs, passing through current Gemini state
|
|
|
|
|
393 |
yield (history, None, STATE_IDLE, "<p>No Space created yet.</p>", "", "", 0,
|
394 |
+
None, None, None, False, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
395 |
|
396 |
elif generate_match:
|
397 |
# User requested generation with description and name
|
|
|
402 |
state = STATE_CREATING_SPACE
|
403 |
repo_name = new_repo_name
|
404 |
app_desc = new_app_desc
|
405 |
+
# Yield updated state variables, passing others through
|
406 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
407 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
408 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
409 |
|
410 |
elif create_match:
|
411 |
# User requested simple space creation with a name
|
|
|
413 |
history = add_bot_message(history, f"Acknowledged: '{message}'. Starting workflow to create Space `{hf_profile.username}/{new_repo_name}`.")
|
414 |
state = STATE_CREATING_SPACE # Transition state to creation
|
415 |
repo_name = new_repo_name # Store the validated repo name
|
416 |
+
# Yield updated state variables, passing others through
|
417 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
418 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
419 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
420 |
|
421 |
elif "create" in message.lower() and not repo_id:
|
422 |
# User wants to create but didn't specify a name yet
|
423 |
history = add_bot_message(history, "Okay, what should the Space be called? (e.g., `my-awesome-app`)")
|
424 |
state = STATE_AWAITING_REPO_NAME # Transition to the state where we wait for the name
|
425 |
+
# Yield updated state, passing others through
|
426 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
427 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
428 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
429 |
|
430 |
else:
|
431 |
# Command not recognized in IDLE state
|
432 |
history = add_bot_message(history, "Command not recognized. Try 'generate me a gradio app called myapp', or 'reset'.")
|
433 |
+
# Yield current state, passing others through
|
434 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
435 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
436 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
437 |
|
438 |
|
439 |
elif state == STATE_AWAITING_REPO_NAME:
|
|
|
446 |
# Stay in AWAITING_REPO_NAME state and yield message (pass UI outputs through)
|
447 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
448 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
449 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
450 |
|
451 |
else:
|
452 |
history = add_bot_message(history, f"Using Space name `{new_repo_name}`. Creating Space `{hf_profile.username}/{new_repo_name}`...")
|
453 |
state = STATE_CREATING_SPACE # Transition state to creation
|
454 |
repo_name = new_repo_name # Store the validated repo name
|
455 |
+
# Yield updated state variables, passing others through
|
|
|
456 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
457 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
458 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
459 |
|
|
|
|
|
460 |
|
461 |
elif state == STATE_CREATING_SPACE:
|
462 |
# Ensure repo_name is available (it should have been set in the previous step)
|
463 |
if not repo_name:
|
464 |
history = add_bot_message(history, "Internal error: Repo name missing for creation. Resetting.")
|
465 |
+
# Reset state on error, passing through current Gemini state
|
466 |
yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
|
467 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
|
|
468 |
else:
|
469 |
try:
|
|
|
470 |
new_repo_id, iframe_html = create_space_action(repo_name, space_sdk, hf_profile, hf_token)
|
471 |
+
updated_preview = iframe_html
|
472 |
+
repo_id = new_repo_id # Update repo_id state variable
|
473 |
history = add_bot_message(history, f"✅ Space `{repo_id}` created. Click 'Send' to generate and upload code.")
|
474 |
+
state = STATE_GENERATING_CODE
|
475 |
+
# Yield updated state variables, passing others through
|
476 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
477 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
478 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
479 |
except Exception as e:
|
480 |
history = add_bot_message(history, f"❌ Error creating space: {e}. Click 'reset'.")
|
481 |
+
# Reset state on error, passing through current Gemini state
|
482 |
yield (history, None, STATE_IDLE, "<p>Error creating space.</p>", "", "", 0,
|
483 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
484 |
|
485 |
|
486 |
elif state == STATE_GENERATING_CODE:
|
|
|
497 |
history = add_bot_message(history, f"🧠 Generating `{prompt_desc}` `{space_sdk}` app (`app.py`) code with Gemini...")
|
498 |
if use_grounding:
|
499 |
history = add_bot_message(history, "(Using Grounding with Google Search)")
|
500 |
+
# Yield message before API call
|
501 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
502 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
503 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
504 |
|
|
|
|
|
505 |
code = call_gemini(prompt, current_gemini_key, current_gemini_model, use_grounding=use_grounding)
|
506 |
code = code.strip()
|
507 |
+
# Clean up markdown
|
508 |
+
if code.startswith("```python"): code = code[len("```python"):].strip()
|
509 |
+
if code.startswith("```"): code = code[len("```"):].strip()
|
510 |
+
if code.endswith("```"): code = code[:-len("```")].strip()
|
|
|
|
|
|
|
511 |
|
512 |
+
if not code: raise ValueError("Gemini returned empty code.")
|
|
|
513 |
|
514 |
history = add_bot_message(history, "✅ `app.py` code generated. Click 'Send' to upload.")
|
515 |
+
state = STATE_UPLOADING_APP_PY
|
516 |
+
generated_code = code
|
517 |
+
# Yield updated state variables
|
518 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
519 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
520 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
521 |
|
522 |
except Exception as e:
|
523 |
history = add_bot_message(history, f"❌ Error generating code: {e}. Click 'reset'.")
|
524 |
+
# Reset state on error, passing through current Gemini state
|
525 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
526 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
527 |
|
528 |
|
529 |
elif state == STATE_UPLOADING_APP_PY:
|
|
|
532 |
if not code_to_upload:
|
533 |
history = add_bot_message(history, "Internal error: No code to upload. Resetting.")
|
534 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
535 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
|
|
536 |
else:
|
537 |
history = add_bot_message(history, "☁️ Uploading `app.py`...")
|
538 |
+
# Yield message before upload
|
539 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
540 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
541 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
542 |
try:
|
|
|
543 |
upload_file_to_space_action(io.StringIO(code_to_upload), "app.py", repo_id, hf_profile, hf_token)
|
544 |
history = add_bot_message(history, "✅ Uploaded `app.py`. Click 'Send' to generate requirements.")
|
545 |
+
state = STATE_GENERATING_REQUIREMENTS
|
546 |
+
generated_code = None
|
547 |
+
# Yield updated state variables
|
548 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
549 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
550 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
551 |
except Exception as e:
|
552 |
history = add_bot_message(history, f"❌ Error uploading `app.py`: {e}. Click 'reset'.")
|
553 |
+
# Reset state on error, passing through current Gemini state
|
554 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
555 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
556 |
|
557 |
|
558 |
elif state == STATE_GENERATING_REQUIREMENTS:
|
559 |
history = add_bot_message(history, "📄 Generating `requirements.txt`...")
|
560 |
+
# Yield message before generating requirements
|
561 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
562 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
563 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
564 |
|
565 |
# Logic to determine required packages based on SDK and keywords in the app description
|
566 |
reqs_list = ["gradio"] if space_sdk == "gradio" else ["streamlit"]
|
|
|
603 |
# Yield updated state variables and history (pass UI outputs and other states through)
|
604 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
605 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
606 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
607 |
|
608 |
|
609 |
elif state == STATE_UPLOADING_REQUIREMENTS:
|
|
|
612 |
if not reqs_content_to_upload:
|
613 |
history = add_bot_message(history, "Internal error: No requirements content to upload. Resetting.")
|
614 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
615 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
|
|
616 |
else:
|
617 |
history = add_bot_message(history, "☁️ Uploading `requirements.txt`...")
|
618 |
# Yield message before upload (pass UI outputs and states through)
|
619 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
620 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
621 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
622 |
try:
|
623 |
# Perform requirements file upload
|
624 |
upload_file_to_space_action(io.StringIO(reqs_content_to_upload), "requirements.txt", repo_id, hf_profile, hf_token)
|
|
|
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) # Correctly yielding back the received Gemini states
|
|
|
|
|
632 |
except Exception as e:
|
633 |
history = add_bot_message(history, f"❌ Error uploading `requirements.txt`: {e}. Click 'reset'.")
|
634 |
# Yield error message and reset state on failure
|
635 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
636 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
637 |
|
638 |
elif state == STATE_GENERATING_README:
|
639 |
history = add_bot_message(history, "📝 Generating `README.md`...")
|
640 |
# Yield message before generating README (pass UI outputs and states through)
|
641 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
642 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
643 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
644 |
|
645 |
# Generate simple README content with Space metadata header
|
646 |
readme_title = repo_name if repo_name else "My Awesome Space"
|
|
|
669 |
# Yield updated state variables and history (pass UI outputs and other states through)
|
670 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
671 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
672 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
673 |
|
674 |
|
675 |
elif state == STATE_UPLOADING_README:
|
|
|
678 |
if not readme_content_to_upload:
|
679 |
history = add_bot_message(history, "Internal error: No README content to upload. Resetting.")
|
680 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
681 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
|
|
682 |
else:
|
683 |
history = add_bot_message(history, "☁️ Uploading `README.md`...")
|
684 |
# Yield message before upload (pass UI outputs and states through)
|
685 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
686 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
687 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
688 |
try:
|
689 |
# Perform README file upload
|
690 |
upload_file_to_space_action(io.StringIO(readme_content_to_upload), "README.md", repo_id, hf_profile, hf_token)
|
|
|
694 |
# Yield updated state variables and history (pass UI outputs and other states through)
|
695 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
696 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
697 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
698 |
except Exception as e:
|
699 |
history = add_bot_message(history, f"❌ Error uploading `README.md`: {e}. Click 'reset'.")
|
700 |
# Yield error message and reset state on failure
|
701 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
702 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
703 |
|
704 |
elif state == STATE_CHECKING_LOGS_BUILD:
|
705 |
history = add_bot_message(history, "🔍 Fetching build logs...")
|
706 |
# Yield message before fetching logs (which includes a delay) (pass UI outputs and states through)
|
707 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
708 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
709 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
710 |
|
711 |
# Fetch build logs from HF Space
|
712 |
build_logs_text = get_build_logs_action(repo_id, hf_profile, hf_token)
|
|
|
719 |
# Yield updated state, logs, and variables
|
720 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
721 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
722 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
723 |
|
724 |
else:
|
725 |
history = add_bot_message(history, "✅ Build logs fetched. Click 'Send' to check container logs.")
|
|
|
727 |
# Yield updated state, logs, and variables
|
728 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
729 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
730 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
731 |
|
732 |
|
733 |
elif state == STATE_CHECKING_LOGS_RUN:
|
|
|
735 |
# Yield message before fetching logs (includes a delay) (pass UI outputs and states through)
|
736 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
737 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
738 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
739 |
|
740 |
# Fetch container logs from HF Space
|
741 |
container_logs_text = get_container_logs_action(repo_id, hf_profile, hf_token)
|
|
|
749 |
# Yield updated state, logs, attempts, and variables
|
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) # Correctly yielding back the received Gemini states
|
|
|
753 |
|
754 |
elif ("error" in updated_run.lower() or "exception" in updated_run.lower()) and attempts >= MAX_DEBUG_ATTEMPTS:
|
755 |
# Max debug attempts reached
|
|
|
758 |
# Yield updated state, logs, attempts, and variables
|
759 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
760 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
761 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
762 |
|
763 |
else:
|
764 |
# No significant errors found in logs, assume success
|
|
|
767 |
# Yield updated state, logs, attempts, and variables
|
768 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
769 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
770 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
771 |
|
772 |
|
773 |
elif state == STATE_DEBUGGING_CODE:
|
|
|
777 |
# Yield message before Gemini API call (pass UI outputs and states through)
|
778 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
779 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
780 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
781 |
|
782 |
# Construct prompt for Gemini including the container logs
|
783 |
debug_prompt = f"""
|
|
|
814 |
# Yield updated state, code, and variables (pass UI outputs and states through)
|
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) # Correctly yielding back the received Gemini states
|
|
|
818 |
|
819 |
except Exception as e:
|
820 |
history = add_bot_message(history, f"❌ Error generating debug code: {e}. Click 'reset'.")
|
821 |
# Yield error message and reset state on failure
|
822 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
823 |
None, None, None, use_grounding,
|
824 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
825 |
|
826 |
elif state == STATE_UPLOADING_FIXED_APP_PY:
|
827 |
# Retrieve the fixed code from the state variable
|
|
|
829 |
if not fixed_code_to_upload:
|
830 |
history = add_bot_message(history, "Internal error: No fixed code available to upload. Resetting.")
|
831 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
832 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
|
|
833 |
else:
|
834 |
history = add_bot_message(history, "☁️ Uploading fixed `app.py`...")
|
835 |
# Yield message before upload (pass UI outputs and states through)
|
836 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
837 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
838 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
839 |
|
840 |
try:
|
841 |
# Perform the upload of the fixed app.py
|
|
|
846 |
# Yield updated state, code, and variables (pass UI outputs and states through)
|
847 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
848 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
849 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
850 |
|
851 |
except Exception as e:
|
852 |
history = add_bot_message(history, f"❌ Error uploading fixed `app.py`: {e}. Click 'reset'.")
|
853 |
# Yield error message and reset state on failure
|
854 |
yield (history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0,
|
855 |
+
None, None, None, use_grounding, current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
|
|
856 |
|
857 |
elif state == STATE_COMPLETE:
|
858 |
# If in the complete state, the workflow is finished for this project.
|
859 |
# Subsequent clicks just add user messages; we simply yield the current state.
|
860 |
yield (history, repo_id, state, updated_preview, updated_run, updated_build,
|
861 |
attempts, app_desc, repo_name, generated_code, use_grounding,
|
862 |
+
current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
|
|
|
863 |
|
864 |
|
865 |
except Exception as e:
|
|
|
867 |
error_message = f"Workflow step failed unexpectedly ({state}): {e}. Click 'Send' to re-attempt this step or 'reset'."
|
868 |
history = add_bot_message(history, error_message)
|
869 |
print(f"Critical Error in state {state}: {e}") # Log the error for debugging purposes
|
870 |
+
# On unexpected error, reset to IDLE, but pass through the current Gemini state
|
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) # Correctly yielding back the received Gemini states
|
|
|
874 |
|
875 |
|
876 |
# --- Build the Gradio UI ---
|
|
|
880 |
# Define these first as they might be used in default values for components
|
881 |
hf_profile = gr.State(None)
|
882 |
hf_token = gr.State(None)
|
883 |
+
# Initialize gemini_api_key_state to empty string
|
884 |
gemini_api_key_state = gr.State("") # start with no key
|
885 |
+
# Initialize gemini_model_state
|
886 |
gemini_model_state = gr.State("gemini-1.5-flash") # Default selected model
|
887 |
|
888 |
repo_id = gr.State(None) # Stores the ID of the created Space
|
|
|
907 |
|
908 |
gr.Markdown("## Google AI Studio / Gemini")
|
909 |
# Define gemini_input and gemini_status before they are used in change handlers
|
910 |
+
# Blank out textbox on load and update info text
|
911 |
gemini_input = gr.Textbox(
|
912 |
label="Your Google AI Studio API Key", # Changed label
|
913 |
type="password", # Hides input for security
|
|
|
953 |
chatbot = gr.Chatbot(type='messages', label="AI Workflow Chat")
|
954 |
user_input = gr.Textbox(placeholder="Type your message…", interactive=True)
|
955 |
# Define send_btn here, BEFORE it's used in send_button_update_output
|
956 |
+
send_btn = gr.Button("Send", interactive=False) # Start disabled by default
|
957 |
|
958 |
|
959 |
# Define iframe, build_txt, run_txt after send_btn
|
|
|
965 |
|
966 |
# --- Define Event Handlers and Chains AFTER all components and required lists are defined ---
|
967 |
|
968 |
+
# Define the inputs used for checking prerequisites
|
969 |
+
# This list provides the values to the check_send_button_ready function
|
970 |
send_button_interactive_binding_inputs = [
|
971 |
hf_profile,
|
972 |
hf_token,
|
973 |
+
gemini_api_key_state,
|
974 |
+
gemini_model_state
|
975 |
]
|
976 |
# Define the output for updating the send button interactivity
|
|
|
977 |
send_button_update_output = [send_btn]
|
978 |
|
979 |
|
980 |
+
# Trigger check_send_button_ready whenever any prerequisite state changes
|
981 |
+
# Bind the check function directly. The inputs list passes the required state values.
|
|
|
982 |
hf_profile.change(
|
983 |
+
check_send_button_ready, # Call the core check function directly
|
984 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
985 |
outputs=send_button_update_output, # Update only the send button
|
986 |
)
|
987 |
hf_token.change(
|
988 |
+
check_send_button_ready, # Call the core check function directly
|
989 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
990 |
outputs=send_button_update_output, # Update only the send button
|
991 |
)
|
992 |
# gemini_input.change updates gemini_api_key_state, which triggers gemini_api_key_state.change
|
993 |
gemini_api_key_state.change(
|
994 |
+
check_send_button_ready, # Call the core check function directly
|
995 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
996 |
outputs=send_button_update_output, # Update only the send button
|
997 |
)
|
998 |
# model_selector.change updates gemini_model_state, which triggers gemini_model_state.change
|
999 |
gemini_model_state.change(
|
1000 |
+
check_send_button_ready, # Call the core check function directly
|
1001 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
1002 |
outputs=send_button_update_output, # Update only the send button
|
1003 |
)
|
1004 |
|
1005 |
|
1006 |
+
# Handle login button click: Update profile/token state -> Their .change handlers trigger check_send_button_ready
|
1007 |
login_btn.click(
|
1008 |
+
lambda x: (x[0], x[1]), # Lambda takes the LoginButton output (profile, token tuple) and returns it
|
1009 |
inputs=[login_btn],
|
1010 |
+
outputs=[hf_profile, hf_token] # Update state variables
|
1011 |
)
|
1012 |
|
1013 |
+
# Handle Gemini Key Input change: Update key state -> Configure Gemini status -> State .change handler triggers check_send_button_ready
|
1014 |
gemini_input.change(
|
1015 |
+
lambda k: k, # Lambda takes the textbox value and returns it
|
1016 |
inputs=[gemini_input],
|
1017 |
+
outputs=[gemini_api_key_state] # Update state variable
|
1018 |
).then(
|
1019 |
+
# Configure Gemini using the updated state variables
|
1020 |
configure_gemini,
|
1021 |
inputs=[gemini_api_key_state, gemini_model_state],
|
1022 |
+
outputs=[gemini_status] # Update Gemini status display
|
1023 |
)
|
1024 |
|
1025 |
+
# Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> State .change handler triggers check_send_button_ready
|
1026 |
model_selector.change(
|
1027 |
+
lambda m: m, # Lambda takes the radio value and returns it
|
1028 |
inputs=[model_selector],
|
1029 |
+
outputs=[gemini_model_state] # Update state variable
|
1030 |
).then(
|
1031 |
+
# Configure Gemini using the updated state variables
|
1032 |
configure_gemini,
|
1033 |
inputs=[gemini_api_key_state, gemini_model_state],
|
1034 |
+
outputs=[gemini_status] # Update Gemini status display
|
1035 |
)
|
1036 |
|
1037 |
|
|
|
1049 |
workflow.change(lambda s: s, inputs=workflow, outputs=status_text)
|
1050 |
|
1051 |
# Link Repo ID State variable change to UI status display
|
1052 |
+
# This binding seems correct and should update the Textbox with the value of repo_id state.
|
1053 |
+
# The API key appearing here means the API key value is somehow ending up *in* the repo_id state.
|
1054 |
repo_id.change(lambda r: r if r else "None", inputs=repo_id, outputs=repo_id_text)
|
1055 |
|
1056 |
|
|
|
1058 |
# This .click() event triggers the ai_workflow_chat generator function
|
1059 |
# Inputs are read from UI components AND State variables
|
1060 |
# Outputs are updated by the values yielded from the generator
|
1061 |
+
# Ensure inputs and outputs match the ai_workflow_chat signature and yield tuple EXACTLY.
|
|
|
|
|
|
|
1062 |
send_btn.click(
|
1063 |
ai_workflow_chat, # The generator function to run
|
1064 |
inputs=[
|
1065 |
user_input, chatbot, # UI component inputs (message, current chat history)
|
1066 |
hf_profile, hf_token, # HF State variables
|
1067 |
+
gemini_api_key_state, gemini_model_state, # Gemini State variables
|
|
|
1068 |
repo_id, workflow, sdk_state, # Workflow State variables
|
|
|
1069 |
iframe, run_txt, build_txt, # UI component inputs (current values)
|
1070 |
debug_attempts, app_description, repo_name_state, generated_code_state, # Other State variables
|
1071 |
use_grounding_state # Grounding state input
|
1072 |
],
|
1073 |
outputs=[
|
1074 |
+
chatbot, # Updates Chatbot
|
1075 |
+
repo_id, workflow, # Updates State variables (repo_id, workflow)
|
1076 |
+
iframe, run_txt, build_txt, # Updates UI components (iframe, logs)
|
1077 |
+
debug_attempts, app_description, repo_name_state, generated_code_state, # Updates other State variables
|
1078 |
+
use_grounding_state, # Updates Grounding state
|
1079 |
+
gemini_api_key_state, gemini_model_state # Updates Gemini State variables
|
|
|
1080 |
]
|
1081 |
).success( # Chain a .success() event to run *after* the .click() handler completes without error
|
1082 |
# Clear the user input textbox after the message is sent and processed
|
|
|
1090 |
# This chain runs once when the app loads
|
1091 |
ai_builder_tab.load(
|
1092 |
# Action 1: Show profile (loads cached login if available)
|
|
|
|
|
1093 |
show_profile,
|
1094 |
inputs=None,
|
1095 |
outputs=login_status # Updates UI
|
1096 |
).then(
|
1097 |
# Action 2: Configure Gemini using initial state (gemini_api_key_state is "", model_state is default)
|
1098 |
configure_gemini,
|
1099 |
+
inputs=[gemini_api_key_state, gemini_model_state],
|
1100 |
outputs=[gemini_status] # Update Gemini status display
|
1101 |
).then(
|
1102 |
# Action 3: After initial load checks, update the button state based on initial states
|
1103 |
+
# Call check_send_button_ready directly on load with initial state values
|
1104 |
+
check_send_button_ready,
|
1105 |
inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
|
1106 |
outputs=send_button_update_output, # Update the send button
|
1107 |
).then(
|