billion-context 0.1.84 → 0.1.85
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/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/agent/omp.js +73 -1
- package/dist/agent/omp.js.map +1 -1
- package/dist/agent/pi.js +73 -1
- package/dist/agent/pi.js.map +1 -1
- package/dist/index.js +213 -406
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -44164,6 +44164,9 @@ function validateConfig(config) {
|
|
|
44164
44164
|
"nudge.maxContextLimitPct must not exceed nudge.emergencyThresholdPct"
|
|
44165
44165
|
);
|
|
44166
44166
|
}
|
|
44167
|
+
if (config.nudge.minPressureBenefitTokens !== void 0 && (!Number.isFinite(config.nudge.minPressureBenefitTokens) || config.nudge.minPressureBenefitTokens < 0)) {
|
|
44168
|
+
errors.push("nudge.minPressureBenefitTokens must be finite and >= 0");
|
|
44169
|
+
}
|
|
44167
44170
|
if (config.promotionThreshold < 1) {
|
|
44168
44171
|
errors.push("promotionThreshold must be >= 1");
|
|
44169
44172
|
}
|
|
@@ -46021,6 +46024,9 @@ function resolveAdaptiveGrowth(modelContextLimit, nudge) {
|
|
|
46021
46024
|
)
|
|
46022
46025
|
);
|
|
46023
46026
|
}
|
|
46027
|
+
function resolveMinPressureBenefit(modelContextLimit, nudge) {
|
|
46028
|
+
return nudge.minPressureBenefitTokens ?? Math.max(5e3, Math.round(modelContextLimit * 0.01));
|
|
46029
|
+
}
|
|
46024
46030
|
function pendingByTier(state, recommendation, countTokens, minCompressRange) {
|
|
46025
46031
|
const out = {};
|
|
46026
46032
|
const merged = recommendation?.recommendedRanges ?? [];
|
|
@@ -46047,6 +46053,7 @@ function decideNudge(input) {
|
|
|
46047
46053
|
const limit = config.modelContextLimit;
|
|
46048
46054
|
const usage = limit > 0 ? tokenCount / limit : 0;
|
|
46049
46055
|
const nudgeGrowthTokens = resolveAdaptiveGrowth(limit, config.nudge);
|
|
46056
|
+
const minPressureBenefit = resolveMinPressureBenefit(limit, config.nudge);
|
|
46050
46057
|
const overLimit = usage >= config.nudge.maxContextLimitPct;
|
|
46051
46058
|
const emergencyOverride = usage >= config.nudge.emergencyThresholdPct;
|
|
46052
46059
|
const pressure = overLimit || emergencyOverride;
|
|
@@ -46072,6 +46079,7 @@ function decideNudge(input) {
|
|
|
46072
46079
|
);
|
|
46073
46080
|
let injectedTier = null;
|
|
46074
46081
|
let injectedReason = "";
|
|
46082
|
+
let bestPending = 0;
|
|
46075
46083
|
const t1Eff = tiers[1]?.pending ?? 0;
|
|
46076
46084
|
const t2Pen = tiers[2]?.pending ?? 0;
|
|
46077
46085
|
const t3Pen = tiers[3]?.pending ?? 0;
|
|
@@ -46085,7 +46093,6 @@ function decideNudge(input) {
|
|
|
46085
46093
|
candidates.push(2, 3);
|
|
46086
46094
|
}
|
|
46087
46095
|
let best = null;
|
|
46088
|
-
let bestPending = 0;
|
|
46089
46096
|
for (const t of candidates) {
|
|
46090
46097
|
const p2 = tiers[t]?.pending ?? 0;
|
|
46091
46098
|
if (p2 > bestPending) {
|
|
@@ -46093,7 +46100,7 @@ function decideNudge(input) {
|
|
|
46093
46100
|
best = t;
|
|
46094
46101
|
}
|
|
46095
46102
|
}
|
|
46096
|
-
if (best !== null && bestPending
|
|
46103
|
+
if (best !== null && bestPending >= minPressureBenefit) {
|
|
46097
46104
|
injectedTier = best;
|
|
46098
46105
|
const label = emergencyOverride ? "EMERGENCY" : "OVER-LIMIT";
|
|
46099
46106
|
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)}%`;
|
|
@@ -46127,7 +46134,7 @@ function decideNudge(input) {
|
|
|
46127
46134
|
reason = injectedReason;
|
|
46128
46135
|
} else if (pressure) {
|
|
46129
46136
|
const label = emergencyOverride ? "EMERGENCY" : "OVER-LIMIT";
|
|
46130
|
-
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`;
|
|
46137
|
+
reason = bestPending === 0 ? `${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` : `${label}: usage ${Math.round(usage * 100)}% but max pending ${bestPending} < min benefit ${minPressureBenefit} tokens (T1 effective ${t1Eff}, T2 ${t2Pen}, T3 ${t3Pen}) \u2014 suppressed: rewriting below the benefit floor reclaims almost nothing while usage stays high; truncate.threshold remains the safety valve`;
|
|
46131
46138
|
} else {
|
|
46132
46139
|
const tiersList = [1, 2, 3];
|
|
46133
46140
|
const eligible = tiersList.filter((t) => config.tiers.enabled || t === 1);
|
|
@@ -46183,6 +46190,7 @@ function decideNudge(input) {
|
|
|
46183
46190
|
hasPendingNudge: hasPendingNudge ? 1 : 0,
|
|
46184
46191
|
overLimit: overLimit ? 1 : 0,
|
|
46185
46192
|
emergencyOverride: emergencyOverride ? 1 : 0,
|
|
46193
|
+
minPressureBenefit,
|
|
46186
46194
|
pendingT1: tiers[1].pending,
|
|
46187
46195
|
pendingT2: tiers[2].pending,
|
|
46188
46196
|
pendingT3: tiers[3].pending
|
|
@@ -51157,7 +51165,7 @@ function generateRootCA() {
|
|
|
51157
51165
|
cert.setSubject(attrs);
|
|
51158
51166
|
cert.setIssuer(attrs);
|
|
51159
51167
|
cert.setExtensions([
|
|
51160
|
-
{ name: "basicConstraints", cA: true },
|
|
51168
|
+
{ name: "basicConstraints", cA: true, critical: true },
|
|
51161
51169
|
{ name: "keyUsage", keyCertSign: true, cRLSign: true, digitalSignature: true },
|
|
51162
51170
|
{ name: "subjectKeyIdentifier" }
|
|
51163
51171
|
]);
|
|
@@ -51193,16 +51201,10 @@ function ensureRootCA() {
|
|
|
51193
51201
|
rootKey = import_node_forge.default.pki.privateKeyFromPem(key);
|
|
51194
51202
|
writeCombinedBundle();
|
|
51195
51203
|
}
|
|
51196
|
-
function
|
|
51204
|
+
function mintHostCert(host) {
|
|
51197
51205
|
if (!rootCertPem || !rootKeyPem || !rootCert || !rootKey) {
|
|
51198
51206
|
throw new Error("CA not initialized \u2014 call ensureRootCA() first");
|
|
51199
51207
|
}
|
|
51200
|
-
const cached = secureContextCache.get(host);
|
|
51201
|
-
if (cached) {
|
|
51202
|
-
secureContextCache.delete(host);
|
|
51203
|
-
secureContextCache.set(host, cached);
|
|
51204
|
-
return cached;
|
|
51205
|
-
}
|
|
51206
51208
|
const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
|
|
51207
51209
|
const cert = import_node_forge.default.pki.createCertificate();
|
|
51208
51210
|
cert.publicKey = keys.publicKey;
|
|
@@ -51212,16 +51214,35 @@ function getSecureContext(host) {
|
|
|
51212
51214
|
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 2);
|
|
51213
51215
|
cert.setSubject([{ name: "commonName", value: host }]);
|
|
51214
51216
|
cert.setIssuer(rootCert.subject.attributes);
|
|
51217
|
+
const rootSki = rootCert.generateSubjectKeyIdentifier().getBytes();
|
|
51215
51218
|
cert.setExtensions([
|
|
51216
51219
|
{ name: "basicConstraints", cA: false },
|
|
51217
51220
|
{ name: "keyUsage", digitalSignature: true, keyEncipherment: true },
|
|
51218
51221
|
{ name: "extKeyUsage", serverAuth: true },
|
|
51219
|
-
{ name: "subjectAltName", altNames: [{ type: 2, value: host }] }
|
|
51222
|
+
{ name: "subjectAltName", altNames: [{ type: 2, value: host }] },
|
|
51223
|
+
{ name: "subjectKeyIdentifier" },
|
|
51224
|
+
{ name: "authorityKeyIdentifier", keyIdentifier: rootSki }
|
|
51220
51225
|
]);
|
|
51221
51226
|
cert.sign(rootKey, import_node_forge.default.md.sha256.create());
|
|
51227
|
+
return {
|
|
51228
|
+
certPem: import_node_forge.default.pki.certificateToPem(cert),
|
|
51229
|
+
keyPem: import_node_forge.default.pki.privateKeyToPem(keys.privateKey)
|
|
51230
|
+
};
|
|
51231
|
+
}
|
|
51232
|
+
function getSecureContext(host) {
|
|
51233
|
+
if (!rootCertPem || !rootKeyPem || !rootCert || !rootKey) {
|
|
51234
|
+
throw new Error("CA not initialized \u2014 call ensureRootCA() first");
|
|
51235
|
+
}
|
|
51236
|
+
const cached = secureContextCache.get(host);
|
|
51237
|
+
if (cached) {
|
|
51238
|
+
secureContextCache.delete(host);
|
|
51239
|
+
secureContextCache.set(host, cached);
|
|
51240
|
+
return cached;
|
|
51241
|
+
}
|
|
51242
|
+
const { certPem, keyPem } = mintHostCert(host);
|
|
51222
51243
|
const ctx = tls2.createSecureContext({
|
|
51223
|
-
cert:
|
|
51224
|
-
key:
|
|
51244
|
+
cert: certPem,
|
|
51245
|
+
key: keyPem,
|
|
51225
51246
|
ca: rootCertPem
|
|
51226
51247
|
});
|
|
51227
51248
|
secureContextCache.set(host, ctx);
|
|
@@ -52001,10 +52022,11 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
|
|
|
52001
52022
|
if (realCalls > 0) ctx.log(`[acp-loop] round ${round}: ${realCalls} real tool call(s) forwarded to client`);
|
|
52002
52023
|
}
|
|
52003
52024
|
if (proxyResults.length > 0) {
|
|
52025
|
+
const requiresThinkingSignature = ctx.protocol === "anthropic";
|
|
52004
52026
|
if (reasoningSegments.length > 0) {
|
|
52005
52027
|
for (let i = 0; i < reasoningSegments.length; i++) {
|
|
52006
52028
|
const seg = reasoningSegments[i];
|
|
52007
|
-
if (seg.text.length === 0 || seg.signature.length === 0) continue;
|
|
52029
|
+
if (seg.text.length === 0 || requiresThinkingSignature && seg.signature.length === 0) continue;
|
|
52008
52030
|
const reasoningMsg = {
|
|
52009
52031
|
id: i === 0 ? `acp_loop_r${round}_reasoning` : `acp_loop_r${round}_reasoning_${i + 1}`,
|
|
52010
52032
|
role: "assistant",
|
|
@@ -52127,7 +52149,7 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
|
|
|
52127
52149
|
try {
|
|
52128
52150
|
respResult = await fetchUpstream(newBody);
|
|
52129
52151
|
} catch (e) {
|
|
52130
|
-
if (!(e instanceof UpstreamHttpError) || e.status < 400 || e.status >= 500 || degradedRetried || !coreMessages.some(isLoopThinking)) {
|
|
52152
|
+
if (!(e instanceof UpstreamHttpError) || e.status < 400 || e.status >= 500 || degradedRetried || ctx.protocol !== "anthropic" || !coreMessages.some(isLoopThinking)) {
|
|
52131
52153
|
throw e;
|
|
52132
52154
|
}
|
|
52133
52155
|
degradedRetried = true;
|
|
@@ -52349,6 +52371,7 @@ data: ${JSON.stringify(obj)}
|
|
|
52349
52371
|
}
|
|
52350
52372
|
async function* iterSseEvents(stream2) {
|
|
52351
52373
|
const reader = stream2.getReader();
|
|
52374
|
+
const decoder = new TextDecoder();
|
|
52352
52375
|
let buf = "";
|
|
52353
52376
|
try {
|
|
52354
52377
|
while (true) {
|
|
@@ -52360,7 +52383,7 @@ async function* iterSseEvents(stream2) {
|
|
|
52360
52383
|
break;
|
|
52361
52384
|
}
|
|
52362
52385
|
if (done) break;
|
|
52363
|
-
buf +=
|
|
52386
|
+
buf += decoder.decode(value, { stream: true });
|
|
52364
52387
|
buf = buf.replace(/\r\n|\r/g, "\n");
|
|
52365
52388
|
let idx;
|
|
52366
52389
|
while ((idx = buf.indexOf("\n\n")) >= 0) {
|
|
@@ -52838,6 +52861,7 @@ function filterRealToolFragments(parsed, realIndexes) {
|
|
|
52838
52861
|
}
|
|
52839
52862
|
async function* iterSseChunks(stream2) {
|
|
52840
52863
|
const reader = stream2.getReader();
|
|
52864
|
+
const decoder = new TextDecoder();
|
|
52841
52865
|
let buf = "";
|
|
52842
52866
|
try {
|
|
52843
52867
|
while (true) {
|
|
@@ -52849,7 +52873,7 @@ async function* iterSseChunks(stream2) {
|
|
|
52849
52873
|
break;
|
|
52850
52874
|
}
|
|
52851
52875
|
if (done) break;
|
|
52852
|
-
buf +=
|
|
52876
|
+
buf += decoder.decode(value, { stream: true });
|
|
52853
52877
|
buf = buf.replace(/\r\n|\r/g, "\n");
|
|
52854
52878
|
let idx;
|
|
52855
52879
|
while ((idx = buf.indexOf("\n\n")) >= 0) {
|
|
@@ -53175,6 +53199,7 @@ function createOpenaiAdapter(requestBody, clientSystem) {
|
|
|
53175
53199
|
// src/loop/adapter-anthropic.ts
|
|
53176
53200
|
async function* iterSseEvents2(stream2) {
|
|
53177
53201
|
const reader = stream2.getReader();
|
|
53202
|
+
const decoder = new TextDecoder();
|
|
53178
53203
|
let buf = "";
|
|
53179
53204
|
try {
|
|
53180
53205
|
while (true) {
|
|
@@ -53186,7 +53211,7 @@ async function* iterSseEvents2(stream2) {
|
|
|
53186
53211
|
break;
|
|
53187
53212
|
}
|
|
53188
53213
|
if (done) break;
|
|
53189
|
-
buf +=
|
|
53214
|
+
buf += decoder.decode(value, { stream: true });
|
|
53190
53215
|
buf = buf.replace(/\r\n|\r/g, "\n");
|
|
53191
53216
|
let idx;
|
|
53192
53217
|
while ((idx = buf.indexOf("\n\n")) >= 0) {
|
|
@@ -53833,6 +53858,76 @@ ${FAKE_COMPLETION_HINT}`;
|
|
|
53833
53858
|
return JSON.stringify(obj);
|
|
53834
53859
|
}
|
|
53835
53860
|
|
|
53861
|
+
// src/acp-panel.ts
|
|
53862
|
+
var PANEL_BOX_TOP = "\u256D";
|
|
53863
|
+
var PANEL_BOX_TITLE = "ACP Context Analysis";
|
|
53864
|
+
var PANEL_BOX_FOOTER = "Tag visibility: tags injected to LLM only (deep copy), not persisted in session, not shown in terminal.";
|
|
53865
|
+
var PANEL_FALLBACK_HEADER = "\u{1F4CA} ACP status";
|
|
53866
|
+
function isAcpPanelText(text) {
|
|
53867
|
+
const t = text.trim();
|
|
53868
|
+
if (t.length === 0) return false;
|
|
53869
|
+
return isBoxPanel(t) || isFallbackPanel(t);
|
|
53870
|
+
}
|
|
53871
|
+
function isBoxPanel(t) {
|
|
53872
|
+
return t.startsWith(PANEL_BOX_TOP) && t.includes(PANEL_BOX_TITLE) && t.endsWith(PANEL_BOX_FOOTER);
|
|
53873
|
+
}
|
|
53874
|
+
function isFallbackPanel(t) {
|
|
53875
|
+
const lines = t.split("\n");
|
|
53876
|
+
if (lines[0] !== PANEL_FALLBACK_HEADER) return false;
|
|
53877
|
+
for (let i = 1; i < lines.length; i++) {
|
|
53878
|
+
const line = lines[i];
|
|
53879
|
+
if (line.length > 0 && !line.startsWith(" ")) return false;
|
|
53880
|
+
}
|
|
53881
|
+
return true;
|
|
53882
|
+
}
|
|
53883
|
+
function messageText(content) {
|
|
53884
|
+
if (typeof content === "string") return content;
|
|
53885
|
+
if (Array.isArray(content)) {
|
|
53886
|
+
let joined = "";
|
|
53887
|
+
for (const part of content) {
|
|
53888
|
+
const p2 = part;
|
|
53889
|
+
if (p2 === null || typeof p2 !== "object") return void 0;
|
|
53890
|
+
const pt2 = p2.type;
|
|
53891
|
+
if (pt2 !== void 0 && pt2 !== "text" && pt2 !== "input_text") return void 0;
|
|
53892
|
+
if (typeof p2.text === "string") joined += p2.text;
|
|
53893
|
+
}
|
|
53894
|
+
return joined;
|
|
53895
|
+
}
|
|
53896
|
+
return void 0;
|
|
53897
|
+
}
|
|
53898
|
+
function stripAcpPanelMessages(messages) {
|
|
53899
|
+
if (!Array.isArray(messages)) return 0;
|
|
53900
|
+
let stripped = 0;
|
|
53901
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
53902
|
+
const rec = messages[i];
|
|
53903
|
+
if (rec === null || typeof rec !== "object") continue;
|
|
53904
|
+
if (rec.role !== "user") continue;
|
|
53905
|
+
const text = messageText(rec.content);
|
|
53906
|
+
if (text !== void 0 && isAcpPanelText(text)) {
|
|
53907
|
+
messages.splice(i, 1);
|
|
53908
|
+
stripped++;
|
|
53909
|
+
}
|
|
53910
|
+
}
|
|
53911
|
+
return stripped;
|
|
53912
|
+
}
|
|
53913
|
+
function stripAcpPanelResponsesInput(input) {
|
|
53914
|
+
if (!Array.isArray(input)) return 0;
|
|
53915
|
+
let stripped = 0;
|
|
53916
|
+
for (let i = input.length - 1; i >= 0; i--) {
|
|
53917
|
+
const rec = input[i];
|
|
53918
|
+
if (rec === null || typeof rec !== "object") continue;
|
|
53919
|
+
const type = rec.type;
|
|
53920
|
+
if (type !== "message" && type !== void 0) continue;
|
|
53921
|
+
if (rec.role !== "user") continue;
|
|
53922
|
+
const text = messageText(rec.content);
|
|
53923
|
+
if (text !== void 0 && isAcpPanelText(text)) {
|
|
53924
|
+
input.splice(i, 1);
|
|
53925
|
+
stripped++;
|
|
53926
|
+
}
|
|
53927
|
+
}
|
|
53928
|
+
return stripped;
|
|
53929
|
+
}
|
|
53930
|
+
|
|
53836
53931
|
// src/stream-openai.ts
|
|
53837
53932
|
function rewriteOpenaiJsonResponse(body, ctx) {
|
|
53838
53933
|
if (!body || typeof body !== "object") return body;
|
|
@@ -55559,6 +55654,7 @@ function readOmpConfig(ompHome) {
|
|
|
55559
55654
|
}
|
|
55560
55655
|
function parseHermesYaml(text) {
|
|
55561
55656
|
const result = { providers: {} };
|
|
55657
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
55562
55658
|
let mode = "none";
|
|
55563
55659
|
let sectionIndent = -1;
|
|
55564
55660
|
let entryIndent = -1;
|
|
@@ -55603,8 +55699,8 @@ function parseHermesYaml(text) {
|
|
|
55603
55699
|
current = m2 ? m2[1] : null;
|
|
55604
55700
|
if (current && !result.providers[current]) result.providers[current] = {};
|
|
55605
55701
|
} else if (indent > entryIndent && current) {
|
|
55606
|
-
const apiMatch = /^api:\s*(\S+)/.exec(trimmed);
|
|
55607
|
-
if (apiMatch)
|
|
55702
|
+
const apiMatch = /^(base_url|url|api):\s*(\S+)/.exec(trimmed);
|
|
55703
|
+
if (apiMatch) candidates.set(`${current}\0${apiMatch[1]}`, apiMatch[2]);
|
|
55608
55704
|
}
|
|
55609
55705
|
} else {
|
|
55610
55706
|
const dashMatch = /^-\s+(.*)$/.exec(trimmed);
|
|
@@ -55621,6 +55717,10 @@ function parseHermesYaml(text) {
|
|
|
55621
55717
|
}
|
|
55622
55718
|
}
|
|
55623
55719
|
}
|
|
55720
|
+
for (const name of Object.keys(result.providers)) {
|
|
55721
|
+
const pick = candidates.get(`${name}\0base_url`) ?? candidates.get(`${name}\0url`) ?? candidates.get(`${name}\0api`);
|
|
55722
|
+
if (pick !== void 0) result.providers[name].api = pick;
|
|
55723
|
+
}
|
|
55624
55724
|
return result;
|
|
55625
55725
|
}
|
|
55626
55726
|
function readHermesConfig(hermesHome) {
|
|
@@ -56921,6 +57021,16 @@ function resolveUpstream(_opts, reqUrl, req) {
|
|
|
56921
57021
|
}
|
|
56922
57022
|
}
|
|
56923
57023
|
}
|
|
57024
|
+
if (reqUrl.startsWith("http://") || reqUrl.startsWith("https://")) {
|
|
57025
|
+
try {
|
|
57026
|
+
const u2 = new URL(reqUrl);
|
|
57027
|
+
const ownHost = (req?.headers.host ?? "").toLowerCase();
|
|
57028
|
+
if (u2.host.toLowerCase() !== ownHost) {
|
|
57029
|
+
return { upstream: `${u2.protocol}//${u2.host}`, rewrittenUrl: reqUrl, tunnel: true };
|
|
57030
|
+
}
|
|
57031
|
+
} catch {
|
|
57032
|
+
}
|
|
57033
|
+
}
|
|
56924
57034
|
return void 0;
|
|
56925
57035
|
}
|
|
56926
57036
|
async function startServer(opts) {
|
|
@@ -57658,6 +57768,10 @@ function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, sessio
|
|
|
57658
57768
|
let rebuiltMessages = parsed.messages;
|
|
57659
57769
|
let systemOut = parsed.system;
|
|
57660
57770
|
let toolsOut = parsed.tools;
|
|
57771
|
+
const strippedPanels = stripAcpPanelMessages(parsed.messages);
|
|
57772
|
+
if (strippedPanels > 0) {
|
|
57773
|
+
log2("info", `[${sessionId}] stripped ${strippedPanels} ACP panel message(s) before projection (UI-only, issue #359)`);
|
|
57774
|
+
}
|
|
57661
57775
|
try {
|
|
57662
57776
|
const { msgs, cacheControls } = anthropicToCore(parsed);
|
|
57663
57777
|
originalMessages = msgs;
|
|
@@ -57747,6 +57861,10 @@ function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session,
|
|
|
57747
57861
|
const isTitleGen = maxTokens <= 200;
|
|
57748
57862
|
const shouldInject = opts.compress.injectTool && !isTitleGen;
|
|
57749
57863
|
const injectTools = shouldInject && !pluginMode;
|
|
57864
|
+
const strippedPanels = stripAcpPanelMessages(parsed.messages);
|
|
57865
|
+
if (strippedPanels > 0) {
|
|
57866
|
+
log2("info", `[${sessionId}] stripped ${strippedPanels} ACP panel message(s) before projection (UI-only, issue #359)`);
|
|
57867
|
+
}
|
|
57750
57868
|
try {
|
|
57751
57869
|
const { msgs, systemText } = openaiToCore(parsed);
|
|
57752
57870
|
openaiSystemText = systemText;
|
|
@@ -57832,6 +57950,10 @@ function prepareResponses(parsed, req, opts, core, config, prompts, log2, sessio
|
|
|
57832
57950
|
if (droppedEmpty > 0) {
|
|
57833
57951
|
log2("info", `[${sessionId}] dropped ${droppedEmpty} whitespace-only message item(s) before projection (flattened-turn artifact)`);
|
|
57834
57952
|
}
|
|
57953
|
+
const strippedPanels = stripAcpPanelResponsesInput(parsed.input);
|
|
57954
|
+
if (strippedPanels > 0) {
|
|
57955
|
+
log2("info", `[${sessionId}] stripped ${strippedPanels} ACP panel message(s) before projection (UI-only, issue #359)`);
|
|
57956
|
+
}
|
|
57835
57957
|
const shouldInject = opts.compress.injectTool;
|
|
57836
57958
|
const injectTools = shouldInject && !pluginMode;
|
|
57837
57959
|
const isCompactionTrigger = hasCompactionTrigger(parsed.input);
|
|
@@ -62862,8 +62984,16 @@ function discoverRoutes(client, config) {
|
|
|
62862
62984
|
if (url.protocol !== "http:" && url.protocol !== "https:") continue;
|
|
62863
62985
|
if (hermesSeen.has(name)) continue;
|
|
62864
62986
|
hermesSeen.add(name);
|
|
62865
|
-
|
|
62866
|
-
|
|
62987
|
+
if (url.protocol === "https:") {
|
|
62988
|
+
const host = url.hostname.toLowerCase();
|
|
62989
|
+
if (host && !httpsSeen.has(host)) {
|
|
62990
|
+
httpsSeen.add(host);
|
|
62991
|
+
httpsDomains.push(host);
|
|
62992
|
+
}
|
|
62993
|
+
} else if (!rewriteKeys.has(name)) {
|
|
62994
|
+
rewriteKeys.add(name);
|
|
62995
|
+
httpRewrites.push({ key: name, realUpstream: real });
|
|
62996
|
+
}
|
|
62867
62997
|
} catch {
|
|
62868
62998
|
}
|
|
62869
62999
|
}
|
|
@@ -62894,8 +63024,23 @@ function discoverRoutes(client, config) {
|
|
|
62894
63024
|
function discoverDomains(client, config) {
|
|
62895
63025
|
return discoverRoutes(client, config).httpsDomains;
|
|
62896
63026
|
}
|
|
62897
|
-
function buildPiEnv(origin, caPath, baseEnv) {
|
|
62898
|
-
|
|
63027
|
+
function buildPiEnv(origin, caPath, baseEnv, httpRewrites = [], httpsRewrites = []) {
|
|
63028
|
+
const manifest = {};
|
|
63029
|
+
for (const r of httpRewrites) {
|
|
63030
|
+
if (r.key.length === 0 || r.realUpstream.length === 0) continue;
|
|
63031
|
+
manifest[r.key] = wrapUpstream(origin, r.realUpstream);
|
|
63032
|
+
}
|
|
63033
|
+
for (const r of httpsRewrites) {
|
|
63034
|
+
if (r.key.length === 0 || r.realUpstream.length === 0) continue;
|
|
63035
|
+
manifest[r.key] = r.realUpstream;
|
|
63036
|
+
}
|
|
63037
|
+
return {
|
|
63038
|
+
...baseEnv,
|
|
63039
|
+
HTTPS_PROXY: origin,
|
|
63040
|
+
NODE_EXTRA_CA_CERTS: caPath,
|
|
63041
|
+
BILLION_CONTEXT_PROXY: origin,
|
|
63042
|
+
...Object.keys(manifest).length > 0 ? { BILI_PROVIDER_REWRITES: JSON.stringify(manifest) } : {}
|
|
63043
|
+
};
|
|
62899
63044
|
}
|
|
62900
63045
|
function buildCodexEnv(origin, caPath, baseEnv) {
|
|
62901
63046
|
return { ...baseEnv, HTTPS_PROXY: origin, SSL_CERT_FILE: caPath, BILLION_CONTEXT_PROXY: origin };
|
|
@@ -63426,363 +63571,6 @@ function writeOverlayFileAtomic(overlay, fileName, contents) {
|
|
|
63426
63571
|
}
|
|
63427
63572
|
}
|
|
63428
63573
|
}
|
|
63429
|
-
function writePiCompactionDisabledSettings(piHome, overlay) {
|
|
63430
|
-
let settings = {};
|
|
63431
|
-
try {
|
|
63432
|
-
const parsed = JSON.parse(fs12.readFileSync(path15.join(piHome, "settings.json"), "utf8"));
|
|
63433
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
63434
|
-
settings = parsed;
|
|
63435
|
-
}
|
|
63436
|
-
} catch {
|
|
63437
|
-
}
|
|
63438
|
-
const compactionRaw = settings.compaction;
|
|
63439
|
-
const compaction = compactionRaw && typeof compactionRaw === "object" && !Array.isArray(compactionRaw) ? { ...compactionRaw } : {};
|
|
63440
|
-
compaction.enabled = false;
|
|
63441
|
-
settings.compaction = compaction;
|
|
63442
|
-
writeOverlayFileAtomic(overlay, "settings.json", JSON.stringify(settings, null, 2));
|
|
63443
|
-
}
|
|
63444
|
-
function preparePiHttpRewrite(piHome, origin, httpRewrites, httpsRewrites) {
|
|
63445
|
-
if (!fs12.existsSync(piHome)) return void 0;
|
|
63446
|
-
const overlay = `${piHome}-bili`;
|
|
63447
|
-
const generated = ["settings.json"];
|
|
63448
|
-
let modelsRoot;
|
|
63449
|
-
try {
|
|
63450
|
-
const parsed = JSON.parse(fs12.readFileSync(path15.join(piHome, "models.json"), "utf8"));
|
|
63451
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
63452
|
-
modelsRoot = parsed;
|
|
63453
|
-
generated.push("models.json");
|
|
63454
|
-
}
|
|
63455
|
-
} catch {
|
|
63456
|
-
}
|
|
63457
|
-
if (!refreshOverlayHome(piHome, overlay, generated)) return void 0;
|
|
63458
|
-
if (modelsRoot) {
|
|
63459
|
-
const providersVal = modelsRoot.providers;
|
|
63460
|
-
if (providersVal && typeof providersVal === "object" && !Array.isArray(providersVal)) {
|
|
63461
|
-
const providers = providersVal;
|
|
63462
|
-
for (const r of httpRewrites) {
|
|
63463
|
-
const prov = providers[r.key];
|
|
63464
|
-
if (prov && typeof prov === "object" && !Array.isArray(prov)) {
|
|
63465
|
-
const p2 = prov;
|
|
63466
|
-
const existing = typeof p2.baseUrl === "string" ? p2.baseUrl : r.realUpstream;
|
|
63467
|
-
p2.baseUrl = wrapUpstream(origin, unwrapUpstream2(existing));
|
|
63468
|
-
}
|
|
63469
|
-
}
|
|
63470
|
-
for (const r of httpsRewrites) {
|
|
63471
|
-
const prov = providers[r.key];
|
|
63472
|
-
if (prov && typeof prov === "object" && !Array.isArray(prov)) {
|
|
63473
|
-
const p2 = prov;
|
|
63474
|
-
p2.baseUrl = r.realUpstream;
|
|
63475
|
-
}
|
|
63476
|
-
}
|
|
63477
|
-
}
|
|
63478
|
-
writeOverlayFileAtomic(overlay, "models.json", JSON.stringify(modelsRoot));
|
|
63479
|
-
}
|
|
63480
|
-
writePiCompactionDisabledSettings(piHome, overlay);
|
|
63481
|
-
return overlay;
|
|
63482
|
-
}
|
|
63483
|
-
function atomicWriteTextFile(filePath, contents) {
|
|
63484
|
-
const draft = `${filePath}.${process.pid}.bili-tmp`;
|
|
63485
|
-
try {
|
|
63486
|
-
fs12.writeFileSync(draft, contents);
|
|
63487
|
-
fs12.renameSync(draft, filePath);
|
|
63488
|
-
} catch {
|
|
63489
|
-
try {
|
|
63490
|
-
fs12.rmSync(draft, { force: true });
|
|
63491
|
-
} catch {
|
|
63492
|
-
}
|
|
63493
|
-
throw new Error(`bili: could not write ${filePath}`);
|
|
63494
|
-
}
|
|
63495
|
-
}
|
|
63496
|
-
function liveProxyPorts() {
|
|
63497
|
-
const ports = /* @__PURE__ */ new Set();
|
|
63498
|
-
const inst = readProxyInstanceFile();
|
|
63499
|
-
if (isProxyInstanceFile(inst)) {
|
|
63500
|
-
if (isPidAlive(inst.pid)) ports.add(inst.port);
|
|
63501
|
-
} else if (inst) {
|
|
63502
|
-
try {
|
|
63503
|
-
ports.add(new URL(inst.origin).port === "" ? 80 : Number(new URL(inst.origin).port));
|
|
63504
|
-
} catch {
|
|
63505
|
-
}
|
|
63506
|
-
}
|
|
63507
|
-
return ports;
|
|
63508
|
-
}
|
|
63509
|
-
function unpackDeadProxyUrlsInFile(filePath, livePorts) {
|
|
63510
|
-
let txt;
|
|
63511
|
-
try {
|
|
63512
|
-
txt = fs12.readFileSync(filePath, "utf8");
|
|
63513
|
-
} catch {
|
|
63514
|
-
return 0;
|
|
63515
|
-
}
|
|
63516
|
-
const re2 = /https?:\/\/(?:127\.0\.0\.1|localhost|\[::1\]):(\d+)\/bili\/(https?:\/\/\S+)/g;
|
|
63517
|
-
let changed = 0;
|
|
63518
|
-
const out = txt.replace(re2, (full, portStr, raw) => {
|
|
63519
|
-
if (livePorts.has(Number(portStr))) return full;
|
|
63520
|
-
changed += 1;
|
|
63521
|
-
return raw;
|
|
63522
|
-
});
|
|
63523
|
-
if (changed === 0) return 0;
|
|
63524
|
-
try {
|
|
63525
|
-
atomicWriteTextFile(filePath, out);
|
|
63526
|
-
} catch {
|
|
63527
|
-
return 0;
|
|
63528
|
-
}
|
|
63529
|
-
return changed;
|
|
63530
|
-
}
|
|
63531
|
-
function mergeOmpCompactionDisabledYaml(text) {
|
|
63532
|
-
const lines = text.split(/\r?\n/);
|
|
63533
|
-
let compactionLine = -1;
|
|
63534
|
-
for (let i = 0; i < lines.length; i++) {
|
|
63535
|
-
const rawLine = lines[i];
|
|
63536
|
-
const trimmed = rawLine.trim();
|
|
63537
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
63538
|
-
const indent = rawLine.length - rawLine.trimStart().length;
|
|
63539
|
-
if (indent === 0 && /^compaction:\s*(#.*)?$/.test(trimmed)) {
|
|
63540
|
-
compactionLine = i;
|
|
63541
|
-
break;
|
|
63542
|
-
}
|
|
63543
|
-
}
|
|
63544
|
-
if (compactionLine === -1) {
|
|
63545
|
-
const base = text === "" || text.endsWith("\n") ? text : `${text}
|
|
63546
|
-
`;
|
|
63547
|
-
return `${base}compaction:
|
|
63548
|
-
enabled: false
|
|
63549
|
-
`;
|
|
63550
|
-
}
|
|
63551
|
-
for (let i = compactionLine + 1; i < lines.length; i++) {
|
|
63552
|
-
const rawLine = lines[i];
|
|
63553
|
-
const trimmed = rawLine.trim();
|
|
63554
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
63555
|
-
const indent = rawLine.length - rawLine.trimStart().length;
|
|
63556
|
-
if (indent === 0) break;
|
|
63557
|
-
if (/^enabled:/.test(trimmed)) {
|
|
63558
|
-
const leading = rawLine.slice(0, rawLine.length - rawLine.trimStart().length);
|
|
63559
|
-
const commentMatch = /\s+#.*$/.exec(rawLine);
|
|
63560
|
-
const comment = commentMatch ? commentMatch[0] : "";
|
|
63561
|
-
lines[i] = `${leading}enabled: false${comment}`;
|
|
63562
|
-
return lines.join("\n");
|
|
63563
|
-
}
|
|
63564
|
-
}
|
|
63565
|
-
let childIndent = 2;
|
|
63566
|
-
for (let i = compactionLine + 1; i < lines.length; i++) {
|
|
63567
|
-
const rawLine = lines[i];
|
|
63568
|
-
const trimmed = rawLine.trim();
|
|
63569
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
63570
|
-
const indent = rawLine.length - rawLine.trimStart().length;
|
|
63571
|
-
if (indent === 0) break;
|
|
63572
|
-
childIndent = indent;
|
|
63573
|
-
break;
|
|
63574
|
-
}
|
|
63575
|
-
lines.splice(compactionLine + 1, 0, `${" ".repeat(childIndent)}enabled: false`);
|
|
63576
|
-
return lines.join("\n");
|
|
63577
|
-
}
|
|
63578
|
-
function writeOmpCompactionDisabledConfig(ompHome, overlay) {
|
|
63579
|
-
let base;
|
|
63580
|
-
let baseIsJson = false;
|
|
63581
|
-
for (const name of ["config.yml", "config.yaml"]) {
|
|
63582
|
-
try {
|
|
63583
|
-
base = fs12.readFileSync(path15.join(ompHome, name), "utf8");
|
|
63584
|
-
break;
|
|
63585
|
-
} catch {
|
|
63586
|
-
}
|
|
63587
|
-
}
|
|
63588
|
-
if (base === void 0) {
|
|
63589
|
-
try {
|
|
63590
|
-
base = fs12.readFileSync(path15.join(ompHome, "settings.json"), "utf8");
|
|
63591
|
-
baseIsJson = true;
|
|
63592
|
-
} catch {
|
|
63593
|
-
}
|
|
63594
|
-
}
|
|
63595
|
-
let merged;
|
|
63596
|
-
if (base === void 0) {
|
|
63597
|
-
merged = "compaction:\n enabled: false\n";
|
|
63598
|
-
} else if (baseIsJson) {
|
|
63599
|
-
let settings = {};
|
|
63600
|
-
try {
|
|
63601
|
-
const parsed = JSON.parse(base);
|
|
63602
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
63603
|
-
settings = parsed;
|
|
63604
|
-
}
|
|
63605
|
-
} catch {
|
|
63606
|
-
}
|
|
63607
|
-
const compactionRaw = settings.compaction;
|
|
63608
|
-
const compaction = compactionRaw && typeof compactionRaw === "object" && !Array.isArray(compactionRaw) ? { ...compactionRaw } : {};
|
|
63609
|
-
compaction.enabled = false;
|
|
63610
|
-
settings.compaction = compaction;
|
|
63611
|
-
merged = JSON.stringify(settings, null, 2);
|
|
63612
|
-
} else {
|
|
63613
|
-
merged = mergeOmpCompactionDisabledYaml(base);
|
|
63614
|
-
}
|
|
63615
|
-
writeOverlayFileAtomic(overlay, "config.yml", merged);
|
|
63616
|
-
}
|
|
63617
|
-
function prepareOmpHttpRewrite(ompHome, origin, httpRewrites, httpsRewrites) {
|
|
63618
|
-
if (!fs12.existsSync(ompHome)) return void 0;
|
|
63619
|
-
const overlay = `${ompHome}-bili`;
|
|
63620
|
-
const generated = ["config.yml"];
|
|
63621
|
-
const modelsPath = path15.join(ompHome, "models.yml");
|
|
63622
|
-
const unpacked = unpackDeadProxyUrlsInFile(modelsPath, liveProxyPorts());
|
|
63623
|
-
if (unpacked > 0) {
|
|
63624
|
-
console.error(`bili: unpacked ${unpacked} dead proxy URL(s) from the real ${modelsPath}`);
|
|
63625
|
-
}
|
|
63626
|
-
let modelsText;
|
|
63627
|
-
try {
|
|
63628
|
-
modelsText = fs12.readFileSync(modelsPath, "utf8");
|
|
63629
|
-
generated.push("models.yml");
|
|
63630
|
-
} catch {
|
|
63631
|
-
}
|
|
63632
|
-
if (!refreshOverlayHome(ompHome, overlay, generated)) return void 0;
|
|
63633
|
-
if (modelsText !== void 0) {
|
|
63634
|
-
const httpMap = new Map(httpRewrites.map((r) => [r.key, wrapUpstream(origin, r.realUpstream)]));
|
|
63635
|
-
const httpsMap = new Map(httpsRewrites.map((r) => [r.key, r.realUpstream]));
|
|
63636
|
-
const lines = modelsText.split(/\r?\n/);
|
|
63637
|
-
let providersIndent = -1;
|
|
63638
|
-
let providerIndent = -1;
|
|
63639
|
-
let currentProvider = null;
|
|
63640
|
-
for (let i = 0; i < lines.length; i++) {
|
|
63641
|
-
const rawLine = lines[i];
|
|
63642
|
-
const trimmed = rawLine.trim();
|
|
63643
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
63644
|
-
const indent = rawLine.length - rawLine.trimStart().length;
|
|
63645
|
-
if (providersIndent === -1) {
|
|
63646
|
-
if (/^providers:\s*(#.*)?$/.test(trimmed)) providersIndent = indent;
|
|
63647
|
-
continue;
|
|
63648
|
-
}
|
|
63649
|
-
if (indent <= providersIndent) break;
|
|
63650
|
-
if (providerIndent === -1) providerIndent = indent;
|
|
63651
|
-
if (indent === providerIndent) {
|
|
63652
|
-
const m2 = /^([A-Za-z0-9_.-]+):/.exec(trimmed);
|
|
63653
|
-
currentProvider = m2 ? m2[1] : null;
|
|
63654
|
-
} else if (indent > providerIndent && currentProvider) {
|
|
63655
|
-
const baseMatch = /^(baseUrl:\s*)(\S+)/.exec(trimmed);
|
|
63656
|
-
if (baseMatch) {
|
|
63657
|
-
const target = httpMap.get(currentProvider) ?? httpsMap.get(currentProvider);
|
|
63658
|
-
if (target) {
|
|
63659
|
-
const leading = rawLine.slice(0, rawLine.length - rawLine.trimStart().length);
|
|
63660
|
-
const commentMatch = /\s+#.*$/.exec(rawLine);
|
|
63661
|
-
const comment = commentMatch ? commentMatch[0] : "";
|
|
63662
|
-
lines[i] = `${leading}baseUrl: ${target}${comment}`;
|
|
63663
|
-
}
|
|
63664
|
-
}
|
|
63665
|
-
}
|
|
63666
|
-
}
|
|
63667
|
-
writeOverlayFileAtomic(overlay, "models.yml", lines.join("\n"));
|
|
63668
|
-
}
|
|
63669
|
-
writeOmpCompactionDisabledConfig(ompHome, overlay);
|
|
63670
|
-
return overlay;
|
|
63671
|
-
}
|
|
63672
|
-
function prepareHermesHome(hermesHome, origin, rewrites) {
|
|
63673
|
-
if (rewrites.length === 0) return void 0;
|
|
63674
|
-
const cfgPath = path15.join(hermesHome, "config.yaml");
|
|
63675
|
-
let txt;
|
|
63676
|
-
try {
|
|
63677
|
-
txt = fs12.readFileSync(cfgPath, "utf8");
|
|
63678
|
-
} catch {
|
|
63679
|
-
return void 0;
|
|
63680
|
-
}
|
|
63681
|
-
const wrapSet = new Set(rewrites.map((r) => r.realUpstream));
|
|
63682
|
-
const eol = txt.includes("\r\n") ? "\r\n" : "\n";
|
|
63683
|
-
const lines = txt.split(/\r?\n/);
|
|
63684
|
-
let changed = false;
|
|
63685
|
-
for (let i = 0; i < lines.length; i++) {
|
|
63686
|
-
const rawLine = lines[i];
|
|
63687
|
-
const m2 = /^(\s*(?:api|base_url|url):\s*)(\S+)(\s+#.*)?$/.exec(rawLine);
|
|
63688
|
-
if (!m2) continue;
|
|
63689
|
-
const rawUrl = m2[2].replace(/^["']|["']$/g, "");
|
|
63690
|
-
if (!/^https?:\/\//i.test(rawUrl)) continue;
|
|
63691
|
-
const real = unwrapUpstream2(rawUrl);
|
|
63692
|
-
if (!wrapSet.has(real)) continue;
|
|
63693
|
-
lines[i] = `${m2[1]}${wrapUpstream(origin, real)}${m2[3] ?? ""}`;
|
|
63694
|
-
changed = true;
|
|
63695
|
-
}
|
|
63696
|
-
if (!changed) return void 0;
|
|
63697
|
-
const overlay = `${hermesHome}-bili`;
|
|
63698
|
-
if (!refreshOverlayHome(hermesHome, overlay, "config.yaml")) return void 0;
|
|
63699
|
-
writeOverlayFileAtomic(overlay, "config.yaml", lines.join(eol));
|
|
63700
|
-
return overlay;
|
|
63701
|
-
}
|
|
63702
|
-
function writeHermesIdentityPlugin(hermesHome, overlay, rewrites) {
|
|
63703
|
-
try {
|
|
63704
|
-
if (fs12.existsSync(path15.join(hermesHome, "plugins"))) return false;
|
|
63705
|
-
} catch {
|
|
63706
|
-
return false;
|
|
63707
|
-
}
|
|
63708
|
-
const dir = path15.join("plugins", "model-providers", "bili-session-identity");
|
|
63709
|
-
try {
|
|
63710
|
-
fs12.mkdirSync(path15.join(overlay, dir), { recursive: true });
|
|
63711
|
-
} catch {
|
|
63712
|
-
return false;
|
|
63713
|
-
}
|
|
63714
|
-
const keys = rewrites.map((r) => r.key);
|
|
63715
|
-
const pluginDir = path15.join(overlay, dir);
|
|
63716
|
-
try {
|
|
63717
|
-
fs12.writeFileSync(path15.join(pluginDir, "__init__.py"), hermesIdentityPluginSource(keys));
|
|
63718
|
-
fs12.writeFileSync(path15.join(pluginDir, "plugin.yaml"), [
|
|
63719
|
-
"name: bili-session-identity",
|
|
63720
|
-
"kind: model-provider",
|
|
63721
|
-
"version: 1.0.0",
|
|
63722
|
-
"description: billion-context session identity (installed by `bili hermes` \u2014 safe to delete)",
|
|
63723
|
-
"author: billion-context",
|
|
63724
|
-
""
|
|
63725
|
-
].join("\n"));
|
|
63726
|
-
} catch {
|
|
63727
|
-
return false;
|
|
63728
|
-
}
|
|
63729
|
-
try {
|
|
63730
|
-
return fs12.existsSync(path15.join(overlay, dir, "__init__.py"));
|
|
63731
|
-
} catch {
|
|
63732
|
-
return false;
|
|
63733
|
-
}
|
|
63734
|
-
}
|
|
63735
|
-
function hermesIdentityPluginSource(providerKeys) {
|
|
63736
|
-
return [
|
|
63737
|
-
'"""Installed by `bili hermes` (billion-context) \u2014 safe to delete.',
|
|
63738
|
-
"",
|
|
63739
|
-
"Re-registers hermes's `custom` provider profile (plus a `custom:<name>`",
|
|
63740
|
-
"profile for every provider the proxy fronts) with one addition: the",
|
|
63741
|
-
"REAL hermes session id is sent as `prompt_cache_key` on every request,",
|
|
63742
|
-
"which the billion-context proxy uses as the stable conversation",
|
|
63743
|
-
"identity for its compression sessions. Removing this file restores",
|
|
63744
|
-
'stock behavior (no prompt_cache_key)."""',
|
|
63745
|
-
"from providers import get_provider_profile, register_provider",
|
|
63746
|
-
"from providers.base import ProviderProfile",
|
|
63747
|
-
"",
|
|
63748
|
-
`_PROVIDER_KEYS = ${JSON.stringify(providerKeys)}`,
|
|
63749
|
-
"",
|
|
63750
|
-
'_custom = get_provider_profile("custom")',
|
|
63751
|
-
"_BASE = type(_custom) if _custom is not None else ProviderProfile",
|
|
63752
|
-
"",
|
|
63753
|
-
"",
|
|
63754
|
-
"class _BiliSessionIdentity(_BASE):",
|
|
63755
|
-
" def build_api_kwargs_extras(self, *, session_id=None, **ctx):",
|
|
63756
|
-
" extra_body, top_level = _BASE.build_api_kwargs_extras(",
|
|
63757
|
-
" self, session_id=session_id, **ctx",
|
|
63758
|
-
" )",
|
|
63759
|
-
' sid = str(session_id or "").strip()',
|
|
63760
|
-
" if sid:",
|
|
63761
|
-
' top_level.setdefault("prompt_cache_key", sid[:64])',
|
|
63762
|
-
" return extra_body, top_level",
|
|
63763
|
-
"",
|
|
63764
|
-
"",
|
|
63765
|
-
"def _register(name, template, with_aliases):",
|
|
63766
|
-
" fields = {}",
|
|
63767
|
-
" if template is not None:",
|
|
63768
|
-
" # Aliases are copied ONLY for the canonical custom",
|
|
63769
|
-
" # re-registration: copying them onto custom:<name> entries",
|
|
63770
|
-
" # would steal the aliases (register_provider re-points each",
|
|
63771
|
-
" # alias at the registering name).",
|
|
63772
|
-
' for attr in (("aliases",) if with_aliases else ()) + ("env_vars", "base_url", "default_max_tokens"):',
|
|
63773
|
-
" value = getattr(template, attr, None)",
|
|
63774
|
-
" if value:",
|
|
63775
|
-
" fields[attr] = value",
|
|
63776
|
-
" register_provider(_BiliSessionIdentity(name=name, **fields))",
|
|
63777
|
-
"",
|
|
63778
|
-
"",
|
|
63779
|
-
"if _custom is not None:",
|
|
63780
|
-
' _register("custom", _custom, True)',
|
|
63781
|
-
"for _key in _PROVIDER_KEYS:",
|
|
63782
|
-
' _register("custom:" + _key, _custom, False)',
|
|
63783
|
-
""
|
|
63784
|
-
].join("\n");
|
|
63785
|
-
}
|
|
63786
63574
|
function prepareDshHome(dshHome, origin, rewrites) {
|
|
63787
63575
|
const cfgPath = path15.join(dshHome, "settings.yaml");
|
|
63788
63576
|
let txt;
|
|
@@ -63944,7 +63732,16 @@ function pickEphemeralPort(host = LAUNCHER_DEFAULT_HOST) {
|
|
|
63944
63732
|
});
|
|
63945
63733
|
});
|
|
63946
63734
|
}
|
|
63947
|
-
var INHERITED_PROXY_VARS = [
|
|
63735
|
+
var INHERITED_PROXY_VARS = [
|
|
63736
|
+
"http_proxy",
|
|
63737
|
+
"https_proxy",
|
|
63738
|
+
"all_proxy",
|
|
63739
|
+
"HTTP_PROXY",
|
|
63740
|
+
"HTTPS_PROXY",
|
|
63741
|
+
"ALL_PROXY",
|
|
63742
|
+
"no_proxy",
|
|
63743
|
+
"NO_PROXY"
|
|
63744
|
+
];
|
|
63948
63745
|
function stripInheritedProxy(env) {
|
|
63949
63746
|
const cleaned = { ...env };
|
|
63950
63747
|
for (const key of INHERITED_PROXY_VARS) delete cleaned[key];
|
|
@@ -64098,9 +63895,30 @@ async function runLaunch(params, deps = {}) {
|
|
|
64098
63895
|
const port = parsePort(params.overrides.ACP_PORT ?? process.env.ACP_PORT);
|
|
64099
63896
|
const passthrough = params.overrides.ACP_PASSTHROUGH === "1";
|
|
64100
63897
|
const debug = params.overrides.ACP_DEBUG === "1";
|
|
64101
|
-
const config = loadClientConfig(process.env, process.cwd());
|
|
64102
63898
|
const base = baseClientName(params.client);
|
|
63899
|
+
const discoveryEnv = base === "pi" || base === "omp" ? { ...process.env, PI_CODING_AGENT_DIR: void 0 } : process.env;
|
|
63900
|
+
const config = loadClientConfig(discoveryEnv, process.cwd());
|
|
64103
63901
|
const routes = discoverRoutes(base, config);
|
|
63902
|
+
const piRealHome = resolvePiHome({ ...process.env, PI_CODING_AGENT_DIR: void 0 });
|
|
63903
|
+
const ompRealHome = resolveOmpHome({ ...process.env, PI_CODING_AGENT_DIR: void 0 });
|
|
63904
|
+
if (base === "pi" && (routes.httpRewrites.length > 0 || routes.httpsRewrites.length > 0)) {
|
|
63905
|
+
const piExt = selfDistFile("agent/pi.js");
|
|
63906
|
+
const extAvailable = piExt !== void 0 && fs12.existsSync(piExt) || piPluginInstalled(piRealHome);
|
|
63907
|
+
if (!extAvailable) {
|
|
63908
|
+
throw new Error(
|
|
63909
|
+
"bili: pi needs provider URL rewrites but the bili extension cannot load (dist/agent/pi.js missing and the plugin is not installed in ~/.pi/agent/settings.json) \u2014 reinstall billion-context or run `bili plugin install pi`"
|
|
63910
|
+
);
|
|
63911
|
+
}
|
|
63912
|
+
}
|
|
63913
|
+
if (base === "omp" && routes.httpRewrites.length > 0) {
|
|
63914
|
+
const ompExt = selfDistFile("agent/omp.js");
|
|
63915
|
+
const extAvailable = ompExt !== void 0 && fs12.existsSync(ompExt) || ompPluginLoadedFrom(ompRealHome);
|
|
63916
|
+
if (!extAvailable) {
|
|
63917
|
+
throw new Error(
|
|
63918
|
+
"bili: omp needs provider URL rewrites but the bili extension cannot load (dist/agent/omp.js missing and the plugin is not installed in ~/.omp/agent/config.yml) \u2014 reinstall billion-context or run `bili plugin install omp`"
|
|
63919
|
+
);
|
|
63920
|
+
}
|
|
63921
|
+
}
|
|
64104
63922
|
const biliRoutes = loadRoutes(process.env);
|
|
64105
63923
|
const domains = dedupeInOrder([...routes.httpsDomains, ...params.mitmDomains ?? []]);
|
|
64106
63924
|
const handle2 = await ensureProxyRunning({ host, port, passthrough, debug, mitmDomains: domains, modelWindows: collectModelWindows(config, base) }, deps);
|
|
@@ -64113,10 +63931,7 @@ async function runLaunch(params, deps = {}) {
|
|
|
64113
63931
|
const ca = resolveCaCertPath(process.env);
|
|
64114
63932
|
let env;
|
|
64115
63933
|
let clientArgs = params.clientArgs;
|
|
64116
|
-
let piOverlayHome;
|
|
64117
|
-
let ompOverlayHome;
|
|
64118
63934
|
let opencodeTmpFile;
|
|
64119
|
-
let hermesOverlayHome;
|
|
64120
63935
|
let dshOverlayHome;
|
|
64121
63936
|
const tmpFiles = [];
|
|
64122
63937
|
const directUrl = launcherDirectUrl(process.env);
|
|
@@ -64144,19 +63959,17 @@ async function runLaunch(params, deps = {}) {
|
|
|
64144
63959
|
}
|
|
64145
63960
|
const origin = handle2.origin;
|
|
64146
63961
|
if (base === "pi") {
|
|
64147
|
-
env = buildPiEnv(origin, ca, process.env);
|
|
64148
|
-
|
|
64149
|
-
if (piOverlayHome) env.PI_CODING_AGENT_DIR = piOverlayHome;
|
|
63962
|
+
env = buildPiEnv(origin, ca, process.env, routes.httpRewrites, routes.httpsRewrites);
|
|
63963
|
+
delete env.PI_CODING_AGENT_DIR;
|
|
64150
63964
|
const piExt = selfDistFile("agent/pi.js");
|
|
64151
|
-
if (piExt && fs12.existsSync(piExt) && !piPluginInstalled(
|
|
63965
|
+
if (piExt && fs12.existsSync(piExt) && !piPluginInstalled(piRealHome)) {
|
|
64152
63966
|
clientArgs = ["-e", piExt, ...clientArgs];
|
|
64153
63967
|
}
|
|
64154
63968
|
} else if (base === "omp") {
|
|
64155
|
-
env = buildPiEnv(origin, ca, process.env);
|
|
64156
|
-
|
|
64157
|
-
if (ompOverlayHome) env.PI_CODING_AGENT_DIR = ompOverlayHome;
|
|
63969
|
+
env = buildPiEnv(origin, ca, process.env, routes.httpRewrites);
|
|
63970
|
+
delete env.PI_CODING_AGENT_DIR;
|
|
64158
63971
|
const ompExt = selfDistFile("agent/omp.js");
|
|
64159
|
-
if (ompExt && fs12.existsSync(ompExt) && !ompPluginLoadedFrom(
|
|
63972
|
+
if (ompExt && fs12.existsSync(ompExt) && !ompPluginLoadedFrom(ompRealHome)) {
|
|
64160
63973
|
clientArgs = ["-e", ompExt, ...clientArgs];
|
|
64161
63974
|
}
|
|
64162
63975
|
} else if (base === "opencode") {
|
|
@@ -64166,18 +63979,12 @@ async function runLaunch(params, deps = {}) {
|
|
|
64166
63979
|
opencodeTmpFile = prepareOpencodeHttpRewrite(resolveOpencodeConfigFile(process.env), origin, routes.httpRewrites, routes.httpsRewrites, opencodePluginPath);
|
|
64167
63980
|
if (opencodeTmpFile) env.OPENCODE_CONFIG = opencodeTmpFile;
|
|
64168
63981
|
} else if (base === "hermes") {
|
|
64169
|
-
env =
|
|
64170
|
-
|
|
64171
|
-
|
|
64172
|
-
|
|
64173
|
-
if (!writeHermesIdentityPlugin(resolveHermesHome(process.env), hermesOverlayHome, routes.httpRewrites)) {
|
|
64174
|
-
console.error(
|
|
64175
|
-
"bili: ~/.hermes has its own plugins/ \u2014 skipping the session-identity plugin; hermes requests will be rejected by the proxy without an identity (see #286)."
|
|
64176
|
-
);
|
|
64177
|
-
}
|
|
64178
|
-
} else {
|
|
63982
|
+
env = stripInheritedProxy(process.env);
|
|
63983
|
+
env.HTTPS_PROXY = origin;
|
|
63984
|
+
env.HERMES_CA_BUNDLE = ca;
|
|
63985
|
+
if (routes.httpRewrites.length === 0 && routes.httpsDomains.length === 0) {
|
|
64179
63986
|
console.error(
|
|
64180
|
-
|
|
63987
|
+
"bili: no hermes providers found in ~/.hermes/config.yaml \u2014 traffic will NOT go through the proxy (configure a provider first)."
|
|
64181
63988
|
);
|
|
64182
63989
|
}
|
|
64183
63990
|
} else if (base === "dsh") {
|