billion-context 0.1.41 → 0.1.42
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 +411 -124
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -13679,8 +13679,8 @@ var require_snapshot_utils = __commonJS({
|
|
|
13679
13679
|
match: new Set(matchHeaders.map((header) => caseSensitive ? header : header.toLowerCase()))
|
|
13680
13680
|
};
|
|
13681
13681
|
}
|
|
13682
|
-
var
|
|
13683
|
-
var hashId2 =
|
|
13682
|
+
var crypto2 = runtimeFeatures.has("crypto") ? __require("crypto") : null;
|
|
13683
|
+
var hashId2 = crypto2?.hash ? (value) => crypto2.hash("sha256", value, "base64url") : (value) => Buffer.from(value).toString("base64url");
|
|
13684
13684
|
function isUndiciHeaders(headers) {
|
|
13685
13685
|
return Array.isArray(headers) && (headers.length & 1) === 0;
|
|
13686
13686
|
}
|
|
@@ -20209,10 +20209,10 @@ var require_subresource_integrity = __commonJS({
|
|
|
20209
20209
|
var assert = __require("assert");
|
|
20210
20210
|
var { runtimeFeatures } = require_runtime_features();
|
|
20211
20211
|
var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]);
|
|
20212
|
-
var
|
|
20212
|
+
var crypto2;
|
|
20213
20213
|
if (runtimeFeatures.has("crypto")) {
|
|
20214
|
-
|
|
20215
|
-
const cryptoHashes =
|
|
20214
|
+
crypto2 = __require("crypto");
|
|
20215
|
+
const cryptoHashes = crypto2.getHashes();
|
|
20216
20216
|
if (cryptoHashes.length === 0) {
|
|
20217
20217
|
validSRIHashAlgorithmTokenSet.clear();
|
|
20218
20218
|
}
|
|
@@ -20302,7 +20302,7 @@ var require_subresource_integrity = __commonJS({
|
|
|
20302
20302
|
return result;
|
|
20303
20303
|
}
|
|
20304
20304
|
var applyAlgorithmToBytes = (algorithm, bytes) => {
|
|
20305
|
-
return
|
|
20305
|
+
return crypto2.hash(algorithm, bytes, "base64");
|
|
20306
20306
|
};
|
|
20307
20307
|
function caseSensitiveMatch(actualValue, expectedValue) {
|
|
20308
20308
|
let actualValueLength = actualValue.length;
|
|
@@ -23285,7 +23285,7 @@ var require_connection = __commonJS({
|
|
|
23285
23285
|
var { WebsocketFrameSend } = require_frame();
|
|
23286
23286
|
var assert = __require("assert");
|
|
23287
23287
|
var { runtimeFeatures } = require_runtime_features();
|
|
23288
|
-
var
|
|
23288
|
+
var crypto2 = runtimeFeatures.has("crypto") ? __require("crypto") : null;
|
|
23289
23289
|
var warningEmitted = false;
|
|
23290
23290
|
function establishWebSocketConnection(url, protocols, client, handler, options) {
|
|
23291
23291
|
const requestURL = url;
|
|
@@ -23305,7 +23305,7 @@ var require_connection = __commonJS({
|
|
|
23305
23305
|
const headersList = getHeadersList(new Headers(options.headers));
|
|
23306
23306
|
request.headersList = headersList;
|
|
23307
23307
|
}
|
|
23308
|
-
const keyValue =
|
|
23308
|
+
const keyValue = crypto2.randomBytes(16).toString("base64");
|
|
23309
23309
|
request.headersList.append("sec-websocket-key", keyValue, true);
|
|
23310
23310
|
request.headersList.append("sec-websocket-version", "13", true);
|
|
23311
23311
|
for (const protocol of protocols) {
|
|
@@ -23345,7 +23345,7 @@ var require_connection = __commonJS({
|
|
|
23345
23345
|
return;
|
|
23346
23346
|
}
|
|
23347
23347
|
const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
|
|
23348
|
-
const digest =
|
|
23348
|
+
const digest = crypto2.hash("sha1", keyValue + uid, "base64");
|
|
23349
23349
|
if (secWSAccept !== digest) {
|
|
23350
23350
|
failWebsocketConnection(handler, 1002, "Incorrect hash received in Sec-WebSocket-Accept header.");
|
|
23351
23351
|
return;
|
|
@@ -29907,36 +29907,36 @@ var require_pbkdf2 = __commonJS({
|
|
|
29907
29907
|
require_md();
|
|
29908
29908
|
require_util7();
|
|
29909
29909
|
var pkcs5 = forge2.pkcs5 = forge2.pkcs5 || {};
|
|
29910
|
-
var
|
|
29910
|
+
var crypto2;
|
|
29911
29911
|
if (forge2.util.isNodejs && !forge2.options.usePureJavaScript) {
|
|
29912
|
-
|
|
29912
|
+
crypto2 = __require("crypto");
|
|
29913
29913
|
}
|
|
29914
29914
|
module.exports = forge2.pbkdf2 = pkcs5.pbkdf2 = function(p2, s3, c, dkLen, md, callback) {
|
|
29915
29915
|
if (typeof md === "function") {
|
|
29916
29916
|
callback = md;
|
|
29917
29917
|
md = null;
|
|
29918
29918
|
}
|
|
29919
|
-
if (forge2.util.isNodejs && !forge2.options.usePureJavaScript &&
|
|
29919
|
+
if (forge2.util.isNodejs && !forge2.options.usePureJavaScript && crypto2.pbkdf2 && (md === null || typeof md !== "object") && (crypto2.pbkdf2Sync.length > 4 || (!md || md === "sha1"))) {
|
|
29920
29920
|
if (typeof md !== "string") {
|
|
29921
29921
|
md = "sha1";
|
|
29922
29922
|
}
|
|
29923
29923
|
p2 = Buffer.from(p2, "binary");
|
|
29924
29924
|
s3 = Buffer.from(s3, "binary");
|
|
29925
29925
|
if (!callback) {
|
|
29926
|
-
if (
|
|
29927
|
-
return
|
|
29926
|
+
if (crypto2.pbkdf2Sync.length === 4) {
|
|
29927
|
+
return crypto2.pbkdf2Sync(p2, s3, c, dkLen).toString("binary");
|
|
29928
29928
|
}
|
|
29929
|
-
return
|
|
29929
|
+
return crypto2.pbkdf2Sync(p2, s3, c, dkLen, md).toString("binary");
|
|
29930
29930
|
}
|
|
29931
|
-
if (
|
|
29932
|
-
return
|
|
29931
|
+
if (crypto2.pbkdf2Sync.length === 4) {
|
|
29932
|
+
return crypto2.pbkdf2(p2, s3, c, dkLen, function(err3, key) {
|
|
29933
29933
|
if (err3) {
|
|
29934
29934
|
return callback(err3);
|
|
29935
29935
|
}
|
|
29936
29936
|
callback(null, key.toString("binary"));
|
|
29937
29937
|
});
|
|
29938
29938
|
}
|
|
29939
|
-
return
|
|
29939
|
+
return crypto2.pbkdf2(p2, s3, c, dkLen, md, function(err3, key) {
|
|
29940
29940
|
if (err3) {
|
|
29941
29941
|
return callback(err3);
|
|
29942
29942
|
}
|
|
@@ -43760,7 +43760,8 @@ function defaultConfig(modelContextLimit, overrides = {}) {
|
|
|
43760
43760
|
growthCap: 5e4,
|
|
43761
43761
|
minGrowthFloor: 2e4,
|
|
43762
43762
|
minGrowthRatio: 0.45,
|
|
43763
|
-
emergencyThresholdPct: 0.95
|
|
43763
|
+
emergencyThresholdPct: 0.95,
|
|
43764
|
+
tier2GrowthMultiplier: 1.5
|
|
43764
43765
|
},
|
|
43765
43766
|
promotionThreshold: 5,
|
|
43766
43767
|
truncate: { threshold: 0.95 },
|
|
@@ -44485,6 +44486,44 @@ function buildCompressibleRanges(messages, state, config, protectedZoneRefs, cou
|
|
|
44485
44486
|
protected: protectedRanges
|
|
44486
44487
|
};
|
|
44487
44488
|
}
|
|
44489
|
+
function mergeBatch(batch) {
|
|
44490
|
+
const first = batch[0];
|
|
44491
|
+
const last = batch[batch.length - 1];
|
|
44492
|
+
const count = batch.reduce((s3, r) => s3 + r.count, 0);
|
|
44493
|
+
const tokens = batch.reduce((s3, r) => s3 + r.tokens, 0);
|
|
44494
|
+
const toolPct = Math.round(
|
|
44495
|
+
batch.reduce((s3, r) => s3 + r.toolPct * r.count, 0) / count
|
|
44496
|
+
);
|
|
44497
|
+
const merged = {
|
|
44498
|
+
startRef: first.startRef,
|
|
44499
|
+
endRef: last.endRef,
|
|
44500
|
+
count,
|
|
44501
|
+
tokens,
|
|
44502
|
+
toolPct,
|
|
44503
|
+
textPct: 100 - toolPct
|
|
44504
|
+
};
|
|
44505
|
+
if (batch.some((r) => r.dangerous === true)) {
|
|
44506
|
+
merged.dangerous = true;
|
|
44507
|
+
}
|
|
44508
|
+
return merged;
|
|
44509
|
+
}
|
|
44510
|
+
function mergeRangesToThreshold(ranges, minChars) {
|
|
44511
|
+
if (minChars <= 0 || ranges.length === 0) return ranges;
|
|
44512
|
+
const result = [];
|
|
44513
|
+
let batch = [];
|
|
44514
|
+
for (const r of ranges) {
|
|
44515
|
+
batch.push(r);
|
|
44516
|
+
const batchTokens = batch.reduce((s3, x) => s3 + x.tokens, 0);
|
|
44517
|
+
if (batchTokens * 4 >= minChars) {
|
|
44518
|
+
result.push(mergeBatch(batch));
|
|
44519
|
+
batch = [];
|
|
44520
|
+
}
|
|
44521
|
+
}
|
|
44522
|
+
if (batch.length > 0) {
|
|
44523
|
+
result.push(mergeBatch(batch));
|
|
44524
|
+
}
|
|
44525
|
+
return result;
|
|
44526
|
+
}
|
|
44488
44527
|
function runPipeline(nodes, initial, ctx) {
|
|
44489
44528
|
let io2 = initial;
|
|
44490
44529
|
for (const node of nodes) {
|
|
@@ -44764,7 +44803,10 @@ var recommendNode = {
|
|
|
44764
44803
|
const nothingToCompress = contextRanges.compressible.length === 0;
|
|
44765
44804
|
const recommendation = {
|
|
44766
44805
|
contextRanges,
|
|
44767
|
-
recommendedRanges:
|
|
44806
|
+
recommendedRanges: mergeRangesToThreshold(
|
|
44807
|
+
contextRanges.compressible,
|
|
44808
|
+
ctx.config.compress.minCompressRange
|
|
44809
|
+
),
|
|
44768
44810
|
nothingToCompress
|
|
44769
44811
|
};
|
|
44770
44812
|
return { ...io2, effects: { ...io2.effects, recommendation } };
|
|
@@ -44790,6 +44832,7 @@ var nudgeNode = {
|
|
|
44790
44832
|
if (baseline > 0 && ctx.tokenCount < baseline - nudgeGrowthTokens) {
|
|
44791
44833
|
stamped.lastPerMessageNudgeTokens = ctx.tokenCount;
|
|
44792
44834
|
stamped.lastNudgeShownTokens = 0;
|
|
44835
|
+
stamped.lastShownByTier = {};
|
|
44793
44836
|
}
|
|
44794
44837
|
if (stamped.lastPerMessageNudgeTokens === 0) {
|
|
44795
44838
|
stamped.lastPerMessageNudgeTokens = ctx.tokenCount;
|
|
@@ -45058,10 +45101,11 @@ function resolveAdaptiveGrowth(modelContextLimit, nudge) {
|
|
|
45058
45101
|
)
|
|
45059
45102
|
);
|
|
45060
45103
|
}
|
|
45061
|
-
function pendingByTier(state, recommendation, countTokens) {
|
|
45104
|
+
function pendingByTier(state, recommendation, countTokens, minCompressRange) {
|
|
45062
45105
|
const out = {};
|
|
45063
|
-
const
|
|
45064
|
-
|
|
45106
|
+
const merged = recommendation?.recommendedRanges ?? [];
|
|
45107
|
+
const effective = minCompressRange > 0 ? merged.filter((r) => r.tokens * 4 >= minCompressRange) : merged;
|
|
45108
|
+
out[1] = { pending: effective.reduce((s3, r) => s3 + r.tokens, 0), targetBlocks: [] };
|
|
45065
45109
|
const active = activeBlocks(state);
|
|
45066
45110
|
const t1 = active.filter((b2) => b2.tier === 1);
|
|
45067
45111
|
const t2 = active.filter((b2) => b2.tier === 2);
|
|
@@ -45076,6 +45120,7 @@ function decideNudge(input) {
|
|
|
45076
45120
|
const nudgeGrowthTokens = resolveAdaptiveGrowth(limit, config.nudge);
|
|
45077
45121
|
const overLimit = usage >= config.nudge.maxContextLimitPct;
|
|
45078
45122
|
const emergencyOverride = usage >= config.nudge.emergencyThresholdPct;
|
|
45123
|
+
const pressure = overLimit || emergencyOverride;
|
|
45079
45124
|
const baseline = state.nudge.lastPerMessageNudgeTokens;
|
|
45080
45125
|
const hadPendingNudge = state.nudge.lastNudgeShownTokens > 0;
|
|
45081
45126
|
const hasPendingNudge = hadPendingNudge;
|
|
@@ -45087,44 +45132,67 @@ function decideNudge(input) {
|
|
|
45087
45132
|
);
|
|
45088
45133
|
const growthSinceReference = tokenCount - growthReference;
|
|
45089
45134
|
const rec = recommendation;
|
|
45090
|
-
const tiers = pendingByTier(
|
|
45135
|
+
const tiers = pendingByTier(
|
|
45136
|
+
state,
|
|
45137
|
+
rec,
|
|
45138
|
+
countTokens,
|
|
45139
|
+
config.compress.minCompressRange
|
|
45140
|
+
);
|
|
45141
|
+
const tier2Threshold = Math.round(
|
|
45142
|
+
nudgeGrowthTokens * (config.nudge.tier2GrowthMultiplier ?? 1.5)
|
|
45143
|
+
);
|
|
45091
45144
|
let injectedTier = null;
|
|
45092
45145
|
let injectedReason = "";
|
|
45093
45146
|
const growthReady = growthSinceReference >= growthFloor;
|
|
45094
|
-
|
|
45095
|
-
|
|
45096
|
-
|
|
45097
|
-
|
|
45098
|
-
|
|
45099
|
-
|
|
45147
|
+
const t1Eff = tiers[1]?.pending ?? 0;
|
|
45148
|
+
const t2Pen = tiers[2]?.pending ?? 0;
|
|
45149
|
+
const t3Pen = tiers[3]?.pending ?? 0;
|
|
45150
|
+
if (pressure) {
|
|
45151
|
+
const candidates = [1];
|
|
45152
|
+
if (config.tiers.enabled) {
|
|
45153
|
+
candidates.push(2, 3);
|
|
45154
|
+
}
|
|
45155
|
+
let best = null;
|
|
45156
|
+
let bestPending = 0;
|
|
45157
|
+
for (const t of candidates) {
|
|
45158
|
+
const p2 = tiers[t]?.pending ?? 0;
|
|
45159
|
+
if (p2 > bestPending) {
|
|
45160
|
+
bestPending = p2;
|
|
45161
|
+
best = t;
|
|
45162
|
+
}
|
|
45163
|
+
}
|
|
45164
|
+
if (best !== null && bestPending > 0) {
|
|
45165
|
+
injectedTier = best;
|
|
45166
|
+
const label = emergencyOverride ? "EMERGENCY" : "OVER-LIMIT";
|
|
45167
|
+
injectedReason = best === 1 ? `${label} T1: max effective pending ${bestPending}, usage ${Math.round(usage * 100)}%` : `${label} T${best} distill: max pending ${bestPending} (T1 effective ${t1Eff}, T2 ${t2Pen}, T3 ${t3Pen}), usage ${Math.round(usage * 100)}%`;
|
|
45168
|
+
}
|
|
45169
|
+
} else if (growthReady) {
|
|
45170
|
+
if (t1Eff >= nudgeGrowthTokens) {
|
|
45171
|
+
injectedTier = 1;
|
|
45172
|
+
injectedReason = `T1 effective ${t1Eff} >= ${nudgeGrowthTokens}, growth ${growthSinceReference}, usage ${Math.round(usage * 100)}%`;
|
|
45173
|
+
} else if (config.tiers.enabled && t2Pen >= tier2Threshold && t2Pen > t1Eff) {
|
|
45174
|
+
const lastShown = state.nudge.lastShownByTier[2] ?? 0;
|
|
45100
45175
|
const cadenceMet = lastShown === 0 || tokenCount - lastShown >= growthFloor;
|
|
45101
|
-
if (
|
|
45102
|
-
|
|
45103
|
-
|
|
45104
|
-
|
|
45105
|
-
}
|
|
45106
|
-
|
|
45107
|
-
|
|
45108
|
-
if (
|
|
45109
|
-
|
|
45110
|
-
|
|
45111
|
-
|
|
45112
|
-
injectedReason = emergencyOverride ? `EMERGENCY: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.emergencyThresholdPct * 100)}%, T${tier} pending ${info.pending}` : `OVER-LIMIT: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.maxContextLimitPct * 100)}%, T${tier} pending ${info.pending}`;
|
|
45113
|
-
break;
|
|
45176
|
+
if (cadenceMet) {
|
|
45177
|
+
injectedTier = 2;
|
|
45178
|
+
injectedReason = `T2 distill ready: ${tiers[2].targetBlocks.length} tier-1 blocks (${t2Pen} tokens) >= ${tier2Threshold} (1.5x) and > T1 effective ${t1Eff}, usage ${Math.round(usage * 100)}%`;
|
|
45179
|
+
}
|
|
45180
|
+
} else if (config.tiers.enabled && t3Pen >= tier2Threshold && t3Pen > t2Pen && t3Pen > t1Eff) {
|
|
45181
|
+
const lastShown = state.nudge.lastShownByTier[3] ?? 0;
|
|
45182
|
+
const cadenceMet = lastShown === 0 || tokenCount - lastShown >= growthFloor;
|
|
45183
|
+
if (cadenceMet) {
|
|
45184
|
+
injectedTier = 3;
|
|
45185
|
+
injectedReason = `T3 condense ready: ${tiers[3].targetBlocks.length} tier-2 blocks (${t3Pen} tokens) >= ${tier2Threshold} (1.5x) and > T2 ${t2Pen} and > T1 effective ${t1Eff}, usage ${Math.round(usage * 100)}%`;
|
|
45186
|
+
}
|
|
45114
45187
|
}
|
|
45115
45188
|
}
|
|
45116
|
-
const shouldInject = injectedTier !== null
|
|
45189
|
+
const shouldInject = injectedTier !== null;
|
|
45117
45190
|
let reason;
|
|
45118
|
-
if (
|
|
45119
|
-
reason = injectedReason;
|
|
45120
|
-
} else if (emergencyOverride) {
|
|
45121
|
-
reason = `EMERGENCY: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.emergencyThresholdPct * 100)}% (no compressible content)`;
|
|
45122
|
-
} else if (overLimit && injectedTier !== null) {
|
|
45123
|
-
reason = injectedReason;
|
|
45124
|
-
} else if (overLimit) {
|
|
45125
|
-
reason = `OVER-LIMIT: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.maxContextLimitPct * 100)}% (no compressible content)`;
|
|
45126
|
-
} else if (injectedTier !== null) {
|
|
45191
|
+
if (injectedTier !== null) {
|
|
45127
45192
|
reason = injectedReason;
|
|
45193
|
+
} else if (pressure) {
|
|
45194
|
+
const label = emergencyOverride ? "EMERGENCY" : "OVER-LIMIT";
|
|
45195
|
+
reason = `${label}: usage ${Math.round(usage * 100)}% but no tier has effective compressible content (T1 effective ${t1Eff}, T2 ${t2Pen}, T3 ${t3Pen}) \u2014 nudge suppressed to avoid offering ranges below minCompressRange`;
|
|
45128
45196
|
} else {
|
|
45129
45197
|
const tiersList = [1, 2, 3];
|
|
45130
45198
|
const eligible = tiersList.filter((t) => config.tiers.enabled || t === 1);
|
|
@@ -45336,6 +45404,23 @@ var defaultPrompts = Object.freeze({
|
|
|
45336
45404
|
tier2DistillRules: TIER2_DISTILL_RULES,
|
|
45337
45405
|
tier3CondenseRules: TIER3_CONDENSE_RULES
|
|
45338
45406
|
});
|
|
45407
|
+
function resolvePrompts(overrides, options = {}) {
|
|
45408
|
+
const clean = {};
|
|
45409
|
+
if (overrides) {
|
|
45410
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
45411
|
+
if (typeof value === "string") {
|
|
45412
|
+
clean[key] = value;
|
|
45413
|
+
}
|
|
45414
|
+
}
|
|
45415
|
+
}
|
|
45416
|
+
const keys = Object.keys(clean);
|
|
45417
|
+
if (keys.length > 0 && !options.acknowledgeRisk) {
|
|
45418
|
+
throw new Error(
|
|
45419
|
+
`resolvePrompts: overriding compression rules requires { acknowledgeRisk: true }. Overridden keys: ${keys.join(", ")}. These rules are quality-critical (tuned over months of production use); changing them can degrade summary quality and break retrieval (summaries may lose paths, signatures, decisions).`
|
|
45420
|
+
);
|
|
45421
|
+
}
|
|
45422
|
+
return { ...defaultPrompts, ...clean };
|
|
45423
|
+
}
|
|
45339
45424
|
function efficiencyNote(prompts) {
|
|
45340
45425
|
return `This is an efficiency nudge to compress early and keep context lean \u2014 not an overflow warning. A separate, stronger alert will appear if the context is actually full.
|
|
45341
45426
|
|
|
@@ -45456,20 +45541,23 @@ ${lines.join("\n")}`;
|
|
|
45456
45541
|
function renderNudgeText(decision, prompts = defaultPrompts) {
|
|
45457
45542
|
const breakdownStr = formatBreakdown(decision.contextBreakdown);
|
|
45458
45543
|
const rangesStr = formatRanges(decision.compressibleRanges, decision.protectedRanges ?? []);
|
|
45544
|
+
const isEmergency = !!decision.breakdown?.emergencyOverride || !!decision.breakdown?.overLimit;
|
|
45459
45545
|
if (decision.tier !== null && decision.tier >= 2) {
|
|
45460
45546
|
const isT2 = decision.tier === 2;
|
|
45461
45547
|
const targets = decision.tierTargetBlocks ?? [];
|
|
45462
45548
|
const blockList = formatTierTargetBlocks(targets);
|
|
45463
45549
|
const startId = targets[0]?.blockId ?? "b1";
|
|
45464
45550
|
const endId = targets[targets.length - 1]?.blockId ?? "b5";
|
|
45551
|
+
const voice = isEmergency ? "emergency" : "gentle";
|
|
45552
|
+
const triggerLine = isEmergency ? `[EMERGENCY \u2014 TIER ${decision.tier} ${isT2 ? "DISTILLATION" : "CONDENSATION"}] Context limit reached \u2014 distill NOW into a denser summary to reclaim tokens.` : `[TIER ${decision.tier} ${isT2 ? "DISTILLATION" : "CONDENSATION"} TRIGGER]`;
|
|
45465
45553
|
return {
|
|
45466
|
-
voice
|
|
45554
|
+
voice,
|
|
45467
45555
|
text: [
|
|
45468
45556
|
efficiencyNote(prompts),
|
|
45469
45557
|
"",
|
|
45470
45558
|
breakdownStr,
|
|
45471
45559
|
"",
|
|
45472
|
-
|
|
45560
|
+
triggerLine,
|
|
45473
45561
|
isT2 ? `Your tier-1 compression summaries have accumulated. Distill them into a single denser tier-2 summary. Use block IDs as boundaries (startId and endId as bN). Any raw (uncompressed) messages sitting between the boundary blocks are absorbed into the tier-2 block as well \u2014 apply HOW TO COMPRESS to those raw messages and the TIER 2 distillation rules to the existing summaries, so the whole span is covered and nothing is lost.` : `Your tier-2 compression summaries have accumulated. Condense them further into a tier-3 ultra-condensed summary. Use block IDs as boundaries (startId and endId as bN). Any raw (uncompressed) messages sitting between the boundary blocks are absorbed into the tier-3 block as well \u2014 apply HOW TO COMPRESS to those raw messages and the TIER 3 condensation rules to the existing summaries, so the whole span is covered and nothing is lost.`,
|
|
45474
45562
|
blockList,
|
|
45475
45563
|
`Example: compress({ content: [{ startId: "${startId}", endId: "${endId}", summary: "..." }] })`,
|
|
@@ -45480,7 +45568,6 @@ function renderNudgeText(decision, prompts = defaultPrompts) {
|
|
|
45480
45568
|
].join("\n")
|
|
45481
45569
|
};
|
|
45482
45570
|
}
|
|
45483
|
-
const isEmergency = !!decision.breakdown?.emergencyOverride || !!decision.breakdown?.overLimit;
|
|
45484
45571
|
if (isEmergency) {
|
|
45485
45572
|
return {
|
|
45486
45573
|
voice: "emergency",
|
|
@@ -46661,6 +46748,7 @@ function resolveContextLimitValue(raw, nativeLimit) {
|
|
|
46661
46748
|
}
|
|
46662
46749
|
function mergeCompress(global2, provider, model) {
|
|
46663
46750
|
const pick2 = (k2) => model?.[k2] ?? provider?.[k2] ?? global2?.[k2];
|
|
46751
|
+
const promptLevels = [global2?.prompts, provider?.prompts, model?.prompts].filter(Boolean);
|
|
46664
46752
|
return {
|
|
46665
46753
|
modelContextLimit: pick2("modelContextLimit"),
|
|
46666
46754
|
maxContextLimit: pick2("maxContextLimit"),
|
|
@@ -46669,13 +46757,31 @@ function mergeCompress(global2, provider, model) {
|
|
|
46669
46757
|
preserveRecentMessages: pick2("preserveRecentMessages"),
|
|
46670
46758
|
preserveRecentTokens: pick2("preserveRecentTokens"),
|
|
46671
46759
|
minCompressRange: pick2("minCompressRange"),
|
|
46672
|
-
tiers: pick2("tiers")
|
|
46760
|
+
tiers: pick2("tiers"),
|
|
46761
|
+
prompts: promptLevels.length > 0 ? Object.assign({}, ...promptLevels) : void 0,
|
|
46762
|
+
acknowledgePromptsRisk: pick2("acknowledgePromptsRisk")
|
|
46673
46763
|
};
|
|
46674
46764
|
}
|
|
46675
46765
|
function resolveCompress(routes, upstreamUrl, model, global2) {
|
|
46676
46766
|
const route = findRoute(routes, upstreamUrl);
|
|
46677
46767
|
return mergeCompress(global2, route?.compress, model ? route?.models?.[model]?.compress : void 0);
|
|
46678
46768
|
}
|
|
46769
|
+
var warnedPromptsRisk = false;
|
|
46770
|
+
function resolveCompressPrompts(s3) {
|
|
46771
|
+
if (!s3.prompts) return defaultPrompts;
|
|
46772
|
+
if (s3.acknowledgePromptsRisk !== true) {
|
|
46773
|
+
if (!warnedPromptsRisk) {
|
|
46774
|
+
warnedPromptsRisk = true;
|
|
46775
|
+
log("warn", "[compress] prompts override IGNORED: acknowledgePromptsRisk !== true. Set it to true to acknowledge the summary-quality risk.");
|
|
46776
|
+
}
|
|
46777
|
+
return defaultPrompts;
|
|
46778
|
+
}
|
|
46779
|
+
try {
|
|
46780
|
+
return resolvePrompts(s3.prompts, { acknowledgeRisk: true });
|
|
46781
|
+
} catch {
|
|
46782
|
+
return defaultPrompts;
|
|
46783
|
+
}
|
|
46784
|
+
}
|
|
46679
46785
|
function hasCompressSettings(s3) {
|
|
46680
46786
|
return Object.values(s3).some((v2) => v2 !== void 0);
|
|
46681
46787
|
}
|
|
@@ -46714,6 +46820,12 @@ function parsePercent(v2) {
|
|
|
46714
46820
|
if (s3.endsWith("%")) return Number(s3.slice(0, -1)) / 100;
|
|
46715
46821
|
return Number(s3);
|
|
46716
46822
|
}
|
|
46823
|
+
function resolveRequestConfig(base, routes, embeddedUrl, model, native, globalCompress) {
|
|
46824
|
+
const compress = resolveCompress(routes, embeddedUrl, model, globalCompress);
|
|
46825
|
+
const limit = resolveContextLimitValue(compress.modelContextLimit, native ?? base.modelContextLimit);
|
|
46826
|
+
if (!hasCompressSettings(compress) && limit === base.modelContextLimit) return base;
|
|
46827
|
+
return applyCompressSettings(base, limit, compress);
|
|
46828
|
+
}
|
|
46717
46829
|
|
|
46718
46830
|
// src/registry.ts
|
|
46719
46831
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
@@ -46878,6 +46990,9 @@ function safeJsonParse(s3) {
|
|
|
46878
46990
|
return {};
|
|
46879
46991
|
}
|
|
46880
46992
|
}
|
|
46993
|
+
function isLoopbackAddress(addr) {
|
|
46994
|
+
return !!addr && (addr.startsWith("127.") || addr === "::1" || addr.startsWith("::ffff:127."));
|
|
46995
|
+
}
|
|
46881
46996
|
|
|
46882
46997
|
// src/message-id.ts
|
|
46883
46998
|
function deriveMessageId(role, contentType, text, options = {}) {
|
|
@@ -47041,7 +47156,7 @@ function coreToAnthropic(messages, cacheControls) {
|
|
|
47041
47156
|
function conversationSignalAnthropic(body, headerValue2) {
|
|
47042
47157
|
if (headerValue2 && headerValue2.trim()) return headerValue2.trim();
|
|
47043
47158
|
const firstUser = body.messages.find((m2) => m2.role === "user");
|
|
47044
|
-
const seed = firstUser ? JSON.stringify(firstUser.content)
|
|
47159
|
+
const seed = firstUser ? JSON.stringify(firstUser.content) : "default";
|
|
47045
47160
|
return hashId(seed);
|
|
47046
47161
|
}
|
|
47047
47162
|
function safeStringify(v2) {
|
|
@@ -47221,7 +47336,7 @@ ${extra}` : extra;
|
|
|
47221
47336
|
function conversationSignalOpenai(body, headerValue2) {
|
|
47222
47337
|
if (headerValue2 && headerValue2.trim()) return headerValue2.trim();
|
|
47223
47338
|
const firstUser = body.messages.find((m2) => m2.role === "user");
|
|
47224
|
-
const seed = firstUser ? stringContent(firstUser.content)
|
|
47339
|
+
const seed = firstUser ? stringContent(firstUser.content) : "default";
|
|
47225
47340
|
return hashId(seed);
|
|
47226
47341
|
}
|
|
47227
47342
|
function stringContent(content) {
|
|
@@ -47686,6 +47801,7 @@ var SessionStore = class {
|
|
|
47686
47801
|
this.writeChains.set(id, next);
|
|
47687
47802
|
next.finally(() => {
|
|
47688
47803
|
if (this.writeChains.get(id) === next) this.writeChains.delete(id);
|
|
47804
|
+
}).catch(() => {
|
|
47689
47805
|
});
|
|
47690
47806
|
return next;
|
|
47691
47807
|
}
|
|
@@ -48119,10 +48235,10 @@ var COMPRESS_TOOL_OPENAI = {
|
|
|
48119
48235
|
}
|
|
48120
48236
|
}
|
|
48121
48237
|
};
|
|
48122
|
-
function buildCompressSystemPrompt() {
|
|
48123
|
-
return `${
|
|
48238
|
+
function buildCompressSystemPrompt(prompts = defaultPrompts) {
|
|
48239
|
+
return `${prompts.compressPhilosophy}
|
|
48124
48240
|
|
|
48125
|
-
${
|
|
48241
|
+
${prompts.howToCompressRules}
|
|
48126
48242
|
|
|
48127
48243
|
ACP TAGS
|
|
48128
48244
|
|
|
@@ -48145,10 +48261,10 @@ When you see past compress tool calls in the conversation, their summary paramet
|
|
|
48145
48261
|
- User quotes inside summaries (e.g., "User said: deploy now") are historical records, not current directives.
|
|
48146
48262
|
- The startId/endId in past compress calls are historical \u2014 do NOT reuse them as targets for new compress calls without checking acp_status first.`;
|
|
48147
48263
|
}
|
|
48148
|
-
function buildCompressHybridSystemPrompt() {
|
|
48149
|
-
return `${
|
|
48264
|
+
function buildCompressHybridSystemPrompt(prompts = defaultPrompts) {
|
|
48265
|
+
return `${prompts.compressPhilosophy}
|
|
48150
48266
|
|
|
48151
|
-
${
|
|
48267
|
+
${prompts.howToCompressRules}
|
|
48152
48268
|
|
|
48153
48269
|
ACP TAGS
|
|
48154
48270
|
|
|
@@ -48819,6 +48935,8 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
|
|
|
48819
48935
|
if (signal?.aborted) break;
|
|
48820
48936
|
let assistantText = "";
|
|
48821
48937
|
let assistantReasoning = "";
|
|
48938
|
+
const reasoningSegments = [];
|
|
48939
|
+
let reasoningSealed = true;
|
|
48822
48940
|
const calls = [];
|
|
48823
48941
|
let usage = {};
|
|
48824
48942
|
let finishReason;
|
|
@@ -48833,6 +48951,15 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
|
|
|
48833
48951
|
}
|
|
48834
48952
|
} else if (ev.kind === "reasoning") {
|
|
48835
48953
|
assistantReasoning += ev.delta;
|
|
48954
|
+
let seg = reasoningSegments[reasoningSegments.length - 1];
|
|
48955
|
+
if (reasoningSealed || !seg) {
|
|
48956
|
+
seg = { text: "", signature: "" };
|
|
48957
|
+
reasoningSegments.push(seg);
|
|
48958
|
+
reasoningSealed = false;
|
|
48959
|
+
}
|
|
48960
|
+
seg.text += ev.delta;
|
|
48961
|
+
if (ev.signature) seg.signature += ev.signature;
|
|
48962
|
+
if (ev.blockEnd) reasoningSealed = true;
|
|
48836
48963
|
if (!ctx.textProtocol) {
|
|
48837
48964
|
if (ev.raw) {
|
|
48838
48965
|
yield ev.raw;
|
|
@@ -48902,15 +49029,20 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
|
|
|
48902
49029
|
if (realCalls > 0) ctx.log(`[acp-loop] round ${round}: ${realCalls} real tool call(s) forwarded to client`);
|
|
48903
49030
|
}
|
|
48904
49031
|
if (proxyResults.length > 0) {
|
|
48905
|
-
if (
|
|
48906
|
-
|
|
48907
|
-
|
|
48908
|
-
|
|
48909
|
-
|
|
48910
|
-
|
|
48911
|
-
|
|
48912
|
-
|
|
48913
|
-
|
|
49032
|
+
if (reasoningSegments.length > 0) {
|
|
49033
|
+
for (let i = 0; i < reasoningSegments.length; i++) {
|
|
49034
|
+
const seg = reasoningSegments[i];
|
|
49035
|
+
if (seg.text.length === 0 && seg.signature.length === 0) continue;
|
|
49036
|
+
const reasoningMsg = {
|
|
49037
|
+
id: i === 0 ? `acp_loop_r${round}_reasoning` : `acp_loop_r${round}_reasoning_${i + 1}`,
|
|
49038
|
+
role: "assistant",
|
|
49039
|
+
contentType: "reasoning",
|
|
49040
|
+
text: seg.text,
|
|
49041
|
+
reasoningContent: seg.text,
|
|
49042
|
+
...seg.signature.length > 0 ? { thinkingSignature: seg.signature } : {}
|
|
49043
|
+
};
|
|
49044
|
+
coreMessages.push(reasoningMsg);
|
|
49045
|
+
}
|
|
48914
49046
|
}
|
|
48915
49047
|
if (assistantText.length > 0) {
|
|
48916
49048
|
coreMessages.push({
|
|
@@ -49774,6 +49906,7 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49774
49906
|
let stopReason;
|
|
49775
49907
|
let usageYielded = false;
|
|
49776
49908
|
const indexMap = /* @__PURE__ */ new Map();
|
|
49909
|
+
const thinkingIndexes = /* @__PURE__ */ new Set();
|
|
49777
49910
|
for await (const eventStr of iterSseEvents2(upstream)) {
|
|
49778
49911
|
const parsed = parseAnthropicSse(eventStr);
|
|
49779
49912
|
if (!parsed) continue;
|
|
@@ -49798,6 +49931,7 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49798
49931
|
const id = typeof block.id === "string" ? block.id : `toolu_${upstreamIndex}`;
|
|
49799
49932
|
pending.set(upstreamIndex, { id, name, json: "" });
|
|
49800
49933
|
} else {
|
|
49934
|
+
if (block.type === "thinking" || block.type === "redacted_thinking") thinkingIndexes.add(upstreamIndex);
|
|
49801
49935
|
const ci2 = clientIndex++;
|
|
49802
49936
|
indexMap.set(upstreamIndex, ci2);
|
|
49803
49937
|
yield { kind: "meta", chunk: remapIndexInEvent(eventStr, ci2), firstRoundOnly: round === 1 };
|
|
@@ -49812,6 +49946,21 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49812
49946
|
} else if (delta.type === "text_delta" && typeof delta.text === "string") {
|
|
49813
49947
|
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49814
49948
|
yield { kind: "text", delta: delta.text, raw: remapIndexInEvent(eventStr, ci2) };
|
|
49949
|
+
} else if (delta.type === "thinking_delta" && typeof delta.thinking === "string" && delta.thinking.length > 0) {
|
|
49950
|
+
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49951
|
+
yield {
|
|
49952
|
+
kind: "reasoning",
|
|
49953
|
+
delta: delta.thinking,
|
|
49954
|
+
...round === 1 ? { raw: remapIndexInEvent(eventStr, ci2) } : {}
|
|
49955
|
+
};
|
|
49956
|
+
} else if (delta.type === "signature_delta" && typeof delta.signature === "string") {
|
|
49957
|
+
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49958
|
+
yield {
|
|
49959
|
+
kind: "reasoning",
|
|
49960
|
+
delta: "",
|
|
49961
|
+
signature: delta.signature,
|
|
49962
|
+
...round === 1 ? { raw: remapIndexInEvent(eventStr, ci2) } : {}
|
|
49963
|
+
};
|
|
49815
49964
|
} else if (round === 1) {
|
|
49816
49965
|
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49817
49966
|
yield { kind: "meta", chunk: remapIndexInEvent(eventStr, ci2), firstRoundOnly: true };
|
|
@@ -49827,6 +49976,12 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49827
49976
|
callId: tb.id,
|
|
49828
49977
|
arguments: tb.json
|
|
49829
49978
|
};
|
|
49979
|
+
} else if (thinkingIndexes.delete(upstreamIndex)) {
|
|
49980
|
+
if (round === 1) {
|
|
49981
|
+
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49982
|
+
yield { kind: "meta", chunk: remapIndexInEvent(eventStr, ci2), firstRoundOnly: true };
|
|
49983
|
+
}
|
|
49984
|
+
yield { kind: "reasoning", delta: "", blockEnd: true };
|
|
49830
49985
|
} else {
|
|
49831
49986
|
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49832
49987
|
yield { kind: "meta", chunk: remapIndexInEvent(eventStr, ci2), firstRoundOnly: round === 1 };
|
|
@@ -49867,6 +50022,22 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49867
50022
|
emitText(delta) {
|
|
49868
50023
|
return buildTextBlock(clientIndex++, delta);
|
|
49869
50024
|
},
|
|
50025
|
+
emitReasoning(delta) {
|
|
50026
|
+
const index = clientIndex++;
|
|
50027
|
+
return Buffer.from(
|
|
50028
|
+
`event: content_block_start
|
|
50029
|
+
data: ${JSON.stringify({ type: "content_block_start", index, content_block: { type: "thinking", thinking: "" } })}
|
|
50030
|
+
|
|
50031
|
+
event: content_block_delta
|
|
50032
|
+
data: ${JSON.stringify({ type: "content_block_delta", index, delta: { type: "thinking_delta", thinking: delta } })}
|
|
50033
|
+
|
|
50034
|
+
event: content_block_stop
|
|
50035
|
+
data: ${JSON.stringify({ type: "content_block_stop", index })}
|
|
50036
|
+
|
|
50037
|
+
`,
|
|
50038
|
+
"utf8"
|
|
50039
|
+
);
|
|
50040
|
+
},
|
|
49870
50041
|
emitToolCall(call) {
|
|
49871
50042
|
return buildToolUseBlock(clientIndex++, call);
|
|
49872
50043
|
},
|
|
@@ -50112,7 +50283,6 @@ ${note}` : note;
|
|
|
50112
50283
|
}
|
|
50113
50284
|
|
|
50114
50285
|
// src/stream-responses.ts
|
|
50115
|
-
var TEXT_PROTOCOL = process.env.ACP_COMPRESS_PROTOCOL === "text";
|
|
50116
50286
|
function rewriteResponsesJsonResponse(body, ctx) {
|
|
50117
50287
|
if (!body || typeof body !== "object") return body;
|
|
50118
50288
|
const b2 = body;
|
|
@@ -50165,12 +50335,35 @@ function emitStreamError(res, protocol, message, log2) {
|
|
|
50165
50335
|
`);
|
|
50166
50336
|
safeWrite(res, "data: [DONE]\n\n");
|
|
50167
50337
|
} else if (protocol === "responses") {
|
|
50338
|
+
const itemId = "msg_acp_error";
|
|
50339
|
+
const oi2 = 0;
|
|
50340
|
+
const errorItem = { type: "message", id: itemId, role: "assistant", content: [{ type: "output_text", text: visible }] };
|
|
50341
|
+
safeWrite(res, `event: response.output_item.added
|
|
50342
|
+
data: ${JSON.stringify({ type: "response.output_item.added", output_index: oi2, item: { type: "message", id: itemId, role: "assistant", content: [] } })}
|
|
50343
|
+
|
|
50344
|
+
`);
|
|
50345
|
+
safeWrite(res, `event: response.content_part.added
|
|
50346
|
+
data: ${JSON.stringify({ type: "response.content_part.added", item_id: itemId, output_index: oi2, part: { type: "output_text", text: "" } })}
|
|
50347
|
+
|
|
50348
|
+
`);
|
|
50168
50349
|
safeWrite(res, `event: response.output_text.delta
|
|
50169
|
-
data: ${JSON.stringify({ type: "response.output_text.delta", delta: visible })}
|
|
50350
|
+
data: ${JSON.stringify({ type: "response.output_text.delta", item_id: itemId, output_index: oi2, delta: visible })}
|
|
50351
|
+
|
|
50352
|
+
`);
|
|
50353
|
+
safeWrite(res, `event: response.output_text.done
|
|
50354
|
+
data: ${JSON.stringify({ type: "response.output_text.done", item_id: itemId, output_index: oi2, text: visible })}
|
|
50355
|
+
|
|
50356
|
+
`);
|
|
50357
|
+
safeWrite(res, `event: response.content_part.done
|
|
50358
|
+
data: ${JSON.stringify({ type: "response.content_part.done", item_id: itemId, output_index: oi2, part: { type: "output_text", text: visible } })}
|
|
50359
|
+
|
|
50360
|
+
`);
|
|
50361
|
+
safeWrite(res, `event: response.output_item.done
|
|
50362
|
+
data: ${JSON.stringify({ type: "response.output_item.done", output_index: oi2, item: errorItem })}
|
|
50170
50363
|
|
|
50171
50364
|
`);
|
|
50172
50365
|
safeWrite(res, `event: response.completed
|
|
50173
|
-
data: ${JSON.stringify({ type: "response.completed", response: { status: "completed", output: [] } })}
|
|
50366
|
+
data: ${JSON.stringify({ type: "response.completed", response: { status: "completed", output: [errorItem] } })}
|
|
50174
50367
|
|
|
50175
50368
|
`);
|
|
50176
50369
|
} else {
|
|
@@ -50237,6 +50430,7 @@ var rootKeyPem;
|
|
|
50237
50430
|
var rootCert;
|
|
50238
50431
|
var rootKey;
|
|
50239
50432
|
var secureContextCache = /* @__PURE__ */ new Map();
|
|
50433
|
+
var SECURE_CONTEXT_CACHE_MAX = 64;
|
|
50240
50434
|
function generateRootCA() {
|
|
50241
50435
|
const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
|
|
50242
50436
|
const cert = import_node_forge.default.pki.createCertificate();
|
|
@@ -50288,7 +50482,11 @@ function getSecureContext(host) {
|
|
|
50288
50482
|
throw new Error("CA not initialized \u2014 call ensureRootCA() first");
|
|
50289
50483
|
}
|
|
50290
50484
|
const cached = secureContextCache.get(host);
|
|
50291
|
-
if (cached)
|
|
50485
|
+
if (cached) {
|
|
50486
|
+
secureContextCache.delete(host);
|
|
50487
|
+
secureContextCache.set(host, cached);
|
|
50488
|
+
return cached;
|
|
50489
|
+
}
|
|
50292
50490
|
const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
|
|
50293
50491
|
const cert = import_node_forge.default.pki.createCertificate();
|
|
50294
50492
|
cert.publicKey = keys.publicKey;
|
|
@@ -50311,6 +50509,10 @@ function getSecureContext(host) {
|
|
|
50311
50509
|
ca: rootCertPem
|
|
50312
50510
|
});
|
|
50313
50511
|
secureContextCache.set(host, ctx);
|
|
50512
|
+
if (secureContextCache.size > SECURE_CONTEXT_CACHE_MAX) {
|
|
50513
|
+
const oldest = secureContextCache.keys().next().value;
|
|
50514
|
+
if (oldest !== void 0) secureContextCache.delete(oldest);
|
|
50515
|
+
}
|
|
50314
50516
|
return ctx;
|
|
50315
50517
|
}
|
|
50316
50518
|
|
|
@@ -50544,6 +50746,11 @@ var DEFAULT_MITM_DOMAINS = [
|
|
|
50544
50746
|
"chatgpt.com"
|
|
50545
50747
|
];
|
|
50546
50748
|
var MITM_UPSTREAM_KEY = "__biliMitmUpstream";
|
|
50749
|
+
var MITM_HANDSHAKE_TIMEOUT_MS_DEFAULT = 1e4;
|
|
50750
|
+
function mitmHandshakeTimeoutMs() {
|
|
50751
|
+
const v2 = Number.parseInt(process.env.BILI_MITM_HANDSHAKE_TIMEOUT_MS ?? "", 10);
|
|
50752
|
+
return Number.isFinite(v2) && v2 > 0 ? v2 : MITM_HANDSHAKE_TIMEOUT_MS_DEFAULT;
|
|
50753
|
+
}
|
|
50547
50754
|
function isMitmHost(host, extraDomains = []) {
|
|
50548
50755
|
const h = host.toLowerCase();
|
|
50549
50756
|
const all = [...DEFAULT_MITM_DOMAINS, ...extraDomains, ...discoverMitmDomains()].map((d) => d.toLowerCase());
|
|
@@ -50553,12 +50760,12 @@ function setupMitm(server, extraDomains = [], log2 = () => {
|
|
|
50553
50760
|
}, resolveProxyUrl) {
|
|
50554
50761
|
ensureRootCA();
|
|
50555
50762
|
server.on("connect", (req, clientSocket, head) => {
|
|
50556
|
-
|
|
50557
|
-
|
|
50558
|
-
clientSocket.
|
|
50559
|
-
clientSocket.end();
|
|
50763
|
+
if (!isLoopbackAddress(clientSocket.remoteAddress)) {
|
|
50764
|
+
log2(`CONNECT ${req.url} rejected: non-loopback client ${clientSocket.remoteAddress}`);
|
|
50765
|
+
clientSocket.end("HTTP/1.1 403 Forbidden\r\n\r\n");
|
|
50560
50766
|
return;
|
|
50561
50767
|
}
|
|
50768
|
+
const { hostname, port } = parseHostPort(req.url ?? "");
|
|
50562
50769
|
const targetPort = port || 443;
|
|
50563
50770
|
if (!isMitmHost(hostname, extraDomains)) {
|
|
50564
50771
|
const proxyUrl = resolveProxyUrl?.(hostname);
|
|
@@ -50578,14 +50785,20 @@ function parseHostPort(s3) {
|
|
|
50578
50785
|
}
|
|
50579
50786
|
function tunnelThrough(clientSocket, host, port, head, log2, proxyUrl) {
|
|
50580
50787
|
let established = false;
|
|
50788
|
+
let aborted = false;
|
|
50581
50789
|
const connectTimer = setTimeout(() => {
|
|
50582
50790
|
if (!established) {
|
|
50791
|
+
aborted = true;
|
|
50583
50792
|
log2(`tunnel ${host}:${port} connect timeout`);
|
|
50584
50793
|
clientSocket.write("HTTP/1.1 504 Gateway Timeout\r\n\r\n");
|
|
50585
50794
|
clientSocket.destroy();
|
|
50586
50795
|
}
|
|
50587
50796
|
}, 15e3);
|
|
50588
50797
|
connectThroughProxy(host, port, proxyUrl).then((upstream) => {
|
|
50798
|
+
if (aborted) {
|
|
50799
|
+
upstream.destroy();
|
|
50800
|
+
return;
|
|
50801
|
+
}
|
|
50589
50802
|
established = true;
|
|
50590
50803
|
clearTimeout(connectTimer);
|
|
50591
50804
|
clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
@@ -50600,6 +50813,7 @@ function tunnelThrough(clientSocket, host, port, head, log2, proxyUrl) {
|
|
|
50600
50813
|
upstream.once("error", (e) => cleanup("upstream", e));
|
|
50601
50814
|
clientSocket.once("error", (e) => cleanup("client", e));
|
|
50602
50815
|
}).catch((err2) => {
|
|
50816
|
+
if (aborted) return;
|
|
50603
50817
|
clearTimeout(connectTimer);
|
|
50604
50818
|
log2(`tunnel ${host}:${port} connect failed: ${err2.message}`);
|
|
50605
50819
|
clientSocket.write("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
|
@@ -50629,6 +50843,14 @@ function doMitm(server, clientSocket, host, port, head, log2) {
|
|
|
50629
50843
|
tlsSocket.destroy();
|
|
50630
50844
|
clientSocket.destroy();
|
|
50631
50845
|
});
|
|
50846
|
+
const handshakeTimer = setTimeout(() => {
|
|
50847
|
+
log2(`mitm ${host}:${port} TLS handshake timeout`);
|
|
50848
|
+
tlsSocket.destroy();
|
|
50849
|
+
clientSocket.destroy();
|
|
50850
|
+
}, mitmHandshakeTimeoutMs());
|
|
50851
|
+
tlsSocket.once("secure", () => clearTimeout(handshakeTimer));
|
|
50852
|
+
tlsSocket.once("close", () => clearTimeout(handshakeTimer));
|
|
50853
|
+
tlsSocket.once("error", () => clearTimeout(handshakeTimer));
|
|
50632
50854
|
server.emit("connection", tlsSocket);
|
|
50633
50855
|
log2(`mitm ${host}:${port} tunnel established (TLS terminated locally)`);
|
|
50634
50856
|
}
|
|
@@ -51364,8 +51586,28 @@ var UPSTREAM_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
|
51364
51586
|
// Node's fetch transparently decodes compressed responses. Do not
|
|
51365
51587
|
// forward the upstream encoding marker when the body is rewritten or
|
|
51366
51588
|
// streamed from fetch, otherwise clients try to decompress plain bytes.
|
|
51367
|
-
"content-encoding"
|
|
51589
|
+
"content-encoding",
|
|
51590
|
+
// RFC 7230 §6.1 hop-by-hop headers. proxy-authorization in particular
|
|
51591
|
+
// carries client→proxy credentials that must never reach the model
|
|
51592
|
+
// endpoint. (#80)
|
|
51593
|
+
"proxy-authenticate",
|
|
51594
|
+
"proxy-authorization",
|
|
51595
|
+
"proxy-connection",
|
|
51596
|
+
"te",
|
|
51597
|
+
"trailer",
|
|
51598
|
+
"upgrade"
|
|
51368
51599
|
]);
|
|
51600
|
+
function connectionNamedHeaders(conn) {
|
|
51601
|
+
const out = /* @__PURE__ */ new Set();
|
|
51602
|
+
if (!conn) return out;
|
|
51603
|
+
for (const part of Array.isArray(conn) ? conn : [conn]) {
|
|
51604
|
+
for (const name of part.split(",")) {
|
|
51605
|
+
const t = name.trim().toLowerCase();
|
|
51606
|
+
if (t) out.add(t);
|
|
51607
|
+
}
|
|
51608
|
+
}
|
|
51609
|
+
return out;
|
|
51610
|
+
}
|
|
51369
51611
|
function buildForwardHeaders(headers) {
|
|
51370
51612
|
const out = {};
|
|
51371
51613
|
for (const [k2, v2] of Object.entries(headers)) {
|
|
@@ -51485,28 +51727,38 @@ async function startServer(opts) {
|
|
|
51485
51727
|
}
|
|
51486
51728
|
return server;
|
|
51487
51729
|
}
|
|
51488
|
-
function
|
|
51489
|
-
if (!
|
|
51490
|
-
return addr === "::1" || addr === "127.0.0.1" || addr.startsWith("127.") || addr.startsWith("::ffff:127.");
|
|
51491
|
-
}
|
|
51492
|
-
function isTrustedAdminOrigin(origin, host) {
|
|
51730
|
+
function isTrustedAdminOrigin(origin, host, trustedHosts) {
|
|
51731
|
+
if (!host || !trustedHosts.has(host.toLowerCase())) return false;
|
|
51493
51732
|
if (!origin) return true;
|
|
51494
|
-
if (!host) return false;
|
|
51495
51733
|
try {
|
|
51496
51734
|
const parsed = new URL(origin);
|
|
51497
|
-
|
|
51735
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
|
|
51736
|
+
return trustedHosts.has(parsed.host.toLowerCase());
|
|
51498
51737
|
} catch {
|
|
51499
51738
|
return false;
|
|
51500
51739
|
}
|
|
51501
51740
|
}
|
|
51741
|
+
function adminTrustedHosts(bindHost, port) {
|
|
51742
|
+
const p2 = String(port);
|
|
51743
|
+
const names = ["localhost", "127.0.0.1", "[::1]"];
|
|
51744
|
+
if (bindHost && bindHost !== "0.0.0.0" && bindHost !== "::" && !names.includes(bindHost)) {
|
|
51745
|
+
names.push(bindHost);
|
|
51746
|
+
}
|
|
51747
|
+
const set = /* @__PURE__ */ new Set();
|
|
51748
|
+
for (const n of names) {
|
|
51749
|
+
set.add(`${n}:${p2}`.toLowerCase());
|
|
51750
|
+
if (p2 === "80") set.add(n.toLowerCase());
|
|
51751
|
+
}
|
|
51752
|
+
return set;
|
|
51753
|
+
}
|
|
51502
51754
|
async function handle(req, res, opts, core, config, log2) {
|
|
51503
51755
|
const isAdminPath = req.url === "/__bili/" || req.url?.startsWith("/__bili/") || req.url === "/__acp/" || req.url?.startsWith("/__acp/");
|
|
51504
|
-
if (isAdminPath && !
|
|
51756
|
+
if (isAdminPath && !isLoopbackAddress(req.socket.remoteAddress)) {
|
|
51505
51757
|
res.writeHead(403, { "content-type": "application/json" });
|
|
51506
51758
|
res.end(JSON.stringify({ error: "management endpoints are loopback-only; access denied for " + (req.socket.remoteAddress ?? "unknown") }));
|
|
51507
51759
|
return;
|
|
51508
51760
|
}
|
|
51509
|
-
if (isAdminPath && !isTrustedAdminOrigin(req.headers.origin, req.headers.host)) {
|
|
51761
|
+
if (isAdminPath && !isTrustedAdminOrigin(req.headers.origin, req.headers.host, adminTrustedHosts(opts.host, req.socket.localPort ?? opts.port))) {
|
|
51510
51762
|
res.writeHead(403, { "content-type": "application/json" });
|
|
51511
51763
|
res.end(JSON.stringify({ error: "management request origin does not match the local bili UI" }));
|
|
51512
51764
|
return;
|
|
@@ -51660,11 +51912,11 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51660
51912
|
}
|
|
51661
51913
|
}
|
|
51662
51914
|
let reqConfig = config;
|
|
51915
|
+
let reqPrompts = defaultPrompts;
|
|
51663
51916
|
if (parsed && typeof parsed === "object") {
|
|
51664
51917
|
const model = parsed.model;
|
|
51665
51918
|
if (model) {
|
|
51666
51919
|
const embeddedUrl = route?.rewrittenUrl;
|
|
51667
|
-
const compress = resolveCompress(opts.routes, embeddedUrl, model, opts.compress);
|
|
51668
51920
|
let native = resolveContextLimit(opts.routes, embeddedUrl, model);
|
|
51669
51921
|
if (!native && embeddedUrl) {
|
|
51670
51922
|
const host = (() => {
|
|
@@ -51676,11 +51928,8 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51676
51928
|
})();
|
|
51677
51929
|
native = await contextFromRegistry(model, host);
|
|
51678
51930
|
}
|
|
51679
|
-
|
|
51680
|
-
|
|
51681
|
-
if (tuned || limit !== config.modelContextLimit) {
|
|
51682
|
-
reqConfig = applyCompressSettings(config, limit, compress);
|
|
51683
|
-
}
|
|
51931
|
+
reqConfig = resolveRequestConfig(config, opts.routes, embeddedUrl, model, native, opts.compress);
|
|
51932
|
+
reqPrompts = resolveCompressPrompts(resolveCompress(opts.routes, embeddedUrl, model, opts.compress));
|
|
51684
51933
|
}
|
|
51685
51934
|
}
|
|
51686
51935
|
let prepared = null;
|
|
@@ -51701,7 +51950,7 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51701
51950
|
acquireInFlight(session);
|
|
51702
51951
|
try {
|
|
51703
51952
|
await withSessionLock(session, async () => {
|
|
51704
|
-
prepared = countTokens ? prepareCountTokens(parsed, core, reqConfig, log2, session) : protocol === "anthropic" ? prepareAnthropic(parsed, req, opts, core, reqConfig, log2, session) : protocol === "openai" ? prepareOpenai(parsed, req, opts, core, reqConfig, log2, session) : responsesCompact ? prepareResponsesCompact(bodyBuffer, parsed, session) : prepareResponses(parsed, req, opts, core, reqConfig, log2, session, responsesIdentity);
|
|
51953
|
+
prepared = countTokens ? prepareCountTokens(parsed, core, reqConfig, log2, session) : protocol === "anthropic" ? prepareAnthropic(parsed, req, opts, core, reqConfig, reqPrompts, log2, session) : protocol === "openai" ? prepareOpenai(parsed, req, opts, core, reqConfig, reqPrompts, log2, session) : responsesCompact ? prepareResponsesCompact(bodyBuffer, parsed, session) : prepareResponses(parsed, req, opts, core, reqConfig, reqPrompts, log2, session, responsesIdentity);
|
|
51705
51954
|
await forward(req, res, opts, prepared.body, prepared, core, reqConfig, log2, route, affinity);
|
|
51706
51955
|
});
|
|
51707
51956
|
} finally {
|
|
@@ -51743,7 +51992,7 @@ function diagNudge(turn, sessionId, tokenCount, limit) {
|
|
|
51743
51992
|
const inject = n.shouldInject ? `INJECT T${n.tier ?? "?"}` : "idle";
|
|
51744
51993
|
return `[${sessionId}] nudge ${inject}: usage=${pct2} (${tokenCount}/${limit}), growth=${growth}/${floor} (ref=${ref}, interval=${interval}), pendingT1=${pendingT1}/${interval}, reason="${n.reason.slice(0, 120)}"`;
|
|
51745
51994
|
}
|
|
51746
|
-
function prepareAnthropic(parsed, req, opts, core, config, log2, session) {
|
|
51995
|
+
function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, session) {
|
|
51747
51996
|
const sessionId = session.id;
|
|
51748
51997
|
const stream2 = parsed.stream === true;
|
|
51749
51998
|
++session.stats.requests;
|
|
@@ -51771,13 +52020,13 @@ function prepareAnthropic(parsed, req, opts, core, config, log2, session) {
|
|
|
51771
52020
|
processedMessages = stripKernelSummaries(turn.messages);
|
|
51772
52021
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
51773
52022
|
rebuiltMessages = coreToAnthropic(processedMessages, cacheControls);
|
|
51774
|
-
systemOut = injectSystem(parsed, opts);
|
|
52023
|
+
systemOut = injectSystem(parsed, opts, prompts);
|
|
51775
52024
|
if (opts.compress.injectTool) {
|
|
51776
52025
|
toolsOut = injectTool(parsed.tools);
|
|
51777
52026
|
}
|
|
51778
52027
|
if (opts.compress.injectNudge && turn.nudge?.shouldInject) {
|
|
51779
52028
|
try {
|
|
51780
|
-
const rendered = renderNudgeText(turn.nudge);
|
|
52029
|
+
const rendered = renderNudgeText(turn.nudge, prompts);
|
|
51781
52030
|
if (rendered.text) {
|
|
51782
52031
|
rebuiltMessages = [...rebuiltMessages, { role: "user", content: rendered.text }];
|
|
51783
52032
|
}
|
|
@@ -51788,11 +52037,11 @@ function prepareAnthropic(parsed, req, opts, core, config, log2, session) {
|
|
|
51788
52037
|
log2("warn", `[${sessionId}] kernel transform failed, forwarding unchanged: ${String(err2)}`);
|
|
51789
52038
|
processedMessages = [];
|
|
51790
52039
|
}
|
|
51791
|
-
const rebuilt = { ...parsed, messages: rebuiltMessages, system: systemOut, tools: toolsOut };
|
|
51792
52040
|
markDirty(session);
|
|
51793
|
-
|
|
52041
|
+
const rebuilt = { ...parsed, messages: rebuiltMessages, system: systemOut, tools: toolsOut };
|
|
52042
|
+
return { body: JSON.stringify(rebuilt), session, processedMessages, originalMessages, anthropicSystem: parsed.system, protocol: "anthropic", stream: stream2, compressInjected: opts.compress.injectTool, nudge, prompts };
|
|
51794
52043
|
}
|
|
51795
|
-
function prepareOpenai(parsed, req, opts, core, config, log2, session) {
|
|
52044
|
+
function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session) {
|
|
51796
52045
|
const sessionId = session.id;
|
|
51797
52046
|
const stream2 = parsed.stream === true;
|
|
51798
52047
|
++session.stats.requests;
|
|
@@ -51822,14 +52071,14 @@ function prepareOpenai(parsed, req, opts, core, config, log2, session) {
|
|
|
51822
52071
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
51823
52072
|
rebuiltMessages = coreToOpenai(processedMessages);
|
|
51824
52073
|
const sysParts = [];
|
|
51825
|
-
if (shouldInject) sysParts.push(buildCompressSystemPrompt());
|
|
52074
|
+
if (shouldInject) sysParts.push(buildCompressSystemPrompt(prompts));
|
|
51826
52075
|
rebuiltMessages = injectOpenaiSystem(rebuiltMessages, sysParts);
|
|
51827
52076
|
if (shouldInject) {
|
|
51828
52077
|
toolsOut = injectOpenaiTool(parsed.tools);
|
|
51829
52078
|
}
|
|
51830
52079
|
if (opts.compress.injectNudge && turn.nudge?.shouldInject && shouldInject) {
|
|
51831
52080
|
try {
|
|
51832
|
-
const rendered = renderNudgeText(turn.nudge);
|
|
52081
|
+
const rendered = renderNudgeText(turn.nudge, prompts);
|
|
51833
52082
|
if (rendered.text) {
|
|
51834
52083
|
rebuiltMessages = [...rebuiltMessages, { role: "user", content: rendered.text }];
|
|
51835
52084
|
}
|
|
@@ -51845,9 +52094,9 @@ function prepareOpenai(parsed, req, opts, core, config, log2, session) {
|
|
|
51845
52094
|
rebuilt.stream_options = { include_usage: true };
|
|
51846
52095
|
}
|
|
51847
52096
|
markDirty(session);
|
|
51848
|
-
return { body: JSON.stringify(rebuilt), session, processedMessages, originalMessages, protocol: "openai", stream: stream2, compressInjected: shouldInject, nudge };
|
|
52097
|
+
return { body: JSON.stringify(rebuilt), session, processedMessages, originalMessages, protocol: "openai", stream: stream2, compressInjected: shouldInject, nudge, prompts };
|
|
51849
52098
|
}
|
|
51850
|
-
function prepareResponses(parsed, req, opts, core, config, log2, session, identity) {
|
|
52099
|
+
function prepareResponses(parsed, req, opts, core, config, prompts, log2, session, identity) {
|
|
51851
52100
|
const sessionId = session.id;
|
|
51852
52101
|
const stream2 = parsed.stream === true;
|
|
51853
52102
|
++session.stats.requests;
|
|
@@ -51885,7 +52134,7 @@ function prepareResponses(parsed, req, opts, core, config, log2, session, identi
|
|
|
51885
52134
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
51886
52135
|
rebuiltInput = patchResponsesInput(projection, processedMessages);
|
|
51887
52136
|
if (shouldInject && !process.env.ACP_NO_COMPRESS_PROMPT) {
|
|
51888
|
-
const prompt = responsesTextProtocol ? buildCompressHybridSystemPrompt() : buildCompressSystemPrompt();
|
|
52137
|
+
const prompt = responsesTextProtocol ? buildCompressHybridSystemPrompt(prompts) : buildCompressSystemPrompt(prompts);
|
|
51889
52138
|
const devContent = [...projection.systemParts, prompt].join("\n\n---\n\n");
|
|
51890
52139
|
rebuiltInput = injectResponsesDeveloperMessage(rebuiltInput, devContent);
|
|
51891
52140
|
if (!process.env.ACP_NO_INJECT_TOOL) {
|
|
@@ -51896,7 +52145,7 @@ function prepareResponses(parsed, req, opts, core, config, log2, session, identi
|
|
|
51896
52145
|
}
|
|
51897
52146
|
if (opts.compress.injectNudge && turn.nudge?.shouldInject && shouldInject) {
|
|
51898
52147
|
try {
|
|
51899
|
-
const rendered = renderNudgeText(turn.nudge);
|
|
52148
|
+
const rendered = renderNudgeText(turn.nudge, prompts);
|
|
51900
52149
|
if (rendered.text) {
|
|
51901
52150
|
const inputItems = typeof rebuiltInput === "string" ? [{ type: "message", role: "user", content: rebuiltInput }] : rebuiltInput;
|
|
51902
52151
|
inputItems.push({ type: "message", role: "user", content: rendered.text });
|
|
@@ -51938,7 +52187,8 @@ function prepareResponses(parsed, req, opts, core, config, log2, session, identi
|
|
|
51938
52187
|
stream: stream2,
|
|
51939
52188
|
compressInjected: shouldInject,
|
|
51940
52189
|
responsesTextProtocol,
|
|
51941
|
-
nudge
|
|
52190
|
+
nudge,
|
|
52191
|
+
prompts
|
|
51942
52192
|
};
|
|
51943
52193
|
}
|
|
51944
52194
|
function isCountTokensRequest(method, urlPath, hasBody) {
|
|
@@ -52001,10 +52251,10 @@ function resolvePromptCacheKey(explicit, identity, routing, upstream) {
|
|
|
52001
52251
|
if (!identity.clientProvided || !shouldInjectPromptCacheKey(routing, upstream)) return void 0;
|
|
52002
52252
|
return identity.value;
|
|
52003
52253
|
}
|
|
52004
|
-
function injectSystem(parsed, opts) {
|
|
52254
|
+
function injectSystem(parsed, opts, prompts = defaultPrompts) {
|
|
52005
52255
|
const baseText = extractSystem(parsed.system);
|
|
52006
52256
|
const parts = [];
|
|
52007
|
-
if (opts.compress.injectTool) parts.push(buildCompressSystemPrompt());
|
|
52257
|
+
if (opts.compress.injectTool) parts.push(buildCompressSystemPrompt(prompts));
|
|
52008
52258
|
if (parts.length === 0) return parsed.system;
|
|
52009
52259
|
const full = baseText ? `${baseText}
|
|
52010
52260
|
|
|
@@ -52083,8 +52333,10 @@ async function forward(req, res, opts, body, prepared, core, config, log2, route
|
|
|
52083
52333
|
}
|
|
52084
52334
|
}
|
|
52085
52335
|
const headers = {};
|
|
52336
|
+
const reqConnNamed = connectionNamedHeaders(req.headers["connection"]);
|
|
52086
52337
|
for (const [k2, v2] of Object.entries(req.headers)) {
|
|
52087
|
-
|
|
52338
|
+
const lower = k2.toLowerCase();
|
|
52339
|
+
if (UPSTREAM_HOP_HEADERS.has(lower) || reqConnNamed.has(lower) || v2 === void 0) continue;
|
|
52088
52340
|
headers[k2] = Array.isArray(v2) ? v2.join(", ") : v2;
|
|
52089
52341
|
}
|
|
52090
52342
|
headers["host"] = new URL(upstreamUrl).host;
|
|
@@ -52145,14 +52397,17 @@ ${bodyText}`);
|
|
|
52145
52397
|
}
|
|
52146
52398
|
const { response: upstream, clearTimer: clearUpstreamTimer } = upstreamResult;
|
|
52147
52399
|
const respHeaders = {};
|
|
52400
|
+
const respConnNamed = connectionNamedHeaders(upstream.headers.get("connection") ?? void 0);
|
|
52148
52401
|
upstream.headers.forEach((v2, k2) => {
|
|
52149
|
-
|
|
52402
|
+
const lower = k2.toLowerCase();
|
|
52403
|
+
if (UPSTREAM_HOP_HEADERS.has(lower) || respConnNamed.has(lower)) return;
|
|
52150
52404
|
respHeaders[k2] = v2;
|
|
52151
52405
|
});
|
|
52152
52406
|
if (opts.debug) {
|
|
52153
52407
|
const respLog = {};
|
|
52154
52408
|
upstream.headers.forEach((v2, k2) => {
|
|
52155
|
-
|
|
52409
|
+
const lower = k2.toLowerCase();
|
|
52410
|
+
if (UPSTREAM_HOP_HEADERS.has(lower) || respConnNamed.has(lower)) return;
|
|
52156
52411
|
respLog[k2] = v2.length > 300 ? v2.slice(0, 300) + "..." : v2;
|
|
52157
52412
|
});
|
|
52158
52413
|
log2("info", `[${prepared?.session.id ?? "unknown"}] \u2190 upstream response headers: ${JSON.stringify(respLog)}`);
|
|
@@ -52215,7 +52470,7 @@ ${hdrText}
|
|
|
52215
52470
|
const parsedReq = JSON.parse(typeof body === "string" ? body : body.toString("utf8"));
|
|
52216
52471
|
const reqHeaders = buildForwardHeaders(headers);
|
|
52217
52472
|
const textProtocol = prepared.protocol === "responses" && !!prepared.responsesTextProtocol;
|
|
52218
|
-
const systemPrompt = textProtocol ? buildCompressHybridSystemPrompt() : buildCompressSystemPrompt();
|
|
52473
|
+
const systemPrompt = textProtocol ? buildCompressHybridSystemPrompt(prepared.prompts ?? defaultPrompts) : buildCompressSystemPrompt(prepared.prompts ?? defaultPrompts);
|
|
52219
52474
|
const adapter = pickAdapter(prepared.protocol, parsedReq, textProtocol, prepared.responsesProjection, prepared.anthropicSystem);
|
|
52220
52475
|
const abortCtrl = new AbortController();
|
|
52221
52476
|
req.on("close", () => {
|
|
@@ -52422,6 +52677,7 @@ function logMsg(opts, level, msg2) {
|
|
|
52422
52677
|
|
|
52423
52678
|
// src/update.ts
|
|
52424
52679
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, access, constants, rm, cp, unlink } from "fs/promises";
|
|
52680
|
+
import crypto from "crypto";
|
|
52425
52681
|
|
|
52426
52682
|
// node_modules/tar/dist/esm/index.min.js
|
|
52427
52683
|
import Qr from "events";
|
|
@@ -55399,7 +55655,10 @@ var REGISTRY_BASE = "https://registry.npmjs.org";
|
|
|
55399
55655
|
var CHECK_INTERVAL_MS = 3 * 60 * 1e3;
|
|
55400
55656
|
var THROTTLE_FILE = path8.join(cacheDir(), ".update-check");
|
|
55401
55657
|
var LOCK_FILE = path8.join(cacheDir(), ".update-lock");
|
|
55402
|
-
var
|
|
55658
|
+
var LOCK_MAX_AGE_MS = 30 * 60 * 1e3;
|
|
55659
|
+
function shouldStealLock(holderAlive, ageMs) {
|
|
55660
|
+
return !holderAlive || ageMs >= LOCK_MAX_AGE_MS;
|
|
55661
|
+
}
|
|
55403
55662
|
var timer;
|
|
55404
55663
|
var inFlight = false;
|
|
55405
55664
|
var firstCheckDone = false;
|
|
@@ -55477,12 +55736,12 @@ async function tryAcquireLock() {
|
|
|
55477
55736
|
}
|
|
55478
55737
|
const existing = await readLock();
|
|
55479
55738
|
if (existing) {
|
|
55480
|
-
const age = now - existing.ts;
|
|
55481
55739
|
const holderAlive = isAlive(existing.pid);
|
|
55482
|
-
if (holderAlive
|
|
55740
|
+
if (!shouldStealLock(holderAlive, now - existing.ts)) {
|
|
55741
|
+
log("info", `[update] lock held by live pid=${existing.pid} (age=${Math.round((now - existing.ts) / 1e3)}s), skipping update`);
|
|
55483
55742
|
return null;
|
|
55484
55743
|
}
|
|
55485
|
-
log("info", `[update] stealing
|
|
55744
|
+
log("info", `[update] stealing lock from pid=${existing.pid} (alive=${holderAlive}, age=${Math.round((now - existing.ts) / 1e3)}s)`);
|
|
55486
55745
|
try {
|
|
55487
55746
|
await unlink(LOCK_FILE);
|
|
55488
55747
|
} catch (e) {
|
|
@@ -55556,6 +55815,8 @@ async function checkForUpdate(opts, force = false) {
|
|
|
55556
55815
|
return;
|
|
55557
55816
|
}
|
|
55558
55817
|
const tarballUrl = data.dist?.tarball;
|
|
55818
|
+
const integrity = data.dist?.integrity;
|
|
55819
|
+
const shasum = data.dist?.shasum;
|
|
55559
55820
|
if (!tarballUrl) {
|
|
55560
55821
|
log("warn", `[update] registry response for ${latest} had no tarball URL`);
|
|
55561
55822
|
return;
|
|
@@ -55567,7 +55828,7 @@ async function checkForUpdate(opts, force = false) {
|
|
|
55567
55828
|
return;
|
|
55568
55829
|
}
|
|
55569
55830
|
try {
|
|
55570
|
-
const result = await installViaTarball(latest, tarballUrl, installDir);
|
|
55831
|
+
const result = await installViaTarball(latest, tarballUrl, installDir, integrity, shasum);
|
|
55571
55832
|
if (result.ok) {
|
|
55572
55833
|
log("info", `[update] installed ${currentVersion} \u2192 ${latest}. Restart to finish.`);
|
|
55573
55834
|
} else {
|
|
@@ -55582,7 +55843,29 @@ async function checkForUpdate(opts, force = false) {
|
|
|
55582
55843
|
inFlight = false;
|
|
55583
55844
|
}
|
|
55584
55845
|
}
|
|
55585
|
-
|
|
55846
|
+
function verifyTarballIntegrity(buf, integrity, shasum) {
|
|
55847
|
+
if (integrity) {
|
|
55848
|
+
const dash = integrity.indexOf("-");
|
|
55849
|
+
if (dash <= 0) return { ok: false, error: "malformed integrity field" };
|
|
55850
|
+
const alg = integrity.slice(0, dash);
|
|
55851
|
+
const expected = integrity.slice(dash + 1);
|
|
55852
|
+
let actual;
|
|
55853
|
+
try {
|
|
55854
|
+
actual = crypto.createHash(alg).update(buf).digest("base64");
|
|
55855
|
+
} catch {
|
|
55856
|
+
return { ok: false, error: `unsupported integrity algorithm: ${alg}` };
|
|
55857
|
+
}
|
|
55858
|
+
if (actual !== expected) return { ok: false, error: `${alg} mismatch` };
|
|
55859
|
+
return { ok: true };
|
|
55860
|
+
}
|
|
55861
|
+
if (shasum) {
|
|
55862
|
+
const actual = crypto.createHash("sha1").update(buf).digest("hex");
|
|
55863
|
+
if (actual !== shasum) return { ok: false, error: "sha1 shasum mismatch" };
|
|
55864
|
+
return { ok: true };
|
|
55865
|
+
}
|
|
55866
|
+
return { ok: false, error: "no integrity or shasum from registry" };
|
|
55867
|
+
}
|
|
55868
|
+
async function installViaTarball(version2, tarballUrl, installDir, integrity, shasum) {
|
|
55586
55869
|
if (!installDir) {
|
|
55587
55870
|
return { ok: false, error: "cannot determine install directory (package.json not found walking up from running binary)" };
|
|
55588
55871
|
}
|
|
@@ -55621,6 +55904,10 @@ async function installViaTarball(version2, tarballUrl, installDir) {
|
|
|
55621
55904
|
} catch (e) {
|
|
55622
55905
|
return { ok: false, error: `tarball download failed: ${String(e)}` };
|
|
55623
55906
|
}
|
|
55907
|
+
const v2 = verifyTarballIntegrity(tgzBuffer, integrity, shasum);
|
|
55908
|
+
if (!v2.ok) {
|
|
55909
|
+
return { ok: false, error: `tarball integrity verification failed: ${v2.error}` };
|
|
55910
|
+
}
|
|
55624
55911
|
const tmpFile = path8.join(cacheDir(), `.update-${version2}.tgz`);
|
|
55625
55912
|
try {
|
|
55626
55913
|
await mkdir2(cacheDir(), { recursive: true });
|