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 +69 -0
- package/dist/index.js +840 -400
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +51 -10
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
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.
|