ZovOS_AI/internal/tools/registry.go
Dan4ick 460d20539f feat: initial project structure - Phase 1 MVP
- Project infrastructure: go.mod, Makefile, .gitignore, README
- Configuration system with YAML parsing and env overrides
- Structured logging with slog
- AI provider interface with Ollama, OpenAI, Anthropic implementations
- Provider manager with runtime switching
- Agent orchestrator with ReAct loop (reason-act-observe)
- Tool registry with JSON Schema descriptions
- Terminal tool: shell command execution with safety controls
- Filesystem tools: read, write, list with path access control
- Conversation memory with session management
- Web UI server with WebSocket streaming
- Modern dark theme UI with glassmorphism, animations
- Frontend: WebSocket client, markdown rendering, tool call display
2026-03-20 00:38:22 +03:00

86 lines
2 KiB
Go

package tools
import (
"context"
"encoding/json"
"fmt"
"log/slog"
"sync"
"git.bebrik.xyz/Dan4ick/ZovOS_AI/internal/ai"
)
// ToolHandler is the function signature for tool implementations.
type ToolHandler func(ctx context.Context, args json.RawMessage) (string, error)
// ToolDef defines a tool with its metadata and handler.
type ToolDef struct {
ai.Tool
Handler ToolHandler
}
// Registry manages all available tools.
type Registry struct {
mu sync.RWMutex
tools map[string]ToolDef
log *slog.Logger
}
// NewRegistry creates a new tool registry.
func NewRegistry(log *slog.Logger) *Registry {
return &Registry{
tools: make(map[string]ToolDef),
log: log,
}
}
// Register adds a tool to the registry.
func (r *Registry) Register(def ToolDef) {
r.mu.Lock()
defer r.mu.Unlock()
r.tools[def.Name] = def
r.log.Info("registered tool", "name", def.Name)
}
// Execute runs a tool by name with the given arguments.
func (r *Registry) Execute(ctx context.Context, name string, argsJSON string) (string, error) {
r.mu.RLock()
td, ok := r.tools[name]
r.mu.RUnlock()
if !ok {
return "", fmt.Errorf("unknown tool: %s", name)
}
r.log.Info("executing tool", "name", name, "args", argsJSON)
result, err := td.Handler(ctx, json.RawMessage(argsJSON))
if err != nil {
r.log.Error("tool execution failed", "name", name, "error", err)
return fmt.Sprintf("Error: %v", err), nil // return error as result, not as Go error
}
r.log.Debug("tool result", "name", name, "result_len", len(result))
return result, nil
}
// List returns AI tool definitions for all registered tools.
func (r *Registry) List() []ai.Tool {
r.mu.RLock()
defer r.mu.RUnlock()
result := make([]ai.Tool, 0, len(r.tools))
for _, td := range r.tools {
result = append(result, td.Tool)
}
return result
}
// Names returns names of all registered tools.
func (r *Registry) Names() []string {
r.mu.RLock()
defer r.mu.RUnlock()
names := make([]string, 0, len(r.tools))
for name := range r.tools {
names = append(names, name)
}
return names
}