Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -394,9 +394,14 @@ def orchestrate_development(client, project_state, config, oauth_token_token):
|
|
394 |
current_task = project_state['current_task']
|
395 |
|
396 |
# Add current task to history for UI visibility (if not already added by previous step)
|
397 |
-
|
|
|
|
|
|
|
|
|
398 |
project_state['chat_history'].append({"role": "assistant", "content": f"➡️ Task: {current_task}"})
|
399 |
|
|
|
400 |
step_successful = True # Flag to track if the current step completed without error
|
401 |
|
402 |
if current_task == 'PLANNING':
|
@@ -404,24 +409,32 @@ def orchestrate_development(client, project_state, config, oauth_token_token):
|
|
404 |
if step_successful:
|
405 |
# Add plan to chat history for user (done inside run_planner now?) - moved to run_planner
|
406 |
project_state['current_task'] = 'CODING - Initial Implementation' # Move to coding after planning
|
|
|
|
|
|
|
|
|
407 |
else:
|
408 |
project_state['current_task'] = 'FAILED' # Planning failed
|
409 |
|
410 |
|
411 |
elif current_task.startswith('CODING'):
|
412 |
-
# Ensure
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
|
|
|
|
|
|
|
|
425 |
title: {project_state['repo_id']}
|
426 |
emoji: 🐢
|
427 |
sdk: {project_state['sdk_choice']}
|
@@ -438,7 +451,7 @@ This is an auto-generated HF Space.
|
|
438 |
**Plan:**
|
439 |
{project_state['plan']}
|
440 |
"""
|
441 |
-
|
442 |
|
443 |
|
444 |
step_successful = run_codegen(client, project_state, config)
|
@@ -449,7 +462,7 @@ This is an auto-generated HF Space.
|
|
449 |
# Code-gen failed (syntax error, parsing issue, etc.)
|
450 |
# The failure is handled within run_codegen by setting status_message and feedback
|
451 |
# We'll try debugging/coding again in the next attempt loop iteration if attempts allow
|
452 |
-
print("Code-Gen step failed.")
|
453 |
# attempt_count is incremented AFTER debugging phase analyses results
|
454 |
project_state['current_task'] = 'DEBUGGING' # Go to debugging to analyze the failure
|
455 |
|
@@ -490,13 +503,15 @@ This is an auto-generated HF Space.
|
|
490 |
# Wait a moment for build to start
|
491 |
time.sleep(5) # Initial wait
|
492 |
wait_time = 5
|
493 |
-
max_log_wait =
|
494 |
elapsed_log_wait = 0
|
495 |
logs_fetched = False
|
496 |
iframe_checked = False
|
497 |
|
498 |
project_state['status_message'] = "Fetching logs and checking iframe..."
|
499 |
-
|
|
|
|
|
500 |
|
501 |
|
502 |
while elapsed_log_wait < max_log_wait:
|
@@ -508,7 +523,8 @@ This is an auto-generated HF Space.
|
|
508 |
logs_fetched = True
|
509 |
|
510 |
# Only check iframe once logs indicate something might be running, or after a delay
|
511 |
-
|
|
|
512 |
project_state['iframe_ok'] = check_iframe(project_state['iframe_url'])
|
513 |
iframe_checked = True
|
514 |
else:
|
@@ -518,14 +534,16 @@ This is an auto-generated HF Space.
|
|
518 |
print(f"Log/Iframe check at {elapsed_log_wait}s. Build logs len: {len(build_logs)}, Run logs len: {len(run_logs)}, Iframe OK: {project_state['iframe_ok']}")
|
519 |
|
520 |
# Conditions to proceed to debugging:
|
521 |
-
# 1. Iframe is OK (app is running and accessible)
|
522 |
# 2. Build logs show errors (need debugging ASAP)
|
523 |
# 3. Max wait time is almost reached (proceed with whatever logs we have)
|
524 |
# 4. Build logs exist and indicate *some* progress (e.g., contain "Building" or sufficient length)
|
|
|
525 |
if project_state['iframe_ok'] or \
|
526 |
"ERROR" in build_logs.upper() or "FATAL" in build_logs.upper() or \
|
527 |
elapsed_log_wait >= max_log_wait - wait_time or \
|
528 |
-
("Building" in build_logs or len(build_logs) > 100) and logs_fetched
|
|
|
529 |
break # Exit the log fetching wait loop
|
530 |
else:
|
531 |
print(f"Logs or iframe not ready. Waiting {wait_time}s...")
|
@@ -541,16 +559,16 @@ This is an auto-generated HF Space.
|
|
541 |
wait_time = min(wait_time * 1.5, 20)
|
542 |
|
543 |
|
|
|
544 |
if logs_fetched or iframe_checked: # Proceed if we got logs OR checked the iframe
|
545 |
project_state['status_message'] = "Logs fetched and iframe checked (or timeout reached)."
|
546 |
-
project_state['chat_history'].append({"role": "assistant", "content": project_state['status_message']})
|
547 |
-
project_state['current_task'] = 'DEBUGGING' # Move to debugging to analyze logs
|
548 |
else:
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
|
|
554 |
|
555 |
|
556 |
elif current_task == 'DEBUGGING':
|
@@ -564,23 +582,17 @@ This is an auto-generated HF Space.
|
|
564 |
# Analyze feedback to decide next step
|
565 |
feedback = project_state['feedback']
|
566 |
iframe_ok = project_state.get('iframe_ok', False)
|
567 |
-
# Re-check logs just before making the decision for freshest info if possible
|
568 |
-
# This might add latency, skipping for now, rely on logs fetched in LOGGING step
|
569 |
-
# build_logs = fetch_logs(project_state['repo_id'], "build", oauth_token_token)
|
570 |
-
# run_logs = fetch_logs(project_state['repo_id'], "run", oauth_token_token)
|
571 |
-
# error_types = classify_errors(build_logs + '\n' + run_logs)
|
572 |
-
# project_state['logs']['build'] = build_logs # Update state with freshest logs
|
573 |
-
# project_state['logs']['run'] = run_logs
|
574 |
-
|
575 |
error_types = classify_errors(project_state['logs'].get('build', '') + '\n' + project_state['logs'].get('run', ''))
|
576 |
|
577 |
-
|
578 |
print(f"Debug Analysis - Feedback: {feedback[:100]}... | Iframe OK: {iframe_ok} | Errors: {error_types}")
|
579 |
|
580 |
|
581 |
-
|
582 |
-
|
583 |
-
|
|
|
|
|
|
|
584 |
project_state['status'] = 'Complete'
|
585 |
project_state['current_task'] = 'FINISHED'
|
586 |
project_state['status_message'] = "Debug Agent reports clear. Project appears complete."
|
@@ -606,7 +618,7 @@ This is an auto-generated HF Space.
|
|
606 |
|
607 |
elif current_task == 'FINISHED':
|
608 |
# Exit the main loop
|
609 |
-
|
610 |
|
611 |
else:
|
612 |
# Unknown task
|
@@ -622,9 +634,14 @@ This is an auto-generated HF Space.
|
|
622 |
# the orchestrator logic above should handle transition to FAILED or DEBUGGING.
|
623 |
# This check acts as a safeguard.
|
624 |
if not step_successful and project_state['status'] == 'In Progress':
|
|
|
|
|
|
|
|
|
625 |
project_state['status'] = 'Failed'
|
626 |
-
project_state['status_message'] = project_state.get('status_message', f'An error
|
627 |
-
project_state['
|
|
|
628 |
|
629 |
|
630 |
# --- End of Orchestration Loop ---
|
@@ -638,6 +655,7 @@ This is an auto-generated HF Space.
|
|
638 |
|
639 |
# Add final outcome message to history if not already the last message
|
640 |
final_outcome_message = f"**Project Outcome:** {project_state['status']} - {project_state['status_message']}"
|
|
|
641 |
if not project_state['chat_history'] or project_state['chat_history'][-1].get('content', '').strip() != final_outcome_message.strip():
|
642 |
project_state['chat_history'].append({"role": "assistant", "content": final_outcome_message})
|
643 |
|
@@ -664,8 +682,10 @@ This is an auto-generated HF Space.
|
|
664 |
|
665 |
# --- MAIN HANDLER (Called by Gradio) ---
|
666 |
|
|
|
667 |
def handle_user_message(
|
668 |
-
history, # This is the list of messages in the Gradio Chatbot
|
|
|
669 |
sdk_choice: str,
|
670 |
gemini_api_key: str,
|
671 |
grounding_enabled: bool,
|
@@ -674,16 +694,17 @@ def handle_user_message(
|
|
674 |
profile: gr.OAuthProfile | None,
|
675 |
oauth_token: gr.OAuthToken | None # We need the token object
|
676 |
):
|
677 |
-
#
|
678 |
-
#
|
679 |
-
#
|
680 |
-
# Check if the last message is
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
|
|
687 |
|
688 |
if not profile or not oauth_token or not oauth_token.token:
|
689 |
# Append error message to history for display
|
@@ -695,6 +716,11 @@ def handle_user_message(
|
|
695 |
error_history = history + [{"role":"assistant","content":"⚠️ Please provide your Gemini API Key."}]
|
696 |
return error_history, "", "", "<p>Please provide API Key.</p>", "API Key required."
|
697 |
|
|
|
|
|
|
|
|
|
|
|
698 |
|
699 |
client = genai.Client(api_key=gemini_api_key)
|
700 |
repo_id = f"{profile.username}/{profile.username}-auto-space"
|
@@ -702,14 +728,8 @@ def handle_user_message(
|
|
702 |
sdk_version = get_sdk_version(sdk_choice)
|
703 |
code_fn = "app.py" if sdk_choice == "gradio" else "streamlit_app.py" # Standard main file name convention
|
704 |
|
705 |
-
#
|
706 |
-
|
707 |
-
user_prompt = history[-1]['content'] if history and history[-1].get("role") == "user" else "No prompt provided."
|
708 |
-
|
709 |
-
if user_prompt == "No prompt provided." or user_prompt.strip() == "":
|
710 |
-
# Handle empty prompt case
|
711 |
-
empty_prompt_history = history + [{"role":"assistant","content":"Please enter requirements for the application."}]
|
712 |
-
return empty_prompt_history, "", "", "<p>Enter requirements.</p>", "Waiting for prompt."
|
713 |
|
714 |
|
715 |
# Initialize project state for this development session
|
@@ -762,7 +782,7 @@ with gr.Blocks(title="HF Space Auto‑Builder (Team AI)") as demo:
|
|
762 |
|
763 |
with gr.Row():
|
764 |
with gr.Column(scale=1):
|
765 |
-
# --- LOGIN BUTTON / PROFILE & MODEL LISTING
|
766 |
login_btn = gr.LoginButton(variant="huggingface", size="lg")
|
767 |
status_md = gr.Markdown("*Not logged in.*")
|
768 |
models_md = gr.Markdown()
|
@@ -784,7 +804,7 @@ with gr.Blocks(title="HF Space Auto‑Builder (Team AI)") as demo:
|
|
784 |
outputs=models_md,
|
785 |
api_name="login_models"
|
786 |
)
|
787 |
-
# --- END FIX ---
|
788 |
|
789 |
|
790 |
gr.Markdown("---")
|
@@ -812,17 +832,37 @@ with gr.Blocks(title="HF Space Auto‑Builder (Team AI)") as demo:
|
|
812 |
preview = gr.HTML("<p>App preview will load here when available.</p>")
|
813 |
|
814 |
|
815 |
-
# Update the button click handler
|
816 |
-
# It will now return the updated chatbot history, logs, preview, and the project status
|
817 |
-
# Inputs=None allows Gradio to inject profile/token from login_btn
|
818 |
send_btn.click(
|
819 |
fn=handle_user_message,
|
820 |
-
inputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
821 |
outputs=[chatbot, build_box, run_box, preview, project_status_md]
|
822 |
)
|
|
|
|
|
823 |
user_in.submit(
|
824 |
fn=handle_user_message,
|
825 |
-
inputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
826 |
outputs=[chatbot, build_box, run_box, preview, project_status_md]
|
827 |
)
|
828 |
|
|
|
394 |
current_task = project_state['current_task']
|
395 |
|
396 |
# Add current task to history for UI visibility (if not already added by previous step)
|
397 |
+
# Avoid adding duplicate "➡️ Task" messages immediately
|
398 |
+
if not project_state['chat_history'] or (
|
399 |
+
project_state['chat_history'][-1].get('content', '').strip().replace('➡️ Task: ', '') != current_task.strip().replace('➡️ Task: ', '')
|
400 |
+
or not project_state['chat_history'][-1].get('content', '').startswith('➡️ Task:')
|
401 |
+
):
|
402 |
project_state['chat_history'].append({"role": "assistant", "content": f"➡️ Task: {current_task}"})
|
403 |
|
404 |
+
|
405 |
step_successful = True # Flag to track if the current step completed without error
|
406 |
|
407 |
if current_task == 'PLANNING':
|
|
|
409 |
if step_successful:
|
410 |
# Add plan to chat history for user (done inside run_planner now?) - moved to run_planner
|
411 |
project_state['current_task'] = 'CODING - Initial Implementation' # Move to coding after planning
|
412 |
+
# Add plan to chat history if it wasn't added by run_planner (depends on its implementation)
|
413 |
+
if project_state['plan'] and not any("**Plan:**" in msg['content'] for msg in project_state['chat_history']):
|
414 |
+
project_state['chat_history'].append({"role": "assistant", "content": f"**Plan:**\n{project_state['plan']}"})
|
415 |
+
|
416 |
else:
|
417 |
project_state['current_task'] = 'FAILED' # Planning failed
|
418 |
|
419 |
|
420 |
elif current_task.startswith('CODING'):
|
421 |
+
# Ensure minimum files exist before asking CodeGen to code
|
422 |
+
# This happens once at the start of the first coding task
|
423 |
+
if project_state['attempt_count'] == 0 and project_state['current_task'] == 'CODING - Initial Implementation':
|
424 |
+
# Add initial stub files if they don't exist
|
425 |
+
if project_state['main_app_file'] not in project_state['files']:
|
426 |
+
project_state['files'][project_state['main_app_file']] = f"# Initial {project_state['sdk_choice']} app file\n" # Start with a basic stub
|
427 |
+
if project_state['sdk_choice'] == 'gradio':
|
428 |
+
project_state['files'][project_state['main_app_file']] += "import gradio as gr\n\n# Define a simple interface\n# For example: gr.Interface(...).launch()\n"
|
429 |
+
elif project_state['sdk_choice'] == 'streamlit':
|
430 |
+
project_state['files'][project_state['main_app_file']] += "import streamlit as st\n\n# Your Streamlit app starts here\n# For example: st.write('Hello, world!')\n"
|
431 |
+
|
432 |
+
if 'requirements.txt' not in project_state['files']:
|
433 |
+
req_content = "pandas\n" + ("streamlit\n" if project_state['sdk_choice']=="streamlit" else "gradio\n") + "google-generativeai\nhuggingface-hub\n"
|
434 |
+
project_state['files']['requirements.txt'] = req_content
|
435 |
+
|
436 |
+
if 'README.md' not in project_state['files']:
|
437 |
+
readme_content = f"""---
|
438 |
title: {project_state['repo_id']}
|
439 |
emoji: 🐢
|
440 |
sdk: {project_state['sdk_choice']}
|
|
|
451 |
**Plan:**
|
452 |
{project_state['plan']}
|
453 |
"""
|
454 |
+
project_state['files']['README.md'] = readme_content
|
455 |
|
456 |
|
457 |
step_successful = run_codegen(client, project_state, config)
|
|
|
462 |
# Code-gen failed (syntax error, parsing issue, etc.)
|
463 |
# The failure is handled within run_codegen by setting status_message and feedback
|
464 |
# We'll try debugging/coding again in the next attempt loop iteration if attempts allow
|
465 |
+
print("Code-Gen step failed. Moving to Debugging.")
|
466 |
# attempt_count is incremented AFTER debugging phase analyses results
|
467 |
project_state['current_task'] = 'DEBUGGING' # Go to debugging to analyze the failure
|
468 |
|
|
|
503 |
# Wait a moment for build to start
|
504 |
time.sleep(5) # Initial wait
|
505 |
wait_time = 5
|
506 |
+
max_log_wait = 120 # Maximum total time to wait for logs in this step (increased slightly more)
|
507 |
elapsed_log_wait = 0
|
508 |
logs_fetched = False
|
509 |
iframe_checked = False
|
510 |
|
511 |
project_state['status_message'] = "Fetching logs and checking iframe..."
|
512 |
+
# Check if the message is already the last one to avoid spamming
|
513 |
+
if not project_state['chat_history'] or project_state['chat_history'][-1].get('content', '').strip() != project_state['status_message'].strip():
|
514 |
+
project_state['chat_history'].append({"role": "assistant", "content": project_state['status_message']})
|
515 |
|
516 |
|
517 |
while elapsed_log_wait < max_log_wait:
|
|
|
523 |
logs_fetched = True
|
524 |
|
525 |
# Only check iframe once logs indicate something might be running, or after a delay
|
526 |
+
# Check iframe more frequently after initial wait
|
527 |
+
if elapsed_log_wait > 10 or len(run_logs) > 0:
|
528 |
project_state['iframe_ok'] = check_iframe(project_state['iframe_url'])
|
529 |
iframe_checked = True
|
530 |
else:
|
|
|
534 |
print(f"Log/Iframe check at {elapsed_log_wait}s. Build logs len: {len(build_logs)}, Run logs len: {len(run_logs)}, Iframe OK: {project_state['iframe_ok']}")
|
535 |
|
536 |
# Conditions to proceed to debugging:
|
537 |
+
# 1. Iframe is OK (app is running and accessible) - strongest signal
|
538 |
# 2. Build logs show errors (need debugging ASAP)
|
539 |
# 3. Max wait time is almost reached (proceed with whatever logs we have)
|
540 |
# 4. Build logs exist and indicate *some* progress (e.g., contain "Building" or sufficient length)
|
541 |
+
# 5. Run logs exist (app is at least trying to run)
|
542 |
if project_state['iframe_ok'] or \
|
543 |
"ERROR" in build_logs.upper() or "FATAL" in build_logs.upper() or \
|
544 |
elapsed_log_wait >= max_log_wait - wait_time or \
|
545 |
+
("Building" in build_logs or len(build_logs) > 100) and logs_fetched or \
|
546 |
+
len(run_logs) > 0:
|
547 |
break # Exit the log fetching wait loop
|
548 |
else:
|
549 |
print(f"Logs or iframe not ready. Waiting {wait_time}s...")
|
|
|
559 |
wait_time = min(wait_time * 1.5, 20)
|
560 |
|
561 |
|
562 |
+
# Update status message after the wait loop
|
563 |
if logs_fetched or iframe_checked: # Proceed if we got logs OR checked the iframe
|
564 |
project_state['status_message'] = "Logs fetched and iframe checked (or timeout reached)."
|
|
|
|
|
565 |
else:
|
566 |
+
project_state['status_message'] = "Warning: Could not fetch logs or check iframe status within timeout." # Use Warning status message
|
567 |
+
step_successful = False # Indicate that this step didn't fully succeed
|
568 |
+
|
569 |
+
|
570 |
+
project_state['chat_history'].append({"role": "assistant", "content": project_state['status_message']})
|
571 |
+
project_state['current_task'] = 'DEBUGGING' # Always move to debugging after attempting to log/check
|
572 |
|
573 |
|
574 |
elif current_task == 'DEBUGGING':
|
|
|
582 |
# Analyze feedback to decide next step
|
583 |
feedback = project_state['feedback']
|
584 |
iframe_ok = project_state.get('iframe_ok', False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
585 |
error_types = classify_errors(project_state['logs'].get('build', '') + '\n' + project_state['logs'].get('run', ''))
|
586 |
|
|
|
587 |
print(f"Debug Analysis - Feedback: {feedback[:100]}... | Iframe OK: {iframe_ok} | Errors: {error_types}")
|
588 |
|
589 |
|
590 |
+
# Decision Logic:
|
591 |
+
# 1. Success? Debugger says clear AND iframe works AND no/minor errors in logs
|
592 |
+
is_complete = ("All clear. Project appears complete." in feedback) or \
|
593 |
+
(iframe_ok and error_types == "none" and "ERROR" not in feedback.upper() and len(project_state['logs'].get('run', '')) > 0) # Appears to run and no errors
|
594 |
+
|
595 |
+
if is_complete:
|
596 |
project_state['status'] = 'Complete'
|
597 |
project_state['current_task'] = 'FINISHED'
|
598 |
project_state['status_message'] = "Debug Agent reports clear. Project appears complete."
|
|
|
618 |
|
619 |
elif current_task == 'FINISHED':
|
620 |
# Exit the main loop
|
621 |
+
break # Loop condition handles exit
|
622 |
|
623 |
else:
|
624 |
# Unknown task
|
|
|
634 |
# the orchestrator logic above should handle transition to FAILED or DEBUGGING.
|
635 |
# This check acts as a safeguard.
|
636 |
if not step_successful and project_state['status'] == 'In Progress':
|
637 |
+
# This case might occur if a sub-function returns False but doesn't set status='Failed'
|
638 |
+
# The logic above *should* set status_message and transition away from the failed task,
|
639 |
+
# but this ensures the overall loop exits if something goes wrong.
|
640 |
+
print(f"Orchestration step '{current_task}' failed, but status is still 'In Progress'. Forcing Failure.")
|
641 |
project_state['status'] = 'Failed'
|
642 |
+
project_state['status_message'] = project_state.get('status_message', f'An unexpected error caused task failure: {current_task}')
|
643 |
+
project_state['chat_history'].append({"role": "assistant", "content": project_state['status_message']})
|
644 |
+
project_state['current_task'] = 'FINISHED'
|
645 |
|
646 |
|
647 |
# --- End of Orchestration Loop ---
|
|
|
655 |
|
656 |
# Add final outcome message to history if not already the last message
|
657 |
final_outcome_message = f"**Project Outcome:** {project_state['status']} - {project_state['status_message']}"
|
658 |
+
# Prevent adding duplicate messages if they were already added inside the loop
|
659 |
if not project_state['chat_history'] or project_state['chat_history'][-1].get('content', '').strip() != final_outcome_message.strip():
|
660 |
project_state['chat_history'].append({"role": "assistant", "content": final_outcome_message})
|
661 |
|
|
|
682 |
|
683 |
# --- MAIN HANDLER (Called by Gradio) ---
|
684 |
|
685 |
+
# Updated signature to include user_input
|
686 |
def handle_user_message(
|
687 |
+
history, # This is the list of messages in the Gradio Chatbot (from previous turns)
|
688 |
+
user_input: str, # <--- The *new* text input from the user_in textbox
|
689 |
sdk_choice: str,
|
690 |
gemini_api_key: str,
|
691 |
grounding_enabled: bool,
|
|
|
694 |
profile: gr.OAuthProfile | None,
|
695 |
oauth_token: gr.OAuthToken | None # We need the token object
|
696 |
):
|
697 |
+
# The user_input is already the new prompt.
|
698 |
+
# We need to add it to the history list here at the beginning,
|
699 |
+
# as Gradio's Chatbot expects the handler to return the *updated* history.
|
700 |
+
# Check if the last message is *not* a user message or is empty to avoid duplicates
|
701 |
+
# (Gradio's default Chatbot adds the user message automatically on submit,
|
702 |
+
# but explicit handling here is safer if using user_in separately)
|
703 |
+
if not history or history[-1].get("role") != "user" or history[-1].get("content") != user_input:
|
704 |
+
history.append({"role": "user", "content": user_input})
|
705 |
+
# Note: If Gradio Chatbot already adds the message, this might cause duplicates.
|
706 |
+
# In typical chatbot+textbox setup, the textbox value is passed explicitly,
|
707 |
+
# and the handler is responsible for appending it to the history.
|
708 |
|
709 |
if not profile or not oauth_token or not oauth_token.token:
|
710 |
# Append error message to history for display
|
|
|
716 |
error_history = history + [{"role":"assistant","content":"⚠️ Please provide your Gemini API Key."}]
|
717 |
return error_history, "", "", "<p>Please provide API Key.</p>", "API Key required."
|
718 |
|
719 |
+
if not user_input or user_input.strip() == "":
|
720 |
+
# Handle empty prompt case - the prompt is now the user_input parameter
|
721 |
+
empty_prompt_history = history + [{"role":"assistant","content":"Please enter requirements for the application."}]
|
722 |
+
return empty_prompt_history, "", "", "<p>Enter requirements.</p>", "Waiting for prompt."
|
723 |
+
|
724 |
|
725 |
client = genai.Client(api_key=gemini_api_key)
|
726 |
repo_id = f"{profile.username}/{profile.username}-auto-space"
|
|
|
728 |
sdk_version = get_sdk_version(sdk_choice)
|
729 |
code_fn = "app.py" if sdk_choice == "gradio" else "streamlit_app.py" # Standard main file name convention
|
730 |
|
731 |
+
# The user's latest prompt is the user_input parameter
|
732 |
+
user_prompt = user_input
|
|
|
|
|
|
|
|
|
|
|
|
|
733 |
|
734 |
|
735 |
# Initialize project state for this development session
|
|
|
782 |
|
783 |
with gr.Row():
|
784 |
with gr.Column(scale=1):
|
785 |
+
# --- LOGIN BUTTON / PROFILE & MODEL LISTING ---
|
786 |
login_btn = gr.LoginButton(variant="huggingface", size="lg")
|
787 |
status_md = gr.Markdown("*Not logged in.*")
|
788 |
models_md = gr.Markdown()
|
|
|
804 |
outputs=models_md,
|
805 |
api_name="login_models"
|
806 |
)
|
807 |
+
# --- END LOGIN FIX ---
|
808 |
|
809 |
|
810 |
gr.Markdown("---")
|
|
|
832 |
preview = gr.HTML("<p>App preview will load here when available.</p>")
|
833 |
|
834 |
|
835 |
+
# Update the button click handler - ADD user_in to inputs
|
|
|
|
|
836 |
send_btn.click(
|
837 |
fn=handle_user_message,
|
838 |
+
inputs=[
|
839 |
+
chatbot, # history (passed automatically by chatbot)
|
840 |
+
user_in, # <-- user_input (pass the textbox component)
|
841 |
+
sdk_choice,
|
842 |
+
api_key,
|
843 |
+
grounding,
|
844 |
+
temp,
|
845 |
+
max_tokens,
|
846 |
+
login_btn, # profile (passed automatically by LoginButton)
|
847 |
+
login_btn # oauth_token (passed automatically by LoginButton)
|
848 |
+
],
|
849 |
outputs=[chatbot, build_box, run_box, preview, project_status_md]
|
850 |
)
|
851 |
+
|
852 |
+
# Update the submit handler - ADD user_in to inputs
|
853 |
user_in.submit(
|
854 |
fn=handle_user_message,
|
855 |
+
inputs=[
|
856 |
+
chatbot, # history
|
857 |
+
user_in, # <-- user_input
|
858 |
+
sdk_choice,
|
859 |
+
api_key,
|
860 |
+
grounding,
|
861 |
+
temp,
|
862 |
+
max_tokens,
|
863 |
+
login_btn,
|
864 |
+
login_btn
|
865 |
+
],
|
866 |
outputs=[chatbot, build_box, run_box, preview, project_status_md]
|
867 |
)
|
868 |
|