Repository navigation
fix: keep system prompt byte-stable for prefix cache - #1
Merged
Merged
Conversation
The nudge (which changes every turn — token count, growth %, dynamic
compress example) was being merged into the system prompt. The system
prompt is the prefix-cache anchor: any byte change at its tail
invalidates the entire cached prefix, so cache hit rate collapsed to
~0% across turns.
Reproduce before fix: consecutive identical requests saw system_len
jump 16871 → 23432 → 16871 ... each turn.
Fix mirrors pai-acp's design: the system block now carries ONLY the
static compress prompt (byte-stable); the nudge is appended as a
separate trailing user message instead. Verified system_len stays
constant across turns (16871 → 16871 → 16871).
- injectSystem(): drop nudge param, only inject static compress prompt
- prepareOpenai(): append nudge as trailing {role:user} message
- prepareAnthropic(): append nudge as trailing {role:user} message
79 tests pass. typecheck clean.
ranxianglei
added a commit
that referenced
this pull request
Aug 8, 2026
Review #2 findings (more comprehensive than #1): #2 (compress-loop*.ts): fetch-timeout timer leak across compress-loop rounds. activeClearTimer = clearTimer overwrote the previous round's timer without clearing it, so rounds 1..N-1 each leaked a 10-min timer that self-fired harmlessly but accumulated handles in the event loop over a long session. Clear the previous timer before overwriting (3 lines, both openai and responses variants). #5 (orphan-gc.ts): orphanStreak was monkey-patched onto the kernel's Block type via (block as unknown as {orphanStreak?:number}).orphanStreak — fragile, no type safety, breaks if the kernel Block shape changes. Replaced with a module-level WeakMap<object, number> keyed by the block object. TS now type-checks the access; counts are GC'd when a block is dropped. #7 (README.md): stale test count (79 → 136) and missing env-var docs (BILI_PERSIST, BILI_PERSIST_DEBOUNCE_MS, MAX_SESSIONS, BILI_SESSIONS_DIR). Both fixed. #8 (tests/*.test.ts): 7 type errors under tsc --noEmit (role: string not narrowing to the union literal; Session literals missing new fields after inFlight/persisted/blockContents were added). Fixed with 'as const' on roles and the missing fields. Full tsc --noEmit now 0 errors. #10 (persist.ts): comment referenced AGENTS.md which doesn't exist; replaced with an inline note on the known concurrency limitation.
This was referenced Aug 8, 2026
LX666-666
pushed a commit
to LX666-666/billion-context
that referenced
this pull request
Aug 9, 2026
…ianglei#2,ranxianglei#3,ranxianglei#4,ranxianglei#6) ranxianglei#1 (CRITICAL) protocol conversion was lossy: image->[image] placeholder, thinking signature dropped (Anthropic rejects unsigned thinking), tool_result .is_error dropped, OpenAI developer->system, image_url/input_image deleted. Fix: BiliMessage sidecar (src/bili-message.ts) extends CoreMessage with optional raw*/signature/isError/originalRole/image* fields. The kernel only does {...msg} spread copies, so sidecar survives the pipeline to coreToX, which replays the original block losslessly. 8 round-trip tests added. #2b (MAJOR) session-id extractKey() lowercased the API key before hashing — two distinct valid keys differing only in case collided into one hash bucket. Remove toLowerCase; keep raw (trim only). ranxianglei#3 (MAJOR) auto-update stale-lock takeover never deleted the stale lock file, so writeFile({flag:'wx'}) always failed EEXIST -> catch returned null -> a single crash during update permanently blocked all future auto-updates. Add unlink(LOCK_FILE) before the wx write, with ENOENT tolerated. ranxianglei#4 (MAJOR, security) /__bili/ management endpoints (config read/write, reload, session stats) had no auth. With --host 0.0.0.0 a remote caller could rewrite upstream routing to exfiltrate API keys. Gate all /__bili/ + /__acp/ paths to loopback connections only (127.x / ::1); model-traffic endpoints stay open. ranxianglei#6 (MINOR) build artifact was not self-contained: acp-kernel stayed as a runtime dependency (dist had 'from "acp-kernel"'). tsup now sets noExternal:[acp-kernel,node-forge] and acp-kernel moves to devDependencies, keeping the exact pin (0.0.17). dist verified: 0 'from acp-kernel' refs.
ranxianglei
added a commit
to LX666-666/billion-context
that referenced
this pull request
Aug 10, 2026
…eload Review feedback from ranxianglei (PR#73 comments ranxianglei#3-ranxianglei#4): 1. [ranxianglei#9 critical] Restore Responses session-identity fallback chain (responses.ts): header → body.session_id → metadata.session_id → previous_response_id → content-fingerprint(hashId). The previous generated-randomUUID() broke compression for headerless clients (Pi, plain OpenAI SDK) — every request got a new session so compression state never accumulated. 2. [ranxianglei#1+ranxianglei#2 critical] parseState robustness (codex-takeover.ts): corrupted state file now returns undefined (treat as stale/recoverable) instead of throwing, which would leave Codex CLI unusable. Added sectionPrefixLength type validation (non-negative number) to prevent NaN slicing that could wipe the entire config.toml. 3. [Comment#4 ranxianglei#2] PUT /__bili/config onChanged now also refreshes routes (server.ts): previously only proxy fields were refreshed, so pure API callers (non-Web-UI) had to also POST /reload for provider config to take effect. Now PUT guarantees save-then-apply in one call. 4. Fix misleading context-window hint on routing page (page.ts).
This was referenced Aug 26, 2026
Merged
Closed
Merged
Closed
This was referenced Sep 2, 2026
Closed
This was referenced Sep 9, 2026
Merged
This was referenced Oct 14, 2026
ranxianglei
pushed a commit
that referenced
this pull request
Oct 14, 2026
…mum (#3071) #3071: on a model with NO declared output ceiling, the proxy's starved-budget restore used the client's own last non-starved high-water as its only lower bound. That estimate decays unbounded from the client's raw-history size (..., 3071, 2061, 252, <=200), so once starved the session pins at a death rattle and every turn truncates at max-tokens (finish=length, 0 visible chars); a fresh fork child inherits the rattle and forwards max_tokens=1 verbatim. On v0.1.195 this blanked 9 turns across 3 DSH sessions in one day. Fix (minimal — matches the issue's suggestion #1 literally): when no source knows a ceiling, the STARVED / born-starved / fork-inherited restore target is floored at OUTPUT_RESTORE_ABSOLUTE_FLOOR (8192). A non-starved value is still trusted verbatim (client's explicit choice; far smaller blast radius), and a known-ceiling model is untouched. The no-ceiling WARN dedup moves from once-per-model (global) to once-per-session+model so each affected session logs its own WARN instead of staying silent behind another session's first hit. Paths fixed: 1 (no-ceiling restore pinned at poisoned high-water), 2a (killed session got zero warns), 2b (fork child forwarded the starved budget verbatim). Path 3 (headroom reserving the shrunken budget) needs no change: the restore runs before the headroom reservation reads max_tokens, so the floored value flows in automatically. Deferred to owner sign-off (product decisions / pinned fail-closed behavior, flagged in-thread): #4 invalidating the #2490 dsh planning floor after a refused replay (contradicts its sticky-by-design overflow guarantee), and #5 retrying a starved finish=length turn (reverses #2756's deliberate exclusion; the root-cause floor fix should remove most of those empty turns first). Closes #3071
This was referenced Oct 15, 2026
Closed
This was referenced Oct 16, 2026
Closed
Open
cskwork
pushed a commit
to cskwork/billion-context
that referenced
this pull request
Oct 21, 2026
…anxianglei#2) Review ranxianglei#2 findings (more comprehensive than ranxianglei#1): ranxianglei#2 (compress-loop*.ts): fetch-timeout timer leak across compress-loop rounds. activeClearTimer = clearTimer overwrote the previous round's timer without clearing it, so rounds 1..N-1 each leaked a 10-min timer that self-fired harmlessly but accumulated handles in the event loop over a long session. Clear the previous timer before overwriting (3 lines, both openai and responses variants). ranxianglei#5 (orphan-gc.ts): orphanStreak was monkey-patched onto the kernel's Block type via (block as unknown as {orphanStreak?:number}).orphanStreak — fragile, no type safety, breaks if the kernel Block shape changes. Replaced with a module-level WeakMap<object, number> keyed by the block object. TS now type-checks the access; counts are GC'd when a block is dropped. ranxianglei#7 (README.md): stale test count (79 → 136) and missing env-var docs (BILI_PERSIST, BILI_PERSIST_DEBOUNCE_MS, MAX_SESSIONS, BILI_SESSIONS_DIR). Both fixed. ranxianglei#8 (tests/*.test.ts): 7 type errors under tsc --noEmit (role: string not narrowing to the union literal; Session literals missing new fields after inFlight/persisted/blockContents were added). Fixed with 'as const' on roles and the missing fields. Full tsc --noEmit now 0 errors. ranxianglei#10 (persist.ts): comment referenced AGENTS.md which doesn't exist; replaced with an inline note on the known concurrency limitation.
This was referenced Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Cache hit rate collapsed to ~0% across turns. Root cause: the nudge (which changes every turn — token count, growth %, dynamic compress example) was merged into the system prompt. The system prompt is the prefix-cache anchor; any byte change at its tail invalidates the entire cached prefix.
Reproduce
Before fix, consecutive requests saw
system_lenjump every turn:Fix
Mirror pai-acp's design: the system block carries ONLY the static compress prompt (byte-stable); the nudge is appended as a separate trailing user message.
Changes
injectSystem(): drop nudge param, only inject static compress promptprepareOpenai(): append nudge as trailing{role:user}messageprepareAnthropic(): append nudge as trailing{role:user}messageVerification