Files
agent-lib/internal/target/opencode.go
T

72 lines
2.1 KiB
Go
Raw Permalink Normal View History

// Package target maps content types to runtime-specific deployment paths.
// The OpenCode target is the thin v2 implementation: a type filter plus
// path mapping, leaving the door open for future targets.
package target
import (
"os"
"path/filepath"
"strings"
"github.com/m3tam3re/agent-lib/internal/lockfile"
)
// OpenCode maps items into the OpenCode runtime layout, rooted at the
// user's home directory.
type OpenCode struct {
Home string
}
// NewOpenCode resolves the home directory once for all path mappings.
func NewOpenCode() (*OpenCode, error) {
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
return &OpenCode{Home: home}, nil
}
// DeployPath returns the absolute destination for an item; ok is false for
// types this target never deploys (MCP stays under fleet control).
func (o *OpenCode) DeployPath(typ, name string) (path string, ok bool) {
switch typ {
case lockfile.TypeSkill:
return filepath.Join(o.Home, ".agents", "skills", name), true
case lockfile.TypeCommand:
return filepath.Join(o.Home, ".config", "opencode", "commands", name+".md"), true
case lockfile.TypeAgent:
return filepath.Join(o.Home, ".config", "opencode", "agents", name+".md"), true
default:
return "", false
}
}
// ScanTargetDirs lists every item currently present in the target dirs,
// keyed "<type>/<name>" — the raw material for detecting unmanaged occupants.
func (o *OpenCode) ScanTargetDirs() map[string]bool {
out := map[string]bool{}
skillsDir := filepath.Join(o.Home, ".agents", "skills")
if entries, err := os.ReadDir(skillsDir); err == nil {
for _, e := range entries {
if e.IsDir() {
out[lockfile.TypeSkill+"/"+e.Name()] = true
}
}
}
for typ, dir := range map[string]string{
lockfile.TypeCommand: filepath.Join(o.Home, ".config", "opencode", "commands"),
lockfile.TypeAgent: filepath.Join(o.Home, ".config", "opencode", "agents"),
} {
entries, err := os.ReadDir(dir)
if err != nil {
continue
}
for _, e := range entries {
if !e.IsDir() && strings.HasSuffix(e.Name(), ".md") {
out[typ+"/"+strings.TrimSuffix(e.Name(), ".md")] = true
}
}
}
return out
}