registry

package
v0.1.0-beta.2 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned when a skill does not exist in the store.

Functions

func BuildWorkflowDAG

func BuildWorkflowDAG(steps []WorkflowStep) ([][]WorkflowStep, error)

BuildWorkflowDAG constructs a dependency graph from workflow steps and returns steps in topological execution order, grouped by level. Steps within the same level have all dependencies satisfied and can run concurrently. Returns an error if cycles are detected or depends_on references are invalid.

func EvaluateCondition

func EvaluateCondition(expr string, ctx *TemplateContext) (bool, error)

EvaluateCondition evaluates a condition expression against the template context. Supports: equality (==, !=), boolean checks, and existence checks.

func RenderSkillMD

func RenderSkillMD(skill *AgentSkill) ([]byte, error)

RenderSkillMD serializes an AgentSkill back to SKILL.md format.

func ResolveArgs

func ResolveArgs(args map[string]any, ctx *TemplateContext) (map[string]any, error)

ResolveArgs resolves template expressions in a step's args map. Returns a new map with all {{ ... }} expressions replaced with values.

func ResolveString

func ResolveString(s string, ctx *TemplateContext) (any, error)

ResolveString resolves template expressions in a single string value. If the entire string is a single expression, the typed value is returned. If mixed with literal text, expressions are resolved and concatenated as a string.

func ResolveTemplate

func ResolveTemplate(tmpl string, ctx *TemplateContext) (string, error)

ResolveTemplate resolves a full template string (used for output.template). Always returns a string, even for single expressions.

func ValidateSkill

func ValidateSkill(s *AgentSkill) error

ValidateSkill validates an AgentSkill and returns just the error (convenience wrapper).

func ValidateSkillName

func ValidateSkillName(name string) error

ValidateSkillName validates a skill name against the agentskills.io spec.

Types

type AgentSkill

type AgentSkill struct {
	// --- Frontmatter fields (from YAML between --- delimiters) ---
	Name          string            `yaml:"name" json:"name"`
	Description   string            `yaml:"description" json:"description"`
	License       string            `yaml:"license,omitempty" json:"license,omitempty"`
	Compatibility string            `yaml:"compatibility,omitempty" json:"compatibility,omitempty"`
	Metadata      map[string]string `yaml:"metadata,omitempty" json:"metadata,omitempty"`
	AllowedTools  string            `yaml:"allowed-tools,omitempty" json:"allowedTools,omitempty"`

	// --- Gridctl extensions (not in agentskills.io spec) ---
	State ItemState `yaml:"state,omitempty" json:"state"`

	// Workflow definition (gridctl extension).
	// When present, the skill becomes executable and is exposed as an MCP tool.
	Inputs   map[string]SkillInput `yaml:"inputs,omitempty" json:"inputs,omitempty"`
	Workflow []WorkflowStep        `yaml:"workflow,omitempty" json:"workflow,omitempty"`
	Output   *WorkflowOutput       `yaml:"output,omitempty" json:"output,omitempty"`

	// --- Parsed from file content (not in frontmatter YAML) ---
	Body string `yaml:"-" json:"body"` // Markdown content after frontmatter

	// --- Computed fields (not serialized to YAML) ---
	FileCount int    `yaml:"-" json:"fileCount"` // Number of supporting files (scripts/, references/, assets/)
	Dir       string `yaml:"-" json:"-"`         // Relative path from skills/ root (e.g., "git-workflow/branch-fork")
}

AgentSkill represents an Agent Skills standard SKILL.md file. See https://agentskills.io/specification for the full spec.

func ParseSkillMD

func ParseSkillMD(data []byte) (*AgentSkill, error)

ParseSkillMD parses a SKILL.md file into an AgentSkill. The file format is YAML frontmatter between --- delimiters followed by a markdown body.

func (*AgentSkill) IsExecutable

func (s *AgentSkill) IsExecutable() bool

IsExecutable returns true if the skill has a workflow definition.

func (*AgentSkill) ToMCPTool

func (s *AgentSkill) ToMCPTool() mcp.Tool

ToMCPTool generates an MCP Tool definition from this skill's inputs. Only meaningful for executable skills (IsExecutable() == true).

func (*AgentSkill) Validate

func (s *AgentSkill) Validate() error

Validate checks the skill against the agentskills.io specification.

type ExecutionResult

type ExecutionResult struct {
	Skill      string                `json:"skill"`
	Status     string                `json:"status"` // "completed", "failed", "partial"
	StartedAt  time.Time             `json:"startedAt"`
	FinishedAt time.Time             `json:"finishedAt"`
	DurationMs int64                 `json:"durationMs"`
	Steps      []StepExecutionResult `json:"steps"`
	Output     *mcp.ToolCallResult   `json:"output,omitempty"`
	Error      string                `json:"error,omitempty"`
}

ExecutionResult captures the full result of a workflow execution.

type Executor

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

Executor runs skill workflows by dispatching steps through a ToolCaller.

func NewExecutor

func NewExecutor(caller ToolCaller, logger *slog.Logger, opts ...ExecutorOption) *Executor

NewExecutor creates a workflow executor that routes calls through the given ToolCaller.

func (*Executor) Execute

func (e *Executor) Execute(ctx context.Context, skill *AgentSkill, arguments map[string]any) (*mcp.ToolCallResult, error)

Execute runs a skill workflow. This is the entry point for CallTool().

func (*Executor) SetLogger

func (e *Executor) SetLogger(logger *slog.Logger)

SetLogger updates the executor's logger. Used when the logger is created after the executor (e.g., in gateway builder where logging is Phase 2).

type ExecutorOption

type ExecutorOption func(*Executor)

ExecutorOption configures an Executor.

func WithMaxParallel

func WithMaxParallel(n int) ExecutorOption

WithMaxParallel sets the maximum number of concurrent steps per DAG level.

func WithMaxResultSize

func WithMaxResultSize(n int) ExecutorOption

WithMaxResultSize sets the maximum size of a single step result.

func WithWorkflowTimeout

func WithWorkflowTimeout(d time.Duration) ExecutorOption

WithWorkflowTimeout sets the maximum duration for an entire workflow execution.

type ItemState

type ItemState string

ItemState represents the lifecycle state of a skill. Note: state is a gridctl extension, not part of the agentskills.io spec.

const (
	StateDraft    ItemState = "draft"
	StateActive   ItemState = "active"
	StateDisabled ItemState = "disabled"
)

type RegistryStatus

type RegistryStatus struct {
	TotalSkills  int `json:"totalSkills"`
	ActiveSkills int `json:"activeSkills"`
}

RegistryStatus contains summary statistics.

type RetryPolicy

type RetryPolicy struct {
	MaxAttempts int    `yaml:"max_attempts" json:"maxAttempts"`
	Backoff     string `yaml:"backoff,omitempty" json:"backoff,omitempty"`
}

RetryPolicy defines retry behavior for a workflow step.

type Server

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

Server is an in-process MCP server that serves Agent Skills as prompts and executable workflow skills as MCP tools. It implements mcp.AgentClient so it can be registered with the gateway router, and mcp.PromptProvider so the gateway can serve skills via MCP prompts and resources.

Skills without a workflow are knowledge documents exposed as prompts. Skills with a workflow are executable and exposed as MCP tools that route through the gateway's ToolCaller for step execution.

func New

func New(store *Store, opts ...ServerOption) *Server

New creates a registry server. If caller is non-nil, executable skills (those with workflows) are exposed as MCP tools that route through the caller. Skills without workflows remain knowledge documents.

func (*Server) CallTool

func (s *Server) CallTool(ctx context.Context, name string, arguments map[string]any) (*mcp.ToolCallResult, error)

CallTool dispatches to the executor for executable skills. Non-executable skills return an informational error.

func (*Server) GetPromptData

func (s *Server) GetPromptData(name string) (*mcp.PromptData, error)

GetPromptData returns a specific active skill's content as MCP PromptData.

func (*Server) HasContent

func (s *Server) HasContent() bool

HasContent returns true if the registry has any skills.

func (*Server) Initialize

func (s *Server) Initialize(ctx context.Context) error

Initialize loads the store.

func (*Server) IsInitialized

func (s *Server) IsInitialized() bool

IsInitialized returns whether the server has been initialized.

func (*Server) ListPromptData

func (s *Server) ListPromptData() []mcp.PromptData

ListPromptData returns active Agent Skills as MCP PromptData. Each skill gets a single optional "context" argument for clients to pass additional context when requesting the skill via prompts/get.

func (*Server) Name

func (s *Server) Name() string

Name returns "registry".

func (*Server) RefreshTools

func (s *Server) RefreshTools(ctx context.Context) error

RefreshTools reloads the store from disk.

func (*Server) ServerInfo

func (s *Server) ServerInfo() mcp.ServerInfo

ServerInfo returns server information.

func (*Server) SetLogger

func (s *Server) SetLogger(logger *slog.Logger)

SetLogger updates the executor's logger if one is configured.

func (*Server) Store

func (s *Server) Store() *Store

Store returns the underlying store for REST API access.

func (*Server) Tools

func (s *Server) Tools() []mcp.Tool

Tools returns executable skills as MCP tools. Skills without workflows are not included (they remain prompts only).

type ServerOption

type ServerOption func(*Server)

ServerOption configures the registry server.

func WithToolCaller

func WithToolCaller(caller ToolCaller, logger *slog.Logger, opts ...ExecutorOption) ServerOption

WithToolCaller enables workflow execution through the given ToolCaller.

type SkillFile

type SkillFile struct {
	Path  string `json:"path"`  // Relative path within the skill dir (e.g., "scripts/lint.sh")
	Size  int64  `json:"size"`  // File size in bytes
	IsDir bool   `json:"isDir"` // True for directories
}

SkillFile represents a file within a skill directory.

type SkillInput

type SkillInput struct {
	Type        string   `yaml:"type" json:"type"`
	Description string   `yaml:"description,omitempty" json:"description,omitempty"`
	Required    bool     `yaml:"required,omitempty" json:"required,omitempty"`
	Default     any      `yaml:"default,omitempty" json:"default,omitempty"`
	Enum        []string `yaml:"enum,omitempty" json:"enum,omitempty"`
}

SkillInput defines a parameter for an executable skill.

type StepExecutionResult

type StepExecutionResult struct {
	ID         string    `json:"id"`
	Tool       string    `json:"tool"`
	Status     string    `json:"status"` // "success", "failed", "skipped"
	StartedAt  time.Time `json:"startedAt"`
	DurationMs int64     `json:"durationMs"`
	Error      string    `json:"error,omitempty"`
	Attempts   int       `json:"attempts,omitempty"`   // retry count (1 = no retry)
	SkipReason string    `json:"skipReason,omitempty"` // why step was skipped
	Level      int       `json:"level"`                // DAG level (0-indexed)
}

StepExecutionResult captures the result of a single workflow step.

type StepResult

type StepResult struct {
	Result  string // Text content from ToolCallResult
	IsError bool   // Whether the step returned isError: true
	Raw     any    // Parsed JSON if result is valid JSON, otherwise nil
}

StepResult captures the output of a completed workflow step.

func NewStepResult

func NewStepResult(result string, isError bool) *StepResult

NewStepResult creates a StepResult, truncating oversized results and parsing JSON.

type Store

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

Store manages skill directories on disk. Each skill is a directory containing a required SKILL.md and optional supporting files (scripts/, references/, assets/).

func NewStore

func NewStore(baseDir string) *Store

NewStore creates a store rooted at the given directory.

func (*Store) ActiveSkills

func (s *Store) ActiveSkills() []*AgentSkill

ActiveSkills returns only skills with State == "active". Returned pointers are copies.

func (*Store) DeleteFile

func (s *Store) DeleteFile(skillName, filePath string) error

DeleteFile removes a file from a skill directory.

func (*Store) DeleteSkill

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

DeleteSkill removes a skill directory and cache entry.

func (*Store) GetSkill

func (s *Store) GetSkill(name string) (*AgentSkill, error)

GetSkill returns a skill by name.

func (*Store) HasContent

func (s *Store) HasContent() bool

HasContent returns true if there is at least one skill.

func (*Store) ListFiles

func (s *Store) ListFiles(skillName string) ([]SkillFile, error)

ListFiles returns all files in a skill directory (excluding SKILL.md).

func (*Store) ListSkills

func (s *Store) ListSkills() []*AgentSkill

ListSkills returns all skills (all states). Returned pointers are copies.

func (*Store) Load

func (s *Store) Load() error

Load scans the skills/ subdirectory for SKILL.md files and checks for legacy YAML registry files.

func (*Store) ReadFile

func (s *Store) ReadFile(skillName, filePath string) ([]byte, error)

ReadFile reads a specific file from a skill directory.

func (*Store) RenameSkill

func (s *Store) RenameSkill(oldName, newName string) error

RenameSkill renames a skill directory and updates its frontmatter.

func (*Store) SaveSkill

func (s *Store) SaveSkill(sk *AgentSkill) error

SaveSkill creates or updates a skill (validates, writes SKILL.md, updates cache).

func (*Store) Status

func (s *Store) Status() RegistryStatus

Status returns registry summary counts.

func (*Store) WriteFile

func (s *Store) WriteFile(skillName, filePath string, data []byte) error

WriteFile writes a file to a skill directory, creating parent directories as needed.

type StringOrSlice

type StringOrSlice []string

StringOrSlice allows YAML fields to be either a single string or a list. "depends_on: step-a" and "depends_on: [step-a, step-b]" both work.

func (*StringOrSlice) UnmarshalYAML

func (s *StringOrSlice) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML implements custom YAML unmarshaling for StringOrSlice.

type TemplateContext

type TemplateContext struct {
	Inputs map[string]any         // User-provided arguments
	Steps  map[string]*StepResult // Completed step results
}

TemplateContext holds the data available to template expressions.

type ToolCaller

type ToolCaller = mcp.ToolCaller

ToolCaller is the interface the executor uses to invoke tools. It matches the existing mcp.ToolCaller interface.

type ValidationResult

type ValidationResult struct {
	Errors   []string // Fatal validation failures
	Warnings []string // Non-fatal advisories (e.g., body too long)
}

ValidationResult contains errors and warnings from skill validation.

func ValidateSkillFull

func ValidateSkillFull(s *AgentSkill) *ValidationResult

ValidateSkillFull validates an AgentSkill and returns both errors and warnings.

func (*ValidationResult) Error

func (v *ValidationResult) Error() error

Error returns the first error as a Go error, or nil if valid.

func (*ValidationResult) Valid

func (v *ValidationResult) Valid() bool

Valid returns true if there are no errors (warnings are OK).

type WorkflowOutput

type WorkflowOutput struct {
	Format   string   `yaml:"format,omitempty" json:"format,omitempty"` // merged|last|custom
	Include  []string `yaml:"include,omitempty" json:"include,omitempty"`
	Template string   `yaml:"template,omitempty" json:"template,omitempty"`
}

WorkflowOutput controls how step results are assembled.

type WorkflowStep

type WorkflowStep struct {
	ID        string         `yaml:"id" json:"id"`
	Tool      string         `yaml:"tool" json:"tool"`
	Args      map[string]any `yaml:"args,omitempty" json:"args,omitempty"`
	DependsOn StringOrSlice  `yaml:"depends_on,omitempty" json:"dependsOn,omitempty"`
	Condition string         `yaml:"condition,omitempty" json:"condition,omitempty"`
	OnError   string         `yaml:"on_error,omitempty" json:"onError,omitempty"`
	Timeout   string         `yaml:"timeout,omitempty" json:"timeout,omitempty"`
	Retry     *RetryPolicy   `yaml:"retry,omitempty" json:"retry,omitempty"`
}

WorkflowStep defines a single tool invocation in a workflow.

Jump to

Keyboard shortcuts

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