feat: Enhance AI Agent and Channel Management
- Updated labels in the AI Agents dashboard for clarity, changing "流程状态" to "Playbook 状态" and "未发布流程" to "未发布 Playbook". - Introduced AI Agent rollout percentage management in channel editing, allowing users to set and rollback rollout percentages. - Added new API endpoints for rolling back AI Agent rollout and fetching agent run metrics. - Implemented new UI components for displaying agent run details, including status, duration, and input/output tokens. - Enhanced type definitions for AdminChannel and AIAgent to include rollout percentages and runtime modes. - Updated navigation to include a section for agent runs. - Added new translations for agent run features in both English and Chinese.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package tooling
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"agent-desk/internal/ai/mcps"
|
||||
"agent-desk/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
|
||||
}
|
||||
Reference in New Issue
Block a user