billion-context 0.1.64-pr.360.210 → 0.1.64

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 CHANGED
@@ -50626,153 +50626,6 @@ import { readFileSync as readFileSync3 } from "fs";
50626
50626
  import { dirname as dirname4, join as join3 } from "path";
50627
50627
  import { fileURLToPath } from "url";
50628
50628
 
50629
- // src/web/page.ts
50630
- import { existsSync as existsSync3 } from "fs";
50631
-
50632
- // src/ca.ts
50633
- var import_node_forge = __toESM(require_lib(), 1);
50634
- import fs2 from "fs";
50635
- import path6 from "path";
50636
- import tls2 from "tls";
50637
- var ROOT_CERT_FILE = "root-ca.pem";
50638
- var ROOT_KEY_FILE = "root-ca-key.pem";
50639
- var COMBINED_CA_FILE = "combined-ca.pem";
50640
- var ROOT_CN = "billion-context MITM Root CA";
50641
- var PLATFORM_CA_CANDIDATES = process.platform === "darwin" ? ["/etc/ssl/cert.pem", "/private/etc/ssl/cert.pem"] : [
50642
- "/etc/ssl/certs/ca-certificates.crt",
50643
- "/etc/pki/tls/certs/ca-bundle.crt",
50644
- "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
50645
- "/etc/ssl/ca-bundle.pem",
50646
- "/etc/ssl/cert.pem"
50647
- ];
50648
- var rootCertPem;
50649
- var rootKeyPem;
50650
- var rootCert;
50651
- var rootKey;
50652
- var secureContextCache = /* @__PURE__ */ new Map();
50653
- var SECURE_CONTEXT_CACHE_MAX = 64;
50654
- function rootCaPath() {
50655
- return path6.join(caDir(), ROOT_CERT_FILE);
50656
- }
50657
- function collectSystemCaPems(env = process.env) {
50658
- const pems = [];
50659
- const seen = /* @__PURE__ */ new Set();
50660
- const pushFile = (file) => {
50661
- try {
50662
- const text = fs2.readFileSync(file, "utf8");
50663
- if (!text.includes("BEGIN CERTIFICATE") || seen.has(text)) return false;
50664
- seen.add(text);
50665
- pems.push(text);
50666
- return true;
50667
- } catch {
50668
- }
50669
- return false;
50670
- };
50671
- const userBundle = env.SSL_CERT_FILE?.trim();
50672
- if (userBundle && pushFile(userBundle)) return pems;
50673
- for (const candidate of PLATFORM_CA_CANDIDATES) {
50674
- if (pushFile(candidate)) break;
50675
- }
50676
- return pems;
50677
- }
50678
- function writeCombinedBundle() {
50679
- const certs = /* @__PURE__ */ new Set();
50680
- for (const pem of collectSystemCaPems()) certs.add(pem.trim());
50681
- for (const pem of tls2.rootCertificates) certs.add(pem.trim());
50682
- certs.add(rootCertPem.trim());
50683
- const body = [...certs].map((pem) => pem.endsWith("\n") ? pem : pem + "\n").join("");
50684
- fs2.writeFileSync(path6.join(caDir(), COMBINED_CA_FILE), body, { mode: 420 });
50685
- }
50686
- function generateRootCA() {
50687
- const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
50688
- const cert = import_node_forge.default.pki.createCertificate();
50689
- cert.publicKey = keys.publicKey;
50690
- cert.serialNumber = "01";
50691
- cert.validity.notBefore = /* @__PURE__ */ new Date();
50692
- cert.validity.notAfter = /* @__PURE__ */ new Date();
50693
- cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10);
50694
- const attrs = [
50695
- { name: "commonName", value: ROOT_CN },
50696
- { name: "organizationName", value: "billion-context" }
50697
- ];
50698
- cert.setSubject(attrs);
50699
- cert.setIssuer(attrs);
50700
- cert.setExtensions([
50701
- { name: "basicConstraints", cA: true },
50702
- { name: "keyUsage", keyCertSign: true, cRLSign: true, digitalSignature: true },
50703
- { name: "subjectKeyIdentifier" }
50704
- ]);
50705
- cert.sign(keys.privateKey, import_node_forge.default.md.sha256.create());
50706
- return {
50707
- cert: import_node_forge.default.pki.certificateToPem(cert),
50708
- key: import_node_forge.default.pki.privateKeyToPem(keys.privateKey)
50709
- };
50710
- }
50711
- function ensureRootCA() {
50712
- if (rootCertPem && rootKeyPem) {
50713
- writeCombinedBundle();
50714
- return;
50715
- }
50716
- const dir = caDir();
50717
- fs2.mkdirSync(dir, { recursive: true });
50718
- const certPath = path6.join(dir, ROOT_CERT_FILE);
50719
- const keyPath = path6.join(dir, ROOT_KEY_FILE);
50720
- if (fs2.existsSync(certPath) && fs2.existsSync(keyPath)) {
50721
- rootCertPem = fs2.readFileSync(certPath, "utf8");
50722
- rootKeyPem = fs2.readFileSync(keyPath, "utf8");
50723
- rootCert = import_node_forge.default.pki.certificateFromPem(rootCertPem);
50724
- rootKey = import_node_forge.default.pki.privateKeyFromPem(rootKeyPem);
50725
- writeCombinedBundle();
50726
- return;
50727
- }
50728
- const { cert, key } = generateRootCA();
50729
- fs2.writeFileSync(certPath, cert, { mode: 420 });
50730
- fs2.writeFileSync(keyPath, key, { mode: 384 });
50731
- rootCertPem = cert;
50732
- rootKeyPem = key;
50733
- rootCert = import_node_forge.default.pki.certificateFromPem(cert);
50734
- rootKey = import_node_forge.default.pki.privateKeyFromPem(key);
50735
- writeCombinedBundle();
50736
- }
50737
- function getSecureContext(host) {
50738
- if (!rootCertPem || !rootKeyPem || !rootCert || !rootKey) {
50739
- throw new Error("CA not initialized \u2014 call ensureRootCA() first");
50740
- }
50741
- const cached = secureContextCache.get(host);
50742
- if (cached) {
50743
- secureContextCache.delete(host);
50744
- secureContextCache.set(host, cached);
50745
- return cached;
50746
- }
50747
- const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
50748
- const cert = import_node_forge.default.pki.createCertificate();
50749
- cert.publicKey = keys.publicKey;
50750
- cert.serialNumber = Date.now().toString() + Math.floor(Math.random() * 1e6).toString();
50751
- cert.validity.notBefore = /* @__PURE__ */ new Date();
50752
- cert.validity.notAfter = /* @__PURE__ */ new Date();
50753
- cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 2);
50754
- cert.setSubject([{ name: "commonName", value: host }]);
50755
- cert.setIssuer(rootCert.subject.attributes);
50756
- cert.setExtensions([
50757
- { name: "basicConstraints", cA: false },
50758
- { name: "keyUsage", digitalSignature: true, keyEncipherment: true },
50759
- { name: "extKeyUsage", serverAuth: true },
50760
- { name: "subjectAltName", altNames: [{ type: 2, value: host }] }
50761
- ]);
50762
- cert.sign(rootKey, import_node_forge.default.md.sha256.create());
50763
- const ctx = tls2.createSecureContext({
50764
- cert: import_node_forge.default.pki.certificateToPem(cert),
50765
- key: import_node_forge.default.pki.privateKeyToPem(keys.privateKey),
50766
- ca: rootCertPem
50767
- });
50768
- secureContextCache.set(host, ctx);
50769
- if (secureContextCache.size > SECURE_CONTEXT_CACHE_MAX) {
50770
- const oldest = secureContextCache.keys().next().value;
50771
- if (oldest !== void 0) secureContextCache.delete(oldest);
50772
- }
50773
- return ctx;
50774
- }
50775
-
50776
50629
  // src/web/client.ts
50777
50630
  var WEB_CLIENT = `
50778
50631
  const byId=(id)=>document.getElementById(id);
@@ -50805,13 +50658,7 @@ var WEB_STYLES = `
50805
50658
  `;
50806
50659
 
50807
50660
  // src/web/page.ts
50808
- function escapeHtml(value) {
50809
- return value.replace(/[&<>"']/g, (char) => char === "&" ? "&amp;" : char === "<" ? "&lt;" : char === ">" ? "&gt;" : char === '"' ? "&quot;" : "&#39;");
50810
- }
50811
50661
  function renderPage(origin, version2) {
50812
- const caPath = rootCaPath();
50813
- const caPathEsc = escapeHtml(caPath);
50814
- const caReady = existsSync3(caPath);
50815
50662
  return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>billion-context</title><style>${WEB_STYLES}</style></head><body>
50816
50663
  <div class="app"><aside class="sidebar"><div class="brand"><div class="brand-title">billion<span>-context</span></div><div class="version">v${version2}</div></div><a class="fork-ribbon" href="https://github.com/ranxianglei/billion-context" target="_blank" rel="noopener">\u2605 Fork me on GitHub</a><nav class="nav"><button class="active" data-page="overview">\u6982\u89C8</button><button data-page="routing">\u63A5\u5165</button><button data-page="upstream">\u4E0A\u6E38</button><button data-page="sessions">\u4F1A\u8BDD</button><button data-page="settings">\u8BBE\u7F6E</button></nav></aside>
50817
50664
  <main class="main"><section id="page-overview" class="page active"><h1>\u6982\u89C8</h1><p class="lead">\u672C\u5730\u8DEF\u7531\u4E0E\u4E0A\u6E38\u7F51\u7EDC\u76F8\u4E92\u72EC\u7ACB\uFF0CACP \u538B\u7F29\u8FD0\u884C\u5728\u4E24\u8005\u4E4B\u95F4\u3002</p><div class="grid"><div class="card"><h2>\u670D\u52A1\u5730\u5740</h2><p class="mono">${origin}</p></div><div class="card"><h2>\u5BA2\u6237\u7AEF\u63A5\u5165</h2><p class="status">\u5728"\u63A5\u5165"\u9875\u5C06\u5404\u5BA2\u6237\u7AEF\uFF08Codex / Claude Code / OpenCode / Pi \u7B49\uFF09\u7684\u6D41\u91CF\u8DEF\u7531\u5230 bili\u3002</p></div></div></section>
@@ -50826,14 +50673,14 @@ function renderPage(origin, version2) {
50826
50673
  <div class="card"><div class="card-head"><h2>\u5176\u4ED6\uFF08Cursor / Aider / Continue\uFF09</h2><button class="btn small copy-btn" data-copy="${origin}/bili/">\u590D\u5236</button></div><dl class="kv"><dt>\u89C4\u5219</dt><dd>\u4EFB\u610F baseURL \u524D\u52A0 <span class="mono">${origin}/bili/</span></dd><dt>\u793A\u4F8B</dt><dd class="mono">${origin}/bili/https://api.openai.com/v1</dd></dl></div>
50827
50674
  <h2 class="section-title">B. \u8BC1\u4E66\u63A5\u5165\u65B9\u5F0F\uFF08zcode \u7B49\u7C7B\u578B\uFF09</h2>
50828
50675
  <p class="hint">\u4E0D\u652F\u6301\u6539 URL \u7684\u5BA2\u6237\u7AEF\uFF08endpoint \u786C\u7F16\u7801\uFF09\u9700 MITM \u900F\u660E\u4EE3\u7406\uFF0C\u8BBE HTTPS_PROXY + \u4FE1\u4EFB CA \u8BC1\u4E66\u3002</p>
50829
- <div class="card"><div class="card-head"><h2>ZCode\uFF08\u7F16\u7A0B\u5957\u9910\uFF09</h2><span class="badge">MITM</span><button class="btn small copy-btn" data-copy="${caPathEsc}">\u590D\u5236 CA \u8DEF\u5F84</button></div><dl class="kv"><dt>\u65B9\u5F0F</dt><dd>MITM \u900F\u660E\u4EE3\u7406</dd><dt>\u8BBE\u7F6E</dt><dd>Settings \u2192 Network \u2192 HTTP Proxy = <span class="mono">${origin}</span></dd><dt>CA \u8BC1\u4E66</dt><dd class="mono">${caPathEsc}${caReady ? "" : "\uFF08\u5C1A\u672A\u751F\u6210\uFF0C\u542F\u52A8\u4EE3\u7406\u540E\u81EA\u52A8\u521B\u5EFA\uFF09"}</dd></dl><p class="hint">CA \u8DEF\u5F84\u662F\u672C\u673A bili \u5B9E\u9645\u751F\u6210\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u70B9"\u590D\u5236 CA \u8DEF\u5F84"\u540E\u76F4\u63A5\u7C98\u8D34\u8FDB ZCode\u3002\u26A0\uFE0F Windows \u4E0A ZCode \u4E0D\u4F1A\u5C55\u5F00 <span class="mono">~</span>\uFF0C\u8BF7\u52FF\u624B\u586B <span class="mono">~/\u2026</span> \u5F62\u5F0F\u7684\u8DEF\u5F84\u3002</p></div></section>
50676
+ <div class="card"><div class="card-head"><h2>ZCode\uFF08\u7F16\u7A0B\u5957\u9910\uFF09</h2><span class="badge">MITM</span></div><dl class="kv"><dt>\u65B9\u5F0F</dt><dd>MITM \u900F\u660E\u4EE3\u7406</dd><dt>\u8BBE\u7F6E</dt><dd>Settings \u2192 Network \u2192 HTTP Proxy = <span class="mono">${origin}</span></dd><dt>CA \u8BC1\u4E66</dt><dd class="mono">~/.local/share/billion-context/ca/root-ca.pem</dd></dl></div></section>
50830
50677
  <section id="page-upstream" class="page"><h1>\u4E0A\u6E38\u7F51\u7EDC</h1><p class="lead">\u63A7\u5236 bili \u5982\u4F55\u8BBF\u95EE\u771F\u5B9E Provider\uFF0C\u4E0D\u4F1A\u6539\u53D8\u5BA2\u6237\u7AEF\u7684\u672C\u5730\u8DEF\u7531\u5730\u5740\u3002</p><div class="card"><div class="card-head"><h2>\u5168\u5C40\u4EE3\u7406</h2></div><div class="modes"><label><input type="radio" name="proxy-mode" value="direct" checked>\u76F4\u8FDE\uFF08\u9ED8\u8BA4\uFF09</label><label><input type="radio" name="proxy-mode" value="manual">\u624B\u52A8\u4EE3\u7406</label><label><input type="radio" name="proxy-mode" value="auto">\u81EA\u52A8\uFF08\u8DDF\u968F\u7CFB\u7EDF\uFF09</label></div><div class="field"><label>HTTP / HTTPS Proxy</label><input id="proxy-url" class="mono" placeholder="http://127.0.0.1:7897"></div><dl class="kv"><dt>\u5F53\u524D\u6765\u6E90</dt><dd id="upstream-source">\u76F4\u8FDE</dd><dt>\u6709\u6548\u4EE3\u7406</dt><dd id="upstream-effective" class="mono">direct</dd><dt>\u7CFB\u7EDF PAC</dt><dd id="upstream-pac" class="mono">\u2014</dd><dt>\u72B6\u6001</dt><dd id="upstream-state" class="status">\u5C1A\u672A\u6D4B\u8BD5</dd></dl><div class="actions"><button id="save-upstream" class="btn primary">\u4FDD\u5B58\u5E76\u70ED\u66F4\u65B0</button><button id="test-upstream" class="btn">\u6D4B\u8BD5\u8FDE\u63A5</button></div></div><div class="card"><div class="card-head"><h2>\u6309 URL \u8986\u76D6</h2></div><p class="status">\u4E3A\u7279\u5B9A Provider \u5355\u72EC\u8BBE\u7F6E\u4E0A\u6E38\u4EE3\u7406\uFF0C\u8986\u76D6\u5168\u5C40\u8BBE\u7F6E\u3002\u7559\u7A7A = \u7EE7\u627F\u5168\u5C40\u3002</p><div id="upstream-overrides" class="status">\u52A0\u8F7D\u4E2D</div><div class="actions"><button id="save-overrides" class="btn primary">\u4FDD\u5B58\u8986\u76D6\u5E76\u70ED\u66F4\u65B0</button></div></div></section>
50831
50678
  <section id="page-sessions" class="page"><div class="card-head"><div><h1>\u4F1A\u8BDD</h1><p class="lead">ACP \u538B\u7F29\u72B6\u6001\u4E0E\u4E0A\u6E38\u7528\u91CF\u3002</p></div><button id="refresh-sessions" class="btn">\u5237\u65B0</button></div><div class="card"><table><thead><tr><th>\u6807\u9898</th><th>\u534F\u8BAE</th><th>\u6807\u8BC6</th><th>\u8BF7\u6C42</th><th>\u4E0A\u4E0B\u6587</th><th>\u6700\u540E\u6D3B\u52A8</th></tr></thead><tbody id="sessions-body"></tbody></table></div></section>
50832
50679
  <section id="page-settings" class="page"><h1>\u9AD8\u7EA7\u8BBE\u7F6E</h1><p class="lead">\u76F4\u63A5\u7F16\u8F91 providers JSON\uFF08\u6DFB\u52A0\u65B0 Provider\u3001\u914D\u7F6E\u6A21\u578B\u4E0A\u4E0B\u6587\u7A97\u53E3\u3001\u6309 URL \u4EE3\u7406\u7B49\uFF09\uFF1B\u4FDD\u5B58\u540E\u7ACB\u5373\u70ED\u66F4\u65B0\u3002</p><div class="card"><div class="field"><label>providers JSON</label><textarea id="providers-json">{}</textarea></div><div class="actions"><button id="save-providers" class="btn primary">\u4FDD\u5B58\u5E76\u5E94\u7528</button></div></div><div class="card"><div class="card-head"><h2>\u538B\u7F29\u53C2\u6570\uFF08\u5168\u5C40\uFF09</h2></div><p class="status">\u5168\u5C40 compress \u914D\u7F6E\uFF08modelContextLimit / maxContextLimit / emergencyThresholdPercent / nudgeGrowthTokens / preserveRecentMessages / preserveRecentTokens / minCompressRange / tiers / injectTool / injectNudge\uFF09\u3002\u4FDD\u5B58\u540E\u70ED\u66F4\u65B0\uFF0C\u65E0\u9700\u91CD\u542F\u3002\u7F6E\u7A7A = \u6062\u590D\u9ED8\u8BA4\u3002</p><div class="field"><label>compress JSON</label><textarea id="compress-json" placeholder='{"modelContextLimit": 200000}'></textarea></div><div class="actions"><button id="save-compress" class="btn primary">\u4FDD\u5B58\u5E76\u70ED\u66F4\u65B0</button></div></div></section></main></div><div id="toast" class="toast"></div><script>${WEB_CLIENT}</script></body></html>`;
50833
50680
  }
50834
50681
 
50835
50682
  // src/web/api.ts
50836
- import { closeSync, existsSync as existsSync4, fsyncSync, mkdirSync as mkdirSync4, openSync, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
50683
+ import { closeSync, existsSync as existsSync3, fsyncSync, mkdirSync as mkdirSync4, openSync, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
50837
50684
  import { dirname as dirname3 } from "path";
50838
50685
  import { randomUUID as randomUUID2 } from "crypto";
50839
50686
  function readConfig() {
@@ -50841,7 +50688,7 @@ function readConfig() {
50841
50688
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
50842
50689
  }
50843
50690
  function configParseError() {
50844
- if (!existsSync4(configFile())) return null;
50691
+ if (!existsSync3(configFile())) return null;
50845
50692
  const parsed = safeReadJson(configFile());
50846
50693
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return null;
50847
50694
  return `config file is not valid JSON: ${configFile()}`;
@@ -52890,65 +52737,6 @@ async function compressLoopResponsesJson(initialResponse, ctx, requestBody, requ
52890
52737
  return current;
52891
52738
  }
52892
52739
 
52893
- // src/acp-panel.ts
52894
- var PANEL_BOX_TOP = "\u256D";
52895
- var PANEL_BOX_TITLE = "ACP Context Analysis";
52896
- var PANEL_FALLBACK_HEADER = "\u{1F4CA} ACP status";
52897
- function isAcpPanelText(text) {
52898
- const t = text.trim();
52899
- if (t.length === 0) return false;
52900
- if (t.startsWith(PANEL_BOX_TOP) && t.includes(PANEL_BOX_TITLE)) return true;
52901
- if (t.startsWith(PANEL_FALLBACK_HEADER)) return true;
52902
- return false;
52903
- }
52904
- function messageText(content) {
52905
- if (typeof content === "string") return content;
52906
- if (Array.isArray(content)) {
52907
- let joined = "";
52908
- for (const part of content) {
52909
- const p2 = part;
52910
- if (p2 === null || typeof p2 !== "object") return void 0;
52911
- const pt2 = p2.type;
52912
- if (pt2 !== void 0 && pt2 !== "text" && pt2 !== "input_text" && pt2 !== "output_text") return void 0;
52913
- if (typeof p2.text === "string") joined += p2.text;
52914
- }
52915
- return joined;
52916
- }
52917
- return void 0;
52918
- }
52919
- function stripAcpPanelMessages(messages) {
52920
- if (!Array.isArray(messages)) return 0;
52921
- let stripped = 0;
52922
- for (let i = messages.length - 1; i >= 0; i--) {
52923
- const rec = messages[i];
52924
- if (rec === null || typeof rec !== "object") continue;
52925
- if (rec.role !== "user") continue;
52926
- const text = messageText(rec.content);
52927
- if (text !== void 0 && isAcpPanelText(text)) {
52928
- messages.splice(i, 1);
52929
- stripped++;
52930
- }
52931
- }
52932
- return stripped;
52933
- }
52934
- function stripAcpPanelResponsesInput(input) {
52935
- if (!Array.isArray(input)) return 0;
52936
- let stripped = 0;
52937
- for (let i = input.length - 1; i >= 0; i--) {
52938
- const rec = input[i];
52939
- if (rec === null || typeof rec !== "object") continue;
52940
- const type = rec.type;
52941
- if (type !== "message" && type !== void 0) continue;
52942
- if (rec.role !== "user") continue;
52943
- const text = messageText(rec.content);
52944
- if (text !== void 0 && isAcpPanelText(text)) {
52945
- input.splice(i, 1);
52946
- stripped++;
52947
- }
52948
- }
52949
- return stripped;
52950
- }
52951
-
52952
52740
  // src/stream-openai.ts
52953
52741
  function rewriteOpenaiJsonResponse(body, ctx) {
52954
52742
  if (!body || typeof body !== "object") return body;
@@ -53557,13 +53345,13 @@ function buildStatusPanel(input) {
53557
53345
 
53558
53346
  // src/plugin.ts
53559
53347
  import { fileURLToPath as fileURLToPath2 } from "url";
53560
- import fs3 from "fs";
53561
- import path7 from "path";
53348
+ import fs2 from "fs";
53349
+ import path6 from "path";
53562
53350
  var PROXY_VERSION = (() => {
53563
53351
  try {
53564
53352
  const here = fileURLToPath2(import.meta.url);
53565
- const pkg = path7.join(path7.dirname(here), "..", "package.json");
53566
- return JSON.parse(fs3.readFileSync(pkg, "utf8")).version ?? "dev";
53353
+ const pkg = path6.join(path6.dirname(here), "..", "package.json");
53354
+ return JSON.parse(fs2.readFileSync(pkg, "utf8")).version ?? "dev";
53567
53355
  } catch {
53568
53356
  return "dev";
53569
53357
  }
@@ -53575,8 +53363,8 @@ var PLUGIN_PROTOCOL_VERSION = 1;
53575
53363
  var VERSION = (() => {
53576
53364
  try {
53577
53365
  const here = fileURLToPath2(import.meta.url);
53578
- const pkg = path7.join(path7.dirname(here), "..", "package.json");
53579
- return JSON.parse(fs3.readFileSync(pkg, "utf8")).version ?? "dev";
53366
+ const pkg = path6.join(path6.dirname(here), "..", "package.json");
53367
+ return JSON.parse(fs2.readFileSync(pkg, "utf8")).version ?? "dev";
53580
53368
  } catch {
53581
53369
  return "dev";
53582
53370
  }
@@ -53605,14 +53393,14 @@ function pluginReportedContextWindow(headers) {
53605
53393
  var MAX_PLUGIN_CONVERSATIONS = 1024;
53606
53394
  var conversations = /* @__PURE__ */ new Map();
53607
53395
  var remembered = /* @__PURE__ */ new Map();
53608
- var conversationsFile = () => path7.join(stateDir(), "plugin-conversations.json");
53396
+ var conversationsFile = () => path6.join(stateDir(), "plugin-conversations.json");
53609
53397
  var conversationsSaveTimer;
53610
53398
  function writeConversationsFile() {
53611
53399
  try {
53612
53400
  const obj = {};
53613
53401
  for (const [k2, v2] of conversations) obj[k2] = v2;
53614
- fs3.mkdirSync(stateDir(), { recursive: true });
53615
- fs3.writeFileSync(conversationsFile(), JSON.stringify(obj));
53402
+ fs2.mkdirSync(stateDir(), { recursive: true });
53403
+ fs2.writeFileSync(conversationsFile(), JSON.stringify(obj));
53616
53404
  } catch {
53617
53405
  }
53618
53406
  }
@@ -53632,7 +53420,7 @@ function flushConversations() {
53632
53420
  }
53633
53421
  function loadConversations() {
53634
53422
  try {
53635
- const raw = fs3.readFileSync(conversationsFile(), "utf8");
53423
+ const raw = fs2.readFileSync(conversationsFile(), "utf8");
53636
53424
  const obj = JSON.parse(raw);
53637
53425
  for (const [k2, v2] of Object.entries(obj)) {
53638
53426
  if (v2 && typeof v2.sessionId === "string" && v2.sessionId.length > 0) {
@@ -54093,6 +53881,147 @@ async function pipePluginJson(stream2, res, session, protocol) {
54093
53881
  // src/mitm.ts
54094
53882
  import tls3 from "tls";
54095
53883
 
53884
+ // src/ca.ts
53885
+ var import_node_forge = __toESM(require_lib(), 1);
53886
+ import fs3 from "fs";
53887
+ import path7 from "path";
53888
+ import tls2 from "tls";
53889
+ var ROOT_CERT_FILE = "root-ca.pem";
53890
+ var ROOT_KEY_FILE = "root-ca-key.pem";
53891
+ var COMBINED_CA_FILE = "combined-ca.pem";
53892
+ var ROOT_CN = "billion-context MITM Root CA";
53893
+ var PLATFORM_CA_CANDIDATES = process.platform === "darwin" ? ["/etc/ssl/cert.pem", "/private/etc/ssl/cert.pem"] : [
53894
+ "/etc/ssl/certs/ca-certificates.crt",
53895
+ "/etc/pki/tls/certs/ca-bundle.crt",
53896
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
53897
+ "/etc/ssl/ca-bundle.pem",
53898
+ "/etc/ssl/cert.pem"
53899
+ ];
53900
+ var rootCertPem;
53901
+ var rootKeyPem;
53902
+ var rootCert;
53903
+ var rootKey;
53904
+ var secureContextCache = /* @__PURE__ */ new Map();
53905
+ var SECURE_CONTEXT_CACHE_MAX = 64;
53906
+ function collectSystemCaPems(env = process.env) {
53907
+ const pems = [];
53908
+ const seen = /* @__PURE__ */ new Set();
53909
+ const pushFile = (file) => {
53910
+ try {
53911
+ const text = fs3.readFileSync(file, "utf8");
53912
+ if (!text.includes("BEGIN CERTIFICATE") || seen.has(text)) return false;
53913
+ seen.add(text);
53914
+ pems.push(text);
53915
+ return true;
53916
+ } catch {
53917
+ }
53918
+ return false;
53919
+ };
53920
+ const userBundle = env.SSL_CERT_FILE?.trim();
53921
+ if (userBundle && pushFile(userBundle)) return pems;
53922
+ for (const candidate of PLATFORM_CA_CANDIDATES) {
53923
+ if (pushFile(candidate)) break;
53924
+ }
53925
+ return pems;
53926
+ }
53927
+ function writeCombinedBundle() {
53928
+ const certs = /* @__PURE__ */ new Set();
53929
+ for (const pem of collectSystemCaPems()) certs.add(pem.trim());
53930
+ for (const pem of tls2.rootCertificates) certs.add(pem.trim());
53931
+ certs.add(rootCertPem.trim());
53932
+ const body = [...certs].map((pem) => pem.endsWith("\n") ? pem : pem + "\n").join("");
53933
+ fs3.writeFileSync(path7.join(caDir(), COMBINED_CA_FILE), body, { mode: 420 });
53934
+ }
53935
+ function generateRootCA() {
53936
+ const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
53937
+ const cert = import_node_forge.default.pki.createCertificate();
53938
+ cert.publicKey = keys.publicKey;
53939
+ cert.serialNumber = "01";
53940
+ cert.validity.notBefore = /* @__PURE__ */ new Date();
53941
+ cert.validity.notAfter = /* @__PURE__ */ new Date();
53942
+ cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10);
53943
+ const attrs = [
53944
+ { name: "commonName", value: ROOT_CN },
53945
+ { name: "organizationName", value: "billion-context" }
53946
+ ];
53947
+ cert.setSubject(attrs);
53948
+ cert.setIssuer(attrs);
53949
+ cert.setExtensions([
53950
+ { name: "basicConstraints", cA: true },
53951
+ { name: "keyUsage", keyCertSign: true, cRLSign: true, digitalSignature: true },
53952
+ { name: "subjectKeyIdentifier" }
53953
+ ]);
53954
+ cert.sign(keys.privateKey, import_node_forge.default.md.sha256.create());
53955
+ return {
53956
+ cert: import_node_forge.default.pki.certificateToPem(cert),
53957
+ key: import_node_forge.default.pki.privateKeyToPem(keys.privateKey)
53958
+ };
53959
+ }
53960
+ function ensureRootCA() {
53961
+ if (rootCertPem && rootKeyPem) {
53962
+ writeCombinedBundle();
53963
+ return;
53964
+ }
53965
+ const dir = caDir();
53966
+ fs3.mkdirSync(dir, { recursive: true });
53967
+ const certPath = path7.join(dir, ROOT_CERT_FILE);
53968
+ const keyPath = path7.join(dir, ROOT_KEY_FILE);
53969
+ if (fs3.existsSync(certPath) && fs3.existsSync(keyPath)) {
53970
+ rootCertPem = fs3.readFileSync(certPath, "utf8");
53971
+ rootKeyPem = fs3.readFileSync(keyPath, "utf8");
53972
+ rootCert = import_node_forge.default.pki.certificateFromPem(rootCertPem);
53973
+ rootKey = import_node_forge.default.pki.privateKeyFromPem(rootKeyPem);
53974
+ writeCombinedBundle();
53975
+ return;
53976
+ }
53977
+ const { cert, key } = generateRootCA();
53978
+ fs3.writeFileSync(certPath, cert, { mode: 420 });
53979
+ fs3.writeFileSync(keyPath, key, { mode: 384 });
53980
+ rootCertPem = cert;
53981
+ rootKeyPem = key;
53982
+ rootCert = import_node_forge.default.pki.certificateFromPem(cert);
53983
+ rootKey = import_node_forge.default.pki.privateKeyFromPem(key);
53984
+ writeCombinedBundle();
53985
+ }
53986
+ function getSecureContext(host) {
53987
+ if (!rootCertPem || !rootKeyPem || !rootCert || !rootKey) {
53988
+ throw new Error("CA not initialized \u2014 call ensureRootCA() first");
53989
+ }
53990
+ const cached = secureContextCache.get(host);
53991
+ if (cached) {
53992
+ secureContextCache.delete(host);
53993
+ secureContextCache.set(host, cached);
53994
+ return cached;
53995
+ }
53996
+ const keys = import_node_forge.default.pki.rsa.generateKeyPair({ bits: 2048 });
53997
+ const cert = import_node_forge.default.pki.createCertificate();
53998
+ cert.publicKey = keys.publicKey;
53999
+ cert.serialNumber = Date.now().toString() + Math.floor(Math.random() * 1e6).toString();
54000
+ cert.validity.notBefore = /* @__PURE__ */ new Date();
54001
+ cert.validity.notAfter = /* @__PURE__ */ new Date();
54002
+ cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 2);
54003
+ cert.setSubject([{ name: "commonName", value: host }]);
54004
+ cert.setIssuer(rootCert.subject.attributes);
54005
+ cert.setExtensions([
54006
+ { name: "basicConstraints", cA: false },
54007
+ { name: "keyUsage", digitalSignature: true, keyEncipherment: true },
54008
+ { name: "extKeyUsage", serverAuth: true },
54009
+ { name: "subjectAltName", altNames: [{ type: 2, value: host }] }
54010
+ ]);
54011
+ cert.sign(rootKey, import_node_forge.default.md.sha256.create());
54012
+ const ctx = tls2.createSecureContext({
54013
+ cert: import_node_forge.default.pki.certificateToPem(cert),
54014
+ key: import_node_forge.default.pki.privateKeyToPem(keys.privateKey),
54015
+ ca: rootCertPem
54016
+ });
54017
+ secureContextCache.set(host, ctx);
54018
+ if (secureContextCache.size > SECURE_CONTEXT_CACHE_MAX) {
54019
+ const oldest = secureContextCache.keys().next().value;
54020
+ if (oldest !== void 0) secureContextCache.delete(oldest);
54021
+ }
54022
+ return ctx;
54023
+ }
54024
+
54096
54025
  // src/discover.ts
54097
54026
  import fs5 from "fs";
54098
54027
  import os2 from "os";
@@ -56142,10 +56071,6 @@ function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, sessio
56142
56071
  let rebuiltMessages = parsed.messages;
56143
56072
  let systemOut = parsed.system;
56144
56073
  let toolsOut = parsed.tools;
56145
- const strippedPanels = stripAcpPanelMessages(parsed.messages);
56146
- if (strippedPanels > 0) {
56147
- log2("info", `[${sessionId}] stripped ${strippedPanels} ACP panel message(s) before projection (UI-only, issue #359)`);
56148
- }
56149
56074
  try {
56150
56075
  const { msgs, cacheControls } = anthropicToCore(parsed);
56151
56076
  originalMessages = msgs;
@@ -56202,10 +56127,6 @@ function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session,
56202
56127
  const isTitleGen = maxTokens <= 200;
56203
56128
  const shouldInject = opts.compress.injectTool && !isTitleGen;
56204
56129
  const injectTools = shouldInject && !pluginMode;
56205
- const strippedPanels = stripAcpPanelMessages(parsed.messages);
56206
- if (strippedPanels > 0) {
56207
- log2("info", `[${sessionId}] stripped ${strippedPanels} ACP panel message(s) before projection (UI-only, issue #359)`);
56208
- }
56209
56130
  try {
56210
56131
  const { msgs, systemText } = openaiToCore(parsed);
56211
56132
  openaiSystemText = systemText;
@@ -56287,10 +56208,6 @@ function prepareResponses(parsed, req, opts, core, config, prompts, log2, sessio
56287
56208
  if (droppedEmpty > 0) {
56288
56209
  log2("info", `[${sessionId}] dropped ${droppedEmpty} whitespace-only message item(s) before projection (flattened-turn artifact)`);
56289
56210
  }
56290
- const strippedPanels = stripAcpPanelResponsesInput(parsed.input);
56291
- if (strippedPanels > 0) {
56292
- log2("info", `[${sessionId}] stripped ${strippedPanels} ACP panel message(s) before projection (UI-only, issue #359)`);
56293
- }
56294
56211
  const shouldInject = opts.compress.injectTool;
56295
56212
  const injectTools = shouldInject && !pluginMode;
56296
56213
  const isCompactionTrigger = hasCompactionTrigger(parsed.input);