- Add bubbletea/lipgloss/glamour dependencies for TUI - Create internal/tui package with EventWriter, styles, and bubbletea Model - Support streaming output display in conversation window - Add right panel with statistics and active agent status - Implement multi-agent collaboration with sub-agents - Add AgentCallTool for delegating tasks to sub-agents - Support parallel tool execution with goroutines - Auto-discover sub-agents from ~/.orca/prompts/ directory - Fix orchestrator routing based on msg.To field - Add non-blocking event writer with timeout to prevent blocking
80 lines
1.9 KiB
Go
80 lines
1.9 KiB
Go
package tool
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"github.com/orca/orca/pkg/bus"
|
||
)
|
||
|
||
type Agent interface {
|
||
Process(ctx context.Context, msg bus.Message) (bus.Message, error)
|
||
}
|
||
|
||
type agentCallTool struct {
|
||
agentRegistry func(string) (Agent, bool)
|
||
}
|
||
|
||
func NewAgentCallTool(registry func(string) (Agent, bool)) Tool {
|
||
return &agentCallTool{agentRegistry: registry}
|
||
}
|
||
|
||
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,
|
||
}
|
||
|
||
resp, err := agent.Process(ctx, msg)
|
||
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
|
||
}
|