agent/pkg/lib/lib.go
Snider a0dc9c32e7 refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package

All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli

Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00

236 lines
5.2 KiB
Go

// SPDX-License-Identifier: EUPL-1.2
// Package lib provides embedded content for agent dispatch.
// Prompts, tasks, flows, personas, and workspace templates.
//
// Structure:
//
// prompt/ — System prompts (HOW to work)
// task/ — Structured task plans (WHAT to do)
// task/code/ — Code-specific tasks (review, refactor, etc.)
// flow/ — Build/release workflows per language/tool
// persona/ — Domain/role system prompts (WHO you are)
// workspace/ — Agent workspace templates (WHERE to work)
//
// Usage:
//
// prompt, _ := lib.Prompt("coding")
// task, _ := lib.Task("code/review")
// persona, _ := lib.Persona("secops/developer")
// flow, _ := lib.Flow("go")
// lib.ExtractWorkspace("default", "/tmp/ws", data)
package lib
import (
"bytes"
"embed"
"io/fs"
"os"
"path/filepath"
"text/template"
core "dappco.re/go/core"
)
//go:embed prompt/*.md
var promptFS embed.FS
//go:embed all:task
var taskFS embed.FS
//go:embed flow/*.md
var flowFS embed.FS
//go:embed persona
var personaFS embed.FS
//go:embed all:workspace
var workspaceFS embed.FS
// --- Prompts ---
// Template tries Prompt then Task (backwards compat).
func Template(slug string) (string, error) {
if content, err := Prompt(slug); err == nil {
return content, nil
}
return Task(slug)
}
func Prompt(slug string) (string, error) {
data, err := promptFS.ReadFile("prompt/" + slug + ".md")
if err != nil {
return "", err
}
return string(data), nil
}
func Task(slug string) (string, error) {
for _, ext := range []string{".md", ".yaml", ".yml"} {
data, err := taskFS.ReadFile("task/" + slug + ext)
if err == nil {
return string(data), nil
}
}
return "", fs.ErrNotExist
}
func TaskBundle(slug string) (string, map[string]string, error) {
main, err := Task(slug)
if err != nil {
return "", nil, err
}
bundleDir := "task/" + slug
entries, err := fs.ReadDir(taskFS, bundleDir)
if err != nil {
return main, nil, nil
}
bundle := make(map[string]string)
for _, e := range entries {
if e.IsDir() {
continue
}
data, err := taskFS.ReadFile(bundleDir + "/" + e.Name())
if err == nil {
bundle[e.Name()] = string(data)
}
}
return main, bundle, nil
}
func Flow(slug string) (string, error) {
data, err := flowFS.ReadFile("flow/" + slug + ".md")
if err != nil {
return "", err
}
return string(data), nil
}
func Persona(path string) (string, error) {
data, err := personaFS.ReadFile("persona/" + path + ".md")
if err != nil {
return "", err
}
return string(data), nil
}
// --- Workspace Templates ---
// WorkspaceData is the data passed to workspace templates.
type WorkspaceData struct {
Repo string
Branch string
Task string
Agent string
Language string
Prompt string
Persona string
Flow string
Context string
Recent string
Dependencies string
Conventions string
RepoDescription string
BuildCmd string
TestCmd string
}
// ExtractWorkspace creates an agent workspace from a template.
// Template names: "default", "security", "review".
func ExtractWorkspace(tmplName, targetDir string, data *WorkspaceData) error {
wsDir := "workspace/" + tmplName
entries, err := fs.ReadDir(workspaceFS, wsDir)
if err != nil {
return err
}
if err := os.MkdirAll(targetDir, 0755); err != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
content, err := fs.ReadFile(workspaceFS, wsDir+"/"+name)
if err != nil {
return err
}
// Process .tmpl files through text/template
outputName := name
if core.HasSuffix(name, ".tmpl") {
outputName = core.TrimSuffix(name, ".tmpl")
tmpl, err := template.New(name).Parse(string(content))
if err != nil {
return err
}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
return err
}
content = buf.Bytes()
}
if err := os.WriteFile(filepath.Join(targetDir, outputName), content, 0644); err != nil {
return err
}
}
return nil
}
// --- List Functions ---
func ListPrompts() []string { return listDir(promptFS, "prompt") }
func ListFlows() []string { return listDir(flowFS, "flow") }
func ListWorkspaces() []string { return listDir(workspaceFS, "workspace") }
func ListTasks() []string {
var slugs []string
fs.WalkDir(taskFS, "task", func(path string, d fs.DirEntry, err error) error {
if err != nil || d.IsDir() {
return nil
}
rel := core.TrimPrefix(path, "task/")
ext := filepath.Ext(rel)
slugs = append(slugs, core.TrimSuffix(rel, ext))
return nil
})
return slugs
}
func ListPersonas() []string {
var paths []string
fs.WalkDir(personaFS, "persona", func(path string, d fs.DirEntry, err error) error {
if err != nil || d.IsDir() {
return nil
}
if core.HasSuffix(path, ".md") {
rel := core.TrimPrefix(path, "persona/")
rel = core.TrimSuffix(rel, ".md")
paths = append(paths, rel)
}
return nil
})
return paths
}
func listDir(fsys embed.FS, dir string) []string {
entries, err := fsys.ReadDir(dir)
if err != nil {
return nil
}
var slugs []string
for _, e := range entries {
name := e.Name()
if e.IsDir() {
slugs = append(slugs, name)
continue
}
slugs = append(slugs, core.TrimSuffix(name, filepath.Ext(name)))
}
return slugs
}