billion-context 0.1.92 → 0.1.93-pr.631.452
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 +278 -136
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5632,7 +5632,7 @@ var require_util2 = __commonJS({
|
|
|
5632
5632
|
callback();
|
|
5633
5633
|
}
|
|
5634
5634
|
};
|
|
5635
|
-
function
|
|
5635
|
+
function createInflate2(zlibOptions) {
|
|
5636
5636
|
return new InflateStream(zlibOptions);
|
|
5637
5637
|
}
|
|
5638
5638
|
function extractMimeType(headers) {
|
|
@@ -5764,7 +5764,7 @@ var require_util2 = __commonJS({
|
|
|
5764
5764
|
readAllBytes,
|
|
5765
5765
|
simpleRangeHeaderValue,
|
|
5766
5766
|
buildContentRange,
|
|
5767
|
-
createInflate,
|
|
5767
|
+
createInflate: createInflate2,
|
|
5768
5768
|
extractMimeType,
|
|
5769
5769
|
getDecodeSplit,
|
|
5770
5770
|
environmentSettingsObject,
|
|
@@ -13122,7 +13122,7 @@ var require_mock_interceptor = __commonJS({
|
|
|
13122
13122
|
var require_mock_client = __commonJS({
|
|
13123
13123
|
"node_modules/undici/lib/mock/mock-client.js"(exports, module) {
|
|
13124
13124
|
"use strict";
|
|
13125
|
-
var { promisify
|
|
13125
|
+
var { promisify } = __require("util");
|
|
13126
13126
|
var Client = require_client();
|
|
13127
13127
|
var { buildMockDispatch } = require_mock_utils();
|
|
13128
13128
|
var {
|
|
@@ -13170,7 +13170,7 @@ var require_mock_client = __commonJS({
|
|
|
13170
13170
|
this[kDispatches] = [];
|
|
13171
13171
|
}
|
|
13172
13172
|
async [kClose]() {
|
|
13173
|
-
await
|
|
13173
|
+
await promisify(this[kOriginalClose])();
|
|
13174
13174
|
this[kConnected] = 0;
|
|
13175
13175
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
13176
13176
|
}
|
|
@@ -13383,7 +13383,7 @@ var require_mock_call_history = __commonJS({
|
|
|
13383
13383
|
var require_mock_pool = __commonJS({
|
|
13384
13384
|
"node_modules/undici/lib/mock/mock-pool.js"(exports, module) {
|
|
13385
13385
|
"use strict";
|
|
13386
|
-
var { promisify
|
|
13386
|
+
var { promisify } = __require("util");
|
|
13387
13387
|
var Pool2 = require_pool();
|
|
13388
13388
|
var { buildMockDispatch } = require_mock_utils();
|
|
13389
13389
|
var {
|
|
@@ -13431,7 +13431,7 @@ var require_mock_pool = __commonJS({
|
|
|
13431
13431
|
this[kDispatches] = [];
|
|
13432
13432
|
}
|
|
13433
13433
|
async [kClose]() {
|
|
13434
|
-
await
|
|
13434
|
+
await promisify(this[kOriginalClose])();
|
|
13435
13435
|
this[kConnected] = 0;
|
|
13436
13436
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
13437
13437
|
}
|
|
@@ -17545,17 +17545,17 @@ var require_cache2 = __commonJS({
|
|
|
17545
17545
|
var require_decompress = __commonJS({
|
|
17546
17546
|
"node_modules/undici/lib/interceptor/decompress.js"(exports, module) {
|
|
17547
17547
|
"use strict";
|
|
17548
|
-
var { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = __require("zlib");
|
|
17548
|
+
var { createInflate: createInflate2, createGunzip: createGunzip2, createBrotliDecompress: createBrotliDecompress2, createZstdDecompress } = __require("zlib");
|
|
17549
17549
|
var { pipeline } = __require("stream");
|
|
17550
17550
|
var DecoratorHandler = require_decorator_handler();
|
|
17551
17551
|
var { runtimeFeatures } = require_runtime_features();
|
|
17552
17552
|
var supportedEncodings = {
|
|
17553
|
-
gzip:
|
|
17554
|
-
"x-gzip":
|
|
17555
|
-
br:
|
|
17556
|
-
deflate:
|
|
17557
|
-
compress:
|
|
17558
|
-
"x-compress":
|
|
17553
|
+
gzip: createGunzip2,
|
|
17554
|
+
"x-gzip": createGunzip2,
|
|
17555
|
+
br: createBrotliDecompress2,
|
|
17556
|
+
deflate: createInflate2,
|
|
17557
|
+
compress: createInflate2,
|
|
17558
|
+
"x-compress": createInflate2,
|
|
17559
17559
|
...runtimeFeatures.has("zstd") ? { zstd: createZstdDecompress } : {}
|
|
17560
17560
|
};
|
|
17561
17561
|
var defaultSkipStatusCodes = (
|
|
@@ -20384,7 +20384,7 @@ var require_fetch = __commonJS({
|
|
|
20384
20384
|
clampAndCoarsenConnectionTimingInfo,
|
|
20385
20385
|
simpleRangeHeaderValue,
|
|
20386
20386
|
buildContentRange,
|
|
20387
|
-
createInflate,
|
|
20387
|
+
createInflate: createInflate2,
|
|
20388
20388
|
extractMimeType,
|
|
20389
20389
|
hasAuthenticationEntry,
|
|
20390
20390
|
includesCredentials,
|
|
@@ -21366,7 +21366,7 @@ var require_fetch = __commonJS({
|
|
|
21366
21366
|
finishFlush: zlib.constants.Z_SYNC_FLUSH
|
|
21367
21367
|
}));
|
|
21368
21368
|
} else if (coding === "deflate") {
|
|
21369
|
-
decoders.push(
|
|
21369
|
+
decoders.push(createInflate2({
|
|
21370
21370
|
flush: zlib.constants.Z_SYNC_FLUSH,
|
|
21371
21371
|
finishFlush: zlib.constants.Z_SYNC_FLUSH
|
|
21372
21372
|
}));
|
|
@@ -23432,7 +23432,7 @@ var require_connection = __commonJS({
|
|
|
23432
23432
|
var require_permessage_deflate = __commonJS({
|
|
23433
23433
|
"node_modules/undici/lib/web/websocket/permessage-deflate.js"(exports, module) {
|
|
23434
23434
|
"use strict";
|
|
23435
|
-
var { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __require("zlib");
|
|
23435
|
+
var { createInflateRaw: createInflateRaw2, Z_DEFAULT_WINDOWBITS } = __require("zlib");
|
|
23436
23436
|
var { isValidClientWindowBits } = require_util5();
|
|
23437
23437
|
var { MessageSizeExceededError } = require_errors();
|
|
23438
23438
|
var tail = Buffer.from([0, 0, 255, 255]);
|
|
@@ -23468,7 +23468,7 @@ var require_permessage_deflate = __commonJS({
|
|
|
23468
23468
|
windowBits = Number.parseInt(this.#options.serverMaxWindowBits);
|
|
23469
23469
|
}
|
|
23470
23470
|
try {
|
|
23471
|
-
this.#inflate =
|
|
23471
|
+
this.#inflate = createInflateRaw2({ windowBits });
|
|
23472
23472
|
} catch (err2) {
|
|
23473
23473
|
callback(err2);
|
|
23474
23474
|
return;
|
|
@@ -38339,7 +38339,7 @@ var require_tls = __commonJS({
|
|
|
38339
38339
|
}
|
|
38340
38340
|
return rval;
|
|
38341
38341
|
};
|
|
38342
|
-
var
|
|
38342
|
+
var inflate = function(c, record, s3) {
|
|
38343
38343
|
var rval = false;
|
|
38344
38344
|
try {
|
|
38345
38345
|
var bytes = c.inflate(record.fragment.getBytes());
|
|
@@ -39484,7 +39484,7 @@ var require_tls = __commonJS({
|
|
|
39484
39484
|
case tls4.CompressionMethod.none:
|
|
39485
39485
|
break;
|
|
39486
39486
|
case tls4.CompressionMethod.deflate:
|
|
39487
|
-
state.read.compressFunction =
|
|
39487
|
+
state.read.compressFunction = inflate;
|
|
39488
39488
|
state.write.compressFunction = deflate;
|
|
39489
39489
|
break;
|
|
39490
39490
|
default:
|
|
@@ -46740,6 +46740,74 @@ function renderCompressedDrilldown(blocks, state, sort, limit, countTokens) {
|
|
|
46740
46740
|
}
|
|
46741
46741
|
return lines.join("\n");
|
|
46742
46742
|
}
|
|
46743
|
+
function renderMessage2(m2) {
|
|
46744
|
+
const parts = [];
|
|
46745
|
+
switch (m2.contentType) {
|
|
46746
|
+
case "text":
|
|
46747
|
+
parts.push(m2.text ?? "");
|
|
46748
|
+
break;
|
|
46749
|
+
case "tool-call":
|
|
46750
|
+
parts.push(`\`${m2.toolName ?? "?"}(${m2.toolCallId ?? ""})\` args: ${m2.text ?? ""}`);
|
|
46751
|
+
break;
|
|
46752
|
+
case "tool-result":
|
|
46753
|
+
parts.push(`\`${m2.toolName ?? "?"}(${m2.toolCallId ?? ""})\` \u2192 ${m2.text ?? ""}`);
|
|
46754
|
+
break;
|
|
46755
|
+
case "reasoning":
|
|
46756
|
+
parts.push(`_reasoning_: ${m2.text ?? ""}`);
|
|
46757
|
+
break;
|
|
46758
|
+
}
|
|
46759
|
+
const body = parts.join("\n").trim();
|
|
46760
|
+
return body === "" ? "_(empty)_" : body + "\n";
|
|
46761
|
+
}
|
|
46762
|
+
function renderHandoff(input) {
|
|
46763
|
+
const { coreMessages, state, full, meta } = input;
|
|
46764
|
+
const lines = [];
|
|
46765
|
+
lines.push("# billion-context session handoff");
|
|
46766
|
+
lines.push("");
|
|
46767
|
+
lines.push(`- title: ${meta.title ?? "(untitled)"}`);
|
|
46768
|
+
if (meta.label) lines.push(`- label: ${meta.label}`);
|
|
46769
|
+
lines.push(`- session id: ${meta.sessionId}`);
|
|
46770
|
+
for (const bullet of meta.extraBullets ?? []) lines.push(bullet);
|
|
46771
|
+
if (meta.contextTokens) lines.push(`- last context tokens: ~${meta.contextTokens}`);
|
|
46772
|
+
lines.push(`- compression blocks: ${state.blocks.length} (active ${state.blocks.filter((b2) => b2.active).length})`);
|
|
46773
|
+
lines.push("");
|
|
46774
|
+
const folded = input.folded === true;
|
|
46775
|
+
const view = full || folded ? coreMessages : prune(coreMessages, state);
|
|
46776
|
+
lines.push(full && !folded ? `## Full conversation (${coreMessages.length} messages)` : folded ? `## Conversation (persisted folded snapshot, ${coreMessages.length} messages)` : `## Conversation (folded view as the model saw it, ${coreMessages.length} client messages)`);
|
|
46777
|
+
lines.push("");
|
|
46778
|
+
if (view.length === 0) {
|
|
46779
|
+
lines.push("No conversation messages to export.");
|
|
46780
|
+
lines.push("");
|
|
46781
|
+
}
|
|
46782
|
+
let lastRole = "";
|
|
46783
|
+
for (const m2 of view) {
|
|
46784
|
+
if (m2.role !== lastRole) {
|
|
46785
|
+
lines.push(`### ${m2.role}`);
|
|
46786
|
+
lines.push("");
|
|
46787
|
+
lastRole = m2.role;
|
|
46788
|
+
}
|
|
46789
|
+
lines.push(renderMessage2(m2));
|
|
46790
|
+
}
|
|
46791
|
+
lines.push("");
|
|
46792
|
+
if (full && folded) {
|
|
46793
|
+
for (const b2 of input.blocksFull ?? []) {
|
|
46794
|
+
lines.push(`## Block ${b2.blockId}${b2.topic ? ` \u2014 ${b2.topic}` : ""}`);
|
|
46795
|
+
lines.push("");
|
|
46796
|
+
lines.push(`### Original messages (${b2.count})`);
|
|
46797
|
+
lines.push("");
|
|
46798
|
+
lines.push(b2.fullText.trim());
|
|
46799
|
+
lines.push("");
|
|
46800
|
+
}
|
|
46801
|
+
}
|
|
46802
|
+
return lines.join("\n");
|
|
46803
|
+
}
|
|
46804
|
+
function matchSession(sessions2, selector, labelOf) {
|
|
46805
|
+
const exact = sessions2.filter((s3) => s3.id === selector);
|
|
46806
|
+
if (exact.length > 0) return exact;
|
|
46807
|
+
const byLabel = sessions2.filter((s3) => labelOf(s3) === selector);
|
|
46808
|
+
if (byLabel.length > 0) return byLabel;
|
|
46809
|
+
return sessions2.filter((s3) => s3.id.startsWith(selector) || (labelOf(s3) ?? "").startsWith(selector));
|
|
46810
|
+
}
|
|
46743
46811
|
function parseCompressArgs(input, opts) {
|
|
46744
46812
|
const callId = opts?.callId;
|
|
46745
46813
|
const diag = { ok: false, kind: "ok", invalidItems: 0 };
|
|
@@ -48293,6 +48361,7 @@ function loadOptions(env = process.env) {
|
|
|
48293
48361
|
passthrough: passthrough.enabled,
|
|
48294
48362
|
passthroughSource: passthrough.source,
|
|
48295
48363
|
autoUpdate: (env.ACP_AUTO_UPDATE ?? (fileConfig.autoUpdate === false ? "0" : "1")) !== "0",
|
|
48364
|
+
updateTag: (env.ACP_UPDATE_TAG ?? fileConfig.updateTag ?? "latest").trim() || "latest",
|
|
48296
48365
|
logFile: env.ACP_LOG_FILE !== void 0 ? env.ACP_LOG_FILE || void 0 : fileConfig.logFile,
|
|
48297
48366
|
mitm: {
|
|
48298
48367
|
enabled: (env.BILI_MITM ?? (fileConfig.mitm?.enabled === false ? "0" : "1")) !== "0",
|
|
@@ -50329,6 +50398,7 @@ function buildAlertMessage(dir, count) {
|
|
|
50329
50398
|
// src/persist.ts
|
|
50330
50399
|
var PERSIST_VERSION = 3;
|
|
50331
50400
|
var MIGRATION_MARKER = ".bili-migration-286.done";
|
|
50401
|
+
var STALE_WARN_THROTTLE_MS = 6e4;
|
|
50332
50402
|
function mergeState(parsed) {
|
|
50333
50403
|
const fresh = createInitialState();
|
|
50334
50404
|
return {
|
|
@@ -50362,11 +50432,14 @@ var SessionStore = class {
|
|
|
50362
50432
|
enabled;
|
|
50363
50433
|
dir;
|
|
50364
50434
|
store;
|
|
50435
|
+
log;
|
|
50436
|
+
staleWarnAt = /* @__PURE__ */ new Map();
|
|
50365
50437
|
constructor(opts) {
|
|
50366
50438
|
const debounceMs = opts?.debounceMs ?? defaultDebounce();
|
|
50367
50439
|
this.enabled = (opts?.enabled ?? true) && debounceMs >= 0;
|
|
50368
50440
|
this.dir = opts?.dir ?? defaultDir();
|
|
50369
50441
|
const baseLog = opts?.log ?? defaultLogger;
|
|
50442
|
+
this.log = baseLog;
|
|
50370
50443
|
const epermAlert = new PersistEpermAlert({
|
|
50371
50444
|
dir: this.dir,
|
|
50372
50445
|
threshold: epermAlertThreshold(),
|
|
@@ -50516,40 +50589,83 @@ var SessionStore = class {
|
|
|
50516
50589
|
});
|
|
50517
50590
|
}
|
|
50518
50591
|
}
|
|
50592
|
+
/** Shared envelope probe for the sync read paths: namespaced path
|
|
50593
|
+
* first, then the _unknown/ location, letting the kernel store layer
|
|
50594
|
+
* also check its discovered map and the flat legacy name. */
|
|
50595
|
+
loadEnvelope(id, meta) {
|
|
50596
|
+
const envelopes = [
|
|
50597
|
+
this.store.loadSync(id, relPathFor(id, meta?.protocol, meta?.upstreamOrigin)),
|
|
50598
|
+
meta?.protocol ? this.store.loadSync(id, relPathFor(id)) : null
|
|
50599
|
+
];
|
|
50600
|
+
for (const envelope of envelopes) {
|
|
50601
|
+
if (envelope) return envelope;
|
|
50602
|
+
}
|
|
50603
|
+
return null;
|
|
50604
|
+
}
|
|
50519
50605
|
/** Synchronous reload of a single session. Used on a memory miss (after
|
|
50520
50606
|
* LRU eviction). Sync fs is acceptable here because a miss is rare and
|
|
50521
50607
|
* reads a single small file (~1ms). Returns null if missing/corrupt or the
|
|
50522
50608
|
* body id does not match what we asked for. */
|
|
50523
50609
|
loadSync(id, meta) {
|
|
50524
50610
|
if (!this.enabled) return null;
|
|
50525
|
-
const
|
|
50526
|
-
|
|
50527
|
-
|
|
50528
|
-
|
|
50529
|
-
|
|
50530
|
-
|
|
50531
|
-
|
|
50532
|
-
|
|
50533
|
-
|
|
50534
|
-
|
|
50535
|
-
|
|
50536
|
-
|
|
50537
|
-
|
|
50611
|
+
const envelope = this.loadEnvelope(id, meta);
|
|
50612
|
+
if (!envelope) return null;
|
|
50613
|
+
const session = buildSession(envelope.payload);
|
|
50614
|
+
if (hasNegativePersistedTokens(envelope.payload)) {
|
|
50615
|
+
this.scheduleSave(session);
|
|
50616
|
+
log("info", `[persist] clamped negative token stats on reload for ${id} (#408)`);
|
|
50617
|
+
}
|
|
50618
|
+
return session;
|
|
50619
|
+
}
|
|
50620
|
+
/** #405 fix #4: dual-instance rollback guard. When two proxy processes
|
|
50621
|
+
* share BILI_SESSIONS_DIR, whoever saves last used to win — an instance
|
|
50622
|
+
* holding a STALE in-memory copy would roll counters back (requests:3 →
|
|
50623
|
+
* 2). Both signals below are monotonic per session id, so either being
|
|
50624
|
+
* strictly smaller proves staleness. Returns the fresher-on-disk payload
|
|
50625
|
+
* when the incoming record is stale, else null. */
|
|
50626
|
+
staleDiskPayload(incoming) {
|
|
50627
|
+
const envelope = this.loadEnvelope(incoming.id, incoming.meta);
|
|
50628
|
+
if (!envelope) return null;
|
|
50629
|
+
const disk = envelope.payload;
|
|
50630
|
+
const diskRequests = disk.stats?.requests ?? disk.requests ?? 0;
|
|
50631
|
+
const incRequests = incoming.stats?.requests ?? incoming.requests ?? 0;
|
|
50632
|
+
if (incRequests < diskRequests) return disk;
|
|
50633
|
+
if (incRequests === diskRequests) {
|
|
50634
|
+
const diskBlocks = disk.state?.nextBlockId ?? 0;
|
|
50635
|
+
const incBlocks = incoming.state?.nextBlockId ?? 0;
|
|
50636
|
+
if (incBlocks < diskBlocks) return disk;
|
|
50538
50637
|
}
|
|
50539
50638
|
return null;
|
|
50540
50639
|
}
|
|
50640
|
+
guardedBuild(session) {
|
|
50641
|
+
return () => {
|
|
50642
|
+
const record = buildRecord(session);
|
|
50643
|
+
const disk = this.staleDiskPayload(record);
|
|
50644
|
+
if (disk === null) return record;
|
|
50645
|
+
const now = Date.now();
|
|
50646
|
+
const last = this.staleWarnAt.get(record.id) ?? 0;
|
|
50647
|
+
if (now - last >= STALE_WARN_THROTTLE_MS) {
|
|
50648
|
+
this.staleWarnAt.set(record.id, now);
|
|
50649
|
+
this.log(
|
|
50650
|
+
"warn",
|
|
50651
|
+
`[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)`
|
|
50652
|
+
);
|
|
50653
|
+
}
|
|
50654
|
+
return disk;
|
|
50655
|
+
};
|
|
50656
|
+
}
|
|
50541
50657
|
/** Schedule a debounced write for a session. Multiple calls within the
|
|
50542
50658
|
* window coalesce; the record is built at WRITE time, so the freshest
|
|
50543
50659
|
* session state is persisted. Safe to call on the hot path. No-op if
|
|
50544
50660
|
* disabled. */
|
|
50545
50661
|
scheduleSave(session) {
|
|
50546
|
-
this.store.scheduleSave(session.id, (
|
|
50662
|
+
this.store.scheduleSave(session.id, this.guardedBuild(session));
|
|
50547
50663
|
}
|
|
50548
50664
|
/** Asynchronously persist a session right now (skips the debounce). Throws
|
|
50549
50665
|
* on write failure so callers can react (e.g. avoid evicting). Serialized
|
|
50550
50666
|
* per-session by the kernel store's write chains. */
|
|
50551
50667
|
async writeNow(session) {
|
|
50552
|
-
await this.store.writeNow(session.id, (
|
|
50668
|
+
await this.store.writeNow(session.id, this.guardedBuild(session));
|
|
50553
50669
|
}
|
|
50554
50670
|
/** Synchronous flush for a single session. Used on memory eviction so a
|
|
50555
50671
|
* dirty evicted session is not lost. Sync because eviction runs in the
|
|
@@ -50557,7 +50673,7 @@ var SessionStore = class {
|
|
|
50557
50673
|
* Returns true on success, false on failure (caller must NOT evict on
|
|
50558
50674
|
* failure for a never-persisted session or it is lost permanently). */
|
|
50559
50675
|
flushSync(session) {
|
|
50560
|
-
return this.store.flushSync(session.id, (
|
|
50676
|
+
return this.store.flushSync(session.id, this.guardedBuild(session));
|
|
50561
50677
|
}
|
|
50562
50678
|
/** Flush all dirty sessions with a pending debounce timer. Called on
|
|
50563
50679
|
* SIGTERM/SIGINT for graceful shutdown. The kernel store flushes its own
|
|
@@ -57416,8 +57532,7 @@ function tunnelAllowlistFromEnv(env = process.env) {
|
|
|
57416
57532
|
}
|
|
57417
57533
|
|
|
57418
57534
|
// src/content-encoding.ts
|
|
57419
|
-
import {
|
|
57420
|
-
import { brotliDecompress, gunzip, inflate, inflateRaw } from "zlib";
|
|
57535
|
+
import { createBrotliDecompress, createGunzip, createInflate, createInflateRaw } from "zlib";
|
|
57421
57536
|
|
|
57422
57537
|
// node_modules/fzstd/esm/index.mjs
|
|
57423
57538
|
var ab = ArrayBuffer;
|
|
@@ -58090,31 +58205,54 @@ var Decompress = /* @__PURE__ */ (function() {
|
|
|
58090
58205
|
})();
|
|
58091
58206
|
|
|
58092
58207
|
// src/content-encoding.ts
|
|
58093
|
-
var
|
|
58094
|
-
|
|
58095
|
-
|
|
58096
|
-
|
|
58097
|
-
|
|
58208
|
+
var DecompressedTooLargeError = class extends Error {
|
|
58209
|
+
constructor(limit) {
|
|
58210
|
+
super(`decompressed request exceeds ${limit} bytes`);
|
|
58211
|
+
this.limit = limit;
|
|
58212
|
+
this.name = "DecompressedTooLargeError";
|
|
58213
|
+
}
|
|
58214
|
+
limit;
|
|
58215
|
+
};
|
|
58216
|
+
function streamDecode(factory, input, max) {
|
|
58217
|
+
return new Promise((resolve, reject) => {
|
|
58218
|
+
const chunks = [];
|
|
58219
|
+
let size = 0;
|
|
58220
|
+
const decoder = factory();
|
|
58221
|
+
decoder.on("data", (chunk) => {
|
|
58222
|
+
size += chunk.length;
|
|
58223
|
+
if (size > max) {
|
|
58224
|
+
decoder.destroy();
|
|
58225
|
+
reject(new DecompressedTooLargeError(max));
|
|
58226
|
+
return;
|
|
58227
|
+
}
|
|
58228
|
+
chunks.push(chunk);
|
|
58229
|
+
});
|
|
58230
|
+
decoder.on("end", () => resolve(Buffer.concat(chunks, size)));
|
|
58231
|
+
decoder.on("error", (err2) => reject(err2));
|
|
58232
|
+
decoder.end(input);
|
|
58233
|
+
});
|
|
58234
|
+
}
|
|
58235
|
+
async function decodeZstd(input, max) {
|
|
58098
58236
|
const chunks = [];
|
|
58099
58237
|
let size = 0;
|
|
58100
58238
|
const decoder = new Decompress((chunk) => {
|
|
58101
58239
|
size += chunk.byteLength;
|
|
58102
|
-
if (size >
|
|
58240
|
+
if (size > max) throw new DecompressedTooLargeError(max);
|
|
58103
58241
|
chunks.push(Buffer.from(chunk));
|
|
58104
58242
|
});
|
|
58105
58243
|
decoder.push(input, true);
|
|
58106
58244
|
return Buffer.concat(chunks, size);
|
|
58107
58245
|
}
|
|
58108
|
-
async function decodeOne(coding, input,
|
|
58109
|
-
|
|
58110
|
-
if (coding === "
|
|
58111
|
-
if (coding === "
|
|
58112
|
-
if (coding === "zstd") return decodeZstd(input, maxOutputBytes);
|
|
58246
|
+
async function decodeOne(coding, input, max) {
|
|
58247
|
+
if (coding === "gzip" || coding === "x-gzip") return streamDecode(createGunzip, input, max);
|
|
58248
|
+
if (coding === "br") return streamDecode(createBrotliDecompress, input, max);
|
|
58249
|
+
if (coding === "zstd") return decodeZstd(input, max);
|
|
58113
58250
|
if (coding === "deflate") {
|
|
58114
58251
|
try {
|
|
58115
|
-
return await
|
|
58116
|
-
} catch {
|
|
58117
|
-
|
|
58252
|
+
return await streamDecode(createInflate, input, max);
|
|
58253
|
+
} catch (err2) {
|
|
58254
|
+
if (err2 instanceof DecompressedTooLargeError) throw err2;
|
|
58255
|
+
return streamDecode(createInflateRaw, input, max);
|
|
58118
58256
|
}
|
|
58119
58257
|
}
|
|
58120
58258
|
throw new Error(`unsupported request content-encoding: ${coding}`);
|
|
@@ -58125,9 +58263,7 @@ async function decodeRequestBody(contentEncoding, input, maxOutputBytes) {
|
|
|
58125
58263
|
let body = input;
|
|
58126
58264
|
for (const coding of codings.reverse()) {
|
|
58127
58265
|
body = await decodeOne(coding, body, maxOutputBytes);
|
|
58128
|
-
if (body.byteLength > maxOutputBytes)
|
|
58129
|
-
throw new Error(`decompressed request exceeds ${maxOutputBytes} bytes`);
|
|
58130
|
-
}
|
|
58266
|
+
if (body.byteLength > maxOutputBytes) throw new DecompressedTooLargeError(maxOutputBytes);
|
|
58131
58267
|
}
|
|
58132
58268
|
return { body, decoded: true };
|
|
58133
58269
|
}
|
|
@@ -58707,18 +58843,24 @@ async function handle(req, res, opts, core, config, log2, instanceId, instanceSt
|
|
|
58707
58843
|
upstreamOrigin = route ? route.upstream : /^https?:\/\//i.test(url) ? new URL(url).origin : opts.upstream;
|
|
58708
58844
|
protocol = route?.explicitProtocol ?? (req.method === "POST" && bodyBuffer.length > 0 ? urlPath.endsWith("/chat/completions") ? "openai" : urlPath.endsWith("/v1/messages") || urlPath.endsWith("/messages") ? "anthropic" : urlPath.endsWith("/responses") || responsesCompact ? "responses" : null : null);
|
|
58709
58845
|
if (protocol !== null && bodyBuffer.length > 0) {
|
|
58710
|
-
|
|
58711
|
-
|
|
58712
|
-
|
|
58846
|
+
try {
|
|
58847
|
+
const decoded = await decodeRequestBody(headerValue2(req, "content-encoding"), bodyBuffer, MAX_REQUEST_BYTES);
|
|
58848
|
+
bodyBuffer = decoded.body;
|
|
58849
|
+
if (decoded.decoded) delete req.headers["content-encoding"];
|
|
58850
|
+
} catch (decErr) {
|
|
58851
|
+
if (decErr instanceof DecompressedTooLargeError) throw decErr;
|
|
58852
|
+
protocol = null;
|
|
58853
|
+
log2("warn", `decode body failed (${String(decErr)}) - forwarding raw body verbatim to ${upstreamOrigin}`);
|
|
58854
|
+
}
|
|
58713
58855
|
}
|
|
58714
58856
|
} catch (err2) {
|
|
58715
|
-
if (err2 instanceof BodyTooLargeError) {
|
|
58857
|
+
if (err2 instanceof BodyTooLargeError || err2 instanceof DecompressedTooLargeError) {
|
|
58716
58858
|
log2("warn", `413: request body exceeds ${err2.limit} bytes`);
|
|
58717
58859
|
res.writeHead(413, { "content-type": "application/json" });
|
|
58718
58860
|
res.end(JSON.stringify({ error: { type: "request_too_large", message: err2.message } }));
|
|
58719
58861
|
return;
|
|
58720
58862
|
}
|
|
58721
|
-
log2("warn", `
|
|
58863
|
+
log2("warn", `failed to prepare inbound request (${String(err2)}) - 400`);
|
|
58722
58864
|
res.writeHead(400, { "content-type": "application/json" });
|
|
58723
58865
|
res.end(JSON.stringify({ error: { type: "invalid_request", message: String(err2) } }));
|
|
58724
58866
|
return;
|
|
@@ -63583,6 +63725,12 @@ var To = (s3) => {
|
|
|
63583
63725
|
import path12 from "path";
|
|
63584
63726
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
63585
63727
|
var REGISTRY_BASE = "https://registry.npmjs.org";
|
|
63728
|
+
function normalizeUpdateTag(tag) {
|
|
63729
|
+
return (tag ?? "latest").trim() || "latest";
|
|
63730
|
+
}
|
|
63731
|
+
function registryUrlFor(packageName, tag) {
|
|
63732
|
+
return `${REGISTRY_BASE}/${packageName}/${encodeURIComponent(tag)}`;
|
|
63733
|
+
}
|
|
63586
63734
|
var CHECK_INTERVAL_MS = 3 * 60 * 1e3;
|
|
63587
63735
|
var THROTTLE_FILE = path12.join(cacheDir(), ".update-check");
|
|
63588
63736
|
var LOCK_FILE = path12.join(cacheDir(), ".update-lock");
|
|
@@ -63593,22 +63741,42 @@ function shouldStealLock(holderAlive, ageMs) {
|
|
|
63593
63741
|
var timer2;
|
|
63594
63742
|
var inFlight = false;
|
|
63595
63743
|
var firstCheckDone = false;
|
|
63596
|
-
function
|
|
63597
|
-
|
|
63598
|
-
|
|
63599
|
-
|
|
63600
|
-
const l = parseVersion(latest);
|
|
63601
|
-
const c = parseVersion(current);
|
|
63744
|
+
function isVersionNewer(latest, current) {
|
|
63745
|
+
const next = parseSemVer(latest);
|
|
63746
|
+
const prev = parseSemVer(current);
|
|
63747
|
+
if (!next || !prev) return false;
|
|
63602
63748
|
for (let i = 0; i < 3; i++) {
|
|
63603
|
-
const
|
|
63604
|
-
const
|
|
63605
|
-
if (
|
|
63606
|
-
|
|
63749
|
+
const a = next.parts[i] ?? 0;
|
|
63750
|
+
const b2 = prev.parts[i] ?? 0;
|
|
63751
|
+
if (a !== b2) return a > b2;
|
|
63752
|
+
}
|
|
63753
|
+
if (!next.pre.length && prev.pre.length) return true;
|
|
63754
|
+
if (next.pre.length && !prev.pre.length) return false;
|
|
63755
|
+
for (let i = 0; i < Math.max(next.pre.length, prev.pre.length); i++) {
|
|
63756
|
+
const a = next.pre[i];
|
|
63757
|
+
const b2 = prev.pre[i];
|
|
63758
|
+
if (a === void 0) return false;
|
|
63759
|
+
if (b2 === void 0) return true;
|
|
63760
|
+
if (a === b2) continue;
|
|
63761
|
+
const aNumber = /^\d+$/.test(a) ? Number(a) : void 0;
|
|
63762
|
+
const bNumber = /^\d+$/.test(b2) ? Number(b2) : void 0;
|
|
63763
|
+
if (aNumber !== void 0 && bNumber !== void 0) return aNumber > bNumber;
|
|
63764
|
+
if (aNumber !== void 0) return false;
|
|
63765
|
+
if (bNumber !== void 0) return true;
|
|
63766
|
+
return a > b2;
|
|
63607
63767
|
}
|
|
63608
63768
|
return false;
|
|
63609
63769
|
}
|
|
63770
|
+
function parseSemVer(version2) {
|
|
63771
|
+
const match = version2.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+.+)?$/);
|
|
63772
|
+
if (!match) return void 0;
|
|
63773
|
+
return {
|
|
63774
|
+
parts: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
63775
|
+
pre: match[4]?.split(".") ?? []
|
|
63776
|
+
};
|
|
63777
|
+
}
|
|
63610
63778
|
function staleInstallStatus(diskVersion, runningVersion) {
|
|
63611
|
-
return diskVersion !== void 0 &&
|
|
63779
|
+
return diskVersion !== void 0 && isVersionNewer(diskVersion, runningVersion) ? "restart" : "current";
|
|
63612
63780
|
}
|
|
63613
63781
|
async function readLastCheck() {
|
|
63614
63782
|
try {
|
|
@@ -63814,7 +63982,8 @@ async function checkForUpdate(opts, force = false) {
|
|
|
63814
63982
|
return;
|
|
63815
63983
|
}
|
|
63816
63984
|
log("info", `[update] checking npm registry for ${opts.packageName}${sinceLastSec < 0 ? " (startup check)" : sinceLastSec === 0 ? "" : ` (last check ${sinceLastSec}s ago)`}\u2026`);
|
|
63817
|
-
const
|
|
63985
|
+
const tag = normalizeUpdateTag(opts.updateTag);
|
|
63986
|
+
const url = registryUrlFor(opts.packageName, tag);
|
|
63818
63987
|
const registryDispatcher = egressDispatcher(opts, url);
|
|
63819
63988
|
const res = await fetchWithEgress(url, {
|
|
63820
63989
|
signal: AbortSignal.timeout(5e3),
|
|
@@ -63833,11 +64002,11 @@ async function checkForUpdate(opts, force = false) {
|
|
|
63833
64002
|
}
|
|
63834
64003
|
const diskVersion = installDir ? await readDiskVersion(installDir) : void 0;
|
|
63835
64004
|
const currentVersion = diskVersion ?? opts.currentVersion;
|
|
63836
|
-
if (!
|
|
64005
|
+
if (!isVersionNewer(latest, currentVersion)) {
|
|
63837
64006
|
if (staleInstallStatus(diskVersion, opts.currentVersion) === "restart") {
|
|
63838
64007
|
log("warn", `[update] running v${opts.currentVersion} but v${diskVersion} is installed \u2014 restart bili to activate (auto-update replaced the on-disk install; this process is still on the old code)`);
|
|
63839
64008
|
} else {
|
|
63840
|
-
log("info", `[update] current=${currentVersion} latest=${latest} (up to date)`);
|
|
64009
|
+
log("info", `[update] current=${currentVersion} latest=${latest} tag=${tag} (up to date)`);
|
|
63841
64010
|
}
|
|
63842
64011
|
return;
|
|
63843
64012
|
}
|
|
@@ -65902,7 +66071,33 @@ function latestBlockTime(s3) {
|
|
|
65902
66071
|
for (const b2 of s3.state.blocks) if (b2.createdAt > latest) latest = b2.createdAt;
|
|
65903
66072
|
return latest;
|
|
65904
66073
|
}
|
|
65905
|
-
function
|
|
66074
|
+
function renderHandoff2(s3, full) {
|
|
66075
|
+
const messages = s3.lastMessages;
|
|
66076
|
+
if (messages && messages.length > 0) {
|
|
66077
|
+
const folded = s3.lastMessagesFolded === true;
|
|
66078
|
+
const blocksFull = full && folded ? s3.state.blocks.filter((b2) => b2.active).map((b2) => {
|
|
66079
|
+
const content = s3.blockContents.get(b2.blockId);
|
|
66080
|
+
return content ? { blockId: b2.blockId, topic: b2.topic, count: content.full.count, fullText: content.full.text } : void 0;
|
|
66081
|
+
}).filter((x) => x !== void 0) : void 0;
|
|
66082
|
+
return renderHandoff({
|
|
66083
|
+
coreMessages: messages,
|
|
66084
|
+
state: s3.state,
|
|
66085
|
+
full,
|
|
66086
|
+
folded,
|
|
66087
|
+
blocksFull,
|
|
66088
|
+
meta: {
|
|
66089
|
+
title: s3.meta.title,
|
|
66090
|
+
label: s3.meta.label,
|
|
66091
|
+
sessionId: s3.id,
|
|
66092
|
+
contextTokens: s3.stats.contextTokens,
|
|
66093
|
+
extraBullets: [
|
|
66094
|
+
...s3.meta.protocol ? [`- protocol: ${s3.meta.protocol}`] : [],
|
|
66095
|
+
...s3.meta.upstreamOrigin ? [`- upstream: ${s3.meta.upstreamOrigin}`] : [],
|
|
66096
|
+
`- requests: ${s3.stats.requests}`
|
|
66097
|
+
]
|
|
66098
|
+
}
|
|
66099
|
+
});
|
|
66100
|
+
}
|
|
65906
66101
|
const lines = [];
|
|
65907
66102
|
lines.push(`# billion-context session handoff`);
|
|
65908
66103
|
lines.push("");
|
|
@@ -65915,38 +66110,6 @@ function renderHandoff(s3, full) {
|
|
|
65915
66110
|
if (s3.stats.contextTokens) lines.push(`- last context tokens: ~${s3.stats.contextTokens}`);
|
|
65916
66111
|
lines.push(`- compression blocks: ${s3.state.blocks.length} (active ${s3.state.blocks.filter((b2) => b2.active).length})`);
|
|
65917
66112
|
lines.push("");
|
|
65918
|
-
const messages = s3.lastMessages;
|
|
65919
|
-
if (messages && messages.length > 0) {
|
|
65920
|
-
const folded = s3.lastMessagesFolded === true;
|
|
65921
|
-
const view = full || folded ? messages : prune(messages, s3.state);
|
|
65922
|
-
lines.push(
|
|
65923
|
-
full && !folded ? `## Full conversation (${messages.length} messages)` : folded ? `## Conversation (persisted folded snapshot, ${messages.length} messages)` : `## Conversation (folded view as the model saw it, ${messages.length} client messages)`
|
|
65924
|
-
);
|
|
65925
|
-
lines.push("");
|
|
65926
|
-
let lastRole = "";
|
|
65927
|
-
for (const m2 of view) {
|
|
65928
|
-
if (m2.role !== lastRole) {
|
|
65929
|
-
lines.push(`### ${m2.role}`);
|
|
65930
|
-
lines.push("");
|
|
65931
|
-
lastRole = m2.role;
|
|
65932
|
-
}
|
|
65933
|
-
lines.push(renderMessage2(m2));
|
|
65934
|
-
}
|
|
65935
|
-
lines.push("");
|
|
65936
|
-
if (full && folded) {
|
|
65937
|
-
for (const b2 of s3.state.blocks.filter((x) => x.active)) {
|
|
65938
|
-
const content = s3.blockContents.get(b2.blockId);
|
|
65939
|
-
if (!content) continue;
|
|
65940
|
-
lines.push(`## Block ${b2.blockId}${b2.topic ? ` \u2014 ${b2.topic}` : ""}`);
|
|
65941
|
-
lines.push("");
|
|
65942
|
-
lines.push(`### Original messages (${content.full.count})`);
|
|
65943
|
-
lines.push("");
|
|
65944
|
-
lines.push(content.full.text.trim());
|
|
65945
|
-
lines.push("");
|
|
65946
|
-
}
|
|
65947
|
-
}
|
|
65948
|
-
return lines.join("\n");
|
|
65949
|
-
}
|
|
65950
66113
|
const active = s3.state.blocks.filter((b2) => b2.active);
|
|
65951
66114
|
if (active.length === 0) {
|
|
65952
66115
|
lines.push("No active compression blocks and no persisted conversation snapshot (v2 session file). Original messages are only persisted when they are compressed into a block, so this session's conversation content is not available for export.");
|
|
@@ -65975,32 +66138,8 @@ function renderHandoff(s3, full) {
|
|
|
65975
66138
|
}
|
|
65976
66139
|
return lines.join("\n");
|
|
65977
66140
|
}
|
|
65978
|
-
function
|
|
65979
|
-
|
|
65980
|
-
switch (m2.contentType) {
|
|
65981
|
-
case "text":
|
|
65982
|
-
parts.push(m2.text ?? "");
|
|
65983
|
-
break;
|
|
65984
|
-
case "tool-call":
|
|
65985
|
-
parts.push(`\`${m2.toolName ?? "?"}(${m2.toolCallId ?? ""})\` args: ${m2.text ?? ""}`);
|
|
65986
|
-
break;
|
|
65987
|
-
case "tool-result":
|
|
65988
|
-
parts.push(`\`${m2.toolName ?? "?"}(${m2.toolCallId ?? ""})\` \u2192 ${m2.text ?? ""}`);
|
|
65989
|
-
break;
|
|
65990
|
-
case "reasoning":
|
|
65991
|
-
parts.push(`_reasoning_: ${m2.text ?? ""}`);
|
|
65992
|
-
break;
|
|
65993
|
-
}
|
|
65994
|
-
const body = parts.join("\n").trim();
|
|
65995
|
-
return body === "" ? "_(empty)_" : body + "\n";
|
|
65996
|
-
}
|
|
65997
|
-
function matchSession(sessions2, selector) {
|
|
65998
|
-
const exact = sessions2.filter((s3) => s3.id === selector);
|
|
65999
|
-
if (exact.length > 0) return exact;
|
|
66000
|
-
const byLabel = sessions2.filter((s3) => s3.meta.label === selector);
|
|
66001
|
-
if (byLabel.length > 0) return byLabel;
|
|
66002
|
-
const byPrefix = sessions2.filter((s3) => s3.id.startsWith(selector) || (s3.meta.label ?? "").startsWith(selector));
|
|
66003
|
-
return byPrefix;
|
|
66141
|
+
function matchSession2(sessions2, selector) {
|
|
66142
|
+
return matchSession(sessions2, selector, (s3) => s3.meta.label);
|
|
66004
66143
|
}
|
|
66005
66144
|
async function exportSession(selector, opts = {}) {
|
|
66006
66145
|
const store = new SessionStore({ dir: opts.dir, enabled: true });
|
|
@@ -66015,7 +66154,7 @@ async function exportSession(selector, opts = {}) {
|
|
|
66015
66154
|
);
|
|
66016
66155
|
return ["Persisted sessions:", "", ...rows.map((r) => ` ${r}`), "", "Usage: bili export <session-id|label> [--output handoff.md] [--full]"].join("\n");
|
|
66017
66156
|
}
|
|
66018
|
-
const matches =
|
|
66157
|
+
const matches = matchSession2(all, selector);
|
|
66019
66158
|
if (matches.length === 0) {
|
|
66020
66159
|
throw new Error(`no session matches "${selector}" (run "bili export" to list sessions)`);
|
|
66021
66160
|
}
|
|
@@ -66023,7 +66162,7 @@ async function exportSession(selector, opts = {}) {
|
|
|
66023
66162
|
const ids = matches.map((s3) => s3.id).join(", ");
|
|
66024
66163
|
throw new Error(`selector "${selector}" matches ${matches.length} sessions (${ids}); use the full session id`);
|
|
66025
66164
|
}
|
|
66026
|
-
const markdown =
|
|
66165
|
+
const markdown = renderHandoff2(matches[0], opts.full ?? false);
|
|
66027
66166
|
if (opts.output) {
|
|
66028
66167
|
mkdirSync6(path16.dirname(path16.resolve(opts.output)), { recursive: true });
|
|
66029
66168
|
writeFileSync5(opts.output, markdown, "utf8");
|
|
@@ -66348,14 +66487,16 @@ async function main() {
|
|
|
66348
66487
|
if (v2 !== void 0) process.env[k2] = v2;
|
|
66349
66488
|
}
|
|
66350
66489
|
let updaterResolveProxy;
|
|
66490
|
+
let updateTag;
|
|
66351
66491
|
try {
|
|
66352
66492
|
const o = loadOptions();
|
|
66353
66493
|
updaterResolveProxy = (url) => resolveProxy(o.routes, o.proxy, url, o.proxyFallback);
|
|
66494
|
+
updateTag = o.updateTag;
|
|
66354
66495
|
} catch (e) {
|
|
66355
66496
|
console.error(`bili update: config load failed (${String(e)}); updater egress goes direct`);
|
|
66356
66497
|
}
|
|
66357
66498
|
await checkForUpdate(
|
|
66358
|
-
{ packageName: PACKAGE_NAME, currentVersion: VERSION3, autoUpdate: true, resolveProxy: updaterResolveProxy },
|
|
66499
|
+
{ packageName: PACKAGE_NAME, currentVersion: VERSION3, autoUpdate: true, resolveProxy: updaterResolveProxy, updateTag },
|
|
66359
66500
|
true
|
|
66360
66501
|
);
|
|
66361
66502
|
return;
|
|
@@ -66383,7 +66524,8 @@ async function main() {
|
|
|
66383
66524
|
packageName: PACKAGE_NAME,
|
|
66384
66525
|
currentVersion: VERSION3,
|
|
66385
66526
|
autoUpdate: true,
|
|
66386
|
-
resolveProxy: (url) => resolveProxy(opts.routes, opts.proxy, url, opts.proxyFallback)
|
|
66527
|
+
resolveProxy: (url) => resolveProxy(opts.routes, opts.proxy, url, opts.proxyFallback),
|
|
66528
|
+
updateTag: opts.updateTag
|
|
66387
66529
|
});
|
|
66388
66530
|
}
|
|
66389
66531
|
}
|