Cletus plugin kit: rules for coding agents, specification, host API, style guide, worker SDK and cletus-plugin tool
This commit is contained in:
commit
9b19d3a8be
41 files changed
+4121
No files matched your search
@@ -0,0 +1,115 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
"git.eidonix.com/eidonix/cletus-plugins/sdk/manifest"
|
||||
)
|
||||
|
||||
//go:embed all:template
|
||||
var templateFS embed.FS
|
||||
|
||||
const sdkModule = "git.eidonix.com/eidonix/cletus-plugins/sdk"
|
||||
|
||||
type templateData struct {
|
||||
ID, Publisher, Name, Title, Short, Module, SDKModule, SDKVersion string
|
||||
}
|
||||
|
||||
func runNew(args []string) error {
|
||||
fs := flag.NewFlagSet("new", flag.ContinueOnError)
|
||||
sdkDir := fs.String("sdk-dir", "", "use a local copy of the SDK (for developing the SDK itself)")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
if fs.NArg() < 1 || fs.NArg() > 2 {
|
||||
return errors.New("usage: cletus-plugin new <publisher>.<name> [folder]")
|
||||
}
|
||||
id := fs.Arg(0)
|
||||
probe := manifest.Plugin{ID: id, Name: "x", Description: "x", Version: "0.1.0", MinAppVersion: "0.5.0", HostAPI: manifest.HostAPI}
|
||||
if errs := probe.Validate(); len(errs) > 0 {
|
||||
return errs[0]
|
||||
}
|
||||
publisher, name, _ := strings.Cut(id, ".")
|
||||
dir := name
|
||||
if fs.NArg() == 2 {
|
||||
dir = fs.Arg(1)
|
||||
}
|
||||
if _, err := os.Stat(dir); err == nil {
|
||||
return fmt.Errorf("%s already exists", dir)
|
||||
}
|
||||
data := templateData{ID: id, Publisher: publisher, Name: name, Title: title(name),
|
||||
Short: strings.ReplaceAll(name, "-", "_"), Module: publisher + ".plugins/" + name,
|
||||
SDKModule: sdkModule, SDKVersion: sdkVersion}
|
||||
if err := writeTemplate(dir, data); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Created %s in %s.\n", id, dir)
|
||||
|
||||
if *sdkDir != "" {
|
||||
abs, err := filepath.Abs(*sdkDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Only for developing the SDK: check refuses replace directives.
|
||||
if out, err := goRun(dir, goEnv("", ""), "mod", "edit", "-replace", sdkModule+"="+abs); err != nil {
|
||||
return fmt.Errorf("go mod edit: %s", out)
|
||||
}
|
||||
}
|
||||
for _, step := range [][]string{{"mod", "tidy"}, {"mod", "vendor"}} {
|
||||
if out, err := goRun(dir, goEnv("", ""), step...); err != nil {
|
||||
return fmt.Errorf("go %s failed. Fix the problem below and run it in %s yourself:\n%s", strings.Join(step, " "), dir, out)
|
||||
}
|
||||
}
|
||||
fmt.Printf("\nNext:\n cd %s\n cletus-plugin check\n cletus-plugin run tools\n cletus-plugin run invoke %s_count_lines '{\"path\":\"sample.txt\"}'\n", dir, data.Short)
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeTemplate(dir string, data templateData) error {
|
||||
return fs.WalkDir(templateFS, "template", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil || d.IsDir() {
|
||||
return err
|
||||
}
|
||||
rel := strings.TrimPrefix(path, "template/")
|
||||
rel = strings.TrimSuffix(rel, ".tmpl")
|
||||
rel = strings.ReplaceAll(rel, "_dot_", ".")
|
||||
src, err := templateFS.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t, err := template.New(rel).Delims("[[", "]]").Parse(string(src))
|
||||
if err != nil {
|
||||
return fmt.Errorf("template %s: %w", rel, err)
|
||||
}
|
||||
var out bytes.Buffer
|
||||
if err := t.Execute(&out, data); err != nil {
|
||||
return fmt.Errorf("template %s: %w", rel, err)
|
||||
}
|
||||
dst := filepath.Join(dir, filepath.FromSlash(rel))
|
||||
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(dst, out.Bytes(), 0o644)
|
||||
})
|
||||
}
|
||||
|
||||
func title(name string) string {
|
||||
words := strings.Split(name, "-")
|
||||
for i, w := range words {
|
||||
if w != "" {
|
||||
r := []rune(w)
|
||||
r[0] = unicode.ToUpper(r[0])
|
||||
words[i] = string(r)
|
||||
}
|
||||
}
|
||||
return strings.Join(words, " ")
|
||||
}
|
||||
Reference in new issue
Block a user