编辑器里AI输出卡住不出字:分段定位是模型、网关还是客户端
输出卡住不出字,绝大多数情况下不是”模型慢”,而是这条链路上有某一段在等一个永远不会到的东西。你要做的第一件事不是换模型、不是调温度,而是把链路切成几段,逐段确认”字走到哪一步就没了”。 只要定位顺序对,十分钟之内你就能把责任落到具体一段上;顺序不对,你会花一下午在客户端里反复改参数,而问题其实在端点地址上。
先说清本篇和站内几篇相邻文章的分工:流式输出乱序讲的是字到了但顺序不对怎么办,API 流式中断续传讲的是断了之后怎么把剩下的内容接着要回来,Cursor Agent 卡住讲的是单个客户端里的具体症状处置。本篇不重复这三件事,只做一件事:在”字根本不出来”的时候,给你一套能一路走到底的分段定位顺序,以及一张各家自定义模型配置里”要你自己填”的字段对照表。至于怎么把自定义端点接进编辑器,见编辑器接入自定义 API。
一、先把这条链路拆成四段
所谓”流式输出”,是指服务端不等整段回答生成完,而是一边生成一边把内容切成小片持续推给你。OpenAI 兼容端点上通行的做法是用 SSE(Server-Sent Events,服务端单向持续推送的一种 HTTP 长连接形式)逐条发送数据片。“OpenAI 兼容端点”这个词也解释一句:它指的是服务商把自己的 API 做成和 OpenAI 那套请求/响应格式一样,于是任何支持 OpenAI 格式的客户端都能直接对着它说话,不需要为每家单独写适配。
把这条路径拆开,从你按下回车开始一共四段:
- 客户端:编辑器插件或终端里的 Agent,负责组装请求、维持连接、把收到的片段渲染到界面上。
- 网关或兼容层:你自己搭的反向代理、公司内部的统一出口、或者服务商在 OpenAI 兼容路径上的转换层。不是每个人都有这一段,但只要你填的 base URL 不是服务商官方那个地址,你就有。
- 服务商的调度层:排队、鉴权、限流都发生在这里。
- 模型推理本身:真正在算 token 的那一段。
四段里任何一段停住,你在界面上看到的都是同一个现象——不出字。所以肉眼观察没有信息量,必须靠”切一刀看哪半边还活着”。
二、第一刀:绕开客户端,直接打端点
这一刀的目的是把”客户端”从嫌疑名单里摘出去或者钉死。方法很朴素:用命令行 HTTP 工具(curl 之类的都行,记得关掉输出缓冲,否则你看到的”卡住”可能只是工具在攒数据),拿你填在客户端里的那个 base URL、那把密钥、那个模型 ID,开着流式直接请求一次。请求体的字段以服务商文档为准,别照着记忆拼。
判定标准要提前给自己定死,否则你会对着屏幕发呆。观察的对象只有一个:终端里有没有出现第一个数据片,以及它是第几秒出现的。给自己划一条线(多长合适取决于你平时的正常等待时间,先拿一个明显宽松的值,比如平时的两三倍),线以内出片记作”通了”,到线还是空白记作”没通”,出了几片又停住记作”半途断”。把开始时间和停住的时刻都记下来——后面判断是超时踢连接还是排队等资源,靠的就是这个数字。
需要一个可对照的坐标的话,Groq 官方 API 参考页给出的接入信息是这两行(引用自其官方文档,核对日 2026-08-07):
https://api.groq.com/openai/v1
Authorization: Bearer $GROQ_API_KEY
结果只有三种,各自指向不同的下一步:
- 命令行能持续吐片段:链路后三段是通的,问题在客户端——它的连接管理、代理设置、或者你在界面里填的某一项和命令行里用的不是同一个值。
- 命令行也卡在那里不返回:客户端无辜,往下查网关和服务商。这时候把 base URL 换成不经过你自己网关的地址再试一次,就能把第二段和第三、四段分开。
- 命令行立刻报错:恭喜,这是最省事的情况——有明确错误码可查,不用猜。
顺带说一句判断依据:请求发出后一直没有任何字节返回,和先返回了几片然后停住,是两类完全不同的故障。前者更像鉴权、路由、排队;后者更像连接被中途掐断或者生成过程本身停了。这一层区分属于 HTTP 与 SSE 的通用机制推理,不是哪家产品文档写下的行为。
三、第二刀:核对”要你自己填”的那几项
各家客户端接自定义模型时,都会留几个必须你手动填的字段。这些字段的名字各不相同,从一家搬到另一家就是编造。下表按截至 2026-08-07 各家官方文档的记录整理,字段名逐字照抄。
| 配置项(逐字) | 它是什么 | 与”卡住”的关系 | 出处(URL 见文末) |
|---|---|---|---|
| Base URL | 客户端要请求的 API 端点地址 | 地址不对,请求根本到不了目标服务——这是 HTTP 层的常识判断,不是产品文档写下的行为 | Cline / Roo Code / Kilo Code 官方文档 |
apiBase | 覆盖默认 API 端点的可选字段 | 同上,且它写在 config.yaml 里,容易和界面里改过的值不一致 | Continue 官方文档 |
api_url | 自定义 base URL | 同上 | Zed 官方文档 |
OPENAI_HOST、OPENAI_BASE_PATH | 自建或企业内部 OpenAI 兼容端点的主机与可选路径,拆成两段设置 | 这是本篇里唯一”地址被拆成两截”的设计,两截拼出来的结果不对就打不通 | goose 官方文档 |
--base-url | 添加自定义 provider 时的命令行参数 | 同上 | Crush README |
| Max Output Tokens | 由你填的一个数,量纲是 token | 这一项由你填、填的是输出长度的量纲;本篇核对的那一页官方文档只列出了字段名,没有说明客户端内部拿它做什么,实际行为以官方文档为准 | Cline / Roo Code 官方文档 |
| Context Window size / Context Window | 由你填的一个数,量纲是 token | 同上:核对到的页面上只出现了字段名,未逐条说明用途 | Cline(Context Window size)/ Roo Code(Context Window) |
max_tokens | 模型条目里的上下文窗口上限 | 手写的数字与服务端实际情况不符时会怎样,属于协议层问题,本篇核对的页面未作说明 | Zed 官方文档 |
max_input_tokens、max_output_tokens | 给 aider 不认识的模型注册上下文上限用的字段 | 同上;这两项写在 .aider.model.metadata.json 里 | aider 官方文档 |
“上下文窗口”这个概念本身解释一句:它是模型一次请求里能容纳的 token 总量上限,历史对话、系统提示、你贴进去的代码全都占这个额度。协议层面有两条通用机制值得知道——请求里声明的窗口大于服务端实际支持时通常会被服务端直接拒绝,最大输出设得过小则会在没说完的地方被截断。这两条是 OpenAI 兼容协议的一般行为推理,不是上表任何一家文档的说法,写在这里只是帮你缩小怀疑范围。
还要提醒一句:上表是本篇核对过的那几页官方文档上出现过的字段,不等于各家文档的完整清单。某一项没出现在表里,只说明本篇没有记录它,不能反过来断言那个产品没有这一项。
四、第三刀:分清”传输断了”和”模型走不下去”
字不出来还有一类原因和网络无关:模型能正常吐字,但 Agent 的推进条件没被满足,于是它停在那里等。最常见的门槛是工具调用。
先解释术语。“原生工具调用”(native tool calling,也叫 function calling)指的是模型在协议层面直接返回一个结构化的”我要调用哪个工具、参数是什么”的对象,客户端照着执行再把结果喂回去。与之相对的老做法是让模型在正文里输出一段 XML 或 JSON 文本,客户端再去正文里解析——这叫回退方案。
Roo Code 官方文档在这一点上写得非常硬,原话是:
“Roo Code uses native tool calling exclusively. This is the only supported tool protocol — there is no XML-based fallback.”
按这句官方说法,所选模型必须支持 OpenAI 兼容的 function calling;文档同时说明,不支持原生工具调用的模型用不了,并建议先去查服务商文档确认该模型是否支持工具调用。这条对排查的意义是:如果你把一个纯对话模型接了进来,问题不在流式链路,而在模型能力选型,怎么调超时都没用。
goose 官方文档也从能力角度给过一句自述——文档称其支持 40+ 个 LLM provider,并写道 “works best with Claude 4 models”,给出的理由正是这些模型的工具调用能力。这是官方文档的说法,不是本篇的判断,也不构成对任何模型的背书;引在这里是想说明:各家对”模型要具备什么能力才带得动 Agent”是有明确态度的,选型时值得先看这一段。
另一个容易看走眼的地方是角色分配。Continue 的模型条目有 roles 字段,取值包括 chat、autocomplete、embed、rerank、edit、apply、summarize,默认值是 [chat, edit, apply, summarize]。这里的”嵌入”(embed)是把文本转成向量以便做相似度检索,“重排”(rerank)是把检索回来的候选按相关度重新排序——这两件事和你在聊天框里等字出来完全是两条路。排查时值得确认一下:你以为正在对话的那个模型,roles 里是否包含 chat。具体行为以官方文档为准。
五、边界与代价:这套方法不管什么
分段定位很好用,但它有明确的适用边界,先说清楚免得你在错的地方使劲。
它需要你能直接访问端点。 第一刀的前提是你手上有密钥、有网络可达性、有一个能发 HTTP 请求的终端。如果密钥被公司统一托管、你只能通过内网出口访问,这一刀就切不下去,只能退而求其次从配置比对开始。
它只看到 HTTP 层。 你能确认字节有没有到、什么时候停的,但看不到客户端拿到片段之后在内部做了什么处理。那部分属于各家实现,本篇核对的文档页面里没有写,也不该靠猜来补。
它不管模型质量。 输出出来了但内容不对、逻辑跑偏、代码编译不过,都不在这套流程的范围内——那是选型和提示词的事。
它不给价格、额度、限速的结论。 触发限流确实会表现为等待或失败,但具体到某家的阈值是多少,本篇一律不写,请你直接查服务商控制台。
它不描述任何产品的界面。 哪个开关在哪一屏、报错文案长什么样、什么时候会拦住你,都以你实际看到的界面为准。本篇依据的是配置层的文档记录,不是界面截图。
六、避坑清单:为什么会踩,以及怎么避
一、/v1 到底要不要带。 为什么会踩:各家对 base URL 的形态要求不一样,你从一家的笔记里复制到另一家就错位了。可核对的事实是:Cline 文档里的 v0 快速上手示例,Base URL 写作 https://api.v0.dev/v1(含 /v1);Kilo Code 文档明确说接受两种形态,既可以是 https://api.provider.com/v1,也可以是完整端点 https://api.provider.com/v1/chat/completions,后者是为端点结构非标准的服务商与自建网关准备的;Zed 文档示例是 https://example.com/v1;Groq 官方 base URL 是 https://api.groq.com/openai/v1;goose 则把地址拆成 OPENAI_HOST 与可选的 OPENAI_BASE_PATH 两段。怎么避:每次配新客户端时,只看这一家自己的文档示例,别用记忆里的形状。
二、你以为改的那把密钥不是生效的那把。 为什么会踩:同一个工具往往有多个凭据来源,改了一处另一处仍在生效。可核对的事实是:Zed 文档原话写着 “Do not put API keys in settings.json.”,凭据走 provider 设置界面或环境变量,环境变量命名规则是 <PROVIDER_NAME>_API_KEY(provider 名为 my-provider 时对应 MY_PROVIDER_API_KEY);其配置页另有一句原话:“Provider keys saved through Zed are stored in the system keychain, not in settings.json.”——这里的 keychain 指操作系统自带的凭据保管服务,密钥存在系统层而不是明文躺在配置文件里。goose 则把密钥放在环境变量或 config.yaml。Gemini CLI 支持在 settings.json 里用 $VAR_NAME 或 ${VAR_NAME} 做环境变量插值——所谓插值就是配置文件里只写变量名,加载时自动替换成环境变量的实际值,好处是配置文件能进版本库而密钥不进。怎么避:排查前先确认这一次请求实际用的是哪一路凭据,别在没生效的那一路上反复改。
三、模型 ID 是手写的还是拉取来的,处理方式不同。 为什么会踩:手写的 ID 打错一个字符,请求会被服务端拒绝,而你在界面上只看到”没反应”。可核对的事实是:Kilo Code 在凭据有效时会从 /v1/models 端点自动拉取模型列表,自动检测失败可手动填模型 ID;Zed 要在 available_models 数组里手写,每项含 name、display_name、max_tokens;Continue 在 models 块里手写,必填 name、provider、model。怎么避:手写路径先做一次一模一样的命令行请求验证 ID,验证通过再往配置里抄。
四、照着旧书签配置。 为什么会踩:文档域名会搬家,搜索引擎里排前面的常常是旧地址。核对日 2026-08-07 的实测记录是:docs.roocode.com/providers/openai-compatible 以 301 永久跳转到 roocodeinc.github.io;kilocode.ai/docs/... 以 308 永久跳转到 kilo.ai;goose 的 block.github.io/goose/docs/getting-started/providers 返回 404,文档站现为 goose-docs.ai。怎么避:每次排查前先确认文档地址还是活的,跳转后的页面才是当前口径。
五、把”Agent 卡住”和”流式断了”当成一回事。 为什么会踩:两者的界面表现都是不出字,但一个在等工具执行结果或用户确认,另一个是传输本身停了。怎么避:先按第二刀确认字节层面还有没有数据在流动,再决定往哪个方向查。前者的处置可以参考Cursor Agent 卡住,后者参考API 流式中断续传。
六、配置改了但没在你以为的那一层生效。 为什么会踩:多层配置文件的优先级不同。可核对的事实是:aider 的 .aider.model.settings.yml 可放四处(home 目录、git 仓库根目录、启动 aider 的当前目录、--model-settings-file 指定的路径),按顺序加载、后加载的优先;Gemini CLI 的优先级从低到高是硬编码默认、system defaults 文件、user settings、project settings、system settings、环境变量、命令行参数;Crush 的 crushrc 优先级是项目级 ./.crushrc 高于全局 ~/.config/crush/crushrc。怎么避:改配置前先想清楚自己改的是哪一层,以及有没有更高优先级的一层在盖着它。Crush 添加自定义 provider 的命令,其 README 原文示例是:
provider add deepseek --type openai-compat \
--base-url "https://api.deepseek.com/v1"
想再往上一层看成本与并发对等待时间的影响,可以接着读API 超时与中断处理。
数据来源与核对日期
以下为本篇引用到的官方文档来源,核对日期均为 2026-08-07。文档内容会变,配置前请以官方文档最新版为准。
- goose:https://goose-docs.ai/docs/getting-started/providers/(核对日
block.github.io/goose/docs/getting-started/providers返回 404,文档站现为goose-docs.ai) - Roo Code:https://roocodeinc.github.io/Roo-Code/providers/openai-compatible(核对日
docs.roocode.com/providers/openai-compatible301 永久跳转至此) - Kilo Code:https://kilo.ai/docs/providers/openai-compatible(核对日
kilocode.ai/docs/...308 永久跳转至此) - Cline:https://docs.cline.bot/provider-config/openai-compatible
- Continue:https://docs.continue.dev/reference
- Zed:https://zed.dev/docs/ai/use-api-access 与 https://zed.dev/docs/ai/configuration
- aider:https://aider.chat/docs/config/adv-model-settings.html
- Crush:https://raw.githubusercontent.com/charmbracelet/crush/main/README.md
- Gemini CLI:https://google-gemini.github.io/gemini-cli/docs/get-started/configuration.html
- Groq:https://console.groq.com/docs/api-reference
- Windsurf(仅用于说明其模型文档在核对日发生跳转):https://docs.windsurf.com/windsurf/models,核对日 307 跳转至 https://docs.devin.ai/desktop/models
本篇没有写的内容,以及原因:
- 价格、免费额度、订阅档位、限速阈值:这类数字变动频繁,且本次核对未取得可复述的一手数值,写出来只会误导。请直接查各服务商控制台与定价页。
- 完整模型清单与版本号:模型上下线的节奏比文章更新快,本篇只在必要时引用官方文档里出现过的示例模型 ID,不做清单。
- 各家客户端的界面细节:本篇依据的是配置层的文档记录,没有界面信息,因此不描述面板位置、菜单层级、提示文案与校验时机,请以你实际看到的界面为准。
- Windsurf 接自定义模型的做法:核对日其模型文档地址发生跳转,落地页未说明自带 API key 的配置位置,因此本篇不写其做法,也不据此推断任何产品之间的关系。
- 各家配置字段的内部用途:本篇核对的那些文档页面上,多个字段只出现了名字(例如 Context Window size、Max Output Tokens),没有说明客户端内部拿它做什么。本篇因此只写”这一项由你填、填的是什么量纲”,不替产品断言行为。需要确切语义时,请查上列对应文档。
最后提醒一句:本篇整理的是截至 2026-08-07 各官方文档页面的内容,字段名与地址都可能变化;真正开始配之前,花两分钟打开对应文档确认一遍,比事后排查半天划算。
延伸阅读:同一组里的 模型接上了 Agent 却不动手、公司网络下代理与证书报错;接完之后照 接完自定义模型别急着干活 逐项过一遍,才算真接通。