Skip to content

feat(general-skills): 通用技能对齐 Agent Skills 官方规范(frontmatter 校验/标准导出/allowed-tools 门控) - #54

Open
tianling536 wants to merge 3 commits into
OpenBMB:mainfrom
tianling536:feat/general-skills-standard
Open

feat(general-skills): 通用技能对齐 Agent Skills 官方规范(frontmatter 校验/标准导出/allowed-tools 门控)#54
tianling536 wants to merge 3 commits into
OpenBMB:mainfrom
tianling536:feat/general-skills-standard

Conversation

@tianling536

@tianling536 tianling536 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

概述

让通用技能(General Skill)的创建/保存/导出全面对齐 Agent Skills 官方规范。此前页面新建技能只是一份裸 Markdown(无 YAML frontmatter、无规范校验、无标准导出),产物在标准工具链里不可用。

规范层(新模块 app/general_skills/standard.py)

  • 字段校验:name(1-64,小写字母/数字/连字符,不可首尾/连续连字符)、description(1-1024,做什么+何时用);
  • frontmatter 解析与 SKILL.md 组装:可选字段 license / compatibility(≤500) / metadata(键值对) / allowed-tools(空格分隔)全支持;
  • name 恒等于 slug(规范硬性要求:name 与父目录名一致);
  • 存量无 frontmatter 的技能,读路径(DTO/导出/运行时物化)同样输出规范形态,无需数据迁移。

保存与发布

  • /import_create_imported_general_skill(zip/GitHub/clawhub)统一归一化:frontmatter 以表单/解析字段重组(name=slug、可选字段透传、正文保留);
  • 校验:新建 slug 不合规 400;导入的第三方不合规名自动 _slugify 清洗;published 缺 description 400(草稿宽限,发布时强制);
  • publish 端点发布前强制规范校验;
  • 新增 GET /{slug}/export:导出标准 zip(根目录=slug,SKILL.md 为规范化版本)——与既有 zip 导入形成往返。

运行时

  • 物化到工作区的 SKILL.md 一律为规范化版本;
  • allowed-tools 门控:声明了 allowed-tools 且不含 Bash 时,runner 计划输入仅给 python、计划后再强制校验(生成 bash 即拒绝触发反思重生成);声明 Bash(...) 或未声明则不限制。

前端

  • 新建模板换成标准 SKILL.md skeleton(含 frontmatter,并注明由表单生成);
  • 基本信息新增 license / compatibility / allowed-tools 三个规范字段(与 frontmatter 同步);
  • 文件编辑器支持任意路径(scripts/run.pyreferences/guide.mdassets/),mime 按扩展名推断;
  • 编辑器新增导出技能包按钮(zip 下载)。

验证

  • 新增测试:规范层 10 例(name/description 规则、解析组装往返、转义、标准化输出、文件清单、allowed-tools 解析)+ API 层 5 例(保存归一化与可选字段透传、非法 slug/无描述发布 400、草稿宽限、导出 zip 结构断言)+ 运行时 2 例(物化标准化、门控语言列表);
  • 存量测试按归一化后的新行为对齐(frontmatter 形态、夹具补 description);
  • 全量 1243 passed、ruff 零告警、前端 build 通过、新增文案已入 en.json(本页 i18n 无缺失;i18n:check 报告的 67 条均为 main 预存在,与纯净 main 一致)。

兼容性

  • 无 schema 变更;存量技能不迁移,保存/导出/运行时自动规范化;
  • 第三方导入(clawhub/GitHub/zip)行为收紧:无 description 的包会被拒绝并给出明确错误(规范必填项)。

编辑器升级(e97b4be 追加)

  • 文件面板改目录树:导入/创建多文件技能包后,按路径组织成文件夹层级(scripts/、references/、assets/ 等),文件夹可折叠,文件按层级缩进显示 basename,悬停显示完整路径;右键菜单(重命名/删除)保持不变;
  • 新建文件改下拉菜单:预置 scripts/run.pyreferences/guide.mdassets/data.json 三个规范目录模板(重名自动追加序号),另有"自定义路径…"展开内联输入(回车创建、Esc 收起)——按规范目录结构建技能一步到位。

@tianling536 tianling536 changed the title feat(general-skills): 通用技能对齐 Agent Skills 官方规范(agentskills.io) feat(general-skills): 按 Agent Skills 标准升级通用技能(规范校验/标准导入导出/目录树编辑器) Jul 31, 2026
@hm1229
hm1229 self-requested a review August 1, 2026 09:25
@hm1229 hm1229 self-assigned this Aug 1, 2026
@hm1229

hm1229 commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

感谢您的补充,这里的部分功能我们在新版中已经进行了调整,部分功能为了新版的执行可能不完全兼容,等我们更新稳定后再进行merge

@hm1229

hm1229 commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

您好,我们目前已将新版能力进行了更新,方便的话修改后我们继续评审

@tianling536
tianling536 force-pushed the feat/general-skills-standard branch from e97b4be to 13efe05 Compare August 6, 2026 16:08
@tianling536

Copy link
Copy Markdown
Contributor Author

已按新版能力完成适配(rebase 到 main 6f72f96,commit 13efe05),当前 MERGEABLE。逐点说明:

  1. 与新版运行时的兼容:runner 的技能包物化保留上游 skill_directories 目录创建,SKILL.md 仍按本 PR 的规范化版本物化(frontmatter 齐全);allowed-tools 门控(未声明 Bash 则仅 python runtime)在新执行链路上完整保留并复核过调用点。
  2. 页面部分对齐上游:main 自带的文件树/新建文件夹/能力范围(capability_scope)全部保留;本 PR 的目录树+新建下拉因与上游实现重复已撤下,只保留独有增量——license/compatibility/allowed-tools 三个规范字段与「导出技能包」按钮。
  3. 校验规则与新测试夹具对齐:上游新增测试的导入夹具按规范补了 description(published 必填)。
  4. en.json 合入上游新文案,并补齐上游缺的几条翻译(渲染切换/发布到广场等)。

验证:全量 1313 passed、ruff 零告警、前端 build 通过、技能页 i18n 无缺失。

本 PR 当前的独有增量收敛为:规范层(frontmatter 校验/组装/解析)、保存与发布的规范校验、标准 zip 导出、runner 的 allowed-tools 门控与 SKILL.md 规范化物化、页面规范字段与导出按钮。

@tianling536 tianling536 changed the title feat(general-skills): 按 Agent Skills 标准升级通用技能(规范校验/标准导入导出/目录树编辑器) feat(general-skills): 通用技能对齐 Agent Skills 官方规范(frontmatter 校验/标准导出/allowed-tools 门控) Aug 6, 2026
@tianling536
tianling536 force-pushed the feat/general-skills-standard branch from 13efe05 to 14eb5c5 Compare August 7, 2026 14:39
田领 added 2 commits August 15, 2026 12:33
规范层(app/general_skills/standard.py):
- name/description 规范校验(1-64 小写连字符/1-1024)
- YAML frontmatter 解析与 SKILL.md 组装;可选字段
  license/compatibility/metadata/allowed-tools 全支持
- name 恒等于 slug(规范:与目录名一致);存量技能读路径同样输出规范形态

保存与发布:
- /import 与 _create_imported_general_skill(zip/GitHub/clawhub)统一归一化:
  frontmatter 以表单/解析字段重组、正文保留;新建 slug 不合规 400,
  导入名不合规自动 _slugify 清洗;published 缺 description 400,草稿宽限
- publish 端点发布前强制规范校验
- 新增 GET /{slug}/export 导出标准 zip(根目录=slug,SKILL.md 规范化)

运行时:
- 物化到工作区的 SKILL.md 一律规范化
- allowed-tools 门控:未声明 Bash 时 runtime 仅 python(计划输入约束+
  计划后强制),声明 Bash(...) 或缺省不限制

前端:
- 新建模板换标准 SKILL.md skeleton;基本信息新增 license/compatibility/
  allowed-tools 三字段(与 frontmatter 同步)
- 文件编辑器支持任意路径(scripts/references/assets)
- 编辑器新增"导出技能包"按钮

测试:规范层 10 例、保存归一化/非法 slug/发布校验/导出 zip 往返/
物化标准化/门控等;存量测试按归一化新行为对齐;全量 1243 passed、
ruff 零告警、前端 build 与 i18n 新增文案齐全
- 与 main 的文件树/新建文件夹/能力范围(capability_scope)合并:保留上游实现,
  叠加本 PR 的规范字段(license/compatibility/allowed-tools)与导出技能包
- runner 物化:保留上游 skill_directories 目录创建,SKILL.md 仍按规范化物化
- 上游新增测试夹具按规范补 description;en.json 合入上游新文案并补齐渲染切换等翻译
@tianling536
tianling536 force-pushed the feat/general-skills-standard branch from 14eb5c5 to dbcd9d6 Compare August 15, 2026 04:37
@hm1229

hm1229 commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

[P1] 并没有真正解析 YAML,重复保存会破坏内容
split_frontmatter() 只是按冒号和引号手工拆字符串,不支持正确的 YAML 转义。
我实际测试:
原始: MIT "Enterprise" \ license
保存读取后: MIT "Enterprise" \ license
再次保存: 转义继续增加
官方参考实现使用 StrictYAML 解析,并会拒绝非法或未闭合的 frontmatter:官方解析器
[P1] 私有技能可以绕过发布校验
整体技能发布会校验 name/description,但员工私有技能分支提前返回,publish-to-gallery 也完全没有校验。
我本地复现了:
draft without description → publish-to-gallery
结果: status=published, description=None
这直接破坏了 PR 声明的“发布前强制符合规范”。
[P2] 第三方技能的非法下划线不会被清理
代码声称会自动清洗非法 slug,但 _slugify() 自己保留 _。例如 bad_name 清洗后仍是 bad_name,最终导出的目录名和 frontmatter 依旧违反规范。
[P2] license 等可选字段无法从界面清空
前端清空后发送 undefined,后端使用:
new_value or existing_value
于是原值又会恢复。例如把 license=MIT 清空并保存,返回结果仍然是 MIT。
另外,compatibility 的 500 字符限制只定义了常量,没有实际校验;我本地确认 501 字符也能保存。

- split_frontmatter 改 PyYAML safe_load(strict 模式拒绝未闭合/非法/
  非映射 frontmatter),compose 改 safe_dump(自动转义,重复保存幂等——
  修复手工拆串导致的转义累积);pyproject 显式声明 PyYAML 依赖
- 发布校验 _validate_skill_publishable 收口并覆盖全部发布路径
  (/publish 的员工私有分支此前提前返回绕过、publish-to-gallery 完全无校验)
- _slugify 下划线转连字符+连续连字符收敛,产出恒为规范 name 形态
- compatibility 500 字符限长实际执行
- 可选字段(license/compatibility/allowed-tools)编辑时可清空:
  后端区分 None(未提交,保留)与空串(显式清空),前端提交空串
- 回归测试:特殊字符反复保存幂等/严格模式三拒绝/publish-to-gallery
  拦截/slugify 合规/限长 400/清空与保留语义
@tianling536

Copy link
Copy Markdown
Contributor Author

感谢复核,四条全部认可并已修复(commit 93772bc):

[P1] 手工拆串不是 YAML 解析,重复保存破坏内容
属实(复现了转义累积)。split_frontmatter 改为 PyYAML safe_load,compose_skill_markdown 改为 safe_dump(自动转义、保序、Unicode 原文);保存路径用 strict 模式——未闭合/非法 YAML/顶层非映射的 frontmatter 直接 400 拒绝(与官方 skills-ref 解析器同语义);读路径保持宽容回退。PyYAML 已显式声明进 pyproject 依赖。回归测试用您的复现值(MIT "Enterprise" \ license)验证反复保存幂等。

[P1] 私有技能绕过发布校验
属实。发布校验收口为 _validate_skill_publishable 并覆盖全部发布路径:/publish 的员工私有分支(此前提前返回绕过)与 publish-to-gallery(此前完全无校验)。回归测试:无描述草稿经 publish-to-gallery 返回 400。

[P2] 下划线不会被清理
属实。_slugify 现在下划线转连字符、连续连字符收敛、去首尾连字符,产出恒为规范 name 形态(bad_namebad-name);测试断言所有样例输出均通过 validate_skill_name

[P2] 可选字段无法从界面清空 + compatibility 限长未执行
都属实。清空:后端区分 None(未提交,保留原值,兼容旧客户端/第三方导入)与空串(编辑时显式清空),前端三个字段改为提交空串;限长:保存时 compatibility 超 500 字符返回 400。均有回归测试。

验证:全量 1458 passed、ruff 零告警、前端 build 通过。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants