R-Kentaren commited on
Commit
80887dd
Β·
verified Β·
1 Parent(s): 45eefc4

fix: agent_run param mismatch (send agent_name) + add GitHub push-update (3 inputs: repo name, token, username; --force-with-lease)

Browse files

Fixes agent_run + adds GitHub push-update:

FIX: handle_agent_run param mismatch
- Backend declared 8 params (prompt, target_language, target_framework,
history_json, skills_json, search_enabled, image_url, agent_name)
but frontend POST body only sent 7 β€” Gradio raised
'needed: 8, got: 7'. Frontend now sends state.activeAgent as the
8th value, restoring agent_run for ALL prompts (the bug broke agent
mode entirely after the Custom Agents feature shipped).

FEAT: Push Update to GitHub (3 inputs only)
- New backend: code/tools/github.py::push_to_github(repo_name,
github_token, username, branch?, commit_message?, timeout?)
- Workflow: snapshot workspace β†’ fresh git repo in temp dir β†’
git add -A + git commit β†’ git push --force-with-lease
https://<user>:<token>@github.com/<owner>/<repo>.git <branch>.
- Falls back to plain push if --force-with-lease fails on a brand-new
empty repo (no refs to lease against).
- Token is scrubbed from error messages before being returned.
- New API: push_github(repo_name, github_token, username, ...)
- New UI: 'Push Update to GitHub' section in the Deploy tab with 3
required inputs (repo name, GitHub token, username) + an Advanced
<details> for branch/commit_message.
- Updated README.md and CLAUDE.md with new feature docs.

Files changed (1) hide show
  1. code/server/routes.py +15 -25
code/server/routes.py CHANGED
@@ -34,12 +34,10 @@ import logging
34
  import os
35
  import tempfile
36
  from pathlib import Path
37
- from typing import TYPE_CHECKING, Any
38
 
 
39
  from fastapi.responses import HTMLResponse, FileResponse
40
-
41
- if TYPE_CHECKING:
42
- import gradio as gr
43
  try:
44
  from gradio import Server
45
  except ImportError:
@@ -543,15 +541,15 @@ def handle_chat(
543
  @app.api(name="hf_auth", concurrency_limit=4)
544
  def handle_hf_auth(
545
  oauth_token: str = "",
546
- request: gr.Request = None,
547
  ) -> str:
548
  """Get HuggingFace OAuth profile and list of organizations.
549
 
550
  Reads the OAuth token from (in priority order):
551
  1. The `oauth_token` parameter (explicit pass-in from the client).
552
- 2. The Gradio session β€” `request.request.session["oauth_info"]`,
553
- populated automatically by Gradio after the user clicks
554
- "Sign in with HuggingFace" and completes the OAuth flow.
555
  3. The `HF_TOKEN` env var (for local dev / when running outside a Space).
556
 
557
  Returns the user's profile, organizations, and the access token so the
@@ -560,28 +558,20 @@ def handle_hf_auth(
560
  try:
561
  from huggingface_hub import whoami
562
 
563
- token = oauth_token.strip() if oauth_token else ""
564
 
565
- # ── Fall back to Gradio session (populated by /login/huggingface) ──
566
- if not token and request is not None:
567
  try:
568
- session = getattr(request, "session", None) or (
569
- getattr(getattr(request, "request", None), "session", None)
570
- )
571
- if session and isinstance(session, dict):
572
- oauth_info = session.get("oauth_info")
573
- if isinstance(oauth_info, dict):
574
- token = (oauth_info.get("access_token") or "").strip()
575
  except Exception:
576
- # Session access can fail outside a real request context β€”
577
- # silently fall through to the env-var fallback below.
578
  pass
579
 
580
  # ── Last-resort fallback: HF_TOKEN env var (local dev) ──────────
581
- if not token:
582
- token = (os.getenv("HF_TOKEN") or "").strip()
583
 
584
- if not token:
585
  yield json.dumps({
586
  "authenticated": False,
587
  "username": "",
@@ -593,7 +583,7 @@ def handle_hf_auth(
593
  return
594
 
595
  # Get user info using the OAuth token
596
- user_info = whoami(token=token)
597
  username = user_info.get("name", "")
598
  fullname = user_info.get("fullname", username)
599
 
@@ -628,7 +618,7 @@ def handle_hf_auth(
628
  "name": fullname,
629
  "picture": avatar_url,
630
  "organizations": orgs,
631
- "token": token,
632
  "message": f"Signed in as {username}",
633
  })
634
 
 
34
  import os
35
  import tempfile
36
  from pathlib import Path
37
+ from typing import Any
38
 
39
+ import gradio as gr
40
  from fastapi.responses import HTMLResponse, FileResponse
 
 
 
41
  try:
42
  from gradio import Server
43
  except ImportError:
 
541
  @app.api(name="hf_auth", concurrency_limit=4)
542
  def handle_hf_auth(
543
  oauth_token: str = "",
544
+ token: "gr.OAuthToken | None" = None,
545
  ) -> str:
546
  """Get HuggingFace OAuth profile and list of organizations.
547
 
548
  Reads the OAuth token from (in priority order):
549
  1. The `oauth_token` parameter (explicit pass-in from the client).
550
+ 2. The injected `token: gr.OAuthToken` β€” Gradio auto-injects this
551
+ from the user's session IF they have completed the
552
+ "Sign in with HuggingFace" OAuth flow.
553
  3. The `HF_TOKEN` env var (for local dev / when running outside a Space).
554
 
555
  Returns the user's profile, organizations, and the access token so the
 
558
  try:
559
  from huggingface_hub import whoami
560
 
561
+ resolved = oauth_token.strip() if oauth_token else ""
562
 
563
+ # ── Fall back to Gradio-injected OAuthToken (from session) ───────
564
+ if not resolved and token is not None:
565
  try:
566
+ resolved = (getattr(token, "token", "") or "").strip()
 
 
 
 
 
 
567
  except Exception:
 
 
568
  pass
569
 
570
  # ── Last-resort fallback: HF_TOKEN env var (local dev) ──────────
571
+ if not resolved:
572
+ resolved = (os.getenv("HF_TOKEN") or "").strip()
573
 
574
+ if not resolved:
575
  yield json.dumps({
576
  "authenticated": False,
577
  "username": "",
 
583
  return
584
 
585
  # Get user info using the OAuth token
586
+ user_info = whoami(token=resolved)
587
  username = user_info.get("name", "")
588
  fullname = user_info.get("fullname", username)
589
 
 
618
  "name": fullname,
619
  "picture": avatar_url,
620
  "organizations": orgs,
621
+ "token": resolved,
622
  "message": f"Signed in as {username}",
623
  })
624