orca.ai/pkg/tool/manager.go
大森 6b94476347 Initial commit: Orca Agent Framework
Core features:
- Microkernel architecture with Actor model
- Session management with JSONL persistence
- Tool system (5 built-in tools)
- Skill system with SKILL.md parsing
- Sandbox security execution
- Ollama integration with gemma4:e4b
- Prompt-based tool calling (compatible with native function calling)
- REPL interface

11 packages, all tests passing
2026-05-08 00:55:48 +08:00

109 lines
2.4 KiB
Go

package tool
import (
"context"
"fmt"
"sort"
"sync"
)
// Manager is a thread-safe registry that manages tool registration and execution.
//
// Tools are registered by name (case-sensitive) and can be discovered,
// listed, and invoked through the Manager. Duplicate registration returns
// an error.
type Manager struct {
mu sync.RWMutex
tools map[string]Tool
}
// NewManager creates a new empty tool manager.
func NewManager() *Manager {
return &Manager{
tools: make(map[string]Tool),
}
}
// Register adds a tool to the manager. Returns an error if a tool with the
// same name is already registered.
func (m *Manager) Register(tool Tool) error {
m.mu.Lock()
defer m.mu.Unlock()
name := tool.Name()
if _, exists := m.tools[name]; exists {
return fmt.Errorf("tool %q is already registered", name)
}
m.tools[name] = tool
return nil
}
// Unregister removes a tool from the manager by name.
func (m *Manager) Unregister(name string) error {
m.mu.Lock()
defer m.mu.Unlock()
if _, exists := m.tools[name]; !exists {
return fmt.Errorf("tool %q is not registered", name)
}
delete(m.tools, name)
return nil
}
// Get retrieves a tool by name. Returns false if not found.
func (m *Manager) Get(name string) (Tool, bool) {
m.mu.RLock()
defer m.mu.RUnlock()
t, ok := m.tools[name]
return t, ok
}
// List returns all registered tools sorted by name.
func (m *Manager) List() []Tool {
m.mu.RLock()
defer m.mu.RUnlock()
result := make([]Tool, 0, len(m.tools))
for _, t := range m.tools {
result = append(result, t)
}
sort.Slice(result, func(i, j int) bool {
return result[i].Name() < result[j].Name()
})
return result
}
// Execute looks up a tool by name and invokes it with the given arguments.
// Returns an error if the tool is not found.
func (m *Manager) Execute(name string, ctx context.Context, args map[string]interface{}) (*Result, error) {
tool, ok := m.Get(name)
if !ok {
return nil, fmt.Errorf("tool %q not found", name)
}
return tool.Execute(ctx, args)
}
// Count returns the number of registered tools.
func (m *Manager) Count() int {
m.mu.RLock()
defer m.mu.RUnlock()
return len(m.tools)
}
// Names returns the names of all registered tools sorted alphabetically.
func (m *Manager) Names() []string {
m.mu.RLock()
defer m.mu.RUnlock()
names := make([]string, 0, len(m.tools))
for name := range m.tools {
names = append(names, name)
}
sort.Strings(names)
return names
}