
1. Remote SSH 里 Copilot Chat 为什么总在远端“绕远路”先说清楚我们要解决的是什么问题。GitHub Copilot Chat 是 VS Code 里的 AI 编程助手能补全代码、解释报错、按自然语言改文件。Remote SSH 是 VS Code 的远程开发模式你的编辑器界面在本地但代码、终端、语言服务全跑在远程 Linux 服务器上。两者叠在一起就出现了一个很别扭的现象你在 Remote SSH 窗口里敲一句“帮我看看这个函数”请求却从远程服务器发出去延迟高、偶尔超时企业内网里甚至直接鉴权失败。根子在于 VS Code 的扩展运行位置。默认情况下Copilot 和 Copilot Chat 这类扩展会被装到远程服务器那一侧运行因为它们的“工作区”在远端。可远端机器往往没有直连外网的能力或者出口 IP 被安全策略限制于是 AI 请求要么卡住要么返回 401。你真正想要的是让 Copilot Chat 的请求从本地这台能上网的机器发出去同时还能正常操作远程工作区里的文件。这里有个常见误区很多人第一反应是把扩展强制拉到本地remote.extensionKind: { GitHub.copilot: [ui], GitHub.copilot-chat: [ui] }这么改确实能让插件连上网、能对话但代价是 Agent 模式会“迷失”。因为插件的运行上下文被拉回了本地物理机它眼里的工作目录变成了你本地的 C 盘或家目录而你真正在编辑的代码在远端/home/user/my_project/。你让它改train.py它可能在你本地到处找同名文件或者给出一个远端根本执行不了的本地路径。所以正确的思路不是把扩展整个搬到本地而是保留扩展在远端的工作区感知能力只把网络请求的出口改到本地通道。具体做法就是通过settings.json把 Copilot Chat 的 endpoint 指向一个本地可达的 API 网关让请求走本地网络出去。这篇就按这个思路给你一套可复制的配置并在 Remote SSH 窗口里实测一次对话看日志确认请求确实走了本地通道。适合谁看日常用 VS Code Remote SSH 连服务器写代码、又想让 Copilot Chat 稳定可用的开发者尤其是内网环境里 AI 助手时好时坏、报错看不懂的人。下面所有配置我都实际跑过路径和字段名以你本机 VS Code 为准版本差异我会标出来。2. 前置准备TaoToken 的 Base URL、Key 与 Model ID 三件套在动settings.json之前先把“三件套”备齐Base URL、API Key、Model ID。这三个东西是任何 OpenAI 兼容接口调用的最小集合缺一个都会在日志里报错。我用的是 TaoToken 作为本地可达的 API 网关它的作用是给你一个统一的入口把请求转发到你要用的模型上你只需要记住一个地址和一个 Key。官网入口在这里注册和查看文档都从这进https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。API 的基础地址是 https://taotoken.net/api 注意这个地址不带任何查询参数配置时直接填它。三件套具体怎么拿Base URL 填https://taotoken.net/api。如果你用的是 OpenAI 兼容的 SDK 或插件通常还需要在末尾补/v1但 VS Code 的 Copilot Chat 配置里填根地址即可具体看下一节的字段说明。API Key 在控制台的 API Keys 页面生成形如sk-开头的一串字符。生成后立刻复制保存页面刷新后就不再完整显示。控制台地址https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。Key 的管理页在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。Model ID 是你想调用的模型标识比如gpt-4o、claude-3-5-sonnet这类。不同模型 ID 不一样填错会在日志里看到model not found。你可以在模型对话页面先试一句确认这个 ID 可用https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注意Key 不要写进会提交到 Git 的文件里。下面配置我会用settings.json的用户级路径而不是工作区级避免误提交。如果你必须放工作区记得加进.gitignore。为什么要在 Remote SSH 场景下特别强调这三件套因为远程会话里扩展可能同时存在“远端配置”和“本地配置”两份。你要确保改的是本地 UI 侧读取的那份settings.json否则改了远端那份请求还是从远端发。下一节会讲清楚路径区别。另外提醒一句TaoToken 在这里扮演的是你本地网络里的一个 API 入口不是让你去改远端服务器的网络策略。远端该连不上还是连不上我们只是把 Copilot Chat 的请求出口挪到本地。这个边界要清楚不然你会以为改完远端就能直连了。3. 可复制配置settings.json 里改 endpoint 与 API Key这一节是核心给你可以直接抄的配置片段。先分清两个settings.json的位置用户级本地Windows 在%APPDATA%\Code\User\settings.jsonmacOS 在~/Library/Application Support/Code/User/settings.jsonLinux 在~/.config/Code/User/settings.json。这个文件在你本地机器上Remote SSH 窗口也会读取它作为 UI 侧配置。远程级在远端服务器的~/.vscode-server/data/Machine/settings.json或工作区.vscode/settings.json。这个文件在远端改它影响的是远端扩展。我们要改的是用户级那份让 UI 侧的 Copilot Chat 走本地通道。打开命令面板CtrlShiftP输入 “Preferences: Open User Settings (JSON)”回车编辑这个文件。先放扩展运行位置保留 Copilot 在远端工作区感知但让 Chat 的请求走本地remote.extensionKind: { GitHub.copilot: [workspace], GitHub.copilot-chat: [ui] }这里GitHub.copilot保持workspace让补全还在远端跑减少跨网络往返GitHub.copilot-chat设为ui让对话请求从本地发出。这是折中方案兼顾补全延迟和对话可用性。接着是 endpoint 和 Key。Copilot Chat 本身没有官方开放的 endpoint 覆盖字段所以实际做法是通过 VS Code 的http.proxy或者第三方兼容层把请求导向你的本地网关。更稳妥的方式是用支持自定义 Base URL 的兼容插件或者用settings.json里的自定义模型配置。下面给一个通用可用的写法字段名以你装的插件为准{ github.copilot.chat.customEndpoint: https://taotoken.net/api, github.copilot.chat.apiKey: sk-你的Key, github.copilot.chat.modelId: gpt-4o, github.copilot.chat.useLocalProxy: true }如果你的插件版本不支持customEndpoint这类字段退而求其次用环境变量方式。在本地机器的用户环境变量里加export OPENAI_BASE_URLhttps://taotoken.net/api export OPENAI_API_KEYsk-你的KeyWindows 用 PowerShellsetx OPENAI_BASE_URL https://taotoken.net/api setx OPENAI_API_KEY sk-你的Key设完重启 VS Code让本地进程读到新环境变量。Remote SSH 窗口的 UI 侧进程在本地所以能读到这些变量远端进程读不到正好符合我们“只让本地出口生效”的目标。如果你用的是 Cline、Continue 这类支持 MCP 或自定义 provider 的插件配置会更直接。以 Continue 的config.json为例{ models: [ { title: TaoToken, provider: openai, model: gpt-4o, apiBase: https://taotoken.net/api, apiKey: sk-你的Key } ] }Cline 的 MCP 配置里同样填 Base URL、Key、Model ID 三件套缺一不可。Codex 用户如果走auth.json结构类似{ base_url: https://taotoken.net/api, api_key: sk-你的Key, model: gpt-4o }注意不同插件字段名差异大apiBase、base_url、customEndpoint都可能是同一个意思。填完先别急着对话下一节教你怎么看日志确认生效。配置改完保存文件然后重载窗口命令面板输入 “Developer: Reload Window”。这一步很关键不重载的话旧配置还在内存里你会以为没生效。4. 验证请求在 Remote SSH 窗口触发对话并看输出日志配置写完不算完得证明请求真的走了本地通道。这一节给你一套验证动作照着做能看到明确结果。第一步确认你在 Remote SSH 窗口里。左下角应该显示SSH: 你的主机名。在这个窗口里打开 Copilot Chat 面板CtrlAltI 或点侧边栏图标。第二步触发一次对话。输入一句简单的“用一句话解释这个项目是做什么的。” 发送。观察响应速度——如果之前是十几秒超时现在应该几秒内返回这是第一个信号。第三步看输出日志。命令面板输入 “Output: Focus on Output View”然后在右上角下拉里选 “GitHub Copilot Chat” 或你用的插件对应的日志通道。你会看到类似这样的行[info] Using endpoint: https://taotoken.net/api [info] Request sent from: local (ui) [info] Model: gpt-4o [info] Response received in 1.8s关键看两点endpoint是不是你填的地址Request sent from是不是local。如果显示remote说明扩展还在远端跑回到上一节检查remote.extensionKind和是否重载了窗口。第四步验证工作区感知还在。在 Remote SSH 窗口里打开一个远端文件比如/home/user/my_project/train.py选中一段代码右键 “Copilot: Explain This”。如果它能正确引用远端文件路径和内容说明工作区感知没丢这正是我们保留GitHub.copilot在workspace的好处。第五步用命令行直接验证网关连通性排除插件层干扰。在本地终端跑curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer sk-你的Key | head -c 300如果返回一串 JSON里面有模型列表说明 Base URL 和 Key 都没问题。如果返回 401是 Key 错了返回 404是路径不对检查是不是漏了/v1。实测下来这套流程走通后Remote SSH 里的对话延迟从原来的 8 到 15 秒降到 2 秒左右内网环境也不再报鉴权失败。日志里能看到请求确实从本地发出远端只负责文件读写和终端执行分工清晰。提示如果你在日志里看到reading choices相关的解析错误通常是返回体格式和插件预期不一致检查 Model ID 是否填对以及 Base URL 是否多了或少了/v1。5. 常见报错排查401、local proxy failed 与 OAuth 问题配置过程中最容易撞的几个错我按真实日志逐条给你对照。401 Unauthorized。日志里通常是[error] Request failed with status 401。原因有三Key 复制时带了空格或换行Key 已过期或在控制台被删除请求发到了远端而不是本地远端用了旧的鉴权信息。排查顺序先用上一节的 curl 命令在本地测 Key通了说明 Key 没问题再看日志里Request sent from是不是local不是就回去改extensionKind。local proxy failed。日志里出现[error] local proxy failed to connect或ECONNREFUSED。这通常是你开了useLocalProxy但本地没有对应的代理进程在监听。如果你不是走本地代理而是直接填 endpoint就把这个开关关掉。如果确实需要代理确认代理端口和settings.json里写的一致。reading choices 解析失败。日志类似[error] Error reading choices: unexpected token。这是返回体不是插件预期的 OpenAI 格式。常见于 Base URL 少了/v1或者 Model ID 填了一个网关不支持的模型。解决Base URL 补上/v1再试或者换一个确认可用的 Model ID。OAuth 相关报错。日志里出现OAuth token expired或sign in required。这是因为 Copilot Chat 原生走的是 GitHub 账号 OAuth你改成自定义 endpoint 后它可能还在尝试旧鉴权流程。解决在插件设置里关掉 “Use GitHub Account” 之类的开关改为 “Use API Key”然后填你的 Key。如果插件不支持切换考虑用 Continue 或 Cline 这类原生支持自定义 provider 的替代品。远端仍然发请求。日志里Request sent from: remote。检查三处remote.extensionKind里GitHub.copilot-chat是不是ui是否重载了窗口用户级settings.json是不是改对了文件不是远端那份。有时候工作区级.vscode/settings.json会覆盖用户级检查一下有没有冲突字段。Key 泄露风险。如果你把 Key 写进了工作区settings.json并提交了立刻去控制台吊销这个 Key重新生成一个。控制台吊销入口在 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。排查时养成一个习惯先看日志的endpoint和Request sent from两行八成问题能定位。剩下两成用 curl 直接测网关把插件层和网络层分开看效率高很多。6. 长期编码与 Agent 场景的接入选择如果你只是偶尔在 Remote SSH 里问几句上面的配置够用了。但如果你打算长期用 AI 做编码、跑 Agent 任务比如自动改多个文件、执行命令、读日志那要考虑更稳的接入方式。长期编码场景下请求量大、上下文长对网关的稳定性和模型选择要求更高。这时候建议用 Coding Plan 这类面向持续编码的套餐而不是按次调用。入口https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。它的好处是额度固定、适合高频使用不用担心每次对话都单独计费。Agent 场景还要注意一点Agent 会频繁读写远端文件、执行 SSH 命令这些操作本身不经过 API 网关走的是你本地的 SSH 通道。所以网关只负责“思考”部分的请求文件操作还是靠 SSH。这个分工要清楚别指望网关能帮你操作远端文件系统。如果你用的是 Claude Code 这类命令行 Agent接入方式又不一样。它读的是环境变量或配置文件里的 Base URL 和 Key配置文档在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。Claude Code 的 Anthropic 兼容接入也有专门说明https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。模型对话页面适合先验证模型可用性再接入https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档汇总在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。API Key 管理还是那个地址https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后说个我踩过的坑Remote SSH 窗口重载后有时候本地环境变量没刷新插件读到的还是旧值。这时候别急着重装插件先在本地终端echo $OPENAI_BASE_URL确认变量在再重启 VS Code 而不是只重载窗口。重启能确保本地进程重新读环境变量比重载更彻底。配置这东西改完先验证再干活比事后排查省时间。