This release is a pre-release and may not be stable for production use.
SSH Agent Harness
LLM 驱动的 SSH 命令生成/执行框架,仅本机 Web 控制台。 支持本机 Ollama(deepseek-r1)或任意 OpenAI 兼容端点(DeepSeek/vLLM/Azure), 以 Harness 架构把「模型 + 工具 + 上下文 + 评估 + 护栏」组合成安全可审计的运维助手。
架构
┌─────────────────────────────────────────────────────────────┐
│ SSH Agent Harness(纯 Web) │
├─────────────────────────────────────────────────────────────┤
│ Web 控制台(FastAPI + React SPA) │
├─────────────────────────────────────────────────────────────┤
│ Generator (deepseek-r1) │ 命令生成 + CoT / 多轮修复 │
├─────────────────────────────────────────────────────────────┤
│ Tool Execution Layer │ SSH / SFTP 传输 / 文件 │
├─────────────────────────────────────────────────────────────┤
│ Context & Memory │ 会话 / 服务器工作空间 / 指纹 │
├─────────────────────────────────────────────────────────────┤
│ Evaluator / Guardrails │ 安全分级 / 审批门控 / 审计 │
└─────────────────────────────────────────────────────────────┘
安装
从 PyPI 安装(自带前端控制台,装完直接可用):
pip install ssh-agent-harness
ssh-agent-web # 浏览器打开 http://127.0.0.1:8000
开发(源码 + 热更新):
conda activate python312
pip install -e ".[dev]"
打包与发布(本地构建、TestPyPI、正式 PyPI)见 docs/packaging-and-release.md。
也可使用本机模型:先 ollama serve,再 ollama pull deepseek-r1:1.5b;
或通过环境变量指向外部 OpenAI 兼容端点(key 只走 env,勿入库):
export LLM_PROVIDER=openai LLM_MODEL=deepseek-chat LLM_API_KEY=***
# 可选:LLM_BASE_URL=https://api.deepseek.com
启动
唯一入口是 Web 控制台 ssh-agent-web(ssh_agent_harness/api/__main__.py:main):
ssh-agent-web --db ./data/agent.db
# 或显式参数:
ssh-agent-web --host 127.0.0.1 --port 8000 --db ./data/agent.db --approval-timeout 900
⚠️ 只能用
ssh-agent-web启动。不要用uvicorn直启 app (python -m uvicorn ssh_agent_harness.api.app:app)——它不解析--db, 会落到用户默认库并触发启动清理(误伤在飞任务)。
| 参数 | 默认值 | 说明 |
|---|---|---|
--host |
127.0.0.1 |
绑定地址;默认只监听回环 |
--port |
8000 |
监听端口 |
--db |
settings.storage.db_path |
SQLite 路径 |
--approval-timeout |
900.0 |
审批等待秒数;超时后审批置 expired、任务判 denied |
--static |
包内自带的 SPA | 覆盖内置前端目录;源码开发时指向 web/dist,安装版无需传 |
交互式 API 文档:http://127.0.0.1:<port>/docs。
日志:启动时按 settings.yaml 的 logging 段装配(控制台 + 轮转文件,默认
~/.ssh-agent-harness/ssh-agent.log,format: json 每行一条;~ 自动展开)。
前端 dev / 构建
前端控制台源码位于 web/(React 18 + TypeScript + Vite 5 + Ant Design 5 + react-query 5):
# dev 双进程:只起本后端(纯 API),前端 dev server 另行启动并把 /api 反代到后端
ssh-agent-web --port 8000
npm run dev --prefix web # vite dev server(5173),/api 反代到 127.0.0.1:8000
# build 单进程:前端产出 dist,后端同一进程托管 SPA 与 /api
npm run build --prefix web # 产出 web/dist(不入库)
ssh-agent-web --port 8000 --static web/dist
后端未开 CORS,dev 模式请走 vite 的
/api反向代理,勿让前端跨源直连。
配置
config/settings.yaml:主设置(LLM provider、SSH、safety、storage/SQLite 路径)。- 服务器清单存 SQLite
hosts表(经 Web 控制台「服务器管理」页增删改;DB 密码明文=已知接受风险,API 永不回显 password)。 - LLM provider 生效优先级:UI 控制台配置 > env
LLM_*>settings.yaml。- UI:「模型配置」可切 Ollama / DeepSeek API / 自定义端点,选择存 SQLite(密钥明文为已知风险、响应永不回显)。
- env:
LLM_PROVIDER/LLM_MODEL/LLM_BASE_URL/LLM_API_KEY(或DEEPSEEK_API_KEY)。 LLM_TIMEOUT(env)可覆盖读超时(默认 600s)。- 注意
config.py以 YAML init 注入 Settings,OLLAMA__*风格 env 覆盖不生效,请用LLM_*。
- Safety:
rm -rf类黑名单为硬 DENY(审批不可越过);systemctl stop等触发确认门;kill/pkill默认直接放行。
Web 功能
- 提交任务:智能模式(默认)/ 快速模式,可设 dry-run、修复轮数(rounds)、步进循环。
- 审批弹窗:危险命令挂起,弹窗内批准/拒绝;超时自动拒绝。
- 服务器管理:YAML ∪ DB 合并视图,CRUD + 连通性测试。
- 服务器工作空间(知识库):按服务器维护规范与事实,供探测轮注入。
- 任务记录:执行记录(sessions)与审计轨迹、run 详情时间线、按 run 撤销工作空间事实。
run 状态机
queued → generating → [awaiting_approval ⇄ running] → succeeded | failed | denied | cancelled
(dry-run 不经审批;cancel 优先于并发完成;重启时未终结的 run 在启动清理中置 failed)
多轮修复(rounds)
POST /api/runs 请求体 rounds(1-10,缺省 1)大于 1 时启用反馈回路:每轮执行完毕,
把命令及其 stdout/stderr 组成观察回灌给模型,模型判定任务是否完成——输出 TASK_COMPLETE
是确认成功的唯一通道;未完成则给出修正命令,下一轮继续执行;轮尽仍未确认 → 终态 failed
(verdict=exhausted)。dry-run 同样适用。verdict 词表
complete|exhausted|no-progress|repair-failed,null = 终态未落判定。
安全边界
- 默认仅监听 127.0.0.1,且无任何鉴权:能访问该端口即可完整操作服务器,勿暴露到公网。
- 明文密码为已知风险:DB 服务器的密码明文存于 SQLite,且
PUT /api/hosts请求体明文传输(仅回环缓解)。 - cancel 不打断在飞命令:只阻止后续命令执行并落终态
cancelled,已发出的 SSH 命令会跑完。 - 安全黑名单硬 DENY:
rm -rf /、mkfs、dd of=/dev/*等被 gate 直接拒绝,审批无法越过。 - 审批超时即 denied:等待
--approval-timeout秒无人决策 → 审批 expired、任务 denied。 - 同一数据库文件同时只允许运行一个
ssh-agent-web实例:启动清理会把库内全部非终态 run 置 failed;多实例请各自指定独立--db。 - dry-run 不落库:只生成不执行,也不写 session 历史。
- 服务器/审批响应一律脱敏:不回显密码与私钥内容。
API 速览
| 方法与路径 | 说明 |
|---|---|
GET /api/version |
版本号 |
GET /api/llm |
当前生效模型 + provider 目录(presets)+ api_key_set;永不回显密钥 |
PUT /api/llm {provider, model, api_key?, adapter_type?, base_url?} |
切换模型(UI 配置存 SQLite,优先于 env/settings) |
DELETE /api/llm |
清除 UI 切换,回落 env/settings |
GET /api/hosts |
服务器清单(读 SQLite hosts 表,脱敏) |
POST /api/hosts |
新建 DB 服务器(同名 shadow YAML 服务器,DB 字段优先) |
PUT /api/hosts/{name} |
更新 DB 服务器;YAML 服务器 403 |
DELETE /api/hosts/{name} |
删除 DB 服务器行;YAML 服务器 403 |
POST /api/hosts/{name}/test |
连通性探测,返回 {reachable, latency_ms, error} |
GET /api/sessions?host=&status=&limit=&offset= |
执行历史,新→旧 |
GET /api/sessions/{id} |
会话详情 + 按时间正序的审计轨迹 |
DELETE /api/sessions/{id} |
删除会话及其审计 |
POST /api/runs {task, host, dry_run?, rounds?, step?} |
提交后台任务 → 202 |
GET /api/runs?limit=&offset= |
run 列表(新→旧,全状态) |
GET /api/runs/{id} |
轮询:status / current_step / commands / results |
POST /api/runs/{id}/cancel |
取消活跃 run;终态或未知 → 409 |
GET /api/approvals?run_id=&status=pending |
待审批收件箱(仅支持 pending) |
POST /api/approvals/{id}/decide {decision: approve|deny} |
首次决策生效并唤醒任务;重复 decide 409 |
GET/PUT/DELETE /api/knowledge/... |
服务器工作空间(规范与事实)读写与撤销 |
测试与门禁
# 后端单测(无需 Ollama/SSH)
conda run -n python312 --no-capture-output python -m pytest -m "not integration" -q
# 类型检查(strict)
mypy ssh_agent_harness
# 前端门禁
npm run typecheck --prefix web
npm run build --prefix web
提交门槛 = 上述四项全绿。集成测试(需 Ollama + 数据库中配置的真实服务器):
conda run -n python312 --no-capture-output python -m pytest -m integration -v。
目录结构(纯 Web)
ssh_agent_harness/
├── api/ # Web 后端 FastAPI 包(app/run_manager/routes/schemas/deps/__main__)
├── core/ # orchestrator/step_loop/multi_turn/llm 工厂/host_loader/run_persistence/...
├── tools/ # ssh_pool(asyncssh)/paramiko fallback/command_executor
├── harness/ # safety + confirmation(含 Web 挂起审批) + evaluator/rollback/protocol
├── storage/ # session_store(SQLite) + run_store(runs/approvals) + host_store
└── config.py # pydantic-settings Settings
web/ # React18+TS+Vite+AntD5 控制台(dist 不入库;打包前由 scripts/build_frontend.py 拷入包内 static/)
tests/ # 最小 Web 测试集(api smoke / web entry / config)
docs/superpowers/ # 黄金路径手册等
config/ # settings.yaml(服务器在 DB,经 Web 服务器管理页维护)
License
MIT
Metadata
Release files for ssh-agent-harness 0.1.0rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ssh_agent_harness-0.1.0rc1.tar.gz | 727.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ssh_agent_harness-0.1.0rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.4 MB
Release files / ssh_agent_harness-0.1.0rc1.tar.gz
| Download URL | ssh_agent_harness-0.1.0rc1.tar.gz |
|---|---|
| Size | 727.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fd1f70d2cc56ac80f072d4ed3e88a9cbd8ced72051c9e7ecfff59d3e606ddf6d
|
|
BLAKE2b-256 checksum How to use checksums |
662c4d04cbd0205f0f4556a117e7b25f128e0fb98f9ca74335b889fda11b0c0c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / ssh_agent_harness-0.1.0rc1-py3-none-any.whl
| Download URL | ssh_agent_harness-0.1.0rc1-py3-none-any.whl |
|---|---|
| Size | 692.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d2c609333515b43d4e2903b53c74c829bfc0c7cc6480d15bb282ae15d98c7173
|
|
BLAKE2b-256 checksum How to use checksums |
15578fb1a985e510ea4afda0fbe2e2724d11612cbc9b788001ce2aebe0f78378
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Security for ssh-agent-harness 0.1.0rc1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.