77 lines
2.1 KiB
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}},
|
|
})
|
|
}
|