跳到主要内容

贡献指南

感谢您为 Tutou Agent 做贡献!本指南涵盖开发环境配置、代码库结构说明以及 PR 合并流程。

贡献优先级​

我们按以下顺序评估贡献价值:

  1. Bug 修复 — 崩溃、错误行为、数据丢失
  2. 跨平台兼容性 — macOS、不同 Linux 发行版、WSL2
  3. 安全加固 — shell 注入、prompt(提示词)注入、路径穿越
  4. 性能与健壮性 — 重试逻辑、错误处理、优雅降级
  5. 新 skill — 具有广泛用途的 skill(参见 创建 Skill)
  6. 新工具 — 极少需要;大多数能力应以 skill 形式实现
  7. 文档 — 修正、说明、新示例

常见贡献路径​

开发环境配置​

前置要求​

项目要求 Python 3.14(>=3.14,<3.15)。PM 提供固定版本的解释器和工具。 准备 Git 和 git-lfs。JS 构建使用 PM 的 Node/npm,或满足相应 package.json engines 的版本。

PM 开发环境​

PM 开发工作流 包含首次准备、激活、日常使用、依赖更新和当前 bootstrap 限制。 请在准备环境前选择独立的开发 TUTOU_HOME,避免实验代码迁移生产数据。

成功准备后,每次在仓库根目录的新 shell 中激活已有环境。

Bash:

source ./activate
tutou --version

PowerShell:

. .\activate.ps1
tutou --version

PowerShell 开头的点和空格用于 dot-source,不能省略。 激活通过 PM 准备工具并同步依赖,但不创建 JS workspaces,也不设置常规 venv 提示符。 激活把 tutou 定义成当前 worktree 的函数,因此会盖住全局命令和 MSIX 别名, 并在离开该 worktree 时拒绝运行。 deactivate 恢复激活前的环境,不卸载依赖或停止已启动的进程。

独立开发和测试环境​

先按 PM 开发工作流 准备 Python 3.14。 在该 checkout 中使用准备好的 Python,并保持相同的开发 TUTOU_HOME。 PM 必须能够启动,才能构建独立测试环境:

python -m pm.build_env --source . --out .venv --group dev --group test

此命令使用提交的锁文件,创建新环境并检查依赖一致性。输出路径必须不存在。 如需重新生成,请先停止使用该环境的进程,再明确删除该可丢弃的环境。 PM 不会自动删除已有目录。不要通过原始 pip 或 uv 命令修改 Tutou 环境。

测试 runner 自动发现仓库的 .venv。它会清除 PYTHONPATH,因此 pytest 必须安装在解释器自身的环境中。 也可将 --out 指向仓库外的新路径,再将 TUTOU_PYTHON 设为该环境的解释器。 Windows 上通过 Bash 运行 scripts/run_tests.sh,并预先准备本机 C++ 编译环境。

独立测试环境不替代 PM 工具存储或应用的依赖选择。不要修改签名应用的载荷。 运行开发实例前,选择临时的 TUTOU_HOME,再使用 tutou setup 配置它。 不要把生产凭据复制到 checkout。

从仓库根目录运行 npm ci 安装 JS workspaces。网站单独使用:

npm ci --prefix website
npm run build:fast --prefix website

图标从 assets/nous-girl-*.svg 和 assets/backgrounds/ 生成。 node scripts/generate-icons.mjs 使用 Tutou 运行时 Python(TUTOU_PYTHON,否则为 PATH 上的 python)渲染图标:Pillow 和 resvg-py 是核心依赖。不要提交生成的 PNG/ICO/ICNS 文件。

运行测试​

scripts/run_tests.sh

该脚本清除凭据环境、设置 UTC 和临时 TUTOU_HOME,并使用独立子进程运行各测试文件。 不同文件可并行,单个文件内的测试串行执行。不要绕过脚本直接运行 pytest。

代码风格​

  • PEP 8,允许合理例外(不强制限制行长度)
  • 注释:仅在解释非显而易见的意图、权衡取舍或 API 特殊行为时添加
  • 错误处理:捕获具体异常。对于意外错误,使用 logger.warning()/logger.error() 并设置 exc_info=True
  • 跨平台:不得假设 Unix 环境(见下文)
  • Profile 安全路径:不得硬编码 ~/.tutou — 代码路径使用 tutou_constants 中的 get_tutou_home(),面向用户的消息使用 display_tutou_home()。完整规则参见 AGENTS.md。

跨平台兼容性​

Tutou 支持 Linux、macOS、WSL2 和原生 Windows。Windows shell 由 PM 解析 Git Bash。Dashboard 聊天通过 pywinpty/ConPTY 支持原生 Windows,并非仅限 WSL2。平台和依赖限制见平台支持。

贡献代码时,请遵守以下规则:

  • 不得添加未加保护的 signal.SIGKILL 引用。 Windows 上未定义该信号。请通过 gateway.status.terminate_pid(pid, force=True)(集中式原语,Windows 上执行 taskkill /T /F,POSIX 上发送 SIGKILL)路由,或使用 getattr(signal, "SIGKILL", signal.SIGTERM) 回退。
  • 不要在 Windows 上用 os.kill(pid, 0) 检查存活。 使用 psutil.pid_exists();信号调用不是安全的只读检查。
  • 不得强制终端使用 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. 文件编码​

某些环境可能以非 UTF-8 编码保存 .env 文件:

try:
load_dotenv(env_path)
except UnicodeDecodeError:
load_dotenv(env_path, encoding="latin-1")

2. 进程管理​

os.setsid()、os.killpg() 以及信号处理在各平台间存在差异:

import platform
if platform.system() != "Windows":
kwargs["preexec_fn"] = os.setsid

3. 路径分隔符​

使用 pathlib.Path 代替用 / 进行字符串拼接。

安全注意事项​

Tutou 拥有终端访问权限,安全至关重要。

现有保护措施​

层级实现方式
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. 手动测试:运行 tutou 并验证您修改的代码路径
  3. 检查跨平台影响:考虑 macOS、Linux、WSL2 和原生 Windows。如果您修改了文件 I/O、进程管理、终端处理、子进程或信号相关代码,请运行 scripts/check-windows-footguns.py。
  4. 保持 PR 聚焦:每个 PR 只包含一个逻辑变更

PR 描述​

请包含:

  • 变更内容及变更原因
  • 测试方法
  • 测试平台
  • 关联 issue 引用

Commit 消息​

我们使用 Conventional Commits:

<type>(<scope>): <description>
类型适用场景
fixBug 修复
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
  • 请包含:操作系统、Python 版本、Tutou 版本(tutou --version)、完整错误堆栈
  • 包含复现步骤
  • 创建前请检查是否已有重复 issue
  • 安全漏洞请私下报告

社区​

  • Discord:discord.gg/NousResearch
  • GitHub Discussions:用于设计提案和架构讨论
  • Skills Hub:上传专业 skill 并与社区共享

许可证​

提交贡献即表示您同意您的贡献将以 MIT 许可证 授权。