billion-context 0.1.135-pr.1107.995 → 0.1.135
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/dist/index.js +1997 -1993
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -52435,8 +52435,8 @@ import { createHash as createHash5 } from "crypto";
|
|
|
52435
52435
|
|
|
52436
52436
|
// src/persist.ts
|
|
52437
52437
|
import { createHash as createHash4 } from "crypto";
|
|
52438
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
52439
|
-
import { readdir, rm } from "fs/promises";
|
|
52438
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
52439
|
+
import { open, readdir, readFile as readFile2, rm } from "fs/promises";
|
|
52440
52440
|
import * as path7 from "path";
|
|
52441
52441
|
|
|
52442
52442
|
// node_modules/acp-kernel/dist/persist/index.js
|
|
@@ -52878,1855 +52878,1183 @@ function rel(p2, base) {
|
|
|
52878
52878
|
// src/encrypt.ts
|
|
52879
52879
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
52880
52880
|
import * as zlib from "zlib";
|
|
52881
|
-
|
|
52882
|
-
|
|
52883
|
-
var
|
|
52884
|
-
var
|
|
52885
|
-
var
|
|
52886
|
-
var
|
|
52887
|
-
var
|
|
52888
|
-
var
|
|
52889
|
-
|
|
52890
|
-
|
|
52891
|
-
|
|
52892
|
-
|
|
52893
|
-
|
|
52894
|
-
|
|
52895
|
-
|
|
52896
|
-
n.set(v2.subarray(s3, e));
|
|
52897
|
-
return n;
|
|
52898
|
-
};
|
|
52899
|
-
var fill = function(v2, n, s3, e) {
|
|
52900
|
-
if (u8.prototype.fill)
|
|
52901
|
-
return u8.prototype.fill.call(v2, n, s3, e);
|
|
52902
|
-
if (s3 == null || s3 < 0)
|
|
52903
|
-
s3 = 0;
|
|
52904
|
-
if (e == null || e > v2.length)
|
|
52905
|
-
e = v2.length;
|
|
52906
|
-
for (; s3 < e; ++s3)
|
|
52907
|
-
v2[s3] = n;
|
|
52908
|
-
return v2;
|
|
52909
|
-
};
|
|
52910
|
-
var cpw = function(v2, t, s3, e) {
|
|
52911
|
-
if (u8.prototype.copyWithin)
|
|
52912
|
-
return u8.prototype.copyWithin.call(v2, t, s3, e);
|
|
52913
|
-
if (s3 == null || s3 < 0)
|
|
52914
|
-
s3 = 0;
|
|
52915
|
-
if (e == null || e > v2.length)
|
|
52916
|
-
e = v2.length;
|
|
52917
|
-
while (s3 < e) {
|
|
52918
|
-
v2[t++] = v2[s3++];
|
|
52881
|
+
var ENCRYPT_MAGIC = Buffer.from("BILIENC1", "utf8");
|
|
52882
|
+
var FORMAT_VERSION = 1;
|
|
52883
|
+
var MODE_RAW = 0;
|
|
52884
|
+
var MODE_ZSTD = 1;
|
|
52885
|
+
var NONCE_LEN = 12;
|
|
52886
|
+
var TAG_LEN = 16;
|
|
52887
|
+
var HEADER_LEN = ENCRYPT_MAGIC.length + 2 + NONCE_LEN;
|
|
52888
|
+
var MIN_ENCRYPTED_LEN = HEADER_LEN + TAG_LEN;
|
|
52889
|
+
function parseEncryptionKey(value) {
|
|
52890
|
+
const v2 = value.trim();
|
|
52891
|
+
let buf = null;
|
|
52892
|
+
if (/^[0-9a-fA-F]+$/.test(v2) && v2.length % 2 === 0) {
|
|
52893
|
+
buf = Buffer.from(v2, "hex");
|
|
52894
|
+
} else if (/^[A-Za-z0-9+/]+={0,2}$/.test(v2)) {
|
|
52895
|
+
buf = Buffer.from(v2, "base64");
|
|
52919
52896
|
}
|
|
52920
|
-
|
|
52921
|
-
|
|
52922
|
-
|
|
52923
|
-
|
|
52924
|
-
|
|
52925
|
-
"FSE accuracy too high",
|
|
52926
|
-
"match distance too far back",
|
|
52927
|
-
"unexpected EOF"
|
|
52928
|
-
];
|
|
52929
|
-
var err = function(ind, msg, nt2) {
|
|
52930
|
-
var e = new Error(msg || ec[ind]);
|
|
52931
|
-
e.code = ind;
|
|
52932
|
-
if (Error.captureStackTrace)
|
|
52933
|
-
Error.captureStackTrace(e, err);
|
|
52934
|
-
if (!nt2)
|
|
52935
|
-
throw e;
|
|
52936
|
-
return e;
|
|
52937
|
-
};
|
|
52938
|
-
var rb = function(d, b2, n) {
|
|
52939
|
-
var i = 0, o = 0;
|
|
52940
|
-
for (; i < n; ++i)
|
|
52941
|
-
o |= d[b2++] << (i << 3);
|
|
52942
|
-
return o;
|
|
52943
|
-
};
|
|
52944
|
-
var b4 = function(d, b2) {
|
|
52945
|
-
return (d[b2] | d[b2 + 1] << 8 | d[b2 + 2] << 16 | d[b2 + 3] << 24) >>> 0;
|
|
52946
|
-
};
|
|
52947
|
-
var rzfh = function(dat, w2) {
|
|
52948
|
-
var n3 = dat[0] | dat[1] << 8 | dat[2] << 16;
|
|
52949
|
-
if (n3 == 3126568 && dat[3] == 253) {
|
|
52950
|
-
var flg = dat[4];
|
|
52951
|
-
var ss2 = flg >> 5 & 1, cc = flg >> 2 & 1, df = flg & 3, fcf = flg >> 6;
|
|
52952
|
-
if (flg & 8)
|
|
52953
|
-
err(0);
|
|
52954
|
-
var bt2 = 6 - ss2;
|
|
52955
|
-
var db = df == 3 ? 4 : df;
|
|
52956
|
-
var di2 = rb(dat, bt2, db);
|
|
52957
|
-
bt2 += db;
|
|
52958
|
-
var fsb = fcf ? 1 << fcf : ss2;
|
|
52959
|
-
var fss = rb(dat, bt2, fsb) + (fcf == 1 && 256);
|
|
52960
|
-
var ws2 = fss;
|
|
52961
|
-
if (!ss2) {
|
|
52962
|
-
var wb = 1 << 10 + (dat[5] >> 3);
|
|
52963
|
-
ws2 = wb + (wb >> 3) * (dat[5] & 7);
|
|
52964
|
-
}
|
|
52965
|
-
if (ws2 > 2145386496)
|
|
52966
|
-
err(1);
|
|
52967
|
-
var buf = new u8((w2 == 1 ? fss || ws2 : w2 ? 0 : ws2) + 12);
|
|
52968
|
-
buf[0] = 1, buf[4] = 4, buf[8] = 8;
|
|
52969
|
-
return {
|
|
52970
|
-
b: bt2 + fsb,
|
|
52971
|
-
y: 0,
|
|
52972
|
-
l: 0,
|
|
52973
|
-
d: di2,
|
|
52974
|
-
w: w2 && w2 != 1 ? w2 : buf.subarray(12),
|
|
52975
|
-
e: ws2,
|
|
52976
|
-
o: new i32(buf.buffer, 0, 3),
|
|
52977
|
-
u: fss,
|
|
52978
|
-
c: cc,
|
|
52979
|
-
m: Math.min(131072, ws2)
|
|
52980
|
-
};
|
|
52981
|
-
} else if ((n3 >> 4 | dat[3] << 20) == 25481893) {
|
|
52982
|
-
return b4(dat, 4) + 8;
|
|
52897
|
+
if (!buf || buf.length !== 32) {
|
|
52898
|
+
const got = buf ? `${buf.length} bytes` : "an undecodable value";
|
|
52899
|
+
throw new Error(
|
|
52900
|
+
`[encrypt] BILI_ENCRYPTION_KEY must be exactly 32 bytes encoded as hex (64 chars) or base64 \u2014 got ${got}`
|
|
52901
|
+
);
|
|
52983
52902
|
}
|
|
52984
|
-
|
|
52985
|
-
}
|
|
52986
|
-
|
|
52987
|
-
|
|
52988
|
-
|
|
52989
|
-
|
|
52990
|
-
return
|
|
52991
|
-
|
|
52992
|
-
|
|
52993
|
-
|
|
52994
|
-
|
|
52995
|
-
|
|
52996
|
-
|
|
52997
|
-
|
|
52998
|
-
|
|
52999
|
-
|
|
53000
|
-
|
|
53001
|
-
|
|
53002
|
-
|
|
53003
|
-
|
|
53004
|
-
|
|
53005
|
-
|
|
53006
|
-
|
|
53007
|
-
|
|
53008
|
-
|
|
53009
|
-
|
|
53010
|
-
|
|
53011
|
-
|
|
53012
|
-
|
|
53013
|
-
|
|
53014
|
-
|
|
53015
|
-
|
|
53016
|
-
|
|
53017
|
-
|
|
53018
|
-
|
|
53019
|
-
|
|
53020
|
-
|
|
53021
|
-
|
|
53022
|
-
if (val == -1) {
|
|
53023
|
-
probs += val;
|
|
53024
|
-
syms[--ht2] = sym;
|
|
53025
|
-
} else
|
|
53026
|
-
probs -= val;
|
|
53027
|
-
if (!val) {
|
|
53028
|
-
do {
|
|
53029
|
-
var rbt = tpos >> 3;
|
|
53030
|
-
re2 = (dat[rbt] | dat[rbt + 1] << 8) >> (tpos & 7) & 3;
|
|
53031
|
-
tpos += 2;
|
|
53032
|
-
sym += re2;
|
|
53033
|
-
} while (re2 == 3);
|
|
52903
|
+
return buf;
|
|
52904
|
+
}
|
|
52905
|
+
function zstdAvailable() {
|
|
52906
|
+
return typeof zlib.zstdCompressSync === "function" && typeof zlib.zstdDecompressSync === "function";
|
|
52907
|
+
}
|
|
52908
|
+
function createSessionCodec(key) {
|
|
52909
|
+
return {
|
|
52910
|
+
encode(data) {
|
|
52911
|
+
const plain = Buffer.from(data, "utf8");
|
|
52912
|
+
const useZstd = zstdAvailable();
|
|
52913
|
+
const body = useZstd ? zlib.zstdCompressSync(plain) : plain;
|
|
52914
|
+
const nonce = randomBytes(NONCE_LEN);
|
|
52915
|
+
const cipher = createCipheriv("aes-256-gcm", key, nonce);
|
|
52916
|
+
const ct2 = Buffer.concat([cipher.update(body), cipher.final()]);
|
|
52917
|
+
return Buffer.concat([
|
|
52918
|
+
ENCRYPT_MAGIC,
|
|
52919
|
+
Buffer.from([FORMAT_VERSION, useZstd ? MODE_ZSTD : MODE_RAW]),
|
|
52920
|
+
nonce,
|
|
52921
|
+
ct2,
|
|
52922
|
+
cipher.getAuthTag()
|
|
52923
|
+
]);
|
|
52924
|
+
},
|
|
52925
|
+
decode(buf) {
|
|
52926
|
+
if (buf.length < ENCRYPT_MAGIC.length || !buf.subarray(0, ENCRYPT_MAGIC.length).equals(ENCRYPT_MAGIC)) {
|
|
52927
|
+
return buf.toString("utf8");
|
|
52928
|
+
}
|
|
52929
|
+
if (buf.length < MIN_ENCRYPTED_LEN || buf[ENCRYPT_MAGIC.length] !== FORMAT_VERSION) {
|
|
52930
|
+
throw new Error(`[encrypt] unsupported session file format version ${buf[ENCRYPT_MAGIC.length]}`);
|
|
52931
|
+
}
|
|
52932
|
+
const mode = buf[ENCRYPT_MAGIC.length + 1];
|
|
52933
|
+
const nonce = buf.subarray(HEADER_LEN - NONCE_LEN, HEADER_LEN);
|
|
52934
|
+
const tag = buf.subarray(buf.length - TAG_LEN);
|
|
52935
|
+
const ct2 = buf.subarray(HEADER_LEN, buf.length - TAG_LEN);
|
|
52936
|
+
const decipher = createDecipheriv("aes-256-gcm", key, nonce);
|
|
52937
|
+
decipher.setAuthTag(tag);
|
|
52938
|
+
const body = Buffer.concat([decipher.update(ct2), decipher.final()]);
|
|
52939
|
+
const plain = mode === MODE_ZSTD ? zlib.zstdDecompressSync(body) : body;
|
|
52940
|
+
return plain.toString("utf8");
|
|
53034
52941
|
}
|
|
52942
|
+
};
|
|
52943
|
+
}
|
|
52944
|
+
|
|
52945
|
+
// src/persist-eperm.ts
|
|
52946
|
+
var LOCK_CODES = /\b(EPERM|EBUSY|EACCES)\b/;
|
|
52947
|
+
var WRITE_FAIL_RE = /^\[persist\] write failed for (.+?) \(total (\d+)x\): (.+)$/;
|
|
52948
|
+
var PersistEpermAlert = class {
|
|
52949
|
+
dir;
|
|
52950
|
+
threshold;
|
|
52951
|
+
repeatMs;
|
|
52952
|
+
platform;
|
|
52953
|
+
now;
|
|
52954
|
+
onAlert;
|
|
52955
|
+
hasAlerted = false;
|
|
52956
|
+
alertedAt = 0;
|
|
52957
|
+
constructor(opts) {
|
|
52958
|
+
this.dir = opts.dir;
|
|
52959
|
+
this.threshold = opts.threshold ?? 5;
|
|
52960
|
+
this.repeatMs = opts.repeatMs ?? 0;
|
|
52961
|
+
this.platform = opts.platform ?? process.platform;
|
|
52962
|
+
this.now = opts.now ?? Date.now;
|
|
52963
|
+
this.onAlert = opts.onAlert ?? ((d, c) => log("warn", buildAlertMessage(d, c)));
|
|
53035
52964
|
}
|
|
53036
|
-
|
|
53037
|
-
|
|
53038
|
-
|
|
53039
|
-
|
|
53040
|
-
|
|
53041
|
-
|
|
53042
|
-
|
|
53043
|
-
|
|
53044
|
-
|
|
53045
|
-
|
|
53046
|
-
|
|
53047
|
-
|
|
53048
|
-
|
|
53049
|
-
|
|
53050
|
-
|
|
53051
|
-
} while (sympos >= ht2);
|
|
53052
|
-
}
|
|
52965
|
+
// Returns true iff an alert was emitted. Runs on every kernel log line, so
|
|
52966
|
+
// the non-matching cases bail before any allocation.
|
|
52967
|
+
observe(level, msg) {
|
|
52968
|
+
if (this.platform !== "win32") return false;
|
|
52969
|
+
if (level !== "error" && level !== "warn") return false;
|
|
52970
|
+
const m2 = WRITE_FAIL_RE.exec(msg);
|
|
52971
|
+
if (!m2) return false;
|
|
52972
|
+
const count = Number(m2[2]);
|
|
52973
|
+
if (count < this.threshold) return false;
|
|
52974
|
+
if (!LOCK_CODES.test(m2[3])) return false;
|
|
52975
|
+
if (!this.shouldAlert()) return false;
|
|
52976
|
+
this.hasAlerted = true;
|
|
52977
|
+
this.alertedAt = this.now();
|
|
52978
|
+
this.onAlert(this.dir, count);
|
|
52979
|
+
return true;
|
|
53053
52980
|
}
|
|
53054
|
-
|
|
53055
|
-
|
|
53056
|
-
|
|
53057
|
-
|
|
53058
|
-
var nb = nbits[i] = al - msb(ns2);
|
|
53059
|
-
nstate[i] = (ns2 << nb) - sz;
|
|
52981
|
+
shouldAlert() {
|
|
52982
|
+
if (!this.hasAlerted) return true;
|
|
52983
|
+
if (this.repeatMs <= 0) return false;
|
|
52984
|
+
return this.now() - this.alertedAt >= this.repeatMs;
|
|
53060
52985
|
}
|
|
53061
|
-
return [tpos + 7 >> 3, {
|
|
53062
|
-
b: al,
|
|
53063
|
-
s: syms,
|
|
53064
|
-
n: nbits,
|
|
53065
|
-
t: nstate
|
|
53066
|
-
}];
|
|
53067
52986
|
};
|
|
53068
|
-
|
|
53069
|
-
|
|
53070
|
-
|
|
53071
|
-
|
|
53072
|
-
|
|
53073
|
-
|
|
53074
|
-
|
|
53075
|
-
|
|
53076
|
-
|
|
53077
|
-
|
|
53078
|
-
|
|
53079
|
-
|
|
53080
|
-
|
|
53081
|
-
|
|
53082
|
-
|
|
53083
|
-
|
|
53084
|
-
|
|
53085
|
-
|
|
53086
|
-
|
|
53087
|
-
|
|
53088
|
-
|
|
53089
|
-
|
|
53090
|
-
|
|
53091
|
-
|
|
53092
|
-
|
|
53093
|
-
|
|
53094
|
-
|
|
53095
|
-
|
|
53096
|
-
|
|
53097
|
-
|
|
53098
|
-
|
|
53099
|
-
|
|
52987
|
+
function buildAlertMessage(dir, count) {
|
|
52988
|
+
return [
|
|
52989
|
+
`[persist] session dir ${dir} failed ${count} consecutive writes (EPERM \u2014 rename is locked).`,
|
|
52990
|
+
"Likely cause: Windows Defender / antivirus / indexer / a sync tool is locking the directory.",
|
|
52991
|
+
`Fix: add ${dir} to Windows Defender exclusions (Settings \u2192 Virus & threat protection \u2192 Manage settings \u2192 Exclusions \u2192 Add an exclusion),`,
|
|
52992
|
+
"and make sure no OneDrive / sync tool is syncing this path."
|
|
52993
|
+
].join("\n");
|
|
52994
|
+
}
|
|
52995
|
+
|
|
52996
|
+
// src/persist.ts
|
|
52997
|
+
var PERSIST_VERSION = 3;
|
|
52998
|
+
var MIGRATION_MARKER = ".bili-migration-286.done";
|
|
52999
|
+
var STALE_WARN_THROTTLE_MS = 6e4;
|
|
53000
|
+
function mergeState(parsed) {
|
|
53001
|
+
const fresh = createInitialState();
|
|
53002
|
+
return {
|
|
53003
|
+
blocks: parsed.blocks ?? fresh.blocks,
|
|
53004
|
+
messageRefs: parsed.messageRefs ?? fresh.messageRefs,
|
|
53005
|
+
nudge: { ...fresh.nudge, ...parsed.nudge ?? {} },
|
|
53006
|
+
stats: { ...fresh.stats, ...parsed.stats ?? {} },
|
|
53007
|
+
nextBlockId: parsed.nextBlockId ?? fresh.nextBlockId,
|
|
53008
|
+
nextRunId: parsed.nextRunId ?? fresh.nextRunId,
|
|
53009
|
+
tokenSnapshot: parsed.tokenSnapshot ?? fresh.tokenSnapshot,
|
|
53010
|
+
// Without this, a restart re-exposes absorbed tool outputs: state
|
|
53011
|
+
// resurrects with absorbed=[] and hideAbsorbedMessages has nothing to hide.
|
|
53012
|
+
absorbed: parsed.absorbed ?? fresh.absorbed,
|
|
53013
|
+
rules: parsed.rules ?? fresh.rules
|
|
53014
|
+
};
|
|
53015
|
+
}
|
|
53016
|
+
function hostLabel(upstreamOrigin) {
|
|
53017
|
+
if (!upstreamOrigin) return "unknown";
|
|
53018
|
+
try {
|
|
53019
|
+
const host = new URL(upstreamOrigin).hostname || "unknown";
|
|
53020
|
+
return host.replace(/[^a-zA-Z0-9.-]/g, "-").slice(0, 48) || "unknown";
|
|
53021
|
+
} catch {
|
|
53022
|
+
return "unknown-" + createHash4("sha256").update(upstreamOrigin, "utf8").digest("hex").slice(0, 6);
|
|
53023
|
+
}
|
|
53024
|
+
}
|
|
53025
|
+
function relPathFor(id, protocol, upstreamOrigin) {
|
|
53026
|
+
const proto = protocol ?? "_unknown";
|
|
53027
|
+
const host = protocol ? hostLabel(upstreamOrigin) + "_" : "";
|
|
53028
|
+
return path7.join(proto, `${host}${createHash4("sha256").update(id, "utf8").digest("hex").slice(0, 24)}.json`);
|
|
53029
|
+
}
|
|
53030
|
+
var SessionStore = class {
|
|
53031
|
+
enabled;
|
|
53032
|
+
dir;
|
|
53033
|
+
store;
|
|
53034
|
+
log;
|
|
53035
|
+
staleWarnAt = /* @__PURE__ */ new Map();
|
|
53036
|
+
codec;
|
|
53037
|
+
constructor(opts) {
|
|
53038
|
+
const debounceMs = opts?.debounceMs ?? defaultDebounce();
|
|
53039
|
+
this.enabled = (opts?.enabled ?? true) && debounceMs >= 0;
|
|
53040
|
+
this.dir = opts?.dir ?? defaultDir();
|
|
53041
|
+
const baseLog = opts?.log ?? defaultLogger;
|
|
53042
|
+
this.log = baseLog;
|
|
53043
|
+
const keyEnv = process.env.BILI_ENCRYPTION_KEY;
|
|
53044
|
+
if (keyEnv) {
|
|
53045
|
+
this.codec = createSessionCodec(parseEncryptionKey(keyEnv));
|
|
53046
|
+
baseLog("info", "[persist] session-file encryption enabled (AES-256-GCM)");
|
|
53100
53047
|
}
|
|
53101
|
-
|
|
53102
|
-
|
|
53103
|
-
|
|
53104
|
-
|
|
53105
|
-
|
|
53106
|
-
|
|
53107
|
-
|
|
53108
|
-
|
|
53048
|
+
const epermAlert = new PersistEpermAlert({
|
|
53049
|
+
dir: this.dir,
|
|
53050
|
+
threshold: epermAlertThreshold(),
|
|
53051
|
+
repeatMs: epermAlertRepeatMs()
|
|
53052
|
+
});
|
|
53053
|
+
this.store = new StateStore({
|
|
53054
|
+
dir: this.dir,
|
|
53055
|
+
version: PERSIST_VERSION,
|
|
53056
|
+
debounceMs: Math.max(0, debounceMs),
|
|
53057
|
+
enabled: this.enabled,
|
|
53058
|
+
codec: this.codec,
|
|
53059
|
+
log: (level, msg) => {
|
|
53060
|
+
epermAlert.observe(level, msg);
|
|
53061
|
+
baseLog(level, msg);
|
|
53062
|
+
},
|
|
53063
|
+
relPath: (id, payload) => relPathFor(id, payload.meta?.protocol ?? payload.protocol, payload.meta?.upstreamOrigin ?? payload.upstreamOrigin),
|
|
53064
|
+
// Adopt the pre-envelope flat format this store itself wrote
|
|
53065
|
+
// before the kernel extraction (and every v1/v2 file before it).
|
|
53066
|
+
legacy: (parsed) => isValidRecord(parsed) ? { id: parsed.id, payload: parsed, version: parsed.version, savedAt: parsed.savedAt } : null,
|
|
53067
|
+
validate: (envelope) => isValidRecord(envelope.payload)
|
|
53068
|
+
});
|
|
53069
|
+
}
|
|
53070
|
+
/** Bulk-load every persisted session from disk into a map keyed by the
|
|
53071
|
+
* REAL session id (read from the file body, not the filename). Called once
|
|
53072
|
+
* at startup before the server accepts traffic. Corrupt individual files
|
|
53073
|
+
* are skipped (logged) — one bad file never blocks boot. */
|
|
53074
|
+
async loadAll() {
|
|
53075
|
+
const out = /* @__PURE__ */ new Map();
|
|
53076
|
+
if (!this.enabled) return out;
|
|
53077
|
+
let clamped = 0;
|
|
53078
|
+
for (const [id, envelope] of await this.store.loadAll()) {
|
|
53079
|
+
const session = buildSession(envelope.payload);
|
|
53080
|
+
if (hasNegativePersistedTokens(envelope.payload)) {
|
|
53081
|
+
await this.store.writeNow(id, () => buildRecord(session));
|
|
53082
|
+
clamped++;
|
|
53083
|
+
}
|
|
53084
|
+
out.set(id, session);
|
|
53109
53085
|
}
|
|
53110
|
-
|
|
53086
|
+
if (clamped > 0) {
|
|
53087
|
+
log("info", `[persist] one-time migration (#408): clamped negative lastInputTokens/contextTokens in ${clamped} session(s) to 0`);
|
|
53088
|
+
}
|
|
53089
|
+
return out;
|
|
53111
53090
|
}
|
|
53112
|
-
|
|
53113
|
-
|
|
53114
|
-
|
|
53115
|
-
|
|
53116
|
-
|
|
53117
|
-
|
|
53091
|
+
/** Single-pass boot (#401): ONE loadAll walk+parse, then the #286
|
|
53092
|
+
* identity migration over the SAME parsed map (no extra directory
|
|
53093
|
+
* walk), then hydration into Sessions. initSessions calls this instead
|
|
53094
|
+
* of migrateLegacyIds()+loadAll(), which walked and parsed the whole
|
|
53095
|
+
* tree twice per start. */
|
|
53096
|
+
async boot() {
|
|
53097
|
+
if (!this.enabled) return /* @__PURE__ */ new Map();
|
|
53098
|
+
await this.migrateLegacyFiles();
|
|
53099
|
+
const loaded = await this.store.loadAll();
|
|
53100
|
+
await this.applyLegacyMigration(loaded);
|
|
53101
|
+
const out = /* @__PURE__ */ new Map();
|
|
53102
|
+
for (const [id, envelope] of loaded) {
|
|
53103
|
+
out.set(id, buildSession(envelope.payload));
|
|
53104
|
+
}
|
|
53105
|
+
return out;
|
|
53118
53106
|
}
|
|
53119
|
-
|
|
53120
|
-
|
|
53121
|
-
|
|
53122
|
-
|
|
53123
|
-
|
|
53124
|
-
|
|
53125
|
-
|
|
53126
|
-
|
|
53127
|
-
|
|
53107
|
+
/** #708: when encryption is enabled, take over legacy plaintext files:
|
|
53108
|
+
* every .json under the sessions dir lacking the BILIENC1 magic is
|
|
53109
|
+
* re-encoded in place — temp write + rename onto the SAME path, so the
|
|
53110
|
+
* atomic replace IS the old-file deletion (no window where both, or
|
|
53111
|
+
* neither, copy exists). A crash mid-run leaves each file either old or
|
|
53112
|
+
* new; the next boot finishes the job and sweeps the crashed run's
|
|
53113
|
+
* orphaned temps. Self-terminating: the 8-byte magic peek decides per
|
|
53114
|
+
* file, so later boots cost O(files × 8 bytes). */
|
|
53115
|
+
async migrateLegacyFiles() {
|
|
53116
|
+
if (!this.codec) return;
|
|
53117
|
+
let files;
|
|
53118
|
+
try {
|
|
53119
|
+
files = await walkJsonFiles(this.dir);
|
|
53120
|
+
} catch {
|
|
53121
|
+
return;
|
|
53122
|
+
}
|
|
53123
|
+
let migrated = 0;
|
|
53124
|
+
let failed = 0;
|
|
53125
|
+
for (const file of files) {
|
|
53126
|
+
if (STALE_ENC_TEMP_RE.test(path7.basename(file))) {
|
|
53127
|
+
await rm(file, { force: true }).catch(() => {
|
|
53128
|
+
});
|
|
53129
|
+
continue;
|
|
53130
|
+
}
|
|
53131
|
+
let head;
|
|
53132
|
+
try {
|
|
53133
|
+
head = await readFileHead(file);
|
|
53134
|
+
} catch {
|
|
53135
|
+
continue;
|
|
53136
|
+
}
|
|
53137
|
+
if (head.equals(ENCRYPT_MAGIC)) continue;
|
|
53138
|
+
let parsed;
|
|
53139
|
+
try {
|
|
53140
|
+
parsed = JSON.parse(await readFile2(file, "utf8"));
|
|
53141
|
+
} catch {
|
|
53142
|
+
failed++;
|
|
53143
|
+
this.log("warn", `[persist] encryption migration (#708): leaving unreadable file in place: ${file}`);
|
|
53144
|
+
continue;
|
|
53145
|
+
}
|
|
53146
|
+
const tmp = `${file}.tmp-enc-${process.pid}-${Date.now()}`;
|
|
53147
|
+
try {
|
|
53148
|
+
writeFileSync2(tmp, this.codec.encode(JSON.stringify(parsed)));
|
|
53149
|
+
renameSync2(tmp, file);
|
|
53150
|
+
migrated++;
|
|
53151
|
+
} catch {
|
|
53152
|
+
failed++;
|
|
53153
|
+
this.log("warn", `[persist] encryption migration (#708): failed to re-encode: ${file}`);
|
|
53154
|
+
await rm(tmp, { force: true }).catch(() => {
|
|
53155
|
+
});
|
|
53156
|
+
}
|
|
53157
|
+
}
|
|
53158
|
+
if (migrated > 0 || failed > 0) {
|
|
53159
|
+
this.log(
|
|
53160
|
+
failed > 0 ? "warn" : "info",
|
|
53161
|
+
`[persist] encryption migration (#708): re-encoded ${migrated} legacy session file(s)${failed > 0 ? `, ${failed} failed` : ""}`
|
|
53162
|
+
);
|
|
53163
|
+
}
|
|
53128
53164
|
}
|
|
53129
|
-
|
|
53130
|
-
|
|
53131
|
-
|
|
53132
|
-
|
|
53133
|
-
|
|
53134
|
-
|
|
53165
|
+
/** One-time migration for the #286 identity change: sessions persisted
|
|
53166
|
+
* under the old derived hash id are re-keyed to the client-provided
|
|
53167
|
+
* conversation value stored in meta.label (which is now the session id
|
|
53168
|
+
* itself). Collisions on the same label keep the most recently saved
|
|
53169
|
+
* record; the losers, and any label already claimed by a new-format
|
|
53170
|
+
* session, are deleted. Records without a label cannot be mapped and are
|
|
53171
|
+
* left in place (they load under their old id but are never requested
|
|
53172
|
+
* again — the new proxy 400s anonymous requests). Self-terminating:
|
|
53173
|
+
* after one pass no loaded id differs from its label. A completion
|
|
53174
|
+
* marker makes it run ONCE EVER (#401): the old code re-scanned the tree
|
|
53175
|
+
* on every boot because unlabeled files are intentionally kept, so the
|
|
53176
|
+
* "one-time" log line repeated forever. */
|
|
53177
|
+
async migrateLegacyIds() {
|
|
53178
|
+
if (!this.enabled) return;
|
|
53179
|
+
if (existsSync3(this.markerPath())) return;
|
|
53180
|
+
const loaded = await this.store.loadAll();
|
|
53181
|
+
await this.applyLegacyMigration(loaded);
|
|
53135
53182
|
}
|
|
53136
|
-
|
|
53137
|
-
|
|
53138
|
-
for (i = 0; i < wc; ++i) {
|
|
53139
|
-
var bits = hw[i];
|
|
53140
|
-
if (bits) {
|
|
53141
|
-
var code = ri2[bits];
|
|
53142
|
-
fill(syms, i, code, ri2[bits] = code + (1 << mb - bits));
|
|
53143
|
-
}
|
|
53183
|
+
markerPath() {
|
|
53184
|
+
return path7.join(this.dir, MIGRATION_MARKER);
|
|
53144
53185
|
}
|
|
53145
|
-
|
|
53146
|
-
|
|
53147
|
-
|
|
53148
|
-
|
|
53149
|
-
|
|
53150
|
-
|
|
53151
|
-
|
|
53152
|
-
|
|
53153
|
-
|
|
53154
|
-
|
|
53155
|
-
|
|
53156
|
-
|
|
53157
|
-
|
|
53158
|
-
|
|
53159
|
-
|
|
53160
|
-
|
|
53161
|
-
|
|
53162
|
-
|
|
53163
|
-
|
|
53164
|
-
|
|
53165
|
-
|
|
53166
|
-
|
|
53167
|
-
|
|
53168
|
-
|
|
53169
|
-
|
|
53170
|
-
|
|
53171
|
-
|
|
53172
|
-
|
|
53173
|
-
|
|
53174
|
-
|
|
53175
|
-
|
|
53176
|
-
|
|
53177
|
-
|
|
53178
|
-
|
|
53179
|
-
|
|
53180
|
-
|
|
53181
|
-
|
|
53182
|
-
|
|
53183
|
-
|
|
53184
|
-
|
|
53185
|
-
|
|
53186
|
-
|
|
53187
|
-
|
|
53188
|
-
|
|
53189
|
-
|
|
53190
|
-
|
|
53191
|
-
|
|
53192
|
-
|
|
53193
|
-
|
|
53194
|
-
|
|
53195
|
-
|
|
53196
|
-
|
|
53197
|
-
|
|
53198
|
-
|
|
53199
|
-
9
|
|
53200
|
-
]), 0, 6)[1];
|
|
53201
|
-
var doct = rfse(/* @__PURE__ */ new u8([
|
|
53202
|
-
32,
|
|
53203
|
-
132,
|
|
53204
|
-
16,
|
|
53205
|
-
66,
|
|
53206
|
-
102,
|
|
53207
|
-
70,
|
|
53208
|
-
68,
|
|
53209
|
-
68,
|
|
53210
|
-
68,
|
|
53211
|
-
68,
|
|
53212
|
-
36,
|
|
53213
|
-
73,
|
|
53214
|
-
2
|
|
53215
|
-
]), 0, 5)[1];
|
|
53216
|
-
var b2bl = function(b2, s3) {
|
|
53217
|
-
var len = b2.length, bl = new i32(len);
|
|
53218
|
-
for (var i = 0; i < len; ++i) {
|
|
53219
|
-
bl[i] = s3;
|
|
53220
|
-
s3 += 1 << b2[i];
|
|
53221
|
-
}
|
|
53222
|
-
return bl;
|
|
53223
|
-
};
|
|
53224
|
-
var llb = /* @__PURE__ */ new u8((/* @__PURE__ */ new i32([
|
|
53225
|
-
0,
|
|
53226
|
-
0,
|
|
53227
|
-
0,
|
|
53228
|
-
0,
|
|
53229
|
-
16843009,
|
|
53230
|
-
50528770,
|
|
53231
|
-
134678020,
|
|
53232
|
-
202050057,
|
|
53233
|
-
269422093
|
|
53234
|
-
])).buffer, 0, 36);
|
|
53235
|
-
var llbl = /* @__PURE__ */ b2bl(llb, 0);
|
|
53236
|
-
var mlb = /* @__PURE__ */ new u8((/* @__PURE__ */ new i32([
|
|
53237
|
-
0,
|
|
53238
|
-
0,
|
|
53239
|
-
0,
|
|
53240
|
-
0,
|
|
53241
|
-
0,
|
|
53242
|
-
0,
|
|
53243
|
-
0,
|
|
53244
|
-
0,
|
|
53245
|
-
16843009,
|
|
53246
|
-
50528770,
|
|
53247
|
-
117769220,
|
|
53248
|
-
185207048,
|
|
53249
|
-
252579084,
|
|
53250
|
-
16
|
|
53251
|
-
])).buffer, 0, 53);
|
|
53252
|
-
var mlbl = /* @__PURE__ */ b2bl(mlb, 3);
|
|
53253
|
-
var dhu = function(dat, out, hu) {
|
|
53254
|
-
var len = dat.length, ss2 = out.length, lb = dat[len - 1], msk = (1 << hu.b) - 1, eb = -hu.b;
|
|
53255
|
-
if (!lb)
|
|
53256
|
-
err(0);
|
|
53257
|
-
var st2 = 0, btr = hu.b, pos = (len << 3) - 8 + msb(lb) - btr, i = -1;
|
|
53258
|
-
for (; pos > eb && i < ss2; ) {
|
|
53259
|
-
var cbt = pos >> 3;
|
|
53260
|
-
var val = (dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (pos & 7);
|
|
53261
|
-
st2 = (st2 << btr | val) & msk;
|
|
53262
|
-
out[++i] = hu.s[st2];
|
|
53263
|
-
pos -= btr = hu.n[st2];
|
|
53264
|
-
}
|
|
53265
|
-
if (pos != eb || i + 1 != ss2)
|
|
53266
|
-
err(0);
|
|
53267
|
-
};
|
|
53268
|
-
var dhu4 = function(dat, out, hu) {
|
|
53269
|
-
var bt2 = 6;
|
|
53270
|
-
var ss2 = out.length, sz1 = ss2 + 3 >> 2, sz2 = sz1 << 1, sz3 = sz1 + sz2;
|
|
53271
|
-
dhu(dat.subarray(bt2, bt2 += dat[0] | dat[1] << 8), out.subarray(0, sz1), hu);
|
|
53272
|
-
dhu(dat.subarray(bt2, bt2 += dat[2] | dat[3] << 8), out.subarray(sz1, sz2), hu);
|
|
53273
|
-
dhu(dat.subarray(bt2, bt2 += dat[4] | dat[5] << 8), out.subarray(sz2, sz3), hu);
|
|
53274
|
-
dhu(dat.subarray(bt2), out.subarray(sz3), hu);
|
|
53275
|
-
};
|
|
53276
|
-
var rzb = function(dat, st2, out) {
|
|
53277
|
-
var _a;
|
|
53278
|
-
var bt2 = st2.b;
|
|
53279
|
-
var b0 = dat[bt2], btype = b0 >> 1 & 3;
|
|
53280
|
-
st2.l = b0 & 1;
|
|
53281
|
-
var sz = b0 >> 3 | dat[bt2 + 1] << 5 | dat[bt2 + 2] << 13;
|
|
53282
|
-
var ebt = (bt2 += 3) + sz;
|
|
53283
|
-
if (btype == 1) {
|
|
53284
|
-
if (bt2 >= dat.length)
|
|
53285
|
-
return;
|
|
53286
|
-
st2.b = bt2 + 1;
|
|
53287
|
-
if (out) {
|
|
53288
|
-
fill(out, dat[bt2], st2.y, st2.y += sz);
|
|
53289
|
-
return out;
|
|
53186
|
+
async applyLegacyMigration(loaded) {
|
|
53187
|
+
if (existsSync3(this.markerPath())) return;
|
|
53188
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
53189
|
+
const byLabel = /* @__PURE__ */ new Map();
|
|
53190
|
+
let unlabeled = 0;
|
|
53191
|
+
for (const [id, envelope] of loaded) {
|
|
53192
|
+
if (id.startsWith("pfa-")) continue;
|
|
53193
|
+
const session = buildSession(envelope.payload);
|
|
53194
|
+
const label = session.meta.label;
|
|
53195
|
+
if (!label) {
|
|
53196
|
+
unlabeled++;
|
|
53197
|
+
continue;
|
|
53198
|
+
}
|
|
53199
|
+
if (label === id) {
|
|
53200
|
+
claimed.add(id);
|
|
53201
|
+
continue;
|
|
53202
|
+
}
|
|
53203
|
+
const prev = byLabel.get(label);
|
|
53204
|
+
if (!prev || envelope.savedAt >= prev.savedAt) {
|
|
53205
|
+
if (prev) {
|
|
53206
|
+
await this.removeLegacyFile(prev.id, prev.session);
|
|
53207
|
+
loaded.delete(prev.id);
|
|
53208
|
+
}
|
|
53209
|
+
byLabel.set(label, { id, savedAt: envelope.savedAt, session });
|
|
53210
|
+
} else {
|
|
53211
|
+
await this.removeLegacyFile(id, session);
|
|
53212
|
+
loaded.delete(id);
|
|
53213
|
+
}
|
|
53214
|
+
}
|
|
53215
|
+
let rekeyed = 0;
|
|
53216
|
+
for (const [label, { id, session }] of byLabel) {
|
|
53217
|
+
if (claimed.has(label)) {
|
|
53218
|
+
await this.removeLegacyFile(id, session);
|
|
53219
|
+
loaded.delete(id);
|
|
53220
|
+
continue;
|
|
53221
|
+
}
|
|
53222
|
+
session.id = label;
|
|
53223
|
+
await this.store.writeNow(label, () => buildRecord(session));
|
|
53224
|
+
await this.removeLegacyFile(id, session);
|
|
53225
|
+
const envelope = loaded.get(id);
|
|
53226
|
+
if (envelope) {
|
|
53227
|
+
loaded.set(label, { ...envelope, id: label, payload: { ...envelope.payload, id: label } });
|
|
53228
|
+
}
|
|
53229
|
+
loaded.delete(id);
|
|
53230
|
+
claimed.add(label);
|
|
53231
|
+
rekeyed++;
|
|
53232
|
+
}
|
|
53233
|
+
try {
|
|
53234
|
+
mkdirSync3(this.dir, { recursive: true });
|
|
53235
|
+
writeFileSync2(this.markerPath(), String(Date.now()), "utf8");
|
|
53236
|
+
} catch {
|
|
53237
|
+
}
|
|
53238
|
+
if (rekeyed || unlabeled) {
|
|
53239
|
+
log("info", `[persist] one-time migration (#286): rekeyed ${rekeyed} legacy session(s), left ${unlabeled} unlabeled legacy file(s) in place`);
|
|
53290
53240
|
}
|
|
53291
|
-
return fill(new u8(sz), dat[bt2]);
|
|
53292
53241
|
}
|
|
53293
|
-
|
|
53294
|
-
|
|
53295
|
-
|
|
53296
|
-
|
|
53297
|
-
|
|
53298
|
-
|
|
53299
|
-
|
|
53300
|
-
|
|
53242
|
+
/** Remove a legacy session file. The kernel store never deletes (cleanup
|
|
53243
|
+
* is downstream policy), so the path is recomputed here: the namespaced
|
|
53244
|
+
* layout for v2+/v3 files, the _unknown/ fallback, and the flat default
|
|
53245
|
+
* name for pre-envelope v1 files. */
|
|
53246
|
+
async removeLegacyFile(id, session) {
|
|
53247
|
+
const candidates = /* @__PURE__ */ new Set([
|
|
53248
|
+
relPathFor(id, session.meta.protocol, session.meta.upstreamOrigin),
|
|
53249
|
+
relPathFor(id),
|
|
53250
|
+
flatFileNameFor(id)
|
|
53251
|
+
]);
|
|
53252
|
+
for (const rel2 of candidates) {
|
|
53253
|
+
await rm(path7.join(this.dir, rel2), { force: true }).catch(() => {
|
|
53254
|
+
});
|
|
53301
53255
|
}
|
|
53302
|
-
return slc(dat, bt2, ebt);
|
|
53303
53256
|
}
|
|
53304
|
-
|
|
53305
|
-
|
|
53306
|
-
|
|
53307
|
-
|
|
53308
|
-
|
|
53309
|
-
|
|
53310
|
-
|
|
53311
|
-
|
|
53312
|
-
|
|
53313
|
-
|
|
53314
|
-
if (sf < 2)
|
|
53315
|
-
lss |= (dat[++bt2] & 63) << 4, lcs = dat[bt2] >> 6 | dat[++bt2] << 2;
|
|
53316
|
-
else if (sf == 2)
|
|
53317
|
-
lss |= dat[++bt2] << 4 | (dat[++bt2] & 3) << 12, lcs = dat[bt2] >> 2 | dat[++bt2] << 6;
|
|
53318
|
-
else
|
|
53319
|
-
lss |= dat[++bt2] << 4 | (dat[++bt2] & 63) << 12, lcs = dat[bt2] >> 6 | dat[++bt2] << 2 | dat[++bt2] << 10;
|
|
53257
|
+
/** Shared envelope probe for the sync read paths: namespaced path
|
|
53258
|
+
* first, then the _unknown/ location, letting the kernel store layer
|
|
53259
|
+
* also check its discovered map and the flat legacy name. */
|
|
53260
|
+
loadEnvelope(id, meta) {
|
|
53261
|
+
const envelopes = [
|
|
53262
|
+
this.store.loadSync(id, relPathFor(id, meta?.protocol, meta?.upstreamOrigin)),
|
|
53263
|
+
meta?.protocol ? this.store.loadSync(id, relPathFor(id)) : null
|
|
53264
|
+
];
|
|
53265
|
+
for (const envelope of envelopes) {
|
|
53266
|
+
if (envelope) return envelope;
|
|
53320
53267
|
}
|
|
53321
|
-
|
|
53322
|
-
|
|
53323
|
-
|
|
53324
|
-
|
|
53325
|
-
|
|
53326
|
-
|
|
53327
|
-
|
|
53328
|
-
|
|
53329
|
-
|
|
53330
|
-
|
|
53331
|
-
|
|
53332
|
-
|
|
53333
|
-
|
|
53334
|
-
|
|
53335
|
-
err(0);
|
|
53336
|
-
(s4 ? dhu4 : dhu)(dat.subarray(bt2, bt2 += lcs), buf.subarray(spl), hu);
|
|
53268
|
+
return null;
|
|
53269
|
+
}
|
|
53270
|
+
/** Synchronous reload of a single session. Used on a memory miss (after
|
|
53271
|
+
* LRU eviction). Sync fs is acceptable here because a miss is rare and
|
|
53272
|
+
* reads a single small file (~1ms). Returns null if missing/corrupt or the
|
|
53273
|
+
* body id does not match what we asked for. */
|
|
53274
|
+
loadSync(id, meta) {
|
|
53275
|
+
if (!this.enabled) return null;
|
|
53276
|
+
const envelope = this.loadEnvelope(id, meta);
|
|
53277
|
+
if (!envelope) return null;
|
|
53278
|
+
const session = buildSession(envelope.payload);
|
|
53279
|
+
if (hasNegativePersistedTokens(envelope.payload)) {
|
|
53280
|
+
this.scheduleSave(session);
|
|
53281
|
+
log("info", `[persist] clamped negative token stats on reload for ${id} (#408)`);
|
|
53337
53282
|
}
|
|
53338
|
-
|
|
53339
|
-
|
|
53340
|
-
|
|
53341
|
-
|
|
53342
|
-
|
|
53343
|
-
|
|
53344
|
-
|
|
53345
|
-
|
|
53346
|
-
|
|
53347
|
-
|
|
53348
|
-
|
|
53349
|
-
|
|
53350
|
-
|
|
53351
|
-
|
|
53352
|
-
|
|
53353
|
-
|
|
53354
|
-
|
|
53355
|
-
|
|
53356
|
-
|
|
53357
|
-
|
|
53358
|
-
|
|
53359
|
-
|
|
53360
|
-
|
|
53361
|
-
|
|
53362
|
-
|
|
53363
|
-
|
|
53364
|
-
|
|
53365
|
-
|
|
53366
|
-
|
|
53367
|
-
|
|
53368
|
-
|
|
53369
|
-
|
|
53370
|
-
|
|
53371
|
-
|
|
53372
|
-
|
|
53373
|
-
|
|
53374
|
-
|
|
53375
|
-
|
|
53376
|
-
|
|
53377
|
-
|
|
53378
|
-
|
|
53379
|
-
|
|
53380
|
-
|
|
53381
|
-
var ofc = oct.s[ost];
|
|
53382
|
-
var obtr = oct.n[ost];
|
|
53383
|
-
cbt = (spos -= ofc) >> 3;
|
|
53384
|
-
var ofp = 1 << ofc;
|
|
53385
|
-
var off = ofp + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16 | dat[cbt + 3] << 24) >>> (spos & 7) & ofp - 1);
|
|
53386
|
-
cbt = (spos -= mlb[mlc]) >> 3;
|
|
53387
|
-
var ml = mlbl[mlc] + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (spos & 7) & (1 << mlb[mlc]) - 1);
|
|
53388
|
-
cbt = (spos -= llb[llc]) >> 3;
|
|
53389
|
-
var ll = llbl[llc] + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (spos & 7) & (1 << llb[llc]) - 1);
|
|
53390
|
-
cbt = (spos -= lbtr) >> 3;
|
|
53391
|
-
lst = llt.t[lst] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << lbtr) - 1);
|
|
53392
|
-
cbt = (spos -= mbtr) >> 3;
|
|
53393
|
-
mst = mlt.t[mst] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << mbtr) - 1);
|
|
53394
|
-
cbt = (spos -= obtr) >> 3;
|
|
53395
|
-
ost = oct.t[ost] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << obtr) - 1);
|
|
53396
|
-
if (off > 3) {
|
|
53397
|
-
st2.o[2] = st2.o[1];
|
|
53398
|
-
st2.o[1] = st2.o[0];
|
|
53399
|
-
st2.o[0] = off -= 3;
|
|
53400
|
-
} else {
|
|
53401
|
-
var idx = off - (ll != 0);
|
|
53402
|
-
if (idx) {
|
|
53403
|
-
off = idx == 3 ? st2.o[0] - 1 : st2.o[idx];
|
|
53404
|
-
if (idx > 1)
|
|
53405
|
-
st2.o[2] = st2.o[1];
|
|
53406
|
-
st2.o[1] = st2.o[0];
|
|
53407
|
-
st2.o[0] = off;
|
|
53408
|
-
} else
|
|
53409
|
-
off = st2.o[0];
|
|
53410
|
-
}
|
|
53411
|
-
for (var i = 0; i < ll; ++i) {
|
|
53412
|
-
buf[oubt + i] = buf[spl + i];
|
|
53413
|
-
}
|
|
53414
|
-
oubt += ll, spl += ll;
|
|
53415
|
-
var stin = oubt - off;
|
|
53416
|
-
if (stin < 0) {
|
|
53417
|
-
var len = -stin;
|
|
53418
|
-
var bs2 = st2.e + stin;
|
|
53419
|
-
if (len > ml)
|
|
53420
|
-
len = ml;
|
|
53421
|
-
for (var i = 0; i < len; ++i) {
|
|
53422
|
-
buf[oubt + i] = st2.w[bs2 + i];
|
|
53423
|
-
}
|
|
53424
|
-
oubt += len, ml -= len, stin = 0;
|
|
53425
|
-
}
|
|
53426
|
-
for (var i = 0; i < ml; ++i) {
|
|
53427
|
-
buf[oubt + i] = buf[stin + i];
|
|
53428
|
-
}
|
|
53429
|
-
oubt += ml;
|
|
53430
|
-
}
|
|
53431
|
-
if (oubt != spl) {
|
|
53432
|
-
while (spl < buf.length) {
|
|
53433
|
-
buf[oubt++] = buf[spl++];
|
|
53434
|
-
}
|
|
53435
|
-
} else
|
|
53436
|
-
oubt = buf.length;
|
|
53437
|
-
if (out)
|
|
53438
|
-
st2.y += oubt;
|
|
53439
|
-
else
|
|
53440
|
-
buf = slc(buf, 0, oubt);
|
|
53441
|
-
} else if (out) {
|
|
53442
|
-
st2.y += lss;
|
|
53443
|
-
if (spl) {
|
|
53444
|
-
for (var i = 0; i < lss; ++i) {
|
|
53445
|
-
buf[i] = buf[spl + i];
|
|
53446
|
-
}
|
|
53283
|
+
return session;
|
|
53284
|
+
}
|
|
53285
|
+
/** Read-only state load for cross-session search (#841): unlike loadSync,
|
|
53286
|
+
* never schedules a save (no #408 clamp-rewrite side effect). */
|
|
53287
|
+
loadStateForSearch(id) {
|
|
53288
|
+
if (!this.enabled) return null;
|
|
53289
|
+
const envelope = this.loadEnvelope(id);
|
|
53290
|
+
if (!envelope) return null;
|
|
53291
|
+
return mergeState(envelope.payload.state);
|
|
53292
|
+
}
|
|
53293
|
+
/** #405 fix #4: dual-instance rollback guard. When two proxy processes
|
|
53294
|
+
* share BILI_SESSIONS_DIR, whoever saves last used to win — an instance
|
|
53295
|
+
* holding a STALE in-memory copy would roll counters back (requests:3 →
|
|
53296
|
+
* 2). Both signals below are monotonic per session id, so either being
|
|
53297
|
+
* strictly smaller proves staleness. Returns the fresher-on-disk payload
|
|
53298
|
+
* when the incoming record is stale, else null. */
|
|
53299
|
+
staleDiskPayload(incoming) {
|
|
53300
|
+
const envelope = this.loadEnvelope(incoming.id, incoming.meta);
|
|
53301
|
+
if (!envelope) return null;
|
|
53302
|
+
const disk = envelope.payload;
|
|
53303
|
+
const diskRequests = disk.stats?.requests ?? disk.requests ?? 0;
|
|
53304
|
+
const incRequests = incoming.stats?.requests ?? incoming.requests ?? 0;
|
|
53305
|
+
if (incRequests < diskRequests) return disk;
|
|
53306
|
+
if (incRequests === diskRequests) {
|
|
53307
|
+
const diskBlocks = disk.state?.nextBlockId ?? 0;
|
|
53308
|
+
const incBlocks = incoming.state?.nextBlockId ?? 0;
|
|
53309
|
+
if (incBlocks < diskBlocks) return disk;
|
|
53310
|
+
}
|
|
53311
|
+
return null;
|
|
53312
|
+
}
|
|
53313
|
+
guardedBuild(session) {
|
|
53314
|
+
return () => {
|
|
53315
|
+
const record = buildRecord(session);
|
|
53316
|
+
const disk = this.staleDiskPayload(record);
|
|
53317
|
+
if (disk === null) return record;
|
|
53318
|
+
const now = Date.now();
|
|
53319
|
+
const last = this.staleWarnAt.get(record.id) ?? 0;
|
|
53320
|
+
if (now - last >= STALE_WARN_THROTTLE_MS) {
|
|
53321
|
+
this.staleWarnAt.set(record.id, now);
|
|
53322
|
+
this.log(
|
|
53323
|
+
"warn",
|
|
53324
|
+
`[persist] rejected stale snapshot for session ${record.id}: in-memory copy is older than the on-disk one (another bili instance holds newer state) \u2014 keeping disk state, no rollback (#405)`
|
|
53325
|
+
);
|
|
53447
53326
|
}
|
|
53448
|
-
|
|
53449
|
-
|
|
53450
|
-
st2.b = ebt;
|
|
53451
|
-
return buf;
|
|
53327
|
+
return disk;
|
|
53328
|
+
};
|
|
53452
53329
|
}
|
|
53453
|
-
|
|
53454
|
-
|
|
53455
|
-
|
|
53456
|
-
|
|
53457
|
-
|
|
53458
|
-
|
|
53459
|
-
|
|
53460
|
-
|
|
53461
|
-
|
|
53462
|
-
|
|
53330
|
+
/** Schedule a debounced write for a session. Multiple calls within the
|
|
53331
|
+
* window coalesce; the record is built at WRITE time, so the freshest
|
|
53332
|
+
* session state is persisted. Safe to call on the hot path. No-op if
|
|
53333
|
+
* disabled. */
|
|
53334
|
+
scheduleSave(session) {
|
|
53335
|
+
this.store.scheduleSave(session.id, this.guardedBuild(session));
|
|
53336
|
+
}
|
|
53337
|
+
/** Asynchronously persist a session right now (skips the debounce). Throws
|
|
53338
|
+
* on write failure so callers can react (e.g. avoid evicting). Serialized
|
|
53339
|
+
* per-session by the kernel store's write chains. */
|
|
53340
|
+
async writeNow(session) {
|
|
53341
|
+
await this.store.writeNow(session.id, this.guardedBuild(session));
|
|
53342
|
+
}
|
|
53343
|
+
/** Synchronous flush for a single session. Used on memory eviction so a
|
|
53344
|
+
* dirty evicted session is not lost. Sync because eviction runs in the
|
|
53345
|
+
* sync getSession path; a single small write is acceptable.
|
|
53346
|
+
* Returns true on success, false on failure (caller must NOT evict on
|
|
53347
|
+
* failure for a never-persisted session or it is lost permanently). */
|
|
53348
|
+
flushSync(session) {
|
|
53349
|
+
return this.store.flushSync(session.id, this.guardedBuild(session));
|
|
53350
|
+
}
|
|
53351
|
+
/** Flush all dirty sessions with a pending debounce timer. Called on
|
|
53352
|
+
* SIGTERM/SIGINT for graceful shutdown. The kernel store flushes its own
|
|
53353
|
+
* pending set (builders read the live Session objects at write time, so
|
|
53354
|
+
* no session list is needed) and drains in-flight write chains. */
|
|
53355
|
+
async flushAll(_sessions) {
|
|
53356
|
+
await this.store.flushAll();
|
|
53357
|
+
}
|
|
53358
|
+
/** Whether a write is currently pending (debounce timer armed) for a id. */
|
|
53359
|
+
hasPending(id) {
|
|
53360
|
+
return this.store.hasPending(id);
|
|
53361
|
+
}
|
|
53362
|
+
/** Cancel all pending writes without flushing (e.g. for tests). */
|
|
53363
|
+
cancelAll() {
|
|
53364
|
+
this.store.cancelAll();
|
|
53463
53365
|
}
|
|
53464
|
-
return buf;
|
|
53465
53366
|
};
|
|
53466
|
-
|
|
53467
|
-
|
|
53468
|
-
|
|
53469
|
-
|
|
53470
|
-
|
|
53471
|
-
|
|
53367
|
+
function buildRecord(session) {
|
|
53368
|
+
const snapshot = boundedFoldedSnapshot(session);
|
|
53369
|
+
return {
|
|
53370
|
+
version: PERSIST_VERSION,
|
|
53371
|
+
savedAt: Date.now(),
|
|
53372
|
+
id: session.id,
|
|
53373
|
+
meta: { ...session.meta },
|
|
53374
|
+
stats: { ...session.stats },
|
|
53375
|
+
messages: snapshot,
|
|
53376
|
+
messagesFolded: snapshot ? true : void 0,
|
|
53377
|
+
metadata: { ...session.metadata },
|
|
53378
|
+
state: session.state,
|
|
53379
|
+
blockContents: Object.fromEntries(session.blockContents),
|
|
53380
|
+
createdAt: session.createdAt
|
|
53381
|
+
};
|
|
53382
|
+
}
|
|
53383
|
+
function isBlockView(v2) {
|
|
53384
|
+
return !!v2 && typeof v2 === "object" && typeof v2.text === "string" && typeof v2.count === "number";
|
|
53385
|
+
}
|
|
53386
|
+
function buildSession(parsed) {
|
|
53387
|
+
const blockContents = /* @__PURE__ */ new Map();
|
|
53388
|
+
for (const [bid, content] of Object.entries(parsed.blockContents ?? {})) {
|
|
53389
|
+
if (!content || typeof content !== "object") continue;
|
|
53390
|
+
const full = content.full;
|
|
53391
|
+
if (!isBlockView(full)) continue;
|
|
53392
|
+
const one = content.one;
|
|
53393
|
+
const oneView = isBlockView(one) ? one : null;
|
|
53394
|
+
blockContents.set(bid, {
|
|
53395
|
+
one: oneView && !(oneView.text === full.text && oneView.count === full.count) ? oneView : null,
|
|
53396
|
+
full
|
|
53397
|
+
});
|
|
53472
53398
|
}
|
|
53473
|
-
|
|
53474
|
-
|
|
53475
|
-
|
|
53476
|
-
|
|
53477
|
-
|
|
53478
|
-
|
|
53479
|
-
|
|
53480
|
-
|
|
53481
|
-
|
|
53482
|
-
|
|
53483
|
-
|
|
53484
|
-
|
|
53485
|
-
|
|
53486
|
-
|
|
53487
|
-
|
|
53488
|
-
|
|
53489
|
-
|
|
53490
|
-
|
|
53491
|
-
|
|
53492
|
-
|
|
53493
|
-
|
|
53494
|
-
|
|
53495
|
-
|
|
53496
|
-
|
|
53497
|
-
|
|
53498
|
-
|
|
53499
|
-
|
|
53500
|
-
|
|
53501
|
-
|
|
53502
|
-
}
|
|
53503
|
-
|
|
53504
|
-
|
|
53505
|
-
|
|
53506
|
-
|
|
53507
|
-
|
|
53508
|
-
|
|
53509
|
-
|
|
53510
|
-
|
|
53511
|
-
|
|
53512
|
-
|
|
53513
|
-
|
|
53514
|
-
|
|
53515
|
-
|
|
53516
|
-
|
|
53517
|
-
if (!this.z && ncs < (this.z = chunk[this.s.b] & 2 ? 4 : 3 + (chunk[this.s.b] >> 3 | chunk[this.s.b + 1] << 5 | chunk[this.s.b + 2] << 13))) {
|
|
53518
|
-
if (final)
|
|
53519
|
-
err(5);
|
|
53520
|
-
this.c.push(chunk);
|
|
53521
|
-
this.l = ncs;
|
|
53522
|
-
return;
|
|
53523
|
-
} else
|
|
53524
|
-
this.z = 0;
|
|
53525
|
-
for (; ; ) {
|
|
53526
|
-
var blk = rzb(chunk, this.s);
|
|
53527
|
-
if (!blk) {
|
|
53528
|
-
if (final)
|
|
53529
|
-
err(5);
|
|
53530
|
-
var adc = chunk.subarray(this.s.b);
|
|
53531
|
-
this.s.b = 0;
|
|
53532
|
-
this.c.push(adc), this.l += adc.length;
|
|
53533
|
-
return;
|
|
53534
|
-
} else {
|
|
53535
|
-
this.ondata(blk, false);
|
|
53536
|
-
cpw(this.s.w, 0, blk.length);
|
|
53537
|
-
this.s.w.set(blk, this.s.w.length - blk.length);
|
|
53538
|
-
}
|
|
53539
|
-
if (this.s.l) {
|
|
53540
|
-
var rest = chunk.subarray(this.s.b);
|
|
53541
|
-
this.s = this.s.c * 4;
|
|
53542
|
-
this.push(rest, final);
|
|
53543
|
-
return;
|
|
53544
|
-
}
|
|
53545
|
-
}
|
|
53546
|
-
} else if (final)
|
|
53547
|
-
err(5);
|
|
53399
|
+
const meta = parsed.meta ?? {};
|
|
53400
|
+
const stats = parsed.stats ?? {};
|
|
53401
|
+
return {
|
|
53402
|
+
id: parsed.id,
|
|
53403
|
+
meta: {
|
|
53404
|
+
protocol: meta.protocol ?? parsed.protocol,
|
|
53405
|
+
upstreamOrigin: meta.upstreamOrigin ?? parsed.upstreamOrigin,
|
|
53406
|
+
label: meta.label ?? parsed.label,
|
|
53407
|
+
title: meta.title
|
|
53408
|
+
},
|
|
53409
|
+
stats: {
|
|
53410
|
+
requests: stats.requests ?? parsed.requests ?? 0,
|
|
53411
|
+
tokensSaved: stats.tokensSaved ?? parsed.tokensSaved ?? 0,
|
|
53412
|
+
inputTokens: stats.inputTokens ?? parsed.inputTokens ?? 0,
|
|
53413
|
+
cachedTokens: stats.cachedTokens ?? parsed.cachedTokens ?? 0,
|
|
53414
|
+
outputTokens: stats.outputTokens ?? parsed.outputTokens ?? 0,
|
|
53415
|
+
cacheSamples: stats.cacheSamples ?? parsed.cacheSamples ?? 0,
|
|
53416
|
+
// #408: clamp at restore — pre-clamp versions persisted negative
|
|
53417
|
+
// values (lastInputTokens = total − credit before the Math.max
|
|
53418
|
+
// guard existed) which would otherwise revive after upgrade and
|
|
53419
|
+
// feed the /acp panel + web stats as negative percentages.
|
|
53420
|
+
lastInputTokens: Math.max(0, stats.lastInputTokens ?? parsed.lastInputTokens ?? 0),
|
|
53421
|
+
// #857: provenance — legacy files lack it; absent stays absent and
|
|
53422
|
+
// evidence-grade consumers treat absent as untrusted.
|
|
53423
|
+
lastInputTokensSource: stats.lastInputTokensSource === "usage" || stats.lastInputTokensSource === "estimate" ? stats.lastInputTokensSource : void 0,
|
|
53424
|
+
// In-memory only — a fresh process has no pending compress fold.
|
|
53425
|
+
compressCreditTokens: 0,
|
|
53426
|
+
contextTokens: Math.max(0, stats.contextTokens ?? parsed.contextTokens ?? 0)
|
|
53427
|
+
},
|
|
53428
|
+
metadata: parsed.metadata ?? {},
|
|
53429
|
+
state: mergeState(parsed.state),
|
|
53430
|
+
createdAt: parsed.createdAt ?? Date.now(),
|
|
53431
|
+
// #404: lastSeen reflects the on-disk savedAt (the last real
|
|
53432
|
+
// activity), NOT the restore moment — a restart must not fabricate
|
|
53433
|
+
// activity for every session (broke fallback=latest ties, panel
|
|
53434
|
+
// freshness, and eviction ordering). Consumers that need "has this
|
|
53435
|
+
// session been used since boot" read the restored flag.
|
|
53436
|
+
lastSeen: parsed.savedAt ?? Date.now(),
|
|
53437
|
+
restored: true,
|
|
53438
|
+
blockContents,
|
|
53439
|
+
lastMessages: Array.isArray(parsed.messages) ? parsed.messages : void 0,
|
|
53440
|
+
lastMessagesFolded: parsed.messagesFolded === true,
|
|
53441
|
+
inFlight: 0,
|
|
53442
|
+
persisted: true
|
|
53548
53443
|
};
|
|
53549
|
-
|
|
53550
|
-
|
|
53551
|
-
|
|
53552
|
-
|
|
53553
|
-
|
|
53554
|
-
|
|
53555
|
-
|
|
53556
|
-
|
|
53557
|
-
|
|
53558
|
-
|
|
53559
|
-
|
|
53560
|
-
|
|
53561
|
-
|
|
53562
|
-
|
|
53563
|
-
|
|
53564
|
-
|
|
53565
|
-
|
|
53566
|
-
if (
|
|
53567
|
-
|
|
53568
|
-
|
|
53569
|
-
buf = Buffer.from(v2, "base64");
|
|
53444
|
+
}
|
|
53445
|
+
function isValidRecord(parsed) {
|
|
53446
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
53447
|
+
const r = parsed;
|
|
53448
|
+
return typeof r.id === "string" && typeof r.state === "object" && r.state !== null && Array.isArray(r.state.blocks);
|
|
53449
|
+
}
|
|
53450
|
+
function hasNegativePersistedTokens(parsed) {
|
|
53451
|
+
const stats = parsed.stats ?? {};
|
|
53452
|
+
const last = stats.lastInputTokens ?? parsed.lastInputTokens;
|
|
53453
|
+
const ctx = stats.contextTokens ?? parsed.contextTokens;
|
|
53454
|
+
return typeof last === "number" && last < 0 || typeof ctx === "number" && ctx < 0;
|
|
53455
|
+
}
|
|
53456
|
+
function defaultDir() {
|
|
53457
|
+
return sessionsDir();
|
|
53458
|
+
}
|
|
53459
|
+
function defaultDebounce() {
|
|
53460
|
+
const env = process.env.BILI_PERSIST_DEBOUNCE_MS;
|
|
53461
|
+
if (env) {
|
|
53462
|
+
const n = Number.parseInt(env, 10);
|
|
53463
|
+
if (Number.isFinite(n) && n >= 0) return n;
|
|
53570
53464
|
}
|
|
53571
|
-
|
|
53572
|
-
|
|
53573
|
-
|
|
53574
|
-
|
|
53575
|
-
|
|
53465
|
+
return 500;
|
|
53466
|
+
}
|
|
53467
|
+
function persistEnabled() {
|
|
53468
|
+
const env = process.env.BILI_PERSIST;
|
|
53469
|
+
if (env === "0" || env === "false") return false;
|
|
53470
|
+
return true;
|
|
53471
|
+
}
|
|
53472
|
+
var STALE_ENC_TEMP_RE = /\.tmp-enc-\d+-\d+$/;
|
|
53473
|
+
async function walkJsonFiles(dir) {
|
|
53474
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
53475
|
+
const out = [];
|
|
53476
|
+
for (const e of entries) {
|
|
53477
|
+
const full = path7.join(dir, e.name);
|
|
53478
|
+
if (e.isDirectory()) {
|
|
53479
|
+
out.push(...await walkJsonFiles(full));
|
|
53480
|
+
} else if (e.isFile() && (STALE_ENC_TEMP_RE.test(e.name) || e.name.endsWith(".json") && !e.name.startsWith(".tmp-"))) {
|
|
53481
|
+
out.push(full);
|
|
53482
|
+
}
|
|
53576
53483
|
}
|
|
53577
|
-
return
|
|
53484
|
+
return out;
|
|
53578
53485
|
}
|
|
53579
|
-
|
|
53580
|
-
|
|
53581
|
-
|
|
53582
|
-
|
|
53486
|
+
async function readFileHead(file, len = ENCRYPT_MAGIC.length) {
|
|
53487
|
+
const fh = await open(file, "r");
|
|
53488
|
+
try {
|
|
53489
|
+
const buf = Buffer.alloc(len);
|
|
53490
|
+
const { bytesRead } = await fh.read(buf, 0, len, 0);
|
|
53491
|
+
return buf.subarray(0, bytesRead);
|
|
53492
|
+
} finally {
|
|
53493
|
+
await fh.close();
|
|
53494
|
+
}
|
|
53583
53495
|
}
|
|
53584
|
-
function
|
|
53585
|
-
|
|
53586
|
-
|
|
53587
|
-
|
|
53588
|
-
|
|
53496
|
+
function persistTailTokens() {
|
|
53497
|
+
const env = process.env.BILI_PERSIST_TAIL_TOKENS;
|
|
53498
|
+
if (env) {
|
|
53499
|
+
const n = Number.parseInt(env, 10);
|
|
53500
|
+
if (Number.isFinite(n) && n >= 0) return n;
|
|
53501
|
+
}
|
|
53502
|
+
return 16384;
|
|
53589
53503
|
}
|
|
53590
|
-
function
|
|
53591
|
-
const
|
|
53592
|
-
|
|
53593
|
-
|
|
53594
|
-
return
|
|
53595
|
-
|
|
53596
|
-
|
|
53597
|
-
|
|
53598
|
-
|
|
53599
|
-
|
|
53600
|
-
|
|
53601
|
-
|
|
53602
|
-
|
|
53603
|
-
|
|
53604
|
-
|
|
53605
|
-
|
|
53606
|
-
}
|
|
53607
|
-
if (!key && mode === MODE_RAW) return plain;
|
|
53608
|
-
const header = Buffer.from([FORMAT_VERSION, mode]);
|
|
53609
|
-
if (!key) {
|
|
53610
|
-
return Buffer.concat([ZSTD_MAGIC, header, body]);
|
|
53611
|
-
}
|
|
53612
|
-
const nonce = randomBytes(NONCE_LEN);
|
|
53613
|
-
const cipher = createCipheriv("aes-256-gcm", key, nonce);
|
|
53614
|
-
const ct2 = Buffer.concat([cipher.update(body), cipher.final()]);
|
|
53615
|
-
return Buffer.concat([ENCRYPT_MAGIC, header, nonce, ct2, cipher.getAuthTag()]);
|
|
53616
|
-
},
|
|
53617
|
-
decode(buf) {
|
|
53618
|
-
if (buf.length >= ENCRYPT_MAGIC.length && buf.subarray(0, ENCRYPT_MAGIC.length).equals(ENCRYPT_MAGIC)) {
|
|
53619
|
-
return decryptEnvelope(buf, key);
|
|
53620
|
-
}
|
|
53621
|
-
if (buf.length >= ZSTD_MAGIC.length && buf.subarray(0, ZSTD_MAGIC.length).equals(ZSTD_MAGIC)) {
|
|
53622
|
-
return decompressEnvelope(buf);
|
|
53504
|
+
function boundedFoldedSnapshot(session) {
|
|
53505
|
+
const msgs = session.lastMessages;
|
|
53506
|
+
if (!msgs || msgs.length === 0) return void 0;
|
|
53507
|
+
const budget = persistTailTokens();
|
|
53508
|
+
if (budget === 0) return void 0;
|
|
53509
|
+
let view = prune(msgs, session.state);
|
|
53510
|
+
let total = 0;
|
|
53511
|
+
for (const m2 of view) total += defaultCountTokens(m2.text ?? "");
|
|
53512
|
+
if (total > budget) {
|
|
53513
|
+
let acc = 0;
|
|
53514
|
+
let start = 0;
|
|
53515
|
+
for (let i = view.length - 1; i >= 0; i--) {
|
|
53516
|
+
acc += defaultCountTokens(view[i].text ?? "");
|
|
53517
|
+
if (acc > budget) {
|
|
53518
|
+
start = Math.min(i + 1, view.length - 1);
|
|
53519
|
+
break;
|
|
53623
53520
|
}
|
|
53624
|
-
return buf.toString("utf8");
|
|
53625
53521
|
}
|
|
53626
|
-
|
|
53522
|
+
if (start > 0) view = view.slice(start);
|
|
53523
|
+
}
|
|
53524
|
+
return view;
|
|
53627
53525
|
}
|
|
53628
|
-
function
|
|
53629
|
-
|
|
53630
|
-
|
|
53526
|
+
function epermAlertThreshold() {
|
|
53527
|
+
const env = process.env.BILI_PERSIST_EPERM_ALERT_THRESHOLD;
|
|
53528
|
+
if (env) {
|
|
53529
|
+
const n = Number.parseInt(env, 10);
|
|
53530
|
+
if (Number.isFinite(n) && n > 0) return n;
|
|
53631
53531
|
}
|
|
53632
|
-
|
|
53633
|
-
|
|
53532
|
+
return 5;
|
|
53533
|
+
}
|
|
53534
|
+
function epermAlertRepeatMs() {
|
|
53535
|
+
const env = process.env.BILI_PERSIST_EPERM_ALERT_REPEAT_MS;
|
|
53536
|
+
if (env) {
|
|
53537
|
+
const n = Number.parseInt(env, 10);
|
|
53538
|
+
if (Number.isFinite(n) && n >= 0) return n;
|
|
53634
53539
|
}
|
|
53635
|
-
|
|
53636
|
-
|
|
53637
|
-
|
|
53638
|
-
|
|
53639
|
-
const decipher = createDecipheriv("aes-256-gcm", key, nonce);
|
|
53640
|
-
decipher.setAuthTag(tag);
|
|
53641
|
-
const body = Buffer.concat([decipher.update(ct2), decipher.final()]);
|
|
53642
|
-
const plain = mode === MODE_ZSTD ? inflateZstd(body) : body;
|
|
53643
|
-
return plain.toString("utf8");
|
|
53540
|
+
return 0;
|
|
53541
|
+
}
|
|
53542
|
+
function defaultLogger(level, m2) {
|
|
53543
|
+
log(level, m2);
|
|
53644
53544
|
}
|
|
53645
|
-
|
|
53646
|
-
|
|
53647
|
-
|
|
53545
|
+
var _store = null;
|
|
53546
|
+
function getStore() {
|
|
53547
|
+
if (!_store) {
|
|
53548
|
+
_store = new SessionStore({ enabled: persistEnabled(), log: defaultLogger });
|
|
53648
53549
|
}
|
|
53649
|
-
|
|
53650
|
-
const body = buf.subarray(PLAIN_HEADER_LEN);
|
|
53651
|
-
const plain = mode === MODE_ZSTD ? inflateZstd(body) : body;
|
|
53652
|
-
return plain.toString("utf8");
|
|
53550
|
+
return _store;
|
|
53653
53551
|
}
|
|
53654
53552
|
|
|
53655
|
-
// src/
|
|
53656
|
-
|
|
53657
|
-
|
|
53658
|
-
|
|
53659
|
-
|
|
53660
|
-
|
|
53661
|
-
|
|
53662
|
-
|
|
53663
|
-
|
|
53664
|
-
|
|
53665
|
-
|
|
53666
|
-
|
|
53667
|
-
|
|
53668
|
-
|
|
53669
|
-
|
|
53670
|
-
|
|
53671
|
-
|
|
53672
|
-
|
|
53673
|
-
|
|
53674
|
-
|
|
53675
|
-
|
|
53676
|
-
|
|
53677
|
-
|
|
53678
|
-
|
|
53679
|
-
|
|
53680
|
-
const
|
|
53681
|
-
|
|
53682
|
-
|
|
53683
|
-
|
|
53684
|
-
|
|
53685
|
-
|
|
53686
|
-
this.hasAlerted = true;
|
|
53687
|
-
this.alertedAt = this.now();
|
|
53688
|
-
this.onAlert(this.dir, count);
|
|
53689
|
-
return true;
|
|
53690
|
-
}
|
|
53691
|
-
shouldAlert() {
|
|
53692
|
-
if (!this.hasAlerted) return true;
|
|
53693
|
-
if (this.repeatMs <= 0) return false;
|
|
53694
|
-
return this.now() - this.alertedAt >= this.repeatMs;
|
|
53553
|
+
// src/session.ts
|
|
53554
|
+
function lastCompressSuffix(info) {
|
|
53555
|
+
if (!info) return "";
|
|
53556
|
+
return ` [after compress: shrink ${Math.round(info.shrinkRatio * 100)}% foldPoint=${info.foldPoint} blocks=${info.blocks} ~${info.tokensCompressed}tok]`;
|
|
53557
|
+
}
|
|
53558
|
+
function storeEffectiveConfig(session, config) {
|
|
53559
|
+
session.metadata["effectiveConfig"] = config;
|
|
53560
|
+
}
|
|
53561
|
+
function effectiveConfig(session, fallback) {
|
|
53562
|
+
const stored = session?.metadata["effectiveConfig"];
|
|
53563
|
+
if (stored && typeof stored === "object") return { ...fallback, ...stored };
|
|
53564
|
+
return fallback;
|
|
53565
|
+
}
|
|
53566
|
+
var sessions = /* @__PURE__ */ new Map();
|
|
53567
|
+
var MAX_SESSIONS = Math.max(1, Number.parseInt(process.env.BILI_MAX_SESSIONS ?? "256", 10) || 256);
|
|
53568
|
+
var initialized = false;
|
|
53569
|
+
async function initSessions() {
|
|
53570
|
+
if (initialized) return;
|
|
53571
|
+
initialized = true;
|
|
53572
|
+
const store = getStore();
|
|
53573
|
+
if (!store.enabled) return;
|
|
53574
|
+
const loaded = await store.boot();
|
|
53575
|
+
if (loaded.size > MAX_SESSIONS) {
|
|
53576
|
+
const freshness = (s3) => Math.max(s3.createdAt ?? 0, s3.lastSeen ?? 0);
|
|
53577
|
+
const entries = [...loaded.entries()].sort((a, b2) => freshness(b2[1]) - freshness(a[1]));
|
|
53578
|
+
for (const [id, s3] of entries) {
|
|
53579
|
+
if (sessions.size >= MAX_SESSIONS) break;
|
|
53580
|
+
sessions.set(id, s3);
|
|
53581
|
+
}
|
|
53582
|
+
} else {
|
|
53583
|
+
for (const [id, s3] of loaded) sessions.set(id, s3);
|
|
53695
53584
|
}
|
|
53696
|
-
};
|
|
53697
|
-
function buildAlertMessage(dir, count) {
|
|
53698
|
-
return [
|
|
53699
|
-
`[persist] session dir ${dir} failed ${count} consecutive writes (EPERM \u2014 rename is locked).`,
|
|
53700
|
-
"Likely cause: Windows Defender / antivirus / indexer / a sync tool is locking the directory.",
|
|
53701
|
-
`Fix: add ${dir} to Windows Defender exclusions (Settings \u2192 Virus & threat protection \u2192 Manage settings \u2192 Exclusions \u2192 Add an exclusion),`,
|
|
53702
|
-
"and make sure no OneDrive / sync tool is syncing this path."
|
|
53703
|
-
].join("\n");
|
|
53704
53585
|
}
|
|
53705
|
-
|
|
53706
|
-
|
|
53707
|
-
|
|
53708
|
-
|
|
53709
|
-
|
|
53710
|
-
|
|
53711
|
-
|
|
53712
|
-
|
|
53713
|
-
|
|
53714
|
-
|
|
53715
|
-
|
|
53716
|
-
|
|
53717
|
-
|
|
53718
|
-
|
|
53719
|
-
|
|
53720
|
-
|
|
53721
|
-
|
|
53722
|
-
|
|
53723
|
-
|
|
53586
|
+
function getSession(id, meta) {
|
|
53587
|
+
const existing = sessions.get(id);
|
|
53588
|
+
if (existing) {
|
|
53589
|
+
existing.lastSeen = Date.now();
|
|
53590
|
+
existing.restored = false;
|
|
53591
|
+
if (meta?.protocol && !existing.meta.protocol) existing.meta.protocol = meta.protocol;
|
|
53592
|
+
if (meta?.upstreamOrigin && !existing.meta.upstreamOrigin) existing.meta.upstreamOrigin = meta.upstreamOrigin;
|
|
53593
|
+
if (meta?.label && !existing.meta.label) existing.meta.label = meta.label;
|
|
53594
|
+
return existing;
|
|
53595
|
+
}
|
|
53596
|
+
const store = getStore();
|
|
53597
|
+
const reloaded = store.loadSync(id, meta);
|
|
53598
|
+
if (reloaded) {
|
|
53599
|
+
reloaded.lastSeen = Date.now();
|
|
53600
|
+
reloaded.restored = false;
|
|
53601
|
+
reloaded.persisted = true;
|
|
53602
|
+
sessions.set(id, reloaded);
|
|
53603
|
+
return reloaded;
|
|
53604
|
+
}
|
|
53605
|
+
if (sessions.size >= MAX_SESSIONS) {
|
|
53606
|
+
const evicted = evictOldest();
|
|
53607
|
+
if (!evicted) {
|
|
53608
|
+
throw new Error(`session pool exhausted (MAX_SESSIONS=${MAX_SESSIONS}; all in-flight)`);
|
|
53609
|
+
}
|
|
53610
|
+
}
|
|
53611
|
+
const session = {
|
|
53612
|
+
id,
|
|
53613
|
+
meta: { protocol: meta?.protocol, upstreamOrigin: meta?.upstreamOrigin, label: meta?.label },
|
|
53614
|
+
stats: { requests: 0, tokensSaved: 0, inputTokens: 0, cachedTokens: 0, outputTokens: 0, cacheSamples: 0, lastInputTokens: 0, compressCreditTokens: 0, contextTokens: 0 },
|
|
53615
|
+
metadata: {},
|
|
53616
|
+
state: createInitialState(),
|
|
53617
|
+
createdAt: Date.now(),
|
|
53618
|
+
lastSeen: Date.now(),
|
|
53619
|
+
blockContents: /* @__PURE__ */ new Map(),
|
|
53620
|
+
inFlight: 0,
|
|
53621
|
+
persisted: false
|
|
53724
53622
|
};
|
|
53623
|
+
sessions.set(id, session);
|
|
53624
|
+
return session;
|
|
53725
53625
|
}
|
|
53726
|
-
function
|
|
53727
|
-
|
|
53626
|
+
function acquireInFlight(session) {
|
|
53627
|
+
session.inFlight++;
|
|
53628
|
+
}
|
|
53629
|
+
function releaseInFlight(session) {
|
|
53630
|
+
if (session.inFlight > 0) session.inFlight--;
|
|
53631
|
+
}
|
|
53632
|
+
function totalInFlight() {
|
|
53633
|
+
let n = 0;
|
|
53634
|
+
for (const s3 of sessions.values()) n += s3.inFlight;
|
|
53635
|
+
return n;
|
|
53636
|
+
}
|
|
53637
|
+
async function withSessionLock(session, fn) {
|
|
53638
|
+
const prev = session.lockChain ?? Promise.resolve();
|
|
53639
|
+
let release;
|
|
53640
|
+
const done = new Promise((resolve) => {
|
|
53641
|
+
release = resolve;
|
|
53642
|
+
});
|
|
53643
|
+
session.lockChain = prev.then(() => done);
|
|
53644
|
+
await prev;
|
|
53728
53645
|
try {
|
|
53729
|
-
|
|
53730
|
-
|
|
53731
|
-
|
|
53732
|
-
return "unknown-" + createHash4("sha256").update(upstreamOrigin, "utf8").digest("hex").slice(0, 6);
|
|
53646
|
+
return await fn();
|
|
53647
|
+
} finally {
|
|
53648
|
+
release();
|
|
53733
53649
|
}
|
|
53734
53650
|
}
|
|
53735
|
-
function
|
|
53736
|
-
|
|
53737
|
-
const host = protocol ? hostLabel(upstreamOrigin) + "_" : "";
|
|
53738
|
-
return path7.join(proto, `${host}${createHash4("sha256").update(id, "utf8").digest("hex").slice(0, 24)}.json`);
|
|
53651
|
+
function listSessions() {
|
|
53652
|
+
return [...sessions.values()].sort((a, b2) => b2.lastSeen - a.lastSeen);
|
|
53739
53653
|
}
|
|
53740
|
-
|
|
53741
|
-
|
|
53742
|
-
|
|
53743
|
-
|
|
53744
|
-
|
|
53745
|
-
|
|
53746
|
-
|
|
53747
|
-
|
|
53748
|
-
|
|
53749
|
-
|
|
53750
|
-
|
|
53751
|
-
|
|
53752
|
-
|
|
53753
|
-
|
|
53754
|
-
|
|
53755
|
-
|
|
53756
|
-
|
|
53757
|
-
if (key) {
|
|
53758
|
-
baseLog("info", "[persist] session-file encryption enabled (AES-256-GCM)");
|
|
53759
|
-
} else if (this.codec) {
|
|
53760
|
-
baseLog("info", "[persist] session-file compression enabled (zstd, BILIZSTD1)");
|
|
53761
|
-
}
|
|
53762
|
-
const epermAlert = new PersistEpermAlert({
|
|
53763
|
-
dir: this.dir,
|
|
53764
|
-
threshold: epermAlertThreshold(),
|
|
53765
|
-
repeatMs: epermAlertRepeatMs()
|
|
53766
|
-
});
|
|
53767
|
-
this.store = new StateStore({
|
|
53768
|
-
dir: this.dir,
|
|
53769
|
-
version: PERSIST_VERSION,
|
|
53770
|
-
debounceMs: Math.max(0, debounceMs),
|
|
53771
|
-
enabled: this.enabled,
|
|
53772
|
-
codec: this.codec,
|
|
53773
|
-
log: (level, msg) => {
|
|
53774
|
-
epermAlert.observe(level, msg);
|
|
53775
|
-
baseLog(level, msg);
|
|
53776
|
-
},
|
|
53777
|
-
relPath: (id, payload) => relPathFor(id, payload.meta?.protocol ?? payload.protocol, payload.meta?.upstreamOrigin ?? payload.upstreamOrigin),
|
|
53778
|
-
// Adopt the pre-envelope flat format this store itself wrote
|
|
53779
|
-
// before the kernel extraction (and every v1/v2 file before it).
|
|
53780
|
-
legacy: (parsed) => isValidRecord(parsed) ? { id: parsed.id, payload: parsed, version: parsed.version, savedAt: parsed.savedAt } : null,
|
|
53781
|
-
validate: (envelope) => isValidRecord(envelope.payload)
|
|
53782
|
-
});
|
|
53783
|
-
}
|
|
53784
|
-
/** Bulk-load every persisted session from disk into a map keyed by the
|
|
53785
|
-
* REAL session id (read from the file body, not the filename). Called once
|
|
53786
|
-
* at startup before the server accepts traffic. Corrupt individual files
|
|
53787
|
-
* are skipped (logged) — one bad file never blocks boot. */
|
|
53788
|
-
async loadAll() {
|
|
53789
|
-
const out = /* @__PURE__ */ new Map();
|
|
53790
|
-
if (!this.enabled) return out;
|
|
53791
|
-
let clamped = 0;
|
|
53792
|
-
for (const [id, envelope] of await this.store.loadAll()) {
|
|
53793
|
-
const session = buildSession(envelope.payload);
|
|
53794
|
-
if (hasNegativePersistedTokens(envelope.payload)) {
|
|
53795
|
-
await this.store.writeNow(id, () => buildRecord(session));
|
|
53796
|
-
clamped++;
|
|
53797
|
-
}
|
|
53798
|
-
out.set(id, session);
|
|
53799
|
-
}
|
|
53800
|
-
if (clamped > 0) {
|
|
53801
|
-
log("info", `[persist] one-time migration (#408): clamped negative lastInputTokens/contextTokens in ${clamped} session(s) to 0`);
|
|
53802
|
-
}
|
|
53803
|
-
return out;
|
|
53654
|
+
function peekSession(id) {
|
|
53655
|
+
return sessions.get(id);
|
|
53656
|
+
}
|
|
53657
|
+
function derivedLegacyCanonicalId(sessionId) {
|
|
53658
|
+
return `pfa-${createHash5("sha256").update(`legacy:${sessionId}`).digest("hex").slice(0, 16)}`;
|
|
53659
|
+
}
|
|
53660
|
+
function canonicalIdOf(session) {
|
|
53661
|
+
if (session.id.startsWith("pfa-")) return session.id;
|
|
53662
|
+
const c = session.metadata.canonicalId;
|
|
53663
|
+
if (typeof c === "string" && c.length > 0) return c;
|
|
53664
|
+
return derivedLegacyCanonicalId(session.id);
|
|
53665
|
+
}
|
|
53666
|
+
function ensureCanonicalId(session) {
|
|
53667
|
+
const id = canonicalIdOf(session);
|
|
53668
|
+
if (!session.id.startsWith("pfa-") && session.metadata.canonicalId !== id) {
|
|
53669
|
+
session.metadata.canonicalId = id;
|
|
53670
|
+
markDirty(session);
|
|
53804
53671
|
}
|
|
53805
|
-
|
|
53806
|
-
|
|
53807
|
-
|
|
53808
|
-
|
|
53809
|
-
|
|
53810
|
-
async boot() {
|
|
53811
|
-
if (!this.enabled) return /* @__PURE__ */ new Map();
|
|
53812
|
-
await this.sweepStaleTemps();
|
|
53813
|
-
const loaded = await this.store.loadAll();
|
|
53814
|
-
await this.applyLegacyMigration(loaded);
|
|
53815
|
-
const out = /* @__PURE__ */ new Map();
|
|
53816
|
-
for (const [id, envelope] of loaded) {
|
|
53817
|
-
out.set(id, buildSession(envelope.payload));
|
|
53818
|
-
}
|
|
53819
|
-
return out;
|
|
53672
|
+
return id;
|
|
53673
|
+
}
|
|
53674
|
+
function findSessionByCanonicalId(canonicalId) {
|
|
53675
|
+
for (const s3 of sessions.values()) {
|
|
53676
|
+
if (canonicalIdOf(s3) === canonicalId) return s3;
|
|
53820
53677
|
}
|
|
53821
|
-
|
|
53822
|
-
|
|
53823
|
-
|
|
53824
|
-
|
|
53825
|
-
|
|
53826
|
-
|
|
53827
|
-
* the only thing boot touches is orphaned `.tmp-enc-*` temps from crashed
|
|
53828
|
-
* writes of previous runs (pure deletion of garbage, never content). */
|
|
53829
|
-
async sweepStaleTemps() {
|
|
53830
|
-
let files;
|
|
53831
|
-
try {
|
|
53832
|
-
files = await walkJsonFiles(this.dir);
|
|
53833
|
-
} catch {
|
|
53834
|
-
return;
|
|
53835
|
-
}
|
|
53836
|
-
for (const file of files) {
|
|
53837
|
-
if (STALE_ENC_TEMP_RE.test(path7.basename(file))) {
|
|
53838
|
-
await rm(file, { force: true }).catch(() => {
|
|
53839
|
-
});
|
|
53840
|
-
}
|
|
53841
|
-
}
|
|
53678
|
+
return void 0;
|
|
53679
|
+
}
|
|
53680
|
+
function snapshotMessages(session, messages) {
|
|
53681
|
+
if (messages.length > 0) {
|
|
53682
|
+
session.lastMessages = messages;
|
|
53683
|
+
session.lastMessagesFolded = false;
|
|
53842
53684
|
}
|
|
53843
|
-
|
|
53844
|
-
|
|
53845
|
-
|
|
53846
|
-
|
|
53847
|
-
|
|
53848
|
-
|
|
53849
|
-
|
|
53850
|
-
|
|
53851
|
-
|
|
53852
|
-
|
|
53853
|
-
|
|
53854
|
-
|
|
53855
|
-
|
|
53856
|
-
|
|
53857
|
-
|
|
53858
|
-
|
|
53859
|
-
|
|
53685
|
+
}
|
|
53686
|
+
function markDirty(session) {
|
|
53687
|
+
getStore().scheduleSave(session);
|
|
53688
|
+
}
|
|
53689
|
+
function cacheBlockContent(session, blockId, content) {
|
|
53690
|
+
session.blockContents.set(blockId, content);
|
|
53691
|
+
}
|
|
53692
|
+
function resetSessionCompression(session) {
|
|
53693
|
+
session.state = createInitialState();
|
|
53694
|
+
session.blockContents.clear();
|
|
53695
|
+
session.stats.lastInputTokens = 0;
|
|
53696
|
+
delete session.stats.lastInputTokensSource;
|
|
53697
|
+
session.stats.localInputEstimate = 0;
|
|
53698
|
+
session.stats.contextTokens = 0;
|
|
53699
|
+
session.metadata.nativeCompactionAt = Date.now();
|
|
53700
|
+
markDirty(session);
|
|
53701
|
+
}
|
|
53702
|
+
function markNativeCompactionBoundary(session) {
|
|
53703
|
+
session.metadata.nativeCompactionBoundary = {
|
|
53704
|
+
at: Date.now(),
|
|
53705
|
+
pendingRebase: true
|
|
53706
|
+
};
|
|
53707
|
+
markDirty(session);
|
|
53708
|
+
}
|
|
53709
|
+
function reconcileNativeCompactionBoundary(session) {
|
|
53710
|
+
const boundary = session.metadata.nativeCompactionBoundary;
|
|
53711
|
+
if (!boundary || typeof boundary !== "object" || !boundary.pendingRebase) {
|
|
53712
|
+
return false;
|
|
53860
53713
|
}
|
|
53861
|
-
|
|
53862
|
-
|
|
53714
|
+
resetSessionCompression(session);
|
|
53715
|
+
session.metadata.nativeCompactionBoundary = {
|
|
53716
|
+
...boundary,
|
|
53717
|
+
pendingRebase: false,
|
|
53718
|
+
rebasedAt: Date.now()
|
|
53719
|
+
};
|
|
53720
|
+
markDirty(session);
|
|
53721
|
+
return true;
|
|
53722
|
+
}
|
|
53723
|
+
function markCompactionBoundary(session) {
|
|
53724
|
+
session.metadata.compactionBoundary = {
|
|
53725
|
+
at: Date.now(),
|
|
53726
|
+
pending: true
|
|
53727
|
+
};
|
|
53728
|
+
markDirty(session);
|
|
53729
|
+
}
|
|
53730
|
+
function readPreCompactionArchive(session) {
|
|
53731
|
+
const raw = session.metadata.preCompactionArchive;
|
|
53732
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
53733
|
+
return raw;
|
|
53863
53734
|
}
|
|
53864
|
-
|
|
53865
|
-
|
|
53866
|
-
|
|
53867
|
-
|
|
53868
|
-
|
|
53869
|
-
|
|
53870
|
-
|
|
53871
|
-
|
|
53872
|
-
|
|
53873
|
-
if (!label) {
|
|
53874
|
-
unlabeled++;
|
|
53875
|
-
continue;
|
|
53876
|
-
}
|
|
53877
|
-
if (label === id) {
|
|
53878
|
-
claimed.add(id);
|
|
53879
|
-
continue;
|
|
53880
|
-
}
|
|
53881
|
-
const prev = byLabel.get(label);
|
|
53882
|
-
if (!prev || envelope.savedAt >= prev.savedAt) {
|
|
53883
|
-
if (prev) {
|
|
53884
|
-
await this.removeLegacyFile(prev.id, prev.session);
|
|
53885
|
-
loaded.delete(prev.id);
|
|
53886
|
-
}
|
|
53887
|
-
byLabel.set(label, { id, savedAt: envelope.savedAt, session });
|
|
53888
|
-
} else {
|
|
53889
|
-
await this.removeLegacyFile(id, session);
|
|
53890
|
-
loaded.delete(id);
|
|
53891
|
-
}
|
|
53892
|
-
}
|
|
53893
|
-
let rekeyed = 0;
|
|
53894
|
-
for (const [label, { id, session }] of byLabel) {
|
|
53895
|
-
if (claimed.has(label)) {
|
|
53896
|
-
await this.removeLegacyFile(id, session);
|
|
53897
|
-
loaded.delete(id);
|
|
53898
|
-
continue;
|
|
53899
|
-
}
|
|
53900
|
-
session.id = label;
|
|
53901
|
-
await this.store.writeNow(label, () => buildRecord(session));
|
|
53902
|
-
await this.removeLegacyFile(id, session);
|
|
53903
|
-
const envelope = loaded.get(id);
|
|
53904
|
-
if (envelope) {
|
|
53905
|
-
loaded.set(label, { ...envelope, id: label, payload: { ...envelope.payload, id: label } });
|
|
53906
|
-
}
|
|
53907
|
-
loaded.delete(id);
|
|
53908
|
-
claimed.add(label);
|
|
53909
|
-
rekeyed++;
|
|
53910
|
-
}
|
|
53911
|
-
try {
|
|
53912
|
-
mkdirSync3(this.dir, { recursive: true });
|
|
53913
|
-
writeFileSync2(this.markerPath(), String(Date.now()), "utf8");
|
|
53914
|
-
} catch {
|
|
53915
|
-
}
|
|
53916
|
-
if (rekeyed || unlabeled) {
|
|
53917
|
-
log("info", `[persist] one-time migration (#286): rekeyed ${rekeyed} legacy session(s), left ${unlabeled} unlabeled legacy file(s) in place`);
|
|
53918
|
-
}
|
|
53735
|
+
return {};
|
|
53736
|
+
}
|
|
53737
|
+
function preCompactionArchiveOf(session) {
|
|
53738
|
+
return readPreCompactionArchive(session);
|
|
53739
|
+
}
|
|
53740
|
+
function applyCompactionArchive(session, activeBefore, liveRawIds, log2) {
|
|
53741
|
+
const boundary = session.metadata.compactionBoundary;
|
|
53742
|
+
if (!boundary || typeof boundary !== "object" || !boundary.pending) {
|
|
53743
|
+
return;
|
|
53919
53744
|
}
|
|
53920
|
-
|
|
53921
|
-
|
|
53922
|
-
|
|
53923
|
-
|
|
53924
|
-
|
|
53925
|
-
const
|
|
53926
|
-
|
|
53927
|
-
relPathFor(id),
|
|
53928
|
-
flatFileNameFor(id)
|
|
53929
|
-
]);
|
|
53930
|
-
for (const rel2 of candidates) {
|
|
53931
|
-
await rm(path7.join(this.dir, rel2), { force: true }).catch(() => {
|
|
53932
|
-
});
|
|
53745
|
+
const activeAfter = new Set(session.state.blocks.filter((b2) => b2.active).map((b2) => b2.blockId));
|
|
53746
|
+
const deactivated = [...activeBefore].filter((id) => !activeAfter.has(id));
|
|
53747
|
+
if (deactivated.length > 0) {
|
|
53748
|
+
const archive = readPreCompactionArchive(session);
|
|
53749
|
+
const at2 = Date.now();
|
|
53750
|
+
for (const id of deactivated) {
|
|
53751
|
+
archive[id] = { at: at2, reason: "content replaced by client native compaction summary" };
|
|
53933
53752
|
}
|
|
53753
|
+
session.metadata.preCompactionArchive = archive;
|
|
53934
53754
|
}
|
|
53935
|
-
|
|
53936
|
-
|
|
53937
|
-
|
|
53938
|
-
|
|
53939
|
-
const envelopes = [
|
|
53940
|
-
this.store.loadSync(id, relPathFor(id, meta?.protocol, meta?.upstreamOrigin)),
|
|
53941
|
-
meta?.protocol ? this.store.loadSync(id, relPathFor(id)) : null
|
|
53942
|
-
];
|
|
53943
|
-
for (const envelope of envelopes) {
|
|
53944
|
-
if (envelope) return envelope;
|
|
53945
|
-
}
|
|
53946
|
-
return null;
|
|
53755
|
+
const { byRaw, byRef } = session.state.messageRefs;
|
|
53756
|
+
const prunedByRaw = {};
|
|
53757
|
+
for (const [rawId, ref] of Object.entries(byRaw)) {
|
|
53758
|
+
if (liveRawIds.has(rawId)) prunedByRaw[rawId] = ref;
|
|
53947
53759
|
}
|
|
53948
|
-
|
|
53949
|
-
|
|
53950
|
-
|
|
53951
|
-
* body id does not match what we asked for. */
|
|
53952
|
-
loadSync(id, meta) {
|
|
53953
|
-
if (!this.enabled) return null;
|
|
53954
|
-
const envelope = this.loadEnvelope(id, meta);
|
|
53955
|
-
if (!envelope) return null;
|
|
53956
|
-
const session = buildSession(envelope.payload);
|
|
53957
|
-
if (hasNegativePersistedTokens(envelope.payload)) {
|
|
53958
|
-
this.scheduleSave(session);
|
|
53959
|
-
log("info", `[persist] clamped negative token stats on reload for ${id} (#408)`);
|
|
53960
|
-
}
|
|
53961
|
-
return session;
|
|
53760
|
+
const prunedByRef = {};
|
|
53761
|
+
for (const [ref, rawId] of Object.entries(byRef)) {
|
|
53762
|
+
if (liveRawIds.has(rawId)) prunedByRef[ref] = rawId;
|
|
53962
53763
|
}
|
|
53963
|
-
|
|
53964
|
-
|
|
53965
|
-
|
|
53966
|
-
|
|
53967
|
-
|
|
53968
|
-
|
|
53969
|
-
|
|
53764
|
+
session.state.messageRefs.byRaw = prunedByRaw;
|
|
53765
|
+
session.state.messageRefs.byRef = prunedByRef;
|
|
53766
|
+
session.metadata.compactionBoundary = {
|
|
53767
|
+
...boundary,
|
|
53768
|
+
pending: false,
|
|
53769
|
+
archivedAt: Date.now(),
|
|
53770
|
+
archivedBlocks: deactivated
|
|
53771
|
+
};
|
|
53772
|
+
markDirty(session);
|
|
53773
|
+
log2("info", `[${session.id}] native compaction boundary: archived ${deactivated.length} pre-compaction block(s)${deactivated.length > 0 ? ` (${deactivated.join(", ")})` : ""}; pruned ref maps to ${prunedByRaw.length} live raw id(s)`);
|
|
53774
|
+
}
|
|
53775
|
+
var REWRITE_MIN_KNOWN_REFS = 20;
|
|
53776
|
+
var REWRITE_MAX_KNOWN_RATIO = 0.5;
|
|
53777
|
+
var REWRITE_MIN_INCOMING_TOTAL = 10;
|
|
53778
|
+
function detectUnannouncedHistoryRewrite(session, knownRefsBefore, liveRawIds) {
|
|
53779
|
+
const knownBefore = knownRefsBefore.size;
|
|
53780
|
+
let incomingTotal = 0;
|
|
53781
|
+
let knownIncoming = 0;
|
|
53782
|
+
for (const id of liveRawIds) {
|
|
53783
|
+
incomingTotal++;
|
|
53784
|
+
if (knownRefsBefore.has(id)) knownIncoming++;
|
|
53970
53785
|
}
|
|
53971
|
-
|
|
53972
|
-
|
|
53973
|
-
|
|
53974
|
-
|
|
53975
|
-
|
|
53976
|
-
|
|
53977
|
-
|
|
53978
|
-
|
|
53979
|
-
if (
|
|
53980
|
-
|
|
53981
|
-
|
|
53982
|
-
const incRequests = incoming.stats?.requests ?? incoming.requests ?? 0;
|
|
53983
|
-
if (incRequests < diskRequests) return disk;
|
|
53984
|
-
if (incRequests === diskRequests) {
|
|
53985
|
-
const diskBlocks = disk.state?.nextBlockId ?? 0;
|
|
53986
|
-
const incBlocks = incoming.state?.nextBlockId ?? 0;
|
|
53987
|
-
if (incBlocks < diskBlocks) return disk;
|
|
53786
|
+
const detected = knownBefore >= REWRITE_MIN_KNOWN_REFS && session.state.blocks.length > 0 && incomingTotal >= REWRITE_MIN_INCOMING_TOTAL && knownIncoming > 0 && knownIncoming / incomingTotal < REWRITE_MAX_KNOWN_RATIO;
|
|
53787
|
+
return { detected, knownBefore, incomingTotal, knownIncoming };
|
|
53788
|
+
}
|
|
53789
|
+
function evictOldest() {
|
|
53790
|
+
let oldestId;
|
|
53791
|
+
let oldestSeen = Infinity;
|
|
53792
|
+
for (const [id, s4] of sessions) {
|
|
53793
|
+
if (s4.inFlight > 0) continue;
|
|
53794
|
+
if (s4.lastSeen < oldestSeen) {
|
|
53795
|
+
oldestSeen = s4.lastSeen;
|
|
53796
|
+
oldestId = id;
|
|
53988
53797
|
}
|
|
53989
|
-
return null;
|
|
53990
|
-
}
|
|
53991
|
-
guardedBuild(session) {
|
|
53992
|
-
return () => {
|
|
53993
|
-
const record = buildRecord(session);
|
|
53994
|
-
const disk = this.staleDiskPayload(record);
|
|
53995
|
-
if (disk === null) return record;
|
|
53996
|
-
const now = Date.now();
|
|
53997
|
-
const last = this.staleWarnAt.get(record.id) ?? 0;
|
|
53998
|
-
if (now - last >= STALE_WARN_THROTTLE_MS) {
|
|
53999
|
-
this.staleWarnAt.set(record.id, now);
|
|
54000
|
-
this.log(
|
|
54001
|
-
"warn",
|
|
54002
|
-
`[persist] rejected stale snapshot for session ${record.id}: in-memory copy is older than the on-disk one (another bili instance holds newer state) \u2014 keeping disk state, no rollback (#405)`
|
|
54003
|
-
);
|
|
54004
|
-
}
|
|
54005
|
-
return disk;
|
|
54006
|
-
};
|
|
54007
53798
|
}
|
|
54008
|
-
|
|
54009
|
-
|
|
54010
|
-
|
|
54011
|
-
|
|
54012
|
-
|
|
54013
|
-
this.store.scheduleSave(session.id, this.guardedBuild(session));
|
|
54014
|
-
}
|
|
54015
|
-
/** Asynchronously persist a session right now (skips the debounce). Throws
|
|
54016
|
-
* on write failure so callers can react (e.g. avoid evicting). Serialized
|
|
54017
|
-
* per-session by the kernel store's write chains. */
|
|
54018
|
-
async writeNow(session) {
|
|
54019
|
-
await this.store.writeNow(session.id, this.guardedBuild(session));
|
|
53799
|
+
if (!oldestId) return false;
|
|
53800
|
+
const s3 = sessions.get(oldestId);
|
|
53801
|
+
const ok = getStore().flushSync(s3);
|
|
53802
|
+
if (!ok && !s3.persisted) {
|
|
53803
|
+
return false;
|
|
54020
53804
|
}
|
|
54021
|
-
|
|
54022
|
-
|
|
54023
|
-
|
|
54024
|
-
|
|
54025
|
-
|
|
54026
|
-
|
|
54027
|
-
|
|
53805
|
+
sessions.delete(oldestId);
|
|
53806
|
+
return true;
|
|
53807
|
+
}
|
|
53808
|
+
async function flushAllSessions() {
|
|
53809
|
+
await getStore().flushAll(sessions.values());
|
|
53810
|
+
}
|
|
53811
|
+
|
|
53812
|
+
// src/update.ts
|
|
53813
|
+
import { readFile as readFile3, writeFile as writeFile2, mkdir as mkdir2, access, constants, rm as rm2, cp, unlink } from "fs/promises";
|
|
53814
|
+
import { execFile as execFile2 } from "child_process";
|
|
53815
|
+
import { realpathSync } from "fs";
|
|
53816
|
+
import crypto from "crypto";
|
|
53817
|
+
|
|
53818
|
+
// node_modules/tar/dist/esm/index.min.js
|
|
53819
|
+
import Qr from "events";
|
|
53820
|
+
import I from "fs";
|
|
53821
|
+
import { EventEmitter as Di } from "events";
|
|
53822
|
+
import Cs from "stream";
|
|
53823
|
+
import { StringDecoder as Hr } from "string_decoder";
|
|
53824
|
+
import cr from "path";
|
|
53825
|
+
import Kt from "fs";
|
|
53826
|
+
import { dirname as Fn, parse as kn } from "path";
|
|
53827
|
+
import { EventEmitter as Dn } from "events";
|
|
53828
|
+
import zi from "assert";
|
|
53829
|
+
import { Buffer as Ot } from "buffer";
|
|
53830
|
+
import * as Ps from "zlib";
|
|
53831
|
+
import en from "zlib";
|
|
53832
|
+
import { posix as Zt } from "path";
|
|
53833
|
+
import { basename as _n } from "path";
|
|
53834
|
+
import mi from "fs";
|
|
53835
|
+
import X from "fs";
|
|
53836
|
+
import js from "path";
|
|
53837
|
+
import { win32 as Pn } from "path";
|
|
53838
|
+
import ar from "path";
|
|
53839
|
+
import Br from "fs";
|
|
53840
|
+
import co from "assert";
|
|
53841
|
+
import { randomBytes as Mr } from "crypto";
|
|
53842
|
+
import u from "fs";
|
|
53843
|
+
import R from "path";
|
|
53844
|
+
import pr from "fs";
|
|
53845
|
+
import wi from "fs";
|
|
53846
|
+
import we from "path";
|
|
53847
|
+
import k from "fs";
|
|
53848
|
+
import ro from "fs/promises";
|
|
53849
|
+
import Si from "path";
|
|
53850
|
+
import { join as xr } from "path";
|
|
53851
|
+
import v from "fs";
|
|
53852
|
+
import Pr from "path";
|
|
53853
|
+
var zr = Object.defineProperty;
|
|
53854
|
+
var Ur = (s3, t) => {
|
|
53855
|
+
for (var e in t) zr(s3, e, { get: t[e], enumerable: true });
|
|
53856
|
+
};
|
|
53857
|
+
var Ds = typeof process == "object" && process ? process : { stdout: null, stderr: null };
|
|
53858
|
+
var Wr = (s3) => !!s3 && typeof s3 == "object" && (s3 instanceof A || s3 instanceof Cs || Gr(s3) || Zr(s3));
|
|
53859
|
+
var Gr = (s3) => !!s3 && typeof s3 == "object" && s3 instanceof Di && typeof s3.pipe == "function" && s3.pipe !== Cs.Writable.prototype.pipe;
|
|
53860
|
+
var Zr = (s3) => !!s3 && typeof s3 == "object" && s3 instanceof Di && typeof s3.write == "function" && typeof s3.end == "function";
|
|
53861
|
+
var Q = /* @__PURE__ */ Symbol("EOF");
|
|
53862
|
+
var J = /* @__PURE__ */ Symbol("maybeEmitEnd");
|
|
53863
|
+
var nt = /* @__PURE__ */ Symbol("emittedEnd");
|
|
53864
|
+
var De = /* @__PURE__ */ Symbol("emittingEnd");
|
|
53865
|
+
var qt = /* @__PURE__ */ Symbol("emittedError");
|
|
53866
|
+
var Ne = /* @__PURE__ */ Symbol("closed");
|
|
53867
|
+
var Ns = /* @__PURE__ */ Symbol("read");
|
|
53868
|
+
var Ae = /* @__PURE__ */ Symbol("flush");
|
|
53869
|
+
var As = /* @__PURE__ */ Symbol("flushChunk");
|
|
53870
|
+
var z = /* @__PURE__ */ Symbol("encoding");
|
|
53871
|
+
var Mt = /* @__PURE__ */ Symbol("decoder");
|
|
53872
|
+
var g = /* @__PURE__ */ Symbol("flowing");
|
|
53873
|
+
var Qt = /* @__PURE__ */ Symbol("paused");
|
|
53874
|
+
var Bt = /* @__PURE__ */ Symbol("resume");
|
|
53875
|
+
var b = /* @__PURE__ */ Symbol("buffer");
|
|
53876
|
+
var N = /* @__PURE__ */ Symbol("pipes");
|
|
53877
|
+
var _ = /* @__PURE__ */ Symbol("bufferLength");
|
|
53878
|
+
var bi = /* @__PURE__ */ Symbol("bufferPush");
|
|
53879
|
+
var Ie = /* @__PURE__ */ Symbol("bufferShift");
|
|
53880
|
+
var L = /* @__PURE__ */ Symbol("objectMode");
|
|
53881
|
+
var S = /* @__PURE__ */ Symbol("destroyed");
|
|
53882
|
+
var _i = /* @__PURE__ */ Symbol("error");
|
|
53883
|
+
var Oi = /* @__PURE__ */ Symbol("emitData");
|
|
53884
|
+
var Is = /* @__PURE__ */ Symbol("emitEnd");
|
|
53885
|
+
var Ti = /* @__PURE__ */ Symbol("emitEnd2");
|
|
53886
|
+
var Z = /* @__PURE__ */ Symbol("async");
|
|
53887
|
+
var xi = /* @__PURE__ */ Symbol("abort");
|
|
53888
|
+
var Ce = /* @__PURE__ */ Symbol("aborted");
|
|
53889
|
+
var Jt = /* @__PURE__ */ Symbol("signal");
|
|
53890
|
+
var Rt = /* @__PURE__ */ Symbol("dataListeners");
|
|
53891
|
+
var C = /* @__PURE__ */ Symbol("discarded");
|
|
53892
|
+
var jt = (s3) => Promise.resolve().then(s3);
|
|
53893
|
+
var Yr = (s3) => s3();
|
|
53894
|
+
var Kr = (s3) => s3 === "end" || s3 === "finish" || s3 === "prefinish";
|
|
53895
|
+
var Vr = (s3) => s3 instanceof ArrayBuffer || !!s3 && typeof s3 == "object" && s3.constructor && s3.constructor.name === "ArrayBuffer" && s3.byteLength >= 0;
|
|
53896
|
+
var $r = (s3) => !Buffer.isBuffer(s3) && ArrayBuffer.isView(s3);
|
|
53897
|
+
var Fe = class {
|
|
53898
|
+
src;
|
|
53899
|
+
dest;
|
|
53900
|
+
opts;
|
|
53901
|
+
ondrain;
|
|
53902
|
+
constructor(t, e, i) {
|
|
53903
|
+
this.src = t, this.dest = e, this.opts = i, this.ondrain = () => t[Bt](), this.dest.on("drain", this.ondrain);
|
|
54028
53904
|
}
|
|
54029
|
-
|
|
54030
|
-
|
|
54031
|
-
* pending set (builders read the live Session objects at write time, so
|
|
54032
|
-
* no session list is needed) and drains in-flight write chains. */
|
|
54033
|
-
async flushAll(_sessions) {
|
|
54034
|
-
await this.store.flushAll();
|
|
53905
|
+
unpipe() {
|
|
53906
|
+
this.dest.removeListener("drain", this.ondrain);
|
|
54035
53907
|
}
|
|
54036
|
-
|
|
54037
|
-
hasPending(id) {
|
|
54038
|
-
return this.store.hasPending(id);
|
|
53908
|
+
proxyErrors(t) {
|
|
54039
53909
|
}
|
|
54040
|
-
|
|
54041
|
-
|
|
54042
|
-
this.store.cancelAll();
|
|
53910
|
+
end() {
|
|
53911
|
+
this.unpipe(), this.opts.end && this.dest.end();
|
|
54043
53912
|
}
|
|
54044
53913
|
};
|
|
54045
|
-
|
|
54046
|
-
|
|
54047
|
-
|
|
54048
|
-
version: PERSIST_VERSION,
|
|
54049
|
-
savedAt: Date.now(),
|
|
54050
|
-
id: session.id,
|
|
54051
|
-
meta: { ...session.meta },
|
|
54052
|
-
stats: { ...session.stats },
|
|
54053
|
-
messages: snapshot,
|
|
54054
|
-
messagesFolded: snapshot ? true : void 0,
|
|
54055
|
-
metadata: { ...session.metadata },
|
|
54056
|
-
state: session.state,
|
|
54057
|
-
blockContents: Object.fromEntries(session.blockContents),
|
|
54058
|
-
createdAt: session.createdAt
|
|
54059
|
-
};
|
|
54060
|
-
}
|
|
54061
|
-
function isBlockView(v2) {
|
|
54062
|
-
return !!v2 && typeof v2 === "object" && typeof v2.text === "string" && typeof v2.count === "number";
|
|
54063
|
-
}
|
|
54064
|
-
function buildSession(parsed) {
|
|
54065
|
-
const blockContents = /* @__PURE__ */ new Map();
|
|
54066
|
-
for (const [bid, content] of Object.entries(parsed.blockContents ?? {})) {
|
|
54067
|
-
if (!content || typeof content !== "object") continue;
|
|
54068
|
-
const full = content.full;
|
|
54069
|
-
if (!isBlockView(full)) continue;
|
|
54070
|
-
const one = content.one;
|
|
54071
|
-
const oneView = isBlockView(one) ? one : null;
|
|
54072
|
-
blockContents.set(bid, {
|
|
54073
|
-
one: oneView && !(oneView.text === full.text && oneView.count === full.count) ? oneView : null,
|
|
54074
|
-
full
|
|
54075
|
-
});
|
|
53914
|
+
var Li = class extends Fe {
|
|
53915
|
+
unpipe() {
|
|
53916
|
+
this.src.removeListener("error", this.proxyErrors), super.unpipe();
|
|
54076
53917
|
}
|
|
54077
|
-
|
|
54078
|
-
|
|
54079
|
-
return {
|
|
54080
|
-
id: parsed.id,
|
|
54081
|
-
meta: {
|
|
54082
|
-
protocol: meta.protocol ?? parsed.protocol,
|
|
54083
|
-
upstreamOrigin: meta.upstreamOrigin ?? parsed.upstreamOrigin,
|
|
54084
|
-
label: meta.label ?? parsed.label,
|
|
54085
|
-
title: meta.title
|
|
54086
|
-
},
|
|
54087
|
-
stats: {
|
|
54088
|
-
requests: stats.requests ?? parsed.requests ?? 0,
|
|
54089
|
-
tokensSaved: stats.tokensSaved ?? parsed.tokensSaved ?? 0,
|
|
54090
|
-
inputTokens: stats.inputTokens ?? parsed.inputTokens ?? 0,
|
|
54091
|
-
cachedTokens: stats.cachedTokens ?? parsed.cachedTokens ?? 0,
|
|
54092
|
-
outputTokens: stats.outputTokens ?? parsed.outputTokens ?? 0,
|
|
54093
|
-
cacheSamples: stats.cacheSamples ?? parsed.cacheSamples ?? 0,
|
|
54094
|
-
// #408: clamp at restore — pre-clamp versions persisted negative
|
|
54095
|
-
// values (lastInputTokens = total − credit before the Math.max
|
|
54096
|
-
// guard existed) which would otherwise revive after upgrade and
|
|
54097
|
-
// feed the /acp panel + web stats as negative percentages.
|
|
54098
|
-
lastInputTokens: Math.max(0, stats.lastInputTokens ?? parsed.lastInputTokens ?? 0),
|
|
54099
|
-
// #857: provenance — legacy files lack it; absent stays absent and
|
|
54100
|
-
// evidence-grade consumers treat absent as untrusted.
|
|
54101
|
-
lastInputTokensSource: stats.lastInputTokensSource === "usage" || stats.lastInputTokensSource === "estimate" ? stats.lastInputTokensSource : void 0,
|
|
54102
|
-
// In-memory only — a fresh process has no pending compress fold.
|
|
54103
|
-
compressCreditTokens: 0,
|
|
54104
|
-
contextTokens: Math.max(0, stats.contextTokens ?? parsed.contextTokens ?? 0)
|
|
54105
|
-
},
|
|
54106
|
-
metadata: parsed.metadata ?? {},
|
|
54107
|
-
state: mergeState(parsed.state),
|
|
54108
|
-
createdAt: parsed.createdAt ?? Date.now(),
|
|
54109
|
-
// #404: lastSeen reflects the on-disk savedAt (the last real
|
|
54110
|
-
// activity), NOT the restore moment — a restart must not fabricate
|
|
54111
|
-
// activity for every session (broke fallback=latest ties, panel
|
|
54112
|
-
// freshness, and eviction ordering). Consumers that need "has this
|
|
54113
|
-
// session been used since boot" read the restored flag.
|
|
54114
|
-
lastSeen: parsed.savedAt ?? Date.now(),
|
|
54115
|
-
restored: true,
|
|
54116
|
-
blockContents,
|
|
54117
|
-
lastMessages: Array.isArray(parsed.messages) ? parsed.messages : void 0,
|
|
54118
|
-
lastMessagesFolded: parsed.messagesFolded === true,
|
|
54119
|
-
inFlight: 0,
|
|
54120
|
-
persisted: true
|
|
54121
|
-
};
|
|
54122
|
-
}
|
|
54123
|
-
function isValidRecord(parsed) {
|
|
54124
|
-
if (!parsed || typeof parsed !== "object") return false;
|
|
54125
|
-
const r = parsed;
|
|
54126
|
-
return typeof r.id === "string" && typeof r.state === "object" && r.state !== null && Array.isArray(r.state.blocks);
|
|
54127
|
-
}
|
|
54128
|
-
function hasNegativePersistedTokens(parsed) {
|
|
54129
|
-
const stats = parsed.stats ?? {};
|
|
54130
|
-
const last = stats.lastInputTokens ?? parsed.lastInputTokens;
|
|
54131
|
-
const ctx = stats.contextTokens ?? parsed.contextTokens;
|
|
54132
|
-
return typeof last === "number" && last < 0 || typeof ctx === "number" && ctx < 0;
|
|
54133
|
-
}
|
|
54134
|
-
function defaultDir() {
|
|
54135
|
-
return sessionsDir();
|
|
54136
|
-
}
|
|
54137
|
-
function defaultDebounce() {
|
|
54138
|
-
const env = process.env.BILI_PERSIST_DEBOUNCE_MS;
|
|
54139
|
-
if (env) {
|
|
54140
|
-
const n = Number.parseInt(env, 10);
|
|
54141
|
-
if (Number.isFinite(n) && n >= 0) return n;
|
|
53918
|
+
constructor(t, e, i) {
|
|
53919
|
+
super(t, e, i), this.proxyErrors = (r) => this.dest.emit("error", r), t.on("error", this.proxyErrors);
|
|
54142
53920
|
}
|
|
54143
|
-
|
|
54144
|
-
|
|
54145
|
-
|
|
54146
|
-
|
|
54147
|
-
|
|
54148
|
-
|
|
54149
|
-
|
|
54150
|
-
|
|
54151
|
-
|
|
54152
|
-
|
|
54153
|
-
|
|
54154
|
-
|
|
54155
|
-
|
|
54156
|
-
|
|
54157
|
-
|
|
54158
|
-
|
|
54159
|
-
|
|
54160
|
-
|
|
54161
|
-
|
|
54162
|
-
|
|
54163
|
-
|
|
54164
|
-
|
|
53921
|
+
};
|
|
53922
|
+
var Xr = (s3) => !!s3.objectMode;
|
|
53923
|
+
var qr = (s3) => !s3.objectMode && !!s3.encoding && s3.encoding !== "buffer";
|
|
53924
|
+
var A = class extends Di {
|
|
53925
|
+
[g] = false;
|
|
53926
|
+
[Qt] = false;
|
|
53927
|
+
[N] = [];
|
|
53928
|
+
[b] = [];
|
|
53929
|
+
[L];
|
|
53930
|
+
[z];
|
|
53931
|
+
[Z];
|
|
53932
|
+
[Mt];
|
|
53933
|
+
[Q] = false;
|
|
53934
|
+
[nt] = false;
|
|
53935
|
+
[De] = false;
|
|
53936
|
+
[Ne] = false;
|
|
53937
|
+
[qt] = null;
|
|
53938
|
+
[_] = 0;
|
|
53939
|
+
[S] = false;
|
|
53940
|
+
[Jt];
|
|
53941
|
+
[Ce] = false;
|
|
53942
|
+
[Rt] = 0;
|
|
53943
|
+
[C] = false;
|
|
53944
|
+
writable = true;
|
|
53945
|
+
readable = true;
|
|
53946
|
+
constructor(...t) {
|
|
53947
|
+
let e = t[0] || {};
|
|
53948
|
+
if (super(), e.objectMode && typeof e.encoding == "string") throw new TypeError("Encoding and objectMode may not be used together");
|
|
53949
|
+
Xr(e) ? (this[L] = true, this[z] = null) : qr(e) ? (this[z] = e.encoding, this[L] = false) : (this[L] = false, this[z] = null), this[Z] = !!e.async, this[Mt] = this[z] ? new Hr(this[z]) : null, e && e.debugExposeBuffer === true && Object.defineProperty(this, "buffer", { get: () => this[b] }), e && e.debugExposePipes === true && Object.defineProperty(this, "pipes", { get: () => this[N] });
|
|
53950
|
+
let { signal: i } = e;
|
|
53951
|
+
i && (this[Jt] = i, i.aborted ? this[xi]() : i.addEventListener("abort", () => this[xi]()));
|
|
54165
53952
|
}
|
|
54166
|
-
|
|
54167
|
-
|
|
54168
|
-
function persistTailTokens() {
|
|
54169
|
-
const env = process.env.BILI_PERSIST_TAIL_TOKENS;
|
|
54170
|
-
if (env) {
|
|
54171
|
-
const n = Number.parseInt(env, 10);
|
|
54172
|
-
if (Number.isFinite(n) && n >= 0) return n;
|
|
53953
|
+
get bufferLength() {
|
|
53954
|
+
return this[_];
|
|
54173
53955
|
}
|
|
54174
|
-
|
|
54175
|
-
|
|
54176
|
-
function boundedFoldedSnapshot(session) {
|
|
54177
|
-
const msgs = session.lastMessages;
|
|
54178
|
-
if (!msgs || msgs.length === 0) return void 0;
|
|
54179
|
-
const budget = persistTailTokens();
|
|
54180
|
-
if (budget === 0) return void 0;
|
|
54181
|
-
let view = prune(msgs, session.state);
|
|
54182
|
-
let total = 0;
|
|
54183
|
-
for (const m2 of view) total += defaultCountTokens(m2.text ?? "");
|
|
54184
|
-
if (total > budget) {
|
|
54185
|
-
let acc = 0;
|
|
54186
|
-
let start = 0;
|
|
54187
|
-
for (let i = view.length - 1; i >= 0; i--) {
|
|
54188
|
-
acc += defaultCountTokens(view[i].text ?? "");
|
|
54189
|
-
if (acc > budget) {
|
|
54190
|
-
start = Math.min(i + 1, view.length - 1);
|
|
54191
|
-
break;
|
|
54192
|
-
}
|
|
54193
|
-
}
|
|
54194
|
-
if (start > 0) view = view.slice(start);
|
|
53956
|
+
get encoding() {
|
|
53957
|
+
return this[z];
|
|
54195
53958
|
}
|
|
54196
|
-
|
|
54197
|
-
|
|
54198
|
-
function epermAlertThreshold() {
|
|
54199
|
-
const env = process.env.BILI_PERSIST_EPERM_ALERT_THRESHOLD;
|
|
54200
|
-
if (env) {
|
|
54201
|
-
const n = Number.parseInt(env, 10);
|
|
54202
|
-
if (Number.isFinite(n) && n > 0) return n;
|
|
53959
|
+
set encoding(t) {
|
|
53960
|
+
throw new Error("Encoding must be set at instantiation time");
|
|
54203
53961
|
}
|
|
54204
|
-
|
|
54205
|
-
|
|
54206
|
-
function epermAlertRepeatMs() {
|
|
54207
|
-
const env = process.env.BILI_PERSIST_EPERM_ALERT_REPEAT_MS;
|
|
54208
|
-
if (env) {
|
|
54209
|
-
const n = Number.parseInt(env, 10);
|
|
54210
|
-
if (Number.isFinite(n) && n >= 0) return n;
|
|
53962
|
+
setEncoding(t) {
|
|
53963
|
+
throw new Error("Encoding must be set at instantiation time");
|
|
54211
53964
|
}
|
|
54212
|
-
|
|
54213
|
-
|
|
54214
|
-
function defaultLogger(level, m2) {
|
|
54215
|
-
log(level, m2);
|
|
54216
|
-
}
|
|
54217
|
-
var _store = null;
|
|
54218
|
-
function getStore() {
|
|
54219
|
-
if (!_store) {
|
|
54220
|
-
_store = new SessionStore({ enabled: persistEnabled(), log: defaultLogger });
|
|
53965
|
+
get objectMode() {
|
|
53966
|
+
return this[L];
|
|
54221
53967
|
}
|
|
54222
|
-
|
|
54223
|
-
|
|
54224
|
-
|
|
54225
|
-
// src/session.ts
|
|
54226
|
-
function lastCompressSuffix(info) {
|
|
54227
|
-
if (!info) return "";
|
|
54228
|
-
return ` [after compress: shrink ${Math.round(info.shrinkRatio * 100)}% foldPoint=${info.foldPoint} blocks=${info.blocks} ~${info.tokensCompressed}tok]`;
|
|
54229
|
-
}
|
|
54230
|
-
function storeEffectiveConfig(session, config) {
|
|
54231
|
-
session.metadata["effectiveConfig"] = config;
|
|
54232
|
-
}
|
|
54233
|
-
function effectiveConfig(session, fallback) {
|
|
54234
|
-
const stored = session?.metadata["effectiveConfig"];
|
|
54235
|
-
if (stored && typeof stored === "object") return { ...fallback, ...stored };
|
|
54236
|
-
return fallback;
|
|
54237
|
-
}
|
|
54238
|
-
var sessions = /* @__PURE__ */ new Map();
|
|
54239
|
-
var MAX_SESSIONS = Math.max(1, Number.parseInt(process.env.BILI_MAX_SESSIONS ?? "256", 10) || 256);
|
|
54240
|
-
var initialized = false;
|
|
54241
|
-
async function initSessions() {
|
|
54242
|
-
if (initialized) return;
|
|
54243
|
-
initialized = true;
|
|
54244
|
-
const store = getStore();
|
|
54245
|
-
if (!store.enabled) return;
|
|
54246
|
-
const loaded = await store.boot();
|
|
54247
|
-
if (loaded.size > MAX_SESSIONS) {
|
|
54248
|
-
const freshness = (s3) => Math.max(s3.createdAt ?? 0, s3.lastSeen ?? 0);
|
|
54249
|
-
const entries = [...loaded.entries()].sort((a, b2) => freshness(b2[1]) - freshness(a[1]));
|
|
54250
|
-
for (const [id, s3] of entries) {
|
|
54251
|
-
if (sessions.size >= MAX_SESSIONS) break;
|
|
54252
|
-
sessions.set(id, s3);
|
|
54253
|
-
}
|
|
54254
|
-
} else {
|
|
54255
|
-
for (const [id, s3] of loaded) sessions.set(id, s3);
|
|
53968
|
+
set objectMode(t) {
|
|
53969
|
+
throw new Error("objectMode must be set at instantiation time");
|
|
54256
53970
|
}
|
|
54257
|
-
|
|
54258
|
-
|
|
54259
|
-
const existing = sessions.get(id);
|
|
54260
|
-
if (existing) {
|
|
54261
|
-
existing.lastSeen = Date.now();
|
|
54262
|
-
existing.restored = false;
|
|
54263
|
-
if (meta?.protocol && !existing.meta.protocol) existing.meta.protocol = meta.protocol;
|
|
54264
|
-
if (meta?.upstreamOrigin && !existing.meta.upstreamOrigin) existing.meta.upstreamOrigin = meta.upstreamOrigin;
|
|
54265
|
-
if (meta?.label && !existing.meta.label) existing.meta.label = meta.label;
|
|
54266
|
-
return existing;
|
|
53971
|
+
get async() {
|
|
53972
|
+
return this[Z];
|
|
54267
53973
|
}
|
|
54268
|
-
|
|
54269
|
-
|
|
54270
|
-
if (reloaded) {
|
|
54271
|
-
reloaded.lastSeen = Date.now();
|
|
54272
|
-
reloaded.restored = false;
|
|
54273
|
-
reloaded.persisted = true;
|
|
54274
|
-
sessions.set(id, reloaded);
|
|
54275
|
-
return reloaded;
|
|
53974
|
+
set async(t) {
|
|
53975
|
+
this[Z] = this[Z] || !!t;
|
|
54276
53976
|
}
|
|
54277
|
-
|
|
54278
|
-
|
|
54279
|
-
if (!evicted) {
|
|
54280
|
-
throw new Error(`session pool exhausted (MAX_SESSIONS=${MAX_SESSIONS}; all in-flight)`);
|
|
54281
|
-
}
|
|
53977
|
+
[xi]() {
|
|
53978
|
+
this[Ce] = true, this.emit("abort", this[Jt]?.reason), this.destroy(this[Jt]?.reason);
|
|
54282
53979
|
}
|
|
54283
|
-
|
|
54284
|
-
|
|
54285
|
-
meta: { protocol: meta?.protocol, upstreamOrigin: meta?.upstreamOrigin, label: meta?.label },
|
|
54286
|
-
stats: { requests: 0, tokensSaved: 0, inputTokens: 0, cachedTokens: 0, outputTokens: 0, cacheSamples: 0, lastInputTokens: 0, compressCreditTokens: 0, contextTokens: 0 },
|
|
54287
|
-
metadata: {},
|
|
54288
|
-
state: createInitialState(),
|
|
54289
|
-
createdAt: Date.now(),
|
|
54290
|
-
lastSeen: Date.now(),
|
|
54291
|
-
blockContents: /* @__PURE__ */ new Map(),
|
|
54292
|
-
inFlight: 0,
|
|
54293
|
-
persisted: false
|
|
54294
|
-
};
|
|
54295
|
-
sessions.set(id, session);
|
|
54296
|
-
return session;
|
|
54297
|
-
}
|
|
54298
|
-
function acquireInFlight(session) {
|
|
54299
|
-
session.inFlight++;
|
|
54300
|
-
}
|
|
54301
|
-
function releaseInFlight(session) {
|
|
54302
|
-
if (session.inFlight > 0) session.inFlight--;
|
|
54303
|
-
}
|
|
54304
|
-
function totalInFlight() {
|
|
54305
|
-
let n = 0;
|
|
54306
|
-
for (const s3 of sessions.values()) n += s3.inFlight;
|
|
54307
|
-
return n;
|
|
54308
|
-
}
|
|
54309
|
-
async function withSessionLock(session, fn) {
|
|
54310
|
-
const prev = session.lockChain ?? Promise.resolve();
|
|
54311
|
-
let release;
|
|
54312
|
-
const done = new Promise((resolve) => {
|
|
54313
|
-
release = resolve;
|
|
54314
|
-
});
|
|
54315
|
-
session.lockChain = prev.then(() => done);
|
|
54316
|
-
await prev;
|
|
54317
|
-
try {
|
|
54318
|
-
return await fn();
|
|
54319
|
-
} finally {
|
|
54320
|
-
release();
|
|
53980
|
+
get aborted() {
|
|
53981
|
+
return this[Ce];
|
|
54321
53982
|
}
|
|
54322
|
-
|
|
54323
|
-
function listSessions() {
|
|
54324
|
-
return [...sessions.values()].sort((a, b2) => b2.lastSeen - a.lastSeen);
|
|
54325
|
-
}
|
|
54326
|
-
function peekSession(id) {
|
|
54327
|
-
return sessions.get(id);
|
|
54328
|
-
}
|
|
54329
|
-
function derivedLegacyCanonicalId(sessionId) {
|
|
54330
|
-
return `pfa-${createHash5("sha256").update(`legacy:${sessionId}`).digest("hex").slice(0, 16)}`;
|
|
54331
|
-
}
|
|
54332
|
-
function canonicalIdOf(session) {
|
|
54333
|
-
if (session.id.startsWith("pfa-")) return session.id;
|
|
54334
|
-
const c = session.metadata.canonicalId;
|
|
54335
|
-
if (typeof c === "string" && c.length > 0) return c;
|
|
54336
|
-
return derivedLegacyCanonicalId(session.id);
|
|
54337
|
-
}
|
|
54338
|
-
function ensureCanonicalId(session) {
|
|
54339
|
-
const id = canonicalIdOf(session);
|
|
54340
|
-
if (!session.id.startsWith("pfa-") && session.metadata.canonicalId !== id) {
|
|
54341
|
-
session.metadata.canonicalId = id;
|
|
54342
|
-
markDirty(session);
|
|
53983
|
+
set aborted(t) {
|
|
54343
53984
|
}
|
|
54344
|
-
|
|
54345
|
-
|
|
54346
|
-
|
|
54347
|
-
|
|
54348
|
-
|
|
53985
|
+
write(t, e, i) {
|
|
53986
|
+
if (this[Ce]) return false;
|
|
53987
|
+
if (this[Q]) throw new Error("write after end");
|
|
53988
|
+
if (this[S]) return this.emit("error", Object.assign(new Error("Cannot call write after a stream was destroyed"), { code: "ERR_STREAM_DESTROYED" })), true;
|
|
53989
|
+
typeof e == "function" && (i = e, e = "utf8"), e || (e = "utf8");
|
|
53990
|
+
let r = this[Z] ? jt : Yr;
|
|
53991
|
+
if (!this[L] && !Buffer.isBuffer(t)) {
|
|
53992
|
+
if ($r(t)) t = Buffer.from(t.buffer, t.byteOffset, t.byteLength);
|
|
53993
|
+
else if (Vr(t)) t = Buffer.from(t);
|
|
53994
|
+
else if (typeof t != "string") throw new Error("Non-contiguous data written to non-objectMode stream");
|
|
53995
|
+
}
|
|
53996
|
+
return this[L] ? (this[g] && this[_] !== 0 && this[Ae](true), this[g] ? this.emit("data", t) : this[bi](t), this[_] !== 0 && this.emit("readable"), i && r(i), this[g]) : t.length ? (typeof t == "string" && !(e === this[z] && !this[Mt]?.lastNeed) && (t = Buffer.from(t, e)), Buffer.isBuffer(t) && this[z] && (t = this[Mt].write(t)), this[g] && this[_] !== 0 && this[Ae](true), this[g] ? this.emit("data", t) : this[bi](t), this[_] !== 0 && this.emit("readable"), i && r(i), this[g]) : (this[_] !== 0 && this.emit("readable"), i && r(i), this[g]);
|
|
54349
53997
|
}
|
|
54350
|
-
|
|
54351
|
-
|
|
54352
|
-
|
|
54353
|
-
|
|
54354
|
-
|
|
54355
|
-
|
|
53998
|
+
read(t) {
|
|
53999
|
+
if (this[S]) return null;
|
|
54000
|
+
if (this[C] = false, this[_] === 0 || t === 0 || t && t > this[_]) return this[J](), null;
|
|
54001
|
+
this[L] && (t = null), this[b].length > 1 && !this[L] && (this[b] = [this[z] ? this[b].join("") : Buffer.concat(this[b], this[_])]);
|
|
54002
|
+
let e = this[Ns](t || null, this[b][0]);
|
|
54003
|
+
return this[J](), e;
|
|
54356
54004
|
}
|
|
54357
|
-
|
|
54358
|
-
|
|
54359
|
-
|
|
54360
|
-
|
|
54361
|
-
|
|
54362
|
-
|
|
54363
|
-
|
|
54364
|
-
function resetSessionCompression(session) {
|
|
54365
|
-
session.state = createInitialState();
|
|
54366
|
-
session.blockContents.clear();
|
|
54367
|
-
session.stats.lastInputTokens = 0;
|
|
54368
|
-
delete session.stats.lastInputTokensSource;
|
|
54369
|
-
session.stats.localInputEstimate = 0;
|
|
54370
|
-
session.stats.contextTokens = 0;
|
|
54371
|
-
session.metadata.nativeCompactionAt = Date.now();
|
|
54372
|
-
markDirty(session);
|
|
54373
|
-
}
|
|
54374
|
-
function markNativeCompactionBoundary(session) {
|
|
54375
|
-
session.metadata.nativeCompactionBoundary = {
|
|
54376
|
-
at: Date.now(),
|
|
54377
|
-
pendingRebase: true
|
|
54378
|
-
};
|
|
54379
|
-
markDirty(session);
|
|
54380
|
-
}
|
|
54381
|
-
function reconcileNativeCompactionBoundary(session) {
|
|
54382
|
-
const boundary = session.metadata.nativeCompactionBoundary;
|
|
54383
|
-
if (!boundary || typeof boundary !== "object" || !boundary.pendingRebase) {
|
|
54384
|
-
return false;
|
|
54005
|
+
[Ns](t, e) {
|
|
54006
|
+
if (this[L]) this[Ie]();
|
|
54007
|
+
else {
|
|
54008
|
+
let i = e;
|
|
54009
|
+
t === i.length || t === null ? this[Ie]() : typeof i == "string" ? (this[b][0] = i.slice(t), e = i.slice(0, t), this[_] -= t) : (this[b][0] = i.subarray(t), e = i.subarray(0, t), this[_] -= t);
|
|
54010
|
+
}
|
|
54011
|
+
return this.emit("data", e), !this[b].length && !this[Q] && this.emit("drain"), e;
|
|
54385
54012
|
}
|
|
54386
|
-
|
|
54387
|
-
|
|
54388
|
-
...boundary,
|
|
54389
|
-
pendingRebase: false,
|
|
54390
|
-
rebasedAt: Date.now()
|
|
54391
|
-
};
|
|
54392
|
-
markDirty(session);
|
|
54393
|
-
return true;
|
|
54394
|
-
}
|
|
54395
|
-
function markCompactionBoundary(session) {
|
|
54396
|
-
session.metadata.compactionBoundary = {
|
|
54397
|
-
at: Date.now(),
|
|
54398
|
-
pending: true
|
|
54399
|
-
};
|
|
54400
|
-
markDirty(session);
|
|
54401
|
-
}
|
|
54402
|
-
function readPreCompactionArchive(session) {
|
|
54403
|
-
const raw = session.metadata.preCompactionArchive;
|
|
54404
|
-
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
54405
|
-
return raw;
|
|
54013
|
+
end(t, e, i) {
|
|
54014
|
+
return typeof t == "function" && (i = t, t = void 0), typeof e == "function" && (i = e, e = "utf8"), t !== void 0 && this.write(t, e), i && this.once("end", i), this[Q] = true, this.writable = false, (this[g] || !this[Qt]) && this[J](), this;
|
|
54406
54015
|
}
|
|
54407
|
-
|
|
54408
|
-
|
|
54409
|
-
function preCompactionArchiveOf(session) {
|
|
54410
|
-
return readPreCompactionArchive(session);
|
|
54411
|
-
}
|
|
54412
|
-
function applyCompactionArchive(session, activeBefore, liveRawIds, log2) {
|
|
54413
|
-
const boundary = session.metadata.compactionBoundary;
|
|
54414
|
-
if (!boundary || typeof boundary !== "object" || !boundary.pending) {
|
|
54415
|
-
return;
|
|
54016
|
+
[Bt]() {
|
|
54017
|
+
this[S] || (!this[Rt] && !this[N].length && (this[C] = true), this[Qt] = false, this[g] = true, this.emit("resume"), this[b].length ? this[Ae]() : this[Q] ? this[J]() : this.emit("drain"));
|
|
54416
54018
|
}
|
|
54417
|
-
|
|
54418
|
-
|
|
54419
|
-
if (deactivated.length > 0) {
|
|
54420
|
-
const archive = readPreCompactionArchive(session);
|
|
54421
|
-
const at2 = Date.now();
|
|
54422
|
-
for (const id of deactivated) {
|
|
54423
|
-
archive[id] = { at: at2, reason: "content replaced by client native compaction summary" };
|
|
54424
|
-
}
|
|
54425
|
-
session.metadata.preCompactionArchive = archive;
|
|
54019
|
+
resume() {
|
|
54020
|
+
return this[Bt]();
|
|
54426
54021
|
}
|
|
54427
|
-
|
|
54428
|
-
|
|
54429
|
-
for (const [rawId, ref] of Object.entries(byRaw)) {
|
|
54430
|
-
if (liveRawIds.has(rawId)) prunedByRaw[rawId] = ref;
|
|
54022
|
+
pause() {
|
|
54023
|
+
this[g] = false, this[Qt] = true, this[C] = false;
|
|
54431
54024
|
}
|
|
54432
|
-
|
|
54433
|
-
|
|
54434
|
-
if (liveRawIds.has(rawId)) prunedByRef[ref] = rawId;
|
|
54025
|
+
get destroyed() {
|
|
54026
|
+
return this[S];
|
|
54435
54027
|
}
|
|
54436
|
-
|
|
54437
|
-
|
|
54438
|
-
session.metadata.compactionBoundary = {
|
|
54439
|
-
...boundary,
|
|
54440
|
-
pending: false,
|
|
54441
|
-
archivedAt: Date.now(),
|
|
54442
|
-
archivedBlocks: deactivated
|
|
54443
|
-
};
|
|
54444
|
-
markDirty(session);
|
|
54445
|
-
log2("info", `[${session.id}] native compaction boundary: archived ${deactivated.length} pre-compaction block(s)${deactivated.length > 0 ? ` (${deactivated.join(", ")})` : ""}; pruned ref maps to ${prunedByRaw.length} live raw id(s)`);
|
|
54446
|
-
}
|
|
54447
|
-
var REWRITE_MIN_KNOWN_REFS = 20;
|
|
54448
|
-
var REWRITE_MAX_KNOWN_RATIO = 0.5;
|
|
54449
|
-
var REWRITE_MIN_INCOMING_TOTAL = 10;
|
|
54450
|
-
function detectUnannouncedHistoryRewrite(session, knownRefsBefore, liveRawIds) {
|
|
54451
|
-
const knownBefore = knownRefsBefore.size;
|
|
54452
|
-
let incomingTotal = 0;
|
|
54453
|
-
let knownIncoming = 0;
|
|
54454
|
-
for (const id of liveRawIds) {
|
|
54455
|
-
incomingTotal++;
|
|
54456
|
-
if (knownRefsBefore.has(id)) knownIncoming++;
|
|
54028
|
+
get flowing() {
|
|
54029
|
+
return this[g];
|
|
54457
54030
|
}
|
|
54458
|
-
|
|
54459
|
-
|
|
54460
|
-
}
|
|
54461
|
-
function evictOldest() {
|
|
54462
|
-
let oldestId;
|
|
54463
|
-
let oldestSeen = Infinity;
|
|
54464
|
-
for (const [id, s4] of sessions) {
|
|
54465
|
-
if (s4.inFlight > 0) continue;
|
|
54466
|
-
if (s4.lastSeen < oldestSeen) {
|
|
54467
|
-
oldestSeen = s4.lastSeen;
|
|
54468
|
-
oldestId = id;
|
|
54469
|
-
}
|
|
54031
|
+
get paused() {
|
|
54032
|
+
return this[Qt];
|
|
54470
54033
|
}
|
|
54471
|
-
|
|
54472
|
-
|
|
54473
|
-
const ok = getStore().flushSync(s3);
|
|
54474
|
-
if (!ok && !s3.persisted) {
|
|
54475
|
-
return false;
|
|
54034
|
+
[bi](t) {
|
|
54035
|
+
this[L] ? this[_] += 1 : this[_] += t.length, this[b].push(t);
|
|
54476
54036
|
}
|
|
54477
|
-
|
|
54478
|
-
|
|
54479
|
-
}
|
|
54480
|
-
async function flushAllSessions() {
|
|
54481
|
-
await getStore().flushAll(sessions.values());
|
|
54482
|
-
}
|
|
54483
|
-
|
|
54484
|
-
// src/update.ts
|
|
54485
|
-
import { readFile as readFile3, writeFile as writeFile2, mkdir as mkdir2, access, constants, rm as rm2, cp, unlink } from "fs/promises";
|
|
54486
|
-
import { execFile as execFile2 } from "child_process";
|
|
54487
|
-
import { realpathSync } from "fs";
|
|
54488
|
-
import crypto from "crypto";
|
|
54489
|
-
|
|
54490
|
-
// node_modules/tar/dist/esm/index.min.js
|
|
54491
|
-
import Qr from "events";
|
|
54492
|
-
import I from "fs";
|
|
54493
|
-
import { EventEmitter as Di } from "events";
|
|
54494
|
-
import Cs from "stream";
|
|
54495
|
-
import { StringDecoder as Hr } from "string_decoder";
|
|
54496
|
-
import cr from "path";
|
|
54497
|
-
import Kt from "fs";
|
|
54498
|
-
import { dirname as Fn, parse as kn } from "path";
|
|
54499
|
-
import { EventEmitter as Dn } from "events";
|
|
54500
|
-
import zi from "assert";
|
|
54501
|
-
import { Buffer as Ot } from "buffer";
|
|
54502
|
-
import * as Ps from "zlib";
|
|
54503
|
-
import en from "zlib";
|
|
54504
|
-
import { posix as Zt } from "path";
|
|
54505
|
-
import { basename as _n } from "path";
|
|
54506
|
-
import mi from "fs";
|
|
54507
|
-
import X from "fs";
|
|
54508
|
-
import js from "path";
|
|
54509
|
-
import { win32 as Pn } from "path";
|
|
54510
|
-
import ar from "path";
|
|
54511
|
-
import Br from "fs";
|
|
54512
|
-
import co from "assert";
|
|
54513
|
-
import { randomBytes as Mr } from "crypto";
|
|
54514
|
-
import u from "fs";
|
|
54515
|
-
import R from "path";
|
|
54516
|
-
import pr from "fs";
|
|
54517
|
-
import wi from "fs";
|
|
54518
|
-
import we from "path";
|
|
54519
|
-
import k from "fs";
|
|
54520
|
-
import ro from "fs/promises";
|
|
54521
|
-
import Si from "path";
|
|
54522
|
-
import { join as xr } from "path";
|
|
54523
|
-
import v from "fs";
|
|
54524
|
-
import Pr from "path";
|
|
54525
|
-
var zr = Object.defineProperty;
|
|
54526
|
-
var Ur = (s3, t) => {
|
|
54527
|
-
for (var e in t) zr(s3, e, { get: t[e], enumerable: true });
|
|
54528
|
-
};
|
|
54529
|
-
var Ds = typeof process == "object" && process ? process : { stdout: null, stderr: null };
|
|
54530
|
-
var Wr = (s3) => !!s3 && typeof s3 == "object" && (s3 instanceof A || s3 instanceof Cs || Gr(s3) || Zr(s3));
|
|
54531
|
-
var Gr = (s3) => !!s3 && typeof s3 == "object" && s3 instanceof Di && typeof s3.pipe == "function" && s3.pipe !== Cs.Writable.prototype.pipe;
|
|
54532
|
-
var Zr = (s3) => !!s3 && typeof s3 == "object" && s3 instanceof Di && typeof s3.write == "function" && typeof s3.end == "function";
|
|
54533
|
-
var Q = /* @__PURE__ */ Symbol("EOF");
|
|
54534
|
-
var J = /* @__PURE__ */ Symbol("maybeEmitEnd");
|
|
54535
|
-
var nt = /* @__PURE__ */ Symbol("emittedEnd");
|
|
54536
|
-
var De = /* @__PURE__ */ Symbol("emittingEnd");
|
|
54537
|
-
var qt = /* @__PURE__ */ Symbol("emittedError");
|
|
54538
|
-
var Ne = /* @__PURE__ */ Symbol("closed");
|
|
54539
|
-
var Ns = /* @__PURE__ */ Symbol("read");
|
|
54540
|
-
var Ae = /* @__PURE__ */ Symbol("flush");
|
|
54541
|
-
var As = /* @__PURE__ */ Symbol("flushChunk");
|
|
54542
|
-
var z = /* @__PURE__ */ Symbol("encoding");
|
|
54543
|
-
var Mt = /* @__PURE__ */ Symbol("decoder");
|
|
54544
|
-
var g = /* @__PURE__ */ Symbol("flowing");
|
|
54545
|
-
var Qt = /* @__PURE__ */ Symbol("paused");
|
|
54546
|
-
var Bt = /* @__PURE__ */ Symbol("resume");
|
|
54547
|
-
var b = /* @__PURE__ */ Symbol("buffer");
|
|
54548
|
-
var N = /* @__PURE__ */ Symbol("pipes");
|
|
54549
|
-
var _ = /* @__PURE__ */ Symbol("bufferLength");
|
|
54550
|
-
var bi = /* @__PURE__ */ Symbol("bufferPush");
|
|
54551
|
-
var Ie = /* @__PURE__ */ Symbol("bufferShift");
|
|
54552
|
-
var L = /* @__PURE__ */ Symbol("objectMode");
|
|
54553
|
-
var S = /* @__PURE__ */ Symbol("destroyed");
|
|
54554
|
-
var _i = /* @__PURE__ */ Symbol("error");
|
|
54555
|
-
var Oi = /* @__PURE__ */ Symbol("emitData");
|
|
54556
|
-
var Is = /* @__PURE__ */ Symbol("emitEnd");
|
|
54557
|
-
var Ti = /* @__PURE__ */ Symbol("emitEnd2");
|
|
54558
|
-
var Z = /* @__PURE__ */ Symbol("async");
|
|
54559
|
-
var xi = /* @__PURE__ */ Symbol("abort");
|
|
54560
|
-
var Ce = /* @__PURE__ */ Symbol("aborted");
|
|
54561
|
-
var Jt = /* @__PURE__ */ Symbol("signal");
|
|
54562
|
-
var Rt = /* @__PURE__ */ Symbol("dataListeners");
|
|
54563
|
-
var C = /* @__PURE__ */ Symbol("discarded");
|
|
54564
|
-
var jt = (s3) => Promise.resolve().then(s3);
|
|
54565
|
-
var Yr = (s3) => s3();
|
|
54566
|
-
var Kr = (s3) => s3 === "end" || s3 === "finish" || s3 === "prefinish";
|
|
54567
|
-
var Vr = (s3) => s3 instanceof ArrayBuffer || !!s3 && typeof s3 == "object" && s3.constructor && s3.constructor.name === "ArrayBuffer" && s3.byteLength >= 0;
|
|
54568
|
-
var $r = (s3) => !Buffer.isBuffer(s3) && ArrayBuffer.isView(s3);
|
|
54569
|
-
var Fe = class {
|
|
54570
|
-
src;
|
|
54571
|
-
dest;
|
|
54572
|
-
opts;
|
|
54573
|
-
ondrain;
|
|
54574
|
-
constructor(t, e, i) {
|
|
54575
|
-
this.src = t, this.dest = e, this.opts = i, this.ondrain = () => t[Bt](), this.dest.on("drain", this.ondrain);
|
|
54037
|
+
[Ie]() {
|
|
54038
|
+
return this[L] ? this[_] -= 1 : this[_] -= this[b][0].length, this[b].shift();
|
|
54576
54039
|
}
|
|
54577
|
-
|
|
54578
|
-
|
|
54040
|
+
[Ae](t = false) {
|
|
54041
|
+
do
|
|
54042
|
+
;
|
|
54043
|
+
while (this[As](this[Ie]()) && this[b].length);
|
|
54044
|
+
!t && !this[b].length && !this[Q] && this.emit("drain");
|
|
54579
54045
|
}
|
|
54580
|
-
|
|
54046
|
+
[As](t) {
|
|
54047
|
+
return this.emit("data", t), this[g];
|
|
54581
54048
|
}
|
|
54582
|
-
|
|
54583
|
-
this
|
|
54049
|
+
pipe(t, e) {
|
|
54050
|
+
if (this[S]) return t;
|
|
54051
|
+
this[C] = false;
|
|
54052
|
+
let i = this[nt];
|
|
54053
|
+
return e = e || {}, t === Ds.stdout || t === Ds.stderr ? e.end = false : e.end = e.end !== false, e.proxyErrors = !!e.proxyErrors, i ? e.end && t.end() : (this[N].push(e.proxyErrors ? new Li(this, t, e) : new Fe(this, t, e)), this[Z] ? jt(() => this[Bt]()) : this[Bt]()), t;
|
|
54584
54054
|
}
|
|
54585
|
-
|
|
54586
|
-
|
|
54587
|
-
|
|
54588
|
-
this.src.removeListener("error", this.proxyErrors), super.unpipe();
|
|
54589
|
-
}
|
|
54590
|
-
constructor(t, e, i) {
|
|
54591
|
-
super(t, e, i), this.proxyErrors = (r) => this.dest.emit("error", r), t.on("error", this.proxyErrors);
|
|
54592
|
-
}
|
|
54593
|
-
};
|
|
54594
|
-
var Xr = (s3) => !!s3.objectMode;
|
|
54595
|
-
var qr = (s3) => !s3.objectMode && !!s3.encoding && s3.encoding !== "buffer";
|
|
54596
|
-
var A = class extends Di {
|
|
54597
|
-
[g] = false;
|
|
54598
|
-
[Qt] = false;
|
|
54599
|
-
[N] = [];
|
|
54600
|
-
[b] = [];
|
|
54601
|
-
[L];
|
|
54602
|
-
[z];
|
|
54603
|
-
[Z];
|
|
54604
|
-
[Mt];
|
|
54605
|
-
[Q] = false;
|
|
54606
|
-
[nt] = false;
|
|
54607
|
-
[De] = false;
|
|
54608
|
-
[Ne] = false;
|
|
54609
|
-
[qt] = null;
|
|
54610
|
-
[_] = 0;
|
|
54611
|
-
[S] = false;
|
|
54612
|
-
[Jt];
|
|
54613
|
-
[Ce] = false;
|
|
54614
|
-
[Rt] = 0;
|
|
54615
|
-
[C] = false;
|
|
54616
|
-
writable = true;
|
|
54617
|
-
readable = true;
|
|
54618
|
-
constructor(...t) {
|
|
54619
|
-
let e = t[0] || {};
|
|
54620
|
-
if (super(), e.objectMode && typeof e.encoding == "string") throw new TypeError("Encoding and objectMode may not be used together");
|
|
54621
|
-
Xr(e) ? (this[L] = true, this[z] = null) : qr(e) ? (this[z] = e.encoding, this[L] = false) : (this[L] = false, this[z] = null), this[Z] = !!e.async, this[Mt] = this[z] ? new Hr(this[z]) : null, e && e.debugExposeBuffer === true && Object.defineProperty(this, "buffer", { get: () => this[b] }), e && e.debugExposePipes === true && Object.defineProperty(this, "pipes", { get: () => this[N] });
|
|
54622
|
-
let { signal: i } = e;
|
|
54623
|
-
i && (this[Jt] = i, i.aborted ? this[xi]() : i.addEventListener("abort", () => this[xi]()));
|
|
54624
|
-
}
|
|
54625
|
-
get bufferLength() {
|
|
54626
|
-
return this[_];
|
|
54627
|
-
}
|
|
54628
|
-
get encoding() {
|
|
54629
|
-
return this[z];
|
|
54630
|
-
}
|
|
54631
|
-
set encoding(t) {
|
|
54632
|
-
throw new Error("Encoding must be set at instantiation time");
|
|
54633
|
-
}
|
|
54634
|
-
setEncoding(t) {
|
|
54635
|
-
throw new Error("Encoding must be set at instantiation time");
|
|
54636
|
-
}
|
|
54637
|
-
get objectMode() {
|
|
54638
|
-
return this[L];
|
|
54639
|
-
}
|
|
54640
|
-
set objectMode(t) {
|
|
54641
|
-
throw new Error("objectMode must be set at instantiation time");
|
|
54642
|
-
}
|
|
54643
|
-
get async() {
|
|
54644
|
-
return this[Z];
|
|
54645
|
-
}
|
|
54646
|
-
set async(t) {
|
|
54647
|
-
this[Z] = this[Z] || !!t;
|
|
54648
|
-
}
|
|
54649
|
-
[xi]() {
|
|
54650
|
-
this[Ce] = true, this.emit("abort", this[Jt]?.reason), this.destroy(this[Jt]?.reason);
|
|
54651
|
-
}
|
|
54652
|
-
get aborted() {
|
|
54653
|
-
return this[Ce];
|
|
54654
|
-
}
|
|
54655
|
-
set aborted(t) {
|
|
54656
|
-
}
|
|
54657
|
-
write(t, e, i) {
|
|
54658
|
-
if (this[Ce]) return false;
|
|
54659
|
-
if (this[Q]) throw new Error("write after end");
|
|
54660
|
-
if (this[S]) return this.emit("error", Object.assign(new Error("Cannot call write after a stream was destroyed"), { code: "ERR_STREAM_DESTROYED" })), true;
|
|
54661
|
-
typeof e == "function" && (i = e, e = "utf8"), e || (e = "utf8");
|
|
54662
|
-
let r = this[Z] ? jt : Yr;
|
|
54663
|
-
if (!this[L] && !Buffer.isBuffer(t)) {
|
|
54664
|
-
if ($r(t)) t = Buffer.from(t.buffer, t.byteOffset, t.byteLength);
|
|
54665
|
-
else if (Vr(t)) t = Buffer.from(t);
|
|
54666
|
-
else if (typeof t != "string") throw new Error("Non-contiguous data written to non-objectMode stream");
|
|
54667
|
-
}
|
|
54668
|
-
return this[L] ? (this[g] && this[_] !== 0 && this[Ae](true), this[g] ? this.emit("data", t) : this[bi](t), this[_] !== 0 && this.emit("readable"), i && r(i), this[g]) : t.length ? (typeof t == "string" && !(e === this[z] && !this[Mt]?.lastNeed) && (t = Buffer.from(t, e)), Buffer.isBuffer(t) && this[z] && (t = this[Mt].write(t)), this[g] && this[_] !== 0 && this[Ae](true), this[g] ? this.emit("data", t) : this[bi](t), this[_] !== 0 && this.emit("readable"), i && r(i), this[g]) : (this[_] !== 0 && this.emit("readable"), i && r(i), this[g]);
|
|
54669
|
-
}
|
|
54670
|
-
read(t) {
|
|
54671
|
-
if (this[S]) return null;
|
|
54672
|
-
if (this[C] = false, this[_] === 0 || t === 0 || t && t > this[_]) return this[J](), null;
|
|
54673
|
-
this[L] && (t = null), this[b].length > 1 && !this[L] && (this[b] = [this[z] ? this[b].join("") : Buffer.concat(this[b], this[_])]);
|
|
54674
|
-
let e = this[Ns](t || null, this[b][0]);
|
|
54675
|
-
return this[J](), e;
|
|
54676
|
-
}
|
|
54677
|
-
[Ns](t, e) {
|
|
54678
|
-
if (this[L]) this[Ie]();
|
|
54679
|
-
else {
|
|
54680
|
-
let i = e;
|
|
54681
|
-
t === i.length || t === null ? this[Ie]() : typeof i == "string" ? (this[b][0] = i.slice(t), e = i.slice(0, t), this[_] -= t) : (this[b][0] = i.subarray(t), e = i.subarray(0, t), this[_] -= t);
|
|
54682
|
-
}
|
|
54683
|
-
return this.emit("data", e), !this[b].length && !this[Q] && this.emit("drain"), e;
|
|
54684
|
-
}
|
|
54685
|
-
end(t, e, i) {
|
|
54686
|
-
return typeof t == "function" && (i = t, t = void 0), typeof e == "function" && (i = e, e = "utf8"), t !== void 0 && this.write(t, e), i && this.once("end", i), this[Q] = true, this.writable = false, (this[g] || !this[Qt]) && this[J](), this;
|
|
54687
|
-
}
|
|
54688
|
-
[Bt]() {
|
|
54689
|
-
this[S] || (!this[Rt] && !this[N].length && (this[C] = true), this[Qt] = false, this[g] = true, this.emit("resume"), this[b].length ? this[Ae]() : this[Q] ? this[J]() : this.emit("drain"));
|
|
54690
|
-
}
|
|
54691
|
-
resume() {
|
|
54692
|
-
return this[Bt]();
|
|
54693
|
-
}
|
|
54694
|
-
pause() {
|
|
54695
|
-
this[g] = false, this[Qt] = true, this[C] = false;
|
|
54696
|
-
}
|
|
54697
|
-
get destroyed() {
|
|
54698
|
-
return this[S];
|
|
54699
|
-
}
|
|
54700
|
-
get flowing() {
|
|
54701
|
-
return this[g];
|
|
54702
|
-
}
|
|
54703
|
-
get paused() {
|
|
54704
|
-
return this[Qt];
|
|
54705
|
-
}
|
|
54706
|
-
[bi](t) {
|
|
54707
|
-
this[L] ? this[_] += 1 : this[_] += t.length, this[b].push(t);
|
|
54708
|
-
}
|
|
54709
|
-
[Ie]() {
|
|
54710
|
-
return this[L] ? this[_] -= 1 : this[_] -= this[b][0].length, this[b].shift();
|
|
54711
|
-
}
|
|
54712
|
-
[Ae](t = false) {
|
|
54713
|
-
do
|
|
54714
|
-
;
|
|
54715
|
-
while (this[As](this[Ie]()) && this[b].length);
|
|
54716
|
-
!t && !this[b].length && !this[Q] && this.emit("drain");
|
|
54717
|
-
}
|
|
54718
|
-
[As](t) {
|
|
54719
|
-
return this.emit("data", t), this[g];
|
|
54720
|
-
}
|
|
54721
|
-
pipe(t, e) {
|
|
54722
|
-
if (this[S]) return t;
|
|
54723
|
-
this[C] = false;
|
|
54724
|
-
let i = this[nt];
|
|
54725
|
-
return e = e || {}, t === Ds.stdout || t === Ds.stderr ? e.end = false : e.end = e.end !== false, e.proxyErrors = !!e.proxyErrors, i ? e.end && t.end() : (this[N].push(e.proxyErrors ? new Li(this, t, e) : new Fe(this, t, e)), this[Z] ? jt(() => this[Bt]()) : this[Bt]()), t;
|
|
54726
|
-
}
|
|
54727
|
-
unpipe(t) {
|
|
54728
|
-
let e = this[N].find((i) => i.dest === t);
|
|
54729
|
-
e && (this[N].length === 1 ? (this[g] && this[Rt] === 0 && (this[g] = false), this[N] = []) : this[N].splice(this[N].indexOf(e), 1), e.unpipe());
|
|
54055
|
+
unpipe(t) {
|
|
54056
|
+
let e = this[N].find((i) => i.dest === t);
|
|
54057
|
+
e && (this[N].length === 1 ? (this[g] && this[Rt] === 0 && (this[g] = false), this[N] = []) : this[N].splice(this[N].indexOf(e), 1), e.unpipe());
|
|
54730
54058
|
}
|
|
54731
54059
|
addListener(t, e) {
|
|
54732
54060
|
return this.on(t, e);
|
|
@@ -61424,8 +60752,8 @@ function getCacheLedger(session) {
|
|
|
61424
60752
|
return led;
|
|
61425
60753
|
}
|
|
61426
60754
|
function pushFold(led, f2) {
|
|
61427
|
-
for (const
|
|
61428
|
-
if (
|
|
60755
|
+
for (const open2 of led.folds) {
|
|
60756
|
+
if (open2.k === null) open2.k = open2.requestsAfter;
|
|
61429
60757
|
}
|
|
61430
60758
|
led.foldSeqCounter += 1;
|
|
61431
60759
|
led.folds.push({ ...f2, seq: led.foldSeqCounter, T: 0, hPct: null, requestsAfter: 0, k: null });
|
|
@@ -61739,11 +61067,11 @@ function looseCloseEnd(s3) {
|
|
|
61739
61067
|
}
|
|
61740
61068
|
function wrappedSpan(s3) {
|
|
61741
61069
|
const broken = BROKEN_ATTRS.exec(s3);
|
|
61742
|
-
const
|
|
61070
|
+
const open2 = LONE_OPEN.exec(s3);
|
|
61743
61071
|
const spans = [];
|
|
61744
61072
|
if (broken) spans.push({ start: broken.index, end: broken.index + broken[0].length });
|
|
61745
|
-
if (
|
|
61746
|
-
spans.push({ start:
|
|
61073
|
+
if (open2 && OPEN_WITH_ATTRS.test(open2[0]) && ((open2[0].match(/"/g) ?? []).length & 1) === 1) {
|
|
61074
|
+
spans.push({ start: open2.index, end: open2.index + open2[0].length });
|
|
61747
61075
|
}
|
|
61748
61076
|
if (spans.length === 0) return null;
|
|
61749
61077
|
const first = spans.reduce((a, b2) => b2.start < a.start ? b2 : a);
|
|
@@ -66904,16 +66232,16 @@ function extractTextTriggers(text) {
|
|
|
66904
66232
|
let i = 0;
|
|
66905
66233
|
let n = 0;
|
|
66906
66234
|
while (i < text.length) {
|
|
66907
|
-
const
|
|
66908
|
-
if (
|
|
66235
|
+
const open2 = text.indexOf(ACP_TEXT_OPEN, i);
|
|
66236
|
+
if (open2 === -1) {
|
|
66909
66237
|
clean += text.slice(i);
|
|
66910
66238
|
break;
|
|
66911
66239
|
}
|
|
66912
|
-
clean += text.slice(i,
|
|
66913
|
-
const after =
|
|
66240
|
+
clean += text.slice(i, open2);
|
|
66241
|
+
const after = open2 + ACP_TEXT_OPEN.length;
|
|
66914
66242
|
const close = text.indexOf(ACP_TEXT_CLOSE, after);
|
|
66915
66243
|
if (close === -1) {
|
|
66916
|
-
clean += text.slice(
|
|
66244
|
+
clean += text.slice(open2);
|
|
66917
66245
|
break;
|
|
66918
66246
|
}
|
|
66919
66247
|
const payload = text.slice(after, close).trim();
|
|
@@ -68159,12 +67487,16 @@ function conversationHeaderSource(headers) {
|
|
|
68159
67487
|
}
|
|
68160
67488
|
return void 0;
|
|
68161
67489
|
}
|
|
68162
|
-
function
|
|
68163
|
-
const
|
|
68164
|
-
if (
|
|
68165
|
-
|
|
68166
|
-
if (
|
|
68167
|
-
|
|
67490
|
+
function instructionsFingerprintExempt(headers) {
|
|
67491
|
+
const src = conversationHeaderSource(headers);
|
|
67492
|
+
if (!src) return false;
|
|
67493
|
+
if (src.name === "x-opencode-session") return true;
|
|
67494
|
+
if (src.name === "x-session-affinity" && src.value.startsWith("ses_")) return true;
|
|
67495
|
+
if (src.name === "x-bili-plugin-conversation") {
|
|
67496
|
+
const flag = headers["x-bili-plugin-instructions-mutable"];
|
|
67497
|
+
return typeof flag === "string" && flag.trim() === "1";
|
|
67498
|
+
}
|
|
67499
|
+
return false;
|
|
68168
67500
|
}
|
|
68169
67501
|
function affinityToken(identity) {
|
|
68170
67502
|
return identity.clientProvided ? identity.value : void 0;
|
|
@@ -70151,240 +69483,912 @@ async function pipePluginResponsesWithStrip(stream2, res, session, log2, refetch
|
|
|
70151
69483
|
log2?.("client aborted mid-stream");
|
|
70152
69484
|
return;
|
|
70153
69485
|
}
|
|
70154
|
-
try {
|
|
70155
|
-
const rest = flushArgTails() + flushTail("");
|
|
70156
|
-
if (rest.length > 0) await write(rest);
|
|
70157
|
-
} catch {
|
|
70158
|
-
}
|
|
70159
|
-
log("warn", `[plugin] upstream stream read failed (responses): ${String(e instanceof Error ? e.message : e)} \u2014 emitting in-band truncation signal`);
|
|
70160
|
-
emitUpstreamTruncation(res, "responses", false, log2);
|
|
70161
|
-
return;
|
|
70162
|
-
} finally {
|
|
70163
|
-
reader.releaseLock();
|
|
70164
|
-
res.end();
|
|
69486
|
+
try {
|
|
69487
|
+
const rest = flushArgTails() + flushTail("");
|
|
69488
|
+
if (rest.length > 0) await write(rest);
|
|
69489
|
+
} catch {
|
|
69490
|
+
}
|
|
69491
|
+
log("warn", `[plugin] upstream stream read failed (responses): ${String(e instanceof Error ? e.message : e)} \u2014 emitting in-band truncation signal`);
|
|
69492
|
+
emitUpstreamTruncation(res, "responses", false, log2);
|
|
69493
|
+
return;
|
|
69494
|
+
} finally {
|
|
69495
|
+
reader.releaseLock();
|
|
69496
|
+
res.end();
|
|
69497
|
+
}
|
|
69498
|
+
}
|
|
69499
|
+
function rebuildEvent(rawEvent, ev) {
|
|
69500
|
+
const lines = rawEvent.split("\n");
|
|
69501
|
+
let replaced = false;
|
|
69502
|
+
const out = [];
|
|
69503
|
+
for (const l of lines) {
|
|
69504
|
+
if (l.startsWith("data:")) {
|
|
69505
|
+
if (replaced) continue;
|
|
69506
|
+
replaced = true;
|
|
69507
|
+
out.push(`data: ${JSON.stringify(ev)}`);
|
|
69508
|
+
continue;
|
|
69509
|
+
}
|
|
69510
|
+
out.push(l);
|
|
69511
|
+
}
|
|
69512
|
+
return replaced ? out.join("\n") + "\n\n" : `data: ${JSON.stringify(ev)}
|
|
69513
|
+
|
|
69514
|
+
`;
|
|
69515
|
+
}
|
|
69516
|
+
function stripGoogleChunk(obj) {
|
|
69517
|
+
if (!obj || typeof obj !== "object") return obj;
|
|
69518
|
+
const o = obj;
|
|
69519
|
+
const candidates = o["candidates"];
|
|
69520
|
+
if (!Array.isArray(candidates)) return obj;
|
|
69521
|
+
o["candidates"] = candidates.map((c) => {
|
|
69522
|
+
if (!c || typeof c !== "object") return c;
|
|
69523
|
+
const cand = c;
|
|
69524
|
+
const content = cand["content"];
|
|
69525
|
+
if (!content || typeof content !== "object") return c;
|
|
69526
|
+
const cont = content;
|
|
69527
|
+
if (!Array.isArray(cont["parts"])) return c;
|
|
69528
|
+
return {
|
|
69529
|
+
...cand,
|
|
69530
|
+
content: {
|
|
69531
|
+
...cont,
|
|
69532
|
+
parts: cont["parts"].map(
|
|
69533
|
+
(p2) => p2 && typeof p2 === "object" && typeof p2["text"] === "string" ? { ...p2, text: stripAcpTags(p2["text"]) } : p2
|
|
69534
|
+
)
|
|
69535
|
+
}
|
|
69536
|
+
};
|
|
69537
|
+
});
|
|
69538
|
+
return obj;
|
|
69539
|
+
}
|
|
69540
|
+
function stripGoogleText(obj) {
|
|
69541
|
+
if (Array.isArray(obj)) {
|
|
69542
|
+
obj.forEach((c) => {
|
|
69543
|
+
stripGoogleChunk(c);
|
|
69544
|
+
});
|
|
69545
|
+
return obj;
|
|
69546
|
+
}
|
|
69547
|
+
return stripGoogleChunk(obj);
|
|
69548
|
+
}
|
|
69549
|
+
async function pipePluginJson(stream2, res, session, protocol) {
|
|
69550
|
+
const reader = stream2.getReader();
|
|
69551
|
+
const chunks = [];
|
|
69552
|
+
try {
|
|
69553
|
+
for (; ; ) {
|
|
69554
|
+
const { done, value } = await reader.read();
|
|
69555
|
+
if (done) break;
|
|
69556
|
+
if (value && value.length > 0) chunks.push(Buffer.from(value));
|
|
69557
|
+
}
|
|
69558
|
+
} catch (e) {
|
|
69559
|
+
if (!res.writableEnded) res.end();
|
|
69560
|
+
if (res.destroyed || res.writableEnded) return;
|
|
69561
|
+
throw e;
|
|
69562
|
+
}
|
|
69563
|
+
reader.releaseLock();
|
|
69564
|
+
const text = Buffer.concat(chunks).toString("utf8");
|
|
69565
|
+
let json;
|
|
69566
|
+
let mutated = false;
|
|
69567
|
+
try {
|
|
69568
|
+
json = JSON.parse(text);
|
|
69569
|
+
const usage = json["usage"];
|
|
69570
|
+
if (session && usage) {
|
|
69571
|
+
const input = num3(usage["prompt_tokens"]) ?? num3(usage["input_tokens"]);
|
|
69572
|
+
if (input !== void 0) {
|
|
69573
|
+
const cached = num3(usage["prompt_tokens_details"]?.["cached_tokens"]) ?? num3(usage["input_tokens_details"]?.["cached_tokens"]) ?? num3(usage["cache_read_input_tokens"]) ?? // #779: DeepSeek-style top-level field (openai wire)
|
|
69574
|
+
num3(usage["prompt_cache_hit_tokens"]);
|
|
69575
|
+
const creation = num3(usage["cache_creation_input_tokens"]);
|
|
69576
|
+
applyUsageSample(session, {
|
|
69577
|
+
inputTokens: input,
|
|
69578
|
+
outputTokens: num3(usage["completion_tokens"]) ?? num3(usage["output_tokens"]),
|
|
69579
|
+
cachedTokens: cached,
|
|
69580
|
+
creationTokens: creation
|
|
69581
|
+
}, protocol);
|
|
69582
|
+
markDirty(session);
|
|
69583
|
+
}
|
|
69584
|
+
}
|
|
69585
|
+
if (session && !usage) {
|
|
69586
|
+
const sample = googleUsageSample(json);
|
|
69587
|
+
if (sample && sample.inputTokens !== void 0) {
|
|
69588
|
+
applyUsageSample(session, sample, protocol);
|
|
69589
|
+
markDirty(session);
|
|
69590
|
+
}
|
|
69591
|
+
}
|
|
69592
|
+
} catch {
|
|
69593
|
+
}
|
|
69594
|
+
if (json && (containsRenderTagText(text) || containsMarkerLineText(text))) {
|
|
69595
|
+
json = protocol === "responses" ? stripResponsesText(json) : protocol === "anthropic" ? stripAnthropicText(json) : protocol === "google" ? stripGoogleText(json) : stripOpenaiChatText(json);
|
|
69596
|
+
mutated = true;
|
|
69597
|
+
}
|
|
69598
|
+
if (mutated && json) {
|
|
69599
|
+
res.end(Buffer.from(JSON.stringify(json), "utf8"));
|
|
69600
|
+
return;
|
|
69601
|
+
}
|
|
69602
|
+
res.end(text);
|
|
69603
|
+
}
|
|
69604
|
+
|
|
69605
|
+
// src/tunnel-guard.ts
|
|
69606
|
+
import { lookup } from "dns/promises";
|
|
69607
|
+
import { networkInterfaces } from "os";
|
|
69608
|
+
var BILI_TUNNEL_HEADER = "x-bili-tunnel";
|
|
69609
|
+
function parseIpLiteral(s3) {
|
|
69610
|
+
const t = s3.trim().toLowerCase();
|
|
69611
|
+
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(t)) return t;
|
|
69612
|
+
if (t.includes(":")) return t;
|
|
69613
|
+
return null;
|
|
69614
|
+
}
|
|
69615
|
+
function normalizeIpLiteral(ip) {
|
|
69616
|
+
const t = ip.trim().toLowerCase();
|
|
69617
|
+
if (!t.startsWith("::ffff:")) return t;
|
|
69618
|
+
const dotted = t.match(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/);
|
|
69619
|
+
if (dotted) return dotted[1];
|
|
69620
|
+
const hex = t.match(/^::ffff:0*([0-9a-f]{1,4}):0*([0-9a-f]{1,4})$/);
|
|
69621
|
+
if (hex) {
|
|
69622
|
+
const hi2 = parseInt(hex[1], 16);
|
|
69623
|
+
const lo2 = parseInt(hex[2], 16);
|
|
69624
|
+
return `${hi2 >> 8 & 255}.${hi2 & 255}.${lo2 >> 8 & 255}.${lo2 & 255}`;
|
|
69625
|
+
}
|
|
69626
|
+
return t;
|
|
69627
|
+
}
|
|
69628
|
+
function classifyIp(ip) {
|
|
69629
|
+
const lit = normalizeIpLiteral(parseIpLiteral(ip) ?? "");
|
|
69630
|
+
if (!lit) return "public";
|
|
69631
|
+
if (lit.includes(":")) {
|
|
69632
|
+
if (lit === "::1" || lit === "::") return "loopback";
|
|
69633
|
+
if (lit.startsWith("fe8") || lit.startsWith("fe9") || lit.startsWith("fea") || lit.startsWith("feb")) return "linkLocal";
|
|
69634
|
+
if (lit.startsWith("fc") || lit.startsWith("fd")) return "private";
|
|
69635
|
+
return "public";
|
|
69636
|
+
}
|
|
69637
|
+
const parts = lit.split(".").map(Number);
|
|
69638
|
+
const [a, b2] = parts;
|
|
69639
|
+
if (a === 127) return "loopback";
|
|
69640
|
+
if (a === 169 && b2 === 254) return "linkLocal";
|
|
69641
|
+
if (a === 10 || a === 0) return "private";
|
|
69642
|
+
if (a === 172 && b2 >= 16 && b2 <= 31) return "private";
|
|
69643
|
+
if (a === 192 && b2 === 168) return "private";
|
|
69644
|
+
if (a === 100 && b2 >= 64 && b2 <= 127) return "private";
|
|
69645
|
+
return "public";
|
|
69646
|
+
}
|
|
69647
|
+
var dnsResolveHost = async (host) => {
|
|
69648
|
+
const res = await lookup(host, { all: true, family: 0 });
|
|
69649
|
+
return res.map((r) => r.address);
|
|
69650
|
+
};
|
|
69651
|
+
var localAddrCache;
|
|
69652
|
+
function localMachineIps() {
|
|
69653
|
+
const now = Date.now();
|
|
69654
|
+
if (!localAddrCache || now - localAddrCache.at > 3e4) {
|
|
69655
|
+
const ips = /* @__PURE__ */ new Set(["127.0.0.1", "::1"]);
|
|
69656
|
+
for (const list of Object.values(networkInterfaces())) {
|
|
69657
|
+
for (const ni2 of list ?? []) {
|
|
69658
|
+
if (ni2.address) ips.add(ni2.address.toLowerCase());
|
|
69659
|
+
}
|
|
69660
|
+
}
|
|
69661
|
+
for (let i = 0; i <= 255; i++) ips.add(`127.0.0.${i}`);
|
|
69662
|
+
localAddrCache = { at: now, ips };
|
|
69663
|
+
}
|
|
69664
|
+
return localAddrCache.ips;
|
|
69665
|
+
}
|
|
69666
|
+
function allowlistHit(host, port, allowlist) {
|
|
69667
|
+
const h = host.toLowerCase();
|
|
69668
|
+
const hp = `${h}:${port}`;
|
|
69669
|
+
return allowlist.some((e) => e === h || e === hp);
|
|
69670
|
+
}
|
|
69671
|
+
async function checkTunnelDestination(origin, ctx) {
|
|
69672
|
+
let u2;
|
|
69673
|
+
try {
|
|
69674
|
+
u2 = new URL(origin);
|
|
69675
|
+
} catch {
|
|
69676
|
+
return { ok: false, code: "unresolvable", message: `invalid tunnel destination ${origin}` };
|
|
69677
|
+
}
|
|
69678
|
+
const host = u2.hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
69679
|
+
const port = u2.port ? Number(u2.port) : u2.protocol === "https:" ? 443 : 80;
|
|
69680
|
+
let ips;
|
|
69681
|
+
const literal = parseIpLiteral(host);
|
|
69682
|
+
if (literal) {
|
|
69683
|
+
ips = [normalizeIpLiteral(literal)];
|
|
69684
|
+
} else {
|
|
69685
|
+
try {
|
|
69686
|
+
ips = await (ctx.resolveHost ?? dnsResolveHost)(host);
|
|
69687
|
+
} catch {
|
|
69688
|
+
return { ok: false, code: "unresolvable", message: `cannot resolve tunnel destination ${host}` };
|
|
69689
|
+
}
|
|
69690
|
+
if (ips.length === 0) return { ok: false, code: "unresolvable", message: `no addresses for tunnel destination ${host}` };
|
|
69691
|
+
}
|
|
69692
|
+
if (ctx.selfPort !== void 0 && port === ctx.selfPort) {
|
|
69693
|
+
const mine = (ctx.localIps ?? localMachineIps)();
|
|
69694
|
+
if (ips.some((ip) => ip === "0.0.0.0" || ip === "::" || mine.has(ip.toLowerCase()) || mine.has(`::ffff:${ip.toLowerCase()}`))) {
|
|
69695
|
+
return { ok: false, code: "self", message: "the bili tunnel may not target the proxy itself" };
|
|
69696
|
+
}
|
|
69697
|
+
}
|
|
69698
|
+
const classes = ips.map((ip) => classifyIp(ip));
|
|
69699
|
+
if (classes.includes("linkLocal")) {
|
|
69700
|
+
return { ok: false, code: "linkLocal", message: "link-local / metadata destinations are blocked from the bili tunnel" };
|
|
69701
|
+
}
|
|
69702
|
+
if (!classes.every((c) => c === "public")) {
|
|
69703
|
+
if (ctx.clientLoopback) return { ok: true };
|
|
69704
|
+
if (allowlistHit(host, port, ctx.allowlist)) return { ok: true };
|
|
69705
|
+
return {
|
|
69706
|
+
ok: false,
|
|
69707
|
+
code: "privateRemote",
|
|
69708
|
+
message: `tunnel destination ${host} resolves to a loopback/private address; remote clients may only reach it via BILI_TUNNEL_ALLOWED_HOSTS`
|
|
69709
|
+
};
|
|
69710
|
+
}
|
|
69711
|
+
return { ok: true };
|
|
69712
|
+
}
|
|
69713
|
+
function tunnelAllowlistFromEnv(env = process.env) {
|
|
69714
|
+
const raw = env.BILI_TUNNEL_ALLOWED_HOSTS ?? "";
|
|
69715
|
+
return raw.split(",").map((s3) => s3.trim().toLowerCase()).filter((s3) => s3.length > 0);
|
|
69716
|
+
}
|
|
69717
|
+
|
|
69718
|
+
// src/content-encoding.ts
|
|
69719
|
+
import { createBrotliDecompress, createGunzip, createInflate, createInflateRaw } from "zlib";
|
|
69720
|
+
|
|
69721
|
+
// node_modules/fzstd/esm/index.mjs
|
|
69722
|
+
var ab = ArrayBuffer;
|
|
69723
|
+
var u8 = Uint8Array;
|
|
69724
|
+
var u16 = Uint16Array;
|
|
69725
|
+
var i16 = Int16Array;
|
|
69726
|
+
var i32 = Int32Array;
|
|
69727
|
+
var slc = function(v2, s3, e) {
|
|
69728
|
+
if (u8.prototype.slice)
|
|
69729
|
+
return u8.prototype.slice.call(v2, s3, e);
|
|
69730
|
+
if (s3 == null || s3 < 0)
|
|
69731
|
+
s3 = 0;
|
|
69732
|
+
if (e == null || e > v2.length)
|
|
69733
|
+
e = v2.length;
|
|
69734
|
+
var n = new u8(e - s3);
|
|
69735
|
+
n.set(v2.subarray(s3, e));
|
|
69736
|
+
return n;
|
|
69737
|
+
};
|
|
69738
|
+
var fill = function(v2, n, s3, e) {
|
|
69739
|
+
if (u8.prototype.fill)
|
|
69740
|
+
return u8.prototype.fill.call(v2, n, s3, e);
|
|
69741
|
+
if (s3 == null || s3 < 0)
|
|
69742
|
+
s3 = 0;
|
|
69743
|
+
if (e == null || e > v2.length)
|
|
69744
|
+
e = v2.length;
|
|
69745
|
+
for (; s3 < e; ++s3)
|
|
69746
|
+
v2[s3] = n;
|
|
69747
|
+
return v2;
|
|
69748
|
+
};
|
|
69749
|
+
var cpw = function(v2, t, s3, e) {
|
|
69750
|
+
if (u8.prototype.copyWithin)
|
|
69751
|
+
return u8.prototype.copyWithin.call(v2, t, s3, e);
|
|
69752
|
+
if (s3 == null || s3 < 0)
|
|
69753
|
+
s3 = 0;
|
|
69754
|
+
if (e == null || e > v2.length)
|
|
69755
|
+
e = v2.length;
|
|
69756
|
+
while (s3 < e) {
|
|
69757
|
+
v2[t++] = v2[s3++];
|
|
69758
|
+
}
|
|
69759
|
+
};
|
|
69760
|
+
var ec = [
|
|
69761
|
+
"invalid zstd data",
|
|
69762
|
+
"window size too large (>2046MB)",
|
|
69763
|
+
"invalid block type",
|
|
69764
|
+
"FSE accuracy too high",
|
|
69765
|
+
"match distance too far back",
|
|
69766
|
+
"unexpected EOF"
|
|
69767
|
+
];
|
|
69768
|
+
var err = function(ind, msg, nt2) {
|
|
69769
|
+
var e = new Error(msg || ec[ind]);
|
|
69770
|
+
e.code = ind;
|
|
69771
|
+
if (Error.captureStackTrace)
|
|
69772
|
+
Error.captureStackTrace(e, err);
|
|
69773
|
+
if (!nt2)
|
|
69774
|
+
throw e;
|
|
69775
|
+
return e;
|
|
69776
|
+
};
|
|
69777
|
+
var rb = function(d, b2, n) {
|
|
69778
|
+
var i = 0, o = 0;
|
|
69779
|
+
for (; i < n; ++i)
|
|
69780
|
+
o |= d[b2++] << (i << 3);
|
|
69781
|
+
return o;
|
|
69782
|
+
};
|
|
69783
|
+
var b4 = function(d, b2) {
|
|
69784
|
+
return (d[b2] | d[b2 + 1] << 8 | d[b2 + 2] << 16 | d[b2 + 3] << 24) >>> 0;
|
|
69785
|
+
};
|
|
69786
|
+
var rzfh = function(dat, w2) {
|
|
69787
|
+
var n3 = dat[0] | dat[1] << 8 | dat[2] << 16;
|
|
69788
|
+
if (n3 == 3126568 && dat[3] == 253) {
|
|
69789
|
+
var flg = dat[4];
|
|
69790
|
+
var ss2 = flg >> 5 & 1, cc = flg >> 2 & 1, df = flg & 3, fcf = flg >> 6;
|
|
69791
|
+
if (flg & 8)
|
|
69792
|
+
err(0);
|
|
69793
|
+
var bt2 = 6 - ss2;
|
|
69794
|
+
var db = df == 3 ? 4 : df;
|
|
69795
|
+
var di2 = rb(dat, bt2, db);
|
|
69796
|
+
bt2 += db;
|
|
69797
|
+
var fsb = fcf ? 1 << fcf : ss2;
|
|
69798
|
+
var fss = rb(dat, bt2, fsb) + (fcf == 1 && 256);
|
|
69799
|
+
var ws2 = fss;
|
|
69800
|
+
if (!ss2) {
|
|
69801
|
+
var wb = 1 << 10 + (dat[5] >> 3);
|
|
69802
|
+
ws2 = wb + (wb >> 3) * (dat[5] & 7);
|
|
69803
|
+
}
|
|
69804
|
+
if (ws2 > 2145386496)
|
|
69805
|
+
err(1);
|
|
69806
|
+
var buf = new u8((w2 == 1 ? fss || ws2 : w2 ? 0 : ws2) + 12);
|
|
69807
|
+
buf[0] = 1, buf[4] = 4, buf[8] = 8;
|
|
69808
|
+
return {
|
|
69809
|
+
b: bt2 + fsb,
|
|
69810
|
+
y: 0,
|
|
69811
|
+
l: 0,
|
|
69812
|
+
d: di2,
|
|
69813
|
+
w: w2 && w2 != 1 ? w2 : buf.subarray(12),
|
|
69814
|
+
e: ws2,
|
|
69815
|
+
o: new i32(buf.buffer, 0, 3),
|
|
69816
|
+
u: fss,
|
|
69817
|
+
c: cc,
|
|
69818
|
+
m: Math.min(131072, ws2)
|
|
69819
|
+
};
|
|
69820
|
+
} else if ((n3 >> 4 | dat[3] << 20) == 25481893) {
|
|
69821
|
+
return b4(dat, 4) + 8;
|
|
69822
|
+
}
|
|
69823
|
+
err(0);
|
|
69824
|
+
};
|
|
69825
|
+
var msb = function(val) {
|
|
69826
|
+
var bits = 0;
|
|
69827
|
+
for (; 1 << bits <= val; ++bits)
|
|
69828
|
+
;
|
|
69829
|
+
return bits - 1;
|
|
69830
|
+
};
|
|
69831
|
+
var rfse = function(dat, bt2, mal) {
|
|
69832
|
+
var tpos = (bt2 << 3) + 4;
|
|
69833
|
+
var al = (dat[bt2] & 15) + 5;
|
|
69834
|
+
if (al > mal)
|
|
69835
|
+
err(3);
|
|
69836
|
+
var sz = 1 << al;
|
|
69837
|
+
var probs = sz, sym = -1, re2 = -1, i = -1, ht2 = sz;
|
|
69838
|
+
var buf = new ab(512 + (sz << 2));
|
|
69839
|
+
var freq = new i16(buf, 0, 256);
|
|
69840
|
+
var dstate = new u16(buf, 0, 256);
|
|
69841
|
+
var nstate = new u16(buf, 512, sz);
|
|
69842
|
+
var bb1 = 512 + (sz << 1);
|
|
69843
|
+
var syms = new u8(buf, bb1, sz);
|
|
69844
|
+
var nbits = new u8(buf, bb1 + sz);
|
|
69845
|
+
while (sym < 255 && probs > 0) {
|
|
69846
|
+
var bits = msb(probs + 1);
|
|
69847
|
+
var cbt = tpos >> 3;
|
|
69848
|
+
var msk = (1 << bits + 1) - 1;
|
|
69849
|
+
var val = (dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (tpos & 7) & msk;
|
|
69850
|
+
var msk1fb = (1 << bits) - 1;
|
|
69851
|
+
var msv = msk - probs - 1;
|
|
69852
|
+
var sval = val & msk1fb;
|
|
69853
|
+
if (sval < msv)
|
|
69854
|
+
tpos += bits, val = sval;
|
|
69855
|
+
else {
|
|
69856
|
+
tpos += bits + 1;
|
|
69857
|
+
if (val > msk1fb)
|
|
69858
|
+
val -= msv;
|
|
69859
|
+
}
|
|
69860
|
+
freq[++sym] = --val;
|
|
69861
|
+
if (val == -1) {
|
|
69862
|
+
probs += val;
|
|
69863
|
+
syms[--ht2] = sym;
|
|
69864
|
+
} else
|
|
69865
|
+
probs -= val;
|
|
69866
|
+
if (!val) {
|
|
69867
|
+
do {
|
|
69868
|
+
var rbt = tpos >> 3;
|
|
69869
|
+
re2 = (dat[rbt] | dat[rbt + 1] << 8) >> (tpos & 7) & 3;
|
|
69870
|
+
tpos += 2;
|
|
69871
|
+
sym += re2;
|
|
69872
|
+
} while (re2 == 3);
|
|
69873
|
+
}
|
|
69874
|
+
}
|
|
69875
|
+
if (sym > 255 || probs)
|
|
69876
|
+
err(0);
|
|
69877
|
+
var sympos = 0;
|
|
69878
|
+
var sstep = (sz >> 1) + (sz >> 3) + 3;
|
|
69879
|
+
var smask = sz - 1;
|
|
69880
|
+
for (var s3 = 0; s3 <= sym; ++s3) {
|
|
69881
|
+
var sf = freq[s3];
|
|
69882
|
+
if (sf < 1) {
|
|
69883
|
+
dstate[s3] = -sf;
|
|
69884
|
+
continue;
|
|
69885
|
+
}
|
|
69886
|
+
for (i = 0; i < sf; ++i) {
|
|
69887
|
+
syms[sympos] = s3;
|
|
69888
|
+
do {
|
|
69889
|
+
sympos = sympos + sstep & smask;
|
|
69890
|
+
} while (sympos >= ht2);
|
|
69891
|
+
}
|
|
69892
|
+
}
|
|
69893
|
+
if (sympos)
|
|
69894
|
+
err(0);
|
|
69895
|
+
for (i = 0; i < sz; ++i) {
|
|
69896
|
+
var ns2 = dstate[syms[i]]++;
|
|
69897
|
+
var nb = nbits[i] = al - msb(ns2);
|
|
69898
|
+
nstate[i] = (ns2 << nb) - sz;
|
|
69899
|
+
}
|
|
69900
|
+
return [tpos + 7 >> 3, {
|
|
69901
|
+
b: al,
|
|
69902
|
+
s: syms,
|
|
69903
|
+
n: nbits,
|
|
69904
|
+
t: nstate
|
|
69905
|
+
}];
|
|
69906
|
+
};
|
|
69907
|
+
var rhu = function(dat, bt2) {
|
|
69908
|
+
var i = 0, wc = -1;
|
|
69909
|
+
var buf = new u8(292), hb = dat[bt2];
|
|
69910
|
+
var hw = buf.subarray(0, 256);
|
|
69911
|
+
var rc = buf.subarray(256, 268);
|
|
69912
|
+
var ri2 = new u16(buf.buffer, 268);
|
|
69913
|
+
if (hb < 128) {
|
|
69914
|
+
var _a = rfse(dat, bt2 + 1, 6), ebt = _a[0], fdt = _a[1];
|
|
69915
|
+
bt2 += hb;
|
|
69916
|
+
var epos = ebt << 3;
|
|
69917
|
+
var lb = dat[bt2];
|
|
69918
|
+
if (!lb)
|
|
69919
|
+
err(0);
|
|
69920
|
+
var st1 = 0, st2 = 0, btr1 = fdt.b, btr2 = btr1;
|
|
69921
|
+
var fpos = (++bt2 << 3) - 8 + msb(lb);
|
|
69922
|
+
for (; ; ) {
|
|
69923
|
+
fpos -= btr1;
|
|
69924
|
+
if (fpos < epos)
|
|
69925
|
+
break;
|
|
69926
|
+
var cbt = fpos >> 3;
|
|
69927
|
+
st1 += (dat[cbt] | dat[cbt + 1] << 8) >> (fpos & 7) & (1 << btr1) - 1;
|
|
69928
|
+
hw[++wc] = fdt.s[st1];
|
|
69929
|
+
fpos -= btr2;
|
|
69930
|
+
if (fpos < epos)
|
|
69931
|
+
break;
|
|
69932
|
+
cbt = fpos >> 3;
|
|
69933
|
+
st2 += (dat[cbt] | dat[cbt + 1] << 8) >> (fpos & 7) & (1 << btr2) - 1;
|
|
69934
|
+
hw[++wc] = fdt.s[st2];
|
|
69935
|
+
btr1 = fdt.n[st1];
|
|
69936
|
+
st1 = fdt.t[st1];
|
|
69937
|
+
btr2 = fdt.n[st2];
|
|
69938
|
+
st2 = fdt.t[st2];
|
|
69939
|
+
}
|
|
69940
|
+
if (++wc > 255)
|
|
69941
|
+
err(0);
|
|
69942
|
+
} else {
|
|
69943
|
+
wc = hb - 127;
|
|
69944
|
+
for (; i < wc; i += 2) {
|
|
69945
|
+
var byte = dat[++bt2];
|
|
69946
|
+
hw[i] = byte >> 4;
|
|
69947
|
+
hw[i + 1] = byte & 15;
|
|
69948
|
+
}
|
|
69949
|
+
++bt2;
|
|
69950
|
+
}
|
|
69951
|
+
var wes = 0;
|
|
69952
|
+
for (i = 0; i < wc; ++i) {
|
|
69953
|
+
var wt2 = hw[i];
|
|
69954
|
+
if (wt2 > 11)
|
|
69955
|
+
err(0);
|
|
69956
|
+
wes += wt2 && 1 << wt2 - 1;
|
|
69957
|
+
}
|
|
69958
|
+
var mb = msb(wes) + 1;
|
|
69959
|
+
var ts2 = 1 << mb;
|
|
69960
|
+
var rem = ts2 - wes;
|
|
69961
|
+
if (rem & rem - 1)
|
|
69962
|
+
err(0);
|
|
69963
|
+
hw[wc++] = msb(rem) + 1;
|
|
69964
|
+
for (i = 0; i < wc; ++i) {
|
|
69965
|
+
var wt2 = hw[i];
|
|
69966
|
+
++rc[hw[i] = wt2 && mb + 1 - wt2];
|
|
69967
|
+
}
|
|
69968
|
+
var hbuf = new u8(ts2 << 1);
|
|
69969
|
+
var syms = hbuf.subarray(0, ts2), nb = hbuf.subarray(ts2);
|
|
69970
|
+
ri2[mb] = 0;
|
|
69971
|
+
for (i = mb; i > 0; --i) {
|
|
69972
|
+
var pv = ri2[i];
|
|
69973
|
+
fill(nb, i, pv, ri2[i - 1] = pv + rc[i] * (1 << mb - i));
|
|
69974
|
+
}
|
|
69975
|
+
if (ri2[0] != ts2)
|
|
69976
|
+
err(0);
|
|
69977
|
+
for (i = 0; i < wc; ++i) {
|
|
69978
|
+
var bits = hw[i];
|
|
69979
|
+
if (bits) {
|
|
69980
|
+
var code = ri2[bits];
|
|
69981
|
+
fill(syms, i, code, ri2[bits] = code + (1 << mb - bits));
|
|
69982
|
+
}
|
|
69983
|
+
}
|
|
69984
|
+
return [bt2, {
|
|
69985
|
+
n: nb,
|
|
69986
|
+
b: mb,
|
|
69987
|
+
s: syms
|
|
69988
|
+
}];
|
|
69989
|
+
};
|
|
69990
|
+
var dllt = rfse(/* @__PURE__ */ new u8([
|
|
69991
|
+
81,
|
|
69992
|
+
16,
|
|
69993
|
+
99,
|
|
69994
|
+
140,
|
|
69995
|
+
49,
|
|
69996
|
+
198,
|
|
69997
|
+
24,
|
|
69998
|
+
99,
|
|
69999
|
+
12,
|
|
70000
|
+
33,
|
|
70001
|
+
196,
|
|
70002
|
+
24,
|
|
70003
|
+
99,
|
|
70004
|
+
102,
|
|
70005
|
+
102,
|
|
70006
|
+
134,
|
|
70007
|
+
70,
|
|
70008
|
+
146,
|
|
70009
|
+
4
|
|
70010
|
+
]), 0, 6)[1];
|
|
70011
|
+
var dmlt = rfse(/* @__PURE__ */ new u8([
|
|
70012
|
+
33,
|
|
70013
|
+
20,
|
|
70014
|
+
196,
|
|
70015
|
+
24,
|
|
70016
|
+
99,
|
|
70017
|
+
140,
|
|
70018
|
+
33,
|
|
70019
|
+
132,
|
|
70020
|
+
16,
|
|
70021
|
+
66,
|
|
70022
|
+
8,
|
|
70023
|
+
33,
|
|
70024
|
+
132,
|
|
70025
|
+
16,
|
|
70026
|
+
66,
|
|
70027
|
+
8,
|
|
70028
|
+
33,
|
|
70029
|
+
68,
|
|
70030
|
+
68,
|
|
70031
|
+
68,
|
|
70032
|
+
68,
|
|
70033
|
+
68,
|
|
70034
|
+
68,
|
|
70035
|
+
68,
|
|
70036
|
+
68,
|
|
70037
|
+
36,
|
|
70038
|
+
9
|
|
70039
|
+
]), 0, 6)[1];
|
|
70040
|
+
var doct = rfse(/* @__PURE__ */ new u8([
|
|
70041
|
+
32,
|
|
70042
|
+
132,
|
|
70043
|
+
16,
|
|
70044
|
+
66,
|
|
70045
|
+
102,
|
|
70046
|
+
70,
|
|
70047
|
+
68,
|
|
70048
|
+
68,
|
|
70049
|
+
68,
|
|
70050
|
+
68,
|
|
70051
|
+
36,
|
|
70052
|
+
73,
|
|
70053
|
+
2
|
|
70054
|
+
]), 0, 5)[1];
|
|
70055
|
+
var b2bl = function(b2, s3) {
|
|
70056
|
+
var len = b2.length, bl = new i32(len);
|
|
70057
|
+
for (var i = 0; i < len; ++i) {
|
|
70058
|
+
bl[i] = s3;
|
|
70059
|
+
s3 += 1 << b2[i];
|
|
70060
|
+
}
|
|
70061
|
+
return bl;
|
|
70062
|
+
};
|
|
70063
|
+
var llb = /* @__PURE__ */ new u8((/* @__PURE__ */ new i32([
|
|
70064
|
+
0,
|
|
70065
|
+
0,
|
|
70066
|
+
0,
|
|
70067
|
+
0,
|
|
70068
|
+
16843009,
|
|
70069
|
+
50528770,
|
|
70070
|
+
134678020,
|
|
70071
|
+
202050057,
|
|
70072
|
+
269422093
|
|
70073
|
+
])).buffer, 0, 36);
|
|
70074
|
+
var llbl = /* @__PURE__ */ b2bl(llb, 0);
|
|
70075
|
+
var mlb = /* @__PURE__ */ new u8((/* @__PURE__ */ new i32([
|
|
70076
|
+
0,
|
|
70077
|
+
0,
|
|
70078
|
+
0,
|
|
70079
|
+
0,
|
|
70080
|
+
0,
|
|
70081
|
+
0,
|
|
70082
|
+
0,
|
|
70083
|
+
0,
|
|
70084
|
+
16843009,
|
|
70085
|
+
50528770,
|
|
70086
|
+
117769220,
|
|
70087
|
+
185207048,
|
|
70088
|
+
252579084,
|
|
70089
|
+
16
|
|
70090
|
+
])).buffer, 0, 53);
|
|
70091
|
+
var mlbl = /* @__PURE__ */ b2bl(mlb, 3);
|
|
70092
|
+
var dhu = function(dat, out, hu) {
|
|
70093
|
+
var len = dat.length, ss2 = out.length, lb = dat[len - 1], msk = (1 << hu.b) - 1, eb = -hu.b;
|
|
70094
|
+
if (!lb)
|
|
70095
|
+
err(0);
|
|
70096
|
+
var st2 = 0, btr = hu.b, pos = (len << 3) - 8 + msb(lb) - btr, i = -1;
|
|
70097
|
+
for (; pos > eb && i < ss2; ) {
|
|
70098
|
+
var cbt = pos >> 3;
|
|
70099
|
+
var val = (dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (pos & 7);
|
|
70100
|
+
st2 = (st2 << btr | val) & msk;
|
|
70101
|
+
out[++i] = hu.s[st2];
|
|
70102
|
+
pos -= btr = hu.n[st2];
|
|
70103
|
+
}
|
|
70104
|
+
if (pos != eb || i + 1 != ss2)
|
|
70105
|
+
err(0);
|
|
70106
|
+
};
|
|
70107
|
+
var dhu4 = function(dat, out, hu) {
|
|
70108
|
+
var bt2 = 6;
|
|
70109
|
+
var ss2 = out.length, sz1 = ss2 + 3 >> 2, sz2 = sz1 << 1, sz3 = sz1 + sz2;
|
|
70110
|
+
dhu(dat.subarray(bt2, bt2 += dat[0] | dat[1] << 8), out.subarray(0, sz1), hu);
|
|
70111
|
+
dhu(dat.subarray(bt2, bt2 += dat[2] | dat[3] << 8), out.subarray(sz1, sz2), hu);
|
|
70112
|
+
dhu(dat.subarray(bt2, bt2 += dat[4] | dat[5] << 8), out.subarray(sz2, sz3), hu);
|
|
70113
|
+
dhu(dat.subarray(bt2), out.subarray(sz3), hu);
|
|
70114
|
+
};
|
|
70115
|
+
var rzb = function(dat, st2, out) {
|
|
70116
|
+
var _a;
|
|
70117
|
+
var bt2 = st2.b;
|
|
70118
|
+
var b0 = dat[bt2], btype = b0 >> 1 & 3;
|
|
70119
|
+
st2.l = b0 & 1;
|
|
70120
|
+
var sz = b0 >> 3 | dat[bt2 + 1] << 5 | dat[bt2 + 2] << 13;
|
|
70121
|
+
var ebt = (bt2 += 3) + sz;
|
|
70122
|
+
if (btype == 1) {
|
|
70123
|
+
if (bt2 >= dat.length)
|
|
70124
|
+
return;
|
|
70125
|
+
st2.b = bt2 + 1;
|
|
70126
|
+
if (out) {
|
|
70127
|
+
fill(out, dat[bt2], st2.y, st2.y += sz);
|
|
70128
|
+
return out;
|
|
70129
|
+
}
|
|
70130
|
+
return fill(new u8(sz), dat[bt2]);
|
|
70165
70131
|
}
|
|
70166
|
-
|
|
70167
|
-
|
|
70168
|
-
|
|
70169
|
-
|
|
70170
|
-
|
|
70171
|
-
|
|
70172
|
-
|
|
70173
|
-
|
|
70174
|
-
replaced = true;
|
|
70175
|
-
out.push(`data: ${JSON.stringify(ev)}`);
|
|
70176
|
-
continue;
|
|
70132
|
+
if (ebt > dat.length)
|
|
70133
|
+
return;
|
|
70134
|
+
if (btype == 0) {
|
|
70135
|
+
st2.b = ebt;
|
|
70136
|
+
if (out) {
|
|
70137
|
+
out.set(dat.subarray(bt2, ebt), st2.y);
|
|
70138
|
+
st2.y += sz;
|
|
70139
|
+
return out;
|
|
70177
70140
|
}
|
|
70178
|
-
|
|
70179
|
-
}
|
|
70180
|
-
return replaced ? out.join("\n") + "\n\n" : `data: ${JSON.stringify(ev)}
|
|
70181
|
-
|
|
70182
|
-
`;
|
|
70183
|
-
}
|
|
70184
|
-
function stripGoogleChunk(obj) {
|
|
70185
|
-
if (!obj || typeof obj !== "object") return obj;
|
|
70186
|
-
const o = obj;
|
|
70187
|
-
const candidates = o["candidates"];
|
|
70188
|
-
if (!Array.isArray(candidates)) return obj;
|
|
70189
|
-
o["candidates"] = candidates.map((c) => {
|
|
70190
|
-
if (!c || typeof c !== "object") return c;
|
|
70191
|
-
const cand = c;
|
|
70192
|
-
const content = cand["content"];
|
|
70193
|
-
if (!content || typeof content !== "object") return c;
|
|
70194
|
-
const cont = content;
|
|
70195
|
-
if (!Array.isArray(cont["parts"])) return c;
|
|
70196
|
-
return {
|
|
70197
|
-
...cand,
|
|
70198
|
-
content: {
|
|
70199
|
-
...cont,
|
|
70200
|
-
parts: cont["parts"].map(
|
|
70201
|
-
(p2) => p2 && typeof p2 === "object" && typeof p2["text"] === "string" ? { ...p2, text: stripAcpTags(p2["text"]) } : p2
|
|
70202
|
-
)
|
|
70203
|
-
}
|
|
70204
|
-
};
|
|
70205
|
-
});
|
|
70206
|
-
return obj;
|
|
70207
|
-
}
|
|
70208
|
-
function stripGoogleText(obj) {
|
|
70209
|
-
if (Array.isArray(obj)) {
|
|
70210
|
-
obj.forEach((c) => {
|
|
70211
|
-
stripGoogleChunk(c);
|
|
70212
|
-
});
|
|
70213
|
-
return obj;
|
|
70141
|
+
return slc(dat, bt2, ebt);
|
|
70214
70142
|
}
|
|
70215
|
-
|
|
70216
|
-
|
|
70217
|
-
|
|
70218
|
-
|
|
70219
|
-
|
|
70220
|
-
|
|
70221
|
-
|
|
70222
|
-
|
|
70223
|
-
|
|
70224
|
-
|
|
70143
|
+
if (btype == 2) {
|
|
70144
|
+
var b3 = dat[bt2], lbt = b3 & 3, sf = b3 >> 2 & 3;
|
|
70145
|
+
var lss = b3 >> 4, lcs = 0, s4 = 0;
|
|
70146
|
+
if (lbt < 2) {
|
|
70147
|
+
if (sf & 1)
|
|
70148
|
+
lss |= dat[++bt2] << 4 | (sf & 2 && dat[++bt2] << 12);
|
|
70149
|
+
else
|
|
70150
|
+
lss = b3 >> 3;
|
|
70151
|
+
} else {
|
|
70152
|
+
s4 = sf;
|
|
70153
|
+
if (sf < 2)
|
|
70154
|
+
lss |= (dat[++bt2] & 63) << 4, lcs = dat[bt2] >> 6 | dat[++bt2] << 2;
|
|
70155
|
+
else if (sf == 2)
|
|
70156
|
+
lss |= dat[++bt2] << 4 | (dat[++bt2] & 3) << 12, lcs = dat[bt2] >> 2 | dat[++bt2] << 6;
|
|
70157
|
+
else
|
|
70158
|
+
lss |= dat[++bt2] << 4 | (dat[++bt2] & 63) << 12, lcs = dat[bt2] >> 6 | dat[++bt2] << 2 | dat[++bt2] << 10;
|
|
70225
70159
|
}
|
|
70226
|
-
|
|
70227
|
-
|
|
70228
|
-
|
|
70229
|
-
|
|
70230
|
-
|
|
70231
|
-
|
|
70232
|
-
|
|
70233
|
-
|
|
70234
|
-
|
|
70235
|
-
|
|
70236
|
-
|
|
70237
|
-
|
|
70238
|
-
|
|
70239
|
-
|
|
70240
|
-
|
|
70241
|
-
|
|
70242
|
-
|
|
70243
|
-
|
|
70244
|
-
|
|
70245
|
-
|
|
70246
|
-
|
|
70247
|
-
|
|
70248
|
-
|
|
70249
|
-
|
|
70250
|
-
|
|
70160
|
+
++bt2;
|
|
70161
|
+
var buf = out ? out.subarray(st2.y, st2.y + st2.m) : new u8(st2.m);
|
|
70162
|
+
var spl = buf.length - lss;
|
|
70163
|
+
if (lbt == 0)
|
|
70164
|
+
buf.set(dat.subarray(bt2, bt2 += lss), spl);
|
|
70165
|
+
else if (lbt == 1)
|
|
70166
|
+
fill(buf, dat[bt2++], spl);
|
|
70167
|
+
else {
|
|
70168
|
+
var hu = st2.h;
|
|
70169
|
+
if (lbt == 2) {
|
|
70170
|
+
var hud = rhu(dat, bt2);
|
|
70171
|
+
lcs += bt2 - (bt2 = hud[0]);
|
|
70172
|
+
st2.h = hu = hud[1];
|
|
70173
|
+
} else if (!hu)
|
|
70174
|
+
err(0);
|
|
70175
|
+
(s4 ? dhu4 : dhu)(dat.subarray(bt2, bt2 += lcs), buf.subarray(spl), hu);
|
|
70176
|
+
}
|
|
70177
|
+
var ns2 = dat[bt2++];
|
|
70178
|
+
if (ns2) {
|
|
70179
|
+
if (ns2 == 255)
|
|
70180
|
+
ns2 = (dat[bt2++] | dat[bt2++] << 8) + 32512;
|
|
70181
|
+
else if (ns2 > 127)
|
|
70182
|
+
ns2 = ns2 - 128 << 8 | dat[bt2++];
|
|
70183
|
+
var scm = dat[bt2++];
|
|
70184
|
+
if (scm & 3)
|
|
70185
|
+
err(0);
|
|
70186
|
+
var dts = [dmlt, doct, dllt];
|
|
70187
|
+
for (var i = 2; i > -1; --i) {
|
|
70188
|
+
var md = scm >> (i << 1) + 2 & 3;
|
|
70189
|
+
if (md == 1) {
|
|
70190
|
+
var rbuf = new u8([0, 0, dat[bt2++]]);
|
|
70191
|
+
dts[i] = {
|
|
70192
|
+
s: rbuf.subarray(2, 3),
|
|
70193
|
+
n: rbuf.subarray(0, 1),
|
|
70194
|
+
t: new u16(rbuf.buffer, 0, 1),
|
|
70195
|
+
b: 0
|
|
70196
|
+
};
|
|
70197
|
+
} else if (md == 2) {
|
|
70198
|
+
_a = rfse(dat, bt2, 9 - (i & 1)), bt2 = _a[0], dts[i] = _a[1];
|
|
70199
|
+
} else if (md == 3) {
|
|
70200
|
+
if (!st2.t)
|
|
70201
|
+
err(0);
|
|
70202
|
+
dts[i] = st2.t[i];
|
|
70203
|
+
}
|
|
70204
|
+
}
|
|
70205
|
+
var _b = st2.t = dts, mlt = _b[0], oct = _b[1], llt = _b[2];
|
|
70206
|
+
var lb = dat[ebt - 1];
|
|
70207
|
+
if (!lb)
|
|
70208
|
+
err(0);
|
|
70209
|
+
var spos = (ebt << 3) - 8 + msb(lb) - llt.b, cbt = spos >> 3, oubt = 0;
|
|
70210
|
+
var lst = (dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << llt.b) - 1;
|
|
70211
|
+
cbt = (spos -= oct.b) >> 3;
|
|
70212
|
+
var ost = (dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << oct.b) - 1;
|
|
70213
|
+
cbt = (spos -= mlt.b) >> 3;
|
|
70214
|
+
var mst = (dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << mlt.b) - 1;
|
|
70215
|
+
for (++ns2; --ns2; ) {
|
|
70216
|
+
var llc = llt.s[lst];
|
|
70217
|
+
var lbtr = llt.n[lst];
|
|
70218
|
+
var mlc = mlt.s[mst];
|
|
70219
|
+
var mbtr = mlt.n[mst];
|
|
70220
|
+
var ofc = oct.s[ost];
|
|
70221
|
+
var obtr = oct.n[ost];
|
|
70222
|
+
cbt = (spos -= ofc) >> 3;
|
|
70223
|
+
var ofp = 1 << ofc;
|
|
70224
|
+
var off = ofp + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16 | dat[cbt + 3] << 24) >>> (spos & 7) & ofp - 1);
|
|
70225
|
+
cbt = (spos -= mlb[mlc]) >> 3;
|
|
70226
|
+
var ml = mlbl[mlc] + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (spos & 7) & (1 << mlb[mlc]) - 1);
|
|
70227
|
+
cbt = (spos -= llb[llc]) >> 3;
|
|
70228
|
+
var ll = llbl[llc] + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (spos & 7) & (1 << llb[llc]) - 1);
|
|
70229
|
+
cbt = (spos -= lbtr) >> 3;
|
|
70230
|
+
lst = llt.t[lst] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << lbtr) - 1);
|
|
70231
|
+
cbt = (spos -= mbtr) >> 3;
|
|
70232
|
+
mst = mlt.t[mst] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << mbtr) - 1);
|
|
70233
|
+
cbt = (spos -= obtr) >> 3;
|
|
70234
|
+
ost = oct.t[ost] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << obtr) - 1);
|
|
70235
|
+
if (off > 3) {
|
|
70236
|
+
st2.o[2] = st2.o[1];
|
|
70237
|
+
st2.o[1] = st2.o[0];
|
|
70238
|
+
st2.o[0] = off -= 3;
|
|
70239
|
+
} else {
|
|
70240
|
+
var idx = off - (ll != 0);
|
|
70241
|
+
if (idx) {
|
|
70242
|
+
off = idx == 3 ? st2.o[0] - 1 : st2.o[idx];
|
|
70243
|
+
if (idx > 1)
|
|
70244
|
+
st2.o[2] = st2.o[1];
|
|
70245
|
+
st2.o[1] = st2.o[0];
|
|
70246
|
+
st2.o[0] = off;
|
|
70247
|
+
} else
|
|
70248
|
+
off = st2.o[0];
|
|
70249
|
+
}
|
|
70250
|
+
for (var i = 0; i < ll; ++i) {
|
|
70251
|
+
buf[oubt + i] = buf[spl + i];
|
|
70252
|
+
}
|
|
70253
|
+
oubt += ll, spl += ll;
|
|
70254
|
+
var stin = oubt - off;
|
|
70255
|
+
if (stin < 0) {
|
|
70256
|
+
var len = -stin;
|
|
70257
|
+
var bs2 = st2.e + stin;
|
|
70258
|
+
if (len > ml)
|
|
70259
|
+
len = ml;
|
|
70260
|
+
for (var i = 0; i < len; ++i) {
|
|
70261
|
+
buf[oubt + i] = st2.w[bs2 + i];
|
|
70262
|
+
}
|
|
70263
|
+
oubt += len, ml -= len, stin = 0;
|
|
70264
|
+
}
|
|
70265
|
+
for (var i = 0; i < ml; ++i) {
|
|
70266
|
+
buf[oubt + i] = buf[stin + i];
|
|
70267
|
+
}
|
|
70268
|
+
oubt += ml;
|
|
70251
70269
|
}
|
|
70252
|
-
|
|
70253
|
-
|
|
70254
|
-
|
|
70255
|
-
|
|
70256
|
-
|
|
70257
|
-
|
|
70270
|
+
if (oubt != spl) {
|
|
70271
|
+
while (spl < buf.length) {
|
|
70272
|
+
buf[oubt++] = buf[spl++];
|
|
70273
|
+
}
|
|
70274
|
+
} else
|
|
70275
|
+
oubt = buf.length;
|
|
70276
|
+
if (out)
|
|
70277
|
+
st2.y += oubt;
|
|
70278
|
+
else
|
|
70279
|
+
buf = slc(buf, 0, oubt);
|
|
70280
|
+
} else if (out) {
|
|
70281
|
+
st2.y += lss;
|
|
70282
|
+
if (spl) {
|
|
70283
|
+
for (var i = 0; i < lss; ++i) {
|
|
70284
|
+
buf[i] = buf[spl + i];
|
|
70285
|
+
}
|
|
70258
70286
|
}
|
|
70259
|
-
}
|
|
70260
|
-
|
|
70261
|
-
|
|
70262
|
-
|
|
70263
|
-
json = protocol === "responses" ? stripResponsesText(json) : protocol === "anthropic" ? stripAnthropicText(json) : protocol === "google" ? stripGoogleText(json) : stripOpenaiChatText(json);
|
|
70264
|
-
mutated = true;
|
|
70265
|
-
}
|
|
70266
|
-
if (mutated && json) {
|
|
70267
|
-
res.end(Buffer.from(JSON.stringify(json), "utf8"));
|
|
70268
|
-
return;
|
|
70269
|
-
}
|
|
70270
|
-
res.end(text);
|
|
70271
|
-
}
|
|
70272
|
-
|
|
70273
|
-
// src/tunnel-guard.ts
|
|
70274
|
-
import { lookup } from "dns/promises";
|
|
70275
|
-
import { networkInterfaces } from "os";
|
|
70276
|
-
var BILI_TUNNEL_HEADER = "x-bili-tunnel";
|
|
70277
|
-
function parseIpLiteral(s3) {
|
|
70278
|
-
const t = s3.trim().toLowerCase();
|
|
70279
|
-
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(t)) return t;
|
|
70280
|
-
if (t.includes(":")) return t;
|
|
70281
|
-
return null;
|
|
70282
|
-
}
|
|
70283
|
-
function normalizeIpLiteral(ip) {
|
|
70284
|
-
const t = ip.trim().toLowerCase();
|
|
70285
|
-
if (!t.startsWith("::ffff:")) return t;
|
|
70286
|
-
const dotted = t.match(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/);
|
|
70287
|
-
if (dotted) return dotted[1];
|
|
70288
|
-
const hex = t.match(/^::ffff:0*([0-9a-f]{1,4}):0*([0-9a-f]{1,4})$/);
|
|
70289
|
-
if (hex) {
|
|
70290
|
-
const hi2 = parseInt(hex[1], 16);
|
|
70291
|
-
const lo2 = parseInt(hex[2], 16);
|
|
70292
|
-
return `${hi2 >> 8 & 255}.${hi2 & 255}.${lo2 >> 8 & 255}.${lo2 & 255}`;
|
|
70293
|
-
}
|
|
70294
|
-
return t;
|
|
70295
|
-
}
|
|
70296
|
-
function classifyIp(ip) {
|
|
70297
|
-
const lit = normalizeIpLiteral(parseIpLiteral(ip) ?? "");
|
|
70298
|
-
if (!lit) return "public";
|
|
70299
|
-
if (lit.includes(":")) {
|
|
70300
|
-
if (lit === "::1" || lit === "::") return "loopback";
|
|
70301
|
-
if (lit.startsWith("fe8") || lit.startsWith("fe9") || lit.startsWith("fea") || lit.startsWith("feb")) return "linkLocal";
|
|
70302
|
-
if (lit.startsWith("fc") || lit.startsWith("fd")) return "private";
|
|
70303
|
-
return "public";
|
|
70287
|
+
} else if (spl)
|
|
70288
|
+
buf = slc(buf, spl);
|
|
70289
|
+
st2.b = ebt;
|
|
70290
|
+
return buf;
|
|
70304
70291
|
}
|
|
70305
|
-
|
|
70306
|
-
const [a, b2] = parts;
|
|
70307
|
-
if (a === 127) return "loopback";
|
|
70308
|
-
if (a === 169 && b2 === 254) return "linkLocal";
|
|
70309
|
-
if (a === 10 || a === 0) return "private";
|
|
70310
|
-
if (a === 172 && b2 >= 16 && b2 <= 31) return "private";
|
|
70311
|
-
if (a === 192 && b2 === 168) return "private";
|
|
70312
|
-
if (a === 100 && b2 >= 64 && b2 <= 127) return "private";
|
|
70313
|
-
return "public";
|
|
70314
|
-
}
|
|
70315
|
-
var dnsResolveHost = async (host) => {
|
|
70316
|
-
const res = await lookup(host, { all: true, family: 0 });
|
|
70317
|
-
return res.map((r) => r.address);
|
|
70292
|
+
err(2);
|
|
70318
70293
|
};
|
|
70319
|
-
var
|
|
70320
|
-
|
|
70321
|
-
|
|
70322
|
-
|
|
70323
|
-
|
|
70324
|
-
|
|
70325
|
-
|
|
70326
|
-
|
|
70327
|
-
}
|
|
70328
|
-
}
|
|
70329
|
-
for (let i = 0; i <= 255; i++) ips.add(`127.0.0.${i}`);
|
|
70330
|
-
localAddrCache = { at: now, ips };
|
|
70294
|
+
var cct = function(bufs, ol) {
|
|
70295
|
+
if (bufs.length == 1)
|
|
70296
|
+
return bufs[0];
|
|
70297
|
+
var buf = new u8(ol);
|
|
70298
|
+
for (var i = 0, b2 = 0; i < bufs.length; ++i) {
|
|
70299
|
+
var chk = bufs[i];
|
|
70300
|
+
buf.set(chk, b2);
|
|
70301
|
+
b2 += chk.length;
|
|
70331
70302
|
}
|
|
70332
|
-
return
|
|
70333
|
-
}
|
|
70334
|
-
|
|
70335
|
-
|
|
70336
|
-
|
|
70337
|
-
|
|
70338
|
-
|
|
70339
|
-
|
|
70340
|
-
let u2;
|
|
70341
|
-
try {
|
|
70342
|
-
u2 = new URL(origin);
|
|
70343
|
-
} catch {
|
|
70344
|
-
return { ok: false, code: "unresolvable", message: `invalid tunnel destination ${origin}` };
|
|
70303
|
+
return buf;
|
|
70304
|
+
};
|
|
70305
|
+
var Decompress = /* @__PURE__ */ (function() {
|
|
70306
|
+
function Decompress2(ondata) {
|
|
70307
|
+
this.ondata = ondata;
|
|
70308
|
+
this.c = [];
|
|
70309
|
+
this.l = 0;
|
|
70310
|
+
this.z = 0;
|
|
70345
70311
|
}
|
|
70346
|
-
|
|
70347
|
-
|
|
70348
|
-
|
|
70349
|
-
|
|
70350
|
-
|
|
70351
|
-
ips = [normalizeIpLiteral(literal)];
|
|
70352
|
-
} else {
|
|
70353
|
-
try {
|
|
70354
|
-
ips = await (ctx.resolveHost ?? dnsResolveHost)(host);
|
|
70355
|
-
} catch {
|
|
70356
|
-
return { ok: false, code: "unresolvable", message: `cannot resolve tunnel destination ${host}` };
|
|
70312
|
+
Decompress2.prototype.push = function(chunk, final) {
|
|
70313
|
+
if (typeof this.s == "number") {
|
|
70314
|
+
var sub = Math.min(chunk.length, this.s);
|
|
70315
|
+
chunk = chunk.subarray(sub);
|
|
70316
|
+
this.s -= sub;
|
|
70357
70317
|
}
|
|
70358
|
-
|
|
70359
|
-
|
|
70360
|
-
|
|
70361
|
-
|
|
70362
|
-
|
|
70363
|
-
|
|
70318
|
+
var sl = chunk.length;
|
|
70319
|
+
var ncs = sl + this.l;
|
|
70320
|
+
if (!this.s) {
|
|
70321
|
+
if (final) {
|
|
70322
|
+
if (!ncs) {
|
|
70323
|
+
this.ondata(new u8(0), true);
|
|
70324
|
+
return;
|
|
70325
|
+
}
|
|
70326
|
+
if (ncs < 5)
|
|
70327
|
+
err(5);
|
|
70328
|
+
} else if (ncs < 18) {
|
|
70329
|
+
this.c.push(chunk);
|
|
70330
|
+
this.l = ncs;
|
|
70331
|
+
return;
|
|
70332
|
+
}
|
|
70333
|
+
if (this.l) {
|
|
70334
|
+
this.c.push(chunk);
|
|
70335
|
+
chunk = cct(this.c, ncs);
|
|
70336
|
+
this.c = [];
|
|
70337
|
+
this.l = 0;
|
|
70338
|
+
}
|
|
70339
|
+
if (typeof (this.s = rzfh(chunk)) == "number")
|
|
70340
|
+
return this.push(chunk, final);
|
|
70364
70341
|
}
|
|
70365
|
-
|
|
70366
|
-
|
|
70367
|
-
|
|
70368
|
-
|
|
70369
|
-
|
|
70370
|
-
|
|
70371
|
-
|
|
70372
|
-
|
|
70373
|
-
|
|
70374
|
-
|
|
70375
|
-
|
|
70376
|
-
|
|
70377
|
-
|
|
70378
|
-
|
|
70379
|
-
|
|
70380
|
-
|
|
70381
|
-
|
|
70382
|
-
|
|
70383
|
-
|
|
70384
|
-
|
|
70342
|
+
if (typeof this.s != "number") {
|
|
70343
|
+
if (ncs < (this.z || 3)) {
|
|
70344
|
+
if (final)
|
|
70345
|
+
err(5);
|
|
70346
|
+
this.c.push(chunk);
|
|
70347
|
+
this.l = ncs;
|
|
70348
|
+
return;
|
|
70349
|
+
}
|
|
70350
|
+
if (this.l) {
|
|
70351
|
+
this.c.push(chunk);
|
|
70352
|
+
chunk = cct(this.c, ncs);
|
|
70353
|
+
this.c = [];
|
|
70354
|
+
this.l = 0;
|
|
70355
|
+
}
|
|
70356
|
+
if (!this.z && ncs < (this.z = chunk[this.s.b] & 2 ? 4 : 3 + (chunk[this.s.b] >> 3 | chunk[this.s.b + 1] << 5 | chunk[this.s.b + 2] << 13))) {
|
|
70357
|
+
if (final)
|
|
70358
|
+
err(5);
|
|
70359
|
+
this.c.push(chunk);
|
|
70360
|
+
this.l = ncs;
|
|
70361
|
+
return;
|
|
70362
|
+
} else
|
|
70363
|
+
this.z = 0;
|
|
70364
|
+
for (; ; ) {
|
|
70365
|
+
var blk = rzb(chunk, this.s);
|
|
70366
|
+
if (!blk) {
|
|
70367
|
+
if (final)
|
|
70368
|
+
err(5);
|
|
70369
|
+
var adc = chunk.subarray(this.s.b);
|
|
70370
|
+
this.s.b = 0;
|
|
70371
|
+
this.c.push(adc), this.l += adc.length;
|
|
70372
|
+
return;
|
|
70373
|
+
} else {
|
|
70374
|
+
this.ondata(blk, false);
|
|
70375
|
+
cpw(this.s.w, 0, blk.length);
|
|
70376
|
+
this.s.w.set(blk, this.s.w.length - blk.length);
|
|
70377
|
+
}
|
|
70378
|
+
if (this.s.l) {
|
|
70379
|
+
var rest = chunk.subarray(this.s.b);
|
|
70380
|
+
this.s = this.s.c * 4;
|
|
70381
|
+
this.push(rest, final);
|
|
70382
|
+
return;
|
|
70383
|
+
}
|
|
70384
|
+
}
|
|
70385
|
+
} else if (final)
|
|
70386
|
+
err(5);
|
|
70387
|
+
};
|
|
70388
|
+
return Decompress2;
|
|
70389
|
+
})();
|
|
70385
70390
|
|
|
70386
70391
|
// src/content-encoding.ts
|
|
70387
|
-
import { createBrotliDecompress, createGunzip, createInflate, createInflateRaw } from "zlib";
|
|
70388
70392
|
var DecompressedTooLargeError = class extends Error {
|
|
70389
70393
|
constructor(limit) {
|
|
70390
70394
|
super(`decompressed request exceeds ${limit} bytes`);
|
|
@@ -71410,10 +71414,10 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
71410
71414
|
// so upstream prefix caches and the UI label stay continuous
|
|
71411
71415
|
// across main and subagent sessions.
|
|
71412
71416
|
claudeSub !== void 0 && opts.subagentSplit !== false ? claudeSubagentSplit(anthropicIdentity?.value ?? anthropicSignal, req.headers, systemTextsForSplit) : anthropicIdentity?.value ?? anthropicSignal
|
|
71413
|
-
) : protocol === "openai" ? openaiIdentity?.value ?? openaiSignal : codexTurn ? codexTurn.value :
|
|
71417
|
+
) : protocol === "openai" ? openaiIdentity?.value ?? openaiSignal : codexTurn ? codexTurn.value : instructionsFingerprintExempt(req.headers) ? responsesIdentity?.value ?? conversationSignalResponses(parsed, convHeader) : subagentNamespace(
|
|
71414
71418
|
responsesIdentity?.value ?? conversationSignalResponses(parsed, convHeader),
|
|
71415
71419
|
parsed.instructions
|
|
71416
|
-
)
|
|
71420
|
+
);
|
|
71417
71421
|
const clientProvided = protocol === "responses" ? responsesIdentity?.clientProvided ?? false : protocol === "openai" ? openaiIdentity?.clientProvided ?? false : protocol === "anthropic" ? anthropicIdentity?.clientProvided ?? false : protocol === "google" ? googleIdentity?.clientProvided ?? false : !!convHeader;
|
|
71418
71422
|
let anonAffinity = null;
|
|
71419
71423
|
if (!clientProvided) {
|