This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-core/toolsrv/discover.go

140 lines
3.4 KiB
Go

package toolsrv
import (
"fmt"
"os"
"path/filepath"
"strings"
"ollie/paths"
)
// ToolsPath returns the tools directory: CfgDir()/tools.
func ToolsPath() string {
return paths.ToolsDir()
}
// ExtractPrompt parses the ollie:prompt ... ollie:end block from a tool
// script's header comments. Returns the prompt text with comment prefixes
// stripped, or "" if no prompt block is found.
func ExtractPrompt(script string) string {
var lines []string
var inPrompt bool
for _, line := range strings.Split(script, "\n") {
trimmed := strings.TrimSpace(line)
// Strip comment prefix (# or //)
bare := trimmed
if strings.HasPrefix(bare, "# ") {
bare = bare[2:]
} else if strings.HasPrefix(bare, "#") {
bare = bare[1:]
} else if strings.HasPrefix(bare, "// ") {
bare = bare[3:]
} else if strings.HasPrefix(bare, "//") {
bare = bare[2:]
} else if inPrompt {
// Non-comment line while in prompt block — end of header
break
} else {
// Non-comment line before prompt block found
if trimmed != "" && !strings.HasPrefix(trimmed, "#!") {
break
}
continue
}
if strings.Contains(bare, "ollie:prompt") {
inPrompt = true
continue
}
if inPrompt && strings.Contains(bare, "ollie:end") {
break
}
if inPrompt {
lines = append(lines, bare)
}
}
if len(lines) == 0 {
return ""
}
return strings.Join(lines, "\n")
}
// DiscoverTools scans the tools directory and returns metadata for all scripts,
// including their ollie:prompt blocks and short descriptions.
func DiscoverTools() []ToolInfo {
dir := ToolsPath()
entries, err := os.ReadDir(dir)
if err != nil {
return nil
}
var infos []ToolInfo
for _, e := range entries {
if e.IsDir() || e.Name() == "idx" || strings.HasPrefix(e.Name(), ".") {
continue
}
data, err := os.ReadFile(filepath.Join(dir, e.Name()))
if err != nil {
continue
}
script := string(data)
prompt := ExtractPrompt(script)
desc := extractShortDescription(prompt)
infos = append(infos, ToolInfo{
Name: e.Name(),
Description: desc,
Prompt: prompt,
})
}
return infos
}
// extractShortDescription gets the first non-heading, non-empty line from a prompt.
func extractShortDescription(prompt string) string {
for _, line := range strings.Split(prompt, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
return line
}
return ""
}
// ExtractShortDescription is the exported version of extractShortDescription.
func ExtractShortDescription(prompt string) string {
return extractShortDescription(prompt)
}
// ToolPrompt returns the full ollie:prompt content for a named tool.
// Returns "" if the tool has no prompt or doesn't exist.
func ToolPrompt(name string) string {
if strings.Contains(name, "/") || strings.Contains(name, "..") {
return ""
}
path := filepath.Join(ToolsPath(), name)
data, err := os.ReadFile(path)
if err != nil {
return ""
}
return ExtractPrompt(string(data))
}
// ReadTool reads a named tool script from the tools directory.
func ReadTool(name string) (string, error) {
if strings.Contains(name, "/") || strings.Contains(name, "..") {
return "", fmt.Errorf("invalid tool name")
}
path := filepath.Join(ToolsPath(), name)
data, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return "", fmt.Errorf("tool not found: %s", name)
}
return "", fmt.Errorf("read tool %s: %w", name, err)
}
return string(data), nil
}