billion-context 0.1.133 → 0.1.134-pr.1088.965
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 +0 -24
- package/README.zh-CN.md +0 -10
- package/dist/index.js +6 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -810,30 +810,6 @@ The file auto-rotates at 10 MB (renamed to `bili.log.old`). Cache-hit stats
|
|
|
810
810
|
per request are logged as `[acp-usage] round N input=X cached=Y (cache hit Z%)`
|
|
811
811
|
so you can measure prefix-cache health directly from the log.
|
|
812
812
|
|
|
813
|
-
### Chaining bili instances (bili → bili)
|
|
814
|
-
|
|
815
|
-
When one bili's upstream is another bili (`client → A → B → LLM`), only the
|
|
816
|
-
instance closest to the client should run the compression pipeline — a second
|
|
817
|
-
pass would double-compress and corrupt session state. Any of three signals on
|
|
818
|
-
the inbound request makes the downstream instance pass it through **verbatim**
|
|
819
|
-
(no tool/tag injection, no acp-loop, no session state):
|
|
820
|
-
|
|
821
|
-
- `x-bili-hop` — stamped with the processing instance's id on every processed
|
|
822
|
-
emission (#300). Clients never send this header, so its presence always means
|
|
823
|
-
"came from a bili".
|
|
824
|
-
- `x-bili-sig` — sha256 digest of the exact emitted body bytes (#1078). Proves
|
|
825
|
-
no middlebox rewrote the request in transit; on mismatch the downstream
|
|
826
|
-
instance passes through anyway, because it must not process content it did
|
|
827
|
-
not produce.
|
|
828
|
-
- ACP artifacts in the body (render tags / context-management tool names) —
|
|
829
|
-
fallback for relays that strip bili's headers.
|
|
830
|
-
|
|
831
|
-
Every detection logs a prominent `[chain]` line (to `bili.log` and stderr)
|
|
832
|
-
naming the signal that fired. Older versions that stamp only `x-bili-hop` keep
|
|
833
|
-
working unchanged. If a third-party relay in your chain rewrites or strips
|
|
834
|
-
request bodies/headers, a `[chain]` warning on the downstream instance is the
|
|
835
|
-
safety mechanism working, not an error.
|
|
836
|
-
|
|
837
813
|
### Self-update
|
|
838
814
|
|
|
839
815
|
The proxy checks npm for a newer version on startup and every 3 minutes. When a
|
package/README.zh-CN.md
CHANGED
|
@@ -402,16 +402,6 @@ bili --host 0.0.0.0 # 所有网卡(或直接用局域网 IP)
|
|
|
402
402
|
|
|
403
403
|
文件超过 10 MB 自动轮转(重命名为 `bili.log.old`)。每个请求的缓存命中统计会以 `[acp-usage] round N input=X cached=Y (cache hit Z%)` 打印,可直接从日志衡量前缀缓存健康度。
|
|
404
404
|
|
|
405
|
-
### 串联多个 bili(bili → bili)
|
|
406
|
-
|
|
407
|
-
当一个 bili 的 upstream 指向另一个 bili(`客户端 → A → B → LLM`)时,只有离客户端最近的那个实例应该执行压缩管线——二次处理会重复压缩并破坏会话状态。入站请求上任意一个信号命中,下游实例都会**原样透传**该请求(不注入工具/标签、不跑 acp-loop、不建会话状态):
|
|
408
|
-
|
|
409
|
-
- `x-bili-hop` —— 处理方实例在每次处理后的转发上盖自己的实例 id(#300)。客户端永远不会发这个头,所以它的出现一定意味着"来自某个 bili"。
|
|
410
|
-
- `x-bili-sig` —— 转发体字节的 sha256 摘要(#1078)。用来证明请求在途中没有被中间设备改写;摘要不符时下游同样直接透传,因为它不能处理自己没有产出的内容。
|
|
411
|
-
- 请求体中的 ACP 产物(render 标签 / 上下文管理工具名)—— 针对会剥掉 bili 请求头的中转站的兜底检测。
|
|
412
|
-
|
|
413
|
-
每次命中都会在 `bili.log`(及 stderr)打一条醒目的 `[chain]` 日志,标明触发信号。只盖 `x-bili-hop` 的旧版本行为不变。如果你的链路里有第三方中转站会改写或剥离请求体/头,下游实例出现的 `[chain]` 警告是安全机制在工作,不是错误。
|
|
414
|
-
|
|
415
405
|
### 自动更新
|
|
416
406
|
|
|
417
407
|
代理启动时和每 3 分钟检查 npm 是否有新版本。发现新版本就全局安装(`npm install -g`)并打印通知 —— **重启 `bili` 才能生效**。
|
package/dist/index.js
CHANGED
|
@@ -50569,7 +50569,7 @@ function rejectLegacyRoute(key, value) {
|
|
|
50569
50569
|
import http from "http";
|
|
50570
50570
|
import fs11 from "fs";
|
|
50571
50571
|
import path18 from "path";
|
|
50572
|
-
import { createHash as
|
|
50572
|
+
import { createHash as createHash8, randomUUID as randomUUID4 } from "crypto";
|
|
50573
50573
|
import { performance as performance2 } from "perf_hooks";
|
|
50574
50574
|
|
|
50575
50575
|
// src/compress-settings.ts
|
|
@@ -70492,35 +70492,6 @@ function anthropicBetaContextWindow(headers) {
|
|
|
70492
70492
|
return best;
|
|
70493
70493
|
}
|
|
70494
70494
|
|
|
70495
|
-
// src/server/chain-sig.ts
|
|
70496
|
-
import { createHash as createHash8, timingSafeEqual } from "crypto";
|
|
70497
|
-
var BILI_SIG_HEADER = "x-bili-sig";
|
|
70498
|
-
var SIG_FORMAT = /^sha256:([0-9a-f]{64})$/;
|
|
70499
|
-
function sha256Hex(body) {
|
|
70500
|
-
return createHash8("sha256").update(typeof body === "string" ? Buffer.from(body, "utf8") : body).digest("hex");
|
|
70501
|
-
}
|
|
70502
|
-
function stampChainSig(headers, body) {
|
|
70503
|
-
headers[BILI_SIG_HEADER] = `sha256:${sha256Hex(body)}`;
|
|
70504
|
-
}
|
|
70505
|
-
function verifyChainSig(header, rawBody) {
|
|
70506
|
-
if (header === void 0) return "absent";
|
|
70507
|
-
const m2 = SIG_FORMAT.exec(header);
|
|
70508
|
-
if (!m2) return "mismatch";
|
|
70509
|
-
const expected = Buffer.from(m2[1], "hex");
|
|
70510
|
-
const actual = createHash8("sha256").update(rawBody).digest();
|
|
70511
|
-
return timingSafeEqual(expected, actual) ? "verified" : "mismatch";
|
|
70512
|
-
}
|
|
70513
|
-
var ACP_TAG_RE = /\x3cacp\s+tokens=\\?"[0-9]+(?:\.[0-9]+)?K?\\?"\s+type=\\?"[^\\"]*\\?"\s*\x3em[0-9]{1,8}\x3c\/acp\x3e/;
|
|
70514
|
-
function detectAcpArtifacts(body) {
|
|
70515
|
-
if (body.length === 0) return false;
|
|
70516
|
-
const tagSeed = body.includes("<acp ");
|
|
70517
|
-
const toolSeed = body.includes('"acp_status"') && body.includes('"search_context"');
|
|
70518
|
-
if (!tagSeed && !toolSeed) return false;
|
|
70519
|
-
const text = body.toString("utf8");
|
|
70520
|
-
if (tagSeed && ACP_TAG_RE.test(text)) return true;
|
|
70521
|
-
return toolSeed;
|
|
70522
|
-
}
|
|
70523
|
-
|
|
70524
70495
|
// src/server/headers.ts
|
|
70525
70496
|
function safeSessionId(id) {
|
|
70526
70497
|
return (id ?? "unknown").replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
@@ -71265,20 +71236,6 @@ async function handle(req, res, opts, core, config, log2, instanceId, instanceSt
|
|
|
71265
71236
|
const selfLoop = hopMarker === instanceId;
|
|
71266
71237
|
log2("warn", selfLoop ? `[chain] inbound request carries THIS instance's ${BILI_HOP_HEADER} marker (${hopMarker}) \u2014 self-loop detected. Passing through without processing; check your upstream config (it may point back to this instance).` : `[chain] inbound request carries ${BILI_HOP_HEADER} from another bili instance (${hopMarker}) \u2014 bili\u2192bili chain detected. Passing through without processing to avoid double compression; keep only one bili instance in the chain.`);
|
|
71267
71238
|
}
|
|
71268
|
-
const chainSig = headerValue2(req, BILI_SIG_HEADER);
|
|
71269
|
-
const hasAcpArtifacts = hopMarker === void 0 && chainSig === void 0 && bodyBuffer.length > 0 && detectAcpArtifacts(bodyBuffer);
|
|
71270
|
-
if (hopMarker !== void 0 && chainSig !== void 0) {
|
|
71271
|
-
if (verifyChainSig(chainSig, bodyBuffer) === "mismatch") {
|
|
71272
|
-
log2("warn", `[chain] ${BILI_HOP_HEADER} (${hopMarker}) present but ${BILI_SIG_HEADER} does not match the received body \u2014 a middlebox rewrote the request in transit. Passing through without processing.`);
|
|
71273
|
-
} else {
|
|
71274
|
-
log2("debug", `[chain] ${BILI_SIG_HEADER} verified for ${BILI_HOP_HEADER}=${hopMarker}`);
|
|
71275
|
-
}
|
|
71276
|
-
} else if (hopMarker === void 0 && chainSig !== void 0) {
|
|
71277
|
-
log2("warn", `[chain] inbound request carries ${BILI_SIG_HEADER} but no ${BILI_HOP_HEADER} \u2014 a middlebox likely stripped the hop header. Passing through without processing.`);
|
|
71278
|
-
} else if (hasAcpArtifacts) {
|
|
71279
|
-
log2("warn", `[chain] inbound request carries ACP compression artifacts but neither ${BILI_HOP_HEADER} nor ${BILI_SIG_HEADER} \u2014 a middlebox likely stripped bili's headers. Passing through without processing.`);
|
|
71280
|
-
}
|
|
71281
|
-
const chainDetected = hopMarker !== void 0 || chainSig !== void 0 || hasAcpArtifacts;
|
|
71282
71239
|
if (headerValue2(req, BILI_PLUGIN_BYPASS_HEADER) === "1") {
|
|
71283
71240
|
log2("debug", `bypass: ${req.method ?? "?"} ${maskUrlForLog(req.url ?? "")} \u2014 raw passthrough (legacy in-process compression)`);
|
|
71284
71241
|
await forward(req, res, opts, bodyBuffer, null, core, config, log2, route, instanceId, void 0);
|
|
@@ -71401,10 +71358,10 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
71401
71358
|
let prepared = null;
|
|
71402
71359
|
let forwarded = false;
|
|
71403
71360
|
const routePassthrough = !opts.passthrough && findRoute(opts.routes, route?.rewrittenUrl)?.passthrough === true;
|
|
71404
|
-
if (routePassthrough &&
|
|
71361
|
+
if (routePassthrough && hopMarker === void 0 && protocol && parsed) {
|
|
71405
71362
|
log2("info", `[route-passthrough] ${maskUrlsInText(route?.rewrittenUrl ?? "")} matches a passthrough route \u2014 forwarding verbatim, kernel bypassed`);
|
|
71406
71363
|
}
|
|
71407
|
-
if (!opts.passthrough && !routePassthrough &&
|
|
71364
|
+
if (!opts.passthrough && !routePassthrough && hopMarker === void 0 && protocol && parsed && typeof parsed === "object") {
|
|
71408
71365
|
const sessionHeader = headerValue2(req, opts.sessionHeader);
|
|
71409
71366
|
let pluginAgent = pluginAgentHeader(req.headers);
|
|
71410
71367
|
let pluginConversation = pluginConversationHeader(req.headers);
|
|
@@ -72699,7 +72656,7 @@ async function preflightCompressIfNeeded(prepared, runPrepare, req, inboundBody,
|
|
|
72699
72656
|
return failFast(502, "no part of the conversation is compressible (nothing left to fold)", false);
|
|
72700
72657
|
}
|
|
72701
72658
|
}
|
|
72702
|
-
const deadEndKey = `${model}\0${limit}\0${
|
|
72659
|
+
const deadEndKey = `${model}\0${limit}\0${createHash8("sha256").update(inboundBody).digest("hex")}`;
|
|
72703
72660
|
const deadEnd = session.metadata.preflightDeadEnd;
|
|
72704
72661
|
if (deadEnd && typeof deadEnd === "object") {
|
|
72705
72662
|
const de2 = deadEnd;
|
|
@@ -72826,9 +72783,6 @@ async function forward(req, res, opts, body, prepared, core, config, log2, route
|
|
|
72826
72783
|
}
|
|
72827
72784
|
}
|
|
72828
72785
|
}
|
|
72829
|
-
if (prepared !== null && req.method !== "GET" && req.method !== "HEAD") {
|
|
72830
|
-
stampChainSig(headers, wireBody);
|
|
72831
|
-
}
|
|
72832
72786
|
const wireTransform = compatProtocol ? (b2) => {
|
|
72833
72787
|
if (compatRoles) applyCompatRolesJson(b2, compatProtocol, compatRoles);
|
|
72834
72788
|
return b2;
|
|
@@ -72966,9 +72920,7 @@ ${bodyText}`);
|
|
|
72966
72920
|
if (fixed.rewritten === 0) return "other";
|
|
72967
72921
|
let r;
|
|
72968
72922
|
try {
|
|
72969
|
-
|
|
72970
|
-
if (prepared !== null) stampChainSig(retryHeaders, fixed.body);
|
|
72971
|
-
r = await fetchWithTimeout(upstreamUrl, { ...init, headers: retryHeaders, body: fixed.body }, void 0, clientAbort.signal);
|
|
72923
|
+
r = await fetchWithTimeout(upstreamUrl, { ...init, body: fixed.body }, void 0, clientAbort.signal);
|
|
72972
72924
|
} catch {
|
|
72973
72925
|
return "other";
|
|
72974
72926
|
}
|
|
@@ -73459,13 +73411,11 @@ async function resolveFakeCompletion(stream2, opts) {
|
|
|
73459
73411
|
opts.log("warn", `[${sid}] fake completion (tool-call XML, no tool block); retry ${attempt}/${max} with corrective hint`);
|
|
73460
73412
|
let r;
|
|
73461
73413
|
try {
|
|
73462
|
-
const retryHeaders = { ...opts.reqHeaders };
|
|
73463
|
-
stampChainSig(retryHeaders, hinted);
|
|
73464
73414
|
r = await fetchWithTimeout(
|
|
73465
73415
|
opts.upstreamUrl,
|
|
73466
73416
|
{
|
|
73467
73417
|
method: "POST",
|
|
73468
|
-
headers:
|
|
73418
|
+
headers: opts.reqHeaders,
|
|
73469
73419
|
body: hinted,
|
|
73470
73420
|
...opts.proxyUrl ? { dispatcher: proxyDispatcher(opts.proxyUrl) } : {}
|
|
73471
73421
|
},
|