diff --git a/g4f/Provider/needs_auth/hf/HuggingChat.py b/g4f/Provider/needs_auth/hf/HuggingChat.py index ada1b8ff..b851923c 100644 --- a/g4f/Provider/needs_auth/hf/HuggingChat.py +++ b/g4f/Provider/needs_auth/hf/HuggingChat.py @@ -1,11 +1,9 @@ from __future__ import annotations import json -import re import os import requests import base64 -import uuid from typing import AsyncIterator try: @@ -37,7 +35,7 @@ class HuggingChat(AsyncAuthedProvider, ProviderModelMixin): origin = f"https://{domain}" url = f"{origin}/chat" - working = False + working = True use_nodriver = True supports_stream = True needs_auth = True @@ -64,27 +62,18 @@ class HuggingChat(AsyncAuthedProvider, ProviderModelMixin): async def on_auth_async(cls, cookies: Cookies = None, proxy: str = None, **kwargs) -> AsyncIterator: if cookies is None: cookies = get_cookies(cls.domain, single_browser=True) - if "hf-chat" in cookies: - yield AuthResult( - cookies=cookies, - headers=DEFAULT_HEADERS, - impersonate="chrome" - ) - return - if cls.needs_auth: + try: yield RequestLogin(cls.__name__, os.environ.get("G4F_LOGIN_URL") or "") yield AuthResult( **await get_args_from_nodriver( cls.url, proxy=proxy, - wait_for='form[action$="/logout"]' + wait_for='div div nav div div img' ) ) - else: + except MissingRequirementsError: yield AuthResult( - cookies={ - "hf-chat": str(uuid.uuid4()) # Generate a session ID - }, + cookies=cookies, headers=DEFAULT_HEADERS, impersonate="chrome" ) @@ -198,7 +187,10 @@ class HuggingChat(AsyncAuthedProvider, ProviderModelMixin): if response.status_code == 400: raise ResponseError(f"{response.text}: Model: {model}") raise_for_status(response) - return response.json().get('conversationId') + try: + return response.json().get('conversationId') + except json.JSONDecodeError as e: + raise MissingAuthError(f"Failed to decode JSON: {e}") from e @classmethod def fetch_message_id(cls, session: Session, conversation_id: str): diff --git a/g4f/gui/server/website.py b/g4f/gui/server/website.py index 95c354f9..0dc1cfe8 100644 --- a/g4f/gui/server/website.py +++ b/g4f/gui/server/website.py @@ -19,11 +19,13 @@ def render(filename = "home", download_url: str = GITHUB_URL): if download_url == GITHUB_URL: filename += ("" if "." in filename else ".html") html = None + is_temp = False if os.path.exists(DIST_DIR) and not request.args.get("debug"): path = os.path.abspath(os.path.join(os.path.dirname(DIST_DIR), filename)) if os.path.exists(path): if download_url == GITHUB_URL: html = open(path, 'r', encoding='utf-8').read() + is_temp = True else: return send_from_directory(os.path.dirname(path), os.path.basename(path)) try: @@ -34,7 +36,6 @@ def render(filename = "home", download_url: str = GITHUB_URL): cache_dir = os.path.join(get_cookies_dir(), ".gui_cache", today) latest_version = str(latest_version) +quote(unquote(request.query_string.decode())) or str(latest_version) cache_file = os.path.join(cache_dir, f"{secure_filename(f'{version.utils.current_version}-{latest_version}')}.{secure_filename(filename)}") - is_temp = False if os.path.isfile(cache_file + ".js"): cache_file += ".js" if not os.path.exists(cache_file): diff --git a/g4f/mcp/tools.py b/g4f/mcp/tools.py index e1d45387..4ad15977 100644 --- a/g4f/mcp/tools.py +++ b/g4f/mcp/tools.py @@ -10,6 +10,7 @@ from __future__ import annotations from typing import Any, Dict from abc import ABC, abstractmethod +import urllib.parse from aiohttp import ClientSession @@ -269,6 +270,8 @@ class ImageGenerationTool(MCPTool): } image_url = image_data.url + + template = 'Display the image using this template: {prompt}' # Return result based on URL type if image_url.startswith('data:'): @@ -277,7 +280,8 @@ class ImageGenerationTool(MCPTool): "model": model, "width": width, "height": height, - "image": image_url + "image": image_url, + "template": template } else: if arguments.get("origin") and image_url.startswith("/media/"): @@ -287,7 +291,8 @@ class ImageGenerationTool(MCPTool): "model": model, "width": width, "height": height, - "image_url": image_url + "image_url": image_url, + "template": template } except Exception as e: @@ -411,13 +416,6 @@ class TextToAudioTool(MCPTool): Returns: Dict[str, Any]: Audio URL or error message """ - try: - import urllib.parse - except ImportError as e: - return { - "error": f"urllib is not available: {str(e)}" - } - prompt = arguments.get("prompt", "") voice = arguments.get("voice", "alloy") url_encode = arguments.get("url_encode", True) @@ -428,9 +426,9 @@ class TextToAudioTool(MCPTool): } # Validate prompt length (reasonable limit for text-to-speech) - if len(prompt) > 5000: + if len(prompt) > 10000: return { - "error": "Prompt is too long (max 5000 characters)" + "error": "Prompt is too long (max 10000 characters)" } try: @@ -441,18 +439,21 @@ class TextToAudioTool(MCPTool): encoded_prompt = prompt.replace(" ", "%20") # Basic space encoding # Construct the Pollinations AI text-to-speech URL - audio_url = f"/backend-api/v2/create?provider=Gemini&model=gemini-audio&cache=true&prompt={encoded_prompt}" + audio_url = f"/backend-api/v2/synthesize/Gemini?text={encoded_prompt}" if arguments.get("origin"): audio_url = f"{arguments.get('origin')}{audio_url}" async with ClientSession() as session: async with session.get(audio_url, max_redirects=0) as resp: audio_url = str(resp.url) + + template = 'Play the audio using this template: