feat: runtime-info protocol — plugins report real model config to the proxy (#955) - #956
Conversation
… proxy (#955) - New per-request headers x-bili-plugin-max-output / x-bili-plugin-model (gated on x-bili-plugin, like the existing window header) - New POST /__bili/plugin/runtime-info endpoint: bootstrap + model-switch report of {agent, model, contextWindow, maxOutput, baseURL, source}, per-agent LRU table, consulted in the native-window chain directly under the per-request header report (agent+model must match) - Reported maxOutput stands in for output-headroom reservation when the request body carries no budget of its own (#924 fallback order) - dsh-native: reads ctx.llm.resolveModelInfo + ctx.agentDefaultModel (dynamic ctx.inject) and stamps model/window/max-output headers + report - opencode v1 (extractV1Outputs), opencode v2 (catalog limit.output), pi: add model/max-output stamps + change-detected runtime report - /__bili/plugin/status now exposes model, windowSource, runtimeInfo - Tests: header parsing gates, endpoint validation/LRU/model guard, change-detection with failure rollback, dsh stamp, 3 e2e chain cases - README (en/zh): runtime-info protocol table for future client ports
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)npm install -g billion-context@pr-956Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf billion-context-pr956.tgz
npm install -g packageInstall instructions are refreshed on each push. |
[bot] 🏷 Review started on PR #956 (branch Initial state:
I'm now walking the diff file by file against the protocol table in the PR description. Will report findings (or a mergeable verdict once CI is green) shortly. |
[bot] 🏷 PR #956 review — complete ✅ Verification (ran locally against branch head
Code review
One minor finding (non-blocking): Verdict: code matches the description, all claims independently verified, CI fully green. Per §7.4 this is a 中文摘要:审查了 runtime-info 协议(插件上报真实模型配置、窗口解析链新增 runtime-info 档、maxOutput 输出预留兜底)——本地独立复验 typecheck / 1893 项测试 / 构建 / 真 codex E2E 全部通过,CI 8 项检查全绿,diff 干净且未动版本号;仅发现一个 dsh-native 异步解析的瞬时竞态(非阻塞,可选后续加固),可以合并。 |
Acceptance criterion #1 ("dsh session: /acp before first request shows model + window from client config") was not met: the runtime-info table was only consulted once a session existed, so the latest-session probe a client without a stable id sends (conversationId=<agent>&fallback=latest) 404'd until the first model request landed. - handlePluginStatus now answers that probe from the agent-keyed runtime table (phase: "pre-first-request") when no session resolves; original 404 messages preserved otherwise - dsh statusOutcome renders the reported model/window/maxOutput/source instead of the generic "no model request yet" notice - tests: e2e pre-first-request status (report->200, empty->404, real session takes over after traffic), dsh /acp render of the probe response; harness now isolates XDG_STATE_HOME + resets the in-memory session map so "no session yet" preconditions are deterministic - README en/zh: one line documenting the pre-first-request behavior
…eck on plugin headers Review findings on PR #956: - dsh-native refreshModelInfo: an in-flight resolve whose model selection changed mid-flight must not overwrite the cache or report the OLD model (one-turn transient mis-sizing); commit + report are now gated on the live selection still matching what was resolved. - server: per-request x-bili-plugin-context-window / -max-output headers are now ignored when x-bili-plugin-model differs from the request body's model (exact or last path segment — openai bodies use provider/model composites). A missing model header keeps the pre-#956 trust.
|
Pushed
New tests: cross-check semantics (4 cases) + existing suites re-run. Local: typecheck clean, 1896 pass / 0 fail, build ok. |
… review) The selectionStillCurrent gate in refreshModelInfo had no dedicated test: drive apply() with a gated async resolve of model A, switch the live selection to B mid-resolve, assert A's numbers never land in the cache or headers, then assert the next refresh self-heals by re-resolving B.
[bot] 🏷 Round-2 review complete ✅ — reviewed both new commits ( Both fixes verified correct
One gap I fixed directly (per repo review rules): the race guard had no regression test. Pushed Verification on final head
Verdict: findings addressed completely, no new issues found, green across the board. Per §7.4 this remains a 中文摘要:二轮审查确认两处加固(dsh 中途切模型的竞态守卫、plugin 头与请求体 model 的交叉校验)实现正确且覆盖全部路径,另审了新增的 /acp 首请求前应答逻辑无问题;竞态守卫原本缺回归测试,我已直接在 PR 分支补上(3f3e5e9,纯测试提交),本地 typecheck/1899 项测试/构建/真 codex E2E 全部通过、CI 8 项全绿,可以合并。 |
Fixes #955
What
Native plugins live INSIDE the client process, so they can read the client's real model configuration. This PR defines and implements the runtime-info protocol so the proxy stops guessing (models.dev snapshot / built-in table / first-request learning) and gets the truth pushed upstream:
x-bili-plugin):x-bili-plugin-context-window(existed) + newx-bili-plugin-max-output,x-bili-plugin-modelPOST /__bili/plugin/runtime-info(loopback):{agent, model, contextWindow, maxOutput, baseURL, source}— sent at plugin bootstrap and on model switch, per-agent LRU tableanthropic-beta> header report > runtime-info table (agent+model must match — a stale post-switch entry can never size a different model) > launcher env > route config > registry > tablePlugin implementations
ctx.agentDefaultModel.currentSelection()+ctx.llm.resolveModelInfo(provider, model)via dynamicctx.inject(missing services degrade gracefully), caches, stamps all three headers, reports at bootstrap/switchextractV1Outputs(limit.output), stamps model + max-output alongside the existing windowlimit.outputmap, same stampsctx.model.id+ optionalmaxTokens, same stamps + report withbaseURLObservability
/__bili/plugin/statusnow returnsmodel,windowSource,runtimeInfo; the[window]log line has aruntime-infosource.Docs
README (en/zh) gained a protocol table — this is the contract other client integrations (see sibling issues) build against.
Pre-flight
npm run typecheck✅npm test1893 pass / 0 fail ✅npm run build✅