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 }