1. 从零认识 VS Code 左侧抽屉面板
如果你写过 VS Code 插件,大概率遇到过这个需求:插件装好了,命令面板里能搜到,但左侧活动栏(Activity Bar)里空空如也,用户根本不知道你的功能藏在哪。这就是「左侧抽屉面板」要解决的问题——它指的是 Activity Bar 上的图标入口,以及点开后 Side Bar 里展开的视图容器(View Container)和具体视图(View)。
VS Code 插件开发里,左侧抽屉面板本质上由package.json里的contributes.viewsContainers和contributes.views两个字段驱动。前者负责在活动栏放一个带图标的容器,后者负责往容器里塞具体的抽屉子项。图标设置则分两层:一层是活动栏上那个小图标,另一层是插件市场里展示的插件图标,两者路径写法不同,很多人第一次做会混淆。
这篇面向需要为插件添加自定义视图容器的开发者,交付一份可直接复制的package.json视图容器与图标字段骨架,同时把 TaoToken 统一 Key/API 通道的settings.json配置片段一并给出。TaoToken 在这里的作用是:当你的插件需要调用大模型能力(比如做一个代码解释抽屉),不用在插件里硬编码各家 Key,而是通过统一通道走,插件配置更干净。适合已经能跑通 Hello World 插件、想进一步做侧边栏交互的开发者跟做。
2. TaoToken 前置:统一 Key 与 API 通道准备
在动手改package.json之前,先把模型调用通道准备好。插件里如果要做「选中代码 → 抽屉面板里显示解释」这类功能,必然要发请求。我试过把 Key 直接写进插件源码,结果一提交就泄露,后来改成走统一通道,插件只认一个地址和一个 Key。
你需要先拿到一个可用的 Key。打开官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 注册后,进入控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 创建 API Key。创建时建议按插件名命名,比如vscode-drawer-demo,方便后续排查是哪个插件在调用。
拿到 Key 后,API 通道地址是 https://taotoken.net/api(这个地址不加 UTM 参数,直接用于代码里的 baseURL)。如果你用的是 Anthropic 风格的接口,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 里有说明;Claude Code 相关的配置参考 https://taotoken.net/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=ClaudeCodeAnthropic&utm_campaign=rewrite。
注意:Key 不要写进
package.json,也不要提交到 Git。插件运行时从 VS Code 的配置里读,配置存在用户本地的settings.json中。
这一步的核心产出是一个 Key 和一个 baseURL。后面第 3 节的settings.json片段会用到它们。如果你暂时只想验证抽屉面板和图标,不接模型,也可以先跳过 Key,等面板跑通再回来补。
3. 可复制配置:package.json 视图容器与图标骨架
现在进入正题。假设你的插件工程叫demo06-iconSet,目录结构里有一个resources文件夹放图标。先看package.json里需要加的完整字段。
3.1 viewsContainers 定义活动栏容器
viewsContainers分activitybar和panel两类,左侧抽屉面板用的是activitybar。每个容器需要id、title、icon三个属性,icon是相对package.json的本地路径。
{ "contributes": { "viewsContainers": { "activitybar": [ { "id": "demo06-drawer", "title": "果盘抽屉", "icon": "resources/fruit.svg" } ] } } }这里id是容器的唯一标识,后面views里要引用它。title是鼠标悬停时显示的提示文字。icon建议用 24x24 的 SVG,VS Code 会自动适配深浅主题;如果用 PNG,浅色主题下可能看不清。
3.2 views 描述抽屉子项
容器有了,里面还得有抽屉。views字段按容器 id 分组,每个视图有id和name:
{ "contributes": { "views": { "demo06-drawer": [ { "id": "demo06.orange", "name": "橙子区" }, { "id": "demo06.apple", "name": "苹果区" } ] } } }demo06-drawer就是上面容器的 id,两个视图会以可折叠分组的形式出现在侧边栏。name是显示给用户看的标题。
3.3 viewsWelcome 自定义欢迎内容
抽屉展开后如果没内容会显示默认的「暂无视图」,可以用viewsWelcome自定义。它支持字符串、换行、执行命令、打开网页链接:
{ "contributes": { "viewsWelcome": [ { "view": "demo06.orange", "contents": "欢迎来到橙子区。\n[执行 Hello World](command:demo06.helloWorld)\n[打开官网](https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=)\n[查看接入文档](https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite)" } ] } }view绑定上面views里的 id,contents里\n换行,command:触发命令,直接写 URL 会打开浏览器。这样用户点开抽屉就有引导,不会一脸茫然。
3.4 插件市场图标设置
活动栏图标和插件市场图标是两回事。市场图标用顶层icon字段,路径同样相对package.json:
{ "icon": "resources/marketplace-icon.png" }市场图标建议 128x128 的 PNG,带透明背景。注意这个icon字段和viewsContainers里的icon不在同一层级,别写混了。
3.5 settings.json 配置 TaoToken 通道
插件运行时读取用户配置。在 VS Code 的settings.json里加:
{ "demo06.apiBase": "https://taotoken.net/api", "demo06.apiKey": "你的_TaoToken_Key", "demo06.model": "claude-sonnet-4-20250514" }然后在插件代码里用vscode.workspace.getConfiguration('demo06')读取。这样 Key 不进源码,换 Key 也不用重新打包插件。模型名可以按需替换,具体可用模型在模型对话页 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 里能看到。
4. 验证请求:抽屉面板与图标生效步骤
配置写完了,怎么确认真的生效?按下面步骤走。
第一步,按F5启动扩展开发宿主窗口。VS Code 会新开一个窗口,标题栏带[扩展开发宿主]。
第二步,看左侧活动栏。如果配置正确,活动栏底部附近会出现你设置的图标(本例是果盘图标)。如果没出现,先检查viewsContainers的icon路径是否存在,路径错了 VS Code 会静默忽略整个容器。
第三步,点击图标。侧边栏会展开,显示「橙子区」和「苹果区」两个可折叠分组。点开「橙子区」,应该看到viewsWelcome里的欢迎文字和三个链接。
第四步,点「执行 Hello World」链接。如果命令已注册,会触发对应逻辑;没注册则报「command not found」。命令注册在extension.ts里:
import * as vscode from 'vscode'; export function activate(context: vscode.ExtensionContext) { const hello = vscode.commands.registerCommand('demo06.helloWorld', () => { vscode.window.showInformationMessage('Hello from 果盘抽屉'); }); context.subscriptions.push(hello); }第五步,验证模型通道。在命令里发一个请求,确认 Key 和 baseURL 生效:
const config = vscode.workspace.getConfiguration('demo06'); const base = config.get<string>('apiBase'); const key = config.get<string>('apiKey'); const res = await fetch(`${base}/v1/messages`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': key as string, 'anthropic-version': '2023-06-01' }, body: JSON.stringify({ model: config.get<string>('model'), max_tokens: 256, messages: [{ role: 'user', content: '用一句话说明抽屉面板是什么' }] }) }); const data = await res.json(); vscode.window.showInformationMessage(JSON.stringify(data).slice(0, 120));跑通后你会看到信息提示里返回了模型内容。这一步成功,说明抽屉面板、图标、统一 Key 通道三者都通了。
5. 本篇常见错排查
做这个功能时踩过的坑集中在几个地方,列出来对照。
图标不显示:最常见是路径问题。icon路径相对package.json,不是相对src。如果图标放在resources/fruit.svg,而package.json在根目录,写resources/fruit.svg正确;写成./resources/fruit.svg一般也行,但写成src/resources/fruit.svg就错了。另外 SVG 里如果有外部引用或脚本,VS Code 会拒绝渲染。
容器出现但视图为空:检查views里的 key 是否和viewsContainers的id完全一致,大小写敏感。demo06-drawer和demo06-Drawer是两个不同的 id。
viewsWelcome 链接不生效:command:后面的命令必须在contributes.commands里声明过,否则链接是灰的。URL 链接必须以https://开头,写相对路径不会打开。
改了 package.json 没反应:扩展开发宿主窗口不会热重载package.json的 contributes 字段。改完要关掉宿主窗口重新按F5。只改 TypeScript 代码的话,重新加载窗口(Ctrl+R)即可。
请求返回 401:Key 没读到或写错。先在设置里搜demo06.apiKey确认值存在,再检查请求头字段名。Anthropic 风格用x-api-key,OpenAI 风格用Authorization: Bearer,别混用。接入文档里有两种风格的对照。
模型名报错:model字段填了不存在的模型。去模型对话页确认当前可用模型名,复制准确的字符串。
6. 后续接入与长期编码建议
抽屉面板跑通后,下一步通常是让它真正干活:选中代码 → 抽屉里显示解释、生成测试、做重构建议。这时候 Key 管理会变复杂,如果你同时维护多个插件,建议统一走 TaoToken 的 Coding Plan,把额度集中管理,避免每个插件单独配 Key。长期做编码类插件的,可以看 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 了解套餐细节。
日常调试时,我习惯把demo06.apiBase和demo06.model做成工作区级配置,demo06.apiKey放用户级配置,这样团队共享.vscode/settings.json时不会泄露 Key。另外插件发布前记得把viewsWelcome里的测试链接换成正式文档地址,市场审核对死链比较敏感。
如果你还没创建 Key,回到 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 建一个,然后按第 3.5 节填进settings.json。整个流程从配置到验证,顺利的话半小时内能跑通。