skill

package
v0.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package skill 实现 Agent Skills 开放标准(https://agentskills.io)。

一个技能就是一份带 YAML frontmatter 的 markdown 文档(SKILL.md):frontmatter 声明 name / description 等元信息,正文是指令内容。技能只做「上下文注入」,不是 可执行工具——采用渐进式披露(progressive disclosure):

  • 仅把技能元信息(name / description)以 XML 注入系统提示词;
  • 正文(Instructions)不注入,模型判断需要时调用 get_skill 工具加载;
  • 技能目录下的参考文档 / 脚本 / 模板等附属资源通过 load_skill_resource 工具按需读取。

设计参考 crush/internal/skills 与 opencode/internal/skills。

Index

Constants

View Source
const (
	// BuiltinSkillDir 是内置技能源码目录(相对工作目录,与内置提示词一致)。
	BuiltinSkillDir = "builtin/skills"
	// BuiltinAnalysisScriptSkillName 是「创建分析脚本流程」内置技能名。
	BuiltinAnalysisScriptSkillName = "analysis-script-workflow"
	// BuiltinAnalysisNodeScriptSkillName 是「分析节点脚本修改」内置技能名。
	BuiltinAnalysisNodeScriptSkillName = "analysis-node-script-editing"
	// BuiltinAnalysisScriptSpecSkillName 是「分析脚本修改规范」内置技能名。
	BuiltinAnalysisScriptSpecSkillName = "analysis-script-spec"
)

内置技能:源码位于仓库 builtin/skills/<name>/SKILL.md(与内置提示词同处 builtin/ 目录), 由 go:embed 打包进二进制;系统启动时读出并覆盖写入用户技能目录 ($BaseDir/.skills/<name>/SKILL.md)。

为什么用「启动时覆盖写文件」而不是内存注入:技能的加载 / 热更新 / 前端查看 / 删除 都只走一条路径(磁盘 + Discover),内置技能因此不需要额外的合并逻辑;同时运维可以 直接打开对应文件查看模型实际拿到的内容。

注意:内置技能写入后与用户技能同处一个目录,前端删除后在下次启动时会再次出现。

View Source
const (
	// SkillFileName 是技能描述文件的文件名。
	SkillFileName = "SKILL.md"
	// MaxNameLength 是技能名允许的最大长度。
	MaxNameLength = 64
	// MaxDescriptionLength 是技能描述允许的最大长度。
	MaxDescriptionLength = 1024
)
View Source
const (
	// ManifestFileName 是技能目录下声明版本等元信息的可选清单文件。
	ManifestFileName = "manifest.json"
	// MaxResourceBytes 是 load_skill_resource 单次返回的资源大小上限。
	MaxResourceBytes = 256 * 1024
)

技能附属资源相关常量。

View Source
const (
	// GetSkillToolName 是「加载技能指令」工具名。
	GetSkillToolName = "get_skill"
	// LoadSkillResourceToolName 是「加载技能附属资源」工具名。
	LoadSkillResourceToolName = "load_skill_resource"
)

技能工具的入参 / 出参定义。

技能本身仍以 SKILL.md 为唯一真实来源,但正文不再由模型「读文件」获取,而是通过 工具调用按需加载(渐进式披露):

  • get_skill:按名称(可选版本)加载 SKILL.md 的指令正文与必要元信息;
  • load_skill_resource:加载技能目录内的附属资源(参考文档 / 脚本 / 模板 / Schema)。

两者都是只读工具,免授权(技能来自 $BaseDir/.skills,属于框架受控目录)。

Variables

This section is empty.

Functions

func BuiltinNames added in v0.2.0

func BuiltinNames() []string

BuiltinNames 返回全部内置技能名。

func DiscoverWithStates added in v0.1.5

func DiscoverWithStates(paths []string) ([]*Skill, []*SkillState)

DiscoverWithStates 发现给定路径下所有合法技能,并返回每个文件的发现状态。

func EnsureBuiltinSkills added in v0.2.0

func EnsureBuiltinSkills(dir string) error

EnsureBuiltinSkills 把内置技能写入 dir(通常为 $BaseDir/.skills),每次启动都覆盖。

写入内容来自 builtin/skills 下的 SKILL.md 原文(不再重新序列化),保证磁盘与源码一致。 dir 为空时无操作;写入失败只记录第一个错误,不影响其他技能继续写入。

func GetSkill added in v0.2.0

func GetSkill(resolver runtimecontext.SkillResolver) tool.Tool

GetSkill 返回「按名称加载技能指令」工具。

func IsBuiltin added in v0.2.0

func IsBuiltin(name string) bool

IsBuiltin 报告 name 是否为内置技能名。

func LoadSkillResource added in v0.2.0

func LoadSkillResource(resolver runtimecontext.SkillResolver) tool.Tool

LoadSkillResource 返回「加载技能附属资源」工具。

用于读取参考文档、脚本源码、模板、Schema 等附属文件,而不是再次读取完整的技能 指令(那应该用 get_skill)。只允许访问技能目录内部的文件。

func SetBuiltinSkillDir added in v0.2.0

func SetBuiltinSkillDir(dir string)

SetBuiltinSkillDir 覆盖内置技能源码目录(空串表示恢复默认:相对当前工作目录)。 仅用于测试或自定义部署目录;非并发安全,应在服务启动前调用。

func ToPromptXML added in v0.1.5

func ToPromptXML(skills []*Skill) string

ToPromptXML 生成注入系统提示词的 <available_skills> XML。

仅包含元信息(name / description),刻意不含指令正文与文件路径——正文与附属资源 都由模型通过工具(get_skill / load_skill_resource)按需加载,避免一次性塞满 上下文。DisableModelInvocation 的技能会被排除。

Types

type DiscoveryState added in v0.1.5

type DiscoveryState int

DiscoveryState 表示单个技能文件的发现结果。

const (
	// StateNormal 表示技能解析并校验成功。
	StateNormal DiscoveryState = iota
	// StateError 表示扫描 / 解析 / 校验失败。
	StateError
)

type GetSkillInput added in v0.2.0

type GetSkillInput struct {
	// Name 是技能名(即 SKILL.md frontmatter 的 name)。
	Name string `json:"name"`
	// Version 是可选的版本约束;当前只支持精确匹配(与 manifest.json /
	// frontmatter 的 version 比对),留空表示使用已发现的当前版本。
	Version string `json:"version,omitempty"`
}

GetSkillInput 是 get_skill 工具的入参。

type GetSkillOutput added in v0.2.0

type GetSkillOutput struct {
	Name         string   `json:"name"`
	Description  string   `json:"description,omitempty"`
	Version      string   `json:"version,omitempty"`
	SkillPath    string   `json:"skill_path,omitempty"`
	Resources    []string `json:"resources,omitempty"`
	Instructions string   `json:"instructions"`
	Error        string   `json:"error,omitempty"`
}

GetSkillOutput 是 get_skill 工具返回给模型的结果。

func ResolveSkillOutput added in v0.2.0

func ResolveSkillOutput(ctx context.Context, resolver runtimecontext.SkillResolver, name, version string) (GetSkillOutput, error)

ResolveSkillOutput 是「按名称获取技能内容」的单一实现(get_skill 工具与 HTTP 接口共用)。

它解析技能并用 ctx 中注入的 RuntimeContext 变量渲染指令正文,保证工具执行期与 前端 / 调试接口看到的技能内容一致。

返回 error 仅表示调用方环境缺失(如未注入 SkillResolver);技能不存在、版本不匹配、 渲染失败等业务错误通过 GetSkillOutput.Error 返回(与工具反馈给模型的口径一致)。

type LoadSkillResourceInput added in v0.2.0

type LoadSkillResourceInput struct {
	// Name 是技能名。
	Name string `json:"name"`
	// Path 是相对技能目录的资源路径,如 references/design.md。
	Path string `json:"path"`
	// Version 语义同 get_skill.Version(可选)。
	Version string `json:"version,omitempty"`
}

LoadSkillResourceInput 是 load_skill_resource 工具的入参。

type LoadSkillResourceOutput added in v0.2.0

type LoadSkillResourceOutput struct {
	Name    string `json:"name"`
	Path    string `json:"path"`
	AbsPath string `json:"abs_path,omitempty"`
	Content string `json:"content,omitempty"`
	Error   string `json:"error,omitempty"`
}

LoadSkillResourceOutput 是 load_skill_resource 工具返回给模型的结果。

type Manifest

type Manifest struct {
	Version string `json:"version"`
}

Manifest 是技能目录下 manifest.json 的结构(全部字段可选)。

现有实现只使用 version(供 get_skill 的版本选择与展示)。

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry 持有一组已发现的技能,提供按名解析与提示词注入。

技能按名称唯一;同名后注册者覆盖先注册者(用户技能覆盖内置技能)。

Registry 支持在程序运行期热更新(Register / Unregister),因此内部用读写锁 保护:一次 Agent 运行读取技能元信息的同时,前端可以新增 / 修改 / 删除技能。

func NewRegistry

func NewRegistry() *Registry

NewRegistry 创建空注册表。

func NewRegistryWith

func NewRegistryWith(skills ...*Skill) *Registry

NewRegistryWith 创建注册表并注册给定技能。

func (*Registry) Filter added in v0.1.5

func (r *Registry) Filter(names ...string) *Registry

Filter 返回仅包含指定名称(保持升序、去重)的新注册表;names 为空时返回全部技能。

func (*Registry) Get

func (r *Registry) Get(name string) (*Skill, bool)

Get 按名称解析技能。

func (*Registry) Has

func (r *Registry) Has(name string) bool

Has 报告指定技能是否已注册。

func (*Registry) List

func (r *Registry) List() []*Skill

List 返回全部技能(按名称升序)。

func (*Registry) Names

func (r *Registry) Names() []string

Names 返回全部技能名(升序)。

func (*Registry) PromptBlock added in v0.1.5

func (r *Registry) PromptBlock(selected ...string) string

PromptBlock 把技能元信息(selected 为空表示全部)拼接为注入系统提示词的 markdown 块。

仅注入 name / description / location,不含指令正文;无匹配技能时返回空字符串。

func (*Registry) Register

func (r *Registry) Register(s *Skill)

Register 注册技能;nil 或空名技能会被忽略,同名覆盖。

func (*Registry) Resolver added in v0.2.0

func (r *Registry) Resolver() runtimecontext.SkillResolver

Resolver 返回实现 runtimecontext.SkillResolver 的视图,供技能工具(get_skill / load_skill_resource)在执行期按名称解析技能。

func (*Registry) Unregister added in v0.1.5

func (r *Registry) Unregister(name string)

Unregister 按名称移除技能;不存在时无操作。

type Skill

type Skill struct {
	Name                   string `yaml:"name" json:"name"`
	Description            string `yaml:"description" json:"description"`
	ManifestVersion        string `yaml:"version,omitempty" json:"version,omitempty"`
	UserInvocable          bool   `yaml:"user-invocable" json:"user_invocable"`
	DisableModelInvocation bool   `yaml:"disable-model-invocation" json:"disable_model_invocation"`
	// DisableRender 为 true 时,get_skill / load_skill_resource 原样返回技能文本,
	// 不按本轮 RuntimeContext 的业务变量做 pongo2 模板渲染。
	//
	// 零值(false)表示启用渲染:技能正文 / 附属资源中出现 {{ var }} 时会用当前场景
	// 变量替换;但若技能文本本身含有不希望被替换的花括号(如代码示例中的模板语法),
	// 将该开关置为 true 即可关闭渲染。
	DisableRender bool `yaml:"disable-render" json:"disable_render"`

	// 以下字段不参与 frontmatter 解析,由加载过程填充。
	Instructions  string `yaml:"-" json:"instructions,omitempty"`    // 指令正文
	Path          string `yaml:"-" json:"path,omitempty"`            // 技能目录
	SkillFilePath string `yaml:"-" json:"skill_file_path,omitempty"` // SKILL.md 路径
}

Skill 表示一份解析后的 SKILL.md。

func Builtin added in v0.2.0

func Builtin() []*Skill

Builtin 读取全部内置技能(磁盘优先,缺失时回退到 go:embed 副本)。

读取 / 解析失败的技能会被跳过,不影响其余技能。

func Deduplicate added in v0.1.5

func Deduplicate(all []*Skill) []*Skill

Deduplicate 按名称去重;同名时后出现的覆盖先出现的(用户技能覆盖内置技能)。

func Discover added in v0.1.5

func Discover(paths []string) []*Skill

Discover 发现给定路径下所有合法技能。

func Filter added in v0.1.5

func Filter(all []*Skill, disabled []string) []*Skill

Filter 移除名称出现在 disabled 列表中的技能。

func Parse added in v0.1.5

func Parse(path string) (*Skill, error)

Parse 从磁盘解析一个 SKILL.md 文件。

func ParseContent added in v0.1.5

func ParseContent(content []byte) (*Skill, error)

ParseContent 从原始字节解析 SKILL.md。

func (*Skill) ListResources added in v0.2.0

func (s *Skill) ListResources() []string

ListResources 递归列出技能目录下的附属资源(相对技能目录的斜杠路径,已排序)。

SKILL.md 与 manifest.json 属于技能描述本身,不在资源列表内。

func (*Skill) ManifestPath added in v0.2.0

func (s *Skill) ManifestPath() string

ManifestPath 返回技能目录下 manifest.json 的路径。

func (*Skill) Marshal added in v0.1.5

func (s *Skill) Marshal() ([]byte, error)

Marshal 把技能序列化为 SKILL.md 内容(YAML frontmatter + 正文)。

与 Parse / ParseContent 互逆:Save 出来的文件应能被 Parse 原样读回。

func (*Skill) ReadResource added in v0.2.0

func (s *Skill) ReadResource(rel string) (string, string, error)

ReadResource 读取技能附属资源文件内容(大小上限 MaxResourceBytes)。

func (*Skill) ReadSkillResource added in v0.2.0

func (s *Skill) ReadSkillResource(path string) (string, string, error)

ReadSkillResource 读取技能目录内的附属资源,返回内容与绝对路径。

func (*Skill) ResolveResource added in v0.2.0

func (s *Skill) ResolveResource(rel string) (string, error)

ResolveResource 把技能目录内的相对路径解析为绝对路径,并拒绝目录穿越。

只允许访问技能目录内部的文件;越界、绝对路径或不存在都会返回错误。

func (*Skill) SkillInfo added in v0.2.0

func (s *Skill) SkillInfo() runtimecontext.SkillInfo

SkillInfo 返回技能的最小元信息与指令正文。

func (*Skill) SkillResources added in v0.2.0

func (s *Skill) SkillResources() []string

SkillResources 返回技能目录下的附属资源相对路径(不含 SKILL.md / manifest.json)。

func (*Skill) SkillVersion added in v0.2.0

func (s *Skill) SkillVersion() string

SkillVersion 返回技能版本(manifest.json 优先,回退 frontmatter version)。

func (*Skill) Validate added in v0.1.5

func (s *Skill) Validate() error

Validate 校验技能是否满足规范要求。

func (*Skill) Version added in v0.2.0

func (s *Skill) Version() string

Version 返回技能版本:优先取 manifest.json 中的 version,缺失时回退到 SKILL.md frontmatter 的 version 字段;都没有则返回空串。

type SkillState added in v0.1.5

type SkillState struct {
	Name  string
	Path  string
	State DiscoveryState
	Err   error
}

SkillState 描述单个技能文件的最新发现状态。

type Store added in v0.1.5

type Store struct {
	// contains filtered or unexported fields
}

Store 把技能以 SKILL.md 的形式持久化到某个根目录(通常为 $BaseDir/.skills)。

磁盘是用户技能的唯一真实来源:运行期新增 / 修改 / 删除都会落盘,进程重启后 由 Discover 重新加载。这样既能保证「程序运行中也能改技能」,又不会因为进程 重启而丢失改动。内存中的 Registry 只是磁盘内容的一份可热更新的缓存。

func NewStore added in v0.1.5

func NewStore(dir string) *Store

NewStore 创建以 dir 为根目录的技能存储;dir 为空时视为未配置。

func (*Store) Available added in v0.1.5

func (s *Store) Available() bool

Available 报告存储是否已配置根目录。

func (*Store) Contains added in v0.1.5

func (s *Store) Contains(path string) bool

Contains 报告 path 是否位于该 Store 的根目录之下。 用于限制只允许删除 / 修改存储在用户技能目录内的技能,避免误删内置或外部技能。

func (*Store) Delete added in v0.1.5

func (s *Store) Delete(name string) error

Delete 删除名为 name 的技能目录;目录不存在时视为成功(幂等)。

func (*Store) Dir added in v0.1.5

func (s *Store) Dir() string

Dir 返回存储根目录。

func (*Store) Save added in v0.1.5

func (s *Store) Save(sk *Skill) error

Save 把技能写入 <dir>/<name>/SKILL.md(写入前做规范校验)。name 作为目录名。

func (*Store) SkillDir added in v0.1.5

func (s *Store) SkillDir(name string) string

SkillDir 返回名为 name 的技能目录 <dir>/<name>。

func (*Store) SkillPath added in v0.1.5

func (s *Store) SkillPath(name string) string

SkillPath 返回名为 name 的技能文件路径 <dir>/<name>/SKILL.md。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL