
1. 从一次插件请求 401 说起自定义配置到底该怎么写VS Code 插件开发到第五篇很多人会卡在同一个地方插件功能跑通了但请求地址和密钥全写死在代码里换一个环境就得重新打包。更麻烦的是团队里每个人用的模型服务地址不一样你不可能让所有人都去改源码。这时候就需要 VS Code 的配置贡献点configuration contribution point出场了。这篇要解决的问题很具体把插件里所有对外请求的 endpoint 和 API Key统一收敛到settings.json里并且让用户在设置面板里能直接改。落地场景我选的是把请求改到 TaoToken——它是一个兼容 OpenAI 接口规范的模型调用服务插件只要把 Base URL 和 Key 换成 TaoToken 的就能直接复用现有的请求逻辑。TaoToken 能做什么简单说就是给插件提供一个统一的模型调用入口适合需要在自己的工具里集成对话、补全、代码生成能力的开发者。你可能会问为什么不直接把 Key 写在代码里因为一旦写死插件就没法分发给别人用也没法做多环境切换。VS Code 的配置系统支持 workspace 和 global 两级作用域正好能解决这个问题workspace 级别放项目相关的 endpointglobal 级别放个人的 API Key。下面我会从package.json的声明开始一步步写到读取、更新、验证最后把常见的报错也过一遍。整篇的节奏是先讲清楚配置项怎么声明再讲代码里怎么读写然后给一份可以直接复制的配置片段接着验证请求是否真的打到了 TaoToken最后排查几个我实际遇到过的错误。如果你跟着做最终效果是在命令面板输入一个命令就能切换配置并看到请求成功返回。2. TaoToken 前置准备Base URL、Key 和 Model ID 三件套在动配置代码之前得先把 TaoToken 这边的信息准备好。不管你后面用哪种方式接入本质上都需要三个东西Base URL、API Key、Model ID。这三个缺一个请求就会失败。Base URL 是https://taotoken.net/api注意这个地址不带任何查询参数直接作为请求的前缀。API Key 需要你去控制台创建路径是https://taotoken.net/console进去之后找到 API Keys 页面新建一个 Key 并复制下来。这个 Key 只会显示一次丢了就得重新建。Model ID 则取决于你要调用的具体模型可以在模型对话页面或者接入文档里查到。这里要提醒一句API Key 属于敏感信息不要提交到 Git 仓库也不要写死在package.json的默认值里。正确的做法是把它放在 global 级别的配置中或者用 VS Code 的 SecretStorage API 存储。本篇为了演示配置读写链路会先用 global 配置来存 Key你在实际项目中可以换成 SecretStorage。如果你还没创建 Key可以先去https://taotoken.net/api-keys这个 deep link 页面登录后直接新建。创建完之后建议先在模型对话页面手动发一条测试请求确认 Key 是有效的。这一步能帮你排除掉后面很多「到底是配置问题还是 Key 问题」的干扰。另外TaoToken 的接口是兼容 OpenAI 格式的所以你的插件里如果用的是openai这个 npm 包只需要把baseURL改成 TaoToken 的地址apiKey改成你的 Key其余代码基本不用动。这也是我选它作为落地场景的原因——改动量小但配置读写的链路是完整的。准备好这三件套之后我们就可以进入代码部分了。下一节会先改package.json把配置项声明出来。3. 可复制配置package.json 贡献点与 settings.json 片段VS Code 插件的配置项必须在package.json的contributes.configuration里声明否则workspace.getConfiguration()读不到设置面板里也不会显示。下面这份是我实际用的配置你可以直接复制到自己的package.json里注意把vsCodePlugin换成你自己的插件前缀。{ contributes: { configuration: { title: TaoToken 插件配置, properties: { vsCodePlugin.taoTokenBaseUrl: { type: string, default: https://taotoken.net/api, description: TaoToken 接口的基础地址一般不需要修改 }, vsCodePlugin.taoTokenApiKey: { type: string, default: , description: TaoToken 控制台创建的 API Key建议在用户设置中配置 }, vsCodePlugin.taoTokenModelId: { type: string, default: gpt-4o-mini, description: 调用的模型 ID可在 TaoToken 接入文档中查询 }, vsCodePlugin.showTip: { type: boolean, default: true, description: 是否在请求成功后显示提示 } } }, commands: [ { command: vsCodePlugin.configurationReadWrite, title: TaoToken: 测试配置读写 } ] } }声明完之后用户在settings.json里就能看到这几个配置项。global 级别的settings.json路径可以通过命令面板的「Preferences: Open User Settings (JSON)」打开workspace 级别的则是项目根目录下的.vscode/settings.json。下面是一份 workspace 级别的示例把 Base URL 和 Model ID 固定到项目里Key 留空让每个人自己填{ vsCodePlugin.taoTokenBaseUrl: https://taotoken.net/api, vsCodePlugin.taoTokenModelId: gpt-4o-mini, vsCodePlugin.showTip: true }这里有个细节要注意type为string的配置项如果默认值是空字符串VS Code 不会报错但你在代码里读取时要做好空值判断。另外配置项的 key 建议用「插件名.配置名」的格式避免和其他插件冲突。我试过用纯小写的taotoken.baseurl结果在设置面板里搜索不到后来改成驼峰才正常显示。配置声明好之后package.json这部分就算完成了。接下来进入代码部分讲怎么在extension.js里读取和更新这些配置。4. 读取与更新configurationReadWrite.js 完整实现配置的读写都通过vscode.workspace.getConfiguration()这个 API。读取用get()更新用update()。下面是我在src/configurationReadWrite.js里的完整实现你可以直接拿去用。const vscode require(vscode); async function configurationReadWrite() { const config vscode.workspace.getConfiguration(vsCodePlugin); // 读取当前配置 const baseUrl config.get(taoTokenBaseUrl); const apiKey config.get(taoTokenApiKey); const modelId config.get(taoTokenModelId); const showTip config.get(showTip); console.log(当前 Base URL:, baseUrl); console.log(当前 Model ID:, modelId); console.log(API Key 是否已配置:, apiKey ? 是 : 否); // 如果 Key 为空提示用户去配置 if (!apiKey) { const action await vscode.window.showWarningMessage( 尚未配置 TaoToken API Key是否现在打开设置, 打开设置 ); if (action 打开设置) { vscode.commands.executeCommand( workbench.action.openSettings, vsCodePlugin.taoTokenApiKey ); } return; } // 更新 showTip 配置演示写入链路 await config.update(showTip, !showTip, vscode.ConfigurationTarget.Global); if (showTip) { vscode.window.showInformationMessage( 配置读取成功当前模型${modelId} ); } } module.exports { configurationReadWrite };然后在extension.js里注册这个命令const vscode require(vscode); const { configurationReadWrite } require(./src/configurationReadWrite); function activate(context) { const disposable vscode.commands.registerCommand( vsCodePlugin.configurationReadWrite, configurationReadWrite ); context.subscriptions.push(disposable); } module.exports { activate };这里有几个关键点。第一getConfiguration(vsCodePlugin)的参数是配置项的前缀不是完整的 key。比如你的配置项是vsCodePlugin.taoTokenBaseUrl那么前缀就是vsCodePlugin读取时用get(taoTokenBaseUrl)。第二update()的第三个参数是作用域vscode.ConfigurationTarget.Global表示写入用户设置Workspace表示写入当前工作区。如果你不传这个参数VS Code 会根据当前上下文自动选择但显式指定更稳妥。第三update()返回的是 Promise记得用await否则可能出现「设置还没写完就去读」的竞态问题。我在早期版本里就踩过这个坑更新完配置立刻读取结果拿到的是旧值排查了半天才发现是没加await。读取和更新都实现之后下一步就是验证请求是否真的打到了 TaoToken。下一节会用一个实际的 HTTP 请求来验证配置生效。5. 验证请求确认配置真的打到了 TaoToken配置读写的最终目的是让请求走对地址。下面这段代码会在命令触发时用读取到的配置发一条真实的请求验证 Base URL、Key、Model ID 是否都生效。async function testRequest() { const config vscode.workspace.getConfiguration(vsCodePlugin); const baseUrl config.get(taoTokenBaseUrl); const apiKey config.get(taoTokenApiKey); const modelId config.get(taoTokenModelId); if (!apiKey) { vscode.window.showErrorMessage(API Key 未配置请先在设置中填写); return; } try { const response await fetch(${baseUrl}/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${apiKey} }, body: JSON.stringify({ model: modelId, messages: [{ role: user, content: 回复 OK 两个字母即可 }], max_tokens: 10 }) }); if (!response.ok) { const errText await response.text(); vscode.window.showErrorMessage(请求失败 ${response.status}: ${errText}); return; } const data await response.json(); const content data.choices?.[0]?.message?.content ?? (空响应); vscode.window.showInformationMessage(TaoToken 返回${content}); } catch (err) { vscode.window.showErrorMessage(请求异常${err.message}); } }把这段挂到命令上运行vsCodePlugin.configurationReadWrite之后如果配置正确你会看到右下角弹出「TaoToken 返回OK」。如果返回的是 401说明 Key 有问题如果返回 404说明 Base URL 拼错了。注意baseUrl后面要拼/v1/chat/completions因为 TaoToken 的 Base URL 是https://taotoken.net/api完整的请求地址是https://taotoken.net/api/v1/chat/completions。验证通过之后你可以把showTip配置改成false再运行一次命令观察提示是否消失。这一步能确认update()写入的配置真的生效了。如果提示没消失去settings.json里看看vsCodePlugin.showTip的值有没有被改掉。实测下来整个链路跑通之后换环境只需要改settings.json不用重新打包插件。这也是配置系统最大的价值。6. 常见报错排查401、local proxy failed 与 reading choices配置读写过程中会遇到几类典型错误我按实际遇到的频率排个序。第一类是 401 Unauthorized。报错信息通常是{error:{message:Invalid API key}}。原因一般是 Key 没配置、配置到了 workspace 但当前打开的不是那个工作区、或者 Key 复制时多了空格。排查方法是先在命令面板运行「Preferences: Open User Settings (JSON)」确认vsCodePlugin.taoTokenApiKey有值且没有首尾空格。如果用的是 workspace 配置确认.vscode/settings.json在当前项目根目录下。第二类是local proxy failed或连接超时。这类报错通常和网络环境有关不是配置本身的问题。你需要确认当前网络能正常访问https://taotoken.net/api。可以在终端里用curl -I https://taotoken.net/api测试连通性。如果连不上检查一下是否有防火墙或公司网络策略拦截。第三类是Cannot read properties of undefined (reading choices)。这个报错说明请求返回了但返回结构里没有choices字段。常见原因是 Base URL 拼错了比如写成了https://taotoken.net少了/api或者多拼了一个/v1导致路径变成/api/v1/v1/chat/completions。排查方法是把完整的请求 URL 打印出来和接入文档里的示例对比。第四类是配置更新后不生效。这种情况多半是作用域搞混了你在 workspace 里更新了 Global 配置但读取时用的是 workspace 作用域两者不是同一个存储位置。解决办法是统一作用域或者在读取时用config.inspect(taoTokenApiKey)查看各个作用域的值。第五类是 OAuth 相关的报错。如果你在插件里集成了需要 OAuth 的模型服务配置里可能涉及 token 刷新。这类报错通常表现为OAuth token expired或refresh failed。排查时先确认 token 是否过期再检查刷新逻辑里的 client ID 和回调地址是否和配置一致。把这几类错误过一遍基本上配置读写链路上的坑就覆盖得差不多了。如果遇到其他报错优先看完整的错误信息里面通常会带 HTTP 状态码和返回体定位起来会快很多。7. 下一步把配置接入你的实际插件配置读写跑通之后你可以把它接入到实际的请求逻辑里。比如你的插件有一个代码补全功能原来请求地址是写死的现在改成从配置读取const config vscode.workspace.getConfiguration(vsCodePlugin); const baseUrl config.get(taoTokenBaseUrl); const apiKey config.get(taoTokenApiKey); const modelId config.get(taoTokenModelId);然后把这个baseUrl和apiKey传给请求函数。这样用户只需要在设置里填一次所有功能都会走 TaoToken。如果你打算长期做编码类插件或者 Agent 类工具可以了解一下 Coding Plan它适合需要稳定调用和批量处理的场景。配置相关的 API 文档在接入文档里里面有完整的参数说明和示例。模型对话页面可以用来快速验证 Key 和模型是否可用。最后提醒一点API Key 不要硬编码在源码里也不要在日志里打印完整 Key。生产环境建议用 VS Code 的 SecretStorage API 存储配置项里只放 Base URL 和 Model ID 这类非敏感信息。这样即使插件分发给别人也不会泄露你的 Key。