VSCode Agent Sessions 运行命令生成指南:基于 tasks.json 的inAgents任务与自动执行的完整实践
【免费下载链接】vscodeVisual Studio Code项目地址: https://gitcode.com/GitHub_Trending/vscode6/vscode
Agent Session(智能会话/代理会话)工作区顶部标题栏的Run 按钮,可以让用户一键执行项目的安装、开发等常用命令。这些出现在 Run 按钮中的运行命令并非特设功能,而是以 VSCode 标准任务(tasks.json)为基础、通过inAgents标记接入的一套机制。本指南以官方内置技能 generate-run-commands/SKILL.md 为主线,讲解运行命令的任务模式(schema)、生成与修改的决策逻辑、文件写入与合并规则,并结合仓库源码揭示inAgents、runOptions.runOn = "worktreeCreated"从配置解析到自动调度的完整链路。读完你将能够为任意 Agent Session 工作区正确编写、推断、合并与调试运行命令。
Skill 的定位:内置技能如何参与运行命令
在仓库中,generate-run-commands属于 Agent 会话的内置技能(skills)之一,与commit、code-review、create-pr等并列存放于 src/vs/sessions/skills 目录。它的作用由文档头部的 YAML Front Matter 定义:
name: generate-run-commands description: Generate or modify run commands for the current session. Use when the user wants to set up or update run commands that appear in the session's Run button.即:当用户希望为当前会话设置或更新出现在标题栏 Run 按钮中的运行命令时,Agent 就会调用该技能。SKILL.md 本身属于"可定制"的内置技能——文档第一行注释明确说明,在产品内可以自定义并保存副本以覆盖其默认行为,删除该副本则恢复内置行为。因此,理解这份技能文档的本质,就是理解 VSCode 对"运行命令"这一概念的标准建模。
任务模式(Task Schema):运行命令到底是什么
SKILL.md 给出的第一个核心结论是:一个运行命令就是一个tasks.json中的任务(task),它依赖两个关键字段:
"inAgents": true—必填:使该任务出现在 Agent(会话)的 Run 按钮中;"runOptions": { "runOn": "worktreeCreated" }—可选:每当新建 worktree 时自动运行该任务(用于 setup/install 类命令)。
文档给出的最小可用示例为:
{ "tasks": [ { "label": "Install dependencies", "type": "shell", "command": "npm install", "inAgents": true, "runOptions": { "runOn": "worktreeCreated" } }, { "label": "Start dev server", "type": "shell", "command": "npm run dev", "inAgents": true } ] }示例展示了两类典型任务:一类是带runOn: worktreeCreated的环境准备命令(安装依赖),另一类是仅带inAgents: true的常驻/启动命令(启动开发服务器)。二者的差异正是"环境就绪"与"按需运行"两种语义的划分。
源码中的字段定义
在任务模型 tasks.ts 中,inAgents的注释直接印证了它的职责——"Show this task in the Agents run action dropdown"(将该任务显示在 Agents 的 run 操作下拉菜单中),它与hide(不显示在 run task 快速选择器中)是同一层级配置属性。
runOn则由内部枚举RunOnOptions支撑:
export enum RunOnOptions { default = 1, folderOpen = 2, worktreeCreated = 3 }IRunOptions实际包含四个属性,任务配置模块 taskConfiguration.ts 在解析时会为未显式给出的属性补齐默认值:
| runOptions 属性 | 默认值 | 说明(来自 taskConfiguration.ts) |
|---|---|---|
reevaluateOnRerun | true | 重新运行时是否重新评估任务 |
runOn | default | 触发的时机,见下方枚举 |
instanceLimit | 1 | 可并发运行的最大实例数(解析时取max(配置值, 1)) |
instancePolicy | prompt | 实例数达到上限时的策略(terminateNewest/terminateOldest/prompt/warn/silent) |
值得注意的是,SKILL.md 只用了runOn一个字段,但 JSON Schema 层面为runOn定义了三档取值(见 jsonSchema_v2.ts):default、folderOpen(文件夹打开时自动运行)、worktreeCreated(创建 Agent Session worktree 时自动运行)。而 taskConfiguration.ts 的 RunOnOptions.fromString 在解析时对值做toLowerCase()后匹配,因此folderOpen/worktreeCreated的大小写写法均会被正确识别。
校验与自动补全
inAgents与runOn均已纳入任务的 JSON Schema 校验(见 jsonSchema_v2.ts 对inAgents的描述),这意味着在编辑器内手写tasks.json时同样可以获得校验、悬浮提示与取值枚举补全,inAgents语法错误的概率很低,与技能生成的写法完全一致。
决策逻辑(Decision Logic):先查、后改、必要时再问
SKILL.md 为 Agent 规定的决策流程高度务实,核心是"能推断就不打扰用户":
- 先读取现有的
.vscode/tasks.json,检查是否已存在运行命令(即inAgents: true的任务)。 - 若已存在运行命令:将其视为修改请求(modify request)——询问用户具体想做什么:新增、删除还是更新某条命令。
- 若不存在运行命令:尝试根据工作区内容推断合理命令:
- 检查
package.json、Makefile、pyproject.toml、Cargo.toml、go.mod、.nvmrc等工程文件,以识别技术栈与常用命令; - 若 setup 命令明确(如
npm install、pip install -r requirements.txt),直接添加并配置"runOptions": { "runOn": "worktreeCreated" },无需询问; - 若主要 run/dev 命令明确(如
npm run dev、cargo run),直接添加,仅带"inAgents": true; - 仅当命令存在歧义时才询问用户,例如存在多个同等合理的选项、无法识别项目结构,或项目采用了非标准 setup。
- 检查
推断来源的工程信号
上述工程文件覆盖了前端(package.json+.nvmrc锁定 Node 版本)、Make 系项目、Python(pyproject.toml)、Rust(Cargo.toml)、Go(go.mod)等主流生态。这一"从项目清单文件反推启动命令"的思路与仓库中SessionsTasksService面向多目标读取任务的设计相呼应——任务既可以从工作区根目录的.vscode/tasks.json读取,也可以来自用户级 tasks 配置,从而保证不同会话形态都能获得一致的可运行命令集合。
读取与修改背后的服务能力
技能文档描述的是 Agent 的行为准则,而其底层能力由 sessionsTasksService.ts 提供,文档中的每一步都能在接口上找到对应实现:
- **"先读现有运行命令"**对应
getSessionTasksOnce()——该方法"一次性返回会话任务(inAgents: true)快照",实现即按t => !!t.inAgents过滤(sessionsTasksService.ts); - **"新增命令"**对应
createAndAddTask()——创建一个inAgents: true的 shell 任务并写入合适的tasks.json(工作区或用户级); - **"修改既有任务/打标"**对应
addTaskToSessions()与updateTask()——其中addTaskToSessions会按 label 定位既有任务,通过 JSON 编辑在路径['tasks', index, 'inAgents']上写入true,实现"原地把普通任务变成运行命令"; - **"删除命令"**对应
removeTask()——按任务 label 从目标tasks.json中移除; - 会话中"不运行命令"的普通任务也并未被忽略——
getNonSessionTasks()专门返回不带inAgents: true的任务,作为"Add Run Action"(添加运行操作)选择器中的候选建议(sessionsTasksService.ts)。
也就是说,"运行命令"并非一套独立的文件格式,而是对既有 VSCode Task 体系的一层视图过滤:inAgents决定它是否进入 Run 按钮的可见集合,其余任务定义能力(dependsOn依赖、shell 类型等)原样保留。例如getAllTasks()会返回全部任务(含无inAgents的),以便 agent-host 运行时通过dependsOn解析被运行命令依赖的普通任务。
文件写入与合并规则
SKILL.md 对落盘行为有两个硬性要求:
- 始终写入工作区根目录的
.vscode/tasks.json; - 若文件已存在则合并,绝不覆盖无关任务(merge,do not overwrite unrelated tasks)。
写入完成后,Agent 应简要向用户确认新增了哪些命令,以及如何从 Run 按钮触发它们。
合并示例
若工作区已存在一组用于调试的任务,那么新增运行命令的正确结果应如下所示——保留原有任务,仅追加两个inAgents条目:
{ "version": "2.0.0", "tasks": [ { "label": "Debug tests", "type": "shell", "command": "npm run test -- --debug", "problemMatcher": [] }, { "label": "Install dependencies", "type": "shell", "command": "npm install", "inAgents": true, "runOptions": { "runOn": "worktreeCreated" } }, { "label": "Start dev server", "type": "shell", "command": "npm run dev", "inAgents": true } ] }为什么强调"不覆盖"?
从实现侧看,tasks.json承载的是整个工作区的任务声明,其中既包含作为运行命令的inAgents任务,也包含大量仅供 Run Task 面板、调试配置或其他工具消费的普通任务。若采用"整文件覆写"策略,会破坏problemMatcher、自定义options.cwd、dependsOn链等既有配置。因此 Agent 端正确的合并策略,与 sessionsTasksService.ts 中"按 label 定位任务、以属性级 JSON 补丁写入inAgents: true、或仅追加新任务条目"的编辑粒度保持一致。
运行命令如何被触发:Run 按钮与 worktree 自动执行
Run 按钮与下拉菜单
inAgents: true的任务会出现在会话标题栏 Run 按钮的下拉菜单中,点击即运行。这与任务的读取链路(getSessionTasks/getSessionTasksOnce的!!t.inAgents过滤)一致:只有当inAgents为真时任务才会被纳入该视图。
worktreeCreated 的自动调度原理
runOn: worktreeCreated的真正含义值得深挖:它指在Agent Session 创建了实际 git worktree 时自动执行该任务。仓库中的 worktreeCreatedTaskDispatcher.ts 以 workbench 贡献点(workbench.contrib.sessions.worktreeCreatedTaskDispatcher)实现了这一逻辑,其行为要点:
- 每个新会话只触发一次:当某会话首次报告真实的 git worktree(监视条件为
session.workspace中存在带workTreeUri的文件夹)时,调度器拉取该会话全部任务,逐个执行runOptions.runOn === 'worktreeCreated'的条目; - 避免重复执行:若会话的运行时本身已在服务端执行过这些任务(通过
ISessionCapabilities.runsWorktreeCreatedTasks信号标识),调度器会直接跳过,防止双重执行; - 随会话生命周期清理:被调度任务返回的 stop handles 按会话跟踪,当会话被归档(archived)或移除时统一 dispose,避免 setup/构建这类长生命周期进程泄漏;
- 可开关:Agent host 会话是否自动执行
worktreeCreated任务受设置chat.agentHost.runWorktreeCreatedTasks控制(默认true),关闭后仅影响自动调度,手动通过 Run Task 面板运行不受影响。
这意味着,一个"Install dependencies"配置了runOn: worktreeCreated后,Agent 每创建一个新 worktree 就能自动获得已就绪的依赖环境——这正是 SKILL.md 将 setup 类命令与worktreeCreated绑定的原因:用一条配置换取每个新工作区的零手工准备。
实战注意事项
基于上述机制,在实际使用或让 Agent 生成运行命令时,值得关注以下几点:
- 区分两类语义:依赖安装、构建产物准备这类"环境就绪"命令应加
runOptions: { runOn: "worktreeCreated" };而 dev server、测试等需用户按需触发的命令,只加inAgents: true,避免在每次建 worktree 时被自动拉起。 - 让 Agent 先探查再写入:技能要求 Agent 先读现有
.vscode/tasks.json,因此当工作区已有运行命令时,向 Agent 明确提出"新增/删除/更新哪条命令"比笼统地"帮我配一下"更高效。 - 合并优于覆写:无论是人工编辑还是让 Agent 修改,都应保留文件中的既有任务;不确定时可先查看该文件确认任务 label,避免与已有条目冲突。
- 利用普通任务的迁移:若工作区已有期望出现在 Run 按钮里的任务,可通过会话的"Add Run Action"将非
inAgents任务打上标记,而无须复制一份命令。 - 验证与回退:所有任务字段均在 jsonSchema_v2.ts 定义的 Schema 校验之下,若希望从 Agent 生成的运行命令恢复到内置默认行为,删除技能的自定义副本即可。
深入阅读
- 技能本体:src/vs/sessions/skills/generate-run-commands/SKILL.md,以及 src/vs/sessions/skills 下的全部内置技能;
- 任务数据模型与
inAgents/RunOnOptions定义:src/vs/workbench/contrib/tasks/common/tasks.ts; - 任务 JSON Schema(含
inAgents与runOn枚举):src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts; runOn/runOptions解析与默认值:任务配置解析 src/vs/workbench/contrib/tasks/common/taskConfiguration.ts;- 会话任务服务(读取、打标、新建、删除运行命令):src/vs/sessions/contrib/chat/browser/sessionsTasksService.ts;
- worktreeCreated 自动执行调度器:src/vs/sessions/contrib/chat/browser/worktreeCreatedTaskDispatcher.ts。
综上,VSCode Agent Session 的运行命令机制可以总结为一句话:标准tasks.json任务 +inAgents可见性标记 + 可选的runOn: worktreeCreated自动触发。掌握这套模式后,无论是人工编辑还是借助generate-run-commands技能,都能为会话工作区快速搭建出"创建即就绪、按钮即启动"的完整运行体验。
【免费下载链接】vscodeVisual Studio Code项目地址: https://gitcode.com/GitHub_Trending/vscode6/vscode
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考