billion-context 0.1.97-pr.667.487 → 0.1.97-pr.669.488

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
@@ -158,7 +158,7 @@ rewrite until dsh gains a settings-path env or an upstream loopback opt-out.
158
158
  Overlay dirs created by older versions are left in place and never merged back
159
159
  into the real home.
160
160
 
161
- ### Option 1 — Launcher (`bili pi` / `bili codex` / `bili claude` / `bili omp` / `bili opencode` / `bili hermes` / `bili dsh`)
161
+ ### Option 1 — Launcher (`bili pi` / `bili codex` / `bili claude` / `bili omp` / `bili opencode` / `bili hermes` / `bili dsh` / `bili trae`)
162
162
 
163
163
  The launcher wraps a client in one command: it starts a proxy on an
164
164
  independent port (a fresh instance is always spawned — a port is never
@@ -177,6 +177,7 @@ bili omp # pi-style, file-free (#535): env + extens
177
177
  bili opencode # MITM for HTTPS + temp opencode.json (/bili/ for HTTP) + thin /acp plugin
178
178
  bili hermes # file-free (#535): hermes proxy env (HTTPS_PROXY + HERMES_CA_BUNDLE) — https via CONNECT MITM, http via absolute-form forward proxy; real ~/.hermes untouched
179
179
  bili dsh # deepseek-harness: non-loopback upstreams ride proxy envs (https MITM, http absolute-form), loopback keeps the overlay DSH_HOME (~/.dsh-bili) rewrite (#535), built-in deepseek route via DEEPSEEK_BASE_URL, native /acp command injected via --patch
180
+ bili trae # Trae CLI (ByteDance, closed Go binary, no base-URL override) — cert-MITM via HTTPS_PROXY + SSL_CERT_FILE, model host from TRAE_CLI_API_HOST or the default enterprise gateway (#655)
180
181
  bili pi --mitm-domain api.foo.com # add a domain to the MITM whitelist
181
182
  ```
182
183
 
package/README.zh-CN.md CHANGED
@@ -84,7 +84,7 @@ npm install -g billion-context
84
84
 
85
85
  bili 永不拥有用户数据:每个被启动的客户端都跑在**真实 home** 上,运行期写入落在用户预期的位置。把客户端指向代理时,启动器按优先级选择——**优先 env 变量**(hermes/dsh/codex 的代理/CA env;pi/omp 的 `BILI_PROVIDER_REWRITES` URL 清单,由扩展加载时经 `registerProvider` 消费),其次 **CLI 参数或扩展 API**(codex `-c key=value`、opencode 插件),最后才是**生成文件**——目前仅剩 opencode 的临时 `opencode.json`(退出即删)和 dsh 的回环例外:dsh 的 fetch 栈对回环目标无条件绕过代理 env,所以本地上游保留持久 `~/.dsh-bili` overlay 改写,直到 dsh 提供 settings-path env 或上游支持回环 opt-out。旧版本创建的 overlay 目录原地保留,绝不合并回真实 home。
86
86
 
87
- ### 方式 1 —— 启动器(`bili pi` / `bili codex` / `bili claude` / `bili omp` / `bili opencode` / `bili hermes` / `bili dsh`)
87
+ ### 方式 1 —— 启动器(`bili pi` / `bili codex` / `bili claude` / `bili omp` / `bili opencode` / `bili hermes` / `bili dsh` / `bili trae`)
88
88
 
89
89
  启动器把客户端包进一条命令:在独立端口拉起一个代理(总是全新实例,绝不复用端口),再按客户端支持的机制把它指向代理 —— 能吃代理/CA 环境变量的走**证书 MITM**,不吃的走隔离的**`/bili/` 配置重写**。真实配置文件从不被修改;客户端自己的配置只被**读取**,用来发现它实际连接的 HTTPS 上游主机,把这些主机加入 MITM 白名单 —— 代理只 TLS 终结它们,其余流量盲透传。
90
90
 
@@ -96,6 +96,7 @@ bili omp # pi 同款,file-free(#535):环境变量 +
96
96
  bili opencode # HTTPS 走 MITM + 临时 opencode.json(HTTP 走 /bili/)+ 轻量 /acp 插件
97
97
  bili hermes # file-free(#535):hermes 代理环境变量(HTTPS_PROXY + HERMES_CA_BUNDLE)—— https 走 CONNECT MITM,http 走绝对形式转发;真实 ~/.hermes 不动
98
98
  bili dsh # deepseek-harness:非回环上游走代理 env(https MITM、http absolute-form),回环上游保留 overlay DSH_HOME(~/.dsh-bili)改写(#535),内置 deepseek 路由走 DEEPSEEK_BASE_URL,经 --patch 注入原生 /acp 命令
99
+ bili trae # Trae CLI(字节跳动,闭源 Go 二进制,无 base-URL 覆盖)—— 证书 MITM(HTTPS_PROXY + SSL_CERT_FILE),模型主机取 TRAE_CLI_API_HOST 或默认企业网关(#655)
99
100
  bili pi --mitm-domain api.foo.com # 向 MITM 白名单追加域名
100
101
  ```
101
102
 
package/dist/index.js CHANGED
@@ -56307,15 +56307,28 @@ function handlePluginManifest(res) {
56307
56307
  statusEndpoint: "/__bili/plugin/status"
56308
56308
  }));
56309
56309
  }
56310
+ function conversationIdForSession(sessionId) {
56311
+ let bestId;
56312
+ let bestSeen = -Infinity;
56313
+ for (const [cid, entry] of conversations) {
56314
+ if (entry.sessionId === sessionId && entry.lastSeen > bestSeen) {
56315
+ bestId = cid;
56316
+ bestSeen = entry.lastSeen;
56317
+ }
56318
+ }
56319
+ return bestId;
56320
+ }
56310
56321
  function handlePluginStatus(conversationId2, res, deps, fallbackLatest = false) {
56311
56322
  let entry = conversations.get(conversationId2);
56312
56323
  let session = entry ? peekSession(entry.sessionId) : void 0;
56313
56324
  let viaFallback = false;
56325
+ let resolvedConversationId = conversationId2;
56314
56326
  if ((!entry || !session) && fallbackLatest) {
56315
56327
  const latest = listSessions().filter((s3) => s3.restored !== true).sort((a, b2) => (b2.lastSeen ?? 0) - (a.lastSeen ?? 0))[0];
56316
56328
  if (latest) {
56317
56329
  session = latest;
56318
56330
  viaFallback = true;
56331
+ resolvedConversationId = conversationIdForSession(latest.id) ?? conversationId2;
56319
56332
  } else {
56320
56333
  res.writeHead(404, { "content-type": "application/json" });
56321
56334
  res.end(JSON.stringify({ ok: false, error: "no session with activity since boot \u2014 issue a model request or pass the conversation id" }));
@@ -56365,7 +56378,7 @@ function handlePluginStatus(conversationId2, res, deps, fallbackLatest = false)
56365
56378
  res.writeHead(200, { "content-type": "application/json" });
56366
56379
  res.end(JSON.stringify({
56367
56380
  ok: true,
56368
- conversationId: conversationId2,
56381
+ conversationId: resolvedConversationId,
56369
56382
  fallback: viaFallback || void 0,
56370
56383
  label: session.meta.label ?? null,
56371
56384
  pluginAgent: session.metadata.pluginAgent ?? null,
@@ -56400,8 +56413,12 @@ async function handlePluginTool(payload, res, deps) {
56400
56413
  const entry = conversations.get(conversationId2);
56401
56414
  const session = entry ? peekSession(entry.sessionId) : void 0;
56402
56415
  if (!entry || !session) {
56416
+ deps.log("warn", `[plugin] tool "${tool}" rejected for conversation ${conversationId2}: ${entry ? "id registered but session not resident in this proxy instance" : "id never registered (stale shim session id after host resume?)"}`);
56403
56417
  res.writeHead(404, { "content-type": "application/json" });
56404
- res.end(JSON.stringify({ ok: false, error: "unknown plugin conversation (no model request has arrived with this conversation id yet)" }));
56418
+ res.end(JSON.stringify({
56419
+ ok: false,
56420
+ error: !entry ? "unknown plugin conversation (no model request has arrived with this conversation id yet)" : "unknown plugin conversation (id registered but its session is not resident in this proxy instance \u2014 a fresh model request re-binds it)"
56421
+ }));
56405
56422
  return;
56406
56423
  }
56407
56424
  if (!isProxyToolFor(tool, session, deps.config)) {
@@ -56969,6 +56986,20 @@ function readDshConfig(dshHome) {
56969
56986
  }
56970
56987
  return { baseUrls: parseDshSettingsYaml(text) };
56971
56988
  }
56989
+ var TRAE_DEFAULT_MODEL_HOSTS = [
56990
+ "console.enterprise.trae.cn",
56991
+ "www.trae.cn"
56992
+ ];
56993
+ function resolveTraeHome(env) {
56994
+ const h = os.homedir();
56995
+ return nonEmpty2(env.TRAE_CONFIG_DIR) ? env.TRAE_CONFIG_DIR : path10.join(h, ".trae");
56996
+ }
56997
+ function readTraeConfig(env) {
56998
+ const result = {};
56999
+ const host = nonEmpty2(env.TRAE_CLI_API_HOST) ? env.TRAE_CLI_API_HOST.replace(/^https?:\/\//i, "").replace(/\/+$/, "") : void 0;
57000
+ if (host) result.modelApiHost = host;
57001
+ return result;
57002
+ }
56972
57003
  function readClaudeSettings(homeDir, cwd, env = process.env) {
56973
57004
  const files = [
56974
57005
  path10.join(homeDir, ".claude", "settings.json"),
@@ -57319,6 +57350,7 @@ function loadClientConfig(env, cwd) {
57319
57350
  config.opencode = readOpencodeConfig(resolveOpencodeConfigFile(env));
57320
57351
  config.hermes = readHermesConfig(resolveHermesHome(env));
57321
57352
  config.dsh = readDshConfig(resolveDshHome(env));
57353
+ config.trae = readTraeConfig(env);
57322
57354
  return config;
57323
57355
  }
57324
57356
  function collectModelWindows(config, scope) {
@@ -57376,6 +57408,10 @@ function extractHttpsHosts(config) {
57376
57408
  if (config.zcode) {
57377
57409
  for (const prov of Object.values(config.zcode.providers)) push(prov.baseURL);
57378
57410
  }
57411
+ if (config.trae) {
57412
+ const hosts = nonEmpty2(config.trae.modelApiHost) ? [config.trae.modelApiHost] : TRAE_DEFAULT_MODEL_HOSTS;
57413
+ for (const h of hosts) push(`https://${h}`);
57414
+ }
57379
57415
  return out;
57380
57416
  }
57381
57417
  function configFilePaths(env) {
@@ -57387,7 +57423,8 @@ function configFilePaths(env) {
57387
57423
  path11.join(process.cwd(), ".claude", "settings.json"),
57388
57424
  path11.join(codexHome, "config.toml"),
57389
57425
  path11.join(resolvePiHome(env), "models.json"),
57390
- path11.join(zcodeHome, "v2", "config.json")
57426
+ path11.join(zcodeHome, "v2", "config.json"),
57427
+ path11.join(resolveTraeHome(env), "traecli.yaml")
57391
57428
  ];
57392
57429
  }
57393
57430
  function readMtimes(paths) {
@@ -58433,7 +58470,7 @@ function logUnrecognizedPath(log2, url) {
58433
58470
  const n = (unrecognizedPathCounts.get(key) ?? 0) + 1;
58434
58471
  unrecognizedPathCounts.set(key, n);
58435
58472
  if (n <= 3) {
58436
- log2("warn", `unrecognized path ${key} \u2014 not a known protocol (/chat/completions, /v1/messages, /responses, /responses/compact); forwarding unchanged`);
58473
+ log2("warn", `unrecognized path ${key} \u2014 not a known protocol (/chat/completions, /llm_raw_chat, /v1/messages, /responses, /responses/compact); forwarding unchanged`);
58437
58474
  } else if (n === 4) {
58438
58475
  log2("info", `unrecognized path ${key}: forwarding unchanged; further occurrences suppressed`);
58439
58476
  }
@@ -58985,7 +59022,7 @@ async function handle(req, res, opts, core, config, log2, instanceId, instanceSt
58985
59022
  }
58986
59023
  }
58987
59024
  upstreamOrigin = route ? route.upstream : /^https?:\/\//i.test(url) ? new URL(url).origin : opts.upstream;
58988
- protocol = route?.explicitProtocol ?? (req.method === "POST" && bodyBuffer.length > 0 ? urlPath.endsWith("/chat/completions") ? "openai" : urlPath.endsWith("/v1/messages") || urlPath.endsWith("/messages") ? "anthropic" : urlPath.endsWith("/responses") || responsesCompact ? "responses" : null : null);
59025
+ protocol = route?.explicitProtocol ?? (req.method === "POST" && bodyBuffer.length > 0 ? urlPath.endsWith("/chat/completions") || urlPath.endsWith("/llm_raw_chat") ? "openai" : urlPath.endsWith("/v1/messages") || urlPath.endsWith("/messages") ? "anthropic" : urlPath.endsWith("/responses") || responsesCompact ? "responses" : null : null);
58989
59026
  if (protocol !== null && bodyBuffer.length > 0) {
58990
59027
  try {
58991
59028
  const decoded = await decodeRequestBody(headerValue2(req, "content-encoding"), bodyBuffer, MAX_REQUEST_BYTES);
@@ -60007,7 +60044,7 @@ function logUpstreamProxyDecision(opts, upstreamUrl, decision) {
60007
60044
  }
60008
60045
  function inferWireProtocol(path18) {
60009
60046
  const p2 = path18.split("?", 2)[0];
60010
- if (p2.endsWith("/chat/completions")) return "openai";
60047
+ if (p2.endsWith("/chat/completions") || p2.endsWith("/llm_raw_chat")) return "openai";
60011
60048
  if (p2.endsWith("/responses") || p2.endsWith("/responses/compact")) return "responses";
60012
60049
  return null;
60013
60050
  }
@@ -64384,6 +64421,7 @@ function resolveProxyOrigin() {
64384
64421
  var TOOL_TIMEOUT_MS = 6e4;
64385
64422
  var CONVERSATION_FROM_ENV = process.env.CLAUDE_CODE_SESSION_ID?.trim() || process.env.BILI_CONVERSATION_ID?.trim() || void 0;
64386
64423
  var IDENTITY_BINDING = Boolean(process.env.CLAUDE_CODE_SESSION_ID?.trim());
64424
+ var ORPHAN_ADOPT = IDENTITY_BINDING && process.env.BILI_MCP_NO_ORPHAN_ADOPT !== "1";
64387
64425
  var manifestTools = [];
64388
64426
  var conversationId = CONVERSATION_FROM_ENV;
64389
64427
  var registered = false;
@@ -64416,21 +64454,45 @@ function ensureManifest() {
64416
64454
  return manifestPromise;
64417
64455
  }
64418
64456
  async function forwardTool(tool, args, timeoutMs = TOOL_TIMEOUT_MS) {
64419
- let res;
64457
+ for (let attempt = 0; ; attempt++) {
64458
+ let res;
64459
+ try {
64460
+ res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/tool`, {
64461
+ method: "POST",
64462
+ headers: { "content-type": "application/json" },
64463
+ body: JSON.stringify({ conversationId, tool, args }),
64464
+ signal: AbortSignal.timeout(timeoutMs)
64465
+ });
64466
+ } catch (err2) {
64467
+ if (err2 instanceof Error && err2.name === "TimeoutError") throw new Error(`tool forward timed out after ${timeoutMs}ms: ${tool}`);
64468
+ throw err2;
64469
+ }
64470
+ const data = await res.json();
64471
+ if (res.ok && data.ok) return data.result ?? "";
64472
+ if (res.status === 404 && attempt === 0 && ORPHAN_ADOPT && conversationId && typeof data.error === "string" && data.error.includes("no model request has arrived")) {
64473
+ if (await adoptLatestActiveConversation()) continue;
64474
+ }
64475
+ throw new Error(data.error ?? `tool forward failed: ${res.status}`);
64476
+ }
64477
+ }
64478
+ async function adoptLatestActiveConversation() {
64420
64479
  try {
64421
- res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/tool`, {
64422
- method: "POST",
64423
- headers: { "content-type": "application/json" },
64424
- body: JSON.stringify({ conversationId, tool, args }),
64425
- signal: AbortSignal.timeout(timeoutMs)
64426
- });
64427
- } catch (err2) {
64428
- if (err2 instanceof Error && err2.name === "TimeoutError") throw new Error(`tool forward timed out after ${timeoutMs}ms: ${tool}`);
64429
- throw err2;
64480
+ const res = await fetch(
64481
+ `${resolveProxyOrigin()}/__bili/plugin/status?conversationId=${encodeURIComponent(conversationId ?? "")}&fallback=latest`,
64482
+ { signal: AbortSignal.timeout(5e3) }
64483
+ );
64484
+ if (!res.ok) return false;
64485
+ const data = await res.json();
64486
+ if (data.ok !== true || data.fallback !== true || !data.conversationId || data.conversationId === conversationId) return false;
64487
+ process.stderr.write(
64488
+ `[bili-mcp] conversation id no longer known by the proxy (host resumed its session?); adopting latest active conversation ${data.conversationId}
64489
+ `
64490
+ );
64491
+ conversationId = data.conversationId;
64492
+ return true;
64493
+ } catch {
64494
+ return false;
64430
64495
  }
64431
- const data = await res.json();
64432
- if (!res.ok || !data.ok) throw new Error(data.error ?? `tool forward failed: ${res.status}`);
64433
- return data.result ?? "";
64434
64496
  }
64435
64497
  var ERR_TOOL = -32602;
64436
64498
  async function handleMessage(msg) {
@@ -64924,7 +64986,7 @@ function selfDistFile(name) {
64924
64986
  return path15.join(selfPackageRoot(), "dist", name);
64925
64987
  }
64926
64988
  var LAUNCHER_DEFAULT_HOST = "127.0.0.1";
64927
- var LAUNCH_CLIENTS = ["pi", "codex", "claude", "omp", "opencode", "hermes", "dsh", "pi-test"];
64989
+ var LAUNCH_CLIENTS = ["pi", "codex", "claude", "omp", "opencode", "hermes", "dsh", "trae", "pi-test"];
64928
64990
  var HEALTH_PATH = "/__bili/health";
64929
64991
  var HEALTH_POLL_INTERVAL_MS = 200;
64930
64992
  var SPAWN_WAIT_MS = 2e4;
@@ -65073,6 +65135,15 @@ function discoverRoutes(client, config) {
65073
65135
  } catch {
65074
65136
  }
65075
65137
  }
65138
+ } else if (client === "trae") {
65139
+ const hosts = nonEmpty2(config.trae?.modelApiHost) ? [config.trae.modelApiHost] : TRAE_DEFAULT_MODEL_HOSTS;
65140
+ for (const h of hosts) {
65141
+ const host = h.split(":", 2)[0].toLowerCase();
65142
+ if (host && !httpsSeen.has(host)) {
65143
+ httpsSeen.add(host);
65144
+ httpsDomains.push(host);
65145
+ }
65146
+ }
65076
65147
  } else {
65077
65148
  for (const [name, prov] of Object.entries(config.codex?.providers ?? {})) {
65078
65149
  classify(prov.baseUrl, `model_providers.${name}.base_url`);
@@ -65105,6 +65176,9 @@ function buildPiEnv(origin, caPath, baseEnv, httpRewrites = [], httpsRewrites =
65105
65176
  function buildCodexEnv(origin, caPath, baseEnv) {
65106
65177
  return { ...baseEnv, HTTPS_PROXY: origin, SSL_CERT_FILE: caPath, BILLION_CONTEXT_PROXY: origin };
65107
65178
  }
65179
+ function buildTraeEnv(origin, caPath, baseEnv) {
65180
+ return { ...baseEnv, HTTPS_PROXY: origin, SSL_CERT_FILE: caPath, BILLION_CONTEXT_PROXY: origin };
65181
+ }
65108
65182
  function buildCodexArgs(origin, httpRewrites, httpsRewrites, extra) {
65109
65183
  const args = [];
65110
65184
  for (const r of httpRewrites) {
@@ -65195,7 +65269,7 @@ function isPrivateIPv4(host) {
65195
65269
  return false;
65196
65270
  }
65197
65271
  function launcherInjectMcp(env, base, codexUpstream) {
65198
- if (base === "pi" || base === "omp" || base === "opencode" || base === "hermes" || base === "dsh") return false;
65272
+ if (base === "pi" || base === "omp" || base === "opencode" || base === "hermes" || base === "dsh" || base === "trae") return false;
65199
65273
  if (env.BILI_LAUNCHER_PLUGIN === "0") return false;
65200
65274
  if (base === "codex" && env.BILI_LAUNCHER_PLUGIN === void 0 && codexUpstream !== void 0 && isPrivateUpstreamHost(codexUpstream)) {
65201
65275
  return false;
@@ -65950,6 +66024,10 @@ function resolveClientCommand(client, env) {
65950
66024
  );
65951
66025
  return { command: process.execPath, prefixArgs: [cli] };
65952
66026
  }
66027
+ if (client === "trae") {
66028
+ const traeBin = resolveOnPath("traecli", env) ?? resolveOnPath("trae-cli", env) ?? resolveOnPath("trae", env);
66029
+ return { command: traeBin ?? "traecli", prefixArgs: [] };
66030
+ }
65953
66031
  const resolved = resolveOnPath(client, env);
65954
66032
  return { command: resolved ?? client, prefixArgs: [] };
65955
66033
  }
@@ -66085,6 +66163,8 @@ async function runLaunch(params, deps = {}) {
66085
66163
  }
66086
66164
  const dshAcpPatch = writeDshAcpPatch(dshHomeDir);
66087
66165
  if (dshAcpPatch) clientArgs = dshArgsWithPatch(clientArgs, dshAcpPatch);
66166
+ } else if (base === "trae") {
66167
+ env = buildTraeEnv(origin, resolveCombinedCaPath(process.env), stripInheritedProxy(process.env));
66088
66168
  } else if (base === "codex") {
66089
66169
  const codexConversationId = injectMcp ? randomUUID5() : void 0;
66090
66170
  if (directUrl) {
@@ -66360,6 +66440,7 @@ Usage:
66360
66440
  bili opencode [opts --] [args] start a proxy + launch opencode against it (cert-MITM)
66361
66441
  bili hermes [opts --] [args] start a proxy + launch hermes-agent against it (/bili/ rewrite)
66362
66442
  bili dsh [opts --] [args] start a proxy + launch deepseek-harness against it (/bili/ rewrite)
66443
+ bili trae [opts --] [args] start a proxy + launch Trae CLI against it (cert-MITM)
66363
66444
  bili test pi non-polluting pi smoke test through the proxy
66364
66445
  bili export [session] [--full] list sessions / export one as a Markdown handoff
66365
66446
  (--full includes original messages; --output FILE)
@@ -66374,12 +66455,12 @@ Usage:
66374
66455
  bili --version print version
66375
66456
  bili --help show this help
66376
66457
 
66377
- Launcher (bili pi / bili codex / bili claude / bili omp / bili opencode / bili hermes / bili dsh):
66458
+ Launcher (bili pi / bili codex / bili claude / bili omp / bili opencode / bili hermes / bili dsh / bili trae):
66378
66459
  Brings up a proxy on an independent port (a fresh instance every launch), then runs the client pointed at it via HTTPS_PROXY + the proxy's
66379
66460
  MITM CA \u2014 no config-file edits. Discovered HTTPS upstream domains are
66380
66461
  auto-whitelisted for MITM so the proxy TLS-terminates exactly the hosts the
66381
- client uses; HTTP / localhost providers go direct. pi/claude trust the CA
66382
- via NODE_EXTRA_CA_CERTS, codex via SSL_CERT_FILE. Proxy killed on client exit.
66462
+ client uses; HTTP / localhost providers go direct. pi/claude trust the CA
66463
+ via NODE_EXTRA_CA_CERTS, codex/trae via SSL_CERT_FILE. Proxy killed on client exit.
66383
66464
  bili flags (-F, --mitm-domain, --port, ...) must precede the client name;
66384
66465
  everything after the client name is passed through to the client.
66385
66466
  bili pi # launch pi through the proxy
@@ -66389,8 +66470,9 @@ Launcher (bili pi / bili codex / bili claude / bili omp / bili opencode / bili h
66389
66470
  bili claude # launch claude through the proxy
66390
66471
  bili omp # launch omp through the proxy (pi-based; /bili/ rewrite)
66391
66472
  bili hermes # launch hermes-agent through the proxy (/bili/ rewrite of ~/.hermes/config.yaml)
66392
- bili dsh --profile web "task" # launch deepseek-harness through the proxy (/bili/ rewrite of ~/.dsh/settings.yaml)
66393
- bili test pi # quick end-to-end check of the pi path
66473
+ bili dsh --profile web "task" # launch deepseek-harness through the proxy (/bili/ rewrite of ~/.dsh/settings.yaml)
66474
+ bili trae # launch Trae CLI through the proxy (cert-MITM; model host via TRAE_CLI_API_HOST or --mitm-domain)
66475
+ bili test pi # quick end-to-end check of the pi path
66394
66476
  bili --mitm-domain api.foo.com pi # add a domain to the MITM whitelist (flags precede the client)
66395
66477
  bili -F http://127.0.0.1:7897 codex # route bili's upstream through a proxy (gost-style -F)
66396
66478