npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@genee/omp-opsx-addon

v0.9.0

Published

Pi Extension: OpenSpec workflow orchestration - coder/reviewer/planner agents, session title & progress

Downloads

1,326

Readme

omp-opsx-addon

Pi Extension: OpenSpec workflow orchestration — coder/reviewer/planner agents, session title & progress.


架构

┌─────────────────────────────────────────────────────────┐
│  主 agent (Orchestrator)                                 │
│  system prompt 由 plugin 注入: model 选择决策 + 路由表    │
│                                                          │
│  用户说 "@coder 实现 X" → transform 成 task 委派指令      │
└───────────────────────┬─────────────────────────────────┘
                        │
                ┌───────▼────────┐
                │  omp 内置 task  │
                │ (所有 role)     │
                │  原生 subagent  │
                └───────┬────────┘
                        │
               ┌────────┴──────────┐
               │ .omp/agents/      │
               │ coder / planner   │
               │ code-reviewer /   │
               │ proposal-reviewer │
               └─────────┬─────────┘
                         │ autoloadSkills
               ┌─────────▼─────────┐
               │ skills/           │
               │ opsx-orchestration│
               │ -protocol(随包) │
               └───────────────────┘

核心机制:主 agent 用 omp 内置 task 工具委派所有 4 个角色。model 选择由插件自动完成,不再有 acpx(外部 agent)路径。每个角色的有效指令集 = .omp/agents/*.md(角色专属模板)+ 随包技能 skills/opsx-orchestration-protocol(四角色共享编排协议,经 frontmatter autoloadSkills 注入)——详见下文「Agent 指令集」。


Agent 指令集:模板 + 协议技能

四个 dispatch agent 的有效指令集 = 角色专属模板.omp/agents/*.md)+ 共享协议技能(随包):

| 角色 | 模板承载的角色专属内容 | autoloadSkills 注入的技能 | | --- | --- | --- | | coder | 工作边界(不改提案文件 / 不二次委派 task / 通用编码请求免 scratchpad)、scoped 自验证门槛、ACTION 报告块 | opsx-orchestration-protocol + openspec-apply-change两个) | | planner | 提案拆分规则、Budget 估算、输出说明 | opsx-orchestration-protocol + openspec-propose两个) | | code-reviewer | 审查维度、全局验证三级定级(微改级 / 全流程级,Tier 1/2/3)、审查输出块 | opsx-orchestration-protocol一个) | | proposal-reviewer | 审查维度、提案审查输出块 | opsx-orchestration-protocol一个) |

共享协议技能 skills/opsx-orchestration-protocol/SKILL.md 是四角色共享编排协议的单一真源:scratchpad 四区共享缓存与角色读写矩阵(append-only、planner 建+写 / coder 读+写 / 两个 reviewer 只读)、supersede 权威语义与两档客观判据(档一继续 + supersede 修正,档二 STATUS: blocked 交主 agent 裁决)、无关状态硬栅栏(节内首行角色门——仅 coder 适用,reviewer / planner / proposal-reviewer MUST NOT 受本节限制)、P0/P1 评审闭环与轮次上限(Loop 1 ≤2 轮、Loop 2 最多 3 轮含首次实现与修复)、报告契约、生效与兜底。模板不再复述这些正文,每处只留指向技能的一行指针。

  • 位置与发现:技能在包根 skills/,由宿主对扩展根的技能发现通道自动收录,无需安装动作——installAgents() 的写入集合仍只有 4 个 .omp/agents/*.md.addon-version,不落项目目录、不建 .omp/skills/,技能也不参与 MARKER / 版本 / conflict 状态机。
  • 生效方式:frontmatter autoloadSkills 在子 agent 首个 prompt 之前把技能正文注入其上下文,等价于 /skill:opsx-orchestration-protocol(coder / planner 另各注入一个官方技能)。
  • frontmattername / description / tools / autoloadSkills(+ 可选 model)。原 skill: 字段是宿主 agent frontmatter 白名单不解析的死配置,已移除。
  • 兜底autoloadSkills 解析失败是静默的,故每份模板对每个技能各留一行 skill://<name> 指针(Skill tool 手动读取,逐行同构、不合并);技能名不可解析且 skill://<name> 亦不可读时视为前提缺失,子 agent 输出 STATUS: blocked(无 SESSION)并报缺失技能名交由主 agent 决策,不凭记忆复述其流程。
  • 官方技能的边界openspec-apply-change / openspec-propose 正文面向主会话撰写;对子 agent 只有流程与产物定义适用(选变更、读 tasks/proposal/design/specs、逐 task 实现、- [ ]- [x]、阻塞时不猜测),announce 进度播报、「ask the user / 询问用户」、「pause / 等待用户输入」、progress / pause 报告块不适用(子 agent 无用户);需用户决策时走 STATUS: blocked 上报主 agent。该边界由协议技能单点声明,官方技能文件本身不改动。
  • 升级路径:技能文件与生成模板的代码同处一个 npm 包版本(.npmignore 未排除 skills/),升级插件即同时在场,不存在「模板已瘦身而技能未就位」的中间态;存量 .omp/agents/*.md 仍由既有 installAgents 状态机处理——含 MARKER 的判 updated 并被覆盖,不含 MARKER 的判 conflict 且不覆盖。

Dispatch 配置 (opsx.yml)

两层 opsx.yml(全局 ~/.omp/agent/opsx.yml + 项目 <cwd>/.omp/opsx.yml,项目逐键覆盖全局)。

# agents.* 的值可以是:
#   'auto'                       — 插件按 tier + usage 自动选 model
#   'smol' / 'slow' / 'default'  — OMP role alias(由 OMP modelRoles 解析)
#   'gpt-5-pro'                  — 明确 model id
#   'anthropic/claude-opus-4-6'  — provider/model 完全限定

agents:
  coder: auto
  reviewer: slow
  planner: slow
  proposal-reviewer: default

# 可选:限制自动选择时使用的 model 池
model_allowlist:
  - "anthropic/claude-opus-*"
  - "openai/gpt-5*"

# 可选:自定义 tier 评分
tiers:
  - pattern: "*opus*"
    tier: top
  - pattern: "openai/gpt-4o-mini"
    tier: low

# 可选:dispatch agent → tier 期望
agent_tiers:
  planner: top

# 可选:OMP model role → tier 重定向(或 skip 排除)。
# 写入作用域 = 最小写入集 {smol, default, slow, vision}:合法 tier 值重定向该 role 的
# 写入档位(如 slow: high);skip 使该 role 不写覆盖。写入集之外 role 的条目对写入
# 惰化(保留解析校验);skip 在非写入 role 上等价 no-op。
model_role_tiers:
  slow: high     # 例:slow 改写 high 档选中(默认 top 档补选)
  vision: skip   # 不覆盖 vision(vision 只经能力门控写入,仅 skip 有效)

# 可选:月计划覆盖的 provider(追加到内置默认集;条目规范化、去重)
plan_providers:
  - ArkCodingPlan

# 可选:从生效 plan 集合剔除((默认集 ∪ plan_providers) − plan_providers_remove)
plan_providers_remove:
  - cursor

# 可选:PAYG 兜底末位(缺省 true);false 折叠覆盖类别键,PAYG 回到常规排序
payg_last_resort: true

# 可选:会话启动自动应用一次选择(缺省 true);false 时新会话不自动应用,
# 行为与本键引入前一致(选择待手动 /pick-model 应用)
autoselect_on_start: true

旧键已废弃(仍生效):顶层的 coder: / reviewer: / planner: / proposal-reviewer:role_tiers: 是上面的旧写法,仍照常生效,但读到时会按层文件各 warn 一条(单文件多个旧键合并为 一条、列出全部旧键名),并计划一个版本周期后移除。迁移:顶层 role 键挪进 agents: mapping、 role_tiers: 改名 agent_tiers:(schema 不变)。同一文件内新旧同现时新键胜出agents.* > 顶层旧键、agent_tiers > role_tiers);跨层合并语义不变(agent 值逐键覆盖、tier 表整键覆盖)。

agents / agent_tiersmodel_role_tiers 消歧义

两者都是 opsx.yml 里的映射键、形似「role → tier」,但管理的对象与生效层完全不同:

| | agents / agent_tiers | model_role_tiers | | --- | --- | --- | | 管的对象 | opsx 插件的 4 个 dispatch agent(coder / reviewer / planner / proposal-reviewer,落 .omp/agents/*.md、经 task 工具委派) | OMP 宿主的 model role(10 个内置 default/smol/slow/vision/plan/designer/commit/tiny/task/advisor + 自定义 role) | | 键空间 | 固定 4 个 agent 名(未知子键 warn 丢弃) | 任意 OMP role 名(内置 + 自定义,宽松键空间) | | 值 | agents.*:role 值(auto / OMP alias / model id / provider-model);agent_tiers:tier 名 | tier 名或 skip | | 生效层 | 插件委派 dispatch agent 时的 model 决策(agent → 用哪个 model) | /pick-model 后写入 session 覆盖(overrideModelRoles)的 role → model 映射 |

model_role_tiersagents / agent_tiers 互不兜底、互不影响:前者不参与 dispatch agent 的 model 选择,后者也不影响 session 覆盖写入哪些 role。

覆盖类别与 PAYG 兜底(自动选择排序首位)

自动选择先按覆盖类别硬分区、再比 tier:① 月计划覆盖 → ② 其它可用 → ③ 按量计费(PAYG)兜底。 ③类仅在①②类无可用候选时参与选择(有别的用,就不用 PAYG)。/pick-model <selector> 收窄池内仍按此 排序、仅剩③类时正常选中;pinned role 不经选择器,分区不影响显式钉值。

  • 归类通用、代码零写死plan_providers 成员(规范化后)→ ①类;quota policy 为 balanceREQUIRED_WINDOWS 注册表,如 deepseek)→ ③类;其余 → ②类。未在 REQUIRED_WINDOWS 登记 的按量计费 provider 落②类,登记即入③类——注册表是按量计费的既有登记扩展点。
  • plan_providers:追加语义,条目规范化(ArkCodingPlan / arkcodingplan 同源到 ark-coding-plan)、去重,非法条目 warn 丢弃。
  • plan_providers_remove:从生效集合剔除默认或追加的成员,条目同样规范化。
  • payg_last_resort:缺省 true,③类保持兜底末位;设为 false 折叠整个覆盖类别键—— ③类回到常规排序(可按 tierGap 胜出),同时取消①类 plan 相对②类 standard 的位次偏好 (类别键整体失效,选择回到 tier / 用量 / 价格轴)。

Model 选择

插件启动时从 ModelRegistry.getAvailable() 拿所有有鉴权的 model,从 authStorage.fetchUsageReports() 拉用量报告,然后按 role → tier 期望 + 用量健康度自动选最优 model。

决策日志打印到 stderr:[omp-opsx-addon] planner → anthropic/claude-opus-4-6 (tier=top, gap=0, remaining=0.80)

会话启动自动应用一次选择(autoselect_on_start,缺省 true

配好 china / model_allowlist / tier 期望后,新会话不再等手动命令:session_start 时插件自动应用一次当前 选择——经 ensureSelection 计算(china/allowlist 约束照常生效),按与 /pick-model 相同的应用路径写入 modelRoles(最小写入集 {smol, default, slow, vision} + per-agent 运行时中和),并把主会话模型设为 reviewer pick(high 档选中模型;与当前模型一致则不调用 setModel)。应用在首 turn 前 await 完成、每个会话 实例只应用一次,之后用户显式 /model 切换保持权威——启动路径不会再次触发、不回写主会话模型。pinned role (agents.* 显式钉值)照常优先于自动 pick(钉值旁路选择器,不被自动写入覆盖)。启动应用路径的任何错误 (选择计算抛错、settings 不可用、setModel 失败)只 warn([omp-opsx-addon] session-start autoselect error: ...),不阻塞会话启动。autoselect_on_start: false(任一层 opsx.yml)完全退出,行为与本键引入前一致。 手动 /pick-model 命令照常可用、立即生效;task 子 agent 不触发启动应用。

/pick-model:selector 约束与 role 定向([roleList:]

语法:/pick-model [roleList:]<selector> [--china];子命令 choices / update / refresh / reset 不变。 无前缀 = 全局约束(全部 role 一起收窄,行为与引入 role 定向之前完全一致);/pick-model reset 清除约束(含 role 定向),一切重算路径(refresh / 约束期 tick / ensureSelection)都遵守当前约束。

roleList 词表(逗号分隔、大小写不敏感,与宿主 MODEL_ROLE_IDS 同源、零硬编码):

  • 内置 model role 10 个:default / smol / slow / vision / plan / designer / commit / tiny / task / advisor
  • opsx agent 名作糖:coder→smolreviewer / code-reviewer / planner / proposal-reviewerdefault(解析期映射为 canonical model role);
  • all:等价无前缀的全局约束。

示例:/pick-model smol:glm*(只收窄 smol)、/pick-model smol,default:zhipu*/glm* --china/pick-model coder:glm qwen --china

粒度 = tier 槽位:约束把 scope role 集映射到的每个 tier 槽位(mid/high 槽位、top 补选与 vision 能力候选集)切到约束池,其余槽位照常走全池。映射到同槽位的其它 role 自然随动——默认映射下 tasksmol 同为 mid,/pick-model smol:glm* 换掉 smol 写入后 task 经其枚举回退链 (["tiny","smol"] 等)跟着解析到新 mid 模型;这不是 bug,是 OMP 原生链的必然结果,命令输出会标注 scope(如 scope=smol)使其可见。model_role_tiers 参与 scope→槽位解析(与写入集同一张有效映射表 OMP_ROLE_TO_TIER);有效档位解析为 skip 的 scope role(如配了 model_role_tiers: { task: skip } 再执行 /pick-model task:glm*)直接报用法错误并指名该 role——skip 的 role 不落任何槽位,池约束对它 不可表达。vision 只出现在 scope 时仅约束其图像能力候选集,不收窄 high 槽位。

scoped pinned 交互:定向约束只把 scope 内 role 置 auto(显式覆盖 pinned);scope 外 role 保留 agents: 配置值(pinned 继续生效、omp-alias 语义不变),不经任何重算路径进入约束池,也不触发空选 回滚;reset 后全部恢复 opsx.yml 语义。agents: / agent_tiers:agent-config-rename 改名后的 键名(改名前为顶层 coder: / code-reviewer: / planner: / proposal-reviewer: 四键与 role_tiers:,语义相同,旧键仍被兼容读取)。

冒号是保留字符:裸词匹配按非字母数字分词,含冒号的 token 若回落 selector 会被拆成多个子词按 OR 静默施加全局约束。因此含 : 但不是 roleList 前缀的 token(如 zhipu:glmzhipu:glm*、拼错的 smlo:glm,不论是否带 *、位于命令中何处)一律报用法错误,并把合法词表全文内联在错误信息里—— 不会静默施加任何约束。

choices 展示:紧凑行式输出(见下文「/pick-model 输出格式」),状态行携带约束段,如 当前选择 · constraint: selectors=glm* · scope=smol,default(scope 段为解析后的 canonical model role;全局约束无 scope 段)。

china 配置键(缺省 false:opsx.yml 顶层布尔键,为 trueCHINA_EXCLUDE_FAMILIES (gpt/claude/openai/anthropic 家族,裸词 token 双侧匹配,语义与 --china 一致)成为一切选择 路径的缺省排除——无约束的默认选择(ensureSelection)、refreshreset 之后的重选、selector 约束池全部生效,无需每次敲 --china。优先级为命令显式 > 配置缺省:显式 --china 写入 session 约束(约束期内持续,fingerprint 化),省略旗标时配置缺省层兜底;china: false 或缺省键 = 与引入前 完全一致(仅显式 --china 生效)。关断手段 = 改配置(无 --no-china 旗标);改 opsx.yml 后新会话 生效(配置 session 启动读一次,无热加载)。scoped(role 定向)约束下缺省排除只作用于约束池 (scope 内槽位);scope 外槽位保持不含 china 排除的全池(显式 scope 划分 > 缺省叠加)。 配置为 true 时 choices/报告头部显示 china=on(无 selector 约束时也显示,如 constraint: china=on);reset 只清 session 约束、不清配置缺省。两层合并(project 逐键覆盖 global):project 显式 china: false 压过 global china: true;非法值 warn 后回落 false

同账号区域变体去重(zai ↔ zhipu-coding-plan)

zaizhipu-coding-plan 是智谱同一账号的两个区域入口。两者同时在候选池且两扇门解析出的 API key 严格相等(同账号凭据证明)时,插件按区域偏好收敛到一侧,池与展示都不再重复;key 不同、缺失 或解析失败则保守并存(两扇门都保留、usage 栏两行都显示,靠「智谱 / Z.AI」标签区分)。同账号 (key 相等)才收窄;多 key 同账号场景请保持单一 key(两扇门配同一把 key)以获得收窄,或接受双行 显示。两扇门共享同一份额度,收窄只影响走哪扇门,不损失额度:

  • 常量表:内置单行 [{ domestic: 'zhipu-coding-plan', intl: 'zai' }]lib/provider-variants.tsREGION_VARIANT_GROUPS)。刻意不建通用配置表;未来出现新的区域入口对时扩展该常量即可。
  • 判定与前提:双侧在池且 key 严格相等才收窄(key 相等 = 同账号证明;key 不等/缺失/解析失败 = 保守并存);池中只剩单侧(allowlist/reachability/静态排除/provider_models 已滤掉一侧)= 零 行为。收窄方向由 china 驱动:china: true 保留 zhipu-coding-plan、收起 zaichina: false/缺省保留 zai、收起 zhipu-coding-plan
  • provider 级整体收窄:被收侧整个 provider 退出候选池(不参与评分),其独有模型一并让位—— 同账号一个入口足够。收窄作用于账号级基础池(与 selector 约束正交,scoped 约束的 scope 外槽位同样 去重);池构成或 key 状态变化(可达性/allowlist/静态排除翻转、重新登录换发 key 使收窄集翻转)纳入 selectionHealthKey 指纹,正确失效重算缓存。
  • 旁路:pinned role(agents: 钉值)与显式 selector 不受去重影响——显式指令 > 去重。显式 selector 指定被收侧 provider 时该侧已不在池中,走既有「无命中」错误路径(provider 计数中不含被收 侧);出路 = 改 china 或调整 allowlist。
  • 诊断:去重激活时 choices 附录追加标注行,如 **区域变体** zai → 已收起(同账号区域变体,已按区域偏好收起;保留 zhipu-coding-plan)zai 的 family 标签显示为 Z.AI(显示名常量映射),与 zhipu-coding-plan 恒可区分。
  • usage 栏同判定收窄:usage 栏的 provider 行应用同一收窄判定(含 key 严格相等门;在场的判定 = 有 usage 数据或凭据即可,不要求模型候选)——收窄激活时 china: true 不渲染 zai 行;缺省 /china: false 不渲染 zhipu-coding-plan 行、zai 行显示 Z.AI。key 不等/缺失时不收窄,两行 都渲染、以「智谱 / Z.AI」标签区分。两扇门共享同一份额度,保留侧行即权威展示,信息不丢;单侧在场 照常渲染。后台状态探测不停探被收侧(可达性记录保持新鲜)。
  • 与 model_allowlist 的叠加:allowlist 是 provider 全串 glob 白名单(未列出即排除),china 是 家族黑名单,两者叠加生效。注意区域偏好切换时 allowlist 不会自动映射——想让两个区域入口都 可用就把两区域条目都写上(如 zhipu-coding-plan/* 之外补 zai/glm-5.3);若 allowlist 只列了 单侧条目,另一侧根本不进池、去重不触发(只写 zhipu-coding-plan 条目的现有配置即此形态,行为 不变)。国内用户「不要家族排除但要国内门」(china=false 偏好国内入口)也可用单侧 allowlist 化解。
  • provider_models(逐 provider 模型约束)的关系:两者同为池过滤阶段的合取输入、互不替代; 变体去重收窄整个 provider,provider_models 收窄 provider 内的模型集合,同配时按交集生效(见下节)。

per-provider 模型目标(provider_auto / provider_auto_tiers / provider_models

三个 provider 键控的顶层键(键均经规范化,ArkCodingPlan / arkcodingplanark-coding-plan 同源收敛),共同表达「每个 provider 的模型走什么」:

# 服务端路由哨兵:provider → 该家「Auto」目录模型 id(须与 catalog id 一致,
# 大小写不敏感)。命中的候选豁免本地启发式评分,按声明档位参选。
provider_auto:
  ark-coding-plan: ark-code-latest
  cursor: default

# 哨兵声明档位(tiny|low|mid|high|top);非法值 warn 丢弃,未声明的哨兵按 mid。
provider_auto_tiers:
  ark-coding-plan: top
  cursor: top

# 逐 provider 模型约束:列出的 provider 收窄到命中模型,未列出的 provider 不受限。
# 裸词按 id 全串锚定(`deepseek-flash` 精确命中,不会过匹配 deepseek-v4-flash);
# `*` 通配族(`glm-5.3*` 命中 5.3 族);含 `/` 的模式按 selector 三级语法求值。
provider_models:
  deepseek: [deepseek-flash]
  zhipu-coding-plan: [glm-5.3, glm-5.3-flash]
  • 哨兵语义:catalog 的全 0 成本不构成比价优势——哨兵在同覆盖类、同档内让位于一切有真实 成本的候选,仅在对手耗尽或无竞争时胜出(备份定位);声明档位是哨兵的合法竞争力(如 cursor/default 声明 top 后,对启发式落档更低的 cursor 具体模型形成 tierGap 优势)。哨兵豁免 per-(provider, tier) 去重(无版本号 id 否则必被驱逐),但不豁免覆盖类别分区、配额(含 cursor bucket)、可达性排除与 allowlist。选中哨兵时 pickedReason / decision log 标注 auto 与 declared tier。role pin 到哨兵(如 agents: {coder: ark-coding-plan/ark-code-latest}) 走既有 pinned 路径直接生效。
  • **「provider 只走哨兵」**用两键组合表达:provider_models: {ark-coding-plan: [ark-code-latest], cursor: [default]}——收窄后该 provider 池内只剩哨兵。没有「provider 内哨兵优先于具体模型」的 隐式规则;想要这个效果就显式收窄。
  • provider_models vs model_allowlistprovider_models追加快照式收窄——只约束列出 的 provider,未列出的全量参选;model_allowlist全局白名单——未列出全排除。2026-09-12 撤销全局 model_allowlist 的反例:白名单无法表达「deepseek 只用 flash、zhipu 只用 5.3 族、 其余 provider 不受限」,会误伤 opencode-go 等未列 provider。两者可并存(合取)。
  • 两层合并陷阱:三键与 concurrency_ceiling_by_provider 同为整键覆盖——项目层 .omp/opsx.yml 声明任一键即完整替换全局同名键(不做 per-key 叠加);只想在项目层追加 provider 时,把全局条目一并抄过来。
  • cursor 区域风险:cursor 区域外会返回 Model not available in your region(不可重试,可达性 探测发现不了);excluded_providers 仍是唯一的用户级排除开关,撞墙自行加回 (如 excluded_providers: [cursor])。
  • 哨兵 id 漂移:provider 改名其 Auto 目录条目后声明静默失效(哨兵回落普通启发式评分,无崩溃); 失效时启动/重算日志会 warn 一行指明该 provider 的哨兵 id 不在存活候选中。

速度感知选择(speed_aware

自动选择排序中预留的 speed 槽位由此键驱动。数据源是宿主 ~/.omp/agent/agent.dbmodel_perf 表(只读:readonly 打开、整表一次 SELECT、零写入、零后台任务——仅在选择路径事件驱动读取, 模块级 TTL 缓存 300s;读失败静默回退空索引并以同 TTL 负缓存,不污染选择路径日志)。

# 速度感知选择。enabled 缺省 true(缺数据时零漂移,开启无风险面);
# mode 缺省 tie-break;min_samples 缺省 20(低于门槛的行视为未测度)。
speed_aware:
  enabled: true
  mode: tie-break   # tie-break | aggressive
  min_samples: 20
  • 排序语义(tie-break,缺省):cost band 量化进既有的 cost 槽位(槽位次序不动)—— band(cost) = max(0, floor(log2(cost)) + 1)(cost > 0),边界为 2 的幂(band 1 = [$1,$2)…); 免费与缺价、以及 clamp 收编的 <$1 正价同落 band 0,带内按 cost 原值升序(免费先于一切正价)。 band 对 cost 全域单调,故跨带候选的相对序与纯 cost 序一致(quota-aware 基线零回归)。 同带候选再比实测 tok/s(sum(output_tokens)/sum(gen_ms)×1000)——band 即「同样经费」的 操作化定义(ratio-2 ≈ 同一价格档);speed 相等回落 cost 原值。

  • aggressive(opt-in):speedKey 提到 band 之前——同覆盖类别、同 tier 轴内速度越过价带 (快而贵胜过慢而便宜)。类别分区与 tier 位次仍然不动。风险:系统性偏向高价快模型,故缺省关闭。

  • 未测度候选(无数据 / 样本 < min_samples / provider_auto 哨兵)speedKey 恒为 -Infinity: 带内排在已测度候选之后,其相互之间仍按 band/cost 定序。选择器不做探索——想试新模型走 显式 role pin 或 /pick-model <selector>;20 样本门槛在正常流量下数小时即达成。

  • 零漂移保证enabled: false 时装配层零 IO(不打开 agent.db),速度索引为空时 band 退化 为 cost 原值序、speed 恒等——全序与引入本特性之前逐字节一致。

  • 可观测:选中候选已测度时,其 pickedReason / decision log 追加 speed=<tok/s>tok/s 段 (数据层标注;/pick-model 渲染层不展示)。手工核查数据源:

    sqlite3 ~/.omp/agent/agent.db 'SELECT model_key, samples,
           output_tokens / gen_ms * 1000 AS tok_s,
           CASE WHEN ttft_samples > 0 THEN ttft_ms / ttft_samples END AS ttft_ms
           FROM model_perf ORDER BY tok_s DESC LIMIT 10;'
  • 两层合并speed_aware 为对象键,与 provider_* 键同款整键覆盖——项目层声明即整份 替换全局,不做字段级叠加。

难度路由与质量带(difficulty_routing / stall_escalation / continuity_guard / quality_preference

「分类在前、选择在后」的结构改造(纲领 W4,全键 opt-in):硬约束过滤(既有池过滤,零改动)→ prompt 难度分档 → 带内选择(W1-W3 冻结全序在偏移后目标下照常运行)→ stall 升档与连续性守门 → 质量带旋钮。

# 三开关全部缺省 false(结构改造 opt-in,W1-W3 的收益不依赖它们);
# quality_preference 缺省 balanced(独立于三开关的顶层旋钮)。
difficulty_routing:
  enabled: false
stall_escalation:
  enabled: false
  window: 6        # 滑窗大小(LiteLLM 同款)
  threshold: 3     # 同签名重复阈值(锚定最新一次调用)
continuity_guard:
  enabled: false
  weight: 0.6      # 换模所需最低分类置信,(0,1],越高越保守
quality_preference: balanced   # balanced(缺省,逐字节现状)| cost | quality
  • 难度分档 = 写入集 tier 目标偏移:纯函数 classifyTask(确定性、无 LLM、无状态)按启发式 信号族加权打分(推理标记 / 代码存在 / 技术术语 / 简单指令负向 / 多步模式 / 疑问复杂度 / 长度对数项),边界 0.15 / 0.35 / 0.60 映射 simple / standard / complex / reasoning;偏移表 simple −1 / standard 0 / complex +1 / reasoning +2(clamp [tiny, top]),只作用于写入集 {smol, default, slow, vision}——非写入集 role 的目标恒不触碰(不复活全量覆盖)。分档是 选择输入的预修正:偏移后目标的 gap-0 组即「带内」,组内仍由冻结链既有键(成本/速度)决胜。
  • 失败语义 = 安全侧强档:分类器异常或置信低于地板(0.35)一律落 complex——绝不因分类失败 或歧义静默降到最便宜档(反向规避 LiteLLM「未命中得 0.0 → 默认最便宜」的已证失效模式)。 plan-mode 感知基于 prompt 文本标记(宿主 plan-mode 状态对插件不可见)。
  • stall 升档:会话域滑窗记录工具调用签名(toolName + 键排序稳定序列化(args),长串截断、 序列化失败回退裸签名);锚定最新一次调用的签名在窗内重复 ≥ threshold → stall 生效, default role 目标 +1(clamp top),单 episode 只升一档、绝不自动降档;签名变化结束 episode (其后目标由分类常规接管,非降档动作)。数据源 = tool_execution_start 事件(主源)+ sessionManager.getEntries() 只读转录回溯(降级源);两源皆不可得 → 惰化(无 stall 状态、 不升档、零 warn),维持现状即安全侧。采样只在主实例生效,子 agent binding 不采样。
  • 连续性守门:自动重算点上,写入集 role 的在选模型(incumbent)仍在候选池时钉住不复换guard=pin 标注),速度/价格 tie-break 压不过钉住。换模仅当:①新 band 严格升级且分类置信 ≥ weight;②stall 升档生效;③incumbent 被硬过滤出局(可用性优先)。incumbent band 未知时以 standard 中性档参与比较(simple 不触发升级换模)。显式命令(/pick-model refresh / reset / selector / choices、role-scope)绕过守门且不做新分类——显式指令 > 守门;重算沿用当前会话级 band。
  • quality_preference 三态(顶层独立键,路由关/开均可独立生效):
    • balanced(缺省):既有冻结全序逐字节执行——零漂移的结构保证是「不进入」旋钮分支;
    • cost:tier 轴槽位内部容差带量化(槽位不移动)——同覆盖类内以最小有效 tier 轴值为锚, relGap ≤ 1(容差常量 T=1,不可配置)为带 0;带 0 内去轴化(tierGap/surge/rank 不参与, 成本/速度决胜,Azure「带内选最便宜」的字面落地,代价是带内放弃档位/声誉区分——知情选择); 带 1 内全链自洽,带 0 恒先于带 1(跨带质量序保持);provider_auto 哨兵按声明档参与量化(无特判);
    • quality:质量分前缀分层 (覆盖类, tier 轴, rank, reputation)——成本/速度无法越过一个轴位或 声誉差距(Azure Quality「无视成本」);哨兵 reputation=0 自然让位已知声誉模型(无特判)。
  • T4 边界:路由重算只更新选择缓存(choices / dispatch 上下文 / decision 消费面),不新增 applyRoleModel / setModel 调用点——无任何会话中途模型身份切换;role 模型应用仍只发生在既有 应用点(显式命令、autoselect 会话启动)。stall 采样与守门均为只读观测/选择后处理。
  • 零漂移与关闭保证:三开关全 false + balanced 时,路由段整体跳过、偏移不施加、守门不进入、 比较器走既有分支——选择输出、事件订阅副作用与 W3 落地态逐字节一致(回归用例逐字节断言)。 逐键开启独立生效、互不依赖;关闭任一开关即回到关闭前行为。
  • 可观测(数据层):路由启用且命中时 pickedReason / decision 追加 band=<band>stall+1guard=pin 标注段;未命中/关闭时与既有格式逐字节一致。choices/widget 渲染层零编辑(标注仅 数据层可得,经 dispatch 提示的「原因」行可见)。
  • 两层合并difficulty_routing / stall_escalation / continuity_guard 为对象键,与 speed_aware 同款整键覆盖quality_preference 为标量键同 ?? 惯例。

子 agent 模型落点:session-scoped modelRoles(最小写入)

/pick-model <selector> / refresh / reset 应用选择结果时,插件写 OMP session 运行时 覆盖 settings.overrideModelRoles,但只写最小写入集 {smol, default, slow, vision}。 本节取代已归档 pick-model-batch-all-roles 的「覆盖宿主全部已知 role(10 内置 + 自定义)」 语义——其动机(scout 等内置 agent 跟随切换)经宿主源码实证由 OMP 原生解析链覆盖,全量写入 属过度供给:

  • smol ← mid 档选中(coder pick)、default ← high 档选中(reviewer pick)、 slow ← top 档补选(唯一保留的 supplemental 补选)、vision ← 能力门控 pick(见下)。

  • 写入集之外的 role 一律不写,由 OMP 原生解析链接管:

    | role | 不写时的解析去向 | | --- | --- | | designer | 经 default 继承(继承集合 {smol, slow, designer})→ high 档 pick(与原显式写入等价) | | task | @task 未配置时回落主会话模型(主会话已被设为 high pick) | | commit / tiny | 消费方走枚举回退链 ["commit","smol",…] / ["tiny","commit","smol"] / ["tiny","smol"],终止于 smol 写入(mid 档) | | plan | 未配置时 plan mode 优雅保持当前模型(no-op) | | advisor | 静态 slow priority 链(固定候选表,不读写入、不继承 default) | | 自定义 role | config 层原样保留,插件不再接管(也不再产生兜底告警) |

  • PAYG 红线(收窄口径):存在①类(月计划)候选时,写入集四 role 以及经写入/继承/枚举 终止的原生链(designer/task/commit/tiny)的最终解析不会落入 PAYG——四 role 的 pick 全部经覆盖类别分区排序产出,vision 能力门控写入同时防住 inspect_image 原生「任一图像模型」 兜底打到 PAYG 图像模型。advisor 静态链是明确的 opt-in 豁免(OMP 原生行为)。如需让 advisor 恢复跟随选择,在 OMP config 配 modelRoles.advisor: "@slow" 自钉(复用写入集 slow 链随切换;model_role_tiers 只能重定向所复用写入 role 的档位,无法让 advisor 本身 被写入);plan 同理可经 modelRoles.plan 自钉恢复跟随。

  • model_role_tiers(opsx.yml)作用域:写入集四 role 的档位重定向(如 slow: high) 与 skip 哨兵(该 role 不写覆盖、保留你的 config 值、不产生告警)。写入集之外 role 的 条目对写入惰化(解析校验与非法值告警保留;skip 在非写入 role 上等价 no-op)。 例外:vision role 固定按 high 档在图像模型中挑选model_role_tiers.visionskip 生效——其他 tier 值被静默接受但不改选档。

  • vision 能力门控:vision 候选只从声明 inputimage 的模型中挑选;当前选择里没有 图像模型时,vision 不写覆盖(warn 汇总为 vision(capability),绝不写入纯文本模型), vision 功能回落 config/default。恢复手段:换一个含图像模型的 selector 或用 model_allowlist 纳入图像模型;改 model_role_tiers.vision 的 tier 绕不过门控、也不改选档。

  • auto role 的 agent 定义.omp/agents/*.md frontmatter 注入带引号的 tier alias (coder model: "@smol",其余三者 model: "@default");task 工具经 modelRoles 解析。 frontmatter 另含 autoloadSkills(见「Agent 指令集」)——原 skill: 字段是宿主不解析的 死配置,已移除。

  • 因此所有经 role 解析的 agent 都跟随切换——包括插件未枚举的 OMP 内置/bundled/ project agent:scout(@smol)直读 smol 写入;commit/title/classifier 经枚举链落 smol; designer/@slow 经 slow 写入或 default 继承;task 继承主会话。

  • auto role 与 omp-alias(如 slow,值无 /)的 dispatch 提示词不传 model=, 由 frontmatter alias 声明式接管;pinned 具体 provider/model 仍显式传 model,行为不变。

  • top 补选没有可用模型(候选耗尽/allowlist 全过滤)时,slow 不写覆盖、warn 汇总 (no-pick),命令不中断;无任何模型时计划为空,与既有「模型注册表不可用」分支一致。

  • 覆盖为 session 作用域、不写盘overrideModelRoles 只写 runtime overlay, session 结束即还原;不会修改你的 ~/.omp/agent/config.yml。每次应用前先 clearOverride('modelRoles'),避免上一 selector 的旧 role 值残留;reset 重算无约束 默认并覆盖(不清空,否则回落 config 硬钉)。

手动清理建议:若全局 ~/.omp/agent/config.yml 里有 modelRoles.smol 钉在会耗尽的 套餐模型(scout 会一直打它直到被 session 覆盖压过),或 task.agentModelOverrides 残留 已删除的 tester 等 key,可手动删除这些钉值;插件运行期间会以 session 空串中和 per-agent 钉值,但不改动你的配置文件。


/pick-model 输出格式(pick-model-ux)

四种命令(choices / selector 切换 / refresh / reset)与错误路径共用一套紧凑行式渲染: 状态行(符号 + 动作短语 + 约束段)→ 明细区(变更行,或 role 行 + agent 清单)→ 候选概览 → 脚注。无 markdown 表格、无 emoji、无分割线。符号每次渲染时读宿主 symbolPreset 设置 (unicode/nerd/ascii,缺省或非法回退 unicode),从 OMP SYMBOL_PRESETS 字形表按 SymbolKey 解析,插件零硬编码字形。内部量在展示层翻译为人话:覆盖类别 → 计划内 / 按量直连 / 按量兜底;tier → 轻量/低档/中档/高档/旗舰;role 配置 → 已指定/自动/ role 链tier=/gap=/class= 等原始字段不再出现在输出中(数据层 pickedReason/ decision 原样保留)。

unicode preset 下 choices 实拍(合成数据):

ⓘ 当前选择 · constraint: selectors=glm* · scope=smol

主会话 zhipu-coding-plan/glm-5.3 — 计划内 · 旗舰
coder → zhipu-coding-plan/glm-5.3-flash — 计划内 · 中档 · 自动
code-reviewer → zhipu-coding-plan/glm-5.2 — 计划内 · 高档 · 自动
planner → zhipu-coding-plan/glm-5.2 — 计划内 · 高档 · 自动
proposal-reviewer → zhipu-coding-plan/glm-5.2 — 计划内 · 高档 · 自动

── agent 清单(10)──
项目
  ⏳ code-reviewer — 继承主会话
  ⏳ coder — 跟随切换 · role 链 @smol
  ⏳ designer — 跟随切换 · role 链 @designer(经 default 继承)
  ⏳ task — 继承主会话(@task 未配置回落主会话)
  ○ researcher — 固定 · 钉值 anthropic/claude-opus-4-6
内置
  ○ commit-title — OMP 自动链 @tiny(静态 priority 模式)
  ⏳ scout — 跟随切换 · role 链 @smol

── 候选 ──
deepseek [按量兜底]: 中档→deepseek-v4-flash
zhipu-coding-plan [计划内]: 旗舰→glm-5.3  高档→glm-5.2  中档→glm-5.3-flash

4 个候选参与评分 · 分区: 计划内 3 · 按量直连 0 · 按量兜底 1(兜底未参与)
/pick-model refresh 切换耗尽模型 · /pick-model update 更新 tier 数据

symbolPreset: nerd 时同一结构,状态符号换 Nerd Font 字形(如 status.info → U+F129 等 PUA 码位,普通日志里显示为空白)。切换 / 刷新 / 重置输出同构,状态行分别为 ⓘ 已切换 selector 约束 (selectors=… · scope=…) / ⓘ 已刷新 / ⓘ 已清除 selector 约束,恢复默认选择,变更行形如 主会话 → provider/id(计划内 · 高档)coder → provider/id(计划内 · 中档 · 自动); 跨 provider 歧义提示以脚注保留(提示: glm* 命中 zhipu-coding-plan(12) deepseek(3);用 zhipu-coding-plan*/… 可锁定单一 provider)。

全量 agent 清单:数据源为宿主 discoverAgents(project .omp/agents(含本插件 installAgents 落盘的 4 个 agent)→ user → 扩展/插件 → bundled 全量合并,沿用宿主优先级, 插件不自扫目录),按 项目 / 用户 / 内置 分组、组内按名排序。每行标注模型解析来源: 缺省 / @default / @task(未配置时)→ 继承主会话;@smol / @slow → role 链(跟随 切换);@designer → role 链(经 default 继承);@tiny / @advisor(未配置时)→ OMP 自动链(静态 priority 模式);字面 pattern → 钉值;其他自定义 @role → 自定义 role。 config modelRoles.* 自钉优先于清单标注(「未配置时」的分类才适用)。discoverAgents 失败 时降级为省略该段并 warn,不阻断命令。

开发

npm run typecheck
bun test