用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/arm2arm/AstroAgentAssistant --skill api-server-media-display命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | api-server-media-display |
| description | Diagnose and fix images not displaying in Open WebUI / API server frontends. |
| version | 1.1.0 |
| author | Hermes Agent |
| license | MIT |
| metadata | {"hermes":{"tags":["api-server","open-webui","media","images","devops"]}} |
Ensure images generated by the agent render correctly in Open WebUI and other API server frontends.
The on_media_deliver hook only fires for Telegram, Discord, and other messaging platform sessions. The API server has its own media path and does NOT trigger hooks — it relies on _convert_media_to_http_urls() to convert image references into http://host:port/media/<hash> URLs that the _handle_media route can serve.
If an image doesn't display in Open WebUI, the conversion pipeline likely missed the image format.
_convert_media_to_http_urls)DATA_URI_RE — matches MEDIA_TAG_RE — matches MEDIA:/path/to/fileLOCAL_PATH_MD_RE — matches  ← often missingCheck gateway/platforms/api_server.py:
LOCAL_PATH_MD_RE exist? (regex for )_convert_local_path_image handler present?LOCAL_PATH_MD_RE.sub(...) called in the pipeline?self._app.router.add_get("/media/{filename}", self._handle_media) called?host and _convert_media_to_http_urls called in both the chat completion handler and the SSE streaming handler?Common symptom: Open WebUI shows a broken image icon or the raw markdown text  instead of rendering the image.
Add to the imports/patterns section (after existing regexes):
# Regex for standard markdown images with local file paths: 
## When to Use
Diagnose and fix images not displaying in Open WebUI / API server frontends.
## Overview
This skill contains a reusable operational workflow. Follow the existing task-specific steps and examples in the sections below.
LOCAL_PATH_MD_RE = re.compile(
r'!\\[([^\\]]*)\\]\\(\\s*(/[\\w./\\-]+\\.[\\w]{2,4})\\s*\\)'
)
Add handler inside _convert_media_to_http_urls() (after existing handlers):
def _convert_local_path_image(match):
"""Convert standard markdown with local file path to HTTP URL."""
alt_text = match.group(1)
file_path = match.group(2)
if not file_path.startswith("/"):
return match.group(0)
ext = os.path.splitext(file_path)[1].lower()
if ext not in ALLOWED_MEDIA_EXTENSIONS:
return match.group(0)
if not os.path.isfile(file_path):
return match.group(0)
try:
with open(file_path, "rb") as f:
file_bytes = f.read()
except Exception:
return match.group(0)
content_hash = hashlib.sha256(file_bytes).hexdigest()[:16]
filename = f"{content_hash}{ext}"
dest_path = os.path.join(media_dir, filename)
if not os.path.exists(dest_path):
import shutil
shutil.copy2(file_path, dest_path)
return f""
Add to pipeline (after other conversions):
result = LOCAL_PATH_MD_RE.sub(_convert_local_path_image, result)
Restart the gateway — changes to api_server.py require a restart:
kill $(cat ~/.hermes/gateway.pid) 2>/dev/null || pkill -f "hermes gateway"
hermes gateway
Check syntax before restarting:
python3 -m py_compile ~/.hermes/hermes-agent/gateway/platforms/api_server.py
Test via curl (if gateway is running):
curl http://localhost:8642/v1/chat/completions \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"model": "hermes-agent", "messages": [{"role": "user", "content": "Generate a simple plot"}], "stream": false}'
Inspect the response — verify it contains http://127.0.0.1:8642/media/<hash>.png not /tmp/... local paths.
Open WebUI — navigate to the conversation and verify the image renders inline.
/tmp/hermes-api-media/ to map hashes backhost = request.host and _convert_media_to_http_urls(item, host))skills-repo-maintenance — for publishing skills to the AstroAgentAssistant GitHub repo