Changeset 0.7.2 (#40)

This commit is contained in:
2026-02-21 19:03:19 +00:00
parent 494b1aa981
commit 416e5439ea
28 changed files with 3813 additions and 138 deletions

92
server/tools/registry.go Normal file
View File

@@ -0,0 +1,92 @@
package tools
import (
"context"
"encoding/json"
"fmt"
"log"
)
// ── Registry ────────────────────────────────
var registry = map[string]Tool{}
// Register adds a tool to the global registry. Called at init time.
func Register(t Tool) {
def := t.Definition()
if _, exists := registry[def.Name]; exists {
panic("tools.Register: duplicate tool name: " + def.Name)
}
registry[def.Name] = t
log.Printf("🔧 Registered tool: %s", def.Name)
}
// Get returns a tool by name, or nil if not found.
func Get(name string) Tool {
return registry[name]
}
// AllDefinitions returns tool definitions for all registered tools.
// Used to populate the `tools` field in LLM requests.
func AllDefinitions() []ToolDef {
defs := make([]ToolDef, 0, len(registry))
for _, t := range registry {
defs = append(defs, t.Definition())
}
return defs
}
// ── Execution ───────────────────────────────
// ExecuteCall runs a single tool call and returns a ToolResult.
// Never returns an error — failures are encoded in the result content
// so the LLM can see what went wrong and adjust.
func ExecuteCall(ctx context.Context, execCtx ExecutionContext, call ToolCall) ToolResult {
tool := Get(call.Name)
if tool == nil {
return ToolResult{
ToolCallID: call.ID,
Name: call.Name,
Content: jsonError(fmt.Sprintf("unknown tool: %s", call.Name)),
IsError: true,
}
}
result, err := tool.Execute(ctx, execCtx, call.Arguments)
if err != nil {
log.Printf("Tool %s error: %v", call.Name, err)
return ToolResult{
ToolCallID: call.ID,
Name: call.Name,
Content: jsonError(err.Error()),
IsError: true,
}
}
return ToolResult{
ToolCallID: call.ID,
Name: call.Name,
Content: result,
}
}
// ExecuteAll runs multiple tool calls and returns all results.
func ExecuteAll(ctx context.Context, execCtx ExecutionContext, calls []ToolCall) []ToolResult {
results := make([]ToolResult, len(calls))
for i, call := range calls {
results[i] = ExecuteCall(ctx, execCtx, call)
}
return results
}
// HasTools returns true if any tools are registered.
func HasTools() bool {
return len(registry) > 0
}
// ── Helpers ─────────────────────────────────
func jsonError(msg string) string {
b, _ := json.Marshal(map[string]string{"error": msg})
return string(b)
}