Repository navigation
Use kernel renderTags:"text-only" + forbid tag echoing in prompt - #3
Merged
Merged
Conversation
Two related changes that keep tags out of model output and client history: 1. server.ts: pass renderTags:"text-only" to processTurn (both Anthropic and OpenAI paths). The acp-kernel render-refs node now skips tool messages (tool-call args / tool-result content) so structured JSON is never polluted by an <acp> tag. This replaces the stripToolTags hack (proxy-side post-processing) — the responsibility moves into the kernel where ref assignment and tag rendering are properly separated. - delete ACP_TAG_RE constant and stripToolTags function - delete the two stripToolTags(turn.messages) call sites 2. compress-tool.ts: ACP TAGS prompt section now states tags are system metadata injected by the proxy and must NEVER be echoed in responses; use only the ref ID inside compress calls. The old wording encouraged the model to 'use these annotations', which led it to reproduce the tag syntax in its output (observed as </acip> typos in replies). Tags never reach the client regardless — they exist only between proxy and provider on the request path. This change ensures they also don't leak into the model's own generated text.
Request-side (server.ts): after processTurn, log renderTags strategy and tag-injection counts — confirms text-only keeps tool messages pristine while text messages stay tagged for the LLM. Response-side (esbuild-safe): detect <acp tags leaking into model output. Plain-function ctx.log survives tree-shaking, so detection lives in server.ts response-forwarding loops (Buffer.toString) and the two non-stream rewrite functions, NOT inside async generators (esbuild DCEs ctx.log calls reachable only from generators). Anthropic routeEvent keeps a fine-grained per-delta check since its ctx.log survives.
ranxianglei
added a commit
that referenced
this pull request
Aug 8, 2026
Concurrent requests sharing a session id could interleave processTurn / stream-rewriter mutations on session.state, corrupting it. Add withSessionLock(session, fn) — a per-session promise chain that serializes the prepare → forward critical section. Also parse the request body once in handle() and pass the parsed object to prepare*, eliminating duplicate JSON.parse on large payloads (review #3).
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.
This was referenced Aug 10, 2026
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 22, 2026
This was referenced Aug 31, 2026
Merged
Closed
Closed
Merged
This was referenced Sep 8, 2026
Closed
This was referenced Sep 15, 2026
This was referenced Oct 15, 2026
Closed
This was referenced Oct 16, 2026
antclt
pushed a commit
to antclt/billion-context
that referenced
this pull request
Oct 16, 2026
The nightly concurrency groups ('schedule' -> shared 'nightly' suffix)
carry cancel-in-progress: true, and GitHub applies that WITHIN the group:
two scheduled runs of the same workflow kill each other. The per-file
comments ('keeps scheduled runs out of that cancel scope', ranxianglei#2637 ranxianglei#3)
describe the intent — pushes must not cancel the nightly run — but the
flag as written also lets the 30-min cron kill its own predecessor if a
run ever outlives the interval: tokens spent, no green recorded, and the
smart gate (ranxianglei#3295) can never learn the head is covered.
Empirically no lane has hit this yet (current scheduled runs finish in
minutes, 0 cancellations in recent history) — this is latent hardening,
not a live-fire fix. cancel-in-progress is now scoped to non-schedule
events, so same-ref supersede semantics are unchanged while scheduled
runs queue behind each other (at most one pending; a superseded PENDING
run costs nothing).
This was referenced Oct 17, 2026
Open
Open
ranxianglei
pushed a commit
that referenced
this pull request
Oct 21, 2026
The new breaker (a failed-only mutating round completes the turn instead of re-requesting) invalidated 24 tests across 15 files that used a failing compress as their re-request vehicle or pinned the old internal-continuation behavior. Three adaptation classes: - contract rewrites (old behavior gone by design): issue1502 salvage (no re-request after unsalvageable garbage args), issue3661 forms 1/2 (exercised on salvage-SUCCESSFUL rounds so the placeholder rides a real re-request; raw-malformed-skeleton absence pinned), issue1195 #2777 (the accepted overflow fold is now asserted to survive into the NEXT turn's rebuild), ccr-v2 unarmed opt-in (refusal receipt asserted on client SSE), loop-compress #422b (no fold refresh, no re-request). - vehicle swaps to acp_status (the test pins a re-request property, not compress itself): loop-core #5, fix-stream abort tests, loop-compress #3/#6/#10, strict-echo-model-criterion, anthropic-thinking-replay x3, upstream-truncation, loop-strict-echo (+responses), visibility-markers streaming pair. - made genuinely successful (the test needs a landed fold): e2e anthropic / responses-chat-relay / proxy-smoke round trips (unique session ids + protected-zone tail mass), subagent-namespace (positional refs + tail mass + honest usage claims — its mock had always failed via hash-boundary refs and only passed on master through retry-after-failure).
This was referenced Oct 21, 2026
z0d0dOr
pushed a commit
to z0d0dOr/billion-context
that referenced
this pull request
Oct 24, 2026
…end contract The new breaker (a failed-only mutating round completes the turn instead of re-requesting) invalidated 24 tests across 15 files that used a failing compress as their re-request vehicle or pinned the old internal-continuation behavior. Three adaptation classes: - contract rewrites (old behavior gone by design): issue1502 salvage (no re-request after unsalvageable garbage args), issue3661 forms 1/2 (exercised on salvage-SUCCESSFUL rounds so the placeholder rides a real re-request; raw-malformed-skeleton absence pinned), issue1195 ranxianglei#2777 (the accepted overflow fold is now asserted to survive into the NEXT turn's rebuild), ccr-v2 unarmed opt-in (refusal receipt asserted on client SSE), loop-compress #422b (no fold refresh, no re-request). - vehicle swaps to acp_status (the test pins a re-request property, not compress itself): loop-core ranxianglei#5, fix-stream abort tests, loop-compress ranxianglei#3/ranxianglei#6/ranxianglei#10, strict-echo-model-criterion, anthropic-thinking-replay x3, upstream-truncation, loop-strict-echo (+responses), visibility-markers streaming pair. - made genuinely successful (the test needs a landed fold): e2e anthropic / responses-chat-relay / proxy-smoke round trips (unique session ids + protected-zone tail mass), subagent-namespace (positional refs + tail mass + honest usage claims — its mock had always failed via hash-boundary refs and only passed on master through retry-after-failure). (cherry picked from commit d2c1086)
This was referenced Oct 24, 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.
Two changes keeping tags out of model output.
1. server.ts — kernel-driven tag strategy replaces proxy hack
Pass
renderTags: "text-only"toprocessTurn(both Anthropic + OpenAI paths). Requires acp-kernel PR#38 (RenderStrategythree-state). The render-refs node now leaves tool messages (tool-call args / tool-result content) pristine — no tag injected — so structured JSON is never corrupted. Refs are still assigned to every message (assignRefsNode runs unconditionally), so compress ranges still work.Removes the
stripToolTagshack:ACP_TAG_REconstant +stripToolTags()function + 2 call sites. Tag stripping was proxy-side post-processing doing what the kernel should do. Now the kernel does it cleanly viarenderTags.2. compress-tool.ts — forbid tag echoing in prompt
The ACP TAGS prompt section previously said 'Use these annotations to assess which messages are consuming the most context' — this encouraged the model to focus on the tags, and it started reproducing the tag syntax in its output (observed as
</acip>typos in replies).New wording: tags are system metadata injected by the proxy; NEVER echo, repeat, or reference these XML tags in responses; use only the ref ID inside compress calls, never the XML wrapper.
Tags never reach the client
Tags exist only on the proxy→provider request path. Provider responses stream back to the client untouched. This PR ensures they also don't leak into the model's generated text.
Depends on
acp-kernel PR#38 (RenderStrategy). Node_modules overlay used locally for testing; npm bump pending.