Files
picoclaw/pkg/skills/config_bridge.go
T
lxowalle 0425cd4d77 refactor skills registries and add GitHub-backed skill discovery (#2442)
* refactor skills registries and add GitHub-backed skill discovery

* fix ci

* fix command error

* fix default skills install registry behavior

* fix github registry URL parsing and versioned skill links

* fix skills registry config compatibility and URL installs

* * fix lint

* fix deprecated github base url compatibility

* fix skills registry yaml and github default branch handling

* fix github skills registry fallback and install metadata

* fix cli skills install origin metadata

* fix clawhub registry env compatibility

* fix skills registry config merge compatibility

* fix skill install metadata consistency and onboard template copy

* fix yaml overrides for default skills registries

* fix install_skill registry metadata normalization

* fix github skill URL parsing for slash branch names

* fix skills registry install/search validation and github URLs

* fix github skill URL host validation

* fix install_skill validation for invalid registry archives

* fix redundant skills registry names in saved config

* fix github blob skill URL installs and metadata links

* fix github registry URL scheme validation

* fix v0 skills migration preserving github registry defaults

* fix github blob skill install directory resolution

* fix install_skill rollback on origin metadata write failure

* fix github skill URL validation and registry JSON merging

* fix github registry target resolution and metadata links

* fix install_skill force reinstall rollback

* fix skills config compatibility and legacy security overlays

* fix ci
2026-04-14 15:14:16 +08:00

137 lines
4.1 KiB
Go

package skills
import "github.com/sipeed/picoclaw/pkg/config"
const defaultGitHubRegistryBaseURL = "https://github.com"
func effectiveRegistryConfigsFromToolsConfig(cfg config.SkillsToolsConfig) []config.SkillRegistryConfig {
effective := make([]config.SkillRegistryConfig, 0, len(cfg.Registries)+1)
seen := map[string]struct{}{}
for _, registryCfg := range cfg.Registries {
if registryCfg == nil || registryCfg.Name == "" {
continue
}
resolved := *registryCfg
if resolved.Name == "github" {
resolved = applyLegacyGithubRegistryCompatibility(cfg, resolved)
}
effective = append(effective, resolved)
seen[resolved.Name] = struct{}{}
}
if _, ok := seen["github"]; ok {
return effective
}
legacyGithubConfigured := cfg.Github.BaseURL != "" || cfg.Github.Token.String() != "" || cfg.Github.Proxy != ""
if !legacyGithubConfigured {
return effective
}
effective = append(effective, applyLegacyGithubRegistryCompatibility(cfg, config.SkillRegistryConfig{
Name: "github",
Enabled: true,
}))
return effective
}
func applyLegacyGithubRegistryCompatibility(
cfg config.SkillsToolsConfig,
registryCfg config.SkillRegistryConfig,
) config.SkillRegistryConfig {
if registryCfg.Name != "github" {
return registryCfg
}
if registryCfg.Param == nil {
registryCfg.Param = map[string]any{}
}
if registryCfg.BaseURL == "" ||
(registryCfg.BaseURL == defaultGitHubRegistryBaseURL &&
cfg.Github.BaseURL != "" &&
cfg.Github.BaseURL != defaultGitHubRegistryBaseURL) {
registryCfg.BaseURL = cfg.Github.BaseURL
}
if registryCfg.AuthToken.String() == "" {
registryCfg.AuthToken = cfg.Github.Token
}
if _, ok := registryCfg.Param["proxy"]; !ok && cfg.Github.Proxy != "" {
registryCfg.Param["proxy"] = cfg.Github.Proxy
}
return registryCfg
}
func registryProvidersFromToolsConfig(cfg config.SkillsToolsConfig) []RegistryProvider {
registryConfigs := effectiveRegistryConfigsFromToolsConfig(cfg)
providers := make([]RegistryProvider, 0, len(registryConfigs))
for _, registryCfg := range registryConfigs {
provider := buildRegistryProvider(registryCfg.Name, registryCfg)
if provider == nil {
continue
}
providers = append(providers, provider)
}
return providers
}
func NewRegistryManagerFromToolsConfig(cfg config.SkillsToolsConfig) *RegistryManager {
return NewRegistryManagerFromConfig(RegistryConfig{
Providers: registryProvidersFromToolsConfig(cfg),
MaxConcurrentSearches: cfg.MaxConcurrentSearches,
})
}
func LookupRegistryFromToolsConfig(cfg config.SkillsToolsConfig, name string) SkillRegistry {
for _, provider := range registryProvidersFromToolsConfig(cfg) {
if provider == nil {
continue
}
registry := provider.BuildRegistry()
if registry == nil || registry.Name() != name {
continue
}
return registry
}
return nil
}
func GitHubInstallDirNameFromToolsConfig(cfg config.SkillsToolsConfig, target string) (string, error) {
registryCfg, ok := cfg.Registries.Get("github")
if ok {
registryCfg = applyLegacyGithubRegistryCompatibility(cfg, registryCfg)
return githubInstallDirNameWithBaseURL(target, registryCfg.BaseURL)
}
return githubInstallDirNameWithBaseURL(target, cfg.Github.BaseURL)
}
func NormalizeInstallTargetForRegistry(cfg config.SkillsToolsConfig, registryName, target string) string {
if registryName == "" || target == "" {
return target
}
registry := LookupRegistryFromToolsConfig(cfg, registryName)
if registry == nil {
return target
}
ghRegistry, ok := registry.(*GitHubRegistry)
if !ok {
return target
}
normalized, err := canonicalGitHubRegistrySlugWithBaseURL(target, ghRegistry.webBase)
if err != nil || normalized == "" {
return target
}
return normalized
}
func BuildInstallMetadataForRegistryInstance(registry SkillRegistry, target, version string) (string, string) {
normalizedTarget := NormalizeInstallTargetForRegistryInstance(registry, target)
if registry == nil {
return normalizedTarget, ""
}
registryURL := registry.SkillURL(target, version)
if registryURL == "" {
registryURL = registry.SkillURL(normalizedTarget, version)
}
return normalizedTarget, registryURL
}