emma-hermes/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/contributing.md

270 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
sidebar_position: 4
title: "贡献指南"
description: "如何为 Hermes Agent 做贡献 — 开发环境配置、代码风格、PR 流程"
---
# 贡献指南
感谢您为 Hermes Agent 做贡献!本指南涵盖开发环境配置、代码库结构说明以及 PR 合并流程。
## 贡献优先级
我们按以下顺序评估贡献价值:
1. **Bug 修复** — 崩溃、错误行为、数据丢失
2. **跨平台兼容性** — macOS、不同 Linux 发行版、WSL2
3. **安全加固** — shell 注入、prompt提示词注入、路径穿越
4. **性能与健壮性** — 重试逻辑、错误处理、优雅降级
5. **新 skill** — 具有广泛用途的 skill参见 [创建 Skill](creating-skills.md)
6. **新工具** — 极少需要;大多数能力应以 skill 形式实现
7. **文档** — 修正、说明、新示例
## 常见贡献路径
- 构建自定义/本地工具而不修改 Hermes 核心?从 [构建 Hermes 插件](../developer-guide/plugins/index.md) 开始
- 为 Hermes 本身构建新的内置核心工具?从 [添加工具](./adding-tools.md) 开始
- 构建新的 skill从 [创建 Skill](./creating-skills.md) 开始
- 构建新的推理提供商?从 [添加提供商](./adding-providers.md) 开始
## 开发环境配置
### 前置要求
| 要求 | 说明 |
|-------------|-------|
| **Git** | 需安装 `git-lfs` 扩展 |
| **Python 3.113.13** | 若未安装uv 会自动安装 |
| **uv** | 高速 Python 包管理器([安装](https://docs.astral.sh/uv/) |
| **Node.js 20+** | 可选 — 浏览器工具和 WhatsApp bridge 需要(与根目录 `package.json` engines 字段一致) |
### 使用标准安装器
对大多数贡献者来说,最好的开发启动方式和用户安装方式相同:运行标准安装器,然后在它克隆出的仓库里开发。安装器会创建 Hermes venv、配置 `hermes` 命令、为 `hermes update` 写入安装方式标记,并把完整 git 项目克隆到 `$HERMES_HOME/hermes-agent`(通常是 `~/.hermes/hermes-agent`)。这样你的开发环境会和 CLI、updater、lazy dependency installer、gateway、docs 默认假设的布局一致。
```bash
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
cd "${HERMES_HOME:-$HOME/.hermes}/hermes-agent"
# 在标准安装基础上添加开发/测试 extras。
uv pip install -e ".[all,dev]"
# 可选:浏览器工具 / docs site dependencies。
npm install
```
之后从这个 checkout 创建分支并运行测试:
```bash
git checkout -b fix/description
scripts/run_tests.sh
```
### 手动克隆备用路径
只有在你明确不想使用 Hermes managed install layout 时才使用这种方式(例如容器或 CI job 里的临时 clone。如果这样安装请确保运行的是这个 venv 里的 `hermes` entrypoint运行系统 `python3 -m hermes_cli.main` 可能会加载无关的系统 Python 包。
```bash
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
# 使用 Python 3.11 创建虚拟环境
uv venv venv --python 3.11
export VIRTUAL_ENV="$(pwd)/venv"
# 安装所有扩展messaging、cron、CLI 菜单、开发工具)
uv pip install -e ".[all,dev]"
# 可选:浏览器工具
npm install
```
### 配置开发环境
```bash
mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}
cp cli-config.yaml.example ~/.hermes/config.yaml
touch ~/.hermes/.env
# 至少添加一个 LLM 提供商密钥:
echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.hermes/.env
```
### 运行
```bash
# 标准安装器已经把 `hermes` 放到了 PATH 上。
hermes doctor
hermes chat -q "Hello"
```
如果你使用了手动克隆备用路径,可以在 checkout 中运行 `./hermes`,或显式把这个 clone 的 venv 链接到 PATH
```bash
mkdir -p ~/.local/bin
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
```
### 运行测试
```bash
scripts/run_tests.sh
```
## 代码风格
- **PEP 8**,允许合理例外(不强制限制行长度)
- **注释**:仅在解释非显而易见的意图、权衡取舍或 API 特殊行为时添加
- **错误处理**:捕获具体异常。对于意外错误,使用 `logger.warning()`/`logger.error()` 并设置 `exc_info=True`
- **跨平台**:不得假设 Unix 环境(见下文)
- **Profile 安全路径**:不得硬编码 `~/.hermes` — 代码路径使用 `hermes_constants` 中的 `get_hermes_home()`,面向用户的消息使用 `display_hermes_home()`。完整规则参见 [AGENTS.md](https://github.com/NousResearch/hermes-agent/blob/main/AGENTS.md#profiles-multi-instance-support)。
## 跨平台兼容性
Hermes 官方支持 **Linux、macOS、WSL2 以及原生 Windows通过 PowerShell 安装)**。原生 Windows 使用 [Git for Windows](https://git-scm.com/download/win) 提供的 Git Bash 执行 shell 命令。部分功能依赖 POSIX 内核原语已做条件限制dashboard 内嵌的 PTY 终端面板(`/chat` 标签页)仅支持 WSL2。如果您主要在 Windows 上开发,推送前请运行 Windows 陷阱footgunlint`scripts/check-windows-footguns.py`)。
贡献代码时,请遵守以下规则:
- **不得添加未加保护的 `signal.SIGKILL` 引用。** Windows 上未定义该信号。请通过 `gateway.status.terminate_pid(pid, force=True)`集中式原语Windows 上执行 `taskkill /T /F`POSIX 上发送 SIGKILL路由或使用 `getattr(signal, "SIGKILL", signal.SIGTERM)` 回退。
- **在 `os.kill(pid, 0)` 探测时同时捕获 `OSError``ProcessLookupError`。** Windows 对已消失的 PID 抛出 `OSError`WinError 87"参数不正确"),而非 `ProcessLookupError`
- **不得强制终端使用 POSIX 语义。** `os.setsid`、`os.killpg`、`os.getpgid`、`os.fork` 在 Windows 上均会抛出异常 — 使用 `if sys.platform != "win32":``if os.name != "nt":` 进行条件判断。
- **打开文件时显式指定 `encoding="utf-8"`。** Windows 上 Python 默认使用系统区域设置(通常为 cp1252处理非拉丁字符时会出现乱码或崩溃。
- **使用 `pathlib.Path` / `os.path.join`,不得手动用 `/` 拼接路径。** 这对我们构造后传给子进程的字符串尤为重要,而非 OS 返回给我们的字符串。
关键模式:
### 1. `termios` 和 `fcntl` 仅适用于 Unix
始终同时捕获 `ImportError``NotImplementedError`
```python
try:
from simple_term_menu import TerminalMenu
menu = TerminalMenu(options)
idx = menu.show()
except (ImportError, NotImplementedError):
# 回退:编号菜单
for i, opt in enumerate(options):
print(f" {i+1}. {opt}")
idx = int(input("Choice: ")) - 1
```
### 2. 文件编码
某些环境可能以非 UTF-8 编码保存 `.env` 文件:
```python
try:
load_dotenv(env_path)
except UnicodeDecodeError:
load_dotenv(env_path, encoding="latin-1")
```
### 3. 进程管理
`os.setsid()`、`os.killpg()` 以及信号处理在各平台间存在差异:
```python
import platform
if platform.system() != "Windows":
kwargs["preexec_fn"] = os.setsid
```
### 4. 路径分隔符
使用 `pathlib.Path` 代替用 `/` 进行字符串拼接。
## 安全注意事项
Hermes 拥有终端访问权限,安全至关重要。
### 现有保护措施
| 层级 | 实现方式 |
|-------|---------------|
| **sudo 密码管道** | 使用 `shlex.quote()` 防止 shell 注入 |
| **危险命令检测** | `tools/approval.py` 中的正则表达式模式,配合用户审批流程 |
| **Cron prompt 注入** | 扫描器阻断指令覆盖模式 |
| **写入拒绝列表** | 受保护路径通过 `os.path.realpath()` 解析,防止符号链接绕过 |
| **Skill 守卫** | 对 hub 安装的 skill 进行安全扫描 |
| **代码执行沙箱** | 子进程运行时剥离 API 密钥 |
| **容器加固** | Docker删除所有 capability禁止权限提升限制 PID 数量 |
### 贡献安全敏感代码
- 将用户输入插入 shell 命令时,始终使用 `shlex.quote()`
- 访问控制检查前,使用 `os.path.realpath()` 解析符号链接
- 不得记录密钥信息
- 在工具执行周围捕获宽泛异常
- 若您的变更涉及文件路径或进程,请在所有平台上测试
## Pull Request 流程
### 分支命名
```
fix/description # Bug 修复
feat/description # 新功能
docs/description # 文档
test/description # 测试
refactor/description # 代码重构
```
### 提交前检查
1. **运行测试**`scripts/run_tests.sh` 以确保 CI 一致性。仅当 wrapper 不可用或您有意在 wrapper 之外调试时,才使用直接 `python -m pytest ...`
2. **手动测试**:运行 `hermes` 并验证您修改的代码路径
3. **检查跨平台影响**:考虑 macOS、Linux、WSL2 和原生 Windows。如果您修改了文件 I/O、进程管理、终端处理、子进程或信号相关代码请运行 `scripts/check-windows-footguns.py`
4. **保持 PR 聚焦**:每个 PR 只包含一个逻辑变更
### PR 描述
请包含:
- **变更内容**及**变更原因**
- **测试方法**
- **测试平台**
- 关联 issue 引用
### Commit 消息
我们使用 [Conventional Commits](https://www.conventionalcommits.org/)
```
<type>(<scope>): <description>
```
| 类型 | 适用场景 |
|------|---------|
| `fix` | Bug 修复 |
| `feat` | 新功能 |
| `docs` | 文档 |
| `test` | 测试 |
| `refactor` | 代码重构 |
| `chore` | 构建、CI、依赖更新 |
Scope 范围:`cli`、`gateway`、`tools`、`skills`、`agent`、`install`、`whatsapp`、`security`
示例:
```
fix(cli): prevent crash in save_config_value when model is a string
feat(gateway): add WhatsApp multi-user session isolation
fix(security): prevent shell injection in sudo password piping
```
## 报告问题
- 使用 [GitHub Issues](https://github.com/NousResearch/hermes-agent/issues)
- 请包含操作系统、Python 版本、Hermes 版本(`hermes version`)、完整错误堆栈
- 包含复现步骤
- 创建前请检查是否已有重复 issue
- 安全漏洞请私下报告
## 社区
- **Discord**[discord.gg/NousResearch](https://discord.gg/NousResearch)
- **GitHub Discussions**:用于设计提案和架构讨论
- **Skills Hub**:上传专业 skill 并与社区共享
## 许可证
提交贡献即表示您同意您的贡献将以 [MIT 许可证](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE) 授权。