server: add Kind field to ModelPath for 5-part naming

Updates ModelPath struct and parsing to support the Kind field,
enabling skills and agents to use the 5-part naming structure.

- ParseModelPath detects valid kinds (skill, agent)
- GetNamespaceRepository includes kind in path
- GetManifestPath returns correct 5-part filepath
- GetFullTagname/GetShortTagname include kind when present
This commit is contained in:
ParthSareen 2025-12-29 00:12:52 -05:00
parent d4f9bd5fe5
commit 253b035b4a
1 changed files with 50 additions and 4 deletions

View File

@ -18,6 +18,7 @@ type ModelPath struct {
ProtocolScheme string ProtocolScheme string
Registry string Registry string
Namespace string Namespace string
Kind string // Optional: "skill", "agent", or empty for models
Repository string Repository string
Tag string Tag string
} }
@ -42,6 +43,7 @@ func ParseModelPath(name string) ModelPath {
ProtocolScheme: DefaultProtocolScheme, ProtocolScheme: DefaultProtocolScheme,
Registry: DefaultRegistry, Registry: DefaultRegistry,
Namespace: DefaultNamespace, Namespace: DefaultNamespace,
Kind: "",
Repository: "", Repository: "",
Tag: DefaultTag, Tag: DefaultTag,
} }
@ -55,13 +57,41 @@ func ParseModelPath(name string) ModelPath {
name = strings.ReplaceAll(name, string(os.PathSeparator), "/") name = strings.ReplaceAll(name, string(os.PathSeparator), "/")
parts := strings.Split(name, "/") parts := strings.Split(name, "/")
switch len(parts) { switch len(parts) {
case 3: case 4:
// host/namespace/kind/model or host/namespace/model:tag with kind
mp.Registry = parts[0] mp.Registry = parts[0]
mp.Namespace = parts[1] mp.Namespace = parts[1]
mp.Repository = parts[2] if model.ValidKinds[parts[2]] {
mp.Kind = parts[2]
mp.Repository = parts[3]
} else {
// Not a valid kind, treat as old format with extra part
mp.Repository = parts[3]
}
case 3:
// Could be: host/namespace/model OR namespace/kind/model
if model.ValidKinds[parts[1]] {
// namespace/kind/model
mp.Namespace = parts[0]
mp.Kind = parts[1]
mp.Repository = parts[2]
} else {
// host/namespace/model
mp.Registry = parts[0]
mp.Namespace = parts[1]
mp.Repository = parts[2]
}
case 2: case 2:
mp.Namespace = parts[0] // Could be: namespace/model OR kind/model
mp.Repository = parts[1] if model.ValidKinds[parts[0]] {
// kind/model (library skill)
mp.Kind = parts[0]
mp.Repository = parts[1]
} else {
// namespace/model
mp.Namespace = parts[0]
mp.Repository = parts[1]
}
case 1: case 1:
mp.Repository = parts[0] mp.Repository = parts[0]
} }
@ -75,20 +105,35 @@ func ParseModelPath(name string) ModelPath {
} }
func (mp ModelPath) GetNamespaceRepository() string { func (mp ModelPath) GetNamespaceRepository() string {
if mp.Kind != "" {
return fmt.Sprintf("%s/%s/%s", mp.Namespace, mp.Kind, mp.Repository)
}
return fmt.Sprintf("%s/%s", mp.Namespace, mp.Repository) return fmt.Sprintf("%s/%s", mp.Namespace, mp.Repository)
} }
func (mp ModelPath) GetFullTagname() string { func (mp ModelPath) GetFullTagname() string {
if mp.Kind != "" {
return fmt.Sprintf("%s/%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Kind, mp.Repository, mp.Tag)
}
return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag) return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
} }
func (mp ModelPath) GetShortTagname() string { func (mp ModelPath) GetShortTagname() string {
if mp.Registry == DefaultRegistry { if mp.Registry == DefaultRegistry {
if mp.Namespace == DefaultNamespace { if mp.Namespace == DefaultNamespace {
if mp.Kind != "" {
return fmt.Sprintf("%s/%s:%s", mp.Kind, mp.Repository, mp.Tag)
}
return fmt.Sprintf("%s:%s", mp.Repository, mp.Tag) return fmt.Sprintf("%s:%s", mp.Repository, mp.Tag)
} }
if mp.Kind != "" {
return fmt.Sprintf("%s/%s/%s:%s", mp.Namespace, mp.Kind, mp.Repository, mp.Tag)
}
return fmt.Sprintf("%s/%s:%s", mp.Namespace, mp.Repository, mp.Tag) return fmt.Sprintf("%s/%s:%s", mp.Namespace, mp.Repository, mp.Tag)
} }
if mp.Kind != "" {
return fmt.Sprintf("%s/%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Kind, mp.Repository, mp.Tag)
}
return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag) return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
} }
@ -97,6 +142,7 @@ func (mp ModelPath) GetManifestPath() (string, error) {
name := model.Name{ name := model.Name{
Host: mp.Registry, Host: mp.Registry,
Namespace: mp.Namespace, Namespace: mp.Namespace,
Kind: mp.Kind,
Model: mp.Repository, Model: mp.Repository,
Tag: mp.Tag, Tag: mp.Tag,
} }