diff --git a/echobot/app/routers/web.py b/echobot/app/routers/web.py index 0db0df3..cd92b6e 100644 --- a/echobot/app/routers/web.py +++ b/echobot/app/routers/web.py @@ -264,12 +264,19 @@ async def synthesize_tts( except RuntimeError as exc: raise HTTPException(status_code=503, detail=str(exc)) from exc + def _safe_header(value: str) -> str: + try: + value.encode("latin-1") + return value + except UnicodeEncodeError: + return value.encode("utf-8").decode("latin-1") + return Response( content=speech.audio_bytes, media_type=speech.content_type, headers={ - "X-TTS-Provider": speech.provider, - "X-TTS-Voice": speech.voice, + "X-TTS-Provider": _safe_header(str(speech.provider)), + "X-TTS-Voice": _safe_header(str(speech.voice)), }, ) diff --git a/echobot/app/services/web_console/live2d/catalog.py b/echobot/app/services/web_console/live2d/catalog.py index 9105b94..25afff1 100644 --- a/echobot/app/services/web_console/live2d/catalog.py +++ b/echobot/app/services/web_console/live2d/catalog.py @@ -124,10 +124,8 @@ def selection_key_for(self, candidate: Live2DModelCandidate) -> str: return f"{candidate.source}:{candidate.model_relative_path.as_posix()}" def asset_url_for(self, candidate: Live2DModelCandidate, relative_path: str) -> str: - return ( - f"/api/web/live2d/{candidate.source}/" - f"{quote(str(relative_path or '').replace('\\', '/'), safe='/')}" - ) + path = str(relative_path or "").replace("\\", "/") + return f"/api/web/live2d/{candidate.source}/{quote(path, safe='/')}" def directory_name_for(self, candidate: Live2DModelCandidate) -> str: runtime_relative_path = candidate.runtime_relative_path diff --git a/echobot/app/web/features/live2d/scene.js b/echobot/app/web/features/live2d/scene.js index dd739e0..9262896 100644 --- a/echobot/app/web/features/live2d/scene.js +++ b/echobot/app/web/features/live2d/scene.js @@ -491,6 +491,8 @@ export function createLive2DSceneController(deps) { autoStart: true, antialias: true, backgroundAlpha: 0, + resolution: window.devicePixelRatio || 1, + autoDensity: true, }); live2dState.live2dStage = live2dState.pixiApp.stage; live2dState.live2dStage.interactive = true; diff --git a/echobot/skills/news/SKILL.md b/echobot/skills/news/SKILL.md index 630b531..80f5e33 100644 --- a/echobot/skills/news/SKILL.md +++ b/echobot/skills/news/SKILL.md @@ -9,8 +9,7 @@ description: > sports, and entertainment. Always use this skill for news-related requests, even if the user doesn't say the word "news" explicitly. metadata: - echo: - emoji: 📰 + echo: '{"emoji": "📰"}' --- # News diff --git a/echobot/skills/scrapling/SKILL.md b/echobot/skills/scrapling/SKILL.md index 724e704..59445d1 100644 --- a/echobot/skills/scrapling/SKILL.md +++ b/echobot/skills/scrapling/SKILL.md @@ -1,5 +1,5 @@ --- -name: scrapling-official +name: scrapling description: Scrape web pages using Scrapling with anti-bot bypass (like Cloudflare Turnstile), stealth headless browsing, spiders framework, adaptive scraping, and JavaScript rendering. Use when asked to scrape, crawl, or extract data from websites; web_fetch fails; the site has anti-bot protections; write Python code to scrape/crawl; or write spiders. version: 0.4.2 license: Complete terms in LICENSE.txt diff --git a/echobot/skills/weather/SKILL.md b/echobot/skills/weather/SKILL.md index f15caf0..d19d6f3 100644 --- a/echobot/skills/weather/SKILL.md +++ b/echobot/skills/weather/SKILL.md @@ -8,8 +8,7 @@ description: > macOS, and Windows without any setup. homepage: "https://wttr.in/:help" metadata: - echo: - emoji: 🌤️ + echo: '{"emoji": "🌤️"}' name: weather ---