billion-context 0.1.84-pr.537.356 → 0.1.84

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 CHANGED
@@ -112,18 +112,6 @@ turn is a semantic mismatch the model tolerates (it is clearly marked
112
112
  summaries (their tool call isn't in the agent's history and the agent's view
113
113
  skips `acp_summary`) — but that needs the id match above, which doesn't occur.
114
114
 
115
- ### Injection priority — no files unless unavoidable
116
-
117
- How the launcher points a client at the proxy follows a strict priority
118
- (#535): **env vars** (`HTTPS_PROXY` cert-MITM for discovered upstream hosts,
119
- `HTTP_PROXY` absolute-form requests for plaintext-http upstreams, plus the
120
- per-client CA trust variable) > **client-native CLI flags / extension APIs**
121
- > **generated config files** (last resort — today omp's overlay and dsh's
122
- loopback exception). No real config file is ever edited, and bili never owns
123
- user data: clients run against their real home directory, and pre-existing
124
- overlay dirs from older versions (e.g. `~/.hermes-bili`) are left in place,
125
- unmigrated.
126
-
127
115
  ## Which do I need?
128
116
 
129
117
  Pick by your client:
@@ -169,8 +157,8 @@ bili codex # launch codex through the proxy
169
157
  bili claude # launch claude through the proxy
170
158
  bili omp # pi-style: MITM env + persistent overlay home (~/.omp/agent-bili, real config untouched)
171
159
  bili opencode # MITM for HTTPS + temp opencode.json (/bili/ for HTTP) + thin /acp plugin
172
- bili hermes # HTTPS_PROXY cert-MITM (HERMES_CA_BUNDLE) + HTTP_PROXY for plaintext upstreams; identity plugin in real ~/.hermes
173
- bili dsh # deepseek-harness: MITM env incl. built-in deepseek route + HTTP_PROXY for non-loopback plaintext; loopback keeps settings.yaml overlay (~/.dsh-bili); native /acp via --patch
160
+ bili hermes # no MITM possible (certifi CA) — persistent overlay home (~/.hermes-bili), all traffic /bili/
161
+ bili dsh # deepseek-harness: built-in deepseek route via DEEPSEEK_BASE_URL + overlay DSH_HOME (~/.dsh-bili), all traffic /bili/, native /acp command injected via --patch
174
162
  bili pi --mitm-domain api.foo.com # add a domain to the MITM whitelist
175
163
  ```
176
164
 
package/README.zh-CN.md CHANGED
@@ -88,8 +88,8 @@ bili codex # 拉起 codex
88
88
  bili claude # 拉起 claude
89
89
  bili omp # pi 同款 MITM 环境变量 + 隔离临时 models.yml
90
90
  bili opencode # HTTPS 走 MITM + 临时 opencode.json(HTTP 走 /bili/)+ 轻量 /acp 插件
91
- bili hermes # HTTPS_PROXY 证书 MITM(HERMES_CA_BUNDLE)+ HTTP_PROXY 走明文上游;身份插件装入真实 ~/.hermes
92
- bili dsh # deepseek-harness:MITM 环境变量(含内置 deepseek 路由)+ HTTP_PROXY 走非回环明文上游;回环上游保留 settings.yaml overlay(~/.dsh-bili);经 --patch 注入原生 /acp 命令
91
+ bili hermes # 无法 MITM(certifi CA)—— 隔离 HERMES_HOME,全部流量 /bili/
92
+ bili dsh # deepseek-harness:内置 deepseek 路由走 DEEPSEEK_BASE_URL + 隔离 DSH_HOME(~/.dsh-bili),全部流量 /bili/,经 --patch 注入原生 /acp 命令
93
93
  bili pi --mitm-domain api.foo.com # 向 MITM 白名单追加域名
94
94
  ```
95
95
 
package/dist/index.js CHANGED
@@ -56901,13 +56901,6 @@ function resolveUpstream(_opts, reqUrl, req) {
56901
56901
  const mitmKey = mitmUpstream.replace(/^https:\/\//, "mitm://");
56902
56902
  return { upstream: mitmUpstream, rewrittenUrl: mitmKey + (reqUrl ?? "") };
56903
56903
  }
56904
- if (/^https?:\/\//i.test(reqUrl)) {
56905
- try {
56906
- const u2 = new URL(reqUrl);
56907
- return { upstream: `${u2.protocol}//${u2.host}`, rewrittenUrl: reqUrl, tunnel: true };
56908
- } catch {
56909
- }
56910
- }
56911
56904
  const KNOWN_PROTOCOLS = ["responses", "anthropic", "openai"];
56912
56905
  if (reqUrl.startsWith("/bili/")) {
56913
56906
  let rest = reqUrl.slice(6);
@@ -62796,12 +62789,6 @@ function unwrapUpstream2(url) {
62796
62789
  const idx = url.indexOf("/bili/");
62797
62790
  return idx >= 0 ? url.slice(idx + "/bili/".length) : url;
62798
62791
  }
62799
- function isLoopbackHost(host) {
62800
- const h = host.toLowerCase();
62801
- if (h === "localhost" || h === "::1" || h === "[::1]") return true;
62802
- const m2 = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(h);
62803
- return m2 !== null && m2[1] === "127";
62804
- }
62805
62792
  function resolveCaCertPath(env) {
62806
62793
  const base = env.XDG_DATA_HOME || path15.join(os5.homedir(), ".local/share");
62807
62794
  return path15.join(base, "billion-context", "ca", "root-ca.pem");
@@ -62814,8 +62801,6 @@ function discoverRoutes(client, config) {
62814
62801
  const httpsDomains = [];
62815
62802
  const httpRewrites = [];
62816
62803
  const httpsRewrites = [];
62817
- const httpEnvRoutes = [];
62818
- const providerKeys = [];
62819
62804
  const httpsSeen = /* @__PURE__ */ new Set();
62820
62805
  const rewriteKeys = /* @__PURE__ */ new Set();
62821
62806
  const httpsRewriteKeys = /* @__PURE__ */ new Set();
@@ -62872,25 +62857,14 @@ function discoverRoutes(client, config) {
62872
62857
  for (const [name, prov] of Object.entries(config.hermes?.providers ?? {})) {
62873
62858
  if (!nonEmpty2(prov.api)) continue;
62874
62859
  const real = unwrapUpstream2(prov.api);
62875
- let url;
62876
62860
  try {
62877
- url = new URL(real);
62861
+ const url = new URL(real);
62862
+ if (url.protocol !== "http:" && url.protocol !== "https:") continue;
62863
+ if (hermesSeen.has(name)) continue;
62864
+ hermesSeen.add(name);
62865
+ rewriteKeys.add(name);
62866
+ httpRewrites.push({ key: name, realUpstream: real });
62878
62867
  } catch {
62879
- continue;
62880
- }
62881
- if (url.protocol !== "http:" && url.protocol !== "https:") continue;
62882
- if (hermesSeen.has(name)) continue;
62883
- hermesSeen.add(name);
62884
- rewriteKeys.add(name);
62885
- providerKeys.push(name);
62886
- if (url.protocol === "https:") {
62887
- const host = url.hostname;
62888
- if (host && !httpsSeen.has(host.toLowerCase())) {
62889
- httpsSeen.add(host.toLowerCase());
62890
- httpsDomains.push(host);
62891
- }
62892
- } else {
62893
- httpEnvRoutes.push(real);
62894
62868
  }
62895
62869
  }
62896
62870
  } else if (client === "dsh") {
@@ -62898,27 +62872,15 @@ function discoverRoutes(client, config) {
62898
62872
  let anon = 0;
62899
62873
  for (const raw of config.dsh?.baseUrls ?? []) {
62900
62874
  const real = unwrapUpstream2(raw);
62901
- let url;
62902
62875
  try {
62903
- url = new URL(real);
62904
- } catch {
62905
- continue;
62906
- }
62907
- if (url.protocol !== "http:" && url.protocol !== "https:") continue;
62908
- if (dshSeen.has(real)) continue;
62909
- dshSeen.add(real);
62910
- if (isLoopbackHost(url.hostname)) {
62876
+ const url = new URL(real);
62877
+ if (url.protocol !== "http:" && url.protocol !== "https:") continue;
62878
+ if (dshSeen.has(real)) continue;
62879
+ dshSeen.add(real);
62911
62880
  anon += 1;
62912
62881
  rewriteKeys.add(`dsh-${anon}`);
62913
62882
  httpRewrites.push({ key: `dsh-${anon}`, realUpstream: real });
62914
- } else if (url.protocol === "https:") {
62915
- const host = url.hostname;
62916
- if (!httpsSeen.has(host.toLowerCase())) {
62917
- httpsSeen.add(host.toLowerCase());
62918
- httpsDomains.push(host);
62919
- }
62920
- } else {
62921
- httpEnvRoutes.push(real);
62883
+ } catch {
62922
62884
  }
62923
62885
  }
62924
62886
  } else {
@@ -62927,7 +62889,7 @@ function discoverRoutes(client, config) {
62927
62889
  }
62928
62890
  classify(config.codex?.openaiBaseUrl, "openai_base_url");
62929
62891
  }
62930
- return { httpsDomains, httpRewrites, httpsRewrites, httpEnvRoutes, providerKeys };
62892
+ return { httpsDomains, httpRewrites, httpsRewrites };
62931
62893
  }
62932
62894
  function discoverDomains(client, config) {
62933
62895
  return discoverRoutes(client, config).httpsDomains;
@@ -63707,12 +63669,53 @@ function prepareOmpHttpRewrite(ompHome, origin, httpRewrites, httpsRewrites) {
63707
63669
  writeOmpCompactionDisabledConfig(ompHome, overlay);
63708
63670
  return overlay;
63709
63671
  }
63710
- function writeHermesIdentityPlugin(hermesHome, providerKeys) {
63711
- const dir = path15.join(hermesHome, "plugins", "model-providers", "bili-session-identity");
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;
63712
63676
  try {
63713
- fs12.mkdirSync(dir, { recursive: true });
63714
- fs12.writeFileSync(path15.join(dir, "__init__.py"), hermesIdentityPluginSource(providerKeys));
63715
- fs12.writeFileSync(path15.join(dir, "plugin.yaml"), [
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"), [
63716
63719
  "name: bili-session-identity",
63717
63720
  "kind: model-provider",
63718
63721
  "version: 1.0.0",
@@ -63724,7 +63727,7 @@ function writeHermesIdentityPlugin(hermesHome, providerKeys) {
63724
63727
  return false;
63725
63728
  }
63726
63729
  try {
63727
- return fs12.existsSync(path15.join(dir, "__init__.py"));
63730
+ return fs12.existsSync(path15.join(overlay, dir, "__init__.py"));
63728
63731
  } catch {
63729
63732
  return false;
63730
63733
  }
@@ -63947,17 +63950,6 @@ function stripInheritedProxy(env) {
63947
63950
  for (const key of INHERITED_PROXY_VARS) delete cleaned[key];
63948
63951
  return cleaned;
63949
63952
  }
63950
- function stripLoopbackNoProxy(env) {
63951
- const out = { ...env };
63952
- for (const key of ["NO_PROXY", "no_proxy"]) {
63953
- const value = out[key];
63954
- if (typeof value !== "string" || value.length === 0) continue;
63955
- const kept = value.split(",").map((s3) => s3.trim()).filter((s3) => s3.length > 0 && !isLoopbackHost(s3));
63956
- if (kept.length > 0) out[key] = kept.join(",");
63957
- else delete out[key];
63958
- }
63959
- return out;
63960
- }
63961
63953
  function proxyStartArgs(opts) {
63962
63954
  const args = ["start", "--host", opts.host, "--port", String(opts.port)];
63963
63955
  if (opts.passthrough) args.push("--passthrough");
@@ -64110,11 +64102,10 @@ async function runLaunch(params, deps = {}) {
64110
64102
  const base = baseClientName(params.client);
64111
64103
  const routes = discoverRoutes(base, config);
64112
64104
  const biliRoutes = loadRoutes(process.env);
64113
- const builtinDomains = base === "dsh" ? ["api.deepseek.com"] : [];
64114
- const domains = dedupeInOrder([...routes.httpsDomains, ...builtinDomains, ...params.mitmDomains ?? []]);
64105
+ const domains = dedupeInOrder([...routes.httpsDomains, ...params.mitmDomains ?? []]);
64115
64106
  const handle2 = await ensureProxyRunning({ host, port, passthrough, debug, mitmDomains: domains, modelWindows: collectModelWindows(config, base) }, deps);
64116
64107
  console.error(
64117
- `bili: started proxy at ${handle2.origin} (MITM domains: ${domains.length ? domains.join(", ") : "defaults"})` + (routes.httpRewrites.length > 0 ? ` (HTTP /bili/ rewrites: ${routes.httpRewrites.length})` : "") + (routes.httpsRewrites.length > 0 ? ` (HTTPS cert rewrites: ${routes.httpsRewrites.length})` : "") + (routes.httpEnvRoutes.length > 0 ? ` (HTTP proxy-env routes: ${routes.httpEnvRoutes.length})` : "") + (params.client === "pi-test" ? " (no extensions)" : "")
64108
+ `bili: started proxy at ${handle2.origin} (MITM domains: ${domains.length ? domains.join(", ") : "defaults"})` + (routes.httpRewrites.length > 0 ? ` (HTTP /bili/ rewrites: ${routes.httpRewrites.length})` : "") + (routes.httpsRewrites.length > 0 ? ` (HTTPS cert rewrites: ${routes.httpsRewrites.length})` : "") + (params.client === "pi-test" ? " (no extensions)" : "")
64118
64109
  );
64119
64110
  if (handle2.logPath) {
64120
64111
  console.error(`bili: proxy log: ${handle2.logPath}`);
@@ -64125,6 +64116,7 @@ async function runLaunch(params, deps = {}) {
64125
64116
  let piOverlayHome;
64126
64117
  let ompOverlayHome;
64127
64118
  let opencodeTmpFile;
64119
+ let hermesOverlayHome;
64128
64120
  let dshOverlayHome;
64129
64121
  const tmpFiles = [];
64130
64122
  const directUrl = launcherDirectUrl(process.env);
@@ -64174,42 +64166,36 @@ async function runLaunch(params, deps = {}) {
64174
64166
  opencodeTmpFile = prepareOpencodeHttpRewrite(resolveOpencodeConfigFile(process.env), origin, routes.httpRewrites, routes.httpsRewrites, opencodePluginPath);
64175
64167
  if (opencodeTmpFile) env.OPENCODE_CONFIG = opencodeTmpFile;
64176
64168
  } else if (base === "hermes") {
64177
- env = stripLoopbackNoProxy({
64178
- ...process.env,
64179
- HTTPS_PROXY: origin,
64180
- HERMES_CA_BUNDLE: resolveCombinedCaPath(process.env),
64181
- ...routes.httpEnvRoutes.length > 0 ? { HTTP_PROXY: origin } : {}
64182
- });
64183
- if (routes.providerKeys.length > 0) {
64184
- if (!writeHermesIdentityPlugin(resolveHermesHome(process.env), routes.providerKeys)) {
64169
+ env = { ...process.env };
64170
+ hermesOverlayHome = prepareHermesHome(resolveHermesHome(process.env), origin, routes.httpRewrites);
64171
+ if (hermesOverlayHome) {
64172
+ env.HERMES_HOME = hermesOverlayHome;
64173
+ if (!writeHermesIdentityPlugin(resolveHermesHome(process.env), hermesOverlayHome, routes.httpRewrites)) {
64185
64174
  console.error(
64186
- "bili: could not install the session-identity plugin into ~/.hermes/plugins \u2014 hermes requests will be rejected by the proxy without an identity (see #286)."
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)."
64187
64176
  );
64188
64177
  }
64189
64178
  } else {
64190
64179
  console.error(
64191
- "bili: no hermes providers found in ~/.hermes/config.yaml \u2014 LLM traffic will NOT go through the proxy (configure a provider first)."
64180
+ routes.httpRewrites.length === 0 ? "bili: no hermes providers found in ~/.hermes/config.yaml \u2014 traffic will NOT go through the proxy (configure a provider first)." : "bili: hermes config.yaml could not be rewritten (unreadable or no matching provider endpoints) \u2014 traffic will NOT go through the proxy."
64192
64181
  );
64193
64182
  }
64194
64183
  } else if (base === "dsh") {
64195
- env = stripLoopbackNoProxy({
64196
- ...process.env,
64197
- BILLION_CONTEXT_PROXY: origin,
64198
- HTTPS_PROXY: origin,
64199
- NODE_EXTRA_CA_CERTS: ca,
64200
- ...routes.httpEnvRoutes.length > 0 ? { HTTP_PROXY: origin } : {}
64201
- });
64184
+ env = { ...process.env, BILLION_CONTEXT_PROXY: origin };
64185
+ env.DEEPSEEK_BASE_URL = wrapUpstream(origin, "https://api.deepseek.com");
64202
64186
  env.PI_CACHE_RETENTION = "long";
64203
64187
  const dshHomeDir = resolveDshHome(process.env);
64204
- if (routes.httpRewrites.length > 0) {
64205
- dshOverlayHome = prepareDshHome(dshHomeDir, origin, routes.httpRewrites);
64206
- if (dshOverlayHome) {
64207
- env.DSH_HOME = dshOverlayHome;
64208
- } else {
64209
- console.error(
64210
- "bili: dsh settings.yaml could not be rewritten (unreadable or no matching loopback endpoints) \u2014 loopback custom providers will NOT go through the proxy."
64211
- );
64212
- }
64188
+ dshOverlayHome = prepareDshHome(dshHomeDir, origin, routes.httpRewrites);
64189
+ if (dshOverlayHome) {
64190
+ env.DSH_HOME = dshOverlayHome;
64191
+ } else if (routes.httpRewrites.length > 0) {
64192
+ console.error(
64193
+ "bili: dsh settings.yaml could not be rewritten (unreadable or no matching endpoints) \u2014 custom providers will NOT go through the proxy; the built-in deepseek route still does."
64194
+ );
64195
+ } else {
64196
+ console.error(
64197
+ "bili: no custom providers found in ~/.dsh/settings.yaml \u2014 proxying the built-in deepseek route via DEEPSEEK_BASE_URL only."
64198
+ );
64213
64199
  }
64214
64200
  const dshAcpPatch = writeDshAcpPatch(dshHomeDir);
64215
64201
  if (dshAcpPatch) clientArgs = dshArgsWithPatch(clientArgs, dshAcpPatch);