fix: yield to billion-context native mode via action-time env re-check (#405) - #406
ranxianglei wants to merge 2 commits into
Conversation
#405) Native mode (billion-context #820/#824) writes BILLION_CONTEXT_NATIVE at the plugin's module evaluation — possibly after ACP setup sampled env — and never touches provider baseURLs, so no pre-existing self-disable signal could see it. - lib/bili-proxy.ts: pure detectBiliEnvYield()/describeBiliEnvYield() covering both owner markers (launcher precedence), injectable env for tests - index.ts: setup fast path covers both markers; guard() and config hook re-sample env at action time with one-time log per source; deny-tools block extracted to a shared helper - lib/compress/types.ts: resolveToolContext() throws when a marker is set at action time — single chokepoint gating all five ACP tools - tests/bili-native-yield.test.ts: 10 tests (unit + integration through the real factory); mutation-checked: 7/10 fail on master, 10/10 pass with fix
📦 Built Plugin ArtifactBranch: Option A — Install from npm PR tag (recommended)opencode plugin opencode-acp@pr-406 --globalEach push to this PR publishes a new version under the Option B — Install from GitHubopencode plugin "github:ranxianglei/opencode-acp#2026-09-16_billion-context-native-yield" --globalOption C — Download artifact
tar xzf opencode-acp-pr406.tgz
cp -r package/dist ~/.cache/opencode/packages/opencode-acp@latest/node_modules/opencode-acp/dist
This comment is automatically updated on each push. |
Verified PR #406 (fixes #405). This is already-completed agent work ( Code review
Local verification (independent re-run at head
CI status
Remaining gates before merge
中文摘要:已核对 #406 代码与设计(action-time env 重采样 + |
Follow-up — CI is now fully green ✅
On the "behind master" state: the branch is 15 commits behind, but I verified zero file overlap between those master commits (paper docs, quality-gate rejection, Status: ready for the second independent agent review + human merge. Per AGENTS.md §5.3/§5.6 the source + test changes still need a second independent reviewer (this was my first round), and per §5.1.1.2 the merge itself is human-only — I won't merge it. 中文摘要:e2e 已转绿,全部 6 项 CI 检查通过;分支虽落后 master 15 个提交但与其改动零文件重叠、可干净合并(可选 rebase)。代码与测试我已复核无误,待第二个独立 agent review + 人工合并即可。 |
- prettier: collapse index.ts import line, wrap detectBiliEnvYield signature (F1) - config hook: compute disabledByBiliProxy before either branch so the flag is never stale when an env marker and a /bili/ provider change together (F2) - restore master's exact launcher log wording via new biliYieldLogMessage() (F4) - tests: tool-gate now covers all 5 tools; hooks-no-op covers command.execute.before; re-enable test wrapped in try/finally; sibling bili-proxy-integration test also clears BILLION_CONTEXT_NATIVE
Problem (#405)
billion-context's OpenCode 2.x native mode (PR ranxianglei/billion-context#824) owns compression from a package-installed plugin that rewrites model-API requests at
http.requesttime. ACP's self-disable signals are all sampled statically:index.tssetup check readsBILLION_CONTEXT_PROXYonce — native mode writes it only after async proxy bootstrap → missed;lib/bili-proxy.tsrely on/bili/in provider baseURL — native mode never touches configured baseURLs → invisible.Result: with both plugins installed, native mode double-compresses. The native entry ships a synchronous marker for exactly this handoff (
markNativeHost()setsprocess.env.BILLION_CONTEXT_NATIVE = "opencode"at module evaluation, before any await, first-writer-wins) — but it can land after ACP setup sampled env.Fix
Re-sample the owner markers at action time, reusing the existing yield path:
lib/bili-proxy.ts: new puredetectBiliEnvYield(env?)("launcher" | "native" | null, launcher precedence — native bootstrap refuses to run whileBILLION_CONTEXT_PROXYis set) +describeBiliEnvYield(), injectable env for tests;index.ts: setup fast path covers both markers;guard()and the config hook re-sample env on every invocation/config run (one-time log per source per factory instance); deny-tools block extracted to a shared helper used by both the new env branch and the existing/bili/branch (whose log message is preserved verbatim);lib/compress/types.ts:resolveToolContext()— first statement of every ACP tool's execute — throws a clear "disabled" error when a marker is set at action time. One chokepoint gates all five tools without touching the five tool files; covers the residual window where a tool call lands after the last config run.Non-latching (unsetting the marker restores ACP), no state-format/API changes, hot path stays O(1) with no I/O.
Tests
New
tests/bili-native-yield.test.ts(10 tests through the real factory): unit detector + precedence, setup fast path ×2 markers, runtime marker → config denies all 5 tools / all hooks no-op / tool execute throws, launcher-marker parity, re-enable after unsetting, exactly-one yield log across repeated invocations.Mutation-checked: with
index.ts+lib/compress/types.tsreverted to master, 7/10 fail; with the fix, 10/10 pass. Full suite: 1273 pass / 0 fail; typecheck + build clean.Trade-off (fail-closed)
If the native marker is set but billion-context's own async bootstrap later fails, ACP stays yielded for that process lifetime — recovery is removing the native plugin and restarting. Deliberate: failing open risks double compression (the bug this PR fixes); a failed bootstrap at least leaves compression visibly unowned. The marker is only written when the native gate passes at module evaluation, so this window is narrow.
Review
Dual-agent review (independent source + test reviewers). Findings addressed in commit 32d94ac: prettier violations in two tracked files; stale-flag edge (env branch returned before assigning
disabledByBiliProxy— flag now computed before either branch); launcher log wording restored byte-identical to master via newbiliYieldLogMessage(); tool-gate test extended from 2 to all five tools; hooks-no-op test extended to covercommand.execute.before; re-enable test wrapped in try/finally; siblingbili-proxy-integration.test.tsnow also clearsBILLION_CONTEXT_NATIVE. Accepted info-level item: the one-time-log dedup var never resets within a process lifetime (cosmetic — detection itself re-samples env on every call). Re-verified after fixes: typecheck clean, 1273/1273 tests pass, build OK.Devlog:
devlog/2026-09-16_billion-context-native-yield/(REQ + DESIGN + WORKLOG).Fixes #405