billion-context 0.1.8 → 0.1.10

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
@@ -212,6 +212,15 @@ The config file is a single JSON object. Example:
212
212
  | `providers` | *(none)* | Provider routes — see below |
213
213
  | `compress` | *(see defaults)* | `{ injectTool, injectNudge }` |
214
214
 
215
+ > **Choosing a `host`** (IPv6 / containers): the default `127.0.0.1` is
216
+ > IPv4-only and loopback-only. Use `--host ::` (or `"host": "::"`) to listen
217
+ > on **both** IPv4 and IPv6, which matters if your client resolves
218
+ > `localhost` to `::1` first (some `/etc/hosts` files list `::1` before
219
+ > `127.0.0.1`). Inside a **container**, `127.0.0.1` binds the container's own
220
+ > loopback and is unreachable through a published port — use
221
+ > `--host 0.0.0.0` there. ⚠️ `0.0.0.0` / `::` expose the proxy on **all**
222
+ > interfaces; ensure you're on a trusted network or behind a firewall.
223
+
215
224
  ### Providers (URL routing + per-model context)
216
225
 
217
226
  `providers` maps a route name to either a bare URL string (simple) or an
package/README.zh-CN.md CHANGED
@@ -196,6 +196,14 @@ bili --no-auto-update # 本次启动禁用自动更新
196
196
  | `providers` | *(无)* | Provider 路由 —— 见下文 |
197
197
  | `compress` | *(见默认值)* | `{ injectTool, injectNudge }` |
198
198
 
199
+ > **选择 `host`**(IPv6 / 容器):默认 `127.0.0.1` 只听 IPv4 且仅
200
+ > loopback。用 `--host ::`(或 `"host": "::"`)可同时听 IPv4 和 IPv6
201
+ > ——当你的客户端把 `localhost` 先解析成 `::1` 时(有些 `/etc/hosts`
202
+ > 把 `::1` 排在 `127.0.0.1` 前)这就很关键。在**容器**内,`127.0.0.1`
203
+ > 绑的是容器自己的 loopback,通过映射端口访问不到——这时用
204
+ > `--host 0.0.0.0`。⚠️ `0.0.0.0` / `::` 会把代理暴露到**所有**网卡;
205
+ > 确保你在可信网络或防火墙后面。
206
+
199
207
  ### Providers(URL 路由 + 按模型 context)
200
208
 
201
209
  `providers` 把路由名映射到一个纯 URL 字符串(简单)或一个带 `url` + 可选按模型 context 窗口的对象(推荐)。
package/dist/index.js CHANGED
@@ -1603,15 +1603,27 @@ import path3 from "path";
1603
1603
  var MAX_BYTES = 10 * 1024 * 1024;
1604
1604
  var stream;
1605
1605
  var logPath;
1606
+ var bytesWritten = 0;
1606
1607
  function open(pathStr) {
1607
1608
  mkdirSync3(path3.dirname(pathStr), { recursive: true });
1609
+ let existingSize = 0;
1608
1610
  try {
1609
- if (statSync(pathStr).size >= MAX_BYTES) {
1610
- renameSync2(pathStr, pathStr + ".old");
1611
+ existingSize = statSync(pathStr).size;
1612
+ if (existingSize >= MAX_BYTES) {
1613
+ rotate(pathStr);
1614
+ existingSize = 0;
1611
1615
  }
1612
1616
  } catch {
1613
1617
  }
1614
- return createWriteStream(pathStr, { flags: "a" });
1618
+ const s = createWriteStream(pathStr, { flags: "a" });
1619
+ bytesWritten = existingSize;
1620
+ return s;
1621
+ }
1622
+ function rotate(pathStr) {
1623
+ try {
1624
+ renameSync2(pathStr, pathStr + ".old");
1625
+ } catch {
1626
+ }
1615
1627
  }
1616
1628
  function configureLogger(file) {
1617
1629
  if (!file || file === "off") {
@@ -1628,13 +1640,20 @@ var log = (level, msg2) => {
1628
1640
  const line = `${ts} [${level}] ${msg2}
1629
1641
  `;
1630
1642
  process.stderr.write(line);
1631
- if (stream) {
1643
+ if (stream && logPath) {
1644
+ if (bytesWritten >= MAX_BYTES) {
1645
+ stream.end();
1646
+ rotate(logPath);
1647
+ stream = open(logPath);
1648
+ }
1632
1649
  stream.write(line);
1650
+ bytesWritten += Buffer.byteLength(line);
1633
1651
  }
1634
1652
  };
1635
1653
  function closeLogger() {
1636
1654
  stream?.end();
1637
1655
  stream = void 0;
1656
+ bytesWritten = 0;
1638
1657
  }
1639
1658
 
1640
1659
  // src/compress-loop.ts
@@ -2657,11 +2676,19 @@ async function startServer(opts) {
2657
2676
  if (shuttingDown) return;
2658
2677
  shuttingDown = true;
2659
2678
  log2("info", `${sig} received \u2014 flushing sessions\u2026`);
2660
- server.close();
2661
- void flushAllSessions().finally(() => {
2662
- closeLogger();
2663
- process.exit(0);
2679
+ server.close(() => {
2680
+ void flushAllSessions().finally(() => {
2681
+ closeLogger();
2682
+ process.exit(0);
2683
+ });
2664
2684
  });
2685
+ setTimeout(() => {
2686
+ log2("warn", "shutdown grace window elapsed; forcing exit");
2687
+ void flushAllSessions().finally(() => {
2688
+ closeLogger();
2689
+ process.exit(0);
2690
+ });
2691
+ }, 1e4).unref?.();
2665
2692
  };
2666
2693
  process.on("SIGTERM", () => shutdown("SIGTERM"));
2667
2694
  process.on("SIGINT", () => shutdown("SIGINT"));
@@ -3250,15 +3277,18 @@ async function checkForUpdate(opts, force = false) {
3250
3277
  if (!opts.autoUpdate && !force) return;
3251
3278
  if (inFlight) return;
3252
3279
  inFlight = true;
3280
+ const firstInProcess = !notified.has("__first_check_done__");
3253
3281
  try {
3254
3282
  const now = Date.now();
3255
3283
  const lastCheck = await readLastCheck();
3256
- if (!force && now - lastCheck < CHECK_INTERVAL_MS) {
3257
- log("info", `[update] check skipped (throttled, ${(CHECK_INTERVAL_MS - (now - lastCheck)) / 1e3 | 0}s until next)`);
3284
+ const sinceLastSec = lastCheck ? (now - lastCheck) / 1e3 | 0 : -1;
3285
+ if (!force && !firstInProcess && now - lastCheck < CHECK_INTERVAL_MS) {
3286
+ const retryIn = (CHECK_INTERVAL_MS - (now - lastCheck)) / 1e3 | 0;
3287
+ log("info", `[update] throttled \u2014 last checked ${sinceLastSec}s ago, retry in ${retryIn}s`);
3258
3288
  return;
3259
3289
  }
3260
3290
  await writeLastCheck(now);
3261
- log("info", `[update] checking npm registry for ${opts.packageName}\u2026`);
3291
+ log("info", `[update] checking npm registry for ${opts.packageName}${firstInProcess ? " (startup check)" : sinceLastSec < 0 ? "" : ` (last check ${sinceLastSec}s ago)`}\u2026`);
3262
3292
  const url = `${REGISTRY_BASE}/${opts.packageName}/latest`;
3263
3293
  const res = await fetch(url, {
3264
3294
  signal: AbortSignal.timeout(5e3),
@@ -3294,6 +3324,7 @@ async function checkForUpdate(opts, force = false) {
3294
3324
  log("warn", `[update] check failed: ${String(e)}`);
3295
3325
  } finally {
3296
3326
  inFlight = false;
3327
+ notified.add("__first_check_done__");
3297
3328
  }
3298
3329
  }
3299
3330
  async function installLatest(packageName, latest) {