首页
/ Cline VS Code 扩展 Workflow 回归修复全解:斜杠命令扩展、开关同步与向 Skills 的迁移

Cline VS Code 扩展 Workflow 回归修复全解:斜杠命令扩展、开关同步与向 Skills 的迁移

2026-09-04 12:26:20作者:彭桢灵Jeremy

本文基于 Cline 仓库中的一份 Changeset 变更记录(gold-otters-march.md),完整解读这次针对 VS Code 扩展 "claude-dev" 包的 patch 级修复:恢复 Workflow 支持中的四处回归——带文件扩展名的 /workflow.md 斜杠命令、消息中段命令、启用/禁用开关的生效逻辑,以及 webview 启动时的斜杠菜单刷新,同时说明 Workflows 管理标签页回归规则模态框并指向 Skills 的迁移方向。读完后,你将理解 Cline 中 Workflow 从「Markdown 文件」到「斜杠命令」再到「提示词展开」的完整链路,以及每一处修复在源码中的具体落点与测试依据。

1. 变更记录说了什么:一次针对 Workflow 的回归修复

本次变更以 Changeset 文件 .changeset/gold-otters-march.md 形式提交,frontmatter 声明变更级别为 "claude-dev": patch,即针对 Cline VS Code 扩展(沿用旧包名 claude-dev)的补丁级修复。正文一次性列出了五个修复点:

  1. 支持展开 /workflow.md 这种斜杠命令——这是自动补全实际插入的「遗留文件名拼写」(legacy filename spelling);
  2. 支持展开消息中段出现的斜杠命令,而非仅消息开头的命令;
  3. 展开过程中尊重 Workflow 的启用/禁用开关(enable/disable toggles);
  4. 在 webview 启动时刷新斜杠命令菜单中的 Workflow 列表;
  5. 恢复规则模态框(rules modal)中的 Workflows 管理标签页——现位于标签列表末尾,并带有指向 Skills 的弃用提示。

理解这些修复点,需要先理解 Cline 中 Workflow 的定位:Workflow 是存放在工作区或全局目录下的 Markdown 文件(支持 .md.markdown.txt 扩展名),用户可以在聊天输入框中以 /文件名 的斜杠命令形式引用它,提交后该命令会被展开为 Workflow 文件正文中的指令内容注入提示词。源码中 slash-command-expansion.ts 的注释明确列出了这三类扩展名与「规范化名称」的对应关系——SDK 侧命令名不含扩展名,而 webview 自动补全和遗留开关状态仍保留扩展名,正是这种命名差异催生了本次修复的第一、二点。

2. 修复一:让 /workflow.md 这种带扩展名的遗留拼写也能展开

2.1 回归的根源:命名不一致

SDK 侧的 @cline/core 在发现 Workflow 时,会以 frontmatter 的 name 字段或去掉扩展名的文件 basename 作为命令名;而 webview 的自动补全菜单(以及旧版 Cline)向用户展示的却是 /my-workflow.md 这样的完整文件名。用户从菜单中选中命令后,输入框里实际插入的就是带 .md 后缀的 token——如果展开逻辑只做精确匹配,这些命令就静默失效了。

2.2 源码中的多级回退匹配

展开逻辑的核心是 findRuntimeCommand,它对输入的命令名做了四级回退:

  1. 精确匹配:先用原始 token(如 release.md),再尝试去掉扩展名后的形式(release),逐个与运行时命令表做精确比对;
  2. 大小写不敏感匹配:webview 对斜杠命令的高亮与校验是大小写不敏感的,因此这里回退到 toLowerCase() 比对,避免「静默不展开」;
  3. 通过文件 basename 解析 frontmatter 重命名:这是关键一步——当 Workflow 文件的 frontmatter name 与文件名不一致时(例如文件叫 release.mdname: Ship It),代码会用规范化名称(去扩展名、小写,见 canonicalWorkflowName)把用户输入的文件名与发现记录(workflowRecords)的 basename 对齐,找到对应记录后优先用稳定的 record.id 匹配命令(SDK 会把 "Ship It" 规范化为 "ship-it",直接比较配置名会失败),最后再回退到规范化名称比较;
  4. 都未命中则返回 undefined,命令保持原样不展开。

2.3 测试用例的印证

slash-command-expansion.test.ts 中有针对该场景的直接断言:

  • 基础场景:expandSlashCommands("/release.md now", commands) 的结果是 "Run the release workflow. now"——带扩展名的遗留拼写被成功展开为指令正文;
  • 重命名场景:当命令名已被规范化(renamed)时,仅凭命令表匹配不到 /release.md;传入 workflowRecords[{ name: "ship-it", filePath: "/repo/.clinerules/workflows/release.md" }])后即可解析展开;
  • 反向验证:当该 Workflow 出现在禁用集合中时,同一输入保持 /release.md 原文不展开——这正是第三点修复的联动效果。

3. 修复二:消息中段的斜杠命令同样被展开

3.1 匹配规则:任意空白边界后的命令 token

SDK 自身的 resolveRuntimeSlashCommand 只处理消息开头/command,但 webview 允许用户在消息中段插入斜杠命令(输入框高亮与补全即如此工作),旧版扩展也支持中段展开。本次回归修复将该能力恢复,实现方式是 SLASH_COMMAND_TOKEN_REGEX

const SLASH_COMMAND_TOKEN_REGEX = /(^|\s)(\/[a-zA-Z0-9_.:@-]+)(?=\s|$)/g

该正则要求命令 token 要么位于消息开头,要么前置空白,且后接空白或行尾。注释特意说明它与 webview 侧 slash-commands.ts 中的 slashCommandRegex 保持同步——即「凡是被聊天输入框高亮/自动补全为命令的 token,都能被展开」。

3.2 展开语义:只展开第一个命中命令

expandSlashCommands 遍历所有匹配,但对第一个能解析为已知 Workflow/Skill 的命令执行展开(用 command.instructions 替换 token 原文,text.slice(0, start) + command.instructions + text.slice(end)),随后立即返回。这与旧版行为及 webview 菜单一致——菜单也只对消息中的第一个命令提供建议。测试用例 expect(expandSlashCommands("please run /release.md for v2", commands)).toBe("please run Run the release workflow. for v2") 验证了中段展开的前后文均被原样保留。

另外值得注意的边界:非内置的 skill 类型命令在此处展开——SDK 会话注册了 skills 工具,其描述要求模型在用户引用斜杠命令时主动调用,指令以工具结果形式到达,转写中保留用户输入的原始命令;而 builtin: 前缀的内置技能(如 /deep-planning)与 Workflow 一样继续走内联展开(见 expandSlashCommands 内注释)。

4. 修复三:展开时尊重启用/禁用开关(含远程锁定的处理)

4.1 开关的三个作用域

Cline 的 Workflow 开关分布在三个作用域中(getAvailableSlashCommands 中可见完整的读取链路):

作用域 状态键 键的含义
工作区(local/workspace) workflowToggles 绝对文件路径
全局(global settings) globalWorkflowToggles 绝对文件路径
远程/企业(remote,全局状态) remoteWorkflowToggles 远程 Workflow 名称

4.2 buildDisabledWorkflowNames 的判定规则

buildDisabledWorkflowNames 负责把三套开关聚合为「禁用命令名集合」,并在 expandSlashCommands 中被消费:命中的 Workflow 被跳过、保持原样不展开。其判定规则有几处细节值得注意:

  • 按记录(record)逐条评估:每个命令由「其自身记录」——即真正会被展开的那个文件——的开关状态管辖,一个作用域中被禁用的 Workflow 既不能压制、也不能解锁另一个作用域中同名的命令;
  • 按 basename 对齐开关:开关以文件路径为键,但命令名可能因 frontmatter 而异,因此用文件 basename 的规范化形式做匹配,保证「文件名 ≠ 命令名」的 Workflow 仍受其文件开关管辖;
  • 多作用域同名取「任一启用即启用」enabledByBasename.set(key, (enabledByBasename.get(key) ?? false) || enabled)——因为多作用域的同名文件会坍缩为同一条记录,旧版展开逻辑只在「已启用」集合中查找,工作区被禁用的文件不应遮蔽全局同名的已启用文件(反之亦然);
  • 远程文件单独处理:路径命中 .cline/remote-config/… 的物化文件由按名称键控的远程开关管辖,且 alwaysEnabled(组织锁定开启)的远程 Workflow 恒为启用。远程名称比对前还要经过 sanitizeRemoteSegment——与 @cline/shared 物化器中命名文件的私有函数逐字对齐(小写、非法字符折叠为 -、截断 80 字符),因为它对已规范化名称是幂等的,可以安全地用于两侧比对。

测试文件 slash-command-expansion.test.ts 中覆盖了对应矩阵:本地/全局开关交叉(全局启用 + 工作区禁用 → 仍启用)、远程文件 + alwaysEnabled、仅存在于全局目录的开关不误伤其他记录等场景。

5. 修复四:webview 启动时刷新斜杠菜单的 Workflow 列表

5.1 启动即同步:refreshWorkflowToggles

变更点位于 webview 初始化阶段。initializeWebview.ts 在 webview 启动时调用 refreshWorkflowToggles,其目的是「让聊天输入的斜杠命令菜单无需用户手动打开规则面板即可感知 Workflow 文件」。这直接解决了回归症状之一:用户新建/删除 Workflow 文件后,斜杠菜单列表陈旧。

5.2 并发安全:串行化队列 + 扫描后合并

Workflow 开关刷新并非简单的「扫描目录 → 写状态」,workflows.ts 处理了两类并发竞态:

  1. 刷新串行化:模块级 refreshQueue 把重叠的刷新(webview 启动、规则面板打开、通过面板创建 Workflow 文件)排成队列,使每次扫描相对其他刷新是原子的;扫描期间发生的文件创建/删除会触发各自独立的、排在队尾的刷新来纠正结果;
  2. 扫描中状态变更的合并mergeToggleStateAfterScan 把异步扫描结果与「扫描前快照」「当前状态」三方合并,保证:扫描中用户手动翻动的开关值获胜;扫描中新增的条目(如面板里刚创建的 Workflow)被保留;扫描中已被删除的条目保持删除;仅当文件确实从磁盘消失时才裁剪对应条目。

刷新会分别处理全局(~/.cline/workflows 等全局目录)与工作区 .clinerules/workflows 两个目录,分别写回 globalWorkflowTogglesworkflowToggles,最终通过 RefreshedRules 响应同步到 webview 状态(ClineRulesToggleModal 在面板可见时也会主动调用 FileServiceClient.refreshRules 拉取最新开关)。

5.3 菜单组装规则:本地优先、仅列启用项

斜杠菜单的数据来自 getAvailableSlashCommands,其组装顺序体现了优先级:内置命令(section: "default")→ 工作区启用的 Workflow → 全局启用的 Workflow(同名时让位于工作区,由 localNames 去重)→ 远程启用的 Workflow(alwaysEnabled || toggles[name] !== false)。所有自定义 Workflow 的 description 形如 Custom workflow: <文件名>,且 cliCompatible: true。注意菜单名保留 .md 等扩展名——这正是第二、三节中「遗留拼写」的由来,菜单与展开逻辑必须成对兼容。

6. 修复五:Workflows 管理标签页回归规则模态框,并指向 Skills

6.1 标签页布局与弃用提示

规则模态框 ClineRulesToggleModal.tsx 通过 currentView 状态在 "rules" | "workflows" | "hooks" | "skills" 四个视图间切换(第 64 行)。本次修复恢复了 Workflows 标签页,且按变更记录所述将其置于标签列表末尾,并在该视图中放置弃用提示。源码中可确认该提示文案:

"Workflows are being deprecated. Use skills instead."(第 608 行附近

6.2 Workflows → Skills 的迁移含义

从同一组件的 Skills 视图描述(第 492 行附近)可以看到官方对两者定位的界定:「Skills are reusable instruction sets that Cline can activate on-demand. When a task matches a ...」——Skills 是 Cline 可按需激活的可复用指令集,且支持全局/工作区/企业(远程)三级来源。与 Workflow 的差异在展开机制上已有体现:skill 类型命令默认不做内联展开,而是由 SDK 会话注册的 skills 工具在模型判定任务匹配时拉取(见 expandSlashCommands 注释)。因此对于新建的可复用指令,推荐路径是 Skills;Workflows 的斜杠展开能力被完整保留以兼容存量用户——本次修复正是「兼容层」质量的回归保障。

7. 端到端链路小结

把五个修复点串起来,Cline VS Code 扩展中 Workflow 的完整生命周期如下:

  1. 发现与同步:webview 启动 → refreshWorkflowToggles(串行队列 + 三态合并)→ globalWorkflowToggles / workflowToggles 与磁盘文件对齐;
  2. 菜单呈现getAvailableSlashCommands 按「本地优先、仅启用项」组装 /xxx.md 形式的候选命令;
  3. 用户提交:输入框中的 token(可能是菜单插入的 /release.md,也可能手工敲在消息中段)经 SLASH_COMMAND_TOKEN_REGEX 捕获;
  4. 开关裁决buildDisabledWorkflowNames 聚合工作区/全局/远程三套开关(含 alwaysEnabled),禁用集合中的命令直接跳过;
  5. 指令展开findRuntimeCommand 四级回退(精确 → 去扩展名 → 大小写不敏感 → basename 解析重命名)命中后,将第一个命令 token 原位替换为 command.instructions
  6. 管理界面:规则模态框中位于末尾的 Workflows 标签页(带弃用提示)继续提供开关与文件管理能力,新指令建议改用 Skills。

本次变更的所有关键行为都有对应测试锚定在 apps/vscode/src/sdk/slash-command-expansion.test.ts 中,涉及遗留拼写、中段命令、重命名解析与开关裁决的各分支;开关刷新的竞态处理则定义在 workflows.ts。对维护者而言,改动这一链路时需要同时留意三处同步约束:webview 高亮正则与展开正则保持一致、findRuntimeCommand 的扩展名正则与 @cline/core 的发现逻辑保持一致、sanitizeRemoteSegment@cline/shared 物化器保持逐字一致——源码注释中均已显式标注这些「Keep in sync」要求。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
902
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341