Remove OLLIE_*_PATH env vars: paths follow ~/.config/ollie/ convention

- Stripped OLLIE_TOOLS_PATH, OLLIE_AGENTS_PATH, OLLIE_SKILLS_PATH,
  OLLIE_PROMPTS_PATH, OLLIE_MEMORY_PATH, OLLIE_TMP_PATH from managed
  list and defaults in env.go
- ToolsPath(), SkillsPath(), PromptsDirs(), AgentsDirs(), ollieTmpDir()
  now derive from paths.CfgDir()/paths.DataDir() directly
- Removed shell-exec fallback from resolveExecPrompt() — only file
  resolution remains
- Cleaned up env_test.go to match reduced managed set
- Updated stale comments referencing /home/lkn/.config/ollie/tools
This commit is contained in:
Ollie Agent 2026-08-05 19:37:13 +02:00
parent 5206f26fc6
commit 2bd6d6f66a
8 changed files with 21 additions and 77 deletions

View File

@ -2,7 +2,6 @@ package agent
import (
"os"
"strings"
"ollie/paths"
)
@ -12,24 +11,17 @@ func DefaultPromptsDir() string {
return paths.CfgDir() + "/prompts"
}
// PromptsDirs returns all prompt directories from OLLIE_PROMPTS_PATH (colon-separated).
// PromptsDirs returns all prompt directories. Currently just the default.
func PromptsDirs() []string {
if p := os.Getenv("OLLIE_PROMPTS_PATH"); p != "" {
return strings.Split(p, ":")
}
return []string{DefaultPromptsDir()}
}
// AgentsDirs returns all agent directories from OLLIE_AGENTS_PATH (colon-separated).
// AgentsDirs returns all agent directories. Currently just the default.
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"

View File

@ -76,42 +76,24 @@ func resolveExecPrompt(cmds []string, cwd string, env []string) (string, error)
continue
}
// Try resolving as a prompt file first.
if content, ok := resolvePromptFile(entry, envMap, expand); ok {
if content, ok := resolvePromptFile(entry, expand); ok {
if content != "" {
parts = append(parts, content)
}
continue
}
// Fall back to shell execution.
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
cmd := exec.CommandContext(ctx, "sh", "-c", entry)
if cwd != "" {
if info, err := os.Stat(cwd); err == nil && info.IsDir() {
cmd.Dir = cwd
}
}
cmd.Env = fullEnv
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
cancel()
if err != nil {
return "", fmt.Errorf("prompt command %q failed: %v: %s", entry, err, stderr.String())
}
if out := strings.TrimRight(stdout.String(), "\n"); out != "" {
parts = append(parts, out)
}
// Not a prompt file — skip.
continue
}
return strings.Join(parts, "\n"), nil
}
// resolvePromptFile attempts to resolve entry as a prompt file.
// It first checks if the entry (after env expansion) is an absolute path to an
// existing file. Otherwise it searches OLLIE_PROMPTS_PATH directories for
// existing file. Otherwise it searches the default prompts directory for
// entry and entry.md. Returns the file content (with env vars expanded) and
// true if found.
func resolvePromptFile(entry string, envMap map[string]string, expand func(string) string) (string, bool) {
func resolvePromptFile(entry string, expand func(string) string) (string, bool) {
expanded := expand(entry)
// If it contains shell metacharacters, it's a command, not a file name.
@ -131,12 +113,8 @@ func resolvePromptFile(entry string, envMap map[string]string, expand func(strin
return "", false
}
// Search OLLIE_PROMPTS_PATH.
promptsPath := envMap["OLLIE_PROMPTS_PATH"]
if promptsPath == "" {
return "", false
}
for _, dir := range filepath.SplitList(promptsPath) {
// Search the default prompts directory.
for _, dir := range PromptsDirs() {
if dir == "" {
continue
}

16
env/env.go vendored
View File

@ -16,12 +16,6 @@ import (
// managed is the ordered list of env vars that ollie exposes to frontends.
var managed = []string{
"OLLIE_CFG_PATH",
"OLLIE_TOOLS_PATH",
"OLLIE_AGENTS_PATH",
"OLLIE_SKILLS_PATH",
"OLLIE_PROMPTS_PATH",
"OLLIE_MEMORY_PATH",
"OLLIE_TMP_PATH",
"OLLIE_ELEVATE_SOCKET",
}
@ -35,14 +29,8 @@ func EnsureDefaults() {
xdgRuntime = fmt.Sprintf("/run/user/%d", os.Getuid())
}
defaults := map[string]string{
"OLLIE_CFG_PATH": filepath.Join(home, ".config", "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"),
"OLLIE_TMP_PATH": filepath.Join(home, ".local", "share", "ollie", "tmp"),
"OLLIE_ELEVATE_SOCKET": filepath.Join(xdgRuntime, "ollie", "elevate.sock"),
"OLLIE_CFG_PATH": filepath.Join(home, ".config", "ollie"),
"OLLIE_ELEVATE_SOCKET": filepath.Join(xdgRuntime, "ollie", "elevate.sock"),
}
for k, v := range defaults {
if os.Getenv(k) == "" {

6
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_TOOLS_PATH", "OLLIE_AGENTS_PATH", "OLLIE_SKILLS_PATH", "OLLIE_PROMPTS_PATH", "OLLIE_MEMORY_PATH", "OLLIE_TMP_PATH"} {
for _, k := range []string{"OLLIE_CFG_PATH", "OLLIE_ELEVATE_SOCKET"} {
if v := os.Getenv(k); v == "" {
t.Errorf("%s not set after EnsureDefaults", k)
}
@ -45,9 +45,9 @@ func TestAll(t *testing.T) {
}
func TestFormat(t *testing.T) {
t.Setenv("OLLIE_TMP_PATH", "/tmp/test-fmt")
t.Setenv("OLLIE_CFG_PATH", "/tmp/test-fmt")
out := string(Format())
if !strings.Contains(out, "OLLIE_TMP_PATH=/tmp/test-fmt") {
if !strings.Contains(out, "OLLIE_CFG_PATH=/tmp/test-fmt") {
t.Errorf("Format() missing expected var, got:\n%s", out)
}
// Every line should be NAME=VALUE\n

View File

@ -110,10 +110,7 @@ func NextUncheckedStep(data []byte) string {
var sweepTmpOnce sync.Once
func ollieTmpDir() string {
if p := os.Getenv("OLLIE_TMP_PATH"); p != "" {
return p
}
return filepath.Join(os.TempDir(), "ollie")
return filepath.Join(paths.DataDir(), "tmp")
}
func sweepStaleTmpDirs() {

View File

@ -9,16 +9,13 @@ import (
"sort"
"strings"
"sync"
"ollie/paths"
)
// SkillsPath returns the directory to search for skill modules.
// Resolved from OLLIE_SKILLS_PATH, then ~/.config/ollie/skills.
// SkillsPath returns ~/.config/ollie/skills.
func SkillsPath() string {
if p := os.Getenv("OLLIE_SKILLS_PATH"); p != "" {
return p
}
home, _ := os.UserHomeDir()
return home + "/.config/ollie/skills"
return paths.CfgDir() + "/skills"
}
// SkillInfo describes an available skill module.

View File

@ -9,16 +9,8 @@ import (
"ollie/paths"
)
// ToolsPath returns the directory to search for named tool scripts.
// Resolved in order: first entry of OLLIE_TOOLS_PATH (colon-separated),
// then ~/.config/ollie/tools.
// ToolsPath returns ~/.config/ollie/tools.
func ToolsPath() string {
if p := os.Getenv("OLLIE_TOOLS_PATH"); p != "" {
if i := strings.Index(p, ":"); i >= 0 {
p = p[:i]
}
return p
}
return paths.CfgDir() + "/tools"
}

View File

@ -188,7 +188,7 @@ func ToolInfoFromMeta(name string, m *MetaFile) ToolInfo {
// ResolveTool returns the executable path for a named tool.
// Resolution order:
// 1. $OLLIE_TOOLS_PATH/<name> (local wrapper wins over system binary)
// 1. ~/.config/ollie/tools/<name> (local wrapper wins over system binary)
// 2. .meta "cmd" field (after variant resolution; absolute path or bare name via $PATH)
// 3. exec.LookPath(<name>) as final fallback
func ResolveTool(name string) (string, error) {