Update app.py
Browse files
app.py
CHANGED
|
@@ -514,6 +514,32 @@ def _log_call_end(func_name: str, output_desc: str) -> None:
|
|
| 514 |
print(f"[TOOL RESULT] {func_name} (failed to log output: {e})", flush=True)
|
| 515 |
|
| 516 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 517 |
# ==============================
|
| 518 |
# Deep Research helpers: slow-host detection
|
| 519 |
# ==============================
|
|
@@ -1776,7 +1802,7 @@ kokoro_interface = gr.Interface(
|
|
| 1776 |
"Supports unlimited text length by processing all segments. Voice examples: 'af_heart' (US female), 'am_onyx' (US male), "
|
| 1777 |
"'bf_emma' (British female), 'af_sky' (US female), 'af_nicole' (US female), "
|
| 1778 |
"Parameters: text (str), speed (float 0.5–2.0, default 1.25x), voice (str from 54 available options, default 'af_heart'). "
|
| 1779 |
-
"Return the generated media to the user in this format
|
| 1780 |
),
|
| 1781 |
flagging_mode="never",
|
| 1782 |
)
|
|
@@ -2164,8 +2190,10 @@ def Generate_Video( # <-- MCP tool #6 (Generate Video)
|
|
| 2164 |
size = os.path.getsize(path)
|
| 2165 |
except Exception:
|
| 2166 |
size = -1
|
| 2167 |
-
|
| 2168 |
-
|
|
|
|
|
|
|
| 2169 |
except Exception as e:
|
| 2170 |
last_error = e
|
| 2171 |
continue
|
|
@@ -2211,7 +2239,7 @@ video_generation_interface = gr.Interface(
|
|
| 2211 |
"'time-lapse of clouds moving across a blue sky'. Default model: Wan2.2-T2V-A14B (2-6 second videos). "
|
| 2212 |
"Parameters: prompt (str), model_id (str), negative_prompt (str), steps (int), cfg_scale (float), seed (int), "
|
| 2213 |
"width/height (int), fps (int), duration (float in seconds). Returns MP4 file path. "
|
| 2214 |
-
"Return the generated media to the user in this format
|
| 2215 |
),
|
| 2216 |
flagging_mode="never",
|
| 2217 |
# Only expose to MCP when HF token is provided; UI tab is always visible
|
|
@@ -2699,10 +2727,18 @@ def Deep_Research(
|
|
| 2699 |
# Build outputs
|
| 2700 |
links_text = "\n".join([f"[{i+1}] {u}" for i, u in enumerate(pages.keys())])
|
| 2701 |
file_path = _write_report_tmp(report)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2702 |
elapsed = time.time() - start_ts
|
| 2703 |
# Print explicit timing and include in structured log output
|
| 2704 |
print(f"[TIMING] Deep_Research elapsed: {elapsed:.2f}s", flush=True)
|
| 2705 |
-
_log_call_end("Deep_Research", f"urls={len(pages)} file={os.path.basename(file_path)} duration={elapsed:.2f}s")
|
|
|
|
|
|
|
| 2706 |
return report, links_text, file_path
|
| 2707 |
|
| 2708 |
|
|
@@ -2735,7 +2771,8 @@ deep_research_interface = gr.Interface(
|
|
| 2735 |
"Runs 1–5 DDG searches (URLs only), caps total results to 50 (when exceeding, each query returns 10). "
|
| 2736 |
"Fetches all URLs (3000 chars each) and calls the Researcher to write a research report. "
|
| 2737 |
"Returns the report (Markdown), the list of sources, and a downloadable text file path. "
|
| 2738 |
-
"
|
|
|
|
| 2739 |
),
|
| 2740 |
flagging_mode="never",
|
| 2741 |
show_api=bool(HF_TEXTGEN_TOKEN),
|
|
|
|
| 514 |
print(f"[TOOL RESULT] {func_name} (failed to log output: {e})", flush=True)
|
| 515 |
|
| 516 |
|
| 517 |
+
# ==============================
|
| 518 |
+
# HF Space file URL helper
|
| 519 |
+
# ==============================
|
| 520 |
+
|
| 521 |
+
def _public_file_url(local_path: str) -> str:
|
| 522 |
+
"""Return an absolute Hugging Face Space URL for a locally saved file.
|
| 523 |
+
|
| 524 |
+
This ensures that download links point to the Space host (SPACE_HOST) rather than any
|
| 525 |
+
reverse-proxy origin (e.g., mcp.nymbo.net), avoiding 404s when proxies don’t expose /file=.
|
| 526 |
+
|
| 527 |
+
If SPACE_HOST is not set (e.g., running locally), falls back to a relative "/file=" URL.
|
| 528 |
+
"""
|
| 529 |
+
try:
|
| 530 |
+
from urllib.parse import quote
|
| 531 |
+
host = os.getenv("SPACE_HOST", "").strip()
|
| 532 |
+
abs_path = os.path.abspath(local_path)
|
| 533 |
+
quoted = quote(abs_path)
|
| 534 |
+
if host:
|
| 535 |
+
return f"https://{host}/file={quoted}"
|
| 536 |
+
# Local/dev fallback
|
| 537 |
+
return f"/file={quoted}"
|
| 538 |
+
except Exception:
|
| 539 |
+
# Last-resort: return the original path to avoid breaking UI
|
| 540 |
+
return local_path
|
| 541 |
+
|
| 542 |
+
|
| 543 |
# ==============================
|
| 544 |
# Deep Research helpers: slow-host detection
|
| 545 |
# ==============================
|
|
|
|
| 1802 |
"Supports unlimited text length by processing all segments. Voice examples: 'af_heart' (US female), 'am_onyx' (US male), "
|
| 1803 |
"'bf_emma' (British female), 'af_sky' (US female), 'af_nicole' (US female), "
|
| 1804 |
"Parameters: text (str), speed (float 0.5–2.0, default 1.25x), voice (str from 54 available options, default 'af_heart'). "
|
| 1805 |
+
"Return the generated media to the user in this format `[Generated Speech](URL)`"
|
| 1806 |
),
|
| 1807 |
flagging_mode="never",
|
| 1808 |
)
|
|
|
|
| 2190 |
size = os.path.getsize(path)
|
| 2191 |
except Exception:
|
| 2192 |
size = -1
|
| 2193 |
+
# Always publish HF Space absolute URL to avoid proxy hosts (e.g., mcp.nymbo.net)
|
| 2194 |
+
url = _public_file_url(path)
|
| 2195 |
+
_log_call_end("Generate_Video", f"provider={provider} path={os.path.basename(path)} bytes={size} url={url}")
|
| 2196 |
+
return url
|
| 2197 |
except Exception as e:
|
| 2198 |
last_error = e
|
| 2199 |
continue
|
|
|
|
| 2239 |
"'time-lapse of clouds moving across a blue sky'. Default model: Wan2.2-T2V-A14B (2-6 second videos). "
|
| 2240 |
"Parameters: prompt (str), model_id (str), negative_prompt (str), steps (int), cfg_scale (float), seed (int), "
|
| 2241 |
"width/height (int), fps (int), duration (float in seconds). Returns MP4 file path. "
|
| 2242 |
+
"Return the generated media to the user in this format `[Generated Video](URL)`"
|
| 2243 |
),
|
| 2244 |
flagging_mode="never",
|
| 2245 |
# Only expose to MCP when HF token is provided; UI tab is always visible
|
|
|
|
| 2727 |
# Build outputs
|
| 2728 |
links_text = "\n".join([f"[{i+1}] {u}" for i, u in enumerate(pages.keys())])
|
| 2729 |
file_path = _write_report_tmp(report)
|
| 2730 |
+
file_url = _public_file_url(file_path)
|
| 2731 |
+
# Append a canonical HF download link so clients avoid proxy origins when clicking
|
| 2732 |
+
try:
|
| 2733 |
+
report = report.rstrip() + f"\n\n---\nDownload the full report as text: [research_report.txt]({file_url})\n"
|
| 2734 |
+
except Exception:
|
| 2735 |
+
pass
|
| 2736 |
elapsed = time.time() - start_ts
|
| 2737 |
# Print explicit timing and include in structured log output
|
| 2738 |
print(f"[TIMING] Deep_Research elapsed: {elapsed:.2f}s", flush=True)
|
| 2739 |
+
_log_call_end("Deep_Research", f"urls={len(pages)} file={os.path.basename(file_path)} duration={elapsed:.2f}s url={file_url}")
|
| 2740 |
+
# Keep return signature for existing UI (report, links, file path). MCP clients can prefer the URL by
|
| 2741 |
+
# reading the api_description instruction or deriving it from the path using the same rule.
|
| 2742 |
return report, links_text, file_path
|
| 2743 |
|
| 2744 |
|
|
|
|
| 2771 |
"Runs 1–5 DDG searches (URLs only), caps total results to 50 (when exceeding, each query returns 10). "
|
| 2772 |
"Fetches all URLs (3000 chars each) and calls the Researcher to write a research report. "
|
| 2773 |
"Returns the report (Markdown), the list of sources, and a downloadable text file path. "
|
| 2774 |
+
"When sharing a link, always use the Space URL constructed as: https://{SPACE_HOST}/file=<abs_path> (we handle this automatically). "
|
| 2775 |
+
"Provide the user with one-paragraph summary of the research report and the txt file in this format `[research_report.txt](URL)`"
|
| 2776 |
),
|
| 2777 |
flagging_mode="never",
|
| 2778 |
show_api=bool(HF_TEXTGEN_TOKEN),
|