akhaliq HF Staff commited on
Commit
0937a16
Β·
1 Parent(s): aaea78f

update space deploy

Browse files
Files changed (1) hide show
  1. app.py +210 -648
app.py CHANGED
@@ -18,7 +18,7 @@ import json
18
  import time
19
 
20
  import gradio as gr
21
- from huggingface_hub import InferenceClient, HfApi, create_repo
22
  from tavily import TavilyClient
23
 
24
  # Configuration
@@ -172,9 +172,6 @@ client = InferenceClient(
172
  History = List[Tuple[str, str]]
173
  Messages = List[Dict[str, str]]
174
 
175
- # HF API Client for deployment
176
- hf_api = HfApi(token=HF_TOKEN)
177
-
178
  # Tavily Search Client
179
  TAVILY_API_KEY = os.getenv('TAVILY_API_KEY')
180
  tavily_client = None
@@ -185,556 +182,6 @@ if TAVILY_API_KEY:
185
  print(f"Failed to initialize Tavily client: {e}")
186
  tavily_client = None
187
 
188
- def validate_oauth_scopes(oauth_token) -> Tuple[bool, List[str]]:
189
- """
190
- Validate that the OAuth token has the required scopes for creating spaces
191
- Returns (is_valid, missing_scopes)
192
- """
193
- required_scopes = ['read-repos', 'write-repos', 'manage-repos']
194
-
195
- if not oauth_token:
196
- return False, required_scopes
197
-
198
- # Try to get scopes from the token object
199
- token_scopes = []
200
-
201
- # Check different ways scopes might be stored
202
- if hasattr(oauth_token, 'scopes'):
203
- token_scopes = oauth_token.scopes
204
- elif hasattr(oauth_token, 'scope'):
205
- token_scopes = oauth_token.scope.split(' ') if oauth_token.scope else []
206
- elif hasattr(oauth_token, 'permissions'):
207
- token_scopes = oauth_token.permissions
208
- else:
209
- # If we can't determine scopes, assume they're missing
210
- return False, required_scopes
211
-
212
- # Convert to list if it's a string
213
- if isinstance(token_scopes, str):
214
- token_scopes = token_scopes.split(' ')
215
-
216
- # Check for required scopes
217
- missing_scopes = [scope for scope in required_scopes if scope not in token_scopes]
218
-
219
- return len(missing_scopes) == 0, missing_scopes
220
-
221
- # Deployment functions
222
- def create_space_from_html(title: str, html_content: str, prompts: List[str] = None, user_token: str = None, username: str = None) -> Dict:
223
- """
224
- Create a Hugging Face Space from generated HTML content
225
- """
226
- try:
227
- # Use user token if provided, otherwise fall back to server token
228
- api_token = user_token if user_token else HF_TOKEN
229
-
230
- if not api_token:
231
- return {
232
- "success": False,
233
- "error": "No Hugging Face token available",
234
- "message": "Please log in with your Hugging Face account to deploy"
235
- }
236
-
237
- # Create API client with user token
238
- user_hf_api = HfApi(token=api_token)
239
-
240
- # Debug: Test the token by getting user info
241
- try:
242
- user_info = user_hf_api.whoami()
243
- print(f"Debug: User info from API: {user_info}")
244
- if not username:
245
- username = user_info.get('name', 'user')
246
- print(f"Debug: Final username: {username}")
247
-
248
- # Additional validation
249
- if not username or username == 'user':
250
- return {
251
- "success": False,
252
- "error": "Could not retrieve username from token",
253
- "message": "The authentication token is valid but username could not be retrieved. Please try logging in again."
254
- }
255
-
256
- except Exception as e:
257
- print(f"Debug: Could not get user info: {e}")
258
- return {
259
- "success": False,
260
- "error": f"Invalid or expired token: {str(e)}",
261
- "message": "Please check your Hugging Face token and try logging in again"
262
- }
263
-
264
- # Clean the title for use as repo name
265
- clean_title = re.sub(r'[^a-zA-Z0-9_-]', '-', title.lower())
266
- clean_title = re.sub(r'-+', '-', clean_title).strip('-')
267
-
268
- # Add timestamp to ensure uniqueness
269
- timestamp = int(time.time())
270
- repo_name = f"{username}/{clean_title}-{timestamp}"
271
-
272
- print(f"Debug: Attempting to create space: {repo_name}")
273
- print(f"Debug: Using token for user: {username}")
274
-
275
- # Create the space
276
- try:
277
- print(f"Debug: Creating space with parameters:")
278
- print(f" repo_id: {repo_name}")
279
- print(f" repo_type: space")
280
- print(f" space_sdk: static")
281
- print(f" private: False")
282
- print(f" exist_ok: False")
283
- print(f" token length: {len(api_token) if api_token else 0}")
284
-
285
- repo_url = user_hf_api.create_repo(
286
- repo_id=repo_name,
287
- repo_type="space",
288
- space_sdk="static",
289
- private=False,
290
- exist_ok=False,
291
- token=api_token
292
- )
293
- print(f"Debug: Successfully created space: {repo_url}")
294
- except Exception as e:
295
- print(f"Debug: Failed to create space: {e}")
296
- print(f"Debug: Exception type: {type(e)}")
297
- print(f"Debug: Exception args: {e.args}")
298
- raise e
299
-
300
- # Prepare the HTML content with proper structure
301
- html_template = """<!DOCTYPE html>
302
- <html lang="en">
303
- <head>
304
- <meta charset="UTF-8">
305
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
306
- <title>{title}</title>
307
- <style>
308
- body {{
309
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
310
- margin: 0;
311
- padding: 20px;
312
- background-color: #f5f5f5;
313
- }}
314
- .container {{
315
- max-width: 1200px;
316
- margin: 0 auto;
317
- background: white;
318
- padding: 20px;
319
- border-radius: 8px;
320
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
321
- }}
322
- .header {{
323
- text-align: center;
324
- margin-bottom: 30px;
325
- padding-bottom: 20px;
326
- border-bottom: 2px solid #f0f0f0;
327
- }}
328
- .header h1 {{
329
- color: #333;
330
- margin: 0;
331
- }}
332
- .header p {{
333
- color: #666;
334
- margin: 10px 0 0 0;
335
- }}
336
- .content {{
337
- line-height: 1.6;
338
- }}
339
- .footer {{
340
- margin-top: 40px;
341
- padding-top: 20px;
342
- border-top: 1px solid #f0f0f0;
343
- text-align: center;
344
- color: #666;
345
- font-size: 14px;
346
- }}
347
- </style>
348
- </head>
349
- <body>
350
- <div class="container">
351
- <div class="header">
352
- <h1>{title}</h1>
353
- <p>Generated with AnyCoder - AI Code Generator</p>
354
- </div>
355
- <div class="content">
356
- {html_content}
357
- </div>
358
- <div class="footer">
359
- <p>Created with ❀️ using AnyCoder</p>
360
- </div>
361
- </div>
362
- </body>
363
- </html>"""
364
-
365
- full_html = html_template.format(title=title, html_content=html_content)
366
-
367
- # Check HTML content size
368
- html_size = len(full_html.encode('utf-8'))
369
- print(f"Debug: HTML content size: {html_size} bytes")
370
-
371
- if html_size > 1000000: # 1MB limit
372
- print(f"Debug: Warning - HTML content is large ({html_size} bytes)")
373
- # Truncate if too large
374
- if len(html_content) > 500000: # 500KB limit for content
375
- html_content = html_content[:500000] + "\n<!-- Content truncated due to size -->"
376
- full_html = html_template.format(title=title, html_content=html_content)
377
- print(f"Debug: HTML content truncated to {len(full_html.encode('utf-8'))} bytes")
378
-
379
- # Upload the HTML file
380
- print(f"Debug: Uploading index.html to {repo_name}")
381
- user_hf_api.upload_file(
382
- path_or_fileobj=full_html.encode('utf-8'),
383
- path_in_repo="index.html",
384
- repo_id=repo_name,
385
- repo_type="space",
386
- token=api_token
387
- )
388
- print(f"Debug: Successfully uploaded index.html")
389
-
390
- # Create README.md with project info
391
- prompts_text = "".join([f"- {prompt}\n" for prompt in (prompts or [])])
392
- readme_template = """# {title}
393
-
394
- This project was generated using [AnyCoder](https://huggingface.co/spaces/ahsenkhaliq/anycoder), an AI-powered code generator.
395
-
396
- ## About
397
-
398
- This is a static HTML application created by describing the requirements in plain English to an AI model.
399
-
400
- ## Generated Prompts
401
-
402
- {prompts_text}
403
-
404
- ## View Live
405
-
406
- Visit: https://huggingface.co/spaces/{repo_name}
407
-
408
- ---
409
- *Generated with ❀️ using AnyCoder*
410
- """
411
-
412
- readme_content = readme_template.format(title=title, prompts_text=prompts_text, repo_name=repo_name)
413
-
414
- print(f"Debug: Uploading README.md to {repo_name}")
415
- user_hf_api.upload_file(
416
- path_or_fileobj=readme_content.encode('utf-8'),
417
- path_in_repo="README.md",
418
- repo_id=repo_name,
419
- repo_type="space",
420
- token=api_token
421
- )
422
- print(f"Debug: Successfully uploaded README.md")
423
-
424
- return {
425
- "success": True,
426
- "space_url": f"https://huggingface.co/spaces/{repo_name}",
427
- "repo_name": repo_name,
428
- "message": f"Successfully created space: {title}"
429
- }
430
-
431
- except Exception as e:
432
- error_msg = str(e)
433
-
434
- # Handle specific API errors
435
- if "401" in error_msg or "Unauthorized" in error_msg:
436
- return {
437
- "success": False,
438
- "error": "Authentication failed - please log in again",
439
- "message": "Your token may have expired. Please log out and log back in."
440
- }
441
- elif "403" in error_msg or "Forbidden" in error_msg:
442
- return {
443
- "success": False,
444
- "error": "Permission denied - insufficient privileges",
445
- "message": "You may not have permission to create spaces. Please check your Hugging Face account settings."
446
- }
447
- elif "409" in error_msg or "Conflict" in error_msg:
448
- return {
449
- "success": False,
450
- "error": "Repository already exists",
451
- "message": "A space with this name already exists. Please try a different title."
452
- }
453
- elif "422" in error_msg or "Validation" in error_msg:
454
- return {
455
- "success": False,
456
- "error": "Invalid repository name",
457
- "message": "The space title contains invalid characters. Please use only letters, numbers, hyphens, and underscores."
458
- }
459
- else:
460
- return {
461
- "success": False,
462
- "error": error_msg,
463
- "message": f"Failed to create space: {error_msg}"
464
- }
465
-
466
- def deploy_to_space(title: str, html_content: str, history: History, oauth_profile: gr.OAuthProfile = None, oauth_token: gr.OAuthToken = None) -> Tuple[str, str]:
467
- """
468
- Deploy the generated HTML to a Hugging Face Space
469
- """
470
- if not title or not title.strip():
471
- return "❌ Please enter a title for your space.", update_oauth_status(oauth_profile, oauth_token)
472
-
473
- if not html_content or not html_content.strip():
474
- return "❌ No HTML content to deploy. Please generate some code first.", update_oauth_status(oauth_profile, oauth_token)
475
-
476
- # Check if user is authenticated
477
- if not oauth_profile or not oauth_token:
478
- return """❌ **Authentication Required**
479
-
480
- To deploy your application, you need to be logged in with your Hugging Face account.
481
-
482
- **How to log in:**
483
- 1. Click the "Sign in with Hugging Face" button in the sidebar
484
- 2. Authorize AnyCoder to access your Hugging Face account with the required permissions:
485
- - read-repos
486
- - write-repos
487
- - manage-repos
488
- 3. Try deploying again
489
-
490
- **Why login is required:**
491
- - Deployments are created under your own Hugging Face account
492
- - You need write permissions to create spaces
493
- - This ensures you own and can manage your deployed applications
494
-
495
- **Note:** Make sure to grant all the requested permissions when authorizing the application.
496
-
497
- ---
498
- *Please log in and try again.*""", update_oauth_status(oauth_profile, oauth_token)
499
-
500
- # Get user information from OAuth profile
501
- username = oauth_profile.name
502
- user_token = oauth_token.token
503
-
504
- # Debug: Print token info (without exposing the actual token)
505
- print(f"Debug: Username from OAuth: {username}")
506
- print(f"Debug: Token type: {type(user_token)}")
507
- print(f"Debug: Token length: {len(user_token) if user_token else 0}")
508
- print(f"Debug: Token starts with: {user_token[:10] if user_token else 'None'}...")
509
-
510
- # Additional debugging for OAuth components
511
- print(f"Debug: OAuth profile type: {type(oauth_profile)}")
512
- print(f"Debug: OAuth token type: {type(oauth_token)}")
513
- print(f"Debug: OAuth profile attributes: {dir(oauth_profile) if oauth_profile else 'None'}")
514
- print(f"Debug: OAuth token attributes: {dir(oauth_token) if oauth_token else 'None'}")
515
-
516
- # Check OAuth token scopes if available
517
- if hasattr(oauth_token, 'scopes'):
518
- print(f"Debug: OAuth token scopes: {oauth_token.scopes}")
519
- else:
520
- print("Debug: OAuth token scopes not available")
521
-
522
- # Check OAuth profile permissions if available
523
- if hasattr(oauth_profile, 'permissions'):
524
- print(f"Debug: OAuth profile permissions: {oauth_profile.permissions}")
525
- else:
526
- print("Debug: OAuth profile permissions not available")
527
-
528
- # Validate OAuth scopes
529
- scopes_valid, missing_scopes = validate_oauth_scopes(oauth_token)
530
- print(f"Debug: OAuth scopes valid: {scopes_valid}")
531
- print(f"Debug: Missing scopes: {missing_scopes}")
532
-
533
- if not scopes_valid:
534
- return f"""❌ **Missing OAuth Scopes**
535
-
536
- Your OAuth token is missing the required permissions to create spaces.
537
-
538
- **Missing Scopes:**
539
- {chr(10).join([f"- `{scope}`" for scope in missing_scopes])}
540
-
541
- **Required Scopes:**
542
- - `read-repos` - Read access to repositories
543
- - `write-repos` - Write access to create repositories
544
- - `manage-repos` - Manage repository settings
545
-
546
- **Steps to fix:**
547
- 1. **Logout**: Click the logout button in the sidebar
548
- 2. **Login Again**: Click "Sign in with Hugging Face" again
549
- 3. **Grant All Permissions**: When the authorization page appears, make sure to check ALL the requested permissions:
550
- - βœ… read-repos
551
- - βœ… write-repos
552
- - βœ… manage-repos
553
- 4. **Complete Authorization**: Click "Authorize" to complete the login
554
- 5. **Try Deploying**: Try deploying again
555
-
556
- **Important:** Make sure you see all three permissions checked on the authorization page before clicking "Authorize".
557
-
558
- ---
559
- *Please log in again with full permissions.*""", update_oauth_status(oauth_profile, oauth_token)
560
-
561
- # Validate token format
562
- if not user_token or not user_token.startswith('hf_'):
563
- return """❌ **Invalid Token Format**
564
-
565
- The OAuth token appears to be invalid or in the wrong format. Please try logging out and logging back in.
566
-
567
- **Steps to fix:**
568
- 1. Click the logout button in the sidebar
569
- 2. Click "Sign in with Hugging Face" again
570
- 3. Authorize the application with the required permissions (read-repos, write-repos, manage-repos)
571
- 4. Try deploying again
572
-
573
- **Note:** Make sure you authorize all the required permissions when logging in.
574
-
575
- ---
576
- *Please try logging in again.*""", update_oauth_status(oauth_profile, oauth_token)
577
-
578
- # Test the token by making a simple API call
579
- try:
580
- test_api = HfApi(token=user_token)
581
- user_info = test_api.whoami()
582
- print(f"Debug: Token test successful - user: {user_info.get('name', 'unknown')}")
583
-
584
- # Test if user can create repositories by checking their account type
585
- try:
586
- # Try to get user info to check account capabilities
587
- user_info = test_api.whoami()
588
- print(f"Debug: User info: {user_info}")
589
-
590
- # Check if user has pro account or sufficient permissions
591
- if user_info.get('type') == 'user':
592
- print("Debug: User account type confirmed")
593
- else:
594
- print(f"Debug: User account type: {user_info.get('type', 'unknown')}")
595
-
596
- except Exception as user_info_error:
597
- print(f"Debug: Could not get detailed user info: {user_info_error}")
598
- # This is not a critical error, so we continue
599
-
600
- except Exception as token_error:
601
- print(f"Debug: Token test failed: {token_error}")
602
- return """❌ **Token Validation Failed**
603
-
604
- The OAuth token could not be validated. This could be because:
605
-
606
- 1. The token has expired
607
- 2. The token doesn't have the right permissions
608
- 3. There's an issue with the authentication
609
-
610
- **Steps to fix:**
611
- 1. Click the logout button in the sidebar
612
- 2. Click "Sign in with Hugging Face" again
613
- 3. Authorize with all required permissions
614
- 4. Try deploying again
615
-
616
- ---
617
- *Please log in again.*""", update_oauth_status(oauth_profile, oauth_token)
618
-
619
- # Extract prompts from history
620
- prompts = []
621
- for user_msg, _ in history:
622
- if isinstance(user_msg, str) and user_msg.strip():
623
- prompts.append(user_msg.strip())
624
-
625
- # Test if user can create repositories by attempting a test creation
626
- try:
627
- test_api = HfApi(token=user_token)
628
-
629
- # Try to create a test repository to verify permissions
630
- test_repo_name = f"{username}/test-permissions-{int(time.time())}"
631
- print(f"Debug: Testing repository creation with: {test_repo_name}")
632
-
633
- try:
634
- # Attempt to create a test repository
635
- test_repo_url = test_api.create_repo(
636
- repo_id=test_repo_name,
637
- repo_type="model",
638
- private=True,
639
- exist_ok=False,
640
- token=user_token
641
- )
642
- print(f"Debug: Successfully created test repository: {test_repo_url}")
643
-
644
- # Clean up the test repository
645
- try:
646
- test_api.delete_repo(repo_id=test_repo_name, token=user_token)
647
- print(f"Debug: Successfully cleaned up test repository")
648
- except Exception as cleanup_error:
649
- print(f"Debug: Could not clean up test repository: {cleanup_error}")
650
-
651
- except Exception as test_create_error:
652
- print(f"Debug: Could not create test repository: {test_create_error}")
653
- error_msg = str(test_create_error).lower()
654
-
655
- if "403" in error_msg or "forbidden" in error_msg:
656
- return """❌ **Repository Creation Permission Denied**
657
-
658
- Your Hugging Face account doesn't have permission to create repositories. This could be because:
659
-
660
- 1. **Account Type**: Your account type may not allow repository creation
661
- 2. **Organization Restrictions**: If you're part of an organization, there may be restrictions
662
- 3. **Account Status**: Your account may be limited or suspended
663
-
664
- **Steps to fix:**
665
- 1. **Check Account Status**: Visit https://huggingface.co/settings/account to check your account status
666
- 2. **Verify Account Type**: Make sure your account allows repository creation
667
- 3. **Contact Support**: If you believe this is an error, contact Hugging Face support
668
- 4. **Try Different Account**: Consider using a different Hugging Face account
669
-
670
- **Note:** Free accounts should be able to create repositories. If you're having issues, it might be a temporary restriction.
671
-
672
- ---
673
- *Please check your account settings or try with a different account.*""", update_oauth_status(oauth_profile, oauth_token)
674
- else:
675
- return f"""❌ **Repository Creation Test Failed**
676
-
677
- Error: {str(test_create_error)}
678
-
679
- This could be due to:
680
- - Network connectivity issues
681
- - Hugging Face API temporary problems
682
- - Account-specific restrictions
683
-
684
- **Steps to fix:**
685
- 1. Check your internet connection
686
- 2. Wait a few minutes and try again
687
- 3. If the problem persists, check your Hugging Face account settings
688
-
689
- ---
690
- *Please try again or contact support if the issue persists.*""", update_oauth_status(oauth_profile, oauth_token)
691
-
692
- except Exception as test_error:
693
- print(f"Debug: Repository creation test failed: {test_error}")
694
- return f"""❌ **Permission Test Failed**
695
-
696
- Could not test repository creation permissions: {str(test_error)}
697
-
698
- **Steps to fix:**
699
- 1. Check your internet connection
700
- 2. Try logging out and logging back in
701
- 3. Wait a few minutes and try again
702
-
703
- ---
704
- *Please try again or contact support if the issue persists.*""", update_oauth_status(oauth_profile, oauth_token)
705
-
706
- # Use user's OAuth token to create space under their account
707
- result = create_space_from_html(title.strip(), html_content, prompts, user_token, username)
708
-
709
- if result["success"]:
710
- return f"""βœ… **Successfully deployed!**
711
-
712
- **Space URL:** {result['space_url']}
713
-
714
- Your application is now live on Hugging Face Spaces under your account. You can share this URL with others to showcase your generated application.
715
-
716
- **What's next:**
717
- - Visit the space to see your application in action
718
- - Share the URL with friends and colleagues
719
- - Make modifications and redeploy as needed
720
- - Manage your space from your Hugging Face dashboard
721
-
722
- ---
723
- *Generated with ❀️ using AnyCoder*""", update_oauth_status(oauth_profile, oauth_token)
724
- else:
725
- return f"""❌ **Deployment failed**
726
-
727
- **Error:** {result['error']}
728
-
729
- **Possible solutions:**
730
- - Ensure you have write access to create spaces on your account
731
- - Try a different title (avoid special characters)
732
- - Check your internet connection
733
- - Make sure your Hugging Face account has the necessary permissions
734
-
735
- ---
736
- *Please try again or contact support if the issue persists.*""", update_oauth_status(oauth_profile, oauth_token)
737
-
738
  def history_to_messages(history: History, system: str) -> Messages:
739
  messages = [{'role': 'system', 'content': system}]
740
  for h in history:
@@ -807,20 +254,6 @@ def history_render(history: History):
807
  def clear_history():
808
  return [], [], None, "" # Empty lists for both tuple format and chatbot messages, None for file, empty string for website URL
809
 
810
- def update_oauth_status(oauth_profile: gr.OAuthProfile = None, oauth_token: gr.OAuthToken = None):
811
- """Update the OAuth status indicator based on login state"""
812
- if not oauth_profile or not oauth_token:
813
- return "πŸ” **Login Required**\nSign in to deploy applications"
814
-
815
- # Check if we have the required scopes
816
- scopes_valid, missing_scopes = validate_oauth_scopes(oauth_token)
817
-
818
- if scopes_valid:
819
- return f"βœ… **Logged in as {oauth_profile.name}**\nReady to deploy applications"
820
- else:
821
- missing_list = ", ".join(missing_scopes)
822
- return f"⚠️ **Incomplete Permissions**\nMissing: {missing_list}\nPlease logout and login again"
823
-
824
  def update_image_input_visibility(model):
825
  """Update image input visibility based on selected model"""
826
  is_ernie_vl = model.get("id") == "baidu/ERNIE-4.5-VL-424B-A47B-Base-PT"
@@ -981,6 +414,188 @@ def demo_card_click(e: gr.EventData):
981
  # Return the first demo description as fallback
982
  return DEMO_LIST[0]['description']
983
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
984
  def extract_text_from_image(image_path):
985
  """Extract text from image using OCR"""
986
  try:
@@ -1477,18 +1092,16 @@ with gr.Blocks(
1477
  gr.Markdown("# AnyCoder")
1478
  gr.Markdown("*AI-Powered Code Generator*")
1479
 
1480
- # Login button at the top
1481
- login_btn = gr.LoginButton(
1482
- value="Sign in with Hugging Face",
1483
- logout_value="Logout ({})",
1484
- variant="huggingface",
1485
- size="sm"
1486
- )
1487
 
1488
- # OAuth components are automatically injected as function parameters
1489
- # when using gr.LoginButton() - no need to create them separately
1490
 
1491
- # OAuth status will be updated automatically by Gradio's OAuth system
 
 
 
1492
 
1493
  # Main input section
1494
  input = gr.Textbox(
@@ -1536,30 +1149,6 @@ with gr.Blocks(
1536
  label="Model"
1537
  )
1538
 
1539
- # Deployment section
1540
- gr.Markdown("---")
1541
- gr.Markdown("**πŸš€ Deploy to Space**")
1542
-
1543
- # Space title input
1544
- space_title_input = gr.Textbox(
1545
- label="Space title",
1546
- placeholder="My Awesome App",
1547
- lines=1
1548
- )
1549
-
1550
- # Deploy button
1551
- deploy_btn = gr.Button(
1552
- "πŸš€ Deploy to Space",
1553
- variant="primary",
1554
- size="lg"
1555
- )
1556
-
1557
- # Deployment status
1558
- deploy_status = gr.Markdown(
1559
- value="",
1560
- visible=False
1561
- )
1562
-
1563
  # Quick examples (minimal)
1564
  gr.Markdown("**Quick start**")
1565
  with gr.Column():
@@ -1580,11 +1169,16 @@ with gr.Blocks(
1580
  else:
1581
  gr.Markdown("βœ… Web search available")
1582
 
1583
- # OAuth status indicator
1584
- oauth_status = gr.Markdown(
1585
- value="πŸ” **Login Required**\nSign in to deploy applications",
1586
- visible=True
 
 
 
1587
  )
 
 
1588
 
1589
  # Hidden elements for functionality
1590
  model_display = gr.Markdown(f"**Model:** {AVAILABLE_MODELS[0]['name']}", visible=False)
@@ -1625,46 +1219,9 @@ with gr.Blocks(
1625
  )
1626
  with gr.Tab("Preview"):
1627
  sandbox = gr.HTML(label="Live preview")
1628
- with gr.Tab("Deploy"):
1629
- deploy_output = gr.Markdown(
1630
- value="""## πŸš€ Deploy Your Application
1631
-
1632
- ### Prerequisites
1633
- 1. **Login Required**: You must be logged in with your Hugging Face account
1634
- 2. **Permissions**: Grant the following permissions when logging in:
1635
- - βœ… **read-repos** - Read access to repositories
1636
- - βœ… **write-repos** - Write access to create repositories
1637
- - βœ… **manage-repos** - Manage repository settings
1638
-
1639
- ### Steps to Deploy
1640
- 1. **Login**: Click "Sign in with Hugging Face" in the sidebar
1641
- 2. **Authorize Permissions**: When the authorization page appears, make sure to grant ALL the requested permissions
1642
- 3. **Generate Code**: Generate some HTML code using the AI
1643
- 4. **Enter Title**: In the sidebar, enter a title for your space (e.g., "My Todo App")
1644
- 5. **Deploy**: Click the "πŸš€ Deploy to Space" button
1645
-
1646
- ### What Happens
1647
- - Your application will be deployed to Hugging Face Spaces under your account
1648
- - You'll get a shareable URL (e.g., `https://huggingface.co/spaces/yourusername/my-app-1234567890`)
1649
- - The deployment includes professional styling and documentation
1650
-
1651
- ### Troubleshooting
1652
- If deployment fails:
1653
- - Make sure you're logged in with the correct account
1654
- - Ensure you granted all required permissions during login
1655
- - Try logging out and logging back in
1656
- - Check that your Hugging Face account can create repositories
1657
-
1658
- **Important**: You must grant ALL three permissions during the OAuth authorization process.
1659
-
1660
- ---
1661
- *Your application will be deployed to Hugging Face Spaces and you'll get a shareable URL!*""",
1662
- label="Deployment Status"
1663
- )
1664
  with gr.Tab("History"):
1665
  history_output = gr.Chatbot(show_label=False, height=400, type="messages")
1666
 
1667
-
1668
  # Event handlers
1669
  btn.click(
1670
  generation_code,
@@ -1673,12 +1230,17 @@ If deployment fails:
1673
  )
1674
  clear_btn.click(clear_history, outputs=[history, history_output, file_input, website_url_input])
1675
 
1676
- # Deployment event handler
 
 
 
1677
  deploy_btn.click(
1678
- deploy_to_space,
1679
- inputs=[space_title_input, code_output, history],
1680
- outputs=[deploy_output, oauth_status],
1681
- api_name="deploy"
 
 
1682
  )
1683
 
1684
  if __name__ == "__main__":
 
18
  import time
19
 
20
  import gradio as gr
21
+ from huggingface_hub import InferenceClient, HfApi, create_repo, whoami
22
  from tavily import TavilyClient
23
 
24
  # Configuration
 
172
  History = List[Tuple[str, str]]
173
  Messages = List[Dict[str, str]]
174
 
 
 
 
175
  # Tavily Search Client
176
  TAVILY_API_KEY = os.getenv('TAVILY_API_KEY')
177
  tavily_client = None
 
182
  print(f"Failed to initialize Tavily client: {e}")
183
  tavily_client = None
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  def history_to_messages(history: History, system: str) -> Messages:
186
  messages = [{'role': 'system', 'content': system}]
187
  for h in history:
 
254
  def clear_history():
255
  return [], [], None, "" # Empty lists for both tuple format and chatbot messages, None for file, empty string for website URL
256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  def update_image_input_visibility(model):
258
  """Update image input visibility based on selected model"""
259
  is_ernie_vl = model.get("id") == "baidu/ERNIE-4.5-VL-424B-A47B-Base-PT"
 
414
  # Return the first demo description as fallback
415
  return DEMO_LIST[0]['description']
416
 
417
+ def get_user_info(profile: gr.OAuthProfile | None) -> str:
418
+ """Get user information from OAuth profile"""
419
+ if profile is None:
420
+ return "πŸ‘€ **Guest User**\n*Sign in to personalize your experience*"
421
+ return f"πŸ‘€ **{profile.name}**\n*Welcome back!*"
422
+
423
+ def create_space_from_code(html_code: str, title: str, oauth_token: gr.OAuthToken | None) -> str:
424
+ """Create a new Hugging Face Space with the generated HTML code"""
425
+ if not oauth_token:
426
+ return "❌ **Error:** Please sign in with your Hugging Face account to deploy spaces."
427
+
428
+ if not html_code or not html_code.strip():
429
+ return "❌ **Error:** No code to deploy. Please generate some code first."
430
+
431
+ if not title or not title.strip():
432
+ return "❌ **Error:** Please provide a title for your space."
433
+
434
+ try:
435
+ # Clean up the title for use as repo name
436
+ import re
437
+ clean_title = re.sub(r'[^a-zA-Z0-9\s-]', '', title)
438
+ clean_title = re.sub(r'\s+', '-', clean_title).lower()
439
+ clean_title = clean_title[:50] # Limit length
440
+
441
+ # Get user info to create repo under their account
442
+ user_info = whoami(oauth_token.token)
443
+ username = user_info.get('name', 'unknown')
444
+
445
+ # Create unique repo ID
446
+ import time
447
+ timestamp = int(time.time())
448
+ repo_id = f"{username}/{clean_title}-{timestamp}"
449
+
450
+ # Create the space
451
+ api = HfApi(token=oauth_token.token)
452
+ api.create_repo(
453
+ repo_id=repo_id,
454
+ repo_type="space",
455
+ space_sdk="static",
456
+ space_hardware="cpu-basic"
457
+ )
458
+
459
+ # Create the HTML file content
460
+ html_content = f"""<!DOCTYPE html>
461
+ <html lang="en">
462
+ <head>
463
+ <meta charset="UTF-8">
464
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
465
+ <title>{title}</title>
466
+ <style>
467
+ body {{
468
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
469
+ margin: 0;
470
+ padding: 20px;
471
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
472
+ min-height: 100vh;
473
+ }}
474
+ .container {{
475
+ max-width: 1200px;
476
+ margin: 0 auto;
477
+ background: white;
478
+ border-radius: 12px;
479
+ box-shadow: 0 20px 40px rgba(0,0,0,0.1);
480
+ overflow: hidden;
481
+ }}
482
+ .header {{
483
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
484
+ color: white;
485
+ padding: 30px;
486
+ text-align: center;
487
+ }}
488
+ .header h1 {{
489
+ margin: 0;
490
+ font-size: 2.5em;
491
+ font-weight: 300;
492
+ }}
493
+ .header p {{
494
+ margin: 10px 0 0 0;
495
+ opacity: 0.9;
496
+ font-size: 1.1em;
497
+ }}
498
+ .content {{
499
+ padding: 40px;
500
+ }}
501
+ .footer {{
502
+ background: #f8f9fa;
503
+ padding: 20px;
504
+ text-align: center;
505
+ color: #666;
506
+ border-top: 1px solid #eee;
507
+ }}
508
+ .footer a {{
509
+ color: #667eea;
510
+ text-decoration: none;
511
+ }}
512
+ .footer a:hover {{
513
+ text-decoration: underline;
514
+ }}
515
+ </style>
516
+ </head>
517
+ <body>
518
+ <div class="container">
519
+ <div class="header">
520
+ <h1>{title}</h1>
521
+ <p>Generated with AnyCoder - AI-Powered Code Generator</p>
522
+ </div>
523
+ <div class="content">
524
+ {html_code}
525
+ </div>
526
+ <div class="footer">
527
+ <p>πŸš€ Created with <a href="https://huggingface.co/spaces/anycoder" target="_blank">AnyCoder</a> |
528
+ <a href="https://huggingface.co/spaces" target="_blank">Hugging Face Spaces</a></p>
529
+ </div>
530
+ </div>
531
+ </body>
532
+ </html>"""
533
+
534
+ # Upload the HTML file
535
+ api.upload_file(
536
+ repo_id=repo_id,
537
+ repo_type="space",
538
+ path_in_repo="index.html",
539
+ path_or_fileobj=html_content.encode('utf-8')
540
+ )
541
+
542
+ # Create a README for the space
543
+ readme_content = f"""---
544
+ title: {title}
545
+ emoji: πŸš€
546
+ colorFrom: blue
547
+ colorTo: purple
548
+ sdk: static
549
+ sdk_version: 1.0.0
550
+ app_file: index.html
551
+ pinned: false
552
+ ---
553
+
554
+ # {title}
555
+
556
+ This application was generated using AnyCoder, an AI-powered code generator.
557
+
558
+ ## About
559
+
560
+ This space contains a web application created by describing requirements in natural language and having AI generate the corresponding HTML/CSS/JavaScript code.
561
+
562
+ ## Features
563
+
564
+ - Responsive design
565
+ - Modern UI/UX
566
+ - Cross-browser compatibility
567
+ - Mobile-friendly layout
568
+
569
+ ## Generated Code
570
+
571
+ The application code was automatically generated and includes:
572
+ - HTML structure
573
+ - CSS styling
574
+ - JavaScript functionality (if applicable)
575
+
576
+ ## Created With
577
+
578
+ - [AnyCoder](https://huggingface.co/spaces/anycoder) - AI-Powered Code Generator
579
+ - [Hugging Face Spaces](https://huggingface.co/spaces) - Deployment Platform
580
+
581
+ ---
582
+ *Generated on {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}*
583
+ """
584
+
585
+ api.upload_file(
586
+ repo_id=repo_id,
587
+ repo_type="space",
588
+ path_in_repo="README.md",
589
+ path_or_fileobj=readme_content.encode('utf-8')
590
+ )
591
+
592
+ space_url = f"https://huggingface.co/spaces/{repo_id}"
593
+ return f"βœ… **Success!** Your space has been created and deployed.\n\n**Space URL:** {space_url}\n\n**Repository:** {repo_id}\n\nYour application is now live and accessible to anyone with the link!"
594
+
595
+ except Exception as e:
596
+ return f"❌ **Error creating space:** {str(e)}\n\nPlease make sure you have the necessary permissions and try again."
597
+
598
+
599
  def extract_text_from_image(image_path):
600
  """Extract text from image using OCR"""
601
  try:
 
1092
  gr.Markdown("# AnyCoder")
1093
  gr.Markdown("*AI-Powered Code Generator*")
1094
 
1095
+ # OAuth Login Button
1096
+ login_btn = gr.LoginButton()
 
 
 
 
 
1097
 
1098
+ # User profile display
1099
+ user_info = gr.Markdown("πŸ‘€ **Guest User**\n*Sign in to personalize your experience*")
1100
 
1101
+ gr.Markdown("---") # Separator
1102
+
1103
+ # Load user info on app load
1104
+ demo.load(get_user_info, inputs=None, outputs=user_info)
1105
 
1106
  # Main input section
1107
  input = gr.Textbox(
 
1149
  label="Model"
1150
  )
1151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1152
  # Quick examples (minimal)
1153
  gr.Markdown("**Quick start**")
1154
  with gr.Column():
 
1169
  else:
1170
  gr.Markdown("βœ… Web search available")
1171
 
1172
+ # Space deployment section
1173
+ gr.Markdown("---")
1174
+ gr.Markdown("**πŸš€ Deploy to Space**")
1175
+ space_title = gr.Textbox(
1176
+ label="Space title",
1177
+ placeholder="My Awesome App",
1178
+ lines=1
1179
  )
1180
+ deploy_btn = gr.Button("Create Space", variant="primary", size="sm")
1181
+ deploy_status = gr.Markdown("", visible=False)
1182
 
1183
  # Hidden elements for functionality
1184
  model_display = gr.Markdown(f"**Model:** {AVAILABLE_MODELS[0]['name']}", visible=False)
 
1219
  )
1220
  with gr.Tab("Preview"):
1221
  sandbox = gr.HTML(label="Live preview")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1222
  with gr.Tab("History"):
1223
  history_output = gr.Chatbot(show_label=False, height=400, type="messages")
1224
 
 
1225
  # Event handlers
1226
  btn.click(
1227
  generation_code,
 
1230
  )
1231
  clear_btn.click(clear_history, outputs=[history, history_output, file_input, website_url_input])
1232
 
1233
+ # Deploy space event handler
1234
+ def deploy_space_wrapper(title, current_code, oauth_token: gr.OAuthToken | None):
1235
+ return create_space_from_code(current_code, title, oauth_token)
1236
+
1237
  deploy_btn.click(
1238
+ deploy_space_wrapper,
1239
+ inputs=[space_title, code_output],
1240
+ outputs=deploy_status
1241
+ ).then(
1242
+ lambda: gr.update(visible=True),
1243
+ outputs=deploy_status
1244
  )
1245
 
1246
  if __name__ == "__main__":