feat: config, OpenAI-compatible streaming provider and safe tools

This commit is contained in:
OpenClaw Dev 2026-10-25 03:10:13 +01:00
commit c1c7b0e005
13 changed files with 1031 additions and 0 deletions

64
internal/tools/tools.go Normal file
View file

@ -0,0 +1,64 @@
// Package tools contains the tool registry and built-in safe tools.
package tools
import (
"context"
"encoding/json"
"fmt"
"sort"
"github.com/crypto/openclaw/internal/llm"
)
type Tool interface {
Spec() llm.ToolSpec
Call(ctx context.Context, args json.RawMessage) (string, error)
}
type Registry struct{ tools map[string]Tool }
func NewRegistry(ts ...Tool) *Registry {
r := &Registry{tools: map[string]Tool{}}
for _, t := range ts {
r.Register(t)
}
return r
}
func (r *Registry) Register(t Tool) { r.tools[t.Spec().Name] = t }
func (r *Registry) Specs() []llm.ToolSpec {
out := make([]llm.ToolSpec, 0, len(r.tools))
for _, t := range r.tools {
out = append(out, t.Spec())
}
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
return out
}
// Call runs a tool; errors are returned as text so the model can react to them.
func (r *Registry) Call(ctx context.Context, name, args string) string {
t, ok := r.tools[name]
if !ok {
return fmt.Sprintf("error: unknown tool %q", name)
}
if args == "" {
args = "{}"
}
if !json.Valid([]byte(args)) {
return "error: arguments are not valid JSON"
}
res, err := t.Call(ctx, json.RawMessage(args))
if err != nil {
return "error: " + err.Error()
}
return res
}
func obj(props map[string]any, required ...string) map[string]any {
m := map[string]any{"type": "object", "properties": props}
if len(required) > 0 {
m["required"] = required
}
return m
}