billion-context 0.1.40 → 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 +436 -132
- 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;
|
|
@@ -48841,7 +48968,7 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
|
|
|
48841
48968
|
}
|
|
48842
48969
|
}
|
|
48843
48970
|
} else if (ev.kind === "tool_call") {
|
|
48844
|
-
calls.push({ name: ev.name, callId: ev.callId, arguments: ev.arguments });
|
|
48971
|
+
calls.push({ name: ev.name, callId: ev.callId, arguments: ev.arguments, passthrough: ev.passthrough });
|
|
48845
48972
|
} else if (ev.kind === "usage") {
|
|
48846
48973
|
usage = {
|
|
48847
48974
|
inputTokens: ev.inputTokens,
|
|
@@ -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({
|
|
@@ -48959,6 +49091,7 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
|
|
|
48959
49091
|
}
|
|
48960
49092
|
}
|
|
48961
49093
|
for (const tc of realToolCalls) {
|
|
49094
|
+
if (tc.passthrough) continue;
|
|
48962
49095
|
yield adapter.emitToolCall(tc);
|
|
48963
49096
|
}
|
|
48964
49097
|
const reRequest = proxyResults.length > 0 && realCalls === 0;
|
|
@@ -49201,13 +49334,18 @@ function createResponsesAdapter(textProtocol, projection) {
|
|
|
49201
49334
|
} else if (type === "response.output_item.added") {
|
|
49202
49335
|
const item = obj.item;
|
|
49203
49336
|
if (item?.type === "function_call") {
|
|
49204
|
-
const
|
|
49205
|
-
|
|
49206
|
-
itemId
|
|
49207
|
-
|
|
49208
|
-
|
|
49209
|
-
|
|
49210
|
-
|
|
49337
|
+
const fcName = typeof item.name === "string" ? item.name : "";
|
|
49338
|
+
if (PROXY_TOOL_NAMES.has(fcName)) {
|
|
49339
|
+
const itemId = typeof item.id === "string" ? item.id : "";
|
|
49340
|
+
pending.set(itemId, {
|
|
49341
|
+
itemId,
|
|
49342
|
+
callId: typeof item.call_id === "string" ? item.call_id : "",
|
|
49343
|
+
name: fcName,
|
|
49344
|
+
arguments: ""
|
|
49345
|
+
});
|
|
49346
|
+
} else {
|
|
49347
|
+
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
49348
|
+
}
|
|
49211
49349
|
} else if (item?.type === "custom_tool_call") {
|
|
49212
49350
|
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
49213
49351
|
} else if (item?.type !== "message" || !suppressTextLifecycle) {
|
|
@@ -49227,11 +49365,13 @@ function createResponsesAdapter(textProtocol, projection) {
|
|
|
49227
49365
|
const delta = typeof obj.delta === "string" ? obj.delta : "";
|
|
49228
49366
|
const fc = pending.get(itemId);
|
|
49229
49367
|
if (fc) fc.arguments += delta;
|
|
49368
|
+
else yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
49230
49369
|
} else if (type === "response.function_call_arguments.done") {
|
|
49231
49370
|
const itemId = typeof obj.item_id === "string" ? obj.item_id : "";
|
|
49232
49371
|
const args = typeof obj.arguments === "string" ? obj.arguments : "";
|
|
49233
49372
|
const fc = pending.get(itemId);
|
|
49234
49373
|
if (fc && args) fc.arguments = args;
|
|
49374
|
+
else yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
49235
49375
|
} else if (type === "response.output_item.done") {
|
|
49236
49376
|
const item = obj.item;
|
|
49237
49377
|
if (item?.type === "function_call") {
|
|
@@ -49246,6 +49386,15 @@ function createResponsesAdapter(textProtocol, projection) {
|
|
|
49246
49386
|
callId: fc.callId,
|
|
49247
49387
|
arguments: fc.arguments
|
|
49248
49388
|
};
|
|
49389
|
+
} else {
|
|
49390
|
+
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
49391
|
+
yield {
|
|
49392
|
+
kind: "tool_call",
|
|
49393
|
+
name: typeof item.name === "string" ? item.name : "",
|
|
49394
|
+
callId: typeof item.call_id === "string" ? item.call_id : "",
|
|
49395
|
+
arguments: typeof item.arguments === "string" ? item.arguments : "",
|
|
49396
|
+
passthrough: true
|
|
49397
|
+
};
|
|
49249
49398
|
}
|
|
49250
49399
|
} else if (item?.type === "custom_tool_call") {
|
|
49251
49400
|
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
@@ -49757,6 +49906,7 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49757
49906
|
let stopReason;
|
|
49758
49907
|
let usageYielded = false;
|
|
49759
49908
|
const indexMap = /* @__PURE__ */ new Map();
|
|
49909
|
+
const thinkingIndexes = /* @__PURE__ */ new Set();
|
|
49760
49910
|
for await (const eventStr of iterSseEvents2(upstream)) {
|
|
49761
49911
|
const parsed = parseAnthropicSse(eventStr);
|
|
49762
49912
|
if (!parsed) continue;
|
|
@@ -49781,6 +49931,7 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49781
49931
|
const id = typeof block.id === "string" ? block.id : `toolu_${upstreamIndex}`;
|
|
49782
49932
|
pending.set(upstreamIndex, { id, name, json: "" });
|
|
49783
49933
|
} else {
|
|
49934
|
+
if (block.type === "thinking" || block.type === "redacted_thinking") thinkingIndexes.add(upstreamIndex);
|
|
49784
49935
|
const ci2 = clientIndex++;
|
|
49785
49936
|
indexMap.set(upstreamIndex, ci2);
|
|
49786
49937
|
yield { kind: "meta", chunk: remapIndexInEvent(eventStr, ci2), firstRoundOnly: round === 1 };
|
|
@@ -49795,6 +49946,21 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49795
49946
|
} else if (delta.type === "text_delta" && typeof delta.text === "string") {
|
|
49796
49947
|
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49797
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
|
+
};
|
|
49798
49964
|
} else if (round === 1) {
|
|
49799
49965
|
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49800
49966
|
yield { kind: "meta", chunk: remapIndexInEvent(eventStr, ci2), firstRoundOnly: true };
|
|
@@ -49810,6 +49976,12 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49810
49976
|
callId: tb.id,
|
|
49811
49977
|
arguments: tb.json
|
|
49812
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 };
|
|
49813
49985
|
} else {
|
|
49814
49986
|
const ci2 = indexMap.get(upstreamIndex) ?? upstreamIndex;
|
|
49815
49987
|
yield { kind: "meta", chunk: remapIndexInEvent(eventStr, ci2), firstRoundOnly: round === 1 };
|
|
@@ -49850,6 +50022,22 @@ ${systemPrompt}` : systemPrompt;
|
|
|
49850
50022
|
emitText(delta) {
|
|
49851
50023
|
return buildTextBlock(clientIndex++, delta);
|
|
49852
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
|
+
},
|
|
49853
50041
|
emitToolCall(call) {
|
|
49854
50042
|
return buildToolUseBlock(clientIndex++, call);
|
|
49855
50043
|
},
|
|
@@ -50095,7 +50283,6 @@ ${note}` : note;
|
|
|
50095
50283
|
}
|
|
50096
50284
|
|
|
50097
50285
|
// src/stream-responses.ts
|
|
50098
|
-
var TEXT_PROTOCOL = process.env.ACP_COMPRESS_PROTOCOL === "text";
|
|
50099
50286
|
function rewriteResponsesJsonResponse(body, ctx) {
|
|
50100
50287
|
if (!body || typeof body !== "object") return body;
|
|
50101
50288
|
const b2 = body;
|
|
@@ -50148,12 +50335,35 @@ function emitStreamError(res, protocol, message, log2) {
|
|
|
50148
50335
|
`);
|
|
50149
50336
|
safeWrite(res, "data: [DONE]\n\n");
|
|
50150
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
|
+
`);
|
|
50151
50349
|
safeWrite(res, `event: response.output_text.delta
|
|
50152
|
-
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 })}
|
|
50153
50363
|
|
|
50154
50364
|
`);
|
|
50155
50365
|
safeWrite(res, `event: response.completed
|
|
50156
|
-
data: ${JSON.stringify({ type: "response.completed", response: { status: "completed", output: [] } })}
|
|
50366
|
+
data: ${JSON.stringify({ type: "response.completed", response: { status: "completed", output: [errorItem] } })}
|
|
50157
50367
|
|
|
50158
50368
|
`);
|
|
50159
50369
|
} else {
|
|
@@ -50220,6 +50430,7 @@ var rootKeyPem;
|
|
|
50220
50430
|
var rootCert;
|
|
50221
50431
|
var rootKey;
|
|
50222
50432
|
var secureContextCache = /* @__PURE__ */ new Map();
|
|
50433
|
+
var SECURE_CONTEXT_CACHE_MAX = 64;
|
|
50223
50434
|
function generateRootCA() {
|
|
50224
50435
|
const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
|
|
50225
50436
|
const cert = import_node_forge.default.pki.createCertificate();
|
|
@@ -50271,7 +50482,11 @@ function getSecureContext(host) {
|
|
|
50271
50482
|
throw new Error("CA not initialized \u2014 call ensureRootCA() first");
|
|
50272
50483
|
}
|
|
50273
50484
|
const cached = secureContextCache.get(host);
|
|
50274
|
-
if (cached)
|
|
50485
|
+
if (cached) {
|
|
50486
|
+
secureContextCache.delete(host);
|
|
50487
|
+
secureContextCache.set(host, cached);
|
|
50488
|
+
return cached;
|
|
50489
|
+
}
|
|
50275
50490
|
const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
|
|
50276
50491
|
const cert = import_node_forge.default.pki.createCertificate();
|
|
50277
50492
|
cert.publicKey = keys.publicKey;
|
|
@@ -50294,6 +50509,10 @@ function getSecureContext(host) {
|
|
|
50294
50509
|
ca: rootCertPem
|
|
50295
50510
|
});
|
|
50296
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
|
+
}
|
|
50297
50516
|
return ctx;
|
|
50298
50517
|
}
|
|
50299
50518
|
|
|
@@ -50527,6 +50746,11 @@ var DEFAULT_MITM_DOMAINS = [
|
|
|
50527
50746
|
"chatgpt.com"
|
|
50528
50747
|
];
|
|
50529
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
|
+
}
|
|
50530
50754
|
function isMitmHost(host, extraDomains = []) {
|
|
50531
50755
|
const h = host.toLowerCase();
|
|
50532
50756
|
const all = [...DEFAULT_MITM_DOMAINS, ...extraDomains, ...discoverMitmDomains()].map((d) => d.toLowerCase());
|
|
@@ -50536,12 +50760,12 @@ function setupMitm(server, extraDomains = [], log2 = () => {
|
|
|
50536
50760
|
}, resolveProxyUrl) {
|
|
50537
50761
|
ensureRootCA();
|
|
50538
50762
|
server.on("connect", (req, clientSocket, head) => {
|
|
50539
|
-
|
|
50540
|
-
|
|
50541
|
-
clientSocket.
|
|
50542
|
-
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");
|
|
50543
50766
|
return;
|
|
50544
50767
|
}
|
|
50768
|
+
const { hostname, port } = parseHostPort(req.url ?? "");
|
|
50545
50769
|
const targetPort = port || 443;
|
|
50546
50770
|
if (!isMitmHost(hostname, extraDomains)) {
|
|
50547
50771
|
const proxyUrl = resolveProxyUrl?.(hostname);
|
|
@@ -50561,14 +50785,20 @@ function parseHostPort(s3) {
|
|
|
50561
50785
|
}
|
|
50562
50786
|
function tunnelThrough(clientSocket, host, port, head, log2, proxyUrl) {
|
|
50563
50787
|
let established = false;
|
|
50788
|
+
let aborted = false;
|
|
50564
50789
|
const connectTimer = setTimeout(() => {
|
|
50565
50790
|
if (!established) {
|
|
50791
|
+
aborted = true;
|
|
50566
50792
|
log2(`tunnel ${host}:${port} connect timeout`);
|
|
50567
50793
|
clientSocket.write("HTTP/1.1 504 Gateway Timeout\r\n\r\n");
|
|
50568
50794
|
clientSocket.destroy();
|
|
50569
50795
|
}
|
|
50570
50796
|
}, 15e3);
|
|
50571
50797
|
connectThroughProxy(host, port, proxyUrl).then((upstream) => {
|
|
50798
|
+
if (aborted) {
|
|
50799
|
+
upstream.destroy();
|
|
50800
|
+
return;
|
|
50801
|
+
}
|
|
50572
50802
|
established = true;
|
|
50573
50803
|
clearTimeout(connectTimer);
|
|
50574
50804
|
clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
@@ -50583,6 +50813,7 @@ function tunnelThrough(clientSocket, host, port, head, log2, proxyUrl) {
|
|
|
50583
50813
|
upstream.once("error", (e) => cleanup("upstream", e));
|
|
50584
50814
|
clientSocket.once("error", (e) => cleanup("client", e));
|
|
50585
50815
|
}).catch((err2) => {
|
|
50816
|
+
if (aborted) return;
|
|
50586
50817
|
clearTimeout(connectTimer);
|
|
50587
50818
|
log2(`tunnel ${host}:${port} connect failed: ${err2.message}`);
|
|
50588
50819
|
clientSocket.write("HTTP/1.1 502 Bad Gateway\r\n\r\n");
|
|
@@ -50612,6 +50843,14 @@ function doMitm(server, clientSocket, host, port, head, log2) {
|
|
|
50612
50843
|
tlsSocket.destroy();
|
|
50613
50844
|
clientSocket.destroy();
|
|
50614
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));
|
|
50615
50854
|
server.emit("connection", tlsSocket);
|
|
50616
50855
|
log2(`mitm ${host}:${port} tunnel established (TLS terminated locally)`);
|
|
50617
50856
|
}
|
|
@@ -51347,8 +51586,28 @@ var UPSTREAM_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
|
51347
51586
|
// Node's fetch transparently decodes compressed responses. Do not
|
|
51348
51587
|
// forward the upstream encoding marker when the body is rewritten or
|
|
51349
51588
|
// streamed from fetch, otherwise clients try to decompress plain bytes.
|
|
51350
|
-
"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"
|
|
51351
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
|
+
}
|
|
51352
51611
|
function buildForwardHeaders(headers) {
|
|
51353
51612
|
const out = {};
|
|
51354
51613
|
for (const [k2, v2] of Object.entries(headers)) {
|
|
@@ -51468,28 +51727,38 @@ async function startServer(opts) {
|
|
|
51468
51727
|
}
|
|
51469
51728
|
return server;
|
|
51470
51729
|
}
|
|
51471
|
-
function
|
|
51472
|
-
if (!
|
|
51473
|
-
return addr === "::1" || addr === "127.0.0.1" || addr.startsWith("127.") || addr.startsWith("::ffff:127.");
|
|
51474
|
-
}
|
|
51475
|
-
function isTrustedAdminOrigin(origin, host) {
|
|
51730
|
+
function isTrustedAdminOrigin(origin, host, trustedHosts) {
|
|
51731
|
+
if (!host || !trustedHosts.has(host.toLowerCase())) return false;
|
|
51476
51732
|
if (!origin) return true;
|
|
51477
|
-
if (!host) return false;
|
|
51478
51733
|
try {
|
|
51479
51734
|
const parsed = new URL(origin);
|
|
51480
|
-
|
|
51735
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
|
|
51736
|
+
return trustedHosts.has(parsed.host.toLowerCase());
|
|
51481
51737
|
} catch {
|
|
51482
51738
|
return false;
|
|
51483
51739
|
}
|
|
51484
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
|
+
}
|
|
51485
51754
|
async function handle(req, res, opts, core, config, log2) {
|
|
51486
51755
|
const isAdminPath = req.url === "/__bili/" || req.url?.startsWith("/__bili/") || req.url === "/__acp/" || req.url?.startsWith("/__acp/");
|
|
51487
|
-
if (isAdminPath && !
|
|
51756
|
+
if (isAdminPath && !isLoopbackAddress(req.socket.remoteAddress)) {
|
|
51488
51757
|
res.writeHead(403, { "content-type": "application/json" });
|
|
51489
51758
|
res.end(JSON.stringify({ error: "management endpoints are loopback-only; access denied for " + (req.socket.remoteAddress ?? "unknown") }));
|
|
51490
51759
|
return;
|
|
51491
51760
|
}
|
|
51492
|
-
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))) {
|
|
51493
51762
|
res.writeHead(403, { "content-type": "application/json" });
|
|
51494
51763
|
res.end(JSON.stringify({ error: "management request origin does not match the local bili UI" }));
|
|
51495
51764
|
return;
|
|
@@ -51643,11 +51912,11 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51643
51912
|
}
|
|
51644
51913
|
}
|
|
51645
51914
|
let reqConfig = config;
|
|
51915
|
+
let reqPrompts = defaultPrompts;
|
|
51646
51916
|
if (parsed && typeof parsed === "object") {
|
|
51647
51917
|
const model = parsed.model;
|
|
51648
51918
|
if (model) {
|
|
51649
51919
|
const embeddedUrl = route?.rewrittenUrl;
|
|
51650
|
-
const compress = resolveCompress(opts.routes, embeddedUrl, model, opts.compress);
|
|
51651
51920
|
let native = resolveContextLimit(opts.routes, embeddedUrl, model);
|
|
51652
51921
|
if (!native && embeddedUrl) {
|
|
51653
51922
|
const host = (() => {
|
|
@@ -51659,11 +51928,8 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51659
51928
|
})();
|
|
51660
51929
|
native = await contextFromRegistry(model, host);
|
|
51661
51930
|
}
|
|
51662
|
-
|
|
51663
|
-
|
|
51664
|
-
if (tuned || limit !== config.modelContextLimit) {
|
|
51665
|
-
reqConfig = applyCompressSettings(config, limit, compress);
|
|
51666
|
-
}
|
|
51931
|
+
reqConfig = resolveRequestConfig(config, opts.routes, embeddedUrl, model, native, opts.compress);
|
|
51932
|
+
reqPrompts = resolveCompressPrompts(resolveCompress(opts.routes, embeddedUrl, model, opts.compress));
|
|
51667
51933
|
}
|
|
51668
51934
|
}
|
|
51669
51935
|
let prepared = null;
|
|
@@ -51684,7 +51950,7 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51684
51950
|
acquireInFlight(session);
|
|
51685
51951
|
try {
|
|
51686
51952
|
await withSessionLock(session, async () => {
|
|
51687
|
-
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);
|
|
51688
51954
|
await forward(req, res, opts, prepared.body, prepared, core, reqConfig, log2, route, affinity);
|
|
51689
51955
|
});
|
|
51690
51956
|
} finally {
|
|
@@ -51726,7 +51992,7 @@ function diagNudge(turn, sessionId, tokenCount, limit) {
|
|
|
51726
51992
|
const inject = n.shouldInject ? `INJECT T${n.tier ?? "?"}` : "idle";
|
|
51727
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)}"`;
|
|
51728
51994
|
}
|
|
51729
|
-
function prepareAnthropic(parsed, req, opts, core, config, log2, session) {
|
|
51995
|
+
function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, session) {
|
|
51730
51996
|
const sessionId = session.id;
|
|
51731
51997
|
const stream2 = parsed.stream === true;
|
|
51732
51998
|
++session.stats.requests;
|
|
@@ -51754,13 +52020,13 @@ function prepareAnthropic(parsed, req, opts, core, config, log2, session) {
|
|
|
51754
52020
|
processedMessages = stripKernelSummaries(turn.messages);
|
|
51755
52021
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
51756
52022
|
rebuiltMessages = coreToAnthropic(processedMessages, cacheControls);
|
|
51757
|
-
systemOut = injectSystem(parsed, opts);
|
|
52023
|
+
systemOut = injectSystem(parsed, opts, prompts);
|
|
51758
52024
|
if (opts.compress.injectTool) {
|
|
51759
52025
|
toolsOut = injectTool(parsed.tools);
|
|
51760
52026
|
}
|
|
51761
52027
|
if (opts.compress.injectNudge && turn.nudge?.shouldInject) {
|
|
51762
52028
|
try {
|
|
51763
|
-
const rendered = renderNudgeText(turn.nudge);
|
|
52029
|
+
const rendered = renderNudgeText(turn.nudge, prompts);
|
|
51764
52030
|
if (rendered.text) {
|
|
51765
52031
|
rebuiltMessages = [...rebuiltMessages, { role: "user", content: rendered.text }];
|
|
51766
52032
|
}
|
|
@@ -51771,11 +52037,11 @@ function prepareAnthropic(parsed, req, opts, core, config, log2, session) {
|
|
|
51771
52037
|
log2("warn", `[${sessionId}] kernel transform failed, forwarding unchanged: ${String(err2)}`);
|
|
51772
52038
|
processedMessages = [];
|
|
51773
52039
|
}
|
|
51774
|
-
const rebuilt = { ...parsed, messages: rebuiltMessages, system: systemOut, tools: toolsOut };
|
|
51775
52040
|
markDirty(session);
|
|
51776
|
-
|
|
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 };
|
|
51777
52043
|
}
|
|
51778
|
-
function prepareOpenai(parsed, req, opts, core, config, log2, session) {
|
|
52044
|
+
function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session) {
|
|
51779
52045
|
const sessionId = session.id;
|
|
51780
52046
|
const stream2 = parsed.stream === true;
|
|
51781
52047
|
++session.stats.requests;
|
|
@@ -51805,14 +52071,14 @@ function prepareOpenai(parsed, req, opts, core, config, log2, session) {
|
|
|
51805
52071
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
51806
52072
|
rebuiltMessages = coreToOpenai(processedMessages);
|
|
51807
52073
|
const sysParts = [];
|
|
51808
|
-
if (shouldInject) sysParts.push(buildCompressSystemPrompt());
|
|
52074
|
+
if (shouldInject) sysParts.push(buildCompressSystemPrompt(prompts));
|
|
51809
52075
|
rebuiltMessages = injectOpenaiSystem(rebuiltMessages, sysParts);
|
|
51810
52076
|
if (shouldInject) {
|
|
51811
52077
|
toolsOut = injectOpenaiTool(parsed.tools);
|
|
51812
52078
|
}
|
|
51813
52079
|
if (opts.compress.injectNudge && turn.nudge?.shouldInject && shouldInject) {
|
|
51814
52080
|
try {
|
|
51815
|
-
const rendered = renderNudgeText(turn.nudge);
|
|
52081
|
+
const rendered = renderNudgeText(turn.nudge, prompts);
|
|
51816
52082
|
if (rendered.text) {
|
|
51817
52083
|
rebuiltMessages = [...rebuiltMessages, { role: "user", content: rendered.text }];
|
|
51818
52084
|
}
|
|
@@ -51828,9 +52094,9 @@ function prepareOpenai(parsed, req, opts, core, config, log2, session) {
|
|
|
51828
52094
|
rebuilt.stream_options = { include_usage: true };
|
|
51829
52095
|
}
|
|
51830
52096
|
markDirty(session);
|
|
51831
|
-
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 };
|
|
51832
52098
|
}
|
|
51833
|
-
function prepareResponses(parsed, req, opts, core, config, log2, session, identity) {
|
|
52099
|
+
function prepareResponses(parsed, req, opts, core, config, prompts, log2, session, identity) {
|
|
51834
52100
|
const sessionId = session.id;
|
|
51835
52101
|
const stream2 = parsed.stream === true;
|
|
51836
52102
|
++session.stats.requests;
|
|
@@ -51868,7 +52134,7 @@ function prepareResponses(parsed, req, opts, core, config, log2, session, identi
|
|
|
51868
52134
|
reapOrphanBlocks(session, msgs, deactivateBlock);
|
|
51869
52135
|
rebuiltInput = patchResponsesInput(projection, processedMessages);
|
|
51870
52136
|
if (shouldInject && !process.env.ACP_NO_COMPRESS_PROMPT) {
|
|
51871
|
-
const prompt = responsesTextProtocol ? buildCompressHybridSystemPrompt() : buildCompressSystemPrompt();
|
|
52137
|
+
const prompt = responsesTextProtocol ? buildCompressHybridSystemPrompt(prompts) : buildCompressSystemPrompt(prompts);
|
|
51872
52138
|
const devContent = [...projection.systemParts, prompt].join("\n\n---\n\n");
|
|
51873
52139
|
rebuiltInput = injectResponsesDeveloperMessage(rebuiltInput, devContent);
|
|
51874
52140
|
if (!process.env.ACP_NO_INJECT_TOOL) {
|
|
@@ -51879,7 +52145,7 @@ function prepareResponses(parsed, req, opts, core, config, log2, session, identi
|
|
|
51879
52145
|
}
|
|
51880
52146
|
if (opts.compress.injectNudge && turn.nudge?.shouldInject && shouldInject) {
|
|
51881
52147
|
try {
|
|
51882
|
-
const rendered = renderNudgeText(turn.nudge);
|
|
52148
|
+
const rendered = renderNudgeText(turn.nudge, prompts);
|
|
51883
52149
|
if (rendered.text) {
|
|
51884
52150
|
const inputItems = typeof rebuiltInput === "string" ? [{ type: "message", role: "user", content: rebuiltInput }] : rebuiltInput;
|
|
51885
52151
|
inputItems.push({ type: "message", role: "user", content: rendered.text });
|
|
@@ -51921,7 +52187,8 @@ function prepareResponses(parsed, req, opts, core, config, log2, session, identi
|
|
|
51921
52187
|
stream: stream2,
|
|
51922
52188
|
compressInjected: shouldInject,
|
|
51923
52189
|
responsesTextProtocol,
|
|
51924
|
-
nudge
|
|
52190
|
+
nudge,
|
|
52191
|
+
prompts
|
|
51925
52192
|
};
|
|
51926
52193
|
}
|
|
51927
52194
|
function isCountTokensRequest(method, urlPath, hasBody) {
|
|
@@ -51984,10 +52251,10 @@ function resolvePromptCacheKey(explicit, identity, routing, upstream) {
|
|
|
51984
52251
|
if (!identity.clientProvided || !shouldInjectPromptCacheKey(routing, upstream)) return void 0;
|
|
51985
52252
|
return identity.value;
|
|
51986
52253
|
}
|
|
51987
|
-
function injectSystem(parsed, opts) {
|
|
52254
|
+
function injectSystem(parsed, opts, prompts = defaultPrompts) {
|
|
51988
52255
|
const baseText = extractSystem(parsed.system);
|
|
51989
52256
|
const parts = [];
|
|
51990
|
-
if (opts.compress.injectTool) parts.push(buildCompressSystemPrompt());
|
|
52257
|
+
if (opts.compress.injectTool) parts.push(buildCompressSystemPrompt(prompts));
|
|
51991
52258
|
if (parts.length === 0) return parsed.system;
|
|
51992
52259
|
const full = baseText ? `${baseText}
|
|
51993
52260
|
|
|
@@ -52066,8 +52333,10 @@ async function forward(req, res, opts, body, prepared, core, config, log2, route
|
|
|
52066
52333
|
}
|
|
52067
52334
|
}
|
|
52068
52335
|
const headers = {};
|
|
52336
|
+
const reqConnNamed = connectionNamedHeaders(req.headers["connection"]);
|
|
52069
52337
|
for (const [k2, v2] of Object.entries(req.headers)) {
|
|
52070
|
-
|
|
52338
|
+
const lower = k2.toLowerCase();
|
|
52339
|
+
if (UPSTREAM_HOP_HEADERS.has(lower) || reqConnNamed.has(lower) || v2 === void 0) continue;
|
|
52071
52340
|
headers[k2] = Array.isArray(v2) ? v2.join(", ") : v2;
|
|
52072
52341
|
}
|
|
52073
52342
|
headers["host"] = new URL(upstreamUrl).host;
|
|
@@ -52128,14 +52397,17 @@ ${bodyText}`);
|
|
|
52128
52397
|
}
|
|
52129
52398
|
const { response: upstream, clearTimer: clearUpstreamTimer } = upstreamResult;
|
|
52130
52399
|
const respHeaders = {};
|
|
52400
|
+
const respConnNamed = connectionNamedHeaders(upstream.headers.get("connection") ?? void 0);
|
|
52131
52401
|
upstream.headers.forEach((v2, k2) => {
|
|
52132
|
-
|
|
52402
|
+
const lower = k2.toLowerCase();
|
|
52403
|
+
if (UPSTREAM_HOP_HEADERS.has(lower) || respConnNamed.has(lower)) return;
|
|
52133
52404
|
respHeaders[k2] = v2;
|
|
52134
52405
|
});
|
|
52135
52406
|
if (opts.debug) {
|
|
52136
52407
|
const respLog = {};
|
|
52137
52408
|
upstream.headers.forEach((v2, k2) => {
|
|
52138
|
-
|
|
52409
|
+
const lower = k2.toLowerCase();
|
|
52410
|
+
if (UPSTREAM_HOP_HEADERS.has(lower) || respConnNamed.has(lower)) return;
|
|
52139
52411
|
respLog[k2] = v2.length > 300 ? v2.slice(0, 300) + "..." : v2;
|
|
52140
52412
|
});
|
|
52141
52413
|
log2("info", `[${prepared?.session.id ?? "unknown"}] \u2190 upstream response headers: ${JSON.stringify(respLog)}`);
|
|
@@ -52198,7 +52470,7 @@ ${hdrText}
|
|
|
52198
52470
|
const parsedReq = JSON.parse(typeof body === "string" ? body : body.toString("utf8"));
|
|
52199
52471
|
const reqHeaders = buildForwardHeaders(headers);
|
|
52200
52472
|
const textProtocol = prepared.protocol === "responses" && !!prepared.responsesTextProtocol;
|
|
52201
|
-
const systemPrompt = textProtocol ? buildCompressHybridSystemPrompt() : buildCompressSystemPrompt();
|
|
52473
|
+
const systemPrompt = textProtocol ? buildCompressHybridSystemPrompt(prepared.prompts ?? defaultPrompts) : buildCompressSystemPrompt(prepared.prompts ?? defaultPrompts);
|
|
52202
52474
|
const adapter = pickAdapter(prepared.protocol, parsedReq, textProtocol, prepared.responsesProjection, prepared.anthropicSystem);
|
|
52203
52475
|
const abortCtrl = new AbortController();
|
|
52204
52476
|
req.on("close", () => {
|
|
@@ -52405,6 +52677,7 @@ function logMsg(opts, level, msg2) {
|
|
|
52405
52677
|
|
|
52406
52678
|
// src/update.ts
|
|
52407
52679
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, access, constants, rm, cp, unlink } from "fs/promises";
|
|
52680
|
+
import crypto from "crypto";
|
|
52408
52681
|
|
|
52409
52682
|
// node_modules/tar/dist/esm/index.min.js
|
|
52410
52683
|
import Qr from "events";
|
|
@@ -55382,7 +55655,10 @@ var REGISTRY_BASE = "https://registry.npmjs.org";
|
|
|
55382
55655
|
var CHECK_INTERVAL_MS = 3 * 60 * 1e3;
|
|
55383
55656
|
var THROTTLE_FILE = path8.join(cacheDir(), ".update-check");
|
|
55384
55657
|
var LOCK_FILE = path8.join(cacheDir(), ".update-lock");
|
|
55385
|
-
var
|
|
55658
|
+
var LOCK_MAX_AGE_MS = 30 * 60 * 1e3;
|
|
55659
|
+
function shouldStealLock(holderAlive, ageMs) {
|
|
55660
|
+
return !holderAlive || ageMs >= LOCK_MAX_AGE_MS;
|
|
55661
|
+
}
|
|
55386
55662
|
var timer;
|
|
55387
55663
|
var inFlight = false;
|
|
55388
55664
|
var firstCheckDone = false;
|
|
@@ -55460,12 +55736,12 @@ async function tryAcquireLock() {
|
|
|
55460
55736
|
}
|
|
55461
55737
|
const existing = await readLock();
|
|
55462
55738
|
if (existing) {
|
|
55463
|
-
const age = now - existing.ts;
|
|
55464
55739
|
const holderAlive = isAlive(existing.pid);
|
|
55465
|
-
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`);
|
|
55466
55742
|
return null;
|
|
55467
55743
|
}
|
|
55468
|
-
log("info", `[update] stealing
|
|
55744
|
+
log("info", `[update] stealing lock from pid=${existing.pid} (alive=${holderAlive}, age=${Math.round((now - existing.ts) / 1e3)}s)`);
|
|
55469
55745
|
try {
|
|
55470
55746
|
await unlink(LOCK_FILE);
|
|
55471
55747
|
} catch (e) {
|
|
@@ -55539,6 +55815,8 @@ async function checkForUpdate(opts, force = false) {
|
|
|
55539
55815
|
return;
|
|
55540
55816
|
}
|
|
55541
55817
|
const tarballUrl = data.dist?.tarball;
|
|
55818
|
+
const integrity = data.dist?.integrity;
|
|
55819
|
+
const shasum = data.dist?.shasum;
|
|
55542
55820
|
if (!tarballUrl) {
|
|
55543
55821
|
log("warn", `[update] registry response for ${latest} had no tarball URL`);
|
|
55544
55822
|
return;
|
|
@@ -55550,7 +55828,7 @@ async function checkForUpdate(opts, force = false) {
|
|
|
55550
55828
|
return;
|
|
55551
55829
|
}
|
|
55552
55830
|
try {
|
|
55553
|
-
const result = await installViaTarball(latest, tarballUrl, installDir);
|
|
55831
|
+
const result = await installViaTarball(latest, tarballUrl, installDir, integrity, shasum);
|
|
55554
55832
|
if (result.ok) {
|
|
55555
55833
|
log("info", `[update] installed ${currentVersion} \u2192 ${latest}. Restart to finish.`);
|
|
55556
55834
|
} else {
|
|
@@ -55565,7 +55843,29 @@ async function checkForUpdate(opts, force = false) {
|
|
|
55565
55843
|
inFlight = false;
|
|
55566
55844
|
}
|
|
55567
55845
|
}
|
|
55568
|
-
|
|
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) {
|
|
55569
55869
|
if (!installDir) {
|
|
55570
55870
|
return { ok: false, error: "cannot determine install directory (package.json not found walking up from running binary)" };
|
|
55571
55871
|
}
|
|
@@ -55604,6 +55904,10 @@ async function installViaTarball(version2, tarballUrl, installDir) {
|
|
|
55604
55904
|
} catch (e) {
|
|
55605
55905
|
return { ok: false, error: `tarball download failed: ${String(e)}` };
|
|
55606
55906
|
}
|
|
55907
|
+
const v2 = verifyTarballIntegrity(tgzBuffer, integrity, shasum);
|
|
55908
|
+
if (!v2.ok) {
|
|
55909
|
+
return { ok: false, error: `tarball integrity verification failed: ${v2.error}` };
|
|
55910
|
+
}
|
|
55607
55911
|
const tmpFile = path8.join(cacheDir(), `.update-${version2}.tgz`);
|
|
55608
55912
|
try {
|
|
55609
55913
|
await mkdir2(cacheDir(), { recursive: true });
|