2bbf42b741
Remove Agent Desk users, roles, login sessions, tokens, and local permission persistence. Expose the backend as an embeddable ai-agent module with host-provided subject lookup and operation authorization callbacks, and complete the frontend/backend repository split.
68 lines
2.0 KiB
Go
68 lines
2.0 KiB
Go
package tooling
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"code.tczkiot.com/wlw/ai-agent/internal/ai/mcps"
|
|
"code.tczkiot.com/wlw/ai-agent/internal/pkg/toolx"
|
|
)
|
|
|
|
// MCPExecutor is the single execution boundary for dynamically discovered
|
|
// MCP tools. Engine adapters supply the policy for the current Agent run.
|
|
type MCPExecutor struct {
|
|
registry *Registry
|
|
runtime *mcps.RuntimeService
|
|
}
|
|
|
|
var DefaultMCPExecutor = NewMCPExecutor(DefaultRegistry, mcps.Runtime)
|
|
|
|
func NewMCPExecutor(registry *Registry, runtime *mcps.RuntimeService) *MCPExecutor {
|
|
return &MCPExecutor{registry: registry, runtime: runtime}
|
|
}
|
|
|
|
func (e *MCPExecutor) Execute(ctx context.Context, toolCode string, arguments map[string]any, policy Policy) (Definition, *mcps.ToolCallResult, error) {
|
|
definition, err := e.registry.Resolve(toolCode)
|
|
if err != nil {
|
|
return Definition{}, nil, err
|
|
}
|
|
if err := DefaultPolicyGuard.Authorize(Invocation{Definition: definition, Arguments: arguments, Policy: policy}); err != nil {
|
|
return Definition{}, nil, err
|
|
}
|
|
serverCode, toolName := toolx.SplitMCPToolCode(strings.TrimSpace(definition.Code))
|
|
if serverCode == "" || toolName == "" {
|
|
return Definition{}, nil, &UnsupportedExecutionError{ToolCode: definition.Code}
|
|
}
|
|
if e.runtime == nil {
|
|
return Definition{}, nil, fmt.Errorf("MCP executor runtime is not configured")
|
|
}
|
|
if definition.TimeoutMS > 0 {
|
|
var cancel context.CancelFunc
|
|
ctx, cancel = context.WithTimeout(ctx, time.Duration(definition.TimeoutMS)*time.Millisecond)
|
|
defer cancel()
|
|
}
|
|
result, err := e.runtime.CallTool(ctx, serverCode, toolName, cloneArguments(arguments))
|
|
return definition, result, err
|
|
}
|
|
|
|
type UnsupportedExecutionError struct {
|
|
ToolCode string
|
|
}
|
|
|
|
func (e *UnsupportedExecutionError) Error() string {
|
|
return "tool is not executable through MCP: " + e.ToolCode
|
|
}
|
|
|
|
func cloneArguments(input map[string]any) map[string]any {
|
|
if len(input) == 0 {
|
|
return map[string]any{}
|
|
}
|
|
ret := make(map[string]any, len(input))
|
|
for key, value := range input {
|
|
ret[key] = value
|
|
}
|
|
return ret
|
|
}
|