internal/catalog/catalog.go
Rama main · réplica de lectura del repositorio original.
package catalog
import (
"os"
"path/filepath"
"regexp"
"sort"
"strings"
)
var (
toolNamePattern = regexp.MustCompile(`Name:\s*(?:toolcontract\.)?([A-Za-z0-9_".]+)`)
toolDescription = regexp.MustCompile(`Description:\s*"((?:[^"\\]|\\.)*)"`)
toolDefinition = regexp.MustCompile(`(?s)toolcontract\.ToolDefinition\{(.*?)\n\t*\}`)
)
type ToolEntry struct {
Name string
Source string
DescriptionBytes int
}
func Tools(sourceRoot string) ([]ToolEntry, error) {
entries := []ToolEntry{}
errorValue := walkSourceFiles(sourceRoot, func(path string, source string) {
for _, definition := range toolDefinition.FindAllStringSubmatch(source, -1) {
name := toolNamePattern.FindStringSubmatch(definition[1])
if name == nil {
continue
}
descriptionBytes := 0
if description := toolDescription.FindStringSubmatch(definition[1]); description != nil {
descriptionBytes = len(description[1])
}
entries = append(entries, ToolEntry{
Name: toolCatalogName(name[1]),
Source: filepath.Base(path),
DescriptionBytes: descriptionBytes,
})
}
})
if errorValue != nil {
return nil, errorValue
}
sort.Slice(entries, func(left int, right int) bool { return entries[left].Name < entries[right].Name })
return entries, nil
}
// A descriptor whose name is only known at runtime has no name to print, and printing
// the expression that produces it would read as a tool nobody can call.
func toolCatalogName(nameExpression string) string {
if strings.HasPrefix(nameExpression, `"`) {
return strings.Trim(nameExpression, `"`)
}
if strings.Contains(nameExpression, "toolDescriptor") {
return "(named by the device catalog)"
}
return nameExpression
}
func walkSourceFiles(sourceRoot string, visit func(path string, source string)) error {
return filepath.Walk(sourceRoot, func(path string, info os.FileInfo, walkError error) error {
if walkError != nil || info.IsDir() || !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") {
return walkError
}
source, readError := os.ReadFile(path)
if readError != nil {
return readError
}
visit(path, string(source))
return nil
})
}