Files
2026-08-14 23:41:57 +08:00

61 lines
2.3 KiB
Go

package agentcore
import (
"context"
"encoding/json"
"strings"
)
// ContentToText flattens text blocks of a content list into a single string,
// the lowest-common-denominator representation accepted by every OpenAI-
// compatible gateway. Non-text blocks (thinking, tool calls) are surfaced
// through their own fields, so they are skipped here.
func ContentToText(list ContentList) string {
var b strings.Builder
for _, c := range list {
if tc, ok := c.(TextContent); ok {
b.WriteString(tc.Text)
}
}
return b.String()
}
// LastAssistantOf returns a pointer to the last AssistantMessage in msgs, or nil.
func LastAssistantOf(msgs []AgentMessage) *AssistantMessage {
for i := len(msgs) - 1; i >= 0; i-- {
if a, ok := msgs[i].(AssistantMessage); ok {
return &a
}
}
return nil
}
// EmitFunc emits a loop-level AgentEvent honoring cancellation.
type EmitFunc func(ctx context.Context, ev AgentEvent) error
// PrepareArgumentsFunc optionally rewrites a tool's raw arguments before schema
// validation (e.g. injecting defaults). An error aborts the call with an error
// result. Optional (nil = identity).
type PrepareArgumentsFunc func(ctx context.Context, toolName string, args json.RawMessage) (json.RawMessage, error)
// BeforeToolCallDecision is the optional result of the beforeToolCall hook. When
// Block is true the tool is not executed and an error result is produced;
// Content/Details override the default block message when set. When Block is
// false and UpdatedInput is non-empty, it replaces the tool's raw arguments
// before execution (PreToolUse rewrite, FR-8); the replacement is re-validated
// against the tool schema.
type BeforeToolCallDecision struct {
Block bool
Content *ContentList
Details *any
UpdatedInput json.RawMessage
}
// BeforeToolCallFunc runs after validation and may block the call (permission /
// sandbox checks, FR-4/FR-26). Returning nil allows the call. Optional.
type BeforeToolCallFunc func(ctx context.Context, call AgentToolCall) *BeforeToolCallDecision
// AfterToolCallFunc runs after execution and may override the result
// field-by-field via AfterToolCallResult (FR-5, no deep merge). Optional.
type AfterToolCallFunc func(ctx context.Context, call AgentToolCall, result AgentToolResult, isError bool) *AfterToolCallResult