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>
236 lines
5.2 KiB
Go
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
|
|
}
|