mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-05-17 21:17:28 +08:00
161 lines
5.1 KiB
Go
161 lines
5.1 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/YspCoder/clawgo/pkg/bus"
|
|
"github.com/YspCoder/clawgo/pkg/config"
|
|
)
|
|
|
|
func BootstrapDefaultTools(ctx context.Context, opts BootstrapOptions) (*BootstrapResult, error) {
|
|
if opts.Config == nil {
|
|
return nil, fmt.Errorf("config is required")
|
|
}
|
|
workspace := strings.TrimSpace(opts.Workspace)
|
|
if workspace == "" {
|
|
workspace = opts.Config.WorkspacePath()
|
|
}
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
|
|
registry := NewToolRegistry()
|
|
processManager := opts.ProcessManager
|
|
if processManager == nil {
|
|
processManager = NewProcessManager(workspace)
|
|
}
|
|
|
|
registerFilesystemTools(registry, workspace)
|
|
registerShellTools(registry, opts, workspace, processManager)
|
|
registerCronTools(registry, opts)
|
|
|
|
maxParallelCalls, parallelSafe := bootstrapParallelConfig(opts.Config)
|
|
registerWebTools(registry, opts, maxParallelCalls, parallelSafe)
|
|
registerMCPTools(ctx, registry, opts, workspace)
|
|
registerMessageTool(registry, opts.MessageBus)
|
|
|
|
subagentManager, subagentRouter := registerSubagentTools(registry, opts, workspace)
|
|
registerSessionTools(registry, opts)
|
|
registerMemoryTools(registry, workspace)
|
|
|
|
registry.Register(NewParallelTool(registry, maxParallelCalls, parallelSafe))
|
|
registry.Register(NewBrowserTool())
|
|
registry.Register(NewCameraTool(workspace))
|
|
registry.Register(NewSystemInfoTool())
|
|
|
|
return &BootstrapResult{
|
|
Registry: registry,
|
|
ProcessManager: processManager,
|
|
SubagentManager: subagentManager,
|
|
SubagentRouter: subagentRouter,
|
|
}, nil
|
|
}
|
|
|
|
func registerFilesystemTools(registry *ToolRegistry, workspace string) {
|
|
registry.Register(NewReadFileTool(workspace))
|
|
registry.Register(NewWriteFileTool(workspace))
|
|
registry.Register(NewListDirTool(workspace))
|
|
registry.Register(NewSkillExecTool(workspace))
|
|
registry.Register(NewEditFileTool(workspace))
|
|
}
|
|
|
|
func registerShellTools(registry *ToolRegistry, opts BootstrapOptions, workspace string, processManager *ProcessManager) {
|
|
registry.Register(NewExecTool(opts.Config.Tools.Shell, workspace, processManager))
|
|
registry.Register(NewProcessTool(processManager))
|
|
}
|
|
|
|
func registerCronTools(registry *ToolRegistry, opts BootstrapOptions) {
|
|
if opts.CronService == nil {
|
|
return
|
|
}
|
|
registry.Register(NewRemindTool(opts.CronService))
|
|
registry.Register(NewCronTool(opts.CronService))
|
|
}
|
|
|
|
func bootstrapParallelConfig(cfg *config.Config) (int, map[string]struct{}) {
|
|
maxParallelCalls := cfg.Agents.Defaults.Execution.ToolMaxParallelCalls
|
|
if maxParallelCalls <= 0 {
|
|
maxParallelCalls = 4
|
|
}
|
|
parallelSafe := make(map[string]struct{})
|
|
for _, name := range cfg.Agents.Defaults.Execution.ToolParallelSafeNames {
|
|
trimmed := strings.TrimSpace(name)
|
|
if trimmed != "" {
|
|
parallelSafe[trimmed] = struct{}{}
|
|
}
|
|
}
|
|
return maxParallelCalls, parallelSafe
|
|
}
|
|
|
|
func registerWebTools(registry *ToolRegistry, opts BootstrapOptions, maxParallelCalls int, parallelSafe map[string]struct{}) {
|
|
searchCfg := opts.Config.Tools.Web.Search
|
|
registry.Register(NewWebSearchTool(searchCfg.APIKey, searchCfg.MaxResults))
|
|
webFetchTool := NewWebFetchTool(50000)
|
|
registry.Register(webFetchTool)
|
|
registry.Register(NewParallelFetchTool(webFetchTool, maxParallelCalls, parallelSafe))
|
|
}
|
|
|
|
func registerMCPTools(ctx context.Context, registry *ToolRegistry, opts BootstrapOptions, workspace string) {
|
|
mcpCfg := opts.Config.Tools.MCP
|
|
if !mcpCfg.Enabled {
|
|
return
|
|
}
|
|
mcpTool := NewMCPTool(workspace, mcpCfg)
|
|
registry.Register(mcpTool)
|
|
timeoutSec := mcpCfg.RequestTimeoutSec
|
|
if timeoutSec <= 0 {
|
|
timeoutSec = 20
|
|
}
|
|
discoveryCtx, cancel := context.WithTimeout(ctx, time.Duration(timeoutSec)*time.Second)
|
|
defer cancel()
|
|
for _, remoteTool := range mcpTool.DiscoverTools(discoveryCtx) {
|
|
registry.Register(remoteTool)
|
|
}
|
|
}
|
|
|
|
func registerMessageTool(registry *ToolRegistry, msgBus *bus.MessageBus) {
|
|
messageTool := NewMessageTool()
|
|
if msgBus != nil {
|
|
messageTool.SetSendCallback(func(channel, chatID, action, content, media, messageID, emoji string, buttons [][]bus.Button) error {
|
|
msgBus.PublishOutbound(bus.OutboundMessage{
|
|
Channel: channel,
|
|
ChatID: chatID,
|
|
Content: content,
|
|
Media: media,
|
|
Buttons: buttons,
|
|
Action: action,
|
|
MessageID: messageID,
|
|
Emoji: emoji,
|
|
})
|
|
return nil
|
|
})
|
|
}
|
|
registry.Register(messageTool)
|
|
}
|
|
|
|
func registerSubagentTools(registry *ToolRegistry, opts BootstrapOptions, workspace string) (*SubagentManager, *SubagentRouter) {
|
|
subagentManager := NewSubagentManager(opts.Provider, workspace, opts.MessageBus)
|
|
subagentRouter := NewSubagentRouter(subagentManager)
|
|
registry.Register(NewSpawnTool(subagentManager))
|
|
if store := subagentManager.ProfileStore(); store != nil {
|
|
registry.Register(NewSubagentProfileTool(store))
|
|
}
|
|
return subagentManager, subagentRouter
|
|
}
|
|
|
|
func registerSessionTools(registry *ToolRegistry, opts BootstrapOptions) {
|
|
registry.Register(NewSessionsTool(opts.SessionList, opts.SessionHistory))
|
|
if opts.SessionManager != nil {
|
|
registry.Register(NewSessionSearchTool(opts.SessionManager))
|
|
}
|
|
}
|
|
|
|
func registerMemoryTools(registry *ToolRegistry, workspace string) {
|
|
registry.Register(NewMemorySearchTool(workspace))
|
|
registry.Register(NewMemoryGetTool(workspace))
|
|
registry.Register(NewMemoryWriteTool(workspace))
|
|
}
|