GuardedPy 是智软训练营暑期学校的期末项目,也是一个面向小型 Python + pytest 项目的本地 CLI Coding Agent Harness。它自行实现连续 Agent 主循环,让用户在同一终端会话中自然对话、检查项目、修改代码、运行测试并继续追问;文件边界、测试反馈、危险动作审批、凭据和会话恢复由确定性代码控制。
当前产品只提供 CLI,不包含 WebUI、HTTP server,也不向模型提供任意 Shell、通用网络、依赖安装或自动发布工具。
- 从当前目录自动发现 Python 源码、测试目录和 pytest 命令;
- 连续 Session/Turn 对话,不对首条输入进行固定任务分类;
- 流式显示模型回复和安全工具状态;
- 受限文件列表、读取、原子补丁和源码/测试新文件创建;
- pytest 反馈分类、回灌和修改后的完整套件验证;
- 项目内 Python 程序运行与文件删除的精确人工审批;
- 只读计划、审查、Git status/diff 和本地诊断;
- keyring-only DeepSeek API Key 管理;
- 会话保存、恢复、选择与删除;
- 离线 mock LLM 单元测试和可观看的机制演示;
- 一键测试、机制演示、wheel/sdist 构建及 GitHub/GitLab CI。
- Linux 或 WSL;
- Python 3.11+;
- 目标项目使用 pytest;
- 交互 TUI 需要真实终端;
- 真实 DeepSeek 调用需要可用的系统 keyring/Secret Service 和到 provider 的网络连接。
git clone git@github.com:WalnuTpz/guardedpy.git
cd guardedpy
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"进入需要处理的 Python + pytest 项目,直接启动:
cd /path/to/python-project
guardedpyGuardedPy 会把当前目录固定为项目根,自动发现源码、测试和 pytest 配置。无需 /init,也不要求手工输入目录或测试命令。
可以传入一条初始请求:
guardedpy "检查当前项目并说明测试失败原因,不要修改"stdin 或 stdout 被重定向时,GuardedPy 使用安全纯文本模式。该模式不能录入秘密或批准危险操作;遇到审批会停止。
在交互界面输入:
/credentials
凭据界面支持:
- 查看是否已配置;
- 掩码录入或更新 DeepSeek API Key;
- 清除 Key。
Key 只写入操作系统 keyring,不会进入项目文件、Git、会话数据库、日志或终端输出。GuardedPy 不提供 .env、命令行参数或明文配置回退。若 keyring 不可用,程序会说明需要先修复系统密钥环。
不要把 API Key 粘贴到对话、命令、项目文件、截图或测试中。
- Enter:提交消息;
- Shift+Enter:输入换行;
/或[+]:打开命令面板;- 方向键/鼠标滚轮:移动选择;
- Enter 或鼠标点击:把候选项填入输入框;
Ctrl+Shift+C:复制当前安全 transcript;- Ctrl+C、Esc 或
/stop:请求中断当前回合。
键盘可以完成全部操作,鼠标用于辅助选择、滚动和点击。transcript 自动换行,只保留纵向滚动条。
| 命令 | 作用 |
|---|---|
/conversations |
选择并恢复已保存会话 |
/new |
新建会话 |
/delete |
删除当前会话并切回上一条;最后一条不能删除 |
/plan <任务> |
用只读模式制定计划 |
/review <路径> |
用只读模式审查项目或路径 |
/goal <目标> |
设置只影响下一回合的目标;/goal clear 取消 |
/queue <任务> |
把下一回合排到当前回合之后 |
/stop |
中断当前回合并清除排队回合 |
/tests |
运行发现到的 pytest 套件 |
/diff |
查看当前 Git diff |
/permissions |
查看自动允许、须审批和拒绝的操作 |
/doctor |
查看当前项目、配置和凭据状态 |
/credentials |
安全管理 API Key |
/model |
为后续回合选择模型 |
/effort |
为后续回合选择思考强度 |
/help |
打开分组帮助面板 |
/exit |
退出 GuardedPy |
支持的模型为 deepseek-v4-flash、deepseek-v4-pro;思考强度为 high、max。修改只影响后续回合,不改变正在运行的 Turn。
模型只能调用 GuardedPy 声明的受限工具:
- 列出和读取项目文件;
- 对源码/测试应用原子补丁;
- 运行 pytest;
- 读取 Git status/diff;
- 运行一个项目内 Python 文件;
- 删除一个普通文件或空目录。
读取、合法补丁、pytest 和 Git 只读检查经过确定性校验后自动执行。以下操作每次都需要精确审批:
- 运行项目内 Python 程序:审批框显示路径和参数;
- 删除文件或空目录:审批框显示目标路径。
拒绝、过期或伪造的审批不会执行动作。GuardedPy 不向模型提供任意 Shell、网络、包安装、Git 写入、部署或发布工具。
无初始任务启动时,GuardedPy 自动载入当前项目最近的会话。/conversations 可选择其他会话,/delete 可删除当前会话。
会话状态位于项目目录之外、按项目根隔离的应用状态目录。可恢复内容包括可见用户/Agent 对话和受限工具事实。以下内容不会保存或恢复:
- API Key;
- 隐藏 reasoning;
- 源码正文;
- 完整 diff;
- 原始工具参数;
- 完整 pytest 输出;
- 中断进程的执行状态。
guardedpy demo演示使用正常 TUI 外壳,但项目、请求和 mock 输出均为隔离的固定数据。使用 ↑/↓ 切换场景,按 Enter 或 [发送] 开始。删除场景会显示真实审批弹层,可以允许或拒绝。
make demo该命令使用同一 ConversationAgent 路径,确定性验证三个场景:
- 删除操作暂停等待审批;headless 模式固定拒绝并验证文件仍存在;
- pytest assertion failure 回灌后,mock 改变下一步动作为补丁,最终测试通过;
- 伪造或过期审批 ID 被拒绝。
演示不读取调用者项目、keyring,不访问网络,也不调用真实 provider。
make test
make demo
make build
python -m compileall -q src tests
git diff --checkmake test:运行全部离线单元与集成测试;make demo:运行固定 mock 机制证据;make build:在dist/生成 wheel 和 sdist。
离线测试使用 mock/stub LLM,不需要真实 Key 或网络。GitHub Actions 执行 test/demo/build 门禁;仓库同时附带 GitLab CI 配置,其中 job 名为 unit-test。
可在一个带已知失败测试的临时项目中依次验证:
- 普通问候和项目问题能自然回答;
- “检查错误但不要修复”不会写文件;
- 修复请求会读取、补丁、运行完整 pytest 并总结结果;
- 新建文件只能位于发现的源码或测试目录;
- 运行 Python 程序会显示准确审批,批准后显示有界输出;
- 删除操作可先拒绝并确认文件保留;
/stop能中断活动回合;- 重启后从
/conversations恢复,并能基于此前事实继续追问。
.
├── src/guardedpy/
│ ├── conversation.py # Session/Turn/Event 与连续主循环
│ ├── governor.py # 工具治理与审批身份
│ ├── executor.py # 工具分发和反馈回灌
│ ├── workspace.py # 根目录受限文件、pytest、Python、Git 工具
│ ├── feedback.py # pytest 确定性分类
│ ├── runtime.py # 会话组成、持久化与恢复
│ ├── conversations.py # 项目隔离的 SQLite 会话存储
│ ├── credentials.py # keyring-only 凭据服务
│ ├── discovery.py # Python/pytest 项目发现
│ ├── tui.py # Textual 正常界面与演示界面
│ ├── terminal.py # 安全纯文本入口
│ └── mechanism_demo.py # 三个 scripted mock 场景
├── tests/ # 离线机制、终端和安装产物测试
├── scripts/ # 无交互机制演示入口
├── Makefile
├── pyproject.toml
├── .github/workflows/ci.yml
└── .gitlab-ci.yml
- LLM 输出、仓库内容和测试输出都按不可信数据处理;
- 所有路径在执行前重新解析并限制在项目根;
- 补丁只能修改发现到的源码/测试范围,失败时零写入;
- 子进程使用固定 argv、超时和
shell=False; - 删除和程序运行使用绑定当前调用的精确审批;
- transcript 和摘要在持久化前脱敏并限制长度;
- 凭据只进入系统 keyring 和实际 provider 调用。
- pytest 会执行项目代码;恶意仓库不在安全模型内;
- 只支持 Linux/WSL、Python 3.11+ 和 pytest 项目;
- 只支持一个本地项目和一个活动 Turn;
- 不支持 Windows 原生终端、远程工作区、非 pytest 测试框架或多 Agent;
- 不向模型提供任意 Shell、通用网络、安装、Git 写入、发布、部署或后台终端管理工具;
- TUI 需要交互终端;重定向模式功能更窄;
- keyring/Secret Service 不可用时不会回退到明文凭据;
- 恢复会话只重建有界对话和安全事实,不恢复模型进程全部状态。
GuardedPy 通过包管理器使用下列直接依赖,不复制其源码:Pydantic(MIT)、keyring(MIT)、OpenAI Python SDK(Apache-2.0)、pytest(MIT)、PyYAML(MIT)、Textual(MIT)、build(MIT)和 setuptools(MIT)。发布时应以实际构建环境中的包元数据为准复核版本与许可证。