Commit 96452f09 by Hermes Desktop

feat(skills): update media-delivery

parent 170b389a
No preview for this file type
---
name: media-delivery
description: Send files to users via MEDIA protocol (native attachments) or Markdown links (workspace files) — path rules, Windows quirks, Chinese filename handling, and per-platform limitations.
version: 1.3.0
version: 1.4.0
author: Hermes Agent
platforms: [windows, linux, macos]
metadata:
......@@ -21,358 +21,163 @@ Hermes detects the `MEDIA:` prefix, validates the path against security rules, a
---
## Quick Reference (常见问题速查)
## ⛔ 核心规则(必须遵守)
| 问题现象 | 可能原因 | 解决方案 |
|---------|---------|---------|
| `Skipping unsafe MEDIA directive path` | Windows 路径格式错误 | 使用 `C:/...` 而非 `/c/...` |
| 文件存在但无法下载 | 中文/空格/特殊字符 | 用尖括号 `](</path/文件.docx>)` 或重命名 |
| 文件找不到 | 不在允许目录 | 移到 `~/.hermes/cache/<type>/``~/.hermes/workspace/` |
| 下载失败无报错 | 文件名含中文/空格 | 重命名为英文 或 用尖括号 |
| `File is outside the session and Hermes workspaces` | 文件不在 workspace 内 | 用 MEDIA 协议 或 拷贝到 `workspace/` |
| `.md` 文件无法下载 | 在 cache 目录被限制 | 移到 `workspace/` 目录 |
| MEDIA 路径返回纯文本 | Gateway 未完成初始化 | 等待 5-10 秒或 `hermes gateway restart` |
### 1. 优先级规则
### 两种交付方式对比
**返回下载链接时,优先使用 MEDIA 协议,其次才用 Markdown 链接。**
| 方式 | 语法 | 适用场景 | 路径要求 | 中文文件名 |
|-----|------|---------|---------|-----------|
| **MEDIA 协议** | `MEDIA:/path/to/file` | 原生附件(图片/视频/音频/文档) | cache 目录或 workspace | ✅ 支持 |
| **Markdown 链接** | `[name](/path/to/file)` | 普通文件下载 | **必须在 workspace** | ⚠️ 需尖括号 |
| 优先级 | 方式 | 语法 | 适用场景 |
|-------|------|------|---------|
| **第一选择** | MEDIA 协议 | `MEDIA:/path/to/file` | 原生附件,支持 cache 和 workspace |
| **第二选择** | Markdown 链接 | `[name](/path/to/file)` | MEDIA 不可用时的降级方案,仅限 workspace |
### 路径选择决策树
### 2. 空格规则
```
用户需要下载文件
├─ 文件在 ~/.hermes/cache/* ?
│ └─ 是 → 用 MEDIA 协议 (推荐)
├─ 文件在 ~/.hermes/workspace/ ?
│ └─ 是 → 用 Markdown 链接 (推荐)
│ 或 MEDIA 协议 (也支持)
└─ 文件在其他位置 ?
└─ 复制文件到 workspace 或 cache,然后发送
```
**下载路径中绝对不能包含空格,必须将空格替换为下划线 `_`。**
---
```bash
# ❌ 禁止
MEDIA:/path/my report.pdf
## 1. Path Validation
# ✅ 正确
cp "/原路径/my report.pdf" ~/.hermes/cache/documents/my_report.pdf
MEDIA:~/.hermes/cache/documents/my_report.pdf
```
The gateway's `validate_media_delivery_path()` function enforces a unified security policy for both MEDIA protocol and Markdown link paths.
### 3. 中文和特殊字符
### Allowed Directories (safe roots)
**只要路径没有空格,中文和特殊字符都可以正常使用,不需要尖括号。**
Files **must** live under one of these directories:
```markdown
# ✅ 成功
[申请表.docx](/home/user/.hermes/workspace/申请表.docx)
[文档(1).pdf](/home/user/.hermes/workspace/文档(1).pdf)
```
| Directory | Content type | MEDIA 协议 | Markdown 链接 |
|-----------|-------------|-----------|--------------|
| `~/.hermes/cache/images/` | Images (jpg, png, webp, gif) | ✅ | ⚠️ 不推荐 |
| `~/.hermes/cache/audio/` | Audio (ogg, opus, mp3, wav, m4a, flac) | ✅ | ⚠️ 不推荐 |
| `~/.hermes/cache/videos/` | Video (mp4, mov, avi, mkv, webm, 3gp) | ✅ | ⚠️ 不推荐 |
| `~/.hermes/cache/documents/` | Documents & other files | ✅ | ⚠️ 部分格式限制 |
| `~/.hermes/workspace/` | **Session workspace (推荐)** | ✅ | ✅ **推荐** |
| `~/.hermes/browser_screenshots/` | Screenshots | ✅ | ⚠️ 不推荐 |
| `~/.hermes/image_cache/` | Legacy image cache | ✅ | ⚠️ 不推荐 |
| `~/.hermes/audio_cache/` | Legacy audio cache | ✅ | ⚠️ 不推荐 |
| `~/.hermes/video_cache/` | Legacy video cache | ✅ | ⚠️ 不推荐 |
| `~/.hermes/document_cache/` | Legacy document cache | ✅ | ⚠️ 不推荐 |
---
**推荐做法**
- **MEDIA 协议**:文件放在任意 cache 目录或 workspace
- **Markdown 链接****仅用于 workspace 目录**,避免 cache 目录的格式限制
## 1. 允许的文件目录
To place a file for delivery:
文件必须位于以下目录之一:
```bash
# Option A: Copy to cache directory (for MEDIA protocol)
cp /some/output/report.pdf ~/.hermes/cache/documents/
MEDIA:~/.hermes/cache/documents/report.pdf
| 目录 | 用途 | MEDIA | Markdown |
|-----|------|-------|----------|
| `~/.hermes/cache/images/` | 图片 | ✅ | ⚠️ |
| `~/.hermes/cache/audio/` | 音频 | ✅ | ⚠️ |
| `~/.hermes/cache/videos/` | 视频 | ✅ | ⚠️ |
| `~/.hermes/cache/documents/` | 文档 | ✅ | ⚠️ |
| `~/.hermes/workspace/` | **工作区(推荐)** | ✅ | ✅ |
| `~/.hermes/browser_screenshots/` | 截图 | ✅ | ⚠️ |
| `~/.hermes/{image,audio,video,document}_cache/` | Legacy 缓存 | ✅ | ⚠️ |
# Option B: Copy to workspace (for Markdown links)
cp /some/output/report.pdf ~/.hermes/workspace/
# Then use: [report](/home/lcai/.hermes/workspace/report.pdf)
```
**推荐**:MEDIA 协议用 cache 或 workspace,Markdown 链接仅用 workspace。
### Denied Locations (always rejected)
### 禁止的目录
These are **never** accepted, even in non-strict mode:
以下目录永远被拒绝:
- `/etc`, `/proc`, `/sys`, `/dev`, `/root`, `/boot`, `/var/log`, `/var/lib`, `/var/run`
- `~/.ssh/`, `~/.aws/`, `~/.gnupg/`, `~/.kube/`, `~/.docker/`
- `~/.hermes/.env`, `~/.hermes/auth.json`, and other credential stores under HERMES_HOME
### Strict Mode
Opt-in via `config.yaml` -> `gateway.strict: true` or `HERMES_MEDIA_DELIVERY_STRICT=1`. In strict mode, files are only accepted if they:
1. Live under an allowlisted root (safe roots above), **or**
2. Were **recently produced** (within the recency window, default 1 second)
Use `HERMES_MEDIA_ALLOW_DIRS` env var to add custom allowlisted roots in strict mode.
- `~/.hermes/.env`, `~/.hermes/auth.json` 等凭据文件
---
## 2. Path Format
### 2.1 Windows Path Format (CRITICAL GOTCHA)
## 2. Windows 路径格式(关键)
**On Windows, always use `C:/Users/...` format, NOT `/c/Users/...` (git-bash/MSYS format).**
**Windows 上必须使用 `C:/Users/...` 格式,不能用 `/c/Users/...`(git-bash 格式)。**
The MEDIA validation runs through Python's `Path.resolve(strict=True)`, which on Windows interprets `/c/Users/...` as a **relative** path (`\c\Users\...` off the current C: drive), not an absolute one. This causes the file to be reported as nonexistent and the path to be skipped as "unsafe".
| Correct ✅ | Wrong ❌ |
|-----------|---------|
| 正确 ✅ | 错误 ❌ |
|---------|---------|
| `MEDIA:C:/Users/...` | `MEDIA:/c/Users/...` |
| `MEDIA:C:\Users\...` | `MEDIA:/C:/Users/...` |
Forward slashes (`C:/Users/...`) work fine — both `Path.resolve()` and Windows APIs accept them.
#### Quick fix when coming from terminal
When you create or find a file in terminal (where `/c/Users/...` paths work), copy it to a cache dir and reference it with the Windows-form path:
```bash
# Terminal (git-bash) — works fine here
# 终端(git-bash)中可以正常使用
cp /c/Users/Administrator/report.pdf ~/.hermes/cache/documents/
# In response — MUST use Windows format
# 响应中必须用 Windows 格式
MEDIA:C:/Users/Administrator/.hermes/cache/documents/report.pdf
```
### 2.2 空格与中文文件名处理 (CRITICAL)
**文件名包含空格、中文或特殊字符时,Markdown 链接需要特殊处理。**
#### 问题示例
```markdown
# ❌ 失败 - 中文文件名
[申请表.docx](/home/lcai/.hermes/workspace/申请表.docx)
# ❌ 失败 - 空格文件名
[my report.pdf](/home/lcai/.hermes/workspace/my report.pdf)
# ✅ 成功 - 使用尖括号包裹
[申请表.docx](</home/lcai/.hermes/workspace/申请表.docx>)
[my report.pdf](</home/lcai/.hermes/workspace/my report.pdf>)
```
#### 规则总结
| 文件名特征 | MEDIA 协议 | Markdown 链接 (无尖括号) | Markdown 链接 (有尖括号) | 推荐做法 |
|-----------|-----------|---------|---------|---------|
| 纯英文无空格 | ✅ | ✅ | ✅ | 任意格式 |
| 英文有空格 | ✅ | ❌ | ✅ | **Markdown 用尖括号** |
| 含中文 | ✅ | ❌ | ✅ | **MEDIA 优先 或 Markdown 用尖括号** |
| 含特殊字符 `()[]#?` | ✅ | ❌ | ✅ | **MEDIA 优先 或 Markdown 用尖括号** |
#### 三种解决方案(按推荐优先级排序)
**方案 A: 使用 MEDIA 协议(推荐)**
```
MEDIA:/home/lcai/.hermes/workspace/2026 年申请表.docx
```
✅ 原生支持中文文件名,无需特殊处理
**方案 B: 使用尖括号(Markdown 链接)**
```markdown
[2026 年申请表](</home/lcai/.hermes/workspace/2026 年申请表.docx>)
```
⚠️ 必须用尖括号包裹路径
**方案 C: 重命名为英文(最佳兼容性)**
```bash
mv "2026 年申请表.docx" "2026-Application-Form.docx"
```
```markdown
[2026 年申请表](/home/lcai/.hermes/workspace/2026-Application-Form.docx)
```
✅ 避免所有格式问题
#### 文件位置选择
- **workspace 目录**:✅ 支持 Markdown 链接和 MEDIA 协议
- **cache 目录**:⚠️ 仅推荐 MEDIA 协议,部分格式(如 `.md`)可能被限制
---
## 3. File-Type Detection
## 3. 文件类型检测
The gateway auto-detects the content type from the file extension:
Gateway 自动根据扩展名检测内容类型:
| Extension | Sent as |
|-----------|---------|
| `.jpg`, `.jpeg`, `.png`, `.webp`, `.gif` | Image (native preview on most platforms) |
| `.mp4`, `.mov`, `.avi`, `.mkv`, `.webm`, `.3gp` | Video (inline playback on supported platforms) |
| `.ogg`, `.opus`, `.mp3`, `.wav`, `.m4a`, `.flac` | Audio (or voice if `is_voice=True`) |
| Everything else (`.pdf`, `.md`, `.txt`, `.zip`, etc.) | Document (downloadable attachment) |
| 扩展名 | 发送为 |
|--------|--------|
| `.jpg`, `.jpeg`, `.png`, `.webp`, `.gif` | 图片(支持预览) |
| `.mp4`, `.mov`, `.avi`, `.mkv`, `.webm`, `.3gp` | 视频(支持播放) |
| `.ogg`, `.opus`, `.mp3`, `.wav`, `.m4a`, `.flac` | 音频 |
| 其他(`.pdf`, `.md`, `.txt`, `.zip` 等) | 文档(可下载附件) |
---
## 4. Per-Platform Notes
### Weixin / WeChat (微信)
- MEDIA protocol IS supported
- Image delivery works reliably (images extracted from markdown `![]()` are also sent)
- File/document delivery works, but may have size limits (~100MB)
- Voice messages supported via `MEDIA_VOICE` type
- Path validation is strict — files MUST be in a cache directory and path MUST resolve through Python
- 中文文件名处理详见 [2.2 节](#22-空格与中文文件名处理-critical)
### Telegram
- MEDIA protocol fully supported
- Images, video, audio, documents all work
- Larger file size limit (~2GB)
## 4. 平台限制
### Discord / Slack
- MEDIA protocol supported
- File-type restrictions may apply per platform
- Discord: 25MB (free), 500MB (Nitro)
### WhatsApp / Other Platforms
- MEDIA protocol supported via gateway
- Platform-specific size and type limits apply
| 平台 | MEDIA 支持 | 文件大小限制 | 备注 |
|------|-----------|-------------|------|
| 微信/WeChat | ✅ | ~100MB | 路径验证严格,必须用 cache 目录 |
| Telegram | ✅ | ~2GB | 完全支持 |
| Discord | ✅ | 25MB (免费) / 500MB (Nitro) | 可能有文件类型限制 |
| Slack | ✅ | 平台限制 | 可能有文件类型限制 |
| WhatsApp | ✅ | 平台限制 | 通过 gateway 支持 |
---
## 5. Client Chat File Delivery Workflow
When sending files to users during interactive chat sessions, follow this workflow:
### Step 1: Generate or Locate the File
Files can come from various sources:
- **Terminal output**: Logs, reports, data exports
- **Screenshots**: Browser captures, desktop screenshots
- **Code artifacts**: Generated code, config files, test results
- **Media**: Audio recordings, video clips, images
- **Documents**: PDFs, markdown files, spreadsheets
### Step 2: Move File to Cache Directory
## 5. 文件交付流程
**Always copy files to an appropriate cache directory before sending:**
### 步骤 1:复制文件到允许目录
```bash
# For documents (reports, logs, configs)
# 文档
cp /path/to/file ~/.hermes/cache/documents/
# For images (screenshots, diagrams)
# 图片
cp /path/to/image ~/.hermes/cache/images/
# For audio (recordings, synthesized speech)
# 音频/视频
cp /path/to/audio ~/.hermes/cache/audio/
# For videos (recordings, animations)
cp /path/to/video ~/.hermes/cache/videos/
```
**Quick one-liner pattern:**
```bash
# Copy and rename in one step
cp output.log ~/.hermes/cache/documents/chat-session-$(date +%Y%m%d-%H%M%S).log
```
### Step 3: Send with Correct Path Format
### 步骤 2:发送 MEDIA 指令
**Linux/macOS:**
```
MEDIA:~/.hermes/cache/documents/your-file.txt
```
**Windows (CRITICAL):**
**Windows:**
```
MEDIA:C:/Users/YourUsername/.hermes/cache/documents/your-file.txt
```
**Never use:**
- `MEDIA:/c/Users/...` (git-bash format - fails on Windows)
- `MEDIA:~/...` (tilde expansion not reliable)
- `MEDIA:./...` (relative paths - always rejected)
### Common Chat Scenarios
#### Scenario 1: Sending Terminal Output
```bash
your-command > /tmp/output.log
cp /tmp/output.log ~/.hermes/cache/documents/
MEDIA:C:/Users/YourUsername/.hermes/cache/documents/output.log
```
#### Scenario 2: Sending a Screenshot
```bash
screencapture -i ~/.hermes/cache/images/screenshot-$(date +%s).png
MEDIA:~/.hermes/cache/images/screenshot-1234567890.png
```
#### Scenario 3: Sending Generated Code
```bash
cat > ~/.hermes/cache/documents/solution.py << 'EOF'
# Your generated code here
EOF
MEDIA:~/.hermes/cache/documents/solution.py
```
#### Scenario 4: Sending Data Export
```bash
python export_data.py --output /tmp/data.csv
cp /tmp/data.csv ~/.hermes/cache/documents/
MEDIA:C:/Users/YourUsername/.hermes/cache/documents/data.csv
```
### Best Practices
1. **Use descriptive filenames**: Include timestamp or context
-`error-log-2026-07-22-143052.txt`
-`temp.txt`
2. **Clean up old cache files**: Periodically remove files older than 24 hours
```bash
find ~/.hermes/cache -type f -mtime +1 -delete
```
3. **Verify file exists before sending**:
```python
python -c "from pathlib import Path; print('✅' if Path('path').exists() else '❌')"
```
4. **Don't send sensitive data**: Never place credentials, tokens, or private keys in cache directories
**禁止使用:**
- `MEDIA:/c/Users/...`(git-bash 格式)
- `MEDIA:~/...`(波浪号不可靠)
- `MEDIA:./...`(相对路径)
---
## 6. Diagnostic Checklist
If MEDIA delivery fails, check in this order:
1. **Check gateway logs**:
```bash
grep "MEDIA\|media" ~/.hermes/logs/gateway.log
```
Look for "Skipping unsafe" or "media delivery failed"
2. **Verify file exists** (use Python, not bash):
```python
python -c "import pathlib; print(pathlib.Path('path').resolve(strict=True))"
```
## 6. 常见问题排查
3. **Check path format** (Windows): must be `C:/...` not `/c/...`
4. **Verify location**: file must be under `~/.hermes/cache/<type>/` or another safe root
5. **Check filename for Chinese/special characters**: 详见 [2.2 节](#22-空格与中文文件名处理-critical)
6. **Check file permissions**: must be a regular file (not a symlink to a denied location)
| 问题 | 原因 | 解决方案 |
|------|------|---------|
| `Skipping unsafe MEDIA directive path` | Windows 路径格式错误 | 使用 `C:/...` 而非 `/c/...` |
| 文件存在但无法下载 | 路径含空格 | 复制时将空格替换为 `_` |
| 文件找不到 | 不在允许目录 | 移到 cache 或 workspace |
| `File is outside the session and Hermes workspaces` | 不在 workspace | 用 MEDIA 协议或拷贝到 workspace |
| MEDIA 路径返回纯文本 | Gateway 未初始化 | 等待 5-10 秒或 `hermes gateway restart` |
7. **Try restarting gateway**:
```bash
hermes gateway restart
```
Helps if cache dirs were created mid-session, or gateway not fully initialized
### 诊断步骤
8. **Check workspace security policy**:
- WebUI 文件下载链接只允许 **session workspace**`~/.hermes/workspace/` 内的文件
- `~/.hermes/cache/` 不在 workspace 内,会报错 `File is outside the session and Hermes workspaces`
- 解决方案:用 MEDIA 协议 或 拷贝到 workspace
- See: `references/workspace-security-policy.md` for details
1. **检查 gateway 日志**`grep "MEDIA\|media" ~/.hermes/logs/gateway.log`
2. **验证文件存在**`python -c "import pathlib; print(pathlib.Path('path').resolve(strict=True))"`
3. **检查路径格式**(Windows):必须是 `C:/...` 不是 `/c/...`
4. **验证目录**:文件必须在允许的目录下
5. **重启 gateway**`hermes gateway restart`
---
......@@ -380,4 +185,4 @@ If MEDIA delivery fails, check in this order:
- [`hermes-agent`](hermes-agent): Configure Hermes itself
- [`markdown-viewer`](markdown-viewer): Create visual diagrams and charts
- [`computer-use`](computer-use): Take screenshots for delivery
\ No newline at end of file
- [`computer-use`](computer-use): Take screenshots for delivery
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment