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 +2 -1
- package/README.zh-CN.md +2 -1
- package/dist/index.js +108 -26
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +38 -13
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
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:
|
|
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({
|
|
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
|
|
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(
|
|
64422
|
-
|
|
64423
|
-
|
|
64424
|
-
|
|
64425
|
-
|
|
64426
|
-
|
|
64427
|
-
|
|
64428
|
-
|
|
64429
|
-
|
|
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
|
-
|
|
66382
|
-
|
|
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
|
-
|
|
66393
|
-
|
|
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
|
|