Initial commit: Hermes Agent skills collection

- Trading skills (OKX, dividend, lottery, quantitative)
- Creative skills (ASCII art, diagrams, video)
- Development skills (GitHub, debugging, TDD)
- Research skills (arXiv, blog monitoring)
- Productivity skills (email, documents, notes)
- MCP integration skills
- Custom user skills
This commit is contained in:
Hermes Skills Manager
2026-07-05 02:31:15 -04:00
commit 6770bc9b9d
908 changed files with 239614 additions and 0 deletions
+247
View File
@@ -0,0 +1,247 @@
---
name: safe-mode
description: 安全模式切换 - 一键切换到去拒绝(abliterated)模型,支持备份/恢复原模型配置。当用户说"安全模式"时进入,说"退出安全模式"时退出。
version: 1.0.0
tags: [safety, model-switching, abliterated, uncensored]
---
# 安全模式切换技能
一键切换到去拒绝(abliterated)模型,支持备份/恢复原模型配置。
## 触发条件
### 进入安全模式
当用户消息**完全匹配**以下任一短语时触发:
- "安全模式"
- "进入安全模式"
- "开启安全模式"
### 退出安全模式
当用户消息**完全匹配**以下任一短语时触发:
- "退出安全模式"
- "关闭安全模式"
- "退出"
- "exit safe mode"
**⚠️ 重要**: 退出时必须执行以下步骤:
1. 运行 `bash ~/.hermes/skills/hermes/safe-mode/scripts/safe-mode.sh exit`
2. 等待脚本完成(配置恢复,无需重启gateway)
3. 提示用户"新开对话以使用恢复后的模型"
## 功能特性
- 一键切换到去拒绝模型
- 自动备份当前模型配置
- 一键恢复原模型
- 状态提示和反馈
- **无需重启 gateway**(只改配置,新开对话生效)
## 目标模型
切换到: `huihui-gemma-4-26b-a4b-it-abliterated-mlx`
- 服务: LM Studio (192.168.199.100:1234)
- 上下文: 262K tokens
- 特点: 去拒绝(abliterated),无安全限制
## 工作流程
### 进入安全模式
```
用户: "安全模式"
↓
1. 检查当前是否已在安全模式
2. 读取当前模型配置
3. 保存备份到 ~/.hermes/safe_mode_backup.json
4. 修改 config.yaml 切换模型
5. 显示成功提示(无需重启gateway)
```
**执行命令**:
```bash
bash ~/.hermes/skills/hermes/safe-mode/scripts/safe-mode.sh enter
```
### 退出安全模式
```
用户: "退出安全模式"
↓
1. 检查备份文件是否存在
2. 读取备份的模型配置
3. 恢复 config.yaml
4. 显示成功提示(无需重启gateway)
5. 压缩当前会话(可选)
```
**执行命令**:
```bash
# 退出安全模式(恢复原模型配置)
bash ~/.hermes/skills/hermes/safe-mode/scripts/safe-mode.sh exit
# 可选:清理旧会话
hermes sessions prune --days 1
```
**⚠️ 退出后**:
- 配置已恢复,**无需重启 gateway**
- **新开对话**以使用恢复后的模型(当前会话仍用旧模型)
## 提示模板
### 进入安全模式
```
🔄 正在切换到安全模式...
━━━━━━━━━━━━━━━━━━━━━━━━
✅ 已进入安全模式
┌────────────────────────────┐
│ 🔓 当前模型 │
│ huihui-gemma-4-26b-a4b-it │
│ abliterated-mlx │
├────────────────────────────┤
│ 💾 原模型已备份 │
│ {original_model} │
├────────────────────────────┤
│ 💡 说"退出安全模式"可恢复 │
└────────────────────────────┘
```
### 退出安全模式
```
🔄 正在退出安全模式...
━━━━━━━━━━━━━━━━━━━━━━━━
✅ 已退出安全模式
┌────────────────────────────┐
│ 🔒 当前模型 │
│ {original_model} │
├────────────────────────────┤
│ 📝 已恢复到切换前的配置 │
└────────────────────────────┘
```
### 错误提示
```
⚠️ 已经在安全模式中
```
```
❌ 未找到安全模式备份
可能之前没有进入过安全模式
```
## 实现脚本
脚本位置: `{baseDir}/scripts/safe-mode.sh`
使用方式:
```bash
# 进入安全模式
bash {baseDir}/scripts/safe-mode.sh enter
# 退出安全模式
bash {baseDir}/scripts/safe-mode.sh exit
# 查看状态
bash {baseDir}/scripts/safe-mode.sh status
```
## 配置文件
备份文件位置: `~/.hermes/safe_mode_backup.json`
```json
{
"original_model": "mimo-v2.5-pro",
"original_provider": "token-plan-cn.xiaomimimo.com",
"backup_time": "2026-05-29T10:30:00",
"in_safe_mode": true
}
```
## 注意事项
- 切换模型**不需要重启 gateway**,只需修改 `config.yaml` 即可
- **新开对话**才能使用新模型(当前会话仍用旧模型)
- 进入安全模式时会自动备份当前配置
- 退出安全模式时会自动恢复备份的配置
- 不要在同一会话中反复切换,避免配置混乱
- 备份文件位于 `~/.hermes/safe_mode_backup.json`
## 常见问题
### Q: 为什么说"安全模式"后没有反应?
A: 确保你的消息**完全匹配**触发词,不要加其他内容。
### Q: 退出后为什么还是旧模型?
A: 当前会话仍然使用旧模型。需要**新开对话**才能使用恢复后的模型。
### Q: 如何查看当前处于什么模式?
A: 说"状态"或"查看状态",会显示当前模型和安全模式状态。
### Q: 切换模型需要重启 gateway 吗?
A: **不需要**。只修改 config.yaml,新开对话即可生效。
## ⚠️ 自动切换被安全策略拦截(Pitfall)
**问题**: `~/.hermes/config.yaml` 是安全敏感文件,agent 无法通过以下任何方式修改:
- `patch()` 工具 → 返回 "Refusing to write to Hermes config file"
- `terminal()` 执行 `hermes config set` 或 bash 脚本 → 被 approvals 策略 BLOCKED
- `execute_code()` → 被 cron_mode=deny 策略阻止
**唯一可行方案**: agent 只能更新 `safe_mode_backup.json`(非敏感),然后**提示用户手动执行命令**:
```bash
# 一键切换(用户 SSH 进服务器执行)
hermes config set model.default "huihui-gemma-4-26b-a4b-it-abliterated-mlx"
hermes config set model.base_url "http://192.168.199.100:1234/v1"
hermes config set model.api_key "***:BYKopbVMhDyrIKklRg2g"
hermes config set model.provider "custom"
hermes config set model.model "huihui-gemma-4-26b-a4b-it-abliterated-mlx"
hermes config set model.api_mode "openai"
```
或直接编辑 `~/.hermes/config.yaml` 的 model 块。
**备选**: 修改 `approvals.cron_mode` 为 `approve` 可能解除限制,但有安全风险。
## 脚本编辑注意事项(Pitfall)
⚠️ **重要**: 编辑 `safe-mode.sh` 时,必须保留所有函数完整性。之前在删除 `restart_gateway` 时意外删除了整个 `exit_safe_mode()` 函数,导致退出安全模式功能失效。
**正确做法**:
1. 编辑前先备份:`cp safe-mode.sh safe-mode.sh.bak`
2. 只删除 `restart_gateway` 相关的调用行,不要删除整个函数块
3. 编辑后用 `bash safe-mode.sh status` 验证脚本语法正确
**函数清单**(编辑后必须确认存在):
- `enter_safe_mode()` - 进入安全模式
- `exit_safe_mode()` - 退出安全模式
- `show_status()` - 查看状态
- `switch_model()` - 切换模型配置
- `create_backup()` - 创建备份
- `read_backup()` - 读取备份
- `is_in_safe_mode()` - 检查是否在安全模式
- `get_current_model()` - 获取当前模型
## 模型名错误排查(Pitfall)
模型名写错(如 `mimo-m2.5-pro` 写成 `mimo-v2.5-pro`,`v` 打成 `m`)会导致 API 调用失败或超时。排查步骤:
1. **查当前模型名**: `hermes config get model` 或 `grep 'model:' ~/.hermes/config.yaml | head -5`
2. **查有效模型列表**: `cat ~/.hermes/provider_models_cache.json | python3 -m json.tool | grep mimo` — 交叉验证模型名是否在列表中
3. **修复**: `hermes config set model <正确的模型名>`
4. **验证**: 发一条消息看是否正常响应
⚠️ agent 无法直接 patch config.yaml(安全保护),必须通过 `hermes config set` 命令行修改。
## 免责声明
⚠️ 去拒绝模型可能生成不受限的内容,请谨慎使用。
+347
View File
@@ -0,0 +1,347 @@
#!/bin/bash
# 安全模式切换脚本
# 用法: safe-mode.sh [enter|exit|status]
set -e
# 配置
HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}"
CONFIG_FILE="$HERMES_HOME/config.yaml"
BACKUP_FILE="$HERMES_HOME/safe_mode_backup.json"
# 安全模式模型
SAFE_MODEL="huihui-gemma-4-26b-a4b-it-abliterated-mlx"
SAFE_PROVIDER="lm-studik-hi6k"
# 颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_line() {
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
print_box() {
local content="$1"
echo "┌────────────────────────────────────────┐"
echo "$content" | while IFS= read -r line; do
printf "│ %-38s │\n" "$line"
done
echo "└────────────────────────────────────────┘"
}
# 获取当前配置的模型
get_current_model() {
if [ -f "$BACKUP_FILE" ] && is_in_safe_mode; then
grep '"original_model"' "$BACKUP_FILE" | cut -d'"' -f4
elif [ -f "$CONFIG_FILE" ]; then
python3 << EOF
import yaml
try:
with open("$CONFIG_FILE", 'r') as f:
config = yaml.safe_load(f)
model_config = config.get('model', {})
print(model_config.get('default', 'unknown'))
except:
print('unknown')
EOF
else
echo "unknown"
fi
}
# 检查是否在安全模式
is_in_safe_mode() {
if [ -f "$BACKUP_FILE" ]; then
local in_safe_mode=$(grep -o '"in_safe_mode": *true' "$BACKUP_FILE" 2>/dev/null)
if [ -n "$in_safe_mode" ]; then
return 0
fi
fi
return 1
}
# 创建备份
create_backup() {
local backup_time=$(date -u +"%Y-%m-%dT%H:%M:%S")
python3 << EOF
import yaml
import json
import sys
config_path = "$CONFIG_FILE"
backup_path = "$BACKUP_FILE"
try:
with open(config_path, 'r') as f:
config = yaml.safe_load(f)
model_config = config.get('model', {})
backup = {
"original_model": model_config.get('default', 'unknown'),
"original_base_url": model_config.get('base_url', ''),
"original_api_key": model_config.get('api_key', ''),
"original_api_mode": model_config.get('api_mode', 'openai'),
"original_provider": model_config.get('provider', 'custom'),
"backup_time": "$backup_time",
"in_safe_mode": True
}
with open(backup_path, 'w') as f:
json.dump(backup, f, indent=2)
print("💾 备份已创建")
print(f" 原模型: {backup['original_model']}")
print(f" 备份时间: $backup_time")
except Exception as e:
print(f"❌ 备份失败: {e}", file=sys.stderr)
sys.exit(1)
EOF
}
# 读取备份
read_backup() {
if [ -f "$BACKUP_FILE" ]; then
python3 << EOF
import json
try:
with open("$BACKUP_FILE", 'r') as f:
backup = json.load(f)
print(f"{backup.get('original_model', '')}|{backup.get('original_base_url', '')}|{backup.get('original_api_key', '')}|{backup.get('original_api_mode', 'openai')}|{backup.get('original_provider', 'custom')}")
except:
print("|||")
EOF
else
echo "|||"
fi
}
# 切换模型
switch_model() {
local new_model="$1"
local new_provider="$2"
cp "$CONFIG_FILE" "${CONFIG_FILE}.bak"
python3 << EOF
import yaml
import sys
config_path = "$CONFIG_FILE"
target_provider = "$new_provider"
try:
with open(config_path, 'r') as f:
config = yaml.safe_load(f)
target_config = None
if 'custom_providers' in config:
for provider in config['custom_providers']:
if provider.get('name') == target_provider:
target_config = provider
break
if target_config:
if 'model' not in config:
config['model'] = {}
config['model']['default'] = target_config.get('model', '')
config['model']['base_url'] = target_config.get('base_url', '')
config['model']['api_key'] = target_config.get('api_key', '')
config['model']['provider'] = 'custom'
if 'api_mode' in target_config:
config['model']['api_mode'] = target_config['api_mode']
else:
config['model']['api_mode'] = 'openai'
print(f"✅ 已切换到 {target_config.get('model', '')}")
else:
print(f"❌ 未找到provider: {target_provider}", file=sys.stderr)
sys.exit(1)
with open(config_path, 'w') as f:
yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
print("✅ 配置已更新")
except Exception as e:
print(f"❌ 更新失败: {e}", file=sys.stderr)
sys.exit(1)
EOF
}
# 进入安全模式
enter_safe_mode() {
echo ""
echo -e "${BLUE}🔄 正在切换到安全模式...${NC}"
print_line
if is_in_safe_mode; then
echo ""
echo -e "${YELLOW}⚠️ 已经在安全模式中${NC}"
echo ""
return 0
fi
create_backup
echo ""
echo -e "${YELLOW}📝 正在更新配置...${NC}"
switch_model "$SAFE_MODEL" "$SAFE_PROVIDER"
echo ""
print_line
echo -e "${GREEN}✅ 已进入安全模式${NC}"
echo ""
print_box "🔓 当前模型
$SAFE_MODEL
💾 原模型已备份
$(get_current_model)
💡 说\"退出安全模式\"可恢复"
echo ""
}
# 退出安全模式
exit_safe_mode() {
echo ""
echo -e "${BLUE}🔄 正在退出安全模式...${NC}"
print_line
if ! is_in_safe_mode; then
echo ""
echo -e "${RED}❌ 未找到安全模式备份${NC}"
echo " 可能之前没有进入过安全模式"
echo ""
return 1
fi
local backup=$(read_backup)
local original_model=$(echo "$backup" | cut -d'|' -f1)
local original_base_url=$(echo "$backup" | cut -d'|' -f2)
local original_api_key=$(echo "$backup" | cut -d'|' -f3)
local original_api_mode=$(echo "$backup" | cut -d'|' -f4)
local original_provider=$(echo "$backup" | cut -d'|' -f5)
if [ -z "$original_model" ]; then
echo ""
echo -e "${RED}❌ 备份文件损坏,无法恢复${NC}"
echo ""
return 1
fi
echo ""
echo -e "${YELLOW}📝 正在恢复配置...${NC}"
python3 << EOF
import yaml
import sys
config_path = "$CONFIG_FILE"
try:
with open(config_path, 'r') as f:
config = yaml.safe_load(f)
config['model'] = {
'default': "$original_model",
'base_url': "$original_base_url",
'api_key': "$original_api_key",
'api_mode': "$original_api_mode",
'provider': "$original_provider"
}
with open(config_path, 'w') as f:
yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
print("✅ 配置已恢复")
except Exception as e:
print(f"❌ 恢复失败: {e}", file=sys.stderr)
sys.exit(1)
EOF
# 更新备份状态
python3 << EOF
import json
backup_file = "$BACKUP_FILE"
try:
with open(backup_file, 'r') as f:
backup = json.load(f)
backup['in_safe_mode'] = False
with open(backup_file, 'w') as f:
json.dump(backup, f, indent=2)
except:
pass
EOF
echo ""
print_line
echo -e "${GREEN}✅ 已退出安全模式${NC}"
echo ""
print_box "🔒 当前模型
$original_model
📝 已恢复到切换前的配置"
echo ""
}
# 查看状态
show_status() {
echo ""
echo -e "${BLUE}📊 安全模式状态${NC}"
print_line
if is_in_safe_mode; then
local backup=$(read_backup)
local original_model=$(echo "$backup" | cut -d'|' -f1)
local backup_time=$(grep '"backup_time"' "$BACKUP_FILE" | cut -d'"' -f4)
echo ""
print_box "🔓 当前处于安全模式
当前模型: $SAFE_MODEL
原模型: $original_model
进入时间: $backup_time"
else
echo ""
print_box "🔒 当前处于正常模式
当前模型: $(get_current_model)"
fi
echo ""
}
# 主函数
main() {
local action="$1"
case "$action" in
enter)
enter_safe_mode
;;
exit)
exit_safe_mode
;;
status)
show_status
;;
*)
echo "用法: $0 [enter|exit|status]"
echo ""
echo " enter - 进入安全模式"
echo " exit - 退出安全模式"
echo " status - 查看状态"
exit 1
;;
esac
}
main "$@"