billion-context 0.1.7 → 0.1.9
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 +9 -0
- package/README.zh-CN.md +8 -0
- package/dist/index.js +70 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
@@ -41,7 +41,8 @@ function defaultLogFile() {
|
|
|
41
41
|
// src/config.ts
|
|
42
42
|
function safeReadJson(path6) {
|
|
43
43
|
try {
|
|
44
|
-
|
|
44
|
+
const raw = readFileSync(path6, "utf8").replace(/^\uFEFF/, "");
|
|
45
|
+
return JSON.parse(raw);
|
|
45
46
|
} catch (e) {
|
|
46
47
|
if (e.code !== "ENOENT") {
|
|
47
48
|
console.error(`[acp-config] failed to parse ${path6}: ${String(e)}`);
|
|
@@ -148,6 +149,7 @@ function parseRouteEntry(v) {
|
|
|
148
149
|
// src/server.ts
|
|
149
150
|
import http from "http";
|
|
150
151
|
import fs2 from "fs";
|
|
152
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
151
153
|
import { createCore, estimateTokensFast as estimateTokensFast3, renderNudgeText, deactivateBlock as deactivateBlock4 } from "acp-kernel";
|
|
152
154
|
|
|
153
155
|
// src/fetch-util.ts
|
|
@@ -837,8 +839,18 @@ var SessionStore = class {
|
|
|
837
839
|
}
|
|
838
840
|
const tmp = this.tempPath(session.id);
|
|
839
841
|
const data = JSON.stringify(record);
|
|
840
|
-
|
|
841
|
-
|
|
842
|
+
try {
|
|
843
|
+
await fs.writeFile(tmp, data, "utf8");
|
|
844
|
+
await fs.rename(tmp, file);
|
|
845
|
+
} catch (e) {
|
|
846
|
+
try {
|
|
847
|
+
await fs.unlink(tmp).catch(() => {
|
|
848
|
+
});
|
|
849
|
+
} catch {
|
|
850
|
+
}
|
|
851
|
+
this.log("error", `[persist] write failed for ${session.id}: ${msg(e)}`);
|
|
852
|
+
throw e;
|
|
853
|
+
}
|
|
842
854
|
}
|
|
843
855
|
/** Synchronous flush for a single session. Used on memory eviction so a
|
|
844
856
|
* dirty evicted session is not lost. Sync because eviction runs in the
|
|
@@ -1591,15 +1603,27 @@ import path3 from "path";
|
|
|
1591
1603
|
var MAX_BYTES = 10 * 1024 * 1024;
|
|
1592
1604
|
var stream;
|
|
1593
1605
|
var logPath;
|
|
1606
|
+
var bytesWritten = 0;
|
|
1594
1607
|
function open(pathStr) {
|
|
1595
1608
|
mkdirSync3(path3.dirname(pathStr), { recursive: true });
|
|
1609
|
+
let existingSize = 0;
|
|
1596
1610
|
try {
|
|
1597
|
-
|
|
1598
|
-
|
|
1611
|
+
existingSize = statSync(pathStr).size;
|
|
1612
|
+
if (existingSize >= MAX_BYTES) {
|
|
1613
|
+
rotate(pathStr);
|
|
1614
|
+
existingSize = 0;
|
|
1599
1615
|
}
|
|
1600
1616
|
} catch {
|
|
1601
1617
|
}
|
|
1602
|
-
|
|
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
|
+
}
|
|
1603
1627
|
}
|
|
1604
1628
|
function configureLogger(file) {
|
|
1605
1629
|
if (!file || file === "off") {
|
|
@@ -1616,13 +1640,20 @@ var log = (level, msg2) => {
|
|
|
1616
1640
|
const line = `${ts} [${level}] ${msg2}
|
|
1617
1641
|
`;
|
|
1618
1642
|
process.stderr.write(line);
|
|
1619
|
-
if (stream) {
|
|
1643
|
+
if (stream && logPath) {
|
|
1644
|
+
if (bytesWritten >= MAX_BYTES) {
|
|
1645
|
+
stream.end();
|
|
1646
|
+
rotate(logPath);
|
|
1647
|
+
stream = open(logPath);
|
|
1648
|
+
}
|
|
1620
1649
|
stream.write(line);
|
|
1650
|
+
bytesWritten += Buffer.byteLength(line);
|
|
1621
1651
|
}
|
|
1622
1652
|
};
|
|
1623
1653
|
function closeLogger() {
|
|
1624
1654
|
stream?.end();
|
|
1625
1655
|
stream = void 0;
|
|
1656
|
+
bytesWritten = 0;
|
|
1626
1657
|
}
|
|
1627
1658
|
|
|
1628
1659
|
// src/compress-loop.ts
|
|
@@ -2624,19 +2655,46 @@ async function startServer(opts) {
|
|
|
2624
2655
|
`acp-proxy listening on http://${opts.host}:${opts.port}` + (Object.keys(opts.routes).length ? ` \u2014 routes: ${Object.entries(opts.routes).map(([n, u]) => `${n}=${typeof u === "string" ? u : u.url}`).join(", ")}` : ` \u2192 ${opts.upstream}`)
|
|
2625
2656
|
);
|
|
2626
2657
|
});
|
|
2658
|
+
server.on("error", (err) => {
|
|
2659
|
+
const hint = err.code === "EADDRINUSE" ? ` \u2014 port ${opts.port} is already in use. Stop the other process or use --port <N>.` : err.code === "EACCES" ? ` \u2014 port ${opts.port} requires privileges. Use a port >= 1024.` : "";
|
|
2660
|
+
log2("error", `listen failed: ${err.code ?? ""} ${err.message}${hint}`);
|
|
2661
|
+
shuttingDown = true;
|
|
2662
|
+
server.close();
|
|
2663
|
+
void flushAllSessions().finally(() => {
|
|
2664
|
+
closeLogger();
|
|
2665
|
+
process.exit(1);
|
|
2666
|
+
});
|
|
2667
|
+
});
|
|
2668
|
+
process.on("uncaughtException", (err) => {
|
|
2669
|
+
log2("error", `uncaughtException: ${String(err?.stack ?? err)}`);
|
|
2670
|
+
});
|
|
2671
|
+
process.on("unhandledRejection", (reason) => {
|
|
2672
|
+
log2("error", `unhandledRejection: ${String(reason)}`);
|
|
2673
|
+
});
|
|
2627
2674
|
let shuttingDown = false;
|
|
2628
2675
|
const shutdown = (sig) => {
|
|
2629
2676
|
if (shuttingDown) return;
|
|
2630
2677
|
shuttingDown = true;
|
|
2631
2678
|
log2("info", `${sig} received \u2014 flushing sessions\u2026`);
|
|
2632
|
-
server.close()
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2679
|
+
server.close(() => {
|
|
2680
|
+
void flushAllSessions().finally(() => {
|
|
2681
|
+
closeLogger();
|
|
2682
|
+
process.exit(0);
|
|
2683
|
+
});
|
|
2636
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?.();
|
|
2637
2692
|
};
|
|
2638
2693
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
2639
2694
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
2695
|
+
if (process.platform === "win32") {
|
|
2696
|
+
process.on("SIGBREAK", () => shutdown("SIGBREAK"));
|
|
2697
|
+
}
|
|
2640
2698
|
return server;
|
|
2641
2699
|
}
|
|
2642
2700
|
async function handle(req, res, opts, core, config, log2) {
|
|
@@ -2940,7 +2998,7 @@ async function forward(req, res, opts, body, prepared, core, config, log2, route
|
|
|
2940
2998
|
});
|
|
2941
2999
|
log2("info", `[debug] tools=[${toolNames.join(",")}] msgs=${parsed.messages?.length ?? 0} stream=${parsed.stream ?? false} system_len=${JSON.stringify(parsed.messages?.find((m) => m.role === "system")?.content ?? "").length}`);
|
|
2942
3000
|
if (process.env.ACP_DUMP_REQ === "1") {
|
|
2943
|
-
const out =
|
|
3001
|
+
const out = `${tmpdir2()}/acp-proxy-debug-req-${Date.now()}.json`;
|
|
2944
3002
|
fs2.writeFileSync(out, body.slice(0, 5e4));
|
|
2945
3003
|
log2("info", `[debug] forwarded body written to ${out}`);
|
|
2946
3004
|
}
|