包管理

hermes pm 管理 Hermes 工具二进制和 Python 依赖环境。它不是应用更新器。更新 Hermes 本体用该安装的更新方法。

钉版、已装状态与运行时选择 {#pins-installed-state-and-runtime-selection}

每个文件各有角色:

文件角色
pm/lock.json精确的受管工具版本、按目标的 URL 和 SHA-256 哈希。
pm/pyproject.toml 和 pm/uv.lock依赖管理器独立的 Python 需求和锁定解析。
pyproject.toml 和 uv.lockPython 需求、extras、平台标记和已提交的 Python 解析。
工具库 facts.json已装工具条目、其身份、环境导出和实际文件摘要。
按安装的 facts.json所选 Python 环境、其输入戳和已启用 extras。
载荷 manifest.json相对载荷布局和 bundle 构建器完成的启动契约。
install-stamp.json构建来源和声明的分发/更新归属。

一个 lockfile 条目不证明包已安装。hermes pm doctor 对照锁检查已装状态并核对实际字节。启动用更便宜的检查。它不在每次启动时查询上游版本。对自管理源码安装,pre-import 启动器把 PM 记录的成功依赖戳与当前输入比较。缺失或陈旧的完成状态触发一次 sync,然后同一命令在托管 Python 上重启,再加载应用依赖。失败的 sync 保留先前选择,下次启动重试;无需待更新标记。开发者 checkout 和打包安装保留其既有归属。

历史更新器在替换源码树后仍可能执行旧 Python 代码。兼容入口点启动一个新子进程、等其完成并返回其退出状态。子引导在应用 import 前请 PM 备齐所需工具并选择 Python 世代。完成逻辑在那个解释器中带着更新上下文和回执运行。父进程不清 sys.modules、不 import 新应用图、也不恢复 pip 回退。

当前源码更新把所选 checkout 交给一个新的完成归属方。其引导 Python 在请 PM sync 已记录 extras 和已启用插件之前,禁用 site-package 初始化。所选 Python 随后拥有前端构建、profile/配置维护、网关重启和运行时验证。Git、已最新重试和 ZIP 回退都走这条同一路径。原命令在等待时持有更新锁;缺失或失败的完成结果不能报告成功。相关联的 PM 失败留在更新回执中,被中断的重启保留其机队义务。依赖或构建失败绝不通过 pip 或源码重下载重试。依赖文件损坏用 hermes pm repair。见开发者源码完成归属说明。

源码安装与打包构建 {#source-installs-and-packaged-builds}

源码安装器备齐所需工具加 Python。它们选 all Python extra。命名的可选工具在请求时安装。

对规范源码安装,Desktop 检查并运行已发布的安装启动器。PM 拥有其解释器和依赖选择。Desktop 不用猜测的 venv 路径替换该命令。开发者覆盖保留其选定解释器。

原生桌面 bundle 在打包前 staging 受支持工具集和所有目标兼容的 Python extras。--extra all 与 --all-extras 不是同义词。平台标记仍排除无法在目标上运行的依赖。

完整桌面构建器把 PM 与 Node/原生打包提供商组合。从发布标签的干净 checkout,python scripts/bundles/desktop.py --tag vX.Y.Z 准备依赖并构建安装器。加 --prepare-only 在准备后停止;用 python scripts/bundles/desktop.py --prepared .build/desktop-job/prepared.json 消费其作业本地结果。--work 和 --cache 选择独立的构建归属根。准备(而非调用方)创建工作目录。一个完整 commit SHA 可经 --commit 替代标签;checkout 必须匹配。

准备使用隔离的 PM 状态、钉版工具、全新的路径绑定 Python 环境、完整 JS workspace 并集、原生绑定和打包工具。可复用依赖缓存不是活安装,也不是可移植虚拟环境。准备结果绑定源码、目标和路径;缺失或变更的输入使消费失败而非触发下载。移动或输入变更后重新准备。签名和公证仍可使用网络。原生编译器要求和发布验证限制见桌面构建指南。

打包应用的基础载荷不可变。Hermes 从该载荷运行其后端,而非在首次启动时复制一份源码 checkout。bundle 构建器检查其文件并把启动路径写进桌面构建戳。Electron 用这些路径,不探测也不修复载荷。额外钉版工具可用可写工具库。Python 增补用签名包外一个完整可写环境。其第一代保留随包 extras 连同新需求。后续世代以记录的 extra 选择为基线。

Termux 用独立的 bionic 构建和密封 APT 包。Docker 把运行时烤进镜像并禁用按需依赖安装。Nix 经 derivation 提供运行时。其限制见 Termux、Docker 和 Nix 指南。

可写状态 {#writable-state}

平台默认数据根在 POSIX 上是 ~/.hermes,在 Windows 上是 %LOCALAPPDATA%\hermes。HERMES_HOME 和 profile 可改变一个进程用哪个数据根。

状态默认位置
共享可写工具条目解析出的默认 Hermes 根下的 tools/。
可恢复下载该根下的 cache/partials/,不在签名载荷内。
按安装的选择与日志依赖状态根下的 installs/INSTALL_KEY/。
Python 世代installs/INSTALL_KEY/environments/。
sync 与更新回执活动 home 下的 logs/update_receipts/。

安装键从规范源码或载荷仓库路径派生。因此不同 checkout 有不同 Python 选择。共享同一安装的 profile 可向同一环境贡献依赖。它们的配置和凭据仍按 profile 隔离。

不要手动编辑 facts 或世代路径。启动器在第三方 import 前解析所选环境。进程在重启前保留其既有 import。垃圾回收保留所选世代和有活读者的租约管理世代。

下载按每个 partial URL 共享一把锁。失败或暂停的传输不能发布一个 partial 目的地,垃圾回收不能删除活传输的文件。恢复仅在记录长度、校验器和可选哈希仍匹配时复用范围。没有强 ETag 或钉版哈希时,中断的传输重新开始,而非混合不同版本。小 .locks/ 文件在完成后保留,使等待中的进程用同一把锁。

可选 Python 依赖与插件 {#optional-python-dependencies-and-plugins}

内建功能经 pm.ensure_import 请求一个项目 extra。目录插件在 pyproject.toml 中声明 Python 需求。没有作者编写的项目文件时,PM 合并 plugin.yaml 或 plugin.yml 中旧的 pip_dependencies 和 python_dependencies 清单。旧的 PM 生成项目文件不覆盖这些清单。同意、依赖归属和时效检查用同一套声明读取器。

PM 一起准备核心需求、已启用 extras 和已启用插件需求。它从既有锁播种解析。兼容的传递版本可变,但声明约束和精确钉版保持绑定。每个候选获得一个全新 workspace,带显式源码、锁种子和已准备环境输入。生成的 workspace 和扩展锁留在随包源码之外。修复复制记录的 workspace 和锁(含插件构建输入),而非对着编辑过的活 manifest 重新解析。

插件启用和分阶段代码更新作为数据提交给隔离的 PM worker。在安装锁下,它发现提议的依赖并集、校验候选,并随环境选择发布配置或插件文件和 metadata。它拒绝准备期间变更的输入。一份持久日志允许在应用 import 前恢复,包括不需要新环境的纯代码更新。

插件选择变更(含 pack 启用)走同一准入事务。PM 在应用每次变更前,在其共享锁下读最新选择。失败候选不替换所选环境,也不静默禁用其他插件。即使准备成功,运行中的 Hermes 进程仍可能需要重启来激活新环境。

普通 Hermes 应用更新保留用户插件目录。显式插件更新可改变所选插件的文件。没有 Python 依赖声明的包装器不加入共享环境。其外部 sidecar 仍单独归属。见插件指南。

懒安装策略 {#lazy-install-policy}

security.allow_lazy_installs 控制按需安装。该设置为 false 时,已装依赖仍可用。

hermes config set security.allow_lazy_installs false

显式安装命令与按需安装不同。但当懒安装被禁用时,bundle 的冻结功能清单仍限制所请求的 Python extra 名。显式插件准入是单独操作,不是按需功能请求。不要把这个设置当作沙箱或对手动安装包的一刀切禁止。Docker 还在镜像里设了内部懒安装禁用标志。

PM 是依赖管理器,不是插件代码的沙箱。安装一个插件意味着信任该插件及其依赖。

可选安全工具 {#optional-security-tools}

PM 拥有 pm/security_packages.py 中钉版的 bws、tirith 和 iron-proxy 包。其版本、产物 URL 和 SHA-256 哈希来自 pm/lock.json。下载和发布用共享工具库,不用 $HERMES_HOME/bin 下的私有安装器。

对 Tirith 和 iron-proxy,PM 还获取钉版签名文件并检查 release 校验和覆盖钉版归档。包 staging 调用集成的签名检查器。Cosign 和 GPG 检查仍以可用可执行文件为条件。锁定的来源文件必须仍可用且哈希匹配。显式签名拒绝中止安装。外部可执行文件不在 PM 的哈希和签名保证范围内。

bws 和 iron-proxy 在检查 PM 选择前优先用 PATH 上的可执行文件。Tirith 优先用 security.tirith_path,其次在其默认名的 PM 选择前用 PATH。显式 Tirith 路径绝不触发替换下载。懒安装遵守 PM 策略。显式安装命令检查并修复受管条目,包括带 --force 的请求。

开发者工作流 {#developer-workflow}

激活请 PM 为源码 checkout 准备或 sync 工具链,然后让它在 shell 中可用。它不选你编辑器的 Python 解释器,也不把已装桌面应用重定向到这个 checkout。

准备一个 checkout {#prepare-a-checkout}

在打包 Hermes 应用之外的普通终端里操作。先离开任何既有 Python 虚拟环境。Windows 上用带 Git 的原生 PowerShell。ARM64 上,PM 在每次从 checkout 构建依赖前准备 Visual Studio C++ 工具、Clang、原生 Rust 和静态 OpenSSL 开发库:setup、activate.ps1、install.ps1、hermes update 和 repair 一视同仁。它复用既有安装并安装缺失前置。缺失的 Visual Studio 组件需要管理员权限:交互式安装经 UAC 提示询问,而 CI、ssh 和计划任务需要 Administrator PowerShell。OpenSSL 用 vcpkg 的 arm64-windows-static-md triplet。损坏的共享安装产生修复错误,而非自动删除。编译器和 OpenSSL 环境变量只作用于 PM 的依赖构建,绝不作用于你的 shell。

其他平台仍需要无兼容 wheel 的依赖所需的原生编译器工具和库。

对钉版 macOS Python,PM 默认把 AR 设为 /usr/bin/ar:分发解释器的 sysconfig 仍指向其供应商的临时 LLVM 目录。这同时适用于源码和 bundle 构建。显式 AR 和 CC 值保持权威;PM 不改调用方提供解释器(如 Nix Python)的工具链。当前钉版不需要 CC 默认值。

克隆仓库并在准备依赖前选好分支:

git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent

为隔离开发,在第一条 PM 命令前选一个独立数据 home。回到这个 checkout 时保持相同值。

Bash,在仓库根:

export HERMES_HOME="$HOME/hermes-dev-data"
export HERMES_RUNTIME_DIR="$HERMES_HOME/tools"
source ./activate

PowerShell,在仓库根:

$env:HERMES_HOME = Join-Path $HOME 'hermes-dev-data'
$env:HERMES_RUNTIME_DIR = Join-Path $env:HERMES_HOME 'tools'
. .\activate.ps1

这些示例中的 HERMES_RUNTIME_DIR 是进程本地的开发覆盖。它让引导和 PM 用同一个可写存储。不要把路径持久化进已装 MSIX 或 macOS bundle。激活运行 setup 脚本的仅运行时路径来备齐工具并 sync all Python extra。它不选 dev 也不装 JS workspace。它维护安装本地命令并修复既有归属的 PATH 包装器,但不创建新的 PATH 便利项,也不加载应用配置。它还跳过 setup 面向用户的安装工作:shell 配置、.env 和内置技能。若你要完整安装工作流,单独运行 setup 脚本。

Python 尚不存在时,shell 引导获取钉版解释器。Python 能跑后,它把依赖工作交给 PM。PM 的私有引擎在解析应用依赖前准备自己小而锁定的运行时。它的项目独立于应用 workspace:坏掉的应用依赖绝不能阻止依赖管理器启动。

uv 是 PM 的私有实现细节。应用代码、setup 流程和构建调用方请求 Python 操作,不请求 uv 可执行文件或命令参数。不要用裸 pip 或 uv 命令改动 Hermes 环境。

PM 的运行时含 ruamel.yaml、packaging、tomli-w 和 truststore,不是应用依赖树。CLI 命令和应用请求的安装、修复在那里跑。只读路径和已装工具查找仍本地。环境时效检查用一个就绪的 PM worker。PM 绝不把自己的依赖加进已运行智能体的 import。一方 YAML 读写器用 ruamel;第三方包在应用环境里仍可能要 PyYAML。失败回执保持仅用标准库。

PM 的 CLI 和 worker 在 import 其 HTTPS 客户端前激活 truststore。这使用平台证书库,即使引导 Python 编译进的 OpenSSL 路径找不到它。无需应用依赖或证书路径覆盖。首次安装后,PM 下次调用时对着托管 Python 重建其小环境;后续调用复用它。

pm.venv_is_current() 经既有 PM worker 检查,即使懒安装被禁用。它绝不只为探测而引导 PM。若管理器运行时不可用,它返回 false,不下载工具或依赖。先跑一次显式 hermes pm install 准备 PM。

原生 bundle 和 Docker 镜像经共享运行时构建器 staging 同一份 PM 锁。Termux 把其验证过的离线 wheelhouse 提供给该构建器。Nix 把 PM 锁构建为单独 derivation。打包 worker 只用其记录的 PM 依赖目录,绝不用应用的库。

激活既有安装 {#activate-an-existing-installation}

每个新 shell 里,恢复你的开发 home 值并进入 checkout。然后激活它;没有单独的 setup 命令要记:

Shell进入离开
Bashsource ./activatedeactivate
PowerShell. .\activate.ps1deactivate

PowerShell 里前导点和空格是必需的。不带点源执行 .\activate.ps1 不提供同样的会话作用域。POSIX 脚本用 Bash 语法。这条配方用 Bash,而非 sh、fish,也不要假设 Zsh 启动文件有 Bash 语义。

每次激活调用 PM 的 install/sync 路径,并信任记录的工具摘要,而非对每个条目重新哈希。PM 仍会安装缺失工具、重建陈旧依赖世代;一次有意安装保留字节检查。跑 python -m pm.cli install 或 hermes update 重新核对实际字节。setup 失败在改变已激活 shell 环境之前返回错误,包括重新 source 一个已激活环境时。

sync 后,激活把已装 PM 工具前置进 PATH,并把 PYTHONPATH 设为这个 checkout 及其所选依赖树。它还为这个 worktree 把 hermes 定义为 shell 函数。该函数运行这个 checkout 的 CLI 并遮蔽已装命令(含 MSIX 别名)。它只在 shell 位于本 worktree 内时运行,在外面拒绝,因此兄弟 worktree 不继承该命令。提示获得一个命名分支的前缀,在树外时去掉。它不改 OS 级 PATH,也不装传统 venv 提示。在干净 shell 里开始,而非嵌在另一个 venv 里。deactivate 恢复激活脚本捕获的环境值,并移除函数和提示前缀。它不卸载包,也不停掉你启动的进程。

干活前先核实解释器和源码:

python -c "import sys, pm; print(sys.executable); print(pm.__file__)"
python -c "import httpx; print(httpx.__file__)"
node --version
npm --version
hermes --version

python 必须解析到 PM 库解释器。pm.__file__ 必须指向本 checkout。依赖来自所选环境,可在仓库外。import 缺失意味着 setup 或选择需要关注,即使 source ./activate 本身成功返回。

在这份源码树上工作 {#work-on-this-source-tree}

shell 在 worktree 内时,hermes 就是这个 worktree 的 CLI。worktree 外函数拒绝,因此它不能跑另一个 checkout 的树,也不会落到已装命令:

hermes setup
hermes
hermes --tui
python -m pm.cli status

这些命令用所选开发 home。下一个进程即可看到源码文件改动。改完后重启受影响的 CLI、网关或后端。纯 Python 源码改动不必重装每个依赖。

对 JavaScript workspace,在仓库根跑一次 npm ci,然后跑相关 workspace 命令。例如:

npm run build --workspace ui-tui
npm run dev --workspace apps/desktop

网站是分开的:npm ci --prefix website,然后 npm run build:fast --prefix website。PM 激活提供工具,不提供这些 node_modules 目录或构建产物。原生桌面构建在桌面构建指南中有额外要求。

不改分支刷新依赖 {#refresh-dependencies-without-changing-branches}

分支或 lockfile 变更后,重新 source 激活脚本以 sync 并选择新依赖(Bash 里 source ./activate,PowerShell 里 . .\activate.ps1)。要在不激活 shell 的情况下 sync:

python -m pm.cli install

独立 sync 后,重新激活环境。重启受影响进程。工具诊断用 python -m pm.cli doctor,最新 sync 回执用 python -m pm.cli status。不要只为刷新一个功能分支而跑 hermes update:那是应用更新,会改变源码分支。

受管工具名和 Python extra 名是不同接口:

python -m pm.cli install chromium
python -c "from pm import sync_venv; sync_venv(['anthropic'], explicit=True)"

第一条命令装一个工具。第二条向本安装既有 Python 选择加一个声明的运行时 extra。extras 经 PM sync 累积。dev 和 test 依赖组只属于独立测试环境,不属于所选应用 venv。改完 extras 后,在启动另一个 Python 进程前重新激活。

编辑 pyproject.toml 后同步 {#syncing-after-you-edit-pyprojecttoml}

  1. 编辑 pyproject.toml。按依赖钉版策略要求钉死每个依赖。用 PEP 508 标记表达平台限制,或在 [tool.hermes.extras-platforms] 里门控整个 extra。

  2. 重新锁:

    hermes pm lock
    

    它用 CI 检查时同样的设置从 pyproject.toml 重新解析 uv.lock,包括 14 天 exclude-newer 隔离期。它不改环境。锁已最新时,它会说明并不写任何东西。(hermes pm lock --bump NAME VERSION 是另一操作:它在 pm/lock.json 钉一个受管工具,不碰 uv.lock。)

  3. 重新 source 激活脚本(source ./activate,或 PowerShell 里 . .\activate.ps1),把应用 venv 和测试解释器 sync 到新锁。激活覆盖 [all]。若你在 [all] 外加了一个可选 extra,hermes pm lock 会打印把它也放进测试解释器的命令,例如 source ./activate --test-extras all,NAME。

  4. 一起提交 pyproject.toml 和 uv.lock。

JS 依赖则更新所属包 manifest 和锁。不要编辑 PM facts 或生成的 workspace,也不要直接往所选世代装包。

测试与编辑器环境 {#test-and-editor-environments}

source ./activate(或 PowerShell 里 . .\activate.ps1)和两个直接的 setup-hermes 脚本都从锁定的 dev 和 test 依赖组准备一个隔离测试解释器。scripts/run_tests.sh 用那个解释器,checkout 或其依赖输入变更时重新激活。应用 venv、安装器和 bundle 都不选这两个组。开发者默认覆盖 [all];要改测试覆盖,给 POSIX 激活传 --test-extras=anthropic,给 PowerShell 传 -TestExtras anthropic;这些参数只在测试解释器里选运行时 extras。

在一个没有激活的隔离环境里(例如 Nix dev shell),调用方可显式给 pytest 提供 HERMES_PYTHON,或构建一个独立的一次性环境:

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

输出不得已存在。要重新生成它,先停掉其进程并有意只删除那个一次性环境。然后跑 scripts/run_tests.sh(Windows 上经 Bash)。测试依赖组含原生启动器测试,绝不进入打包运行时。

编辑器调试则选那个独立解释器,把工作目录设为本 checkout,并把 hermes 作为脚本启动。让其 HERMES_HOME 与生产分开。终端激活不配置已经在跑的编辑器。不要把编辑器指向瞬态 PM 世代或签名应用的 Python 可执行文件。

Python 操作接口 {#python-operation-interfaces}

Python 依赖工作用公开的 pm 模块:

操作归属
pm.sync_venv(extras, explicit=True)准备并选择完整应用依赖并集,含已启用插件。
pm.sync_venv(repair=True, explicit=True)在新应用世代重放记录的依赖集。
pm.build_environment(source=..., out=..., explicit=True)构建并校验一个全新的、调用方拥有的输出。无插件发现、无应用选择。
pm.lock_project(source, explicit=True)刷新一个显式项目的锁,不选环境。
pm.ensure_environment(name, requirements, explicit=True)准备并选择一个隔离依赖世代。返回其 Python 路径。
pm.ensure_python_tool(name, requirements, executable, explicit=True)准备一个隔离工具并返回其可执行路径。
pm.environment_python(name) / pm.python_tool(name, executable)读所选路径,不装任何东西。
pm.venv_is_current()问一个就绪 PM worker 应用依赖是否最新。管理器运行时不可用时返回 false。

pm.stage_manager_runtime(...) 是引导例外。它经直接私有引擎 staging PM 自己的锁定运行时,因为该运行时无法经自己的 worker 自举。它不向调用方暴露 uv。

pm.build_env 是显式构建和锁工作的命令行接口。支持选项跑 python -m pm.build_env --help。默认项目构建用已提交锁。--resolve 在构建前解析。--python 选显式构建解释器。--sealed 移除构建期 .pth 引用。--offline 和 --cache 控制依赖获取。

应用环境构建要求 PM 已能在调用 Python 中启动。这些构建不是解释器引导。它们不改运行中应用的 import,也不替换其所选环境。Nix 的声明式 uv2nix 构建仍归 Nix。无关项目或智能体沙箱的包管理器命令不管 Hermes 本体。

命令 {#commands}

hermes pm --help
hermes pm doctor
hermes pm status
hermes pm install
hermes pm install chromium
命令作用
pm install [names...]安装命名包。无名字时,备齐所需工具加 Python、把这些工具放上 PATH,然后 sync all extra。裸 install 还装默认可选工具(agent-browser 和 Chromium、cua-driver);这些下载失败打印警告,不使安装失败。命名一个你之前拒绝过的包会撤销那个选择。
pm install --without NAME做一次裸 install,但不含默认可选包 NAME(agent-browser 或 cua-driver),并记录该选择。后续裸 install 和 hermes update 也略过它。安装器的 --skip-browser / -SkipBrowser 和 --skip-computer-use / -SkipComputerUse 用这个。
pm install --tools-only安装该工具闭包并放上 PATH,然后停止。venv sync 不跑。
pm env [names...]以 JSON 打印已装包贡献的 PM 环境值。它不装缺失包,尽管冷启动 Hermes 可能先准备自己的 Python 运行时。
pm doctor对照锁检查已装工具身份、文件和摘要。
pm repair在新世代重建记录的 Python 依赖集、校验它,然后选中它。不更新钉版、功能或插件配置。
pm status以 JSON 打印最新 sync/更新回执,或报告无回执。
pm gc移除未引用的工具库条目、合格的下载 partial 和未用的租约管理 Python 世代。

pm env 排除继承的进程变量,含凭据。其输出仍可能暴露本地安装路径;分享前审阅。

维护者命令 {#maintainer-commands}

这些命令改变依赖输入或 staging 构建产物。它们不是已装应用更新机制的替代品。

命令作用
pm lock从 pyproject.toml 重新锁 uv.lock。不改环境;锁最新时不写任何东西。
pm lock --bump NAME VERSION解析并哈希受支持目标产物,然后把工具钉版写进 pm/lock.json。
pm update [names...]查询上游版本、改工具钉版、装变更工具。
pm update --check查询不写入。退出码 1 可表示有更新;查看输出区分错误。
pm update --target TARGET为指定目标解析版本。
pm update --uv / --npm同时刷新 Python 或 npm 依赖解析。
pm update --termux [--check]重新钉滚动池已退役的 termux pool 归档(运行时库钉版表和 bionic 锁行)。--check 只报告不写入,钉版被退役时退出 1。
pm install --target TARGET NAME...staging 显式跨目标包,不把它们记为主机已装运行时。win32 git 目标钉一个自解压 PortableGit 归档:staging 它会跑厂商解压程序,因此需要 Windows 主机。
pm bundle --out DIR [--ref REF]staging 一份源码快照、原生工具、facts 和 Python 依赖。它不产出签名桌面安装器。

完整桌面构建器还构建 JavaScript 表面、生成启动器并调用原生打包。维护者可读构建桌面安装器。

网络重试 {#network-retries}

PM 在工具下载、产物哈希和版本查找期间重试瞬态 HTTP 失败。每次探测或传输至多四次尝试。退避等待为 1、2、4 秒。Retry-After 头可延长等待,最长 30 秒。每次重试在日志中报告其原因、延迟和下次尝试。

可重试 HTTP 状态为 408、429、500、502、503、504。连接重置、超时、临时 DNS 失败和被中断的响应体也重试。范围下载保留已完成字节。不支持 range 的服务器需要新流。暂停中断退避并保留 partial 下载。

PM 不重试坏哈希、证书失败、本地文件系统错误或其他永久失败。成功探测后一次 range GET 返回 403 或 404 时保留 CDN 回退:对缺失范围做一次串行尝试。解压、校验和发布不重复。Python 和 npm 包请求仍走 uv 和 npm 自己的重试策略。

诊断 {#diagnostics}

  • Python 依赖构建慢: PM 流式 uv 命令启用详细输出。bundle 和构建日志在构建运行期间显示包活动和构建后端 stdout/stderr,而非只在失败后。
  • 工具缺失或过时: 读 hermes pm doctor,然后在可写安装上用显式 PM install。
  • 新环境需要重启: 重启受影响的 Hermes 进程。不要往其活 import 里加第二棵 site-packages 树。
  • 依赖冲突: 读 hermes pm status。先修正插件需求再重试准入。
  • Python 依赖损坏: 跑 hermes pm repair,然后重启 Hermes。修复重放所选世代保存的 workspace 和锁,不解析插件配置。记录不可读或保存锁缺失时失败,不选一个缩减依赖集。世代尚不存在时,修复用随包或已提交锁和记录的功能集。
  • 依赖安装被中断: 启动在依赖激活前请求同一 PM 修复。自动尝试有界;pm repair 显式重试。失败的修复保留先前选择及其重试标记。
  • Python 可执行文件或应用源码损坏: 经包归属方修复或重装。PM 没有这些文件无法运行。依赖修复绝不修改签名载荷文件。
  • 未知包或 extra: 用声明的名字。pm install 接受包名,不接受 Python extra 名或 pip 规范。