Pulse/internal/agentcapabilities/tool_execution.go
rcourtman ee8a24e14a backend and governance: MCP contract, agent capabilities, API, and release-control
Manifest-backed MCP tools, prompts, and resources with surface affordance contracts; agent capability manifest and governance projection; API contract tests and capability route projection; operations-loop and intelligence-funnel telemetry; release-control subsystem documentation, registry, and tooling; licensing and configuration.
2026-06-23 17:26:15 +01:00

75 lines
2.7 KiB
Go

package agentcapabilities
import (
"context"
"errors"
"fmt"
)
// ExecuteCapabilityToolHTTP projects one shared tool-call request onto the
// canonical agent capability manifest and wraps the upstream Pulse response in
// the shared tool result envelope.
func ExecuteCapabilityToolHTTP(ctx context.Context, client HTTPDoer, baseURL, token string, capabilities []Capability, params ToolCallParams) (ToolResult, error) {
params = NormalizeToolCallParams(params)
if err := ValidateToolCallParams(params); err != nil {
return ToolResult{}, err
}
resp, err := CallRequestResponseCapabilityHTTPByName(ctx, client, baseURL, token, capabilities, params.Name, params.Arguments)
if err != nil {
var lookupErr CapabilityLookupError
if errors.As(err, &lookupErr) {
return ToolResult{}, fmt.Errorf("unknown tool: %s", lookupErr.Name)
}
return ToolResult{}, fmt.Errorf("call Pulse: %w", err)
}
return NewCapabilityHTTPToolResult(resp), nil
}
// DirectToolExecutionOptions names the surface-specific error messages used
// when native Pulse code executes a shared tool result directly instead of
// feeding it back into a model turn.
type DirectToolExecutionOptions struct {
FailurePrefix string
ApprovalRequiredMessage string
PolicyBlockedMessage string
}
// DirectToolExecutionOutcome is the shared direct-execution projection of a
// tool result. OutputText is the text callers should expose as execution
// output; Interpretation keeps the full marker/result view available for
// diagnostics and future policy callers.
type DirectToolExecutionOutcome struct {
OutputText string
Interpretation ToolResultInterpretation
}
// InterpretDirectToolExecution maps a shared tool result into the output and
// error contract used by native Assistant direct execution paths.
// This keeps marker detection, isError handling, and direct-execution failure
// messages out of individual chat or adapter surfaces.
func InterpretDirectToolExecution(result ToolResult, opts DirectToolExecutionOptions) (DirectToolExecutionOutcome, error) {
interpreted := InterpretToolResult(result)
outcome := DirectToolExecutionOutcome{
OutputText: interpreted.Text,
Interpretation: interpreted,
}
if interpreted.IsError {
prefix := firstNonEmptyString(opts.FailurePrefix, "tool execution failed")
return outcome, fmt.Errorf("%s: %s", prefix, interpreted.Text)
}
if interpreted.ApprovalRequired {
outcome.OutputText = ""
message := firstNonEmptyString(opts.ApprovalRequiredMessage, "tool requires approval")
return outcome, errors.New(message)
}
if interpreted.PolicyBlocked {
outcome.OutputText = ""
message := firstNonEmptyString(opts.PolicyBlockedMessage, "tool blocked by security policy")
return outcome, errors.New(message)
}
return outcome, nil
}