support OLLIE_PROMPTS_PATH: multi-dir prompt store via NewFlatDirUnion

This commit is contained in:
Levi Neely 2026-05-08 11:59:22 +02:00
parent 11618a7960
commit 77c20cf43d
2 changed files with 61 additions and 1 deletions

View File

@ -251,7 +251,7 @@ func New(sink *olog.Sink, opts ...ServerOption) *Server {
sink: sink,
agentsDir: agentsDir,
agentStore: NewFlatDirStore(agentsDir, 0644),
promptStore: NewFlatDirStore(agent.DefaultPromptsDir(), 0444),
promptStore: store.NewFlatDirUnion(agent.PromptsDirs(), 0444),
memStore: NewFlatDirStore(memDir, 0644),
toolStore: NewToolStore(),
utilStore: NewUtilStore(),

View File

@ -111,6 +111,66 @@ func NewFlatDir(dir string, perm os.FileMode) Store {
}
}
// NewFlatDirUnion returns a read-only Store that merges multiple directories.
// Files are deduplicated by name; the first directory containing a name wins.
func NewFlatDirUnion(dirs []string, perm os.FileMode) Store {
notBlocking := func(context.Context, string) ([]byte, error) {
return nil, fmt.Errorf("blocking read not supported")
}
resolve := func(name string) (string, error) {
for _, dir := range dirs {
p := filepath.Join(dir, name)
if _, err := os.Stat(p); err == nil {
return p, nil
}
}
return "", fmt.Errorf("%s: not found", name)
}
return &storeConfig{
StatFn: func(name string) (os.FileInfo, error) {
p, err := resolve(name)
if err != nil {
return nil, err
}
return os.Stat(p)
},
ListFn: func() ([]os.DirEntry, error) {
seen := make(map[string]bool)
var result []os.DirEntry
for _, dir := range dirs {
entries, err := os.ReadDir(dir)
if err != nil {
continue
}
for _, e := range entries {
if !seen[e.Name()] {
seen[e.Name()] = true
result = append(result, e)
}
}
}
return result, nil
},
OpenFn: func(name string) (StoreEntry, error) {
p, err := resolve(name)
if err != nil {
return nil, err
}
return &EntryConfig{
StatFn: func() (os.FileInfo, error) { return os.Stat(p) },
ReadFn: func() ([]byte, error) { return os.ReadFile(p) },
WriteFn: func([]byte) error { return fmt.Errorf("%s: read-only", name) },
BlockingReadFn: notBlocking,
}, nil
},
CreateFn: func(string) error { return fmt.Errorf("read-only store") },
DeleteFn: func(string) error { return fmt.Errorf("read-only store") },
RenameFn: func(string, string) error { return fmt.Errorf("read-only store") },
}
}
// SyntheticFileInfo implements os.FileInfo for entries with no backing file.
type SyntheticFileInfo struct {
Name_ string