This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-core/pkg/tools/registry/server.go

77 lines
2.1 KiB
Go

package registry
import (
"context"
"encoding/json"
"fmt"
"ollie/pkg/tools"
"ollie/pkg/tools/execute"
)
// Server implements tools.Server backed by a session-aware registry.
type Server struct {
registry *Registry
sessionID string
execServer *execute.Server
}
func NewServer(registry *Registry, sessionID string, execServer *execute.Server) *Server {
return &Server{
registry: registry,
sessionID: sessionID,
execServer: execServer,
}
}
func (s *Server) ListTools() ([]tools.ToolInfo, error) {
return s.registry.Loaded(s.sessionID), nil
}
func (s *Server) CallTool(ctx context.Context, tool string, args json.RawMessage) (json.RawMessage, error) {
if _, promoted := s.registry.Lookup(s.sessionID, tool); !promoted {
return nil, fmt.Errorf("tool_not_loaded: %s (must be loaded via /tools/load first)", tool)
}
// Read the tool script
script, err := execute.ReadTool(tool)
if err != nil {
return nil, fmt.Errorf("read tool %s: %w", tool, err)
}
// Convert JSON object args to positional string args.
// Try to extract an "args" array first (legacy call_tool format),
// otherwise convert object values to positional strings.
var positional []string
var argMap map[string]interface{}
if err := json.Unmarshal(args, &argMap); err == nil {
if argsArr, ok := argMap["args"]; ok {
if arr, ok := argsArr.([]interface{}); ok {
for _, v := range arr {
positional = append(positional, fmt.Sprintf("%v", v))
}
}
} else {
// Convert object values to positional strings (schema-defined order)
for _, v := range argMap {
positional = append(positional, fmt.Sprintf("%v", v))
}
}
}
// Run the script through the execute kernel
lang := execute.DetectLanguage(script)
code := execute.InjectArgs(lang, tool, positional, script)
result, err := s.execServer.Execute(ctx, code, lang, 30, "default", true)
if err != nil {
return json.Marshal(map[string]interface{}{
"isError": true,
"content": []map[string]string{{"type": "text", "text": err.Error()}},
})
}
return json.Marshal(map[string]interface{}{
"content": []map[string]string{{"type": "text", "text": result}},
})
}