![]() 玄同 765 AI Engineer | ▍深耕领域 AI Agent 架构设计 Agent Harness 工程 Context Engineering 多智能体协同 & RAG |
| 「 让 AI 交互更智能,让技术落地更高效 」 | 欢迎技术探讨 / 项目合作,关注解锁大模型与智能交互的无限可能! | |
Cursor 自定义大模型 API 保姆级教程:本地与官方模型双模并存、五档思考强度与五档上下文窗口配置
很多刚开始用 Cursor 的朋友都会遇到同一个困惑:明明自己手里有现成的大模型 API Key,或者已经在电脑上用 Ollama、vLLM 跑起了本地大模型,可一旦填进 Cursor 的设置页,点下 Verify 不是报连接失败,就是在 Agent 模式下读不了文件、调不动终端工具;或者好不容易配通了本地模型,结果 Cursor 原有的官方模型(Claude / GPT / Auto)、Cursor Tab 代码自动补全和 Cmd + K 行内编辑全都失效了。
更让人头疼的是,像 DeepSeek-R1、Qwen3、Gemini 等支持深度思考(Reasoning)与超长上下文的模型,接进 Cursor 后往往只能按默认参数跑,左下角根本找不到调节 「思考强度(Reasoning Effort)」 与 「上下文窗口(Context Tiers:64K~1M)」 的开关,甚至在流式工具调用被截断重试时还会弹出 Requests ending with a model turn are not supported. 报错。
这篇文章我们就把 Cursor 接入自定义模型 API 的底层逻辑彻底扒开。不讲空话,从最基础的第三方 API 接入讲起,一步步带你打通本地大模型与官方云端模型双模并存(保留 Cursor Tab 与 Cmd + K)、Agent 多轮工具调用、五档思考强度与五档上下文窗口的自由切换,以及 Cursor 三层阶段性结论守卫与 model turn 自动续接。
文章目录
一、为什么你在 Cursor 里配自定义模型 API 老是报错?
1.1 从一个直觉误区说起:到底是谁在连你的 API?
在动手改配置之前,我们先花两分钟搞清楚一个最核心的原理问题:当你在 Cursor 的输入框里敲下一句提问时,请求到底是从哪台机器发给大模型的?
很多人的第一直觉是:Cursor 装在我的电脑上,我在设置里填了 API Key 和 Base URL,那肯定是我的电脑直接发请求给模型服务商。
但事实恰恰相反。
在默认模式下,Cursor 采用的是「云端中转架构」。你可以把它理解成一家代购驿站:你在本地客户端填好的 API Key 和 Base URL,会先被打包发给 Cursor 的云端服务器;然后由云端服务器代替你去请求那个 Base URL,拿到结果后再流式传回你的电脑。
看懂上面这张图,你就瞬间明白为什么会出现那两个经典报错了:
- 为什么公网 API 能通,本地
localhost/127.0.0.1死活连不上?
因为你填了http://127.0.0.1:11434/v1之后,是远在海外的云端服务器去访问它自己的127.0.0.1:11434,请求根本不可能回到你的电脑上。 - 为什么有时候连上了,却用不了 Agent 模式读写文件?
因为 Cursor 的 Agent 模式依赖模型返回标准的函数调用(tool_calls),并且会根据/models接口返回的能力标签来判断这个模型「会不会用工具、支不支持思考」。如果缺少能力标签,客户端就会把模型的工具权限或思考档位直接关掉。
1.2 三种接入方式全景对比:你适合哪一种?
根据你手头模型服务的部署位置,接入 Cursor 一共有三种方式。先看对比表,按需对号入座:
| 接入方式 | 适用模型来源 | 是否需要内网穿透 | Agent 工具调用 | 思考强度调节 | 推荐指数 |
|---|---|---|---|---|---|
| 方式一:设置页 BYOK 模式 | DeepSeek、硅基流动、OpenRouter 等公网 API | 不需要 | 支持(受模型目录限制) | 仅内置白名单模型支持 | ⭐⭐⭐⭐ |
| 方式二:反向隧道穿透模式 | 本机 Ollama / vLLM 临时测试 | 需要(ngrok 等) | 部分支持(延迟极高) | 不支持 | ⭐⭐ |
| 方式三:本地 Agent 运行时直连 | 本机 Ollama / vLLM / 局域网自建网关 | 不需要(本机直连) | 原生完整支持 | 支持五档自由切换 | ⭐⭐⭐⭐⭐ |
选型建议:如果你只用现成的公网第三方 API,直接看第二节即可,3 分钟搞定;如果你要在 Cursor 里用本机或内网跑的大模型,或者想给自定义模型开启五档「思考强度」与五档「上下文窗口(64K~1M)」调节,请直接重点看第三节和第四节。
二、基础篇:3 分钟接入公网第三方大模型 API
如果你使用的是支持 OpenAI 兼容格式的公网大模型 API(比如 DeepSeek 官方 API、硅基流动、阿里云百炼、OpenRouter 等),只需要在 Cursor 设置界面里按下面四步配置。
2.1 四步完成公网 API 配置
- 打开模型设置面板:按下快捷键
Cmd + Shift + J(Windows 为Ctrl + Shift + J),切换到左侧的 Models 选项卡。 - 添加自定义模型名称:在模型列表底部点击 + Add Model,输入服务商文档里对应的准确模型 ID(例如
deepseek-chat、deepseek-reasoner或Qwen/Qwen2.5-Coder-32B-Instruct),然后只勾选你刚刚添加的模型。 - 填写 API Key 与 Base URL:向下滚动找到 OpenAI API Key 区域:
- 在输入框中填入你在对应平台申请的
API Key。 - 展开下方的 Override OpenAI Base URL,填入包含
/v1后缀的接口基础地址。
- 在输入框中填入你在对应平台申请的
- 点击 Verify 验证并开启:点击右侧的 Verify 按钮。此时 Cursor 会用你勾选的第一个模型发送一条测试请求,验证通过后开关会自动变成绿色开启状态。
2.2 常见细节避坑:为什么填对了 Key 还是报 404?
新手在这一步最容易踩的坑就是 Base URL 末尾的 /v1 路径。Cursor 在发起对话时,会自动在你的 Base URL 后面拼接 /chat/completions。因此填写时必须遵循以下规则:
| 你填写的 Base URL 格式 | Cursor 实际请求的地址 | 结果 |
|---|---|---|
https://api.example.com/v1 | https://api.example.com/v1/chat/completions | 正确(推荐写法) |
https://api.example.com | https://api.example.com/chat/completions | 报错 404(漏了 /v1) |
https://api.example.com/v1/chat/completions | https://api.example.com/v1/chat/completions/chat/completions | 报错 404(路径重复) |
三、进阶篇:将本地 / 内网大模型直连接入 Cursor Agent
如果你想接入的是本机运行的 Ollama(默认端口 11434)、vLLM(默认端口 8000)、LM Studio(默认端口 1234),或者是实验室/团队内部局域网里的模型网关,就必须绕开云端中转,启用 Cursor 内置的本地 Agent 运行时(Local Agent Runtime)。
3.1 本地 Agent 运行时是怎么工作的?
在 Cursor 的安装目录里,其实内置了两个专门负责本地执行的扩展模块:cursor-agent-exec(本地工具执行器)和 cursor-local-agent-runtime(本地推理运行时)。一旦激活本地模式,整个对话流程就会变成一套纯粹的本机闭环:
要打通这条链路,我们只需要解决三个核心问题:开启本地直连开关、处理 :latest 模型名后缀,以及给 /models 接口补齐能力声明。
3.2 第一步:先用一条命令确认本地模型支持工具调用
在配置 Cursor 之前,先打开终端跑一条 curl 命令,确认你的本地模型服务(这里以 http://127.0.0.1:11434/v1 为例)能够正常响应 tools 工具调用请求:
curl -s -X POST http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ollama" \
-d '{
"model": "qwen2.5-coder:latest",
"messages": [{"role": "user", "content": "帮我查一下北京今天的天气"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取城市天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}],
"stream": false
}'
只要返回的 JSON 里包含 "tool_calls" 字段,就说明你的本地模型完全具备驱动 Cursor Agent 的能力。
3.3 第二步:解决 :latest 后缀不识别与能力过滤问题
用过 Ollama 的朋友都知道,本地拉取的模型名字通常都带着 :latest 后缀(比如 deepseek-r1:latest、qwen2.5-coder:latest)。但 Cursor 内置的模型匹配函数默认只处理了 / 分隔符,遇到 :latest 就会认为这是个「未知模型」,从而把它藏进折叠列表里。
更关键的是,Cursor 本地运行时在请求 /models 接口时,有一套非常严格的能力准入机制(Fail-Closed):
- 标准的本地
/models接口只返回{"id": "deepseek-r1:latest", "object": "model"},没有任何能力描述。 - 如果我们在解析
/models响应时,为本地对话模型统一补上capabilities字段,同时剔除embedding(向量模型)、tts(语音模型)等非对话模型,Cursor 就会自动为这些模型开启 Agent 工具调用、长上下文和多模态图片输入!
核心处理逻辑非常清晰,只需要下面几十行代码:
// 1. 归一化模型名称:剥离命名空间前缀与 :latest 标签,确保本地模型正常匹配置顶
function normalizeModelId(rawId) {
const slashIdx = rawId.lastIndexOf("/");
const baseName = slashIdx === -1 ? rawId : rawId.slice(slashIdx + 1);
return baseName.replace(/:latest$/u, "");
}
// 2. 为本地 /models 返回的模型列表自动注入 Agent 能力标签
function enrichLocalModels(rawResponse) {
const list = Array.isArray(rawResponse?.data) ? rawResponse.data : [];
// 自动过滤掉向量嵌入、语音合成等非对话模型
const nonChatPattern = /embedding|bge-|rerank|tts|whisper/i;
return list
.filter(item => item && typeof item.id === "string" && !nonChatPattern.test(item.id))
.map(item => {
if (Array.isArray(item.api_types)) return item;
return {
...item,
api_types: ["chat_completions"],
long_context_threshold_tokens: 262144, // 默认 256K 上下文窗口阈值
capabilities: {
context_length: 1048576, // 声明最大 1M 上下文窗口上限(支持 64K~1M 五档切换)
output_modalities: ["text"],
input_modalities: ["text", "image"],
supports_tool_use: true, // 关键:开启 Agent 工具调用权限
supports_streaming: true, // 关键:开启流式输出
supports_reasoning: true, // 关键:开启思考强度调节支持
supports_vision: true,
reasoning_effort: ["none", "low", "medium", "high", "max"]
}
};
});
}
3.4 第三步:实现「本地模型 + 官方原版模型」双模并存(Per-Model Hybrid Routing)
很多教程在教大家开启本地 Agent 运行时的时候,都会直接把客户端的全局开关 localMode 从 false 改成 true,并把数据库里的 availableDefaultModels2 替换成本地模型列表。这样做虽然能让本地模型跑起来,但会带来三个严重的副作用:
- 官方原版模型全部消失:一旦全局
localMode = true,模型过滤函数会把不在localProviderModelIds里的 40 多个 Cursor 官方云端模型全部隐藏。 - Cursor Tab 代码补全与
Cmd + K被禁用:客户端的代码补全服务(isAllowedCpp)和行内编辑服务(Cmd+K)在检测到全局localMode === true时会直接提前返回,导致写代码时失去自动补全。 - BYOK 凭证污染官方请求:如果全局开启了
useOpenAIKey = true并填了http://127.0.0.1:11434/v1,当你切回官方云端模型时,客户端会把本地的ollamaKey 和127.0.0.1地址塞进云端请求头里发给官方服务器,直接触发鉴权报错。
怎么才能既用上本地大模型,又 100% 保留官方原版模型、Cursor Tab 和 Cmd + K 呢?答案是保持全局 localMode = false,改为基于 :latest 后缀的「按模型动态混合路由(Per-Model Hybrid Routing)」:
在底层实现上,我们只需要在 Workbench 渲染层打通以下三个钩子,即可实现零冲突双模并存:
// 1. 按模型动态路由 (AgentClientService.run):仅 :latest 模型走本机 Runtime,其余走官方云端
async function dispatchAgentTurn(ctx, state, action, modelDetails, listener, res, blobs, mgr, ckpt, mcp, runOpts) {
const modelId = String(
runOpts?.requestedModel?.modelId ?? modelDetails?.modelId ?? modelDetails?.modelName ?? ""
);
if (modelId.endsWith(":latest")) {
runOpts?.onNetworkPhaseStart?.();
return this.runLocalAgentInExtensionHost(ctx, state, action, modelDetails, listener, blobs, ckpt, mcp, res, runOpts);
}
return this.client.run(ctx, state, action, modelDetails, listener, res, blobs, mgr, ckpt, mcp, runOpts);
}
// 2. 凭证按模型隔离 (getModelDetailsFromName):防止本地 Key 污染官方云端模型请求
function resolveModelCredentials(modelName, maxMode) {
const isLocalModel = String(modelName ?? "").endsWith(":latest");
const apiKey = isLocalModel ? this._cursorAuthenticationService.getApiKeyForModel(modelName) : undefined;
const baseUrl = isLocalModel
? (this._reactiveStorageService.applicationUserPersistentStorage.openAIBaseUrl ?? "http://127.0.0.1:11434/v1")
: undefined;
return { modelName, apiKey, openaiApiBaseUrl: baseUrl, maxMode };
}
// 3. 自愈式模型目录合并 (computeAvailableDefaultModels & persistAvailableDefaultModels)
function mergeHybridCatalog(persistedCatalog) {
const localModels = persistedCatalog.filter(m => String(m?.name ?? "").endsWith(":latest"));
const officialModels = persistedCatalog.filter(m => !String(m?.name ?? "").endsWith(":latest"));
return [
...(localModels.length > 0 ? localModels : (globalThis.__HYBRID_LOCAL_MODELS__ || [])),
...(officialModels.length > 0 ? officialModels : (globalThis.__HYBRID_OFFICIAL_MODELS__ || [])),
];
}
四、隐藏大招:为自定义模型开启五档「思考强度」与五档「上下文窗口(64K~1M)」
在日常写代码时,我们既不希望模型在所有小问题上都耗费几十秒「过度思考」,也不希望它的上下文窗口被死锁在某一个固定值:
- 思考强度(Reasoning Effort)需要按需切换:改个变量名、写个简单正则,我们希望它秒回(
None或Low);而在排查复杂并发 Bug、设计模块架构时,才需要把思考强度拉满(High或Max)。 - 上下文窗口(Context Tiers)同样需要分档控制:如果把上下文窗口死锁在
1M,长对话到了后半程每次请求都会携带几十万 Token,不仅首字延迟(TTFT)明显变慢,还会引发长文注意力稀释;反过来如果死锁在64K,跨模块重构时又会频繁触发历史摘要压缩(Compaction)导致丢记忆。因此,最佳方案是同时开启 五档思考强度(None / Low / Medium / High / Max) 与 五档上下文窗口(64K / 128K / 256K / 512K / 1M)!
4.1 五档思考强度在底层是怎么工作的?
当你在 Cursor 左下角的模型选择器里切换思考强度时,客户端本地运行时会在发送 HTTP 请求前拦截请求体,并根据你选中的档位动态修改 JSON 参数:
4.2 五档上下文窗口(64K ~ 1M)与后台自动压缩(Compaction)机制
很多人不知道的是,Cursor 本地 Agent 运行时内部自带了一套 基于 context 参数的自动上下文压缩器(Context Compactor):
- 默认情况下,Cursor 只会根据模型的
long_context_threshold_tokens(默认阈值)和context_length(最大上限)生成固定的两档切换。 - 当我们将本地运行时的
tiers扩展为[65536, 131072, 262144, 512000, 1048576]五档,并把默认档位定在黄金甜点位256K(262,144Tokens) 后,你就可以在对话框左下角随时按任务规模切换上下文容量与自动压缩时机:
| 上下文档位 | 对应 Token 上限 | 自动触发后台压缩阈值 | 响应速度与注意力集中度 | 适用工程场景建议 |
|---|---|---|---|---|
64K | 65,536 | 约 55.5K | 极快(注意力最集中) | 单文件函数编写、正则生成、极速轻量问答 |
128K | 131,072 | 约 118K | 快 | 常规单模块日常开发、独立组件 Bug 修复 |
256K(默认) | 262,144 | 约 236K | 黄金平衡点(推荐默认) | 兼顾 15~25 步多文件重构记忆与流式响应速度 |
512K | 512,000 | 约 460K | 较深(适合长链路) | 跨多模块联动重构、大型 PR 全量 Diff 审查 |
1M | 1,048,576 | 约 944K | 超大容量 | 全仓库架构梳理、超长运行日志与多文档交叉排查 |
在本地 Agent 运行时(cursor-local-agent-runtime/dist/main.js 与 cursor-agent-exec/dist/main.js)中,解锁这五档上下文窗口只需要修改两处核心逻辑:
// 1. 将原本只有 [defaultTokens, longTokens] 的两档数组,扩展为 64K ~ 1M 五档枚举
function getContextTierConfig() {
return {
defaultTokens: 262144, // 默认选中 256K 黄金档位
longTokens: 1048576, // 最大支持 1M 超长上下文
tiers: [65536, 131072, 262144, 512000, 1048576]
};
}
// 2. 按二进制 1024 换算档位显示名称(64K / 128K / 256K / 512K / 1M)
function formatContextLabel(tokens) {
if (tokens >= 1048576) return Math.round((tokens / 1048576) * 10) / 10 + "M";
if (tokens >= 1024) return `${Math.round(tokens / 1024)}K`;
return String(tokens);
}
4.3 为什么默认看不见这两个菜单?一键解锁 5×5=25 组合变体
即使底层运行时已经支持了 reasoning_effort 与 context 参数,Cursor 前端界面默认也做了三道限制:
- 实验开关默认关闭:控制模型选择器顶部平铺展示参数栏的实验开关(
effort_first_variant)默认处于"control"关闭状态。 - 设置页本地模式过滤:在
Settings -> Models页面渲染函数里,有一行判断localMode ? {...model, parameterDefinitions: [], variants: []} : model,硬生生把本地模型的参数定义给清空了。 - 左下角徽标未挂载
"context"参数:前端模型选择器在拼接输入框左下角药丸徽标时,默认只读取了["effort", "reasoning"],漏掉了"context",需要把getParamBadge(i, r, "context")一并加入徽标数组。
解除这三道限制后,我们只需要用下面这段 Python 脚本,把本地网关地址、API Key 以及带有 五档思考强度 × 五档上下文窗口(共 5×5=25 个组合变体) 的本地模型置顶注入 Cursor 的本地 SQLite 状态数据库(state.vscdb),同时自动合并保留原有的 45+ 个官方云端模型:
import json
import os
import sqlite3
from pathlib import Path
EFFORT_TIERS = [
("none", "None", "关闭思考,最快响应"),
("low", "Low", "轻量思考,适合简单修改"),
("medium", "Medium", "均衡思考,适合日常编码"),
("high", "High", "深度思考(默认推荐)"),
("max", "Max", "最大思考强度,适合复杂架构与疑难排障"),
]
WINDOW_TIERS = [
(str(64 * 1024), "64K", "64K 上下文窗口(约 55.5K 启动后台压缩,极速防发散)"),
(str(128 * 1024), "128K", "128K 上下文窗口(约 118K 启动后台压缩,适合单模块开发)"),
(str(256 * 1024), "256K", "256K 上下文窗口(默认推荐,约 236K 启动后台压缩)"),
(str(500 * 1024), "512K", "512K 上下文窗口(约 460K 启动后台压缩,适合跨模块重构)"),
(str(1024 * 1024), "1M", "1M 超长上下文窗口(约 944K 启动后台压缩,适合全库分析)"),
]
def create_picker_enum_schema(
field_key: str, title: str, description: str, options: list[tuple[str, str, str]]
) -> dict:
"""构造 Cursor 模型选择器的枚举型参数定义字典。"""
return {
"id": field_key,
"name": title,
"markdownTooltip": description,
"isCycleableByHotkey": (field_key == "reasoning"),
"parameterType": {
"enumParameter": {
"values": [
{"value": val, "displayName": label, "markdownTooltip": tip, "modelPickerBadges": []}
for val, label, tip in options
]
}
},
}
def configure_hybrid_local_and_cloud_models(
gateway_url: str, token_secret: str, local_slug: str, label_title: str
) -> None:
"""配置本地模型与官方云端模型双模并存,并解锁五档思考强度与五档上下文窗口。"""
sqlite_file = Path(os.path.expanduser("~/Library/Application Support/Cursor/User/globalStorage/state.vscdb"))
default_window = str(256 * 1024)
db_conn = sqlite3.connect(str(sqlite_file))
cursor_obj = db_conn.cursor()
cursor_obj.execute(
"INSERT OR REPLACE INTO ItemTable (key, value) VALUES (?, ?)",
("cursorAuth/openAIKey", token_secret),
)
app_user_key = "src.vs.platform.reactivestorage.browser.reactiveStorageServiceImpl.persistentStorage.applicationUser"
cursor_obj.execute("SELECT value FROM ItemTable WHERE key = ?", (app_user_key,))
user_payload = json.loads(cursor_obj.fetchone()[0])
# 保持全局 useOpenAIKey 为 False,避免污染官方云端模型请求
user_payload["useOpenAIKey"] = False
user_payload["openAIBaseUrl"] = gateway_url
local_descriptor = {
"name": local_slug,
"serverModelName": local_slug,
"defaultOn": True,
"clientDisplayName": label_title,
"inputboxShortModelName": label_title,
"supportsAgent": True,
"supportsPlanMode": True,
"supportsSandboxing": True,
"supportsNonMaxMode": True,
"supportsMaxMode": True,
"supportsThinking": True,
"supportsImages": True,
"contextTokenLimit": 1024 * 1024,
"namedModelSectionIndex": 1,
"parameterDefinitions": [
create_picker_enum_schema("reasoning", "Reasoning", "调节模型回答前的思考深度", EFFORT_TIERS),
create_picker_enum_schema("context", "Context", "调节会话最大上下文与自动压缩窗口(默认 256K)", WINDOW_TIERS),
],
"variants": [
{
"parameterValues": [{"id": "reasoning", "value": r_val}, {"id": "context", "value": c_val}],
"displayName": f"{label_title} {r_label} {c_label}",
"displayNameOutsidePicker": f"{label_title} {r_label} {c_label}",
"modelPickerBadges": [],
"isMaxMode": False,
"isDefaultNonMaxConfig": (r_val == "high" and c_val == default_window),
"isDefaultMaxConfig": (r_val == "high" and c_val == default_window),
}
for r_val, r_label, _ in EFFORT_TIERS
for c_val, c_label, _ in WINDOW_TIERS
],
}
# 提取并保留所有非 :latest 的官方云端模型,将本地模型置顶合并
existing_catalog = user_payload.get("availableDefaultModels2", [])
cloud_entries = [m for m in existing_catalog if isinstance(m, dict) and not str(m.get("name", "")).endswith(":latest")]
user_payload["availableDefaultModels2"] = [local_descriptor] + cloud_entries
user_payload["localProviderModelIds"] = [local_slug]
user_payload["localProviderAgentModelIds"] = [local_slug]
ai_cfg = user_payload.setdefault("aiSettings", {})
ai_cfg["lastDefaultModelSetDate"] = "9999999999999"
ai_cfg.setdefault("modelConfig", {})["composer"] = {
"modelName": local_slug,
"maxMode": False,
"selectedModels": [{
"modelId": local_slug,
"parameters": [
{"id": "reasoning", "value": "high"},
{"id": "context", "value": default_window},
],
}],
}
cursor_obj.execute(
"UPDATE ItemTable SET value = ? WHERE key = ?",
(json.dumps(user_payload, ensure_ascii=False), app_user_key),
)
db_conn.commit()
db_conn.close()
print(f"已成功配置本地模型 {local_slug} 与 {len(cloud_entries)} 个官方模型双模并存!")
if __name__ == "__main__":
configure_hybrid_local_and_cloud_models(
gateway_url="http://127.0.0.1:11434/v1",
token_secret="ollama",
local_slug="deepseek-r1:latest",
label_title="DeepSeek R1 (Local)",
)
重启 Cursor 后,点击对话框左下角的模型选择按钮,你会发现菜单顶部同时出现了两排清爽的平铺选项栏:
- 第一排
Reasoning:None/Low/Medium/High/Max(默认选中High); - 第二排
Context:64K/128K/256K/512K/1M(默认选中256K),且输入框左下角会实时显示形如High 256K的当前档位徽标!
五、实战避坑指南:9 个高频报错与一键解决速查表
最后,我把大家在配置过程中最容易碰到的 9 个报错整理成了一张速查表。遇到问题不用慌,直接对照表里的现象找解法:
| 序号 | 遇到的报错或现象 | 背后的真正原因 | 一句话解决办法 |
|---|---|---|---|
| 1 | 点 Verify 报错 Connection failed 或 127.0.0.1 refused | 还在走默认的「云端中转模式」,云端服务器连不上你电脑的 127.0.0.1 | 切换到本地 Agent 运行时模式,或者给本地端口配一个临时反向隧道 |
| 2 | 填完 Base URL 后报 404 Not Found | Base URL 漏写了末尾的 /v1,或者多写了 /chat/completions | 确保 Base URL 严格以 /v1 结尾(例如 http://127.0.0.1:11434/v1) |
| 3 | 本地 /models 有十几个模型,但列表里一个都不显示 | 触发了本地运行时的严格能力校验,缺少 supports_tool_use: true 的模型被全部静默剔除 | 在 /models 响应解析处统一注入 capabilities.supports_tool_use = true |
| 4 | 第一轮调工具正常,第二轮回传结果报 missing thought_signature | 常见于带思考签名的推理模型:中间代理层篡改了首轮返回的 tool_call.id,导致签名丢失 | 走 /chat/completions 原生直连,不要用改写 call_id 的第三方中转脚本 |
| 5 | 模型能对话,但左下角看不到 Reasoning 思考强度与 Context 上下文窗口选项 | 前端实验开关 effort_first 未激活,且设置页在本地模式下清空了 parameterDefinitions | 开启 selected-model-parameters-flat 菜单模式,保留 parameterDefinitions 并生成 5×5=25 组合 variants |
| 6 | 菜单里能切 64K ~ 1M 上下文档位,但输入框左下角只显示 High 不显示 256K | 前端模型选择器的外显徽标数组默认只读取了 ["effort", "reasoning"],未挂载 "context" | 在前端 Workbench 徽标渲染数组中加入 getBadge(i, r, "context") 并更新 product.json 校验和 |
| 7 | macOS 修改客户端脚本重签名后,启动卡住 20 秒或弹钥匙串窗口 | 重签名改变了应用签名身份,触发了 macOS SecurityAgent 拦截钥匙串访问 | 在 ~/.cursor/argv.json 中加上 "use-inmemory-secretstorage": true 即可免弹窗秒开 |
| 8 | 对话中途报错 Failed to call LLM service: invoking wrapper: Requests ending with a model turn are not supported. | 模型流式输出阶段性结论后,工具调用块因触发上游 PROHIBITED_CONTENT 过滤或网络中断被丢弃,Cursor 自动重试时请求末尾停留在 role: "assistant" | 在本地 Runtime 请求序列化出口加入末尾 assistant 回合检测,自动追加 role: "user" 续接提醒或补齐 tool 响应 |
| 9 | 配好本地模型后,原有的官方模型消失、切换官方模型报 Key 错误,且 Cursor Tab / Cmd+K 失效 | 全局强行开启了 localMode = true、全量覆盖了 availableDefaultModels2,且 useOpenAIKey = true 污染了云端请求 | 保持全局 localMode = false 与 useOpenAIKey = false,在 AgentClientService.run 与 getModelDetailsFromName 中按 :latest 后缀动态分流并合并保留官方模型目录 |
结语
把自定义大模型 API 和本地推理服务真正跑通之后,Cursor 就不再只是一个绑定固定云端订阅的编辑器,而是一个可以随时挂载任何开源模型、自建网关和深度推理能力的本地 AI 工作台。
日常写业务代码时切到 Low 或 Medium 享受极速流式响应,遇到硬骨头时切到 High 或 Max 让模型深度思考后再动手改代码——希望这篇从原理到实操的完整指南,能帮你把自己的大模型 API 在 Cursor 里真正用出生产力!





2202



被折叠的 条评论
为什么被折叠?



