billion-context 0.1.72 → 0.1.73-pr.474.289
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 +163 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -53254,6 +53254,86 @@ async function compressLoopResponsesJson(initialResponse, ctx, requestBody, requ
|
|
|
53254
53254
|
return current;
|
|
53255
53255
|
}
|
|
53256
53256
|
|
|
53257
|
+
// src/fake-completion.ts
|
|
53258
|
+
var FAKE_COMPLETION_HINT = "[billion-context] Your last reply described a tool call as plain text instead of invoking it, so no tool actually ran. To act, invoke the tool through the proper tool-calling mechanism (emit a tool_use / tool_calls / function_call block). Do not write tool-call markup as text in your reply.";
|
|
53259
|
+
function maxFakeCompletionRetries() {
|
|
53260
|
+
const n = Number.parseInt(process.env.BILI_FAKE_COMPLETION_RETRIES ?? "0", 10);
|
|
53261
|
+
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
53262
|
+
}
|
|
53263
|
+
function fakeBufCap() {
|
|
53264
|
+
const n = Number.parseInt(process.env.BILI_FAKE_BUF_CAP ?? String(16 * 1024 * 1024), 10);
|
|
53265
|
+
return Number.isFinite(n) && n > 0 ? n : 16 * 1024 * 1024;
|
|
53266
|
+
}
|
|
53267
|
+
var ANTHROPIC_TOOL_BLOCK = /"type"\s*:\s*"tool_use"/;
|
|
53268
|
+
var OPENAI_TOOL_BLOCK = /"tool_calls"\s*:\s*\[\s*\{/;
|
|
53269
|
+
var RESPONSES_TOOL_BLOCK = /"type"\s*:\s*"function_call"/;
|
|
53270
|
+
function hasToolBlock(protocol, rawText) {
|
|
53271
|
+
switch (protocol) {
|
|
53272
|
+
case "anthropic":
|
|
53273
|
+
return ANTHROPIC_TOOL_BLOCK.test(rawText);
|
|
53274
|
+
case "openai":
|
|
53275
|
+
return OPENAI_TOOL_BLOCK.test(rawText);
|
|
53276
|
+
case "responses":
|
|
53277
|
+
return RESPONSES_TOOL_BLOCK.test(rawText);
|
|
53278
|
+
}
|
|
53279
|
+
}
|
|
53280
|
+
var TOOL_OPEN = /\x3c(?!\s*\/)(?:antml:)?(invoke|tool_calls|tool_call|parameter|parameters)\b|\\u003c(?!\s*\/)(?:antml:)?(invoke|tool_calls|tool_call|parameter|parameters)\b/i;
|
|
53281
|
+
var TOOL_CLOSE_GLOBAL = /\x3c\/(?:antml:)?(invoke|tool_calls|tool_call|parameter|parameters)\b|\\u003c\/(?:antml:)?(invoke|tool_calls|tool_call|parameter|parameters)\b/gi;
|
|
53282
|
+
function hasToolCallStructure(text) {
|
|
53283
|
+
if (!containsToolCallXmlFragment(text)) return false;
|
|
53284
|
+
if (TOOL_OPEN.test(text)) return true;
|
|
53285
|
+
const closes = /* @__PURE__ */ new Set();
|
|
53286
|
+
for (const m2 of text.matchAll(TOOL_CLOSE_GLOBAL)) {
|
|
53287
|
+
const name = m2[1] ?? m2[2];
|
|
53288
|
+
if (name) closes.add(name.toLowerCase());
|
|
53289
|
+
}
|
|
53290
|
+
return closes.size >= 2;
|
|
53291
|
+
}
|
|
53292
|
+
function isFakeCompletion(protocol, rawText) {
|
|
53293
|
+
return hasToolCallStructure(rawText) && !hasToolBlock(protocol, rawText);
|
|
53294
|
+
}
|
|
53295
|
+
function injectFakeCompletionHint(protocol, body) {
|
|
53296
|
+
const raw = typeof body === "string" ? body : body.toString("utf8");
|
|
53297
|
+
let obj;
|
|
53298
|
+
try {
|
|
53299
|
+
obj = JSON.parse(raw);
|
|
53300
|
+
} catch {
|
|
53301
|
+
return null;
|
|
53302
|
+
}
|
|
53303
|
+
if (protocol === "responses") {
|
|
53304
|
+
const input = obj.input;
|
|
53305
|
+
if (!Array.isArray(input)) return null;
|
|
53306
|
+
const arr2 = input;
|
|
53307
|
+
const last2 = arr2[arr2.length - 1];
|
|
53308
|
+
if (last2 && typeof last2 === "object" && last2.role === "user") {
|
|
53309
|
+
const c = last2.content;
|
|
53310
|
+
if (typeof c === "string") last2.content = `${c}
|
|
53311
|
+
|
|
53312
|
+
${FAKE_COMPLETION_HINT}`;
|
|
53313
|
+
else if (Array.isArray(c)) last2.content = [...c, { type: "input_text", text: FAKE_COMPLETION_HINT }];
|
|
53314
|
+
else last2.content = FAKE_COMPLETION_HINT;
|
|
53315
|
+
} else {
|
|
53316
|
+
arr2.push({ role: "user", content: [{ type: "input_text", text: FAKE_COMPLETION_HINT }] });
|
|
53317
|
+
}
|
|
53318
|
+
return JSON.stringify(obj);
|
|
53319
|
+
}
|
|
53320
|
+
const messages = obj.messages;
|
|
53321
|
+
if (!Array.isArray(messages)) return null;
|
|
53322
|
+
const arr = messages;
|
|
53323
|
+
const last = arr[arr.length - 1];
|
|
53324
|
+
if (last && typeof last === "object" && last.role === "user") {
|
|
53325
|
+
const c = last.content;
|
|
53326
|
+
if (typeof c === "string") last.content = `${c}
|
|
53327
|
+
|
|
53328
|
+
${FAKE_COMPLETION_HINT}`;
|
|
53329
|
+
else if (Array.isArray(c)) last.content = [...c, { type: "text", text: FAKE_COMPLETION_HINT }];
|
|
53330
|
+
else last.content = FAKE_COMPLETION_HINT;
|
|
53331
|
+
} else {
|
|
53332
|
+
arr.push({ role: "user", content: FAKE_COMPLETION_HINT });
|
|
53333
|
+
}
|
|
53334
|
+
return JSON.stringify(obj);
|
|
53335
|
+
}
|
|
53336
|
+
|
|
53257
53337
|
// src/stream-openai.ts
|
|
53258
53338
|
function rewriteOpenaiJsonResponse(body, ctx) {
|
|
53259
53339
|
if (!body || typeof body !== "object") return body;
|
|
@@ -54221,7 +54301,7 @@ function mergeUsageSample(acc, sample) {
|
|
|
54221
54301
|
if (sample.cachedTokens !== void 0) acc.cachedTokens = sample.cachedTokens;
|
|
54222
54302
|
if (sample.outputTokens !== void 0) acc.outputTokens = sample.outputTokens;
|
|
54223
54303
|
}
|
|
54224
|
-
async function pipePluginChatWithStrip(stream2, res,
|
|
54304
|
+
async function pipePluginChatWithStrip(stream2, res, protocol, session, log2) {
|
|
54225
54305
|
const reader = stream2.getReader();
|
|
54226
54306
|
const decoder = new TextDecoder("utf-8");
|
|
54227
54307
|
let buf = "";
|
|
@@ -54375,7 +54455,7 @@ data: ${JSON.stringify({ type: "content_block_delta", index, delta: { type: delt
|
|
|
54375
54455
|
}
|
|
54376
54456
|
const rest = flushTails();
|
|
54377
54457
|
if (rest.length > 0 && !res.destroyed && !res.writableEnded) await write(rest);
|
|
54378
|
-
if (acc.inputTokens !== void 0 || acc.outputTokens !== void 0 || acc.cachedTokens !== void 0) {
|
|
54458
|
+
if (session && (acc.inputTokens !== void 0 || acc.outputTokens !== void 0 || acc.cachedTokens !== void 0)) {
|
|
54379
54459
|
applyUsageSample(session, acc, protocol);
|
|
54380
54460
|
markDirty(session);
|
|
54381
54461
|
}
|
|
@@ -54484,7 +54564,7 @@ async function pipePluginResponsesWithStrip(stream2, res, session, log2) {
|
|
|
54484
54564
|
const rest = flushTail("");
|
|
54485
54565
|
if (rest.length > 0) await write(rest);
|
|
54486
54566
|
}
|
|
54487
|
-
if (acc.inputTokens !== void 0 || acc.outputTokens !== void 0 || acc.cachedTokens !== void 0) {
|
|
54567
|
+
if (session && (acc.inputTokens !== void 0 || acc.outputTokens !== void 0 || acc.cachedTokens !== void 0)) {
|
|
54488
54568
|
applyUsageSample(session, acc, "responses");
|
|
54489
54569
|
markDirty(session);
|
|
54490
54570
|
}
|
|
@@ -57511,7 +57591,7 @@ ${hdrText}
|
|
|
57511
57591
|
if (prepared.protocol === "responses") {
|
|
57512
57592
|
await pipePluginResponsesWithStrip(upstream.body, res, prepared.session, (msg) => log2("info", `[${prepared.session.id}] ${msg}`));
|
|
57513
57593
|
} else {
|
|
57514
|
-
await pipePluginChatWithStrip(upstream.body, res, prepared.
|
|
57594
|
+
await pipePluginChatWithStrip(upstream.body, res, prepared.protocol, prepared.session, (msg) => log2("info", `[${prepared.session.id}] ${msg}`));
|
|
57515
57595
|
}
|
|
57516
57596
|
} else {
|
|
57517
57597
|
await pipePluginJson(upstream.body, res, prepared.session, prepared.protocol);
|
|
@@ -57519,10 +57599,24 @@ ${hdrText}
|
|
|
57519
57599
|
clearUpstreamTimer();
|
|
57520
57600
|
return;
|
|
57521
57601
|
}
|
|
57602
|
+
let responseBody = upstream.body;
|
|
57603
|
+
if (prepared !== null && prepared.stream && maxFakeCompletionRetries() > 0) {
|
|
57604
|
+
const resolvedBuf = await resolveFakeCompletion(upstream.body, {
|
|
57605
|
+
protocol: prepared.protocol,
|
|
57606
|
+
body,
|
|
57607
|
+
upstreamUrl,
|
|
57608
|
+
reqHeaders: buildForwardHeaders(headers),
|
|
57609
|
+
proxyUrl,
|
|
57610
|
+
signal: clientAbort.signal,
|
|
57611
|
+
session: prepared.session,
|
|
57612
|
+
log: log2
|
|
57613
|
+
});
|
|
57614
|
+
responseBody = bufferToStream(resolvedBuf);
|
|
57615
|
+
}
|
|
57522
57616
|
const useRewriter = prepared !== null && prepared.compressInjected && prepared.processedMessages.length > 0;
|
|
57523
57617
|
if (!useRewriter || prepared === null) {
|
|
57524
57618
|
if (prepared && prepared.resetAfterSuccess) {
|
|
57525
|
-
const [toClient, toObserve] =
|
|
57619
|
+
const [toClient, toObserve] = responseBody.tee();
|
|
57526
57620
|
const observed = observeResponsesTerminalState(toObserve, prepared.stream);
|
|
57527
57621
|
await pipeThrough(toClient, res);
|
|
57528
57622
|
clearUpstreamTimer();
|
|
@@ -57533,8 +57627,17 @@ ${hdrText}
|
|
|
57533
57627
|
} else {
|
|
57534
57628
|
log2("warn", `[${prepared.session.id}] native compact response terminal=${terminal}; rebase NOT scheduled`);
|
|
57535
57629
|
}
|
|
57630
|
+
} else if (prepared && prepared.stream && (upstream.headers.get("content-type") ?? "").includes("text/event-stream")) {
|
|
57631
|
+
const p2 = prepared;
|
|
57632
|
+
const tagLog = (msg) => log2("info", `[${p2.session.id}] ${msg}`);
|
|
57633
|
+
if (p2.protocol === "responses") {
|
|
57634
|
+
await pipePluginResponsesWithStrip(responseBody, res, void 0, tagLog);
|
|
57635
|
+
} else {
|
|
57636
|
+
await pipePluginChatWithStrip(responseBody, res, p2.protocol, void 0, tagLog);
|
|
57637
|
+
}
|
|
57638
|
+
clearUpstreamTimer();
|
|
57536
57639
|
} else {
|
|
57537
|
-
await pipeThrough(
|
|
57640
|
+
await pipeThrough(responseBody, res);
|
|
57538
57641
|
clearUpstreamTimer();
|
|
57539
57642
|
}
|
|
57540
57643
|
return;
|
|
@@ -57548,10 +57651,10 @@ ${hdrText}
|
|
|
57548
57651
|
debug: opts.debug
|
|
57549
57652
|
};
|
|
57550
57653
|
if (prepared.stream) {
|
|
57551
|
-
let streamToRead =
|
|
57654
|
+
let streamToRead = responseBody;
|
|
57552
57655
|
let dumpRaw;
|
|
57553
57656
|
if (opts.dumpSse) {
|
|
57554
|
-
const [a, b2] =
|
|
57657
|
+
const [a, b2] = responseBody.tee();
|
|
57555
57658
|
streamToRead = a;
|
|
57556
57659
|
dumpRaw = dumpStreamToFile(b2, opts.dumpSse, `${Date.now()}-${safeSessionId(prepared.session.id)}-raw.sse`);
|
|
57557
57660
|
}
|
|
@@ -57677,6 +57780,58 @@ async function readStreamToBuffer(stream2, maxBytes = 1 << 20) {
|
|
|
57677
57780
|
}
|
|
57678
57781
|
return Buffer.concat(chunks);
|
|
57679
57782
|
}
|
|
57783
|
+
function bufferToStream(buf) {
|
|
57784
|
+
return new ReadableStream({
|
|
57785
|
+
start(controller) {
|
|
57786
|
+
controller.enqueue(new Uint8Array(buf));
|
|
57787
|
+
controller.close();
|
|
57788
|
+
}
|
|
57789
|
+
});
|
|
57790
|
+
}
|
|
57791
|
+
async function resolveFakeCompletion(stream2, opts) {
|
|
57792
|
+
let buffer = await readStreamToBuffer(stream2, fakeBufCap());
|
|
57793
|
+
const max = maxFakeCompletionRetries();
|
|
57794
|
+
const sid = opts.session.id;
|
|
57795
|
+
const priorStreak = opts.session.metadata.fakeCompletionStreak ?? 0;
|
|
57796
|
+
if (max > 0 && priorStreak < max && isFakeCompletion(opts.protocol, buffer.toString("utf8"))) {
|
|
57797
|
+
for (let attempt = 1; attempt <= max && !opts.signal.aborted; attempt++) {
|
|
57798
|
+
const hinted = injectFakeCompletionHint(opts.protocol, opts.body);
|
|
57799
|
+
if (hinted === null) break;
|
|
57800
|
+
opts.log("warn", `[${sid}] fake completion (tool-call XML, no tool block); retry ${attempt}/${max} with corrective hint`);
|
|
57801
|
+
let r;
|
|
57802
|
+
try {
|
|
57803
|
+
r = await fetchWithTimeout(
|
|
57804
|
+
opts.upstreamUrl,
|
|
57805
|
+
{
|
|
57806
|
+
method: "POST",
|
|
57807
|
+
headers: opts.reqHeaders,
|
|
57808
|
+
body: hinted,
|
|
57809
|
+
...opts.proxyUrl ? { dispatcher: proxyDispatcher(opts.proxyUrl) } : {}
|
|
57810
|
+
},
|
|
57811
|
+
void 0,
|
|
57812
|
+
opts.signal
|
|
57813
|
+
);
|
|
57814
|
+
} catch (e) {
|
|
57815
|
+
opts.log("warn", `[${sid}] fake-completion retry failed: ${String(e)}; presenting original`);
|
|
57816
|
+
break;
|
|
57817
|
+
}
|
|
57818
|
+
try {
|
|
57819
|
+
if (!r.response.ok || !r.response.body) {
|
|
57820
|
+
opts.log("warn", `[${sid}] fake-completion retry rejected (HTTP ${r.response.status}); presenting original`);
|
|
57821
|
+
break;
|
|
57822
|
+
}
|
|
57823
|
+
buffer = await readStreamToBuffer(r.response.body, fakeBufCap());
|
|
57824
|
+
} finally {
|
|
57825
|
+
r.clearTimer();
|
|
57826
|
+
}
|
|
57827
|
+
if (!isFakeCompletion(opts.protocol, buffer.toString("utf8"))) break;
|
|
57828
|
+
}
|
|
57829
|
+
}
|
|
57830
|
+
const stillFake = isFakeCompletion(opts.protocol, buffer.toString("utf8"));
|
|
57831
|
+
opts.session.metadata.fakeCompletionStreak = stillFake ? priorStreak + 1 : 0;
|
|
57832
|
+
markDirty(opts.session);
|
|
57833
|
+
return buffer;
|
|
57834
|
+
}
|
|
57680
57835
|
async function pipeThrough(stream2, res) {
|
|
57681
57836
|
const reader = stream2.getReader();
|
|
57682
57837
|
try {
|