orca.ai/pkg/tool/agent_call.go
2026-05-12 00:09:01 +08:00

137 lines
3.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tool
import (
"context"
"fmt"
"io"
"github.com/orca/orca/pkg/bus"
)
type AgentStreamWriter struct {
agentName string
eventBus bus.MessageBus
}
func (w *AgentStreamWriter) Write(p []byte) (n int, err error) {
if w.eventBus != nil {
w.eventBus.Publish("agent_events", bus.Message{
Type: bus.MsgTypeLog,
Content: map[string]interface{}{
"event": "token",
"agent": w.agentName,
"text": string(p),
},
})
}
return len(p), nil
}
type Agent interface {
Process(ctx context.Context, msg bus.Message) (bus.Message, error)
}
type agentCallTool struct {
agentRegistry func(string) (Agent, bool)
eventBus bus.MessageBus
}
func NewAgentCallTool(registry func(string) (Agent, bool)) Tool {
return &agentCallTool{agentRegistry: registry}
}
func (t *agentCallTool) SetEventBus(mb bus.MessageBus) {
t.eventBus = mb
}
func (t *agentCallTool) Name() string { return "agent_call" }
func (t *agentCallTool) Description() string {
return "调用其他专业Agent来协助完成任务。当你需要特定领域的专业知识时使用此工具委托给专门的Agent处理。"
}
func (t *agentCallTool) Parameters() map[string]ParameterSchema {
return map[string]ParameterSchema{
"agent": {
Type: "string",
Description: "要调用的Agent名称如 coder, reviewer, designer",
Required: true,
},
"task": {
Type: "string",
Description: "要委托给该Agent处理的具体任务描述",
Required: true,
},
}
}
func (t *agentCallTool) Execute(ctx context.Context, args map[string]interface{}) (*Result, error) {
agentName, ok := args["agent"].(string)
if !ok || agentName == "" {
return ErrorResult("'agent' argument is required and must be a string"), nil
}
task, ok := args["task"].(string)
if !ok || task == "" {
return ErrorResult("'task' argument is required and must be a string"), nil
}
agent, ok := t.agentRegistry(agentName)
if !ok {
return ErrorResult(fmt.Sprintf("agent '%s' not found", agentName)), nil
}
msg := bus.Message{
Type: bus.MsgTypeTaskRequest,
From: "llm",
To: agentName,
Content: task,
}
if t.eventBus != nil {
t.eventBus.Publish("agent_events", bus.Message{
Type: bus.MsgTypeToolCall,
From: "llm",
To: agentName,
Content: map[string]interface{}{"event": "start", "agent": agentName, "task": task},
})
}
if setter, ok := agent.(interface{ SetStreamWriter(io.Writer) }); ok && t.eventBus != nil {
writer := &AgentStreamWriter{agentName: agentName, eventBus: t.eventBus}
setter.SetStreamWriter(writer)
}
resp, err := agent.Process(ctx, msg)
if t.eventBus != nil {
status := "completed"
if err != nil {
status = "failed"
}
resultContent := ""
if resp.Content != nil {
resultContent = fmt.Sprintf("%v", resp.Content)
}
t.eventBus.Publish("agent_events", bus.Message{
Type: bus.MsgTypeToolResult,
From: agentName,
To: "llm",
Content: map[string]interface{}{"event": "end", "agent": agentName, "status": status, "result": resultContent},
})
}
if err != nil {
return ErrorResult(fmt.Sprintf("agent '%s' execution failed: %v", agentName, err)), nil
}
return &Result{
Success: true,
Data: map[string]interface{}{
"agent": agentName,
"result": resp.Content,
"metadata": resp.Metadata,
},
}, nil
}