billion-context 0.1.67 → 0.1.68-pr.428.255

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,6 +50,66 @@ Agent (Claude Code / Codex / Cursor / Aider ...)
50
50
 
51
51
  The proxy injects four context-management tools (`compress`, `decompress`, `search_context`, `acp_status`) into the conversation. The model calls `compress` when the conversation grows, and the proxy executes it server-side — the compressed ranges are folded into the conversation history before the next turn.
52
52
 
53
+ ### Two compression modes — who executes `compress`
54
+
55
+ The proxy runs in one of two modes, and **the mode decides who executes
56
+ `compress`, which in turn decides how the summary travels to the model** (the
57
+ "carrier"). This distinction is the root of #377.
58
+
59
+ | | **Launcher / plugin mode** (`bili pi`, `bili codex`, …) | **Proxy mode** (plain client → `/bili/`) |
60
+ |---|---|---|
61
+ | Client | ACP-native agent with the bili extension (pi/omp) | Any OpenAI/Anthropic client, no extension |
62
+ | Who executes `compress` | **The agent** (pi runs it locally) | **The proxy** (server-side compress loop) |
63
+ | `compress` tool call in the re-sent history? | Yes — part of the agent's own conversation | No — ephemeral proxy-loop traffic |
64
+ | Preflight blocks (no tool call)? | No — overflow forces the model to call `compress` | Yes — `src/preflight.ts` compresses behind the client's back |
65
+ | **Summary carrier on the wire** | **the `compress` tool call** | **an `acp_summary` user message** |
66
+ | System messages on the wire | always exactly 1 (client + prompt) | always exactly 1 (client + prompt) — summaries ride on user messages |
67
+ | SGLang "single system" 400 (#377) | cannot happen | cannot happen (summaries are user messages, not system) |
68
+
69
+ **Why the carriers differ.** In plugin mode the agent owns compression: the
70
+ `compress` call + result live in the agent's own history and are re-sent every
71
+ turn, so the summary rides on the tool call and the agent's view never renders
72
+ the kernel's `acp_summary` fallback (`billion-context-pi` `src/messages.ts`
73
+ skips `acp_summary_*`). In proxy mode the client is not ACP-native, so the
74
+ proxy executes `compress` server-side; the tool call never enters the client's
75
+ history, and preflight blocks have no tool call at all — so the kernel's
76
+ `acp_summary` message is the only carrier. The kernel renders it as role
77
+ `system`, but strict OpenAI-compatible backends (SGLang) require exactly one
78
+ system message at index 0, so `systemToUser` (`src/util.ts`) re-voices it as a
79
+ `user` message, leaving it at its anchor position. This keeps the head system
80
+ message (the prefix-cache anchor) byte-stable across compress turns, so a new
81
+ block does not invalidate the whole-conversation prefix.
82
+
83
+ **Why `user`, not `system` or a forged tool call.** A mid-stream `system`
84
+ message is what SGLang rejects (#377). A forged `compress` tool call would be
85
+ the "pure" carrier, but in proxy mode it requires fabricating an
86
+ assistant `tool_calls` + `user` `tool_result` pair by id, declaring the tool in
87
+ the request, and handling preflight blocks that have no authentic call — far
88
+ more invasive than re-voicing a standalone note. A `user` message is allowed
89
+ anywhere in the conversation, so it is the minimal change that satisfies both
90
+ SGLang's one-system rule and prefix-cache stability. The accepted trade-off:
91
+ a summary is a stand-in for the folded history, and re-voicing it as a user
92
+ turn is a semantic mismatch the model tolerates (it is clearly marked
93
+ `[Compressed conversation section]`).
94
+
95
+ **Do the two modes coexist?**
96
+
97
+ - **Same proxy instance: yes, by design.** One proxy serves plugin and plain
98
+ clients at once; `pluginMode` is decided per request (`x-bili-plugin` header)
99
+ and bound per session (`session.metadata.pluginAgent`). The launcher reuses a
100
+ running proxy.
101
+ - **Same session: the mode is sticky.** A session created in plugin mode stays
102
+ plugin mode (metadata inheritance); a plain session can only be *upgraded* to
103
+ plugin mode if a plugin request arrives with a matching conversation id (the
104
+ header outranks) — and never downgraded. In practice a plain→plugin upgrade
105
+ requires the plugin client's conversation id to match an existing plain
106
+ session id, which doesn't happen (each client generates its own id).
107
+ - **Cross-mode block hazard: theoretical only.** It would require the same
108
+ conversation id to span a mode switch. plugin→proxy is safe (the tool call is
109
+ in the shared history); proxy→plugin could orphan proxy-created block
110
+ summaries (their tool call isn't in the agent's history and the agent's view
111
+ skips `acp_summary`) — but that needs the id match above, which doesn't occur.
112
+
53
113
  ## Install
54
114
 
55
115
  ```bash
@@ -162,6 +222,15 @@ bili --host 0.0.0.0 # all interfaces (or use your LAN IP)
162
222
  - MITM-mode `CONNECT` then also accepts remote clients — for **whitelisted
163
223
  model hosts only**. Blind tunnels to arbitrary hosts stay loopback-only, so
164
224
  the proxy can never be used as an open relay.
225
+ - The `/bili/<absolute-url>` tunnel has destination admission (#409): the
226
+ proxy itself and link-local/metadata addresses are **always denied**;
227
+ loopback/private destinations are allowed for local clients (self-hosted
228
+ upstreams) and **denied for remote clients** unless listed in
229
+ `BILI_TUNNEL_ALLOWED_HOSTS` (`host` or `host:port`, comma-separated) — a
230
+ remote peer must not use the proxy as an SSRF pivot into your LAN, and the
231
+ management plane is unreachable through the tunnel even via NAT hairpin
232
+ (tunneled requests carry an internal `x-bili-tunnel` marker that `/__bili/`
233
+ rejects).
165
234
  - There is **no authentication**: only do this on a trusted LAN or behind a
166
235
  firewall. The `/__bili/` management endpoints remain loopback-only.
167
236
  - A startup `[security]` warning reminds you of the above.