Files
2026-07-13 12:49:10 +08:00

203 lines
6.4 KiB
Go

/*
* Copyright 2026 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package adk
import (
"context"
"github.com/cloudwego/eino/callbacks"
"github.com/cloudwego/eino/components"
icb "github.com/cloudwego/eino/internal/callbacks"
)
// AgentCallbackInput represents the input passed to agent callbacks during OnStart.
// Use ConvAgentCallbackInput to safely convert from callbacks.CallbackInput.
type AgentCallbackInput struct {
// Input contains the agent input for a new run. Nil when resuming.
Input *AgentInput
// ResumeInfo contains resume information when resuming from an interrupt. Nil for new runs.
ResumeInfo *ResumeInfo
}
// AgentCallbackOutput represents the output passed to agent callbacks during OnEnd.
// Use ConvAgentCallbackOutput to safely convert from callbacks.CallbackOutput.
//
// Important: The Events iterator should be consumed asynchronously to avoid blocking
// the agent execution. Each callback handler receives an independent copy of the iterator.
type AgentCallbackOutput struct {
// Events provides a stream of agent events. Each handler receives its own copy.
Events *AsyncIterator[*AgentEvent]
}
func copyTypedEventIterator[M MessageType](iter *AsyncIterator[*TypedAgentEvent[M]], n int) []*AsyncIterator[*TypedAgentEvent[M]] {
if n <= 0 {
return nil
}
if n == 1 {
return []*AsyncIterator[*TypedAgentEvent[M]]{iter}
}
iterators := make([]*AsyncIterator[*TypedAgentEvent[M]], n)
generators := make([]*AsyncGenerator[*TypedAgentEvent[M]], n)
for i := 0; i < n; i++ {
iterators[i], generators[i] = NewAsyncIteratorPair[*TypedAgentEvent[M]]()
}
go func() {
defer func() {
for _, g := range generators {
g.Close()
}
}()
for {
event, ok := iter.Next()
if !ok {
break
}
for i := 0; i < n-1; i++ {
generators[i].Send(copyTypedAgentEvent(event))
}
generators[n-1].Send(event)
}
}()
return iterators
}
func copyAgentCallbackOutput(out *AgentCallbackOutput, n int) []*AgentCallbackOutput {
if out == nil || out.Events == nil {
result := make([]*AgentCallbackOutput, n)
for i := 0; i < n; i++ {
result[i] = out
}
return result
}
iters := copyTypedEventIterator(out.Events, n)
result := make([]*AgentCallbackOutput, n)
for i, iter := range iters {
result[i] = &AgentCallbackOutput{Events: iter}
}
return result
}
// ConvAgentCallbackInput converts a generic CallbackInput to AgentCallbackInput.
// Returns nil if the input is not an AgentCallbackInput.
func ConvAgentCallbackInput(input callbacks.CallbackInput) *AgentCallbackInput {
if v, ok := input.(*AgentCallbackInput); ok {
return v
}
return nil
}
// ConvAgentCallbackOutput converts a generic CallbackOutput to AgentCallbackOutput.
// Returns nil if the output is not an AgentCallbackOutput.
func ConvAgentCallbackOutput(output callbacks.CallbackOutput) *AgentCallbackOutput {
if v, ok := output.(*AgentCallbackOutput); ok {
return v
}
return nil
}
func initAgentCallbacks(ctx context.Context, agentName, agentType string, opts ...AgentRunOption) context.Context {
ri := &callbacks.RunInfo{
Name: agentName,
Type: agentType,
Component: ComponentOfAgent,
}
o := getCommonOptions(nil, opts...)
if len(o.handlers) == 0 {
return icb.ReuseHandlers(ctx, ri)
}
return icb.AppendHandlers(ctx, ri, o.handlers...)
}
func getAgentType(agent Agent) string {
if typer, ok := agent.(components.Typer); ok {
return typer.GetType()
}
return ""
}
// TypedAgentCallbackInput represents the input passed to typed agent callbacks during OnStart.
// Use ConvTypedCallbackInput to safely convert from callbacks.CallbackInput.
type TypedAgentCallbackInput[M MessageType] struct {
// Input contains the agent input for a new run. Nil when resuming.
Input *TypedAgentInput[M]
// ResumeInfo contains resume information when resuming from an interrupt. Nil for new runs.
ResumeInfo *ResumeInfo
}
// TypedAgentCallbackOutput represents the output passed to typed agent callbacks during OnEnd.
// Use ConvTypedCallbackOutput to safely convert from callbacks.CallbackOutput.
//
// Important: The Events iterator should be consumed asynchronously to avoid blocking
// the agent execution. Each callback handler receives an independent copy of the iterator.
type TypedAgentCallbackOutput[M MessageType] struct {
// Events provides a stream of agent events. Each handler receives its own copy.
Events *AsyncIterator[*TypedAgentEvent[M]]
}
// ConvTypedCallbackInput converts a callbacks.CallbackInput to *TypedAgentCallbackInput[M].
// Returns nil if the input is not of the expected type.
func ConvTypedCallbackInput[M MessageType](input callbacks.CallbackInput) *TypedAgentCallbackInput[M] {
if v, ok := input.(*TypedAgentCallbackInput[M]); ok {
return v
}
return nil
}
// ConvTypedCallbackOutput converts a callbacks.CallbackOutput to *TypedAgentCallbackOutput[M].
// Returns nil if the output is not of the expected type.
func ConvTypedCallbackOutput[M MessageType](output callbacks.CallbackOutput) *TypedAgentCallbackOutput[M] {
if v, ok := output.(*TypedAgentCallbackOutput[M]); ok {
return v
}
return nil
}
func copyTypedCallbackOutput[M MessageType](out *TypedAgentCallbackOutput[M], n int) []*TypedAgentCallbackOutput[M] {
if out == nil || out.Events == nil {
result := make([]*TypedAgentCallbackOutput[M], n)
for i := 0; i < n; i++ {
result[i] = out
}
return result
}
iters := copyTypedEventIterator(out.Events, n)
result := make([]*TypedAgentCallbackOutput[M], n)
for i, iter := range iters {
result[i] = &TypedAgentCallbackOutput[M]{Events: iter}
}
return result
}
func initAgenticCallbacks(ctx context.Context, agentName, agentType string, opts ...AgentRunOption) context.Context {
ri := &callbacks.RunInfo{
Name: agentName,
Type: agentType,
Component: ComponentOfAgenticAgent,
}
o := getCommonOptions(nil, opts...)
if len(o.handlers) == 0 {
return icb.ReuseHandlers(ctx, ri)
}
return icb.AppendHandlers(ctx, ri, o.handlers...)
}