来源: #640 分析 codebuddy 客户端支持时发现(owner 在 #640 要求立项)
背景
qoder(Qoder CLI,npm 包 @qoder-ai/qodercli 国际版 / @qodercn-ai/qoderclicn 国内版,bin qoder / qodercli,Apache-2.0,阿里出品)是 gemini-cli 的 fork(bundle 里保留 GEMINI_* env 别名和 gemini-cli 的 zod 配置 schema)。和 codebuddy 一样是 Node CLI,但模型端点 scheme 硬编码 https,没有可用的 HTTP base URL 覆盖 env ,所以 codebuddy 的 /bili/ rewrite 路线走不通,需要 cert-MITM(dsh/claude 式)。
推荐方案:cert-MITM,proxy mode
qoder 尊重 HTTPS_PROXY(内置 undici 带 ProxyAgent,网络管理器 getProxy() 读标准 proxy env)和 NODE_EXTRA_CA_CERTS(无自定义 https.Agent,TLS 走 undici 默认)
launcher 注入:HTTPS_PROXY=http://127.0.0.1:PORT + NODE_EXTRA_CA_CERTS=<bili CA> + BILLION_CONTEXT_PROXY
默认 MITM 白名单模型 host(下表);代理看到 POST /model/v1/chat/completions → OpenAI adapter → 压缩
认证 token(Bearer,私有 SSO/PAT 签发)对代理不透明,原样转发
压缩走 proxy mode(wire 注入)。qoder 不是 ACP-native agent(bundle 里有 ACP 协议 schema,见开放问题 feat: persistent + namespaced sessions, multi-tenant session isolation, stream robustness #5 ,可作未来 plugin mode 方向)
调研确认的配置事实(v1.1.47,从 npm 包 bundle 核实,国际/国内两版)
模型流量
wire 是 OpenAI chat completions :POST https://<host>/model/v1/chat/completions,body = 标准 OpenAI chat + qoder 扩展(顶层 metadata/patches/custom_model,message 级 reasoning_content/reasoning_item);SSE + [DONE],另有配额标记 [EXCEED_QUOTA]/[NOTIFICATIONS]
模型 host 优先级:QODER_MODEL_SERVER_HOST(未文档化 env,剥 scheme 和尾部斜杠)> 静态 map {prod: api2-v2.qoder.sh, daily: daily-api2-v2.qoder.sh, test: test-api2-v2.qoder.sh}(国际/国内 bundle 相同)
区域推理 host:api1.qoder.sh(US) / api2.qoder.sh(SG) / api3.qoder.sh(JP);国内版全部走 gateway.qoder.com.cn;center 面 center.qoder.sh / gateway.qoder.com.cn(控制面,不需要 MITM)
scheme 硬编码 https → /bili/ rewrite 不可行,cert-MITM 是唯一路线
transport:QODER_MODEL_TRANSPORT(http|grpc|legacy|http3|sse|off),协议 map {"custom-openai", "custom-openai-responses", "custom-anthropic"};默认由服务端 feature gate 决定,fallback legacy(remoteChatAsk 生命周期,wire 待真机验证)。注意:配置了 proxy 时 grpc 会自动降级为 http(bundle 里有 p7c() 检查)——http 是 proxy 友好路径
认证(私有,已确认)
浏览器 SSO 登录(后台每 30 分钟自动刷新 token)或 PAT(QODER_PERSONAL_ACCESS_TOKEN,qoder.com/account/integrations 创建);token = security_oauth_token ?? access_token,Authorization: Bearer 发送
与 codebuddy 同类私有认证;不影响 bili(代理不解析 token,原样转发)
配置
配置根:QODER_CONFIG_DIR / QODERCN_CONFIG_DIR(完整路径)> QODER_CLI_HOME/QODERCN_CLI_HOME+目录名 > ~/.qoder(国际)/ ~/.qoder-cn(国内);QODER_CONFIG_DIR_NAME/QODERCN_CONFIG_DIR_NAME 控制目录名;项目资源在 <cwd>/.qoder
settings.json 在 <configDir>/settings.json,gemini-cli 风格 zod schema(mcpServers 等)
站点:QODERCLI_SITE=cn → QODERCN_ 前缀;国内包 site 内置
启动 env:QODER_MODEL(-m)、QODER_MCP_CONFIG(--mcp-config,文件或 inline JSON)、QODER_WORKING_DIR、QODER_SESSION_ID、QODER_SESSION_NAME、QODER_PERMISSION_MODE
--list-models 列模型(服务端驱动的 catalog,本地配置里没有模型清单)
预算对齐
QODER_AUTOCOMPACT_WINDOW / QODERCN_AUTOCOMPACT_WINDOW:cap 有效上下文窗口(min(modelWindow, env)),正好对应 REQ: codex 压缩预算协调 + 匿名代理模式拦截伪造(根本解决方案) #321 的 claude 预算对齐模式(env 注入面)
模型窗口服务端驱动(catalog max_input_tokens,缺省 128k);另有 QODER_AUTOCOMPACT_PCT_OVERRIDE
MCP
QODER_MCP_CONFIG = --mcp-config(文件或 inline JSON),语义与 claude 一致 → MCP 注入可接(首版可选)
接入点清单
src/client-config.ts:QoderConfig、resolveQoderHome(env)(QODER_CONFIG_DIR ?? QODERCN_CONFIG_DIR ?? ~/.qoder)、readQoderConfig()——只读发现 settings.json(model 选择);无本地 models.json(服务端驱动)
src/launcher.ts:LAUNCH_CLIENTS 加 "qoder";discoverRoutes qoder 分支——无 /bili/ rewrite (scheme 硬编码 https),改为返回默认 MITM 域名:api2-v2.qoder.sh、api1.qoder.sh、api2.qoder.sh、api3.qoder.sh、gateway.qoder.com.cn(daily/test 变体不默认加);buildQoderEnv()(HTTPS_PROXY + NODE_EXTRA_CA_CERTS + BILLION_CONTEXT_PROXY,无 base URL rewrite);resolveQoderBudgetEnv()(QODER_AUTOCOMPACT_WINDOW,国内站点用 QODERCN_ 前缀);resolveClientCommand(qoder → qodercli)
src/discover.ts:extractHttpsHosts qoder 分支(默认模型 host);configFilePaths 加 <configDir>/settings.json
src/cli.ts:HELP 加一行
测试仿 launcher.test.ts / dsh 模式
README client 章节和 AGENTS.md 模块表同步更新
开放问题
legacy transport wire :默认 transport 由服务端 feature gate 决定,fallback legacy(remoteChatAsk 生命周期)——其 wire 是否也是 OpenAI 兼容 SSE 待真机验证。建议首版 launcher 注入 QODER_MODEL_TRANSPORT=http 强制走 OpenAI wire 路径,真机验证后再决定是否去掉
qoder body 扩展字段 (metadata/patches/custom_model):需验证 bili 的 OpenAI adapter 对未知顶层字段的透传行为
模型窗口 :服务端驱动 catalog,bili 的 models.dev registry 大概率没有 qoder 模型名——首版依赖 QODER_AUTOCOMPACT_WINDOW 或 bili configured limit 兜底
国内站点检测 :launcher 如何判定 QODER_ vs QODERCN_ 前缀(QODERCLI_SITE env?安装的 binary 是哪个包?),需要定一个规则
ACP mode (QODER_ACP_LOGIN_METHOD_ID 等):bundle 里有 ACP 协议 schema(sampling/createMessage),未来可做 plugin mode(agent 侧压缩),首版不做
首个验证场景
国际版 + PAT 登录(QODER_PERSONAL_ACCESS_TOKEN),跑 bili qoder,确认:模型流量经代理 TLS 终止、/model/v1/chat/completions 走 OpenAI 压缩管线、QODER_AUTOCOMPACT_WINDOW 对齐日志出现、压缩循环正常触发。
来源: #640 分析 codebuddy 客户端支持时发现(owner 在 #640 要求立项)
背景
qoder(Qoder CLI,npm 包
@qoder-ai/qodercli国际版 /@qodercn-ai/qoderclicn国内版,binqoder/qodercli,Apache-2.0,阿里出品)是 gemini-cli 的 fork(bundle 里保留GEMINI_*env 别名和 gemini-cli 的 zod 配置 schema)。和 codebuddy 一样是 Node CLI,但模型端点 scheme 硬编码 https,没有可用的 HTTP base URL 覆盖 env,所以 codebuddy 的/bili/rewrite 路线走不通,需要 cert-MITM(dsh/claude 式)。推荐方案:cert-MITM,proxy mode
HTTPS_PROXY(内置 undici 带 ProxyAgent,网络管理器getProxy()读标准 proxy env)和NODE_EXTRA_CA_CERTS(无自定义 https.Agent,TLS 走 undici 默认)HTTPS_PROXY=http://127.0.0.1:PORT+NODE_EXTRA_CA_CERTS=<bili CA>+BILLION_CONTEXT_PROXYPOST /model/v1/chat/completions→ OpenAI adapter → 压缩调研确认的配置事实(v1.1.47,从 npm 包 bundle 核实,国际/国内两版)
模型流量
POST https://<host>/model/v1/chat/completions,body = 标准 OpenAI chat + qoder 扩展(顶层metadata/patches/custom_model,message 级reasoning_content/reasoning_item);SSE +[DONE],另有配额标记[EXCEED_QUOTA]/[NOTIFICATIONS]QODER_MODEL_SERVER_HOST(未文档化 env,剥 scheme 和尾部斜杠)> 静态 map{prod: api2-v2.qoder.sh, daily: daily-api2-v2.qoder.sh, test: test-api2-v2.qoder.sh}(国际/国内 bundle 相同)api1.qoder.sh(US) /api2.qoder.sh(SG) /api3.qoder.sh(JP);国内版全部走gateway.qoder.com.cn;center 面center.qoder.sh/gateway.qoder.com.cn(控制面,不需要 MITM)/bili/rewrite 不可行,cert-MITM 是唯一路线QODER_MODEL_TRANSPORT(http|grpc|legacy|http3|sse|off),协议 map{"custom-openai", "custom-openai-responses", "custom-anthropic"};默认由服务端 feature gate 决定,fallbacklegacy(remoteChatAsk 生命周期,wire 待真机验证)。注意:配置了 proxy 时 grpc 会自动降级为 http(bundle 里有p7c()检查)——http 是 proxy 友好路径认证(私有,已确认)
QODER_PERSONAL_ACCESS_TOKEN,qoder.com/account/integrations 创建);token =security_oauth_token ?? access_token,Authorization: Bearer发送配置
QODER_CONFIG_DIR/QODERCN_CONFIG_DIR(完整路径)>QODER_CLI_HOME/QODERCN_CLI_HOME+目录名 >~/.qoder(国际)/~/.qoder-cn(国内);QODER_CONFIG_DIR_NAME/QODERCN_CONFIG_DIR_NAME控制目录名;项目资源在<cwd>/.qodersettings.json在<configDir>/settings.json,gemini-cli 风格 zod schema(mcpServers等)QODERCLI_SITE=cn→QODERCN_前缀;国内包 site 内置QODER_MODEL(-m)、QODER_MCP_CONFIG(--mcp-config,文件或 inline JSON)、QODER_WORKING_DIR、QODER_SESSION_ID、QODER_SESSION_NAME、QODER_PERMISSION_MODE--list-models列模型(服务端驱动的 catalog,本地配置里没有模型清单)预算对齐
QODER_AUTOCOMPACT_WINDOW/QODERCN_AUTOCOMPACT_WINDOW:cap 有效上下文窗口(min(modelWindow, env)),正好对应 REQ: codex 压缩预算协调 + 匿名代理模式拦截伪造(根本解决方案) #321 的 claude 预算对齐模式(env 注入面)max_input_tokens,缺省 128k);另有QODER_AUTOCOMPACT_PCT_OVERRIDEMCP
QODER_MCP_CONFIG=--mcp-config(文件或 inline JSON),语义与 claude 一致 → MCP 注入可接(首版可选)接入点清单
src/client-config.ts:QoderConfig、resolveQoderHome(env)(QODER_CONFIG_DIR??QODERCN_CONFIG_DIR??~/.qoder)、readQoderConfig()——只读发现settings.json(model 选择);无本地 models.json(服务端驱动)src/launcher.ts:LAUNCH_CLIENTS加"qoder";discoverRoutesqoder 分支——无/bili/rewrite(scheme 硬编码 https),改为返回默认 MITM 域名:api2-v2.qoder.sh、api1.qoder.sh、api2.qoder.sh、api3.qoder.sh、gateway.qoder.com.cn(daily/test 变体不默认加);buildQoderEnv()(HTTPS_PROXY + NODE_EXTRA_CA_CERTS + BILLION_CONTEXT_PROXY,无 base URL rewrite);resolveQoderBudgetEnv()(QODER_AUTOCOMPACT_WINDOW,国内站点用QODERCN_前缀);resolveClientCommand(qoder→qodercli)src/discover.ts:extractHttpsHostsqoder 分支(默认模型 host);configFilePaths加<configDir>/settings.jsonsrc/cli.ts:HELP 加一行launcher.test.ts/ dsh 模式开放问题
legacy(remoteChatAsk 生命周期)——其 wire 是否也是 OpenAI 兼容 SSE 待真机验证。建议首版 launcher 注入QODER_MODEL_TRANSPORT=http强制走 OpenAI wire 路径,真机验证后再决定是否去掉metadata/patches/custom_model):需验证 bili 的 OpenAI adapter 对未知顶层字段的透传行为QODER_AUTOCOMPACT_WINDOW或 bili configured limit 兜底QODER_vsQODERCN_前缀(QODERCLI_SITEenv?安装的 binary 是哪个包?),需要定一个规则QODER_ACP_LOGIN_METHOD_ID等):bundle 里有 ACP 协议 schema(sampling/createMessage),未来可做 plugin mode(agent 侧压缩),首版不做首个验证场景
国际版 + PAT 登录(
QODER_PERSONAL_ACCESS_TOKEN),跑bili qoder,确认:模型流量经代理 TLS 终止、/model/v1/chat/completions走 OpenAI 压缩管线、QODER_AUTOCOMPACT_WINDOW对齐日志出现、压缩循环正常触发。