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 +0 -17
- package/README.zh-CN.md +0 -6
- package/dist/index.js +1 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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:
|
|
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
|
}
|