p9: add configstore, move skills filesystem ops from core
- configstore.go: loadAgentConfig helper for agent config loading - skillstore.go: absorbed List/Read/Dirs from skills package - Removed unused config imports from batchstore/server
This commit is contained in:
parent
2ac8ca8639
commit
e031d2ba90
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
"ollie/pkg/agent"
|
||||
"ollie/pkg/backend"
|
||||
"ollie/pkg/config"
|
||||
"ollie/pkg/tools"
|
||||
"ollie/pkg/tools/execute"
|
||||
)
|
||||
|
|
@ -282,8 +281,7 @@ func (s *BatchStore) executeJob(ctx context.Context, job *batchJob) (string, err
|
|||
be.SetModel(modelName)
|
||||
}
|
||||
|
||||
cfgPath := agent.AgentConfigPath(s.srv.agentsDir, agentName)
|
||||
cfg, _ := config.Load(cfgPath)
|
||||
cfg := loadAgentConfig(s.srv.agentsDir, agentName)
|
||||
|
||||
newDisp := tools.NewDispatcherFunc(map[string]func() tools.Server{
|
||||
"execute": execute.Decl(cwd),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package p9
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"ollie/pkg/agent"
|
||||
"ollie/pkg/config"
|
||||
)
|
||||
|
||||
// loadAgentConfig resolves and loads the config for a named agent.
|
||||
// Returns nil (not an error) if the config file does not exist;
|
||||
// BuildAgentEnv handles nil configs.
|
||||
func loadAgentConfig(agentsDir, name string) *config.Config {
|
||||
f, err := os.Open(agent.AgentConfigPath(agentsDir, name))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer f.Close()
|
||||
cfg, _ := config.Load(f)
|
||||
return cfg
|
||||
}
|
||||
|
|
@ -46,7 +46,6 @@ import (
|
|||
|
||||
"ollie/pkg/agent"
|
||||
"ollie/pkg/backend"
|
||||
"ollie/pkg/config"
|
||||
olog "ollie/pkg/log"
|
||||
"ollie/pkg/paths"
|
||||
"ollie/pkg/tools"
|
||||
|
|
@ -1236,8 +1235,7 @@ func (s *Server) createSession(args []string) error {
|
|||
return fmt.Errorf("sessions dir: %w", err)
|
||||
}
|
||||
|
||||
cfgPath := agent.AgentConfigPath(s.agentsDir, agentName)
|
||||
cfg, _ := config.Load(cfgPath) // nil cfg is handled by BuildAgentEnv
|
||||
cfg := loadAgentConfig(s.agentsDir, agentName)
|
||||
|
||||
newDisp := tools.NewDispatcherFunc(map[string]func() tools.Server{
|
||||
"execute": execute.Decl(cwd),
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"ollie/pkg/paths"
|
||||
"ollie/pkg/skills"
|
||||
)
|
||||
|
||||
|
|
@ -19,12 +21,63 @@ func NewSkillStore() *SkillStore {
|
|||
return &SkillStore{}
|
||||
}
|
||||
|
||||
// skillDirs returns the skill directories from OLLIE_SKILLS_PATH,
|
||||
// falling back to the default skills directory.
|
||||
func skillDirs() []string {
|
||||
if env := os.Getenv("OLLIE_SKILLS_PATH"); env != "" {
|
||||
return strings.Split(env, ":")
|
||||
}
|
||||
return []string{paths.CfgDir() + "/skills"}
|
||||
}
|
||||
|
||||
// listSkills scans all skill directories and returns deduplicated metadata.
|
||||
// First occurrence by directory order wins on name collision.
|
||||
func listSkills() []skills.Meta {
|
||||
seen := make(map[string]bool)
|
||||
var result []skills.Meta
|
||||
for _, dir := range skillDirs() {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, e := range entries {
|
||||
if !e.IsDir() || seen[e.Name()] {
|
||||
continue
|
||||
}
|
||||
skillDir := filepath.Join(dir, e.Name())
|
||||
f, err := os.Open(filepath.Join(skillDir, "SKILL.md"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
meta, err := skills.ParseFrontMatter(f, filepath.Base(skillDir), skillDir)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
seen[meta.Name] = true
|
||||
result = append(result, *meta)
|
||||
}
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool { return result[i].Name < result[j].Name })
|
||||
return result
|
||||
}
|
||||
|
||||
// readSkill returns the SKILL.md content for the named skill.
|
||||
func readSkill(name string) ([]byte, error) {
|
||||
for _, m := range listSkills() {
|
||||
if m.Name == name {
|
||||
return os.ReadFile(filepath.Join(m.Dir, "SKILL.md"))
|
||||
}
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
func (s *SkillStore) Stat(name string) (os.FileInfo, error) {
|
||||
if name == "idx" {
|
||||
return &syntheticFileInfo{name: "idx", mode: 0444}, nil
|
||||
}
|
||||
skillName := strings.TrimSuffix(name, ".md")
|
||||
if _, err := skills.Read(skillName); err != nil {
|
||||
if _, err := readSkill(skillName); err != nil {
|
||||
return nil, fmt.Errorf("%s: not found", name)
|
||||
}
|
||||
return &syntheticFileInfo{name: name, mode: 0666}, nil
|
||||
|
|
@ -32,7 +85,7 @@ func (s *SkillStore) Stat(name string) (os.FileInfo, error) {
|
|||
|
||||
func (s *SkillStore) List() ([]os.DirEntry, error) {
|
||||
result := []os.DirEntry{syntheticEntry("idx", 0444)}
|
||||
for _, m := range skills.List() {
|
||||
for _, m := range listSkills() {
|
||||
result = append(result, syntheticEntry(m.Name+".md", 0666))
|
||||
}
|
||||
return result, nil
|
||||
|
|
@ -43,20 +96,20 @@ func (s *SkillStore) Get(name string) ([]byte, error) {
|
|||
return s.index()
|
||||
}
|
||||
skillName := strings.TrimSuffix(name, ".md")
|
||||
return skills.Read(skillName)
|
||||
return readSkill(skillName)
|
||||
}
|
||||
|
||||
func (s *SkillStore) Put(name string, data []byte) error {
|
||||
skillName := strings.TrimSuffix(name, ".md")
|
||||
dir := ""
|
||||
for _, m := range skills.List() {
|
||||
for _, m := range listSkills() {
|
||||
if m.Name == skillName {
|
||||
dir = m.Dir
|
||||
break
|
||||
}
|
||||
}
|
||||
if dir == "" {
|
||||
dir = filepath.Join(skills.Dirs()[0], skillName)
|
||||
dir = filepath.Join(skillDirs()[0], skillName)
|
||||
}
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return err
|
||||
|
|
@ -66,7 +119,7 @@ func (s *SkillStore) Put(name string, data []byte) error {
|
|||
|
||||
func (s *SkillStore) Delete(name string) error {
|
||||
skillName := strings.TrimSuffix(name, ".md")
|
||||
for _, m := range skills.List() {
|
||||
for _, m := range listSkills() {
|
||||
if m.Name == skillName {
|
||||
return os.RemoveAll(m.Dir)
|
||||
}
|
||||
|
|
@ -77,7 +130,7 @@ func (s *SkillStore) Delete(name string) error {
|
|||
func (s *SkillStore) Rename(oldName, newName string) error {
|
||||
oldSkill := strings.TrimSuffix(oldName, ".md")
|
||||
newSkill := strings.TrimSuffix(newName, ".md")
|
||||
for _, m := range skills.List() {
|
||||
for _, m := range listSkills() {
|
||||
if m.Name == oldSkill {
|
||||
newDir := filepath.Join(filepath.Dir(m.Dir), newSkill)
|
||||
return os.Rename(m.Dir, newDir)
|
||||
|
|
@ -88,7 +141,7 @@ func (s *SkillStore) Rename(oldName, newName string) error {
|
|||
|
||||
func (s *SkillStore) Create(name string) error {
|
||||
skillName := strings.TrimSuffix(name, ".md")
|
||||
dir := filepath.Join(skills.Dirs()[0], skillName)
|
||||
dir := filepath.Join(skillDirs()[0], skillName)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -97,7 +150,7 @@ func (s *SkillStore) Create(name string) error {
|
|||
|
||||
func (s *SkillStore) index() ([]byte, error) {
|
||||
var sb strings.Builder
|
||||
for _, m := range skills.List() {
|
||||
for _, m := range listSkills() {
|
||||
fmt.Fprintf(&sb, "## %s\n", m.Name)
|
||||
fmt.Fprintf(&sb, "description: %s\n", m.Description)
|
||||
sb.WriteString("\n")
|
||||
|
|
|
|||
Reference in New Issue