Files
nexus/openclaw/yunce/TOOLS.md

536 lines
19 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TOOLS管理
## 统一SSH管理
- **所有服务器**: 包括macmini、ubuntu1、ubuntu2、NAS
- **管理方式**: 通过SSH统一管理不存储sudo密码
- **权限原则**: 遵循最小权限原则
## 管理流程
1. 所有服务器操作都通过SSH进行
2. 不存储任何服务器的sudo密码
3. 需要sudo权限的操作通过SSH执行
4. 保持所有服务器的管理方式一致
## Docker命令路径
- **macmini**: `/usr/local/bin/docker``/opt/homebrew/bin/docker`SSH时PATH不包含docker
- **NAS**: `/usr/local/bin/docker`(使用 `docker-compose` 而非 `docker compose`
- **ubuntu1/ubuntu2**: 直接用 `docker`
## 文件编辑注意事项
- **所有重要文件**: 使用 `exec + echo` 追加内容,避免 edit 工具在文件末尾无换行时失败
- **edit工具使用准则**: edit依赖精确文本匹配任何空白字符差异都会导致失败。建议先 read 文件确认内容,用 write 重写整个文件更可靠(特别是 memory、SOUL、IDENTITY 等重要文件)
## FRP (frpc 客户端) 管理
### 安装目录
| 服务器 | FRP目录 |
| ------- | -------------------------------- |
| macmini | /opt/frp/frp_0.65.0_darwin_arm64 |
| ubuntu1 | /opt/frp/frp_0.65.0_linux_amd64 |
| ubuntu2 | /opt/frp/frp_0.65.0_linux_amd64 |
### 配置文件
- **文件名**: `frpc.toml`在FRP目录下
- **作用**: 定义所有通过frp反向代理的应用及端口映射 (localPort ↔ remotePort)
### 管理方式通过tmux
1. 切换到root用户: `sudo su`
2. 进入FRP目录: `cd /opt/frp/frp_xxx`
3. 连接到tmux会话: `tmux attach -t frpc`
4. 停止进程: `Ctrl+C`
5. 重启frpc: `./frpc -c frpc.toml`
6. 查看启动是否成功
### 查看配置
```bash
# 读取frpc.toml了解端口映射
cat /opt/frp/frp_0.65.0_xxx/frpc.toml
```
## FRP端口映射查询格式 (2026-03-14)
用户会这样提问:
- "ubuntu1上frp的列表"
- "macmini的frp配置"
- "查看ubuntu2的frpc.toml"
格式: 扫描frpc.toml文件列出proxies相关配置
输出格式: 表格 (名称 | 类型 | localPort | remotePort)
查询示例: ssh到对应服务器 -> cat /opt/frp/frp_0.65.0_xxx/frpc.toml
## FRP状态检查 (2026-03-14)
用户可能说: "检查frp状态"
**检查方法**:
1. SSH到对应服务器
2. 切换root: `sudo su`
3. 进入FRP目录: `cd /opt/frp/frp_xxx`
4. 如果是macmini服务器连接tmux: `tmux attach -t frpc`
5. 如果是ubuntu服务器`systemctl status frpc`
6. 查看日志输出
**正常状态标志**:
- 所有 proxy 启动成功时会显示: `[xxx] [name] start proxy success`
- 例如: `2026-03-14 20:49:36.007 [I] [client/control.go:172] [65f4a34a064fae9e] [transmission] start proxy success`
**重启命令** (如果需要):
1. 如果是macmini服务器
- `Ctrl+C` 停止当前进程
- `./frpc -c frpc.toml` 重启
2. 如果是ubuntu服务器
- `systemctl stop frpc` `systemctl start frpc` `systemctl restart frpc`
## VPS2 (x-UI 科学上网)
- **IP**: 104.194.92.188
- **SSH**: `ssh vps2`
- **管理命令**: `x-ui`
- **用途**: x-UI 面板管理,用于科学上网
- 结果展示用列表方式,方便阅读
## 笔记系统
用户可能说: "请帮我记笔记"、"帮我把这篇文章保存在笔记目录"、"请读取知识库笔记目录下的这篇笔记"
使用obsidian skill 读取/保存/修改Markdown笔记
Macmini服务器上
- **Obsidian笔记目录**: `/Users/weishen/Workspace/nexus`
- **Openclaw笔记目录**: `/Users/weishen/Workspace/nexus/openclaw`
- **知识库笔记目录**: `/Users/weishen/Workspace/nexus/openclaw/knowledgebase`
- **云策专属笔记目录**: `/Users/weishen/Workspace/nexus/openclaw/yunce`
## 网络测试策略 (2026-03-15)
用户可能说: "网络测试"、"检查服务器科学上网"
**测试项目**:
1. 国内直连baidu (https://www.baidu.com)
2. 国外直连 Google (https://www.google.com)
3. 国外通过代理访问 Google (socks5://127.0.0.1:10808)
**测试命令模板**:
**国内访问直连**
```
curl -v https://www.baidu.com
```
**国外访问直连**
```
curl -v https://www.google.com
```
**国外访问通过代理连**
这是最快、最直接的方法。我们可以强制 `curl` 使用 SOCKS5 代理去访问 Google 的状态页。
**执行命令:**
```
curl -x socks5h://127.0.0.1:10808 -v https://www.google.com
```
- **参数解释:**
    - `-x socks5h://`:指定使用 SOCKS5 代理。注意加个 `h`,这表示让代理服务器去解析域名(防止本地 DNS 污染导致测试失败)。
    - `-v`(Verbose) 显示详细连接过程。
- **判断标准:**    
    - 如果看到 `HTTP/2 200` 或者大量的 HTML 文本,说明**代理成功**。
    - 如果显示 `Connection refused``Timeout`,说明**端口未开放或 V2Ray 未运行**。
**服务器列表与代理端口**:
| 服务器 | IP | 代理端口 | 备注 |
|--------|-----|---------|------|
| MacMini | 192.168.3.189 | 10808 | V2RayN |
| Ubuntu1 | 192.168.3.47 | 10808 | 需SSH后测试 |
| Ubuntu2 | 192.168.3.45 | 10808 | 需SSH后测试 |
| NAS | 192.168.3.17 | 20170 | 仅监听127.0.0.1 |
| VPS1 | 192.227.222.142 | - | 直连正常 |
| VPS2 | 104.194.92.188 | - | 直连正常 |
**输出格式**: 列表方式,方便阅读
**网络测试输出格式**
用户要求格式示例:
• 服务器名
  • 国内访问直连: ✅/❌
  • 国外访问直连: ✅/❌
  • 国外访问通过代理XXX连: ✅/❌
 
## Telegram 配置注意事项 (2026-03-15)
- groupPolicy=allowlist 时必须配置 groupAllowFrom否则群消息被静默丢弃
- 中国访问Telegram API需要配置代理 (proxy)
- 代理协议必须是 http:// 或 socks5://
- Bot 的 has_topics_enabled: false不支持 Telegram Topics 功能
## OpenClaw 命令路径 (2026-03-27)
| 服务器 | OpenClaw 路径 |
| -------- | ---------------------------------------- |
| Mac mini | `/opt/homebrew/bin/openclaw` |
| Ubuntu1 | `/home/shenwei/.npm-global/bin/openclaw` |
| Ubuntu2 | `/home/shenwei/.npm-global/bin/openclaw` |
## NAS Docker 代理配置 (2026-03-27)
- **配置文件**: `/etc/systemd/system/pkg-ContainerManager-dockerd.service.d/http-proxy.conf`
- **用途**: Synology NAS 上 Docker 守护进程的代理设置
- **修改后需执行**: `sudo systemctl daemon-reload && sudo systemctl restart docker`
**使用方式**:
- SSH 到对应服务器后,使用完整路径执行命令
- 例如: `ssh ubuntu1 '/home/shenwei/.npm-global/bin/openclaw status'`
## sag (TTS 语音生成) (2026-03-27)
### 安装
```bash
brew install steipete/tap/sag
```
### API Key 配置
- 位置: `~/.openclaw/.env`
- 环境变量: `ELEVENLABS_API_KEY`
### 生成语音并发送到 Telegram
```bash
# 1. 生成 MP3 文件
source ~/.openclaw/.env
sag --api-key "$ELEVENLABS_API_KEY" -o /tmp/voice.mp3 "要转换的文字"
# 2. 发送到 Telegram (voice note)
message --account <telegram bot> --chatId <user_id> --filePath /tmp/voice.mp3 --message "文字" --buttons []
```
### 使用规则
- 所有用 sag 生成的语音都必须通过 Telegram voice note 发送给我
- 使用 当前agent对应的telegram bot 账号发送
- 文件临时保存在 /tmp/ 目录
### OpenCode
- **路径**: `/Users/weishen/.opencode/bin/opencode`
- **版本**: 1.2.27
- **用法**: 开发任务必须通过它执行
## Nexus Git 仓库配置
当用户说 "请帮我把这个笔记push到Git"
用于提交Obsidian笔记目录里的笔记进行版本控制管理
- **Remote URL**: `ssh://git@192.168.3.189:2222/admin/nexus.git`
- **SSH认证**: 已配置osxkeychain无需输入用户名密码
- **可直接执行**: git add → git commit → git push
- **用户名**: weishen
- **邮箱**: ishenwei@gmail.com
## AgentMail (邮件收发与自动化) (2026-03-28)
### 安装
```
npm install -g @clawhub/agentmail
```
### API Key / 账号配置
- 位置: `~/.openclaw/.env`
- 环境变量:
AGENTMAIL_API_KEY=your_api_key
AGENTMAIL_EMAIL=your_email@example.com
AGENTMAIL_PROVIDER=imap_smtp # 或 gmail / outlook
AGENTMAIL_IMAP_HOST=imap.example.com
AGENTMAIL_SMTP_HOST=smtp.example.com
AGENTMAIL_PASSWORD=your_password_or_app_password
> ⚠️ 建议使用 **App Password**(如 Gmail / Outlook避免主密码暴露
### 发送邮件
```
agentmail send \
--to "target@example.com" \
--subject "测试邮件" \
--body "这是一封由 Agent 自动发送的邮件"
```
#### 带附件发送
```
agentmail send \
--to "target@example.com" \
--subject "报告文件" \
--body "请查收附件" \
--attachments "/tmp/report.pdf,/tmp/log.txt"
```
### 收取邮件
```
agentmail fetch \
--limit 10 \
--unread true
```
#### 输出为 JSON方便 Agent 处理)
```
agentmail fetch \
--limit 20 \
--format json > /tmp/mails.json
```
### 搜索邮件
```
agentmail search \
--query "from:boss@example.com subject:urgent" \
--limit 5
```
### 自动化处理(典型 Agent 场景)
#### 1⃣ 拉取未读邮件并分类
```
agentmail fetch --unread true --format json > /tmp/unread.json
```
#### 2⃣ 解析后自动回复
```
agentmail send \
--to "<extracted_email>" \
--subject "Re: <original_subject>" \
--body "已收到您的邮件,我们会尽快处理"
```
#### 3⃣ 保存关键邮件到 Markdown用于知识库 / Daily Notes
```
agentmail fetch --limit 10 --format markdown > /tmp/mails.md
```
### 与 Telegram 联动(通知类)
```
agentmail fetch --unread true --format text > /tmp/mail.txt
```
```
message \
--account <telegram bot> \
--chatId <user_id> \
--message "$(cat /tmp/mail.txt)"
```
### 使用规则
- 所有 **重要邮件(如告警 / 客户 / 商机)必须同步到 Telegram**
- 邮件正文必须经过摘要处理(避免噪音信息)
- 附件文件统一下载到 `/tmp/` 目录再处理
- 自动回复必须符合上下文语义,避免机械回复
- 对于批量邮件处理,优先输出 JSON 供 Agent 决策
- 敏感邮件(如包含凭证 / 密钥)禁止自动转发
## Obsidian笔记同步 (2026-03-28)
用户可能说: "请帮我同步一下Obsidian笔记"、"请帮我把这篇笔记push到Git"、"请同步iCloud Obsidian笔记目录"
### 使用规则
1. 打开Macmini上的终端
2. 先把Obsidian笔记目录(`/Users/weishen/Workspace/nexus`)里新增内容添加到Git, 并添加备注并push到Git
3. 再做一次`git pull`把Git上最新的内容同步到Obsidian笔记目录(`/Users/weishen/Workspace/nexus`)
4. 进入iCloud Obsidian目录 `/Users/weishen/Library/Mobile\ Documents/iCloud~md~obsidian/Documents/nexus`
5. 再执行一次`git pull`
6. 如果push成功可以把commit id告诉用户。
7. 如果pull成功也可以告诉用户目录已经更新。
### 异常处理
如果在处理git命令过程中出现任何问题请第一时间联系用户。并把错误消息贴给用户看。
## N8N 工作流管理 (2026-03-29)
用户可能说: "帮我看看n8n上的工作流"、"触发n8n工作流"、"查看n8n执行记录"
### 连接配置
| 配置项 | 值 |
|--------|-----|
| **Base URL** | `https://n8n.ishenwei.online` |
| **API Key** | `~/.openclaw/.env` 中的 `N8N_API_KEY` |
| **管理界面** | https://n8n.ishenwei.online |
### 核心脚本路径
- **技能位置**: `~/.openclaw/skills/n8n/`
- **n8n_api.py**: 工作流管理、触发执行、查看状态
- **n8n_tester.py**: 验证工作流、dry-run 测试
- **n8n_optimizer.py**: 性能分析与优化建议
### 环境变量(已在 `~/.openclaw/.env`
```
N8N_API_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
N8N_BASE_URL=https://n8n.ishenwei.online
```
### 常用操作
```bash
# 查看工作流列表
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py list-workflows --pretty
# 查看执行记录
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py list-executions --id <workflow-id> --limit 20 --pretty
# 手动触发工作流
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py execute --id <workflow-id>
# 带数据触发
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py execute --id <workflow-id> --data '{"key": "value"}'
# 激活/停用
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py activate --id <workflow-id>
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py deactivate --id <workflow-id>
```
### 测试与验证
```bash
# 验证工作流结构
python3 ~/.openclaw/skills/n8n/scripts/n8n_tester.py validate --id <workflow-id> --pretty
# Dry Run 测试
python3 ~/.openclaw/skills/n8n/scripts/n8n_tester.py dry-run --id <workflow-id> --data '{}'
```
### 创建工作流
```bash
# 从 JSON 文件创建
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py create --from-file workflow.json
# 创建后激活
python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py activate --id <new-workflow-id>
```
### 性能分析
```bash
# 分析性能
python3 ~/.openclaw/skills/n8n/scripts/n8n_optimizer.py analyze --id <workflow-id> --pretty
# 获取优化建议
python3 ~/.openclaw/skills/n8n/scripts/n8n_optimizer.py suggest --id <workflow-id> --pretty
```
### Webhook 触发
```bash
# 直接调用 Webhook
curl -X POST "https://n8n.ishenwei.online/webhook/<webhook-path>" \
-H "Content-Type: application/json" \
-d '{"key": "value"}'
```
---
## N8N 内容翻译流水线 (2026-03-29)
**用途**:英文文章 → 中文公众号Markdown + HTML+ Twitter文案 + 视频脚本
**架构说明**
- n8n 只能读写容器内的 `/home/node/.n8n-files/` 目录
- OpenClaw 负责文件搬运:复制到 n8n → 触发 → 复制回 Obsidian
- 完整设计文档:`~/Obsidian/shenwei/openclaw/yunce/n8n-content-pipeline-workflow.md`
### 工作流版本
| 版本 | ID | 状态 | 说明 |
|------|-----|------|------|
| **v5最新** | `iOf32aOKvTjfTDSM` | 未激活 | 双输出Markdown + HTML |
| v3 | `tOGMiC6qOJPOY89E` | 活跃 | 单输出Markdown |
### 调用前的文件准备
n8n 的 Read/Write File 节点使用 `/home/node/.n8n-files/` 目录,**不是** Obsidian 目录。
```
n8n 容器内路径: /home/node/.n8n-files/
MacMini Obsidian: /Users/weishen/Workspace/nexus/openclaw/
```
### OpenClaw 完整调用流程
#### 第一步:复制原文到 n8n-files
```bash
# SSH 到 MacMini将源文件复制到 n8n 容器可访问的目录
scp /Users/weishen/Workspace/nexus/openclaw/content-queue/{文件名}.md \
macmini:/home/node/.n8n-files/{文件名}.md
```
#### 第二步:触发 Webhook
```bash
# 注意v5 使用 /content-translation-v5
# note_name = n8n-files 里的文件名
# output_name = 输出的文件名(不含扩展名)
# source_path = Obsidian 原文路径(用于记录溯源)
curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v5" \
-H "Content-Type: application/json" \
-d "{
\"note_name\": \"{文件名}.md\",
\"output_name\": \"{文件名}\",
\"source_path\": \"/Users/weishen/Workspace/nexus/openclaw/content-queue/{文件名}.md\",
\"callback_url\": \"http://192.168.3.189:18789/webhook/yunce\"
}"
```
#### 第三步:等待 Telegram 通知
- Telegram Bot (`y1NdRSaJwl0LoY37`) 会发送完成消息
- 消息格式:`✅ 文章转换完成!📝 标题xxx`
#### 第四步:复制输出回 Obsidian
```bash
# 复制 Markdown 成品
scp macmini:/home/node/.n8n-files/{output_name}_output.md \
/Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.md
# 复制 HTML 成品(公众号用)
scp macmini:/home/node/.n8n-files/{output_name}_output.html \
/Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.html
```
#### 第五步:清理 n8n-files 临时文件
```bash
ssh macmini "rm /home/node/.n8n-files/{文件名}.md \
/home/node/.n8n-files/{output_name}_output.md \
/home/node/.n8n-files/{output_name}_output.html"
```
### 完整 Python 调用示例
```python
import subprocess
import time
import json
def trigger_content_translation(source_note_name, source_path, output_name):
"""完整的内容翻译流水线调用"""
n8n_files_dir = "/home/node/.n8n-files"
obsidian_root = "/Users/weishen/Workspace/nexus/openclaw"
# ========== 第一步:复制原文到 n8n ==========
source_full_path = f"{obsidian_root}/content-queue/{source_note_name}"
print(f"[1/5] 复制原文到 n8n-files: {source_note_name}")
subprocess.run([
'scp', source_full_path,
f'macmini:{n8n_files_dir}/{source_note_name}'
], check=True)
# ========== 第二步:触发 Webhook ==========
print(f"[2/5] 触发 n8n 工作流...")
webhook_url = "https://n8n.ishenwei.online/webhook/content-translation-v5"
payload = json.dumps({
"note_name": source_note_name,
"output_name": output_name,
"source_path": source_path,
"callback_url": "http://192.168.3.189:18789/webhook/yunce"
})
subprocess.run([
'curl', '-X', 'POST', webhook_url,
'-H', 'Content-Type: application/json',
'-d', payload
], check=True)
# ========== 第三步:等待处理 ==========
print("[3/5] 等待 Telegram 完成通知...")
# Agent 应等待 Telegram 消息后再继续
time.sleep(5) # 示意用,实际应监听 Telegram
# ========== 第四步:复制输出回 Obsidian ==========
print(f"[4/5] 复制输出到 content-output...")
output_md = f"{n8n_files_dir}/{output_name}_output.md"
output_html = f"{n8n_files_dir}/{output_name}_output.html"
dest_root = f"{obsidian_root}/content-output"
subprocess.run(['scp', f'macmini:{output_md}', f'{dest_root}/{output_name}.md'], check=True)
subprocess.run(['scp', f'macmini:{output_html}', f'{dest_root}/{output_name}.html'], check=True)
# ========== 第五步:清理 ==========
print(f"[5/5] 清理 n8n-files...")
subprocess.run(['ssh', 'macmini', f'rm {n8n_files_dir}/{source_note_name} {output_md} {output_html}'])
print(f"✅ 完成!输出: {dest_root}/{output_name}.md + .html")
# 调用示例
trigger_content_translation(
source_note_name="article-2026-03-29.md",
source_path="/Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md",
output_name="article-2026-03-29"
)
```
### Obsidian 目录结构
```
~/Workspace/nexus/openclaw/
├── content-queue/ # 原始英文文章
│ └── article-2026-03-29.md
└── content-output/ # 翻译成品Markdown + HTML
├── article-2026-03-29.md # 中文 Markdown留存溯源
└── article-2026-03-29.html # 公众号 HTML直接复制粘贴
```
### 输出文件说明
| 文件 | 格式 | 用途 |
|------|------|------|
| `*.md` | 中文 Markdown | Obsidian 留存、溯源、可修改 |
| `*.html` | 带样式 HTML | 复制到公众号编辑器,几乎零调整 |
### 常见问题
**Q: n8n API 返回 401**
A: 检查 `~/.openclaw/.env` 里的 `N8N_API_KEY` 是否完整(应为 3 段 JWT
**Q: 文件复制到 n8n-files 失败?**
A: 确认 MacMini 上 `/home/node/.n8n-files/` 目录存在且有写权限
**Q: 如何查看工作流状态?**
A: 用 `n8n_api.py list-executions --id <workflow-id> --limit 10 --pretty` 查看最近执行