skills

package
v0.0.0-...-1f1a93d Latest Latest
Warning

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

Go to latest
Published: May 13, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

NemesisBot - AI agent License: MIT Copyright (c) 2026 NemesisBot contributors

Index

Constants

View Source
const (
	MaxNameLength        = 64
	MaxDescriptionLength = 1024
)

Variables

This section is empty.

Functions

func DownloadFile

func DownloadFile(ctx context.Context, client *http.Client, url string, maxSize int64) ([]byte, error)

DownloadFile downloads a single file from a URL with size limit.

func DownloadSkillTreeFromGitHub

func DownloadSkillTreeFromGitHub(ctx context.Context, client *http.Client,
	apiBaseURL, rawBaseURL, repo, branch, dirPrefix, targetDir string,
	maxFileSize int64,
) error

DownloadSkillTreeFromGitHub downloads all files in a skill directory from GitHub using the Trees API. It lists the full tree, filters for files under the given directory prefix, and downloads each file individually.

Parameters:

  • apiBaseURL: GitHub API base URL (e.g. "https://api.github.com")
  • rawBaseURL: raw content base URL (e.g. "https://raw.githubusercontent.com")
  • repo: repository in "owner/repo" format
  • branch: branch name (e.g. "main")
  • dirPrefix: directory prefix to filter (e.g. "skills/pdf" or "skills/owner/slug")
  • targetDir: local directory to write files into
  • maxFileSize: maximum size per file in bytes (0 = use default 10MB)

func ValidateSkillIdentifier

func ValidateSkillIdentifier(slug string) error

ValidateSkillIdentifier validates a skill identifier to prevent path traversal attacks.

Types

type AvailableSkill

type AvailableSkill struct {
	Name        string   `json:"name"`
	Repository  string   `json:"repository"`
	Description string   `json:"description"`
	Author      string   `json:"author"`
	Tags        []string `json:"tags"`
}

type CacheEntry

type CacheEntry struct {
	Results      []RegistrySearchResult // grouped by registry
	Trigrams     []uint32               // trigram signature for similarity matching
	CreatedAt    time.Time
	LastAccessAt time.Time
	AccessCount  int
}

CacheEntry represents a single cache entry with search results and metadata.

type CacheStats

type CacheStats struct {
	Size      int     // current number of entries
	MaxSize   int     // maximum number of entries
	HitCount  int     // number of cache hits
	MissCount int     // number of cache misses
	HitRate   float64 // cache hit rate (0.0 - 1.0)
}

CacheStats holds cache statistics.

type ClawHubConfig

type ClawHubConfig struct {
	Enabled   bool
	BaseURL   string // ClawHub website URL (e.g. "https://clawhub.ai"), used for search API
	ConvexURL string // Convex deployment URL (e.g. "https://wry-manatee-359.convex.cloud")
	Timeout   int    // seconds, 0 = default (30s)
}

ClawHubConfig configures the ClawHub registry.

type ClawHubRegistry

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

ClawHubRegistry implements the SkillRegistry interface for ClawHub.ai.

API endpoints used:

  • Search: GET {baseURL}/api/search?q={query}&limit={limit}
  • List: Convex POST /api/query {"path":"skills:list","args":{"limit":N},"format":"json"}
  • Meta: Convex POST /api/query {"path":"skills:getBySlug","args":{"slug":"..."},"format":"json"}

func NewClawHubRegistry

func NewClawHubRegistry(cfg ClawHubConfig) *ClawHubRegistry

NewClawHubRegistry creates a new ClawHub registry client.

func (*ClawHubRegistry) DownloadAndInstall

func (r *ClawHubRegistry) DownloadAndInstall(ctx context.Context, slug, version, targetDir string) (*InstallResult, error)

DownloadAndInstall fetches metadata to find the owner handle, then downloads the full skill directory (all files and subdirectories).

Strategy:

  1. Try ZIP download from the Convex site URL (primary).
  2. Fallback to GitHub Trees API for individual file downloads.

func (*ClawHubRegistry) GetSkillMeta

func (r *ClawHubRegistry) GetSkillMeta(ctx context.Context, slug string) (*SkillMeta, error)

GetSkillMeta retrieves metadata for a specific skill by slug.

func (*ClawHubRegistry) Name

func (r *ClawHubRegistry) Name() string

Name returns the registry name.

func (*ClawHubRegistry) Search

func (r *ClawHubRegistry) Search(ctx context.Context, query string, limit int) ([]SearchResult, error)

Search searches the ClawHub registry for skills matching the query. Non-empty query uses the clawhub.ai search API (vector search). Empty query falls back to Convex skills:list (sorted by creation time).

type DangerPattern

type DangerPattern struct {
	ID          string // unique identifier, e.g. "DEST-001"
	Name        string // human-readable name
	Category    string // "destructive", "exfiltration", "privilege", "obfuscation", "recon"
	Severity    string // "critical", "high", "medium", "low"
	Pattern     string // regex pattern string
	Description string
}

DangerPattern represents a dangerous code pattern detected by the linter.

type DimensionScore

type DimensionScore struct {
	Score   float64 `json:"score"`   // 0-100
	Max     float64 `json:"max"`     // always 100
	Details string  `json:"details"` // explanation
}

DimensionScore represents a single scoring dimension with score, max, and details.

type GitHubConfig

type GitHubConfig struct {
	Enabled bool
	BaseURL string // defaults to github.com
	Timeout int    // seconds, 0 = default (30s)
	MaxSize int    // bytes, 0 = default (1MB)
}

GitHubConfig configures the GitHub registry (legacy single-source).

type GitHubRegistry

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

GitHubRegistry implements SkillRegistry for GitHub repositories.

func NewGitHubRegistry

func NewGitHubRegistry(cfg GitHubConfig) *GitHubRegistry

NewGitHubRegistry creates a new GitHub registry client from config (legacy single-source).

func NewGitHubRegistryFromSource

func NewGitHubRegistryFromSource(source GitHubSourceConfig) *GitHubRegistry

NewGitHubRegistryFromSource creates a new GitHub registry from a GitHubSourceConfig.

func (*GitHubRegistry) DownloadAndInstall

func (g *GitHubRegistry) DownloadAndInstall(ctx context.Context, slug, version, targetDir string) (*InstallResult, error)

DownloadAndInstall downloads a skill from GitHub and installs it to the target directory. Downloads all files and subdirectories within the skill directory, not just SKILL.md.

func (*GitHubRegistry) GetSkillMeta

func (g *GitHubRegistry) GetSkillMeta(ctx context.Context, slug string) (*SkillMeta, error)

GetSkillMeta retrieves metadata for a specific GitHub skill.

func (*GitHubRegistry) Name

func (g *GitHubRegistry) Name() string

func (*GitHubRegistry) Search

func (g *GitHubRegistry) Search(ctx context.Context, query string, limit int) ([]SearchResult, error)

Search searches for available GitHub skills. Dispatches to the appropriate search strategy based on indexType.

type GitHubSourceConfig

type GitHubSourceConfig struct {
	Name             string
	Repo             string // e.g. "anthropics/skills"
	Enabled          bool
	Branch           string // default "main"
	IndexType        string // "skills_json" or "github_api"
	IndexPath        string // e.g. "skills.json"
	SkillPathPattern string // e.g. "skills/{slug}/SKILL.md"
	Timeout          int
	MaxSize          int
}

GitHubSourceConfig configures a single GitHub source for skills.

type InstallResult

type InstallResult struct {
	Version          string
	IsMalwareBlocked bool
	IsSuspicious     bool
	Summary          string
}

InstallResult is returned by DownloadAndInstall to carry metadata back to the caller for moderation and user messaging.

type LintIssue

type LintIssue struct {
	PatternID   string `json:"pattern_id"`
	Category    string `json:"category"`
	Severity    string `json:"severity"`
	Message     string `json:"message"`
	Line        int    `json:"line"`
	MatchedText string `json:"matched_text"`
}

LintIssue represents a single linting issue found in skill content.

type LintResult

type LintResult struct {
	SkillName string      `json:"skill_name"`
	Passed    bool        `json:"passed"`
	Issues    []LintIssue `json:"issues"`
	Score     float64     `json:"score"` // 0-100, 100 = clean
}

LintResult holds the result of linting a skill's content.

type Linter

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

Linter performs static analysis on skill definitions to detect dangerous patterns.

func NewLinter

func NewLinter() *Linter

NewLinter creates a Linter with 27 built-in dangerous pattern detectors.

func (*Linter) Lint

func (l *Linter) Lint(content string, skillName string) *LintResult

Lint analyzes the given skill content and returns a LintResult with all detected issues.

type MockRegistry

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

MockRegistry is a test implementation of SkillRegistry

func NewMockRegistry

func NewMockRegistry(name string) *MockRegistry

NewMockRegistry creates a new MockRegistry with the given name

func (*MockRegistry) AddSearchResult

func (m *MockRegistry) AddSearchResult(result SearchResult)

AddSearchResult adds a search result to the mock registry

func (*MockRegistry) DownloadAndInstall

func (m *MockRegistry) DownloadAndInstall(ctx context.Context, slug, version, targetDir string) (*InstallResult, error)

func (*MockRegistry) GetSkillMeta

func (m *MockRegistry) GetSkillMeta(ctx context.Context, slug string) (*SkillMeta, error)

func (*MockRegistry) Name

func (m *MockRegistry) Name() string

func (*MockRegistry) Search

func (m *MockRegistry) Search(ctx context.Context, query string, limit int) ([]SearchResult, error)

func (*MockRegistry) SetSkillMeta

func (m *MockRegistry) SetSkillMeta(slug string, meta *SkillMeta)

SetSkillMeta sets the metadata for a skill

type QualityScore

type QualityScore struct {
	Overall      float64        `json:"overall"`      // 0-100, weighted average
	Security     DimensionScore `json:"security"`     // safety analysis
	Completeness DimensionScore `json:"completeness"` // completeness of definition
	Clarity      DimensionScore `json:"clarity"`      // clarity of instructions
	Testing      DimensionScore `json:"testing"`      // test coverage hints
}

QualityScore holds the overall and per-dimension quality scores for a skill.

type QualityScorer

type QualityScorer struct{}

QualityScorer evaluates skill content quality across four dimensions.

func NewQualityScorer

func NewQualityScorer() *QualityScorer

NewQualityScorer creates a new QualityScorer.

func (*QualityScorer) Score

func (qs *QualityScorer) Score(content string, metadata map[string]string) *QualityScore

Score evaluates the given skill content and returns a QualityScore. The metadata map may contain keys like "name", "description", "source" that supplement the content analysis.

type RegistryConfig

type RegistryConfig struct {
	SearchCache           SearchCacheConfig
	ClawHub               ClawHubConfig
	GitHub                GitHubConfig         // Legacy single-source config (backward compat)
	GitHubSources         []GitHubSourceConfig // New multi-source config
	MaxConcurrentSearches int
}

RegistryConfig holds configuration for all skill registries.

type RegistryManager

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

RegistryManager coordinates multiple skill registries. It fans out search requests and routes installs to the correct registry.

func NewRegistryManager

func NewRegistryManager() *RegistryManager

NewRegistryManager creates an empty RegistryManager.

func NewRegistryManagerFromConfig

func NewRegistryManagerFromConfig(cfg RegistryConfig) *RegistryManager

NewRegistryManagerFromConfig builds a RegistryManager from config, instantiating only the enabled registries.

func (*RegistryManager) AddRegistry

func (rm *RegistryManager) AddRegistry(r SkillRegistry)

AddRegistry adds a registry to the manager.

func (*RegistryManager) GetRegistry

func (rm *RegistryManager) GetRegistry(name string) SkillRegistry

GetRegistry returns a registry by name, or nil if not found.

func (*RegistryManager) GetSearchCache

func (rm *RegistryManager) GetSearchCache() *SearchCache

GetSearchCache returns the search cache, or nil if not enabled.

func (*RegistryManager) SearchAll

func (rm *RegistryManager) SearchAll(ctx context.Context, query string, limit int) ([]RegistrySearchResult, error)

SearchAll fans out the query to all registries concurrently. Each registry is searched independently with the given limit. Results are returned grouped by registry, not merged.

type RegistrySearchResult

type RegistrySearchResult struct {
	RegistryName string         // e.g. "clawhub", "anthropics", "openclaw"
	Results      []SearchResult // results from this registry (sorted by score desc)
	Truncated    bool           // true if the registry may have more results than returned
}

RegistrySearchResult holds the search results for a single registry source.

type SearchCache

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

SearchCache provides intelligent caching for skill search results with similarity matching. Uses trigram-based similarity and Jaccard coefficient to match similar queries.

func NewSearchCache

func NewSearchCache(cfg SearchCacheConfig) *SearchCache

NewSearchCache creates a new search cache with the given configuration.

func (*SearchCache) Clear

func (sc *SearchCache) Clear()

Clear clears all entries from the cache.

func (*SearchCache) Get

func (sc *SearchCache) Get(query string, limit int) ([]RegistrySearchResult, bool)

Get retrieves search results from cache, checking for similar queries if exact match not found. Returns (results, true) if cache hit (exact or similar), (nil, false) if cache miss. Results are clamped per-registry to the given limit.

func (*SearchCache) Put

func (sc *SearchCache) Put(query string, results []RegistrySearchResult)

Put stores search results in the cache with the query as key. If the key already exists, it updates the entry and moves it to the front of LRU.

func (*SearchCache) Stats

func (sc *SearchCache) Stats() CacheStats

Stats returns cache statistics.

type SearchCacheConfig

type SearchCacheConfig struct {
	Enabled bool          `json:"enabled"`
	MaxSize int           `json:"max_size"` // maximum number of cache entries (default: 50)
	TTL     time.Duration `json:"ttl"`      // time-to-live (default: 5 minutes)
}

SearchCacheConfig configures the search cache.

type SearchResult

type SearchResult struct {
	Score        float64 `json:"score"`
	Slug         string  `json:"slug"`
	DisplayName  string  `json:"display_name"`
	Summary      string  `json:"summary"`
	Version      string  `json:"version"`
	RegistryName string  `json:"registry_name"`
	SourceRepo   string  `json:"source_repo,omitempty"`   // e.g. "anthropics/skills"
	DownloadPath string  `json:"download_path,omitempty"` // e.g. "skills/pdf/SKILL.md"
	Author       string  `json:"author,omitempty"`        // skill author handle
	Downloads    int64   `json:"downloads,omitempty"`     // download count
	Truncated    bool    `json:"truncated,omitempty"`     // hint: more results may exist beyond this entry
}

SearchResult represents a single result from a skill registry search.

func FlattenSearchResults

func FlattenSearchResults(grouped []RegistrySearchResult) []SearchResult

FlattenSearchResults flattens a slice of RegistrySearchResult into a single slice of SearchResult, for callers that don't need per-registry grouping.

type SecurityCheckResult

type SecurityCheckResult struct {
	LintResult   *LintResult   `json:"lint_result"`
	QualityScore *QualityScore `json:"quality_score"`
	Blocked      bool          `json:"blocked"`
	BlockReason  string        `json:"block_reason"`
}

SecurityCheckResult holds the combined results of lint + quality + signature checks.

func SecurityCheck

func SecurityCheck(content string, skillName string, metadata map[string]string) *SecurityCheckResult

SecurityCheck performs lint + quality scoring on skill content.

Blocking rules:

  • LintResult.Score < 30 → Blocked (severe dangerous patterns)
  • Any critical severity issue → Blocked
  • LintResult.Score < 60 → Warning only (not blocked)
  • QualityScore is informational only (never blocks)

type SkillInfo

type SkillInfo struct {
	Name        string  `json:"name"`
	Path        string  `json:"path"`
	Source      string  `json:"source"`
	Description string  `json:"description"`
	LintScore   float64 `json:"lint_score,omitempty"`
	HasWarnings bool    `json:"has_warnings,omitempty"`
}

type SkillInstaller

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

func NewSkillInstaller

func NewSkillInstaller(workspace string) *SkillInstaller

func (*SkillInstaller) GetOriginTracking

func (si *SkillInstaller) GetOriginTracking(skillName string) (*SkillOrigin, error)

GetOriginTracking reads the .skill-origin.json file for a skill.

func (*SkillInstaller) GetRegistryManager

func (si *SkillInstaller) GetRegistryManager() *RegistryManager

GetRegistryManager returns the configured registry manager.

func (*SkillInstaller) HasRegistry

func (si *SkillInstaller) HasRegistry(name string) bool

HasRegistry checks if a registry with the given name exists.

func (*SkillInstaller) HasRegistryManager

func (si *SkillInstaller) HasRegistryManager() bool

HasRegistryManager checks if a registry manager is configured.

func (*SkillInstaller) InstallFromGitHub

func (si *SkillInstaller) InstallFromGitHub(ctx context.Context, repo string) error

func (*SkillInstaller) InstallFromRegistry

func (si *SkillInstaller) InstallFromRegistry(ctx context.Context, registryName, slug, version string) error

InstallFromRegistry installs a skill using a registry from the RegistryManager.

func (*SkillInstaller) LastSecurityCheck

func (si *SkillInstaller) LastSecurityCheck() *SecurityCheckResult

LastSecurityCheck returns the security check result from the most recent install.

func (*SkillInstaller) ListAvailableSkills

func (si *SkillInstaller) ListAvailableSkills(ctx context.Context) ([]AvailableSkill, error)

func (*SkillInstaller) SearchAll

func (si *SkillInstaller) SearchAll(ctx context.Context, query string, limit int) ([]RegistrySearchResult, error)

SearchAll searches all configured registries for skills matching the query. This uses the search cache if enabled. Results are returned grouped by registry source.

func (*SkillInstaller) SearchRegistries

func (si *SkillInstaller) SearchRegistries(ctx context.Context, query string, limit int) ([]RegistrySearchResult, error)

SearchRegistries searches across all configured registries. Results are returned grouped by registry source.

func (*SkillInstaller) SetGitHubBaseURL

func (si *SkillInstaller) SetGitHubBaseURL(url string)

SetGitHubBaseURL sets the base URL for GitHub raw content (for testing).

func (*SkillInstaller) SetRegistryManager

func (si *SkillInstaller) SetRegistryManager(rm *RegistryManager)

SetRegistryManager sets the registry manager for advanced installation features.

func (*SkillInstaller) Uninstall

func (si *SkillInstaller) Uninstall(skillName string) error

type SkillMeta

type SkillMeta struct {
	Slug             string `json:"slug"`
	DisplayName      string `json:"display_name"`
	Summary          string `json:"summary"`
	LatestVersion    string `json:"latest_version"`
	IsMalwareBlocked bool   `json:"is_malware_blocked,omitempty"` // make optional for backward compatibility
	IsSuspicious     bool   `json:"is_suspicious,omitempty"`      // make optional for backward compatibility
	RegistryName     string `json:"registry_name"`
}

SkillMeta holds metadata about a skill from a registry.

type SkillMetadata

type SkillMetadata struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

type SkillOrigin

type SkillOrigin struct {
	Version          int    `json:"version"`           // format version
	Registry         string `json:"registry"`          // registry name (e.g., "github", "clawhub")
	Slug             string `json:"slug"`              // skill slug/identifier
	InstalledVersion string `json:"installed_version"` // installed version
	InstalledAt      int64  `json:"installed_at"`      // unix timestamp
}

SkillOrigin represents the origin metadata of an installed skill.

type SkillRegistry

type SkillRegistry interface {
	// Name returns the unique name of this registry (e.g., "clawhub").
	Name() string
	// Search searches the registry for skills matching the query.
	Search(ctx context.Context, query string, limit int) ([]SearchResult, error)
	// GetSkillMeta retrieves metadata for a specific skill by slug.
	GetSkillMeta(ctx context.Context, slug string) (*SkillMeta, error)
	// DownloadAndInstall fetches metadata, resolves the version, downloads and
	// installs the skill to targetDir. Returns an InstallResult with metadata
	// for the caller to use for moderation and user messaging.
	DownloadAndInstall(ctx context.Context, slug, version, targetDir string) (*InstallResult, error)
}

SkillRegistry is the interface that all skill registries must implement. Each registry represents a different source of skills (e.g., clawhub.ai, github)

type SkillSigner

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

SkillSigner provides high-level signing and verification operations for skills. It wraps the security/signature package with skill-specific logic.

func NewSkillSigner

func NewSkillSigner(configPath string) (*SkillSigner, error)

NewSkillSigner creates a SkillSigner using the trust store at configPath. If configPath is empty, an in-memory trust store is used.

func (*SkillSigner) GenerateKeyPair

func (ss *SkillSigner) GenerateKeyPair(outputDir string) (string, error)

GenerateKeyPair generates a new Ed25519 key pair and saves it to outputDir. The public key is saved as "skill_sign.pub" and the private key as "skill_sign.key". Returns the path to the output directory.

func (*SkillSigner) SignSkill

func (ss *SkillSigner) SignSkill(skillPath string, keyPath string) error

SignSkill signs all files in the skill directory at skillPath using the private key loaded from keyPath and writes a .signature file.

keyPath should point to a file containing the raw Ed25519 private key bytes (64 bytes: 32-byte seed concatenated with 32-byte public key).

func (*SkillSigner) Verifier

func (ss *SkillSigner) Verifier() *signature.Verifier

Verifier returns the underlying signature.Verifier for advanced operations.

func (*SkillSigner) VerifySkill

func (ss *SkillSigner) VerifySkill(skillPath string) (*signature.VerificationResult, error)

VerifySkill verifies the signature of the skill at skillPath. It returns a VerificationResult indicating whether the signature is valid, who signed it, and the trust level.

type SkillsLoader

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

func NewSkillsLoader

func NewSkillsLoader(workspace string, globalSkills string, builtinSkills string) *SkillsLoader

func (*SkillsLoader) BuildSkillsSummary

func (sl *SkillsLoader) BuildSkillsSummary() string

func (*SkillsLoader) EnableSecurity

func (sl *SkillsLoader) EnableSecurity()

EnableSecurity enables security scanning during skill listing.

func (*SkillsLoader) ListSkills

func (sl *SkillsLoader) ListSkills() []SkillInfo

func (*SkillsLoader) LoadSkill

func (sl *SkillsLoader) LoadSkill(name string) (string, bool)

func (*SkillsLoader) LoadSkillsForContext

func (sl *SkillsLoader) LoadSkillsForContext(skillNames []string) string

Jump to

Keyboard shortcuts

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