billion-context 0.1.66-pr.373.227 → 0.1.66

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
@@ -307,23 +307,6 @@ recommended** for many concurrent conversations because of the collision
307
307
  risk — until pi grows its own session-id signal. For pi multi-agent use,
308
308
  pass an explicit `x-acp-session` header per conversation to avoid collisions.
309
309
 
310
- ### Windows: exclude the sessions dir from antivirus (#362)
311
-
312
- The proxy persists each session's compression state to the sessions dir
313
- (`%USERPROFILE%\.local\share\billion-context\` by default) and rewrites the
314
- file every turn of a long session. On Windows, real-time antivirus (Windows
315
- Defender), the search indexer, or a sync tool (OneDrive) can lock that
316
- directory mid-write, so the rename fails with `EPERM` and every persist for
317
- that session fails until the lock clears.
318
-
319
- When the same session fails N consecutive writes (default `5`), the proxy
320
- logs a one-time, actionable alert naming the directory to exclude. To fix it
321
- at the root: add `%USERPROFILE%\.local\share\billion-context\` to your
322
- antivirus **exclusions** (Windows Defender: Settings → Virus & threat
323
- protection → Manage settings → Exclusions → Add an exclusion → Folder) and
324
- make sure no sync tool (OneDrive / Dropbox / …) is syncing that path. Full
325
- steps in [CONFIGURATION.md](CONFIGURATION.md#windows-exclude-the-sessions-dir-from-antivirus-362).
326
-
327
310
  ## Status
328
311
 
329
312
  Early. Protocol handling and compression work against mock tests (500+ passing). Real-model integration testing is the next milestone. Expect rough edges.
package/README.zh-CN.md CHANGED
@@ -254,12 +254,6 @@ Windows 下会自动发现常见 Clash/Mihomo 静态系统代理;Web UI 会显
254
254
 
255
255
  **建议:** Codex 和 OpenCode 可以安全地通过代理并发跑很多会话。pi 单个 agent 没问题,但因碰撞风险**不建议**并发多会话 —— 直到 pi 自己长出 session-id 信号。pi 多 agent 场景下,每个会话发一个显式 `x-acp-session` header 来避免碰撞。
256
256
 
257
- ### Windows:把会话目录加入杀软排除项(#362)
258
-
259
- 代理把每个会话的压缩状态持久化到会话目录(默认 `%USERPROFILE%\.local\share\billion-context\`),长会话每一轮都会重写该文件。在 Windows 上,实时杀毒(Windows Defender)、搜索索引器或同步工具(OneDrive)可能在写入中途锁住该目录,导致 rename 以 `EPERM` 失败,在锁解除前该会话的每次持久化都会失败。
260
-
261
- 当同一会话连续 N 次写失败(默认 `5`)时,代理会打一条一次性、可操作的告警,明确指出要排除的目录。要从根上修复:把 `%USERPROFILE%\.local\share\billion-context\` 加入杀软**排除项**(Windows Defender:设置 → 病毒和威胁防护 → 管理设置 → 排除项 → 添加排除 → 文件夹),并确认没有同步工具(OneDrive / Dropbox / …)在同步该路径。完整步骤见 [CONFIGURATION.zh-CN.md](CONFIGURATION.zh-CN.md) 的「Windows:把会话目录加入杀软排除项」章节。
262
-
263
257
  ## 状态
264
258
 
265
259
  早期。协议处理和压缩已通过 mock 测试(500+ 项通过)。真实模型集成测试是下一里程碑。预期会有粗糙的地方。
package/dist/index.js CHANGED
@@ -49685,57 +49685,6 @@ function rel(p2, base) {
49685
49685
  return r && !r.startsWith("..") ? r : p2;
49686
49686
  }
49687
49687
 
49688
- // src/persist-eperm.ts
49689
- var LOCK_CODES = /\b(EPERM|EBUSY|EACCES)\b/;
49690
- var WRITE_FAIL_RE = /^\[persist\] write failed for (.+?) \(total (\d+)x\): (.+)$/;
49691
- var PersistEpermAlert = class {
49692
- dir;
49693
- threshold;
49694
- repeatMs;
49695
- platform;
49696
- now;
49697
- onAlert;
49698
- hasAlerted = false;
49699
- alertedAt = 0;
49700
- constructor(opts) {
49701
- this.dir = opts.dir;
49702
- this.threshold = opts.threshold ?? 5;
49703
- this.repeatMs = opts.repeatMs ?? 0;
49704
- this.platform = opts.platform ?? process.platform;
49705
- this.now = opts.now ?? Date.now;
49706
- this.onAlert = opts.onAlert ?? ((d, c) => log("warn", buildAlertMessage(d, c)));
49707
- }
49708
- // Returns true iff an alert was emitted. Runs on every kernel log line, so
49709
- // the non-matching cases bail before any allocation.
49710
- observe(level, msg) {
49711
- if (this.platform !== "win32") return false;
49712
- if (level !== "error" && level !== "warn") return false;
49713
- const m2 = WRITE_FAIL_RE.exec(msg);
49714
- if (!m2) return false;
49715
- const count = Number(m2[2]);
49716
- if (count < this.threshold) return false;
49717
- if (!LOCK_CODES.test(m2[3])) return false;
49718
- if (!this.shouldAlert()) return false;
49719
- this.hasAlerted = true;
49720
- this.alertedAt = this.now();
49721
- this.onAlert(this.dir, count);
49722
- return true;
49723
- }
49724
- shouldAlert() {
49725
- if (!this.hasAlerted) return true;
49726
- if (this.repeatMs <= 0) return false;
49727
- return this.now() - this.alertedAt >= this.repeatMs;
49728
- }
49729
- };
49730
- function buildAlertMessage(dir, count) {
49731
- return [
49732
- `[persist] session dir ${dir} failed ${count} consecutive writes (EPERM \u2014 rename is locked).`,
49733
- "Likely cause: Windows Defender / antivirus / indexer / a sync tool is locking the directory.",
49734
- `Fix: add ${dir} to Windows Defender exclusions (Settings \u2192 Virus & threat protection \u2192 Manage settings \u2192 Exclusions \u2192 Add an exclusion),`,
49735
- "and make sure no OneDrive / sync tool is syncing this path."
49736
- ].join("\n");
49737
- }
49738
-
49739
49688
  // src/persist.ts
49740
49689
  var PERSIST_VERSION = 3;
49741
49690
  function mergeState(parsed) {
@@ -49772,21 +49721,12 @@ var SessionStore = class {
49772
49721
  const debounceMs = opts?.debounceMs ?? defaultDebounce();
49773
49722
  this.enabled = (opts?.enabled ?? true) && debounceMs >= 0;
49774
49723
  this.dir = opts?.dir ?? defaultDir();
49775
- const baseLog = opts?.log ?? defaultLogger;
49776
- const epermAlert = new PersistEpermAlert({
49777
- dir: this.dir,
49778
- threshold: epermAlertThreshold(),
49779
- repeatMs: epermAlertRepeatMs()
49780
- });
49781
49724
  this.store = new StateStore({
49782
49725
  dir: this.dir,
49783
49726
  version: PERSIST_VERSION,
49784
49727
  debounceMs: Math.max(0, debounceMs),
49785
49728
  enabled: this.enabled,
49786
- log: (level, msg) => {
49787
- epermAlert.observe(level, msg);
49788
- baseLog(level, msg);
49789
- },
49729
+ log: opts?.log ?? defaultLogger,
49790
49730
  relPath: (id, payload) => relPathFor(id, payload.meta?.protocol ?? payload.protocol, payload.meta?.upstreamOrigin ?? payload.upstreamOrigin),
49791
49731
  // Adopt the pre-envelope flat format this store itself wrote
49792
49732
  // before the kernel extraction (and every v1/v2 file before it).
@@ -49995,22 +49935,6 @@ function persistEnabled() {
49995
49935
  if (env === "0" || env === "false") return false;
49996
49936
  return true;
49997
49937
  }
49998
- function epermAlertThreshold() {
49999
- const env = process.env.BILI_PERSIST_EPERM_ALERT_THRESHOLD;
50000
- if (env) {
50001
- const n = Number.parseInt(env, 10);
50002
- if (Number.isFinite(n) && n > 0) return n;
50003
- }
50004
- return 5;
50005
- }
50006
- function epermAlertRepeatMs() {
50007
- const env = process.env.BILI_PERSIST_EPERM_ALERT_REPEAT_MS;
50008
- if (env) {
50009
- const n = Number.parseInt(env, 10);
50010
- if (Number.isFinite(n) && n >= 0) return n;
50011
- }
50012
- return 0;
50013
- }
50014
49938
  function defaultLogger(level, m2) {
50015
49939
  log(level, m2);
50016
49940
  }