mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-13 05:37:29 +08:00
135 lines
3.2 KiB
Go
135 lines
3.2 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/YspCoder/clawgo/pkg/logger"
|
|
)
|
|
|
|
type ToolRegistry struct {
|
|
tools map[string]Tool
|
|
mu sync.RWMutex
|
|
snapshot atomic.Value // map[string]Tool (copy-on-write)
|
|
}
|
|
|
|
func NewToolRegistry() *ToolRegistry {
|
|
r := &ToolRegistry{tools: make(map[string]Tool)}
|
|
r.snapshot.Store(map[string]Tool{})
|
|
return r
|
|
}
|
|
|
|
func (r *ToolRegistry) Register(tool Tool) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.tools[tool.Name()] = tool
|
|
next := make(map[string]Tool, len(r.tools))
|
|
for k, v := range r.tools {
|
|
next[k] = v
|
|
}
|
|
r.snapshot.Store(next)
|
|
}
|
|
|
|
func (r *ToolRegistry) Get(name string) (Tool, bool) {
|
|
cur, _ := r.snapshot.Load().(map[string]Tool)
|
|
tool, ok := cur[name]
|
|
return tool, ok
|
|
}
|
|
|
|
func (r *ToolRegistry) Execute(ctx context.Context, name string, args map[string]interface{}) (string, error) {
|
|
logger.InfoCF("tool", logger.C0164,
|
|
map[string]interface{}{
|
|
"tool": name,
|
|
"args": args,
|
|
})
|
|
|
|
tool, ok := r.Get(name)
|
|
if !ok {
|
|
logger.ErrorCF("tool", logger.C0165,
|
|
map[string]interface{}{
|
|
"tool": name,
|
|
})
|
|
return "", fmt.Errorf("tool '%s' not found", name)
|
|
}
|
|
|
|
start := time.Now()
|
|
result, err := tool.Execute(ctx, args)
|
|
duration := time.Since(start)
|
|
|
|
if err != nil {
|
|
logger.ErrorCF("tool", logger.C0166,
|
|
map[string]interface{}{
|
|
"tool": name,
|
|
"duration": duration.Milliseconds(),
|
|
logger.FieldError: err.Error(),
|
|
})
|
|
} else {
|
|
logger.InfoCF("tool", logger.C0167,
|
|
map[string]interface{}{
|
|
"tool": name,
|
|
"duration_ms": duration.Milliseconds(),
|
|
logger.FieldOutputContentLength: len(result),
|
|
})
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (r *ToolRegistry) GetDefinitions() []map[string]interface{} {
|
|
cur, _ := r.snapshot.Load().(map[string]Tool)
|
|
definitions := make([]map[string]interface{}, 0, len(cur))
|
|
for _, tool := range cur {
|
|
definitions = append(definitions, ToolToSchema(tool))
|
|
}
|
|
return definitions
|
|
}
|
|
|
|
func (r *ToolRegistry) Catalog() []map[string]interface{} {
|
|
cur, _ := r.snapshot.Load().(map[string]Tool)
|
|
items := make([]map[string]interface{}, 0, len(cur))
|
|
for _, tool := range cur {
|
|
item := map[string]interface{}{
|
|
"name": tool.Name(),
|
|
"description": tool.Description(),
|
|
"parameters": tool.Parameters(),
|
|
}
|
|
if ct, ok := tool.(CatalogTool); ok {
|
|
for k, v := range ct.CatalogEntry() {
|
|
item[k] = v
|
|
}
|
|
}
|
|
items = append(items, item)
|
|
}
|
|
return items
|
|
}
|
|
|
|
// List returns a list of all registered tool names.
|
|
func (r *ToolRegistry) List() []string {
|
|
cur, _ := r.snapshot.Load().(map[string]Tool)
|
|
names := make([]string, 0, len(cur))
|
|
for name := range cur {
|
|
names = append(names, name)
|
|
}
|
|
return names
|
|
}
|
|
|
|
// Count returns the number of registered tools.
|
|
func (r *ToolRegistry) Count() int {
|
|
cur, _ := r.snapshot.Load().(map[string]Tool)
|
|
return len(cur)
|
|
}
|
|
|
|
// GetSummaries returns human-readable summaries of all registered tools.
|
|
// Returns a slice of "name - description" strings.
|
|
func (r *ToolRegistry) GetSummaries() []string {
|
|
cur, _ := r.snapshot.Load().(map[string]Tool)
|
|
summaries := make([]string, 0, len(cur))
|
|
for _, tool := range cur {
|
|
summaries = append(summaries, fmt.Sprintf("- `%s` - %s", tool.Name(), tool.Description()))
|
|
}
|
|
return summaries
|
|
}
|