| name | tokenkey-modelops-planner |
| description | TokenKey model operations hub — single ops entry for catalog/menu refresh, newapi mapping drift, mirror diff, account model_mapping runtime hotfix, and onboard prep. Routes read-only plan, catalog write, runtime setting sync, or onboard write. |
TokenKey:modelops 运营 hub(唯一入口)
所有 model ops 从这里进——公开 /pricing、用户 Menu、newapi 长尾 mapping、mirror、上架前
对账。不要直接加载写入子 skill,除非本 skill 路由表已判定意图。
tokenkey-modelops-planner(本 skill)
│
┌────────────────────┼────────────────────┬────────────────────┐
▼ ▼ ▼ ▼
分支 A 对账 分支 B catalog/menu 分支 C 上架 分支 D runtime
modelops.py plan refresh-servable-* tokenkey-onboard-model manage-account-model-mapping-runtime.py
(只读) (写 Go allowlist) (写 manifest/migration/价) (写 prod/edge settings)
| 运营说法 / 症状 | 走哪条分支 |
|---|
| 目录/Menu 过时、模型可能不再 200、要刷新 allowlist | 分支 B(本 skill 路由后读写入子 skill) |
Antigravity gemini-2.5-pro generateContent 超时 / inconclusive,要窄探 chat vs v1beta | 分支 B → tokenkey-servable-model-refresh §「Antigravity gemini-2.5-pro 专项」 |
新模型已定价/可服务/可展示但 prod Unsupported model、空池或疑似被 model_mapping floor 拦 | 先按下方「新模型 prod model_mapping 判读」区分当前 prod floor 与上游账号能力;只有目标账号实测 servable 且 mapping 路径复核后才进入 分支 B/D |
| Qwen/DeepSeek mapping 漂、429 空池、60↔72 mirror | 分支 A |
已有 servable+priced+displayable SSOT,需要快速热更新账号 model_mapping | 分支 D(runtime desired layer + 显式 check/diff/apply) |
| 已有 release bundle,要把新模型面正式激活到 prod | modelops.py activate(current/target bundle + 独立 probe/pricing evidence) |
| 客户要上新模型、ready_for_onboard | 分支 C(可先 A 再 C) |
| 单账号单模型能不能通 | tokenkey-account-model-probe(诊断,非 hub 子分支) |
硬边界:分支 A 只读;分支 B/C/D 会改仓库或 prod/edge,合并/apply/sync-runtime/clear-runtime 等人授权。
设计基线:docs/approved/served-model-reconcile-planner.md · 脚本表:ops/pricing/README.md
测试原则:model ops 改动若触达 catalog/menu/model_mapping/pricing,测试必须从下方「四事实」owner
派生正向/负向集合(例如 ServableClientFacingIDs、supportedCatalogModelIDsForPlatform、
manifest/overlay parser 或 runtime desired layer helper)。禁止在测试、skill 或 PR 模板里手写一套
会随模型上架同步变动的模型清单;手写样本只保留未知 ID、跨平台 ID、兼容别名、priced-but-hidden
等真实边界,并说明它不是 owner 副本。
0) 路由(先做,再跑命令)
- 问清是 catalog/menu、newapi mapping/镜像、账号 model_mapping runtime 热更新、还是 上新模型。
- catalog/menu → §分支 B,加载
tokenkey-servable-model-refresh 执行写入。
- mapping/mirror/空池 → §分支 A(
modelops.py plan)。
- runtime 热更新 → §分支 D,先
validate/check --file,确认后 sync-runtime(只写 setting);账号持久化写入必须再跑 check-accounts 看 diff,确认后 apply-accounts --confirm ...。
- plan 出
ready_for_onboard → §分支 C,加载 tokenkey-onboard-model。
同一工单可 A→C 或「B 与 A 并行认知、分开 PR」;禁止在分支 A 里跑 refresh run/apply。
新模型 prod model_mapping 判读(全平台 floor vs 上游能力)
可展示 SSOT(官方别名):对已支持的平台与 newapi channel,若上游官方 model page
(或 tk_served_models.json 策展行)声明了 model id/alias,且 TokenKey 已核实 有价 +
可服务,则必须进入公开 catalog/menu(不只列 stable bare id)。仅退休重定向、无官方 SKU
的兼容键保持 priced-only。详见 docs/global/agent-reference.md § Model serving SSOT。
新模型不能只看「已定价」「可展示」或 prod 普通探测的 400/429。prod 账号会按 SSOT
model_mapping 收窄可服务模型;未列入当前 mapping/floor 的型号可能在调度或账号选择前被
TokenKey 拦住,表现为 Unsupported model: <id>、account_id=null、无 upstream event,或
空池/无可用账号。这只能说明当前 prod serving 面未放行,不等于上游账号不可服务。
反过来,清开或热更 prod model_mapping 后也不保证模型可服务:仍必须看到目标账号/目标路径真正
返回 verdict=servable。gpt-5.6 在 2026-07-08 的实测中,prod 普通探测先被本地 floor 拦截;
edge OpenAI OAuth account 7/5 随后都到达上游,但返回
The 'gpt-5.6-sol' model is not supported when using Codex with a ChatGPT account.。
安全顺序:
bash ops/observability/run-probe.sh --target prod \
--script ops/pricing/probe-servable-models.sh \
--with ops/pricing/probe_reserved_resources.sh \
--env "<PLATFORM_FAMILY_MODELS>=<model>" --timeout-seconds 180
bash ops/observability/run-probe.sh --target <prod|edge:edge_id> \
--script ops/stage0/probe_account_model.sh \
--with ops/pricing/probe_reserved_resources.sh \
--env ACCOUNT_ID=<account_id> \
--env MODEL=<model> --env ENDPOINT=<messages|chat|responses> --timeout-seconds 180
bash ops/observability/run-probe.sh --target <prod|edge:edge_id> \
--script ops/stage0/probe_direct_upstream_model.sh \
--with ops/stage0/probe_openai_upstream_model.sh \
--with ops/stage0/probe_grok_upstream_model.sh \
--env PLATFORM=<openai|grok> \
--env ACCOUNT_ID=<account_id> \
--env MODEL=<model> --timeout-seconds 180
只有平台专用探测返回 verdict=servable,且 gateway 单账号探测能以
usage_match.account_id == ACCOUNT_ID 证明 TokenKey 路径命中目标账号,才允许把该型号当作
servable 候选进入 分支 B(公开 catalog/Menu)或 分支 D(runtime model_mapping)。若
verdict=gateway_rejected 且 body 是 Unsupported model: <id>、空池或无 upstream event,先当作
当前 prod mapping/floor 未放行,不能当作上游能力结论;按平台用 direct upstream probe、edge
原生账号直连 provider 探测(如 ark 直连)或经人审的 分支 D runtime mapping 更新后重探。
若 direct upstream / 平台专用探测已到达上游但返回平台级 upstream_rejected,保持不展示、
不热更 model_mapping,直到目标账号返回 servable。
分支 A:newapi / mapping / mirror 对账(只读)
脚本:ops/pricing/modelops.py(reconcile-served-models.py 为兼容 wrapper)。
python3 ops/pricing/modelops.py --selftest
python3 ops/pricing/modelops.py snapshot-sql --accounts 60,72
bash ops/observability/run-probe.sh --target prod \
--script ops/pricing/probe-servable-models.sh \
--with ops/pricing/probe_reserved_resources.sh \
--env "DASHSCOPE_CHAT_MODELS=qwen3-8b" --timeout-seconds 300 \
| tee /tmp/qwen_probe.tsv
python3 ops/pricing/modelops.py plan \
--upstream 60:/tmp/qwen_upstream.json \
--probe-results /tmp/qwen_probe.tsv \
--live-mapping /tmp/model_mapping_snapshot.json \
--mirror 60:72
| plan 块 | 下一步 |
|---|
probe_needed | 复制 probe_commands |
price_missing | apply-pricing-hotfix.py lookup 或 分支 C |
mapping_* / mirror_* | guarded dry-run → 人审 → apply-live |
ready_for_onboard | §分支 C |
surfaces.catalog_menu | 若目录也 stale → §分支 B(与 mapping 不同 PR 面) |
策展账号 id:60 Qwen、72 Qwen-2(mirror 源→目标)、39 ds-官、67 GLM、7 volcengine。
分支 B:公开 catalog / Menu 实测刷新(写入)
执行体 = tokenkey-servable-model-refresh(Gemini 三族、Volcengine ark、inconclusive
取舍、catch-all 安全闸等细节只在该 skill,此处不重复)。
Hub 级最小路径(需 AWS / prod SSM):
python3 ops/pricing/refresh-servable-allowlist.py candidates
python3 ops/pricing/refresh-servable-allowlist.py run
cd backend && go test -tags=unit ./internal/service/ -run PublicCatalog
路由后:立即读 .cursor/skills/tokenkey-servable-model-refresh/SKILL.md 走完写入与真判断。
缺价告警处置仍用 apply-pricing-hotfix.py(refresh skill §姊妹 runbook)。
分支 C:newapi 长尾上架(写入)
执行体 = tokenkey-onboard-model。manifest → 迁移/overlay → livefire → PR。
不确定缺口时先 分支 A 再加载 onboard skill。
分支 D:账号 model_mapping runtime 热更新(desired layer + 显式 apply)
脚本:ops/pricing/manage-account-model-mapping-runtime.py。
用途:把已确认 可服务、已定价、可展示 的账号 model_mapping SSOT 作为 runtime
replacement 写入 settings.tk_account_model_mapping_runtime,再用只读 release-gate /
check-accounts 对 prod 生成 diff(默认 prod only;edge 空 mapping 不纳入日常检查,需
--include-edges 才查 edge)。release-gate 只用于显式 modelops / 模型激活预检:它检查
live prod 是否覆盖所选 release bundle 的 required floor,并允许预热/回滚额外 mapping,但拒绝
缺 key、错 target 或该 bundle 明确 forbidden 的 key/prefix。rollout 不编译 Go,也不发现 sibling
source checkout。generic binary deploy 与
rollback 不调用也不等待它。账号和 Antigravity group 的持久化写入只通过
apply-accounts --confirm yes-apply-account-model-mapping 执行;服务进程启动、周期 tick
和 settings_updated fan-out 都不会批量覆盖账号配置。该文件是 scope replacement,
不是增量 patch:写了某个平台或 newapi channel_type,就必须给出该 scope 的完整期望
mapping;未出现的 scope 继续用编译期 floor。
python3 ops/pricing/manage-account-model-mapping-runtime.py --selftest
python3 ops/pricing/manage-account-model-mapping-runtime.py example > /tmp/account-model-mapping-runtime.json
python3 ops/pricing/manage-account-model-mapping-runtime.py validate \
--file /tmp/account-model-mapping-runtime.json \
--bundle /tmp/model-surface-bundle.json
python3 ops/pricing/manage-account-model-mapping-runtime.py check --file /tmp/account-model-mapping-runtime.json
python3 ops/pricing/manage-account-model-mapping-runtime.py sync-runtime --file /tmp/account-model-mapping-runtime.json
python3 ops/pricing/manage-account-model-mapping-runtime.py release-gate
python3 ops/pricing/manage-account-model-mapping-runtime.py check-accounts --json
python3 ops/pricing/manage-account-model-mapping-runtime.py apply-accounts \
--target prod \
--bundle /tmp/model-surface-bundle.json \
--confirm yes-apply-account-model-mapping
python3 ops/pricing/manage-account-model-mapping-runtime.py clear-runtime
新增模型的安全顺序:先确认 live probe / pricing / display gate,再更新 runtime JSON,
sync-runtime 后跑 check-accounts 生成 diff,最后经人审 apply-accounts 预热 prod
账号物化层;本次意图确为激活该 model surface 时,用唯一入口做默认 dry-run:
python3 ops/pricing/modelops.py activate \
--bundle /tmp/model-surface-bundle.json \
--current-bundle /tmp/current-model-surface-bundle.json \
--probe-evidence /tmp/model-activation-probe.json \
--pricing-evidence /tmp/model-activation-pricing.json
它只为 current→target 新增/retarget 的 required mappings 接受独立 evidence;两份 evidence
必须绑定 current/target floor digest、24 小时内生成,probe 每行还必须有真实 account_id。
probe/pricing 的 source 必须不同;prod 存在
tk_account_model_mapping_runtime 也会在写前 fail closed,避免 runtime scope shadow evidence
覆盖的 immutable bundle(先 fold-in 或 clear-runtime)。首次 gate 解析出的 prod instance 会固定给
dry-run、apply 与 post-gate;apply 在账号写事务内锁定 settings 并再次确认 runtime replacement 不存在。
默认只生成 prod plan + 只读 gate;人审后加
--confirm yes-activate-model-surface 才 apply,并要求 post-apply gate 通过。证据 JSON 契约见
docs/approved/model-surface-activation-contract.md。旧镜像不会因为预热 mapping 自动公开新模型;通用 hotfix deploy 与
rollback 始终独立于这条模型激活链。如果这是长期产品面,随后把同样的 mapping 折回 Go
floor 或 tk_served_models.json,避免 runtime 长期 shadow 编译期事实。
四事实(hub 只对齐,不拥有)
| 事实 | Owner | 典型分支 |
|---|
| Public catalog + Menu | pricing_catalog_supported_models_tk.go | B |
| Runtime serving | accounts.credentials.model_mapping + tk_account_model_mapping_runtime | A / C / D |
| Price | overlay + channel pricing | A / C / hotfix |
| Curated newapi intent | tk_served_models.json | A / C |