203 lines
6.4 KiB
Go
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...)
|
|
}
|