公司网络下代理与证书报错:编辑器走的不是你终端那套代理设置

2026-08-07

在公司网络里遇到代理或证书报错,最常见的误判是:你在终端里 export 过代理变量、curl 打服务商地址也通,于是默认编辑器里那个 AI 插件同样通。这两个进程读的根本不是同一份配置。 判断”我这边网络没问题”的证据链,在这里是断的。

这篇只讲一件事:这批编辑器 / 终端 Agent 把 HTTP 层的设置放在哪里,以及你怎么确认当前生效的是哪一份。站内另外三篇管别的段落——内网代理与证书链的排查讲的是网络侧本身通不通(证书链是否被中间设备替换、代理是否拦了 TLS),DNS 与 hosts 配错讲域名解析这一层,API 超时与连接中断讲请求发出去之后的重试与断流处置。本篇站在客户端配置这一层,不重复它们。

下文提到的所有产品字段,都来自各家官方文档在 2026-08-07 的记录,字段随版本会变,最终以官方文档最新版为准。

一、终端试通的那一次,证明不了编辑器也通

先把概念摆平。这批工具接自定义模型,绝大多数走的是OpenAI 兼容端点——服务商把自己的接口做成和 OpenAI 那套请求/响应格式一致,客户端只要换个地址、换把密钥就能调,不用为每家单独写适配。这也是为什么走表单的那几家(Cline、Roo Code、Kilo Code),文档里列出来的主参数都落在”填地址、填密钥、指定模型”这三件事上。

问题出在”地址填对了,请求却发不出去”这一步。你在终端里设的代理变量,属于那个 shell 进程和它拉起来的子进程。编辑器通常是由桌面环境或启动器直接拉起的,它的环境变量集合来自那条启动路径,不一定包含你写在 shell 配置里的东西。这是操作系统的进程模型,不是哪家产品的特性——但结果就是:curl 成功和插件失败可以同时成立,而且这时候你越盯着网络排查越绕远。相关的通用坑可以看环境变量丢失那篇。

所以正确的下一步不是继续测网络,而是回到这个客户端自己的配置体系,确认三件事:HTTP 层的设置写在哪个文件、这次生效的是哪一份、密钥从哪来。这三件事各家答案完全不同。

二、HTTP 层的设置写在哪:先认清四种配置形态

把这批工具的配置形态归一下类,能省很多试错:图形界面表单一类(Cline、Roo Code、Kilo Code),YAML 配置文件一类(Continue 的 config.yaml、aider 的 .aider.model.settings.yml),JSON settings 一类(Zed 的 settings.json、Gemini CLI 的 settings.json),环境变量与 CLI 子命令一类(goose 的 GOOSE_PROVIDERgoose configure、Crush 的 crushrcprovider add)。

形态决定了你该去哪儿改。表单那类,你手上没有一份能直接打开的配置文本(存到哪里、以什么格式存,本篇依据的文档页面没有说明,以官方文档为准);文件那类,改动落在你能 git diff 出来的文本上;环境变量那类,改动跟着进程走——而”跟着进程走”恰恰是本篇开头那个误判的温床。

本篇最直接的落点在 Continue。它的模型配置写在 config.yamlmodels 块下,必填 name(唯一标识)、provider(如 openai、ollama、mistral)、model(具体模型名);可选字段里有 apiBase(覆盖默认 API 端点)、rolescapabilitiesdefaultCompletionOptionsautocompleteOptionschatOptions,以及 requestOptions(timeout、headers、proxy 等 HTTP 配置)。官方文档对这一项的记录就到这个粒度,具体子字段怎么写、取什么值,以官方文档为准。

关键在于结构:requestOptions 是挂在单个模型条目下面的可选字段,也就是说它是逐条配置的。而 Continue 的 roles 取值有 chatautocompleteembedrerankeditapplysummarize,默认是 [chat, edit, apply, summarize]。这里的 embed 指把文本转成向量以便做相似度检索,rerank 指把检索出来的候选再按相关度重排一遍——一个稍微完整的仓库配置里,对话、补全、嵌入、重排很可能是四条独立的 models 条目。你只在对话那条上加了 HTTP 设置,其余几条并不共享同一份写法(这是配置结构决定的,未配置条目的实际行为以官方文档为准)。

官方文档给的示例长这样,可以原样参照结构:

models:
  - name: GPT-4o
    provider: openai
    model: gpt-4o
    roles:
      - chat
      - edit
    defaultCompletionOptions:
      temperature: 0.7
      maxTokens: 1500

其他几家在”自定义 HTTP 头”这件事上也各有落点。Kilo Code 新建 provider 时有一项 Headers(可选,自定义 HTTP 头,键值对形式);aider 的 extra_params 可以把任意参数透传给 litellm.completion(),其中包括 extra_headers,文档示例是:

- name: provider/model-name
  extra_params:
    extra_headers:
      Custom-Header: value
    max_tokens: 8192

至于 Zed,本篇依据的那两页记录里没有出现 HTTP 代理相关的字段,这不等于 Zed 没有对应能力,只说明本篇不据此展开。

配置项(逐字)属于哪家、写在哪截至 2026-08-07 官方文档记录的说明来源
requestOptionsContinue,config.yamlmodels 条目下可选字段,timeout、headers、proxy 等 HTTP 配置docs.continue.dev/reference
apiBaseContinue,同上可选字段,覆盖默认 API 端点同上
HeadersKilo Code,新建 provider 的字段可选,自定义 HTTP 头,键值对形式kilo.ai/docs/providers/openai-compatible
extra_paramsaider,.aider.model.settings.yml把任意参数透传给 litellm.completion(),包括 extra_headersaider.chat/docs/config/adv-model-settings.html
api_urlZed,settings.jsonopenai_compatible自定义 base URLzed.dev/docs/ai/use-api-access
OPENAI_HOSTgoose,环境变量自建 / 企业内部的 OpenAI 兼容端点,可选配 OPENAI_BASE_PATHgoose-docs.ai/docs/getting-started/providers/
--base-urlCrush,provider add 命令行参数自定义 provider 时指定基址Crush 仓库 README
Base URLCline / Roo Code / Kilo Code,界面表单填服务商给的 API 端点;Cline 与 Roo Code 的文档都提示这里不会是官方 OpenAI 那个地址(https://api.openai.com/v1各家文档,URL 见文末

这张表最实用的读法是反过来读:当你在某家的文档里搜”proxy”搜不到时,先确认你搜的是不是这家对应的那个字段名。apiBaseapi_url、Base URL、OPENAI_HOST--base-url 是五个不同的东西,串台着填就是自己给自己造 bug。

三、确认”哪一份配置真的生效”

代理和证书类报错之所以难缠,一半原因是你改的那份配置压根没被读到。几家文档里都有可复核的加载规则,值得先看这个再看报错。

Gemini CLI 把 settings.json 放在四处:系统默认 /etc/gemini-cli/system-defaults.json(Linux)、用户级 ~/.gemini/settings.json、项目级的项目根 .gemini/settings.json、系统覆盖 /etc/gemini-cli/settings.json(Linux)。优先级从低到高是:硬编码默认 → system defaults 文件 → user settings → project settings → system settings → 环境变量 → 命令行参数。注意环境变量排在项目配置之上、命令行参数最高——你在项目里改了半天没效果,很可能是被上层压住了。

它还支持在 settings.json 里做环境变量插值:写 $VAR_NAME${VAR_NAME},加载时自动解析成当前进程环境里的值。这个机制的价值在于配置文件能进版本库而密钥不进。同时它的 .env 查找顺序是:当前工作目录 → 逐级父目录(到项目根或 home 为止)→ 用户 home 的 ~/.env。这条直接解释了一个常见现象:从仓库根目录启动和从子目录启动,读到的可能是不同的 .env

aider 的 .aider.model.settings.yml 可以放四处,按顺序加载、后加载的优先:home 目录、git 仓库根目录、启动 aider 的当前目录、--model-settings-file <filename> 指定的自定义路径。Crush 的配置文件是 crushrc(bash 风格加 Crush 内建命令,不是 JSON),文档列出的顺序是 ./.crushrc(项目级)在前、~/.config/crush/crushrc(全局,Unix 类系统)在后。goose 那边,文档记录的是环境变量 GOOSE_PROVIDERGOOSE_MODEL 用来设默认 provider 与模型,配置则持久化在 config.yaml——两套并存,但两者冲突时谁压谁,本篇依据的文档页面没有写,别靠猜,以官方文档为准。

密钥这一路也一样要确认来源。Zed 文档原话是 “Do not put API keys in settings.json.”,凭据走两条路:provider 设置界面,或环境变量,命名规则是 <PROVIDER_NAME>_API_KEY——provider 名为 my-provider 时对应 MY_PROVIDER_API_KEY。它的 configuration 页还有一句原话:“Provider keys saved through Zed are stored in the system keychain, not in settings.json.”(keychain 指操作系统自带的凭据保管服务。)所以排查鉴权类报错时,你得先答出这次用的是界面存进 keychain 的那把,还是环境变量那把。

落到手上,“确认哪一份生效”可以按这个顺序做,每一步都有明确的通过标准:

  1. 把候选文件全列出来。 照上面各家的位置逐条 ls:Gemini CLI 查 ~/.gemini/settings.json 与项目根的 .gemini/settings.json(Linux 上还有 /etc/gemini-cli/settings.json/etc/gemini-cli/system-defaults.json);aider 查 home、git 仓库根、当前目录三处的 .aider.model.settings.yml;Crush 查 ./.crushrc~/.config/crush/crushrc通过标准:你能说出这次一共存在几份、分别在哪。 只找到一份反而是好消息,找到两份以上就得往下走。
  2. 按文档的优先级排序,从最高的那一份开始看,而不是从你最熟的那份。 Gemini CLI 是命令行参数 > 环境变量 > system settings > project settings > user settings > system defaults 文件 > 硬编码默认;aider 是后加载优先,--model-settings-file 指定的那份在最后、也就是最强。通过标准:你能指着一份文件说”改这份才有用”,并说出压在它上面的还有谁。
  3. 查环境里有没有东西压着。 在真正启动这个工具的那个环境里(不是你另开的一个终端)跑 printenv 看有没有相关变量,比如 goose 的 GOOSE_PROVIDERGOOSE_MODEL,Zed 的 <PROVIDER_NAME>_API_KEY,Gemini CLI 的 GEMINI_API_KEYGEMINI_MODEL通过标准:能列出这些变量此刻是有值还是空。 有值又和文件里写的不一致,就是第 2 步排的那条优先级在起作用。
  4. 确认 .env 是从哪儿读的。 Gemini CLI 的查找顺序是当前工作目录 → 逐级父目录 → ~/.env,所以从仓库根启动和从子目录启动可能读到不同的文件。通过标准:你能说出这次启动时的工作目录,以及从它往上第一个存在 .env 的目录是哪个。
  5. 最后才用这个工具本身发一次最小请求。 不要用 curl 代验,理由见第一节。通过标准:报错文案变了(说明你改的那份确实被读到了),或者请求通了。 报错文案一字不变,多半说明前四步里有一步的结论是错的,回到第 2 步重来,而不是继续改内容。

四、边界与代价:这套做法不管什么

把 HTTP 层设置写进各家自己的配置文件,代价是可移植性。你手上同时用三四个工具,就得配三四份,字段名还都不一样;换个代理地址要改好几处,漏一处就出现”有的工具能用、有的不能”的诡异状态。愿意接受这个代价的理由是它可复现——配置是文本,能进版本库,能 diff,能给同事复制。

它明确不管的事有这么几类:

第一,网络本身通不通它不管。代理是否拦截并重签了 TLS、企业根证书有没有装进对应运行时的信任库、链路上有没有别的设备改写请求——这些都在客户端配置之外,属于内网代理与证书链排查的范围。客户端能做的只是”按你说的地址和头发出去”。

第二,超时与断流的处置策略它不管。Continue 的 requestOptions 里记录了有 timeout 这一项,但请求断在半路之后怎么重试、怎么续传,是另一个话题。

第三,模型能力它不管。Roo Code 文档写得很硬:

“Roo Code uses native tool calling exclusively. This is the only supported tool protocol — there is no XML-based fallback.”

这是官方文档的说法。原生工具调用(function calling)指的是模型按接口约定直接输出结构化的函数调用请求,而不是靠在文本里拼一段标签让客户端解析。文档建议先查服务商文档确认该模型是否支持工具调用。也就是说,代理配对了、证书装好了、地址和密钥都没错,模型不支持这套协议照样用不成——这类失败很容易被误当成网络问题。Continue 那边对应的是 capabilities 里的 tool_use,Zed 的 capabilities 对象里有 tools、parallel_tool_calls 这些开关。

第四,界面细节本篇不写。各家的面板长什么样、提示语怎么写、什么时候校验,以你实际看到的界面为准。

第五,本篇不覆盖全部产品。举个可复现的例子:2026-08-07 当天,Windsurf 的模型文档地址会跳转到 Devin Desktop 的文档页,那一页未说明是否支持自带 API key(BYOK,即用你自己申请的密钥调模型),也没给配置位置,所以本篇不写它的做法,请以官方文档为准。

五、避坑清单

curl 的成功当编辑器的成功。 会踩是因为两者的进程环境不同源,你的验证根本没覆盖出问题的那个进程。避法:验证要在同一个客户端里做——改完配置后用这个工具本身发一次最小请求,别用别的通道代验。

改了一份配置,生效的是另一份。 会踩是因为几家都有多处加载:aider 四个位置后加载优先,Gemini CLI 有六级优先级且环境变量压过项目配置,Crush 有项目级和全局两份。避法:动手前先按文档把加载顺序列出来,从优先级最高的那一层往下查,而不是从你最熟的那份文件开始改。

把 A 家的字段名套到 B 家。 会踩是因为这些字段在中文语境里都被叫成”接口地址”,看着可互换。避法:认名不认义,apiBase / api_url / Base URL / OPENAI_HOST / --base-url 各归各家,照着上面那张表填。

/v1 加不加拿不准。 各家文档给的形态确实不同:Cline 文档的 v0 示例是 https://api.v0.dev/v1(含 /v1),Kilo Code 明确接受 https://api.provider.com/v1https://api.provider.com/v1/chat/completions 两种形态,后者是为端点结构非标准的服务商与自建网关准备的;Zed 示例是 https://example.com/v1;Groq 官方 base URL 是 https://api.groq.com/openai/v1;goose 的 OPENAI_HOSTOPENAI_BASE_PATH 则是拆成两段的设计。会踩是因为公司网关常会重写路径,拼错一段返回的可能是 404 或一个网关自己的错误页,看着不像”路径拼错”。避法:以你要接的那家服务商文档给的完整端点为准,逐段比对客户端拼出来的地址。

把密钥写进 settings.json 提交上去。 会踩是因为配置文件要进版本库,密钥顺手就写在旁边了。避法:Zed 明确禁止这么做,用界面或 <PROVIDER_NAME>_API_KEY;Gemini CLI 用 $VAR_NAME 插值把值留在环境里。

上下文窗口这类需要手填的项被忽略。 有几家把它交给你填:Cline 的 Context Window size、Roo Code 的 Context Window、Zed available_models 条目里的 max_tokens、aider 用 .aider.model.metadata.json 注册的 max_input_tokens / max_output_tokens。上下文窗口指一次请求里模型能看到的 token 上限,这几项填的就是 token 数量这个量纲。官方文档没有逐条说明客户端内部拿这些数做什么,所以本篇不替它们下结论;只提醒一点:按 OpenAI 兼容协议的通用机制推理,客户端报出来的参数类错误有时会长得很像网络错误,别一上来就往代理上归因。

Azure 场景直接套通用 OpenAI 兼容 provider。 Kilo Code 文档明确提醒:Azure GPT-5 不要用通用的 OpenAI 兼容 provider,要用 Kilo 原生的 azure provider,因为 Azure 会拒绝 max_tokens 参数。会踩是因为”它也是 OpenAI 兼容的”这个直觉太强。避法:先查目标平台有没有专门的 provider 选项。同类的接入路径选择可参考编辑器接自定义 API

数据来源与核对日期

本篇引用的产品事实全部来自下列官方文档页面,核对日期均为 2026-08-07。字段与文档结构会随版本变化,请以官方文档最新版为准。

本篇没有写什么,以及为什么。 任何产品的价格、免费额度、订阅档位、限速数字、版本号、完整模型清单,本次都不写——这类信息变动频繁,且不在本次核对范围内,请直接查各产品官方文档与定价页。各家界面的菜单层级、按钮位置、报错文案也不写,因为本次核对的是配置层文档,不是界面。另外,文中凡属 OpenAI 兼容协议层面的通用机制推理(例如参数类错误容易被误认成网络错误),已在原句里标明是机制推理,不是某家文档的记载;官方文档只列了字段名而没说明客户端内部用途的项,本篇也只写”这一项由你填、填的是什么量纲”,不代产品下结论。

延伸阅读:同一组里的 编辑器里AI输出卡住不出字编辑器请求被截断或报超上下文;接完之后照 接完自定义模型别急着干活 逐项过一遍,才算真接通。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。