skills: add registry reference check and working directory env var

- Add check for registry references without digest in loadSkillsFromRefs
- Fix IsLocalSkillPath to not treat registry refs as local paths
- Inject OLLAMA_WORKING_DIR env var so skill scripts can access the
  directory where 'ollama run' was called from
This commit is contained in:
ParthSareen 2025-12-30 14:58:05 -05:00
parent 7ff2b373f4
commit ca43de117f
2 changed files with 19 additions and 3 deletions

View File

@ -140,6 +140,13 @@ func loadSkillsFromRefs(refs []api.SkillRef) (*skillCatalog, error) {
skillDir = path skillDir = path
} else if ref.Name != "" { } else if ref.Name != "" {
// Check if this is a local path or a registry reference
if !server.IsLocalSkillPath(ref.Name) {
// Registry reference without a digest - skill needs to be pulled first
// This happens when an agent references a skill that hasn't been bundled
return nil, fmt.Errorf("skill %q is a registry reference but has no digest - the agent may need to be recreated or the skill pulled separately", ref.Name)
}
// Local path - resolve it // Local path - resolve it
skillPath := ref.Name skillPath := ref.Name
if strings.HasPrefix(skillPath, "~") { if strings.HasPrefix(skillPath, "~") {
@ -486,6 +493,14 @@ func runSkillScript(skillDir, command string) (string, error) {
cmd := exec.CommandContext(ctx, "sh", "-c", command) cmd := exec.CommandContext(ctx, "sh", "-c", command)
cmd.Dir = absSkillDir cmd.Dir = absSkillDir
// Inject the current working directory (where ollama run was called from)
// as an environment variable so scripts can reference files in that directory
workingDir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get working directory: %w", err)
}
cmd.Env = append(os.Environ(), "OLLAMA_WORKING_DIR="+workingDir)
// Capture both stdout and stderr // Capture both stdout and stderr
var stdout, stderr bytes.Buffer var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout cmd.Stdout = &stdout

View File

@ -250,13 +250,14 @@ func CreateSkillLayer(skillDir string) (Layer, error) {
} }
// IsLocalSkillPath checks if a skill reference looks like a local path. // IsLocalSkillPath checks if a skill reference looks like a local path.
// Local paths are explicitly prefixed with /, ./, ../, or ~.
// Registry references like "skill/calculator:1.0.0" should NOT be treated as local paths.
func IsLocalSkillPath(name string) bool { func IsLocalSkillPath(name string) bool {
// Local paths start with /, ./, or contain path separators // Local paths are explicitly indicated by path prefixes
return strings.HasPrefix(name, "/") || return strings.HasPrefix(name, "/") ||
strings.HasPrefix(name, "./") || strings.HasPrefix(name, "./") ||
strings.HasPrefix(name, "../") || strings.HasPrefix(name, "../") ||
strings.HasPrefix(name, "~") || strings.HasPrefix(name, "~")
strings.Contains(name, string(os.PathSeparator))
} }
// SkillNamespace is the namespace used for standalone skills in the registry. // SkillNamespace is the namespace used for standalone skills in the registry.