env: add OLLIE_AGENTS_PATH with colon-separated multi-dir resolution

This commit is contained in:
Levi Neely 2026-05-08 13:01:04 +02:00
parent 0041fc77ec
commit a2b6adb6cf
5 changed files with 39 additions and 15 deletions

View File

@ -131,26 +131,32 @@ func (s *agent) handleCommand(ctx context.Context, input string, handler EventHa
},
"/agents": func(args []string) {
entries, err := os.ReadDir(s.agentsDir)
if err != nil {
handler(infoEvent(fmt.Sprintf("agents: %v", err)))
return
}
seen := make(map[string]bool)
found := false
for _, e := range entries {
if e.IsDir() || !strings.HasSuffix(e.Name(), ".json") {
for _, dir := range AgentsDirs() {
entries, err := os.ReadDir(dir)
if err != nil {
continue
}
name := strings.TrimSuffix(e.Name(), ".json")
marker := " "
if name == s.agentName {
marker = "* "
for _, e := range entries {
if e.IsDir() || !strings.HasSuffix(e.Name(), ".json") {
continue
}
name := strings.TrimSuffix(e.Name(), ".json")
if seen[name] {
continue
}
seen[name] = true
marker := " "
if name == s.agentName {
marker = "* "
}
handler(infoEvent(marker + name))
found = true
}
handler(infoEvent(marker + name))
found = true
}
if !found {
handler(infoEvent("no agents found in " + s.agentsDir))
handler(infoEvent("no agents found"))
}
},

View File

@ -137,9 +137,24 @@ func PromptsDirs() []string {
return []string{DefaultPromptsDir()}
}
// AgentsDirs returns all agent directories from OLLIE_AGENTS_PATH (colon-separated).
func AgentsDirs() []string {
if p := os.Getenv("OLLIE_AGENTS_PATH"); p != "" {
return strings.Split(p, ":")
}
return []string{paths.CfgDir() + "/agents"}
}
// AgentConfigPath resolves the config file path for a named agent.
// It searches all directories in OLLIE_AGENTS_PATH, falling back to agentsDir.
func AgentConfigPath(agentsDir, name string) string {
for _, dir := range AgentsDirs() {
p := dir + "/" + name + ".json"
if _, err := os.Stat(p); err == nil {
return p
}
}
return agentsDir + "/" + name + ".json"
}

View File

@ -1405,6 +1405,7 @@ func TestCommand_SP(t *testing.T) {
func TestCommand_Agents_List(t *testing.T) {
c := newCore(t, nil, nil)
t.Setenv("OLLIE_AGENTS_PATH", c.agentsDir)
if err := os.WriteFile(c.agentsDir+"/myagent.json", []byte(`{}`), 0600); err != nil {
t.Fatal(err)
}

2
pkg/env/env.go vendored
View File

@ -14,6 +14,7 @@ import (
var managed = []string{
"OLLIE",
"OLLIE_TOOLS_PATH",
"OLLIE_AGENTS_PATH",
"OLLIE_SKILLS_PATH",
"OLLIE_PROMPTS_PATH",
"OLLIE_MEMORY_PATH",
@ -35,6 +36,7 @@ func EnsureDefaults() {
defaults := map[string]string{
"OLLIE": filepath.Join(home, "mnt", "ollie"),
"OLLIE_TOOLS_PATH": filepath.Join(home, ".config", "ollie", "tools"),
"OLLIE_AGENTS_PATH": filepath.Join(home, ".config", "ollie", "agents"),
"OLLIE_SKILLS_PATH": filepath.Join(home, ".config", "ollie", "skills"),
"OLLIE_PROMPTS_PATH": filepath.Join(home, ".config", "ollie", "prompts"),
"OLLIE_MEMORY_PATH": filepath.Join(home, ".config", "ollie", "memory"),

2
pkg/env/env_test.go vendored
View File

@ -13,7 +13,7 @@ func TestEnsureDefaults(t *testing.T) {
os.Unsetenv(k)
}
EnsureDefaults()
for _, k := range []string{"OLLIE", "OLLIE_TOOLS_PATH", "OLLIE_SKILLS_PATH", "OLLIE_PROMPTS_PATH", "OLLIE_MEMORY_PATH", "OLLIE_TMP_PATH", "OLLIE_TRANSCRIPT_PATH"} {
for _, k := range []string{"OLLIE", "OLLIE_TOOLS_PATH", "OLLIE_AGENTS_PATH", "OLLIE_SKILLS_PATH", "OLLIE_PROMPTS_PATH", "OLLIE_MEMORY_PATH", "OLLIE_TMP_PATH", "OLLIE_TRANSCRIPT_PATH"} {
if v := os.Getenv(k); v == "" {
t.Errorf("%s not set after EnsureDefaults", k)
}