安装与下载
1 ClawHub CLI
从源直接安装技能的最快方式。
npx clawhub@latest install rez-package-orderers
2 手动安装
将技能文件夹复制到以下位置之一
~/.openclaw/skills/
{'/skills/'}
优先级:工作区 › 全局 › 内置
3 提示词安装
将此提示词复制到 Openclaw 即可自动安装。
请帮我使用 Clawhub 安装 skill-rez-package-orderers。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
更倾向于下载?
获取包含原生技能文件的ZIP压缩包。
基本信息
rez-package-orderers
安装指南
- ClawHub CLI
从源直接安装技能的最快方式。
npx clawhub@latest install rez-package-orderers - 手动安装
将技能文件夹复制到以下位置之一
全局模式
~/.openclaw/skills/
工作区
/skills/
优先级:工作区 > 本地 > 内置 - 提示词安装
将此提示词复制到 OpenClaw 即可自动安装。
请帮我使用 Clawhub 安装 rez-package-orderers。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
更倾向于下载?
获取包含原生技能文件的ZIP压缩包。
下载技能 (.zip)
什么是
Rez 包排序器介绍 Rez 如何在求解器选择第一个符合条件的版本之前,对候选版本进行排序。内容涵盖五种内置排序器——sorted、version_split、per_family、soft_timestamp 和 no_order——并说明其规则如何影响包和变体。排序器会改变优先级,而不会改变可用性:显式请求某个版本仍然可以选择该版本。
当 rez-env foo 成功解析,却在没有冲突的情况下选择了意料之外的旧版本时,请使用这份 Openclaw Skills 指南。指南提供实用的配置示例、诊断命令和验证步骤,还说明了在内置规则不足时如何注册自定义排序器。文档所述行为适用于 Rez 3.4.0。
应用场景
诊断为什么
rez-env foo
会选择较旧版本,尽管存在更新版本。
检查配置分层是否引入了非默认的
package_orderers
设置。
在迁移期间优先选择不高于某个边界的版本,例如将 Python 2 保持为默认版本,同时允许显式请求 Python 3。
对选定的包系列应用不同的版本偏好,或使某个包免受排序规则影响。
优先选择某个时间戳之前的发行版,同时通过
rank
允许受控的版本变更。
验证解析结果变化是由排序器导致,而非依赖求解失败。
当内置排序器无法表达所需行为时,实现并注册自定义排序策略。
工作原理
使用 rez-config package_orderers 检查有效的 package_orderers 值;空列表表示采用默认的降序 sorted 行为。
如果该值非空,使用 rez-config --source-list package_orderers 找出提供该值的配置层。
Rez 获取包或变体候选项,并将配置的排序规则应用于候选列表。
求解器按该顺序尝试候选项,并选择第一个满足请求和约束的候选项。排序不会禁止其他版本,因此显式版本请求仍可选择优先级较低的候选项。
使用 rez-search foo 比较可用版本,并使用 rez-env foo -o context.rxt 和 rez-context --so 检查实际解析结果。
暂时清空 package_orderers 后重复解析,并比较所选版本,以确认因果关系。
配置指南
在 Rez 配置中设置 package_orderers,通常是在 rezconfig.py 中。更改行为前,先检查有效值及其来源:
rez-config package_orderers
rez-config --source-list package_orderers
示例:将不高于 1.1.0 的版本设为优先组:
package_orderers = [
{
"type": "version_split",
"first_version": "1.1.0",
}
]
要将排序规则限定到某个包,请提供 packages 列表。要按系列使用不同规则,请在 per_family 中嵌套规则。例如,优先选择不高于 2.7.16 的 Python 版本,同时保留对更新版本的显式请求:
package_orderers = [
{
"type": "per_family",
"orderers": [
{
"packages": ["python"],
"type": "version_split",
"first_version": "2.7.16",
}
],
}
]
验证可用候选项和解析结果:
rez-search foo
rez-env foo -o context.rxt
rez-context --so
对于自定义排序器,请在配置中定义并注册 PackageOrder 子类,然后再引用其已注册的 type。调用 super().init(**kwargs)——不要传入 self。
数据架构
Rez 排序器配置以 Python 数据表示,通常通过 rezconfig.py 中的 package_orderers 设置进行配置。每个条目都使用 type 字段;其他字段取决于排序器。规则可以选择包含 packages 以限定其作用范围,而 per_family 则包含嵌套的排序器定义。
排序器类型 配置字段和行为
sorted descending 控制版本方向;可选的 packages 用于限定规则范围。
version_split first_version 将小于或等于该边界的版本排在前面,然后对其余版本应用默认排序。
per_family orderers 包含适用于所选包系列的嵌套规则;未命名系列保留默认排序。
soft_timestamp timestamp 是 Unix 纪元整数;rank 控制版本变更偏离时间戳偏好的幅度。
no_order 空操作规则;适用于在 per_family 中保持所选包的顺序不变。
排序器会同时影响变体排序和包版本排序。Rez 配置分层决定有效设置;使用 rez-config --source-list package_orderers 追踪其来源。解析输出可以写入诸如 context.rxt 的上下文文件,而 rez-context --so 可以显示所选版本及产生该结果的请求。自定义排序器除了 sort_key_implementation 外,还必须提供包括 str、eq、to_pod 和 from_pod 在内的序列化相关方法。
高级特性
sorted
配置为升序或降序;默认行为为降序。
version_split
将不高于指定边界的版本排在较新候选项之前,而不阻止显式请求。
per_family
下嵌套规则,以按包系列调整排序,并使用
packages
限定规则范围。
使用带有 Unix 纪元时间戳和
rank
soft_timestamp
,平衡发行版的新旧程度与版本变更;请结合仓库验证结果,因为其效果取决于实际发行日期。
per_family
中使用
no_order
,使某个包免受原本适用的排序行为影响。
PackageOrder
并在配置加载时注册自定义排序器。自定义实现必须提供排序键和序列化方法;本指南建议尽可能使用内置排序器,尤其是
version_split
。
通过比较
rez-search
、解析后的上下文,以及移除排序设置后重复解析的结果来验证影响,而不要仅凭推测。
请记住,排序器也会影响变体的优先级,而且显式版本请求仍然可用。
name: rez-package-orderers
description: "How rez decides which version of a package to pick — the package_orderers setting, the five built-in orderers sorted / version_split / per_family / soft_timestamp / no_order, how orderers apply to variants as well as packages, writing and registering a custom orderer, and how to prove an orderer is or is not what changed your resolve. Use when rez picks a version you did not expect and the resolve is not failing, or when a studio needs python-2-style version pinning to survive an upgrade. Covers Rez 3.4.0."
Rez package orderers
One-sentence summary: an orderer reorders the version list rez sorts before it solves, so the "latest" version rez returns is the latest by the orderer's rule — and a configured orderer is the only reason a successful resolve picks an older version without any conflict to explain it.
Skill scope: the orderer mechanism itself — which orderers exist, how they are configured, and how to tell whether one is in play. For how version tokens compare (1.0.0 vs 1.0.0-beta, alphanumeric vs numeric segments) see rez-core-concepts; for a resolve that fails see rez-resolve-troubleshooting, since orderers only matter when the resolve succeeds; for reading the solver trace see rez-resolve.
What an orderer changes
The solver always asks the package repository for versions in a defined order and takes the first that fits. Orderers change that order. They do not forbid anything: a higher version is still reachable if you request it explicitly.
That is the diagnostic signature. If rez-env foo gives you 1.1.0 while rez-env foo-2 happily gives you 2.0.0, and there is no conflict anywhere, an orderer is almost always why.
Orderers apply to variants as well as to package versions, so a variant list is reordered the same way.
Is an orderer in play?
Check before you theorise — the default is empty:
rez-config package_orderers
An empty list means no orderer is configured and the default (sorted, descending) applies. A non-empty list is inherited through the normal config layering, so also confirm where it came from:
rez-config --source-list package_orderers
The built-in orderers
type What it does
sorted the default — sort by version, descending
version_split versions less than or equal to first_version first, then the default order
per_family apply different orderers to different package families
soft_timestamp versions released before timestamp first, then the rest; rank relaxes it
no_order a no-op — explicitly leave a package's order alone
sorted
The default. You only need to name it to change its direction, or to scope it:
package_orderers = [
{
"type": "sorted", # required
"descending": True, # required
"packages": ["python"], # optional; omit to apply to every package
}
]
descending: False inverts it, so the lowest version wins. Verified against a repository holding foo-1.0.0, foo-1.1.0, foo-2.0.0:
Orderer rez-env foo resolves
none (default) foo-2.0.0
sorted with descending: False foo-1.0.0
version_split
Orders every version less than or equal to first_version first, then falls back to the default order for the rest. Given [5, 4, 3, 2, 1], an orderer with first_version=3 yields [3, 2, 1, 5, 4].
package_orderers = [
{
"type": "version_split",
"first_version": "1.1.0",
}
]
With the same three foo versions, first_version: "1.1.0" makes rez-env foo resolve foo-1.1.0 instead of foo-2.0.0. Note the comparison is less than or equal to, so the named version itself is included in the preferred group.
The canonical studio use is easing a python-2 to python-3 migration:
package_orderers = [
{
"type": "per_family",
"orderers": [
{
"packages": ["python"],
"type": "version_split",
"first_version": "2.7.16",
}
],
}
]
For the python family, versions at or below 2.7.16 win. An explicit rez-env python-3 still gets 3.7.4.
per_family
Applies different orderers to different families. Any orderer above can be nested in it, together with a packages list. A family not named by any nested orderer keeps the default order.
This is also how you scope no_order.
soft_timestamp
Prefers packages released before timestamp (a Unix epoch integer), in descending order, followed by everything released after. rank relaxes the boundary: a non-zero rank lets version changes at that rank and above win over the timestamp.
package_orderers = [
{
"type": "soft_timestamp",
"timestamp": 1568001600, # 2019-09-09
"rank": 3,
}
]
rank: 3 is the usual choice under semantic versioning — it allows a different patch number through. Generate the timestamp rather than hand-computing it:
python -c "import datetime, time; print(int(time.mktime(datetime.date(2019, 9, 9).timetuple())))"
Which version wins depends on rank, and the effect is not monotonic — a rank that lets a later patch through can land on a different version than a rank that lets a later minor through. Measure it against your own repository rather than assuming, because the answer depends on when each version was actually released.
no_order
A no-op. It exists so that inside a per_family block you can apply an orderer broadly but exempt one package:
package_orderers = [
{
"type": "per_family",
"orderers": [
{"packages": ["foo"], "type": "no_order"},
],
}
]
Custom orderers
Subclass PackageOrder, implement the mandatory methods, and register it with register_orderer. Everything except sort_key_implementation is boilerplate you must supply for serialization:
# rezconfig.py
from rez.package_order import PackageOrder, register_orderer
class MyOrderer(PackageOrder):
name = "my_orderer"
def init(self, custom_arg, **kwargs):
super().init(**kwargs)
self.custom_arg = custom_arg
def sort_key_implementation(self, package_name, version):
...
def str(self):
...
def eq(self, other):
...
def to_pod(self, other):
...
@classmethod
def from_pod(cls, data):
...
register_orderer(MyOrderer)
package_orderers = [
{
"type": "my_orderer",
"custom_arg": "value here",
}
]
rezconfig.py is ordinary Python, so the class is defined and registered at config load time.
Do not pass self to super().init() — super().init(self, **kwargs) raises TypeError: 'MyOrderer' object is not iterable, because self lands in the packages argument that the base class sorts. The upstream package_orderers.rst at 3.4.0 shows the broken form in its custom-orderer example; the correct call is super().init(**kwargs).
Upstream explicitly warns against this: a custom orderer makes environments behave in ways users do not expect, and makes the affected packages harder to share. Prefer a built-in, and prefer version_split over anything bespoke.
Verifying what an orderer did
Never infer the effect from one command — compare the resolve against the version list.
rez-search foo # every version, as the repository holds them
rez-env foo -o context.rxt # what the solver actually picked
rez-context --so # the resolved version, with the request that produced it
If rez-context --so shows the version you did not expect, and rez-search shows a newer one exists, the orderer is the explanation. Confirm by repeating the resolve with the setting emptied — package_orderers is a normal config key, so a temporary override is enough to prove it.
Troubleshooting
Symptom Cause
An older version wins with no conflict an orderer reordered the version list
rez-env foo and rez-env foo-2 disagree working as intended — orderers do not forbid explicit requests
no_order seems to do nothing that is what it does; it only matters inside per_family
An unknown type is rejected at resolve time only sorted, version_split, per_family, soft_timestamp, no_order and registered custom names are accepted
The orderer applies to packages I did not name omit packages (outside per_family) and it applies to everything
A variant is chosen oddly orderers apply to variants too, not just versions
soft_timestamp picks a surprising version rank decides how far past the timestamp a version may drift; check it
Agent workflow
Read rez-config package_orderers first — an empty list means orderers are not your problem.
Find where a non-empty value comes from with rez-config --source-list package_orderers.
Distinguish "the version list is ordered unexpectedly" (rez-search) from "the solve failed" — the latter is rez-resolve-troubleshooting, not this skill.
Prefer version_split and per_family over a custom orderer; scope with packages.
Verify by resolving and inspecting with rez-context --so, then repeat with the orderer removed to prove it is the cause.
Windows 上的 Rez
Rez 软件包测试与 CI