VS Code 插件开发(二)— 用 TaoToken 统一 Key 打通 Command 注册与调试配置
1. 从一次插件调试说起Command 注册了却按不动写 VS Code 插件的人大多经历过这个瞬间registerCommand写完了package.json里也填了contributes.commandsF5 一按命令面板里搜得到回车却没反应或者干脆报「command not found」。更麻烦的是插件里要接 AI 能力时Key 散落在各个文件里调试一次改一次改到最后自己都记不清哪个是当前生效的。这篇就围绕两个实操点展开一是把自定义 Command 从注册到调试跑通二是用 TaoToken 统一管理插件里的 API Key 和请求通道让 Command 触发时能稳定拿到模型返回。适合已经在写 VS Code 插件、准备在插件内接入 AI 能力的开发者。读完你能拿到一份可直接复制的package.json骨架、settings.json配置片段以及 F5 调试验证 Command 的具体动作。先说清楚 TaoToken 在这里的角色它是一个统一的模型 API 接入层插件不需要为每个模型单独维护 Key 和地址通过一个 API Key 就能调用对话、编码等能力。官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。插件里我们只关心两件事Key 从哪读、请求发到哪。2. TaoToken 前置Key 与通道先备好在写代码之前先把外部依赖准备好否则调试时容易把「Key 没配」误判成「Command 没注册」。第一步是拿到 API Key。打开 https://taotoken.net/api-keys 登录后创建一个 Key复制出来。这个 Key 后面会写进 VS Code 的settings.json而不是硬编码在插件源码里。硬编码的坑我踩过一旦提交到仓库Key 就泄露了而且换 Key 要重新打包插件。第二步是确认 API 通道地址。插件里请求的 base URL 用 https://taotoken.net/api 不要带任何多余路径。很多请求 404 的情况都是因为把 base URL 写成了带/v1/chat/completions的完整地址又在代码里拼了一次。第三步是了解模型标识。TaoToken 的模型对话入口在 https://taotoken.net/models 你可以在页面上直接试跑确认模型名和返回格式再写进插件配置。插件里建议把模型名也做成可配置项方便切换。如果你后续要做长期编码类插件或 Agent 类功能可以关注 Coding Planhttps://taotoken.net/coding-plan 。它更适合高频调用场景这里先不展开本篇聚焦 Command 与调试。注意Key 只放在用户级或工作区级的settings.json里不要写进package.json的contributes.configuration默认值默认值会随插件分发出去。3. 可复制配置package.json 与 settings.json这一节给两份可直接抄的配置。先看package.json里 Command 注册和配置项声明的骨架。{ name: ai-command-demo, version: 0.0.1, engines: { vscode: ^1.85.0 }, activationEvents: [], main: ./out/extension.js, contributes: { commands: [ { command: aiCommandDemo.askModel, title: AI: Ask Model, category: AI Command Demo }, { command: aiCommandDemo.openSettings, title: AI: Open TaoToken Settings, category: AI Command Demo } ], configuration: { title: AI Command Demo, properties: { aiCommandDemo.apiKey: { type: string, default: , description: TaoToken API Key请在设置中填写 }, aiCommandDemo.baseUrl: { type: string, default: https://taotoken.net/api, description: TaoToken API 通道地址 }, aiCommandDemo.model: { type: string, default: gpt-4o-mini, description: 调用的模型标识 } } } }, scripts: { compile: tsc -p ./, watch: tsc -watch -p ./ }, devDependencies: { types/vscode: ^1.85.0, types/node: ^20.0.0, typescript: ^5.3.0 } }几个关键点。activationEvents在新版本里可以留空VS Code 会根据contributes.commands自动推断激活时机不用再手写onCommand。contributes.commands里的command字段必须和代码里registerCommand的第一个参数完全一致大小写都不能差这是「命令面板搜得到但执行报错」最常见的原因。再看settings.json的配置片段。用户级设置通过命令面板「Preferences: Open User Settings (JSON)」打开工作区级则是.vscode/settings.json。{ aiCommandDemo.apiKey: sk-你的TaoToken密钥, aiCommandDemo.baseUrl: https://taotoken.net/api, aiCommandDemo.model: gpt-4o-mini }插件代码里通过vscode.workspace.getConfiguration(aiCommandDemo)读取这三项。这样调试时改 Key 不用动源码改完保存即可生效省去反复编译。4. 注册 Command 并接入模型请求配置就绪后写extension.ts。下面这段把 Command 注册、配置读取、请求发送串起来。import * as vscode from vscode; export function activate(context: vscode.ExtensionContext) { const askModel vscode.commands.registerCommand( aiCommandDemo.askModel, async () { const config vscode.workspace.getConfiguration(aiCommandDemo); const apiKey config.getstring(apiKey); const baseUrl config.getstring(baseUrl); const model config.getstring(model); if (!apiKey) { vscode.window.showErrorMessage(请先在设置中填写 aiCommandDemo.apiKey); return; } const editor vscode.window.activeTextEditor; const selected editor ? editor.document.getText(editor.selection) : ; if (!selected) { vscode.window.showWarningMessage(请先选中一段代码再执行); return; } await vscode.window.withProgress( { location: vscode.ProgressLocation.Notification, title: 请求模型中... }, async () { try { const res await fetch(${baseUrl}/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${apiKey} }, body: JSON.stringify({ model, messages: [ { role: system, content: 你是一个代码解释助手回答简洁。 }, { role: user, content: 解释这段代码\n${selected} } ] }) }); if (!res.ok) { const text await res.text(); vscode.window.showErrorMessage(请求失败 ${res.status}: ${text}); return; } const data await res.json(); const content data.choices?.[0]?.message?.content ?? 无返回内容; const doc await vscode.workspace.openTextDocument({ content, language: markdown }); await vscode.window.showTextDocument(doc, vscode.ViewColumn.Beside); } catch (err) { vscode.window.showErrorMessage(请求异常: ${String(err)}); } } ); } ); const openSettings vscode.commands.registerCommand( aiCommandDemo.openSettings, () { vscode.commands.executeCommand( workbench.action.openSettings, aiCommandDemo ); } ); context.subscriptions.push(askModel, openSettings); }这里有两个设计取舍值得说。第一用fetch而不是引入额外 HTTP 库Node 18 以上内置了fetchVS Code 1.85 对应的 Electron 版本已经支持少一个依赖少一层打包问题。第二把结果写进一个新的 Markdown 文档而不是弹窗长回答在弹窗里会被截断文档里可以滚动、复制、继续编辑。openSettings这个 Command 是顺手加的它调用内置命令workbench.action.openSettings并传入过滤词用户点一下就能跳到本插件的配置项比让用户自己去设置里翻要友好。5. F5 调试验证Command 触发的完整动作配置和代码都写完后进入验证环节。按下面的顺序操作每一步都有明确的预期结果。先编译。在终端执行npm run compile确认out/extension.js生成且无 TypeScript 报错。如果报Cannot find module vscode检查devDependencies里是否装了types/vscode。然后按 F5 启动扩展开发宿主。VS Code 会新开一个窗口标题栏带[Extension Development Host]。这个新窗口里才加载了你刚写的插件原窗口不会生效这是新手最容易搞混的一点。在新窗口里按CtrlShiftP打开命令面板输入AI: Ask Model。如果搜不到回到package.json检查contributes.commands的command和title是否拼写正确改完需要重新 F5。搜到后先别急着执行打开新窗口的设置搜索aiCommandDemo把apiKey填上。保存后回到编辑器选中一段代码再执行AI: Ask Model。预期结果是右下角出现进度通知随后侧边打开一个 Markdown 文档里面是模型返回的解释。如果进度通知一闪而过并弹出错误看错误内容。401说明 Key 不对或没填404多半是baseUrl拼错确认是https://taotoken.net/api且代码里拼的是/v1/chat/completionsmodel not found则是模型名写错去 https://taotoken.net/models 核对。验证openSettings命令命令面板输入AI: Open TaoToken Settings回车后应直接跳到设置页并过滤出本插件配置项。这一步能过说明 Command 注册和executeCommand调用都没问题。调试过程中改代码如果开了npm run watchTypeScript 会自动重编译但扩展宿主窗口需要按CtrlR重载才生效不用关掉重开。6. 本篇常见错排查把上面流程里高频出现的几个问题集中列一下方便对照。命令面板搜不到命令。九成是package.json的contributes.commands没写、写错或者改完没重新 F5。注意command字段是唯一标识title才是显示名两者不要混。执行命令报command xxx not found。说明registerCommand没执行到通常是activate函数里抛了异常提前退出或者命令名和package.json不一致。在activate开头加一行console.log(activated)在扩展宿主的「帮助 切换开发人员工具」里看控制台输出。请求一直转圈或超时。先确认网络能访问https://taotoken.net/api再确认baseUrl没有多余斜杠。如果用了公司网络检查是否有出站限制。返回401。Key 没填、填错或者填到了工作区设置但当前打开的是另一个工作区。用openSettings命令跳过去确认当前生效的值。返回内容为空。检查data.choices[0].message.content的路径是否和实际返回一致不同模型返回结构可能有细微差别建议先把data打印出来看一次。选中文本为空导致警告。这是预期行为askModel里做了空选中拦截。如果希望不选中也能用可以把selected为空时改成取整个文档内容但要注意长文档会超出上下文限制。Key 相关操作和接入细节可以对照文档https://taotoken.net/doc 。需要直接试跑模型确认返回格式用模型对话页https://taotoken.net/models 。长期做编码类插件、调用频率高的话看 Coding Planhttps://taotoken.net/coding-plan 。Key 管理入口统一在 https://taotoken.net/api-keys 。最后补一个实用技巧把aiCommandDemo.model做成快速切换项在package.json里加一个enum类型的配置或者在插件里注册一个aiCommandDemo.switchModel命令用vscode.window.showQuickPick列出常用模型选中后写回配置。这样调试不同模型时不用反复开设置页Command 体系也能顺势扩展成一个小型命令中心。