package pluginsdk import ( "fmt" "github.com/Masterminds/semver/v3" contractv1 "goaiapi/proto/contract/v1" ) // ComputeTier 由依赖图复算层级——不信插件自报,内核以此校验声明。 // 无依赖 -> base // 只依赖 base -> mid // 依赖任一非 base -> complex // allTiers 是「已注册插件名 -> 其层级」的快照。 func ComputeTier(deps []Dependency, allTiers map[string]contractv1.PluginTier) contractv1.PluginTier { if len(deps) == 0 { return contractv1.PluginTier_TIER_BASE } for _, d := range deps { t, ok := allTiers[d.Name] if !ok || t != contractv1.PluginTier_TIER_BASE { // 依赖未知(尚未注册)或依赖非 base,都算 complex return contractv1.PluginTier_TIER_COMPLEX } } return contractv1.PluginTier_TIER_MID } // ValidateManifest 校验 manifest 自洽:名字/版本非空、版本是合法 semver、 // 依赖约束可解析。tier 的 DAG 一致性由内核在注册时校验(这里拿不到全图)。 func ValidateManifest(m Manifest) error { if m.Name == "" { return fmt.Errorf("插件名为空") } if _, err := semver.NewVersion(m.Version); err != nil { return fmt.Errorf("插件 %s 版本号 %q 非合法 semver: %w", m.Name, m.Version, err) } for _, d := range m.Dependencies { if d.Name == "" { return fmt.Errorf("插件 %s 有一条依赖名为空", m.Name) } if _, err := semver.NewConstraint(d.VersionConstraint); err != nil { return fmt.Errorf("插件 %s 依赖 %s 的约束 %q 非法: %w", m.Name, d.Name, d.VersionConstraint, err) } } return nil } // toProto 把 SDK 的 Manifest 转成 GetManifest 响应。 func (m Manifest) toProto() *contractv1.GetManifestResponse { deps := make([]*contractv1.Dependency, 0, len(m.Dependencies)) for _, d := range m.Dependencies { deps = append(deps, &contractv1.Dependency{ Name: d.Name, VersionConstraint: d.VersionConstraint, }) } caps := make([]*contractv1.Capability, 0, len(m.Capabilities)) for _, c := range m.Capabilities { caps = append(caps, &contractv1.Capability{ServiceName: c}) } return &contractv1.GetManifestResponse{ Name: m.Name, Version: m.Version, Tier: m.Tier, Deps: deps, Caps: caps, } }