Commit 96452f09 by Hermes Desktop

feat(skills): update media-delivery

parent 170b389a
No preview for this file type
--- ---
name: media-delivery 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. 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 author: Hermes Agent
platforms: [windows, linux, macos] platforms: [windows, linux, macos]
metadata: metadata:
...@@ -21,358 +21,163 @@ Hermes detects the `MEDIA:` prefix, validates the path against security rules, a ...@@ -21,358 +21,163 @@ Hermes detects the `MEDIA:` prefix, validates the path against security rules, a
--- ---
## Quick Reference (常见问题速查) ## ⛔ 核心规则(必须遵守)
| 问题现象 | 可能原因 | 解决方案 | ### 1. 优先级规则
|---------|---------|---------|
| `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` |
### 两种交付方式对比 **返回下载链接时,优先使用 MEDIA 协议,其次才用 Markdown 链接。**
| 方式 | 语法 | 适用场景 | 路径要求 | 中文文件名 | | 优先级 | 方式 | 语法 | 适用场景 |
|-----|------|---------|---------|-----------| |-------|------|------|---------|
| **MEDIA 协议** | `MEDIA:/path/to/file` | 原生附件(图片/视频/音频/文档) | cache 目录或 workspace | ✅ 支持 | | **第一选择** | MEDIA 协议 | `MEDIA:/path/to/file` | 原生附件,支持 cache 和 workspace |
| **Markdown 链接** | `[name](/path/to/file)` | 普通文件下载 | **必须在 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 | ✅ | ⚠️ 不推荐 |
**推荐做法** ## 1. 允许的文件目录
- **MEDIA 协议**:文件放在任意 cache 目录或 workspace
- **Markdown 链接****仅用于 workspace 目录**,避免 cache 目录的格式限制
To place a file for delivery: 文件必须位于以下目录之一:
```bash | 目录 | 用途 | MEDIA | Markdown |
# Option A: Copy to cache directory (for MEDIA protocol) |-----|------|-------|----------|
cp /some/output/report.pdf ~/.hermes/cache/documents/ | `~/.hermes/cache/images/` | 图片 | ✅ | ⚠️ |
MEDIA:~/.hermes/cache/documents/report.pdf | `~/.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) **推荐**:MEDIA 协议用 cache 或 workspace,Markdown 链接仅用 workspace。
cp /some/output/report.pdf ~/.hermes/workspace/
# Then use: [report](/home/lcai/.hermes/workspace/report.pdf)
```
### 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` - `/etc`, `/proc`, `/sys`, `/dev`, `/root`, `/boot`, `/var/log`, `/var/lib`, `/var/run`
- `~/.ssh/`, `~/.aws/`, `~/.gnupg/`, `~/.kube/`, `~/.docker/` - `~/.ssh/`, `~/.aws/`, `~/.gnupg/`, `~/.kube/`, `~/.docker/`
- `~/.hermes/.env`, `~/.hermes/auth.json`, and other credential stores under HERMES_HOME - `~/.hermes/.env`, `~/.hermes/auth.json` 等凭据文件
### 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.
--- ---
## 2. Path Format ## 2. Windows 路径格式(关键)
### 2.1 Windows Path Format (CRITICAL GOTCHA)
**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/...` |
| `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 ```bash
# Terminal (git-bash) — works fine here # 终端(git-bash)中可以正常使用
cp /c/Users/Administrator/report.pdf ~/.hermes/cache/documents/ 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 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) | | `.jpg`, `.jpeg`, `.png`, `.webp`, `.gif` | 图片(支持预览) |
| `.mp4`, `.mov`, `.avi`, `.mkv`, `.webm`, `.3gp` | Video (inline playback on supported platforms) | | `.mp4`, `.mov`, `.avi`, `.mkv`, `.webm`, `.3gp` | 视频(支持播放) |
| `.ogg`, `.opus`, `.mp3`, `.wav`, `.m4a`, `.flac` | Audio (or voice if `is_voice=True`) | | `.ogg`, `.opus`, `.mp3`, `.wav`, `.m4a`, `.flac` | 音频 |
| Everything else (`.pdf`, `.md`, `.txt`, `.zip`, etc.) | Document (downloadable attachment) | | 其他(`.pdf`, `.md`, `.txt`, `.zip` 等) | 文档(可下载附件) |
--- ---
## 4. Per-Platform Notes ## 4. 平台限制
### 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)
### Discord / Slack | 平台 | MEDIA 支持 | 文件大小限制 | 备注 |
- MEDIA protocol supported |------|-----------|-------------|------|
- File-type restrictions may apply per platform | 微信/WeChat | ✅ | ~100MB | 路径验证严格,必须用 cache 目录 |
- Discord: 25MB (free), 500MB (Nitro) | Telegram | ✅ | ~2GB | 完全支持 |
| Discord | ✅ | 25MB (免费) / 500MB (Nitro) | 可能有文件类型限制 |
### WhatsApp / Other Platforms | Slack | ✅ | 平台限制 | 可能有文件类型限制 |
- MEDIA protocol supported via gateway | WhatsApp | ✅ | 平台限制 | 通过 gateway 支持 |
- Platform-specific size and type limits apply
--- ---
## 5. Client Chat File Delivery Workflow ## 5. 文件交付流程
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
**Always copy files to an appropriate cache directory before sending:** ### 步骤 1:复制文件到允许目录
```bash ```bash
# For documents (reports, logs, configs) # 文档
cp /path/to/file ~/.hermes/cache/documents/ cp /path/to/file ~/.hermes/cache/documents/
# For images (screenshots, diagrams) # 图片
cp /path/to/image ~/.hermes/cache/images/ cp /path/to/image ~/.hermes/cache/images/
# For audio (recordings, synthesized speech) # 音频/视频
cp /path/to/audio ~/.hermes/cache/audio/ cp /path/to/audio ~/.hermes/cache/audio/
# For videos (recordings, animations)
cp /path/to/video ~/.hermes/cache/videos/ cp /path/to/video ~/.hermes/cache/videos/
``` ```
**Quick one-liner pattern:** ### 步骤 2:发送 MEDIA 指令
```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
**Linux/macOS:** **Linux/macOS:**
``` ```
MEDIA:~/.hermes/cache/documents/your-file.txt MEDIA:~/.hermes/cache/documents/your-file.txt
``` ```
**Windows (CRITICAL):** **Windows:**
``` ```
MEDIA:C:/Users/YourUsername/.hermes/cache/documents/your-file.txt MEDIA:C:/Users/YourUsername/.hermes/cache/documents/your-file.txt
``` ```
**Never use:** **禁止使用:**
- `MEDIA:/c/Users/...` (git-bash format - fails on Windows) - `MEDIA:/c/Users/...`(git-bash 格式)
- `MEDIA:~/...` (tilde expansion not reliable) - `MEDIA:~/...`(波浪号不可靠)
- `MEDIA:./...` (relative paths - always rejected) - `MEDIA:./...`(相对路径)
### 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
--- ---
## 6. Diagnostic Checklist ## 6. 常见问题排查
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))"
```
3. **Check path format** (Windows): must be `C:/...` not `/c/...` | 问题 | 原因 | 解决方案 |
|------|------|---------|
4. **Verify location**: file must be under `~/.hermes/cache/<type>/` or another safe root | `Skipping unsafe MEDIA directive path` | Windows 路径格式错误 | 使用 `C:/...` 而非 `/c/...` |
| 文件存在但无法下载 | 路径含空格 | 复制时将空格替换为 `_` |
5. **Check filename for Chinese/special characters**: 详见 [2.2 节](#22-空格与中文文件名处理-critical) | 文件找不到 | 不在允许目录 | 移到 cache 或 workspace |
| `File is outside the session and Hermes workspaces` | 不在 workspace | 用 MEDIA 协议或拷贝到 workspace |
6. **Check file permissions**: must be a regular file (not a symlink to a denied location) | 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**: 1. **检查 gateway 日志**`grep "MEDIA\|media" ~/.hermes/logs/gateway.log`
- WebUI 文件下载链接只允许 **session workspace**`~/.hermes/workspace/` 内的文件 2. **验证文件存在**`python -c "import pathlib; print(pathlib.Path('path').resolve(strict=True))"`
- `~/.hermes/cache/` 不在 workspace 内,会报错 `File is outside the session and Hermes workspaces` 3. **检查路径格式**(Windows):必须是 `C:/...` 不是 `/c/...`
- 解决方案:用 MEDIA 协议 或 拷贝到 workspace 4. **验证目录**:文件必须在允许的目录下
- See: `references/workspace-security-policy.md` for details 5. **重启 gateway**`hermes gateway restart`
--- ---
...@@ -380,4 +185,4 @@ If MEDIA delivery fails, check in this order: ...@@ -380,4 +185,4 @@ If MEDIA delivery fails, check in this order:
- [`hermes-agent`](hermes-agent): Configure Hermes itself - [`hermes-agent`](hermes-agent): Configure Hermes itself
- [`markdown-viewer`](markdown-viewer): Create visual diagrams and charts - [`markdown-viewer`](markdown-viewer): Create visual diagrams and charts
- [`computer-use`](computer-use): Take screenshots for delivery - [`computer-use`](computer-use): Take screenshots for delivery
\ No newline at end of file
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