feat(tools): optionality

This commit is contained in:
Mauro Trulli 2026-02-24 16:34:56 +01:00
parent eb138a3f13
commit 9a6b49f9ba
5 changed files with 126 additions and 41 deletions

View file

@ -203,6 +203,15 @@
} }
}, },
"tools": { "tools": {
"core": {
"enable_web_fetch": true,
"enable_message": true,
"enable_spawn": true
},
"hardware": {
"enable_i2c": false,
"enable_spi": false
},
"web": { "web": {
"brave": { "brave": {
"enabled": false, "enabled": false,
@ -223,10 +232,19 @@
"exec_timeout_minutes": 5 "exec_timeout_minutes": 5
}, },
"exec": { "exec": {
"enabled": true,
"enable_deny_patterns": false, "enable_deny_patterns": false,
"custom_deny_patterns": [] "custom_deny_patterns": []
}, },
"filesystem": {
"enable_read": true,
"enable_write": true,
"enable_list": true,
"enable_edit": true,
"enable_append": true
},
"skills": { "skills": {
"enabled": true,
"registries": { "registries": {
"clawhub": { "clawhub": {
"enabled": true, "enabled": true,

View file

@ -48,12 +48,24 @@ func NewAgentInstance(
restrict := defaults.RestrictToWorkspace restrict := defaults.RestrictToWorkspace
toolsRegistry := tools.NewToolRegistry() toolsRegistry := tools.NewToolRegistry()
toolsRegistry.Register(tools.NewReadFileTool(workspace, restrict)) if cfg.Tools.Filesystem.EnableRead {
toolsRegistry.Register(tools.NewWriteFileTool(workspace, restrict)) toolsRegistry.Register(tools.NewReadFileTool(workspace, restrict))
toolsRegistry.Register(tools.NewListDirTool(workspace, restrict)) }
toolsRegistry.Register(tools.NewExecToolWithConfig(workspace, restrict, cfg)) if cfg.Tools.Filesystem.EnableWrite {
toolsRegistry.Register(tools.NewEditFileTool(workspace, restrict)) toolsRegistry.Register(tools.NewWriteFileTool(workspace, restrict))
toolsRegistry.Register(tools.NewAppendFileTool(workspace, restrict)) }
if cfg.Tools.Filesystem.EnableList {
toolsRegistry.Register(tools.NewListDirTool(workspace, restrict))
}
if cfg.Tools.Filesystem.EnableEdit {
toolsRegistry.Register(tools.NewEditFileTool(workspace, restrict))
}
if cfg.Tools.Filesystem.EnableAppend {
toolsRegistry.Register(tools.NewAppendFileTool(workspace, restrict))
}
if cfg.Tools.Exec.Enabled {
toolsRegistry.Register(tools.NewExecToolWithConfig(workspace, restrict, cfg))
}
sessionsDir := filepath.Join(workspace, "sessions") sessionsDir := filepath.Join(workspace, "sessions")
sessionsManager := session.NewSessionManager(sessionsDir) sessionsManager := session.NewSessionManager(sessionsDir)

View file

@ -109,45 +109,57 @@ func registerSharedTools(
}); searchTool != nil { }); searchTool != nil {
agent.Tools.Register(searchTool) agent.Tools.Register(searchTool)
} }
agent.Tools.Register(tools.NewWebFetchTool(50000)) if cfg.Tools.Core.EnableWebFetch {
agent.Tools.Register(tools.NewWebFetchTool(50000))
}
// Hardware tools (I2C, SPI) - Linux only, returns error on other platforms // Hardware tools (I2C, SPI) - Linux only, returns error on other platforms
agent.Tools.Register(tools.NewI2CTool()) if cfg.Tools.Hardware.EnableI2C {
agent.Tools.Register(tools.NewSPITool()) agent.Tools.Register(tools.NewI2CTool())
}
if cfg.Tools.Hardware.EnableSPI {
agent.Tools.Register(tools.NewSPITool())
}
// Message tool // Message tool
messageTool := tools.NewMessageTool() if cfg.Tools.Core.EnableMessage {
messageTool.SetSendCallback(func(channel, chatID, content string) error { messageTool := tools.NewMessageTool()
msgBus.PublishOutbound(bus.OutboundMessage{ messageTool.SetSendCallback(func(channel, chatID, content string) error {
Channel: channel, msgBus.PublishOutbound(bus.OutboundMessage{
ChatID: chatID, Channel: channel,
Content: content, ChatID: chatID,
Content: content,
})
return nil
}) })
return nil agent.Tools.Register(messageTool)
}) }
agent.Tools.Register(messageTool)
// Skill discovery and installation tools // Skill discovery and installation tools
registryMgr := skills.NewRegistryManagerFromConfig(skills.RegistryConfig{ if cfg.Tools.Skills.Enabled {
MaxConcurrentSearches: cfg.Tools.Skills.MaxConcurrentSearches, registryMgr := skills.NewRegistryManagerFromConfig(skills.RegistryConfig{
ClawHub: skills.ClawHubConfig(cfg.Tools.Skills.Registries.ClawHub), MaxConcurrentSearches: cfg.Tools.Skills.MaxConcurrentSearches,
}) ClawHub: skills.ClawHubConfig(cfg.Tools.Skills.Registries.ClawHub),
searchCache := skills.NewSearchCache( })
cfg.Tools.Skills.SearchCache.MaxSize, searchCache := skills.NewSearchCache(
time.Duration(cfg.Tools.Skills.SearchCache.TTLSeconds)*time.Second, cfg.Tools.Skills.SearchCache.MaxSize,
) time.Duration(cfg.Tools.Skills.SearchCache.TTLSeconds)*time.Second,
agent.Tools.Register(tools.NewFindSkillsTool(registryMgr, searchCache)) )
agent.Tools.Register(tools.NewInstallSkillTool(registryMgr, agent.Workspace)) agent.Tools.Register(tools.NewFindSkillsTool(registryMgr, searchCache))
agent.Tools.Register(tools.NewInstallSkillTool(registryMgr, agent.Workspace))
}
// Spawn tool with allowlist checker // Spawn tool with allowlist checker
subagentManager := tools.NewSubagentManager(provider, agent.Model, agent.Workspace, msgBus) if cfg.Tools.Core.EnableSpawn {
subagentManager.SetLLMOptions(agent.MaxTokens, agent.Temperature) subagentManager := tools.NewSubagentManager(provider, agent.Model, agent.Workspace, msgBus)
spawnTool := tools.NewSpawnTool(subagentManager) subagentManager.SetLLMOptions(agent.MaxTokens, agent.Temperature)
currentAgentID := agentID spawnTool := tools.NewSpawnTool(subagentManager)
spawnTool.SetAllowlistChecker(func(targetAgentID string) bool { currentAgentID := agentID
return registry.CanSpawnSubagent(currentAgentID, targetAgentID) spawnTool.SetAllowlistChecker(func(targetAgentID string) bool {
}) return registry.CanSpawnSubagent(currentAgentID, targetAgentID)
agent.Tools.Register(spawnTool) })
agent.Tools.Register(spawnTool)
}
// Update context builder with the complete tools registry // Update context builder with the complete tools registry
agent.ContextBuilder.SetToolsRegistry(agent.Tools) agent.ContextBuilder.SetToolsRegistry(agent.Tools)

View file

@ -456,22 +456,47 @@ type WebToolsConfig struct {
} }
type CronToolsConfig struct { type CronToolsConfig struct {
ExecTimeoutMinutes int `json:"exec_timeout_minutes" env:"PICOCLAW_TOOLS_CRON_EXEC_TIMEOUT_MINUTES"` // 0 means no timeout Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_CRON_ENABLED"`
ExecTimeoutMinutes int `json:"exec_timeout_minutes" env:"PICOCLAW_TOOLS_CRON_EXEC_TIMEOUT_MINUTES"` // 0 means no timeout
}
type HardwareToolsConfig struct {
EnableI2C bool `json:"enable_i2c" env:"PICOCLAW_TOOLS_HW_ENABLE_I2C"`
EnableSPI bool `json:"enable_spi" env:"PICOCLAW_TOOLS_HW_ENABLE_SPI"`
}
type CoreToolsConfig struct {
EnableWebFetch bool `json:"enable_web_fetch" env:"PICOCLAW_TOOLS_CORE_ENABLE_WEB_FETCH"`
EnableMessage bool `json:"enable_message" env:"PICOCLAW_TOOLS_CORE_ENABLE_MESSAGE"`
EnableSpawn bool `json:"enable_spawn" env:"PICOCLAW_TOOLS_CORE_ENABLE_SPAWN"`
}
type FilesystemConfig struct {
EnableRead bool `json:"enable_read" env:"PICOCLAW_TOOLS_FS_ENABLE_READ"`
EnableWrite bool `json:"enable_write" env:"PICOCLAW_TOOLS_FS_ENABLE_WRITE"`
EnableList bool `json:"enable_list" env:"PICOCLAW_TOOLS_FS_ENABLE_LIST"`
EnableEdit bool `json:"enable_edit" env:"PICOCLAW_TOOLS_FS_ENABLE_EDIT"`
EnableAppend bool `json:"enable_append" env:"PICOCLAW_TOOLS_FS_ENABLE_APPEND"`
} }
type ExecConfig struct { type ExecConfig struct {
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_EXEC_ENABLED"`
EnableDenyPatterns bool `json:"enable_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS"` EnableDenyPatterns bool `json:"enable_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS"`
CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"` CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"`
} }
type ToolsConfig struct { type ToolsConfig struct {
Web WebToolsConfig `json:"web"` Web WebToolsConfig `json:"web"`
Cron CronToolsConfig `json:"cron"` Cron CronToolsConfig `json:"cron"`
Exec ExecConfig `json:"exec"` Exec ExecConfig `json:"exec"`
Skills SkillsToolsConfig `json:"skills"` Skills SkillsToolsConfig `json:"skills"`
Filesystem FilesystemConfig `json:"filesystem"`
Hardware HardwareToolsConfig `json:"hardware"`
Core CoreToolsConfig `json:"core"`
} }
type SkillsToolsConfig struct { type SkillsToolsConfig struct {
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_SKILLS_ENABLED"`
Registries SkillsRegistriesConfig `json:"registries"` Registries SkillsRegistriesConfig `json:"registries"`
MaxConcurrentSearches int `json:"max_concurrent_searches" env:"PICOCLAW_SKILLS_MAX_CONCURRENT_SEARCHES"` MaxConcurrentSearches int `json:"max_concurrent_searches" env:"PICOCLAW_SKILLS_MAX_CONCURRENT_SEARCHES"`
SearchCache SearchCacheConfig `json:"search_cache"` SearchCache SearchCacheConfig `json:"search_cache"`

View file

@ -276,6 +276,15 @@ func DefaultConfig() *Config {
Port: 18790, Port: 18790,
}, },
Tools: ToolsConfig{ Tools: ToolsConfig{
Core: CoreToolsConfig{
EnableWebFetch: true,
EnableMessage: true,
EnableSpawn: true,
},
Hardware: HardwareToolsConfig{
EnableI2C: true,
EnableSPI: true,
},
Web: WebToolsConfig{ Web: WebToolsConfig{
Brave: BraveConfig{ Brave: BraveConfig{
Enabled: false, Enabled: false,
@ -296,9 +305,18 @@ func DefaultConfig() *Config {
ExecTimeoutMinutes: 5, ExecTimeoutMinutes: 5,
}, },
Exec: ExecConfig{ Exec: ExecConfig{
Enabled: true,
EnableDenyPatterns: true, EnableDenyPatterns: true,
}, },
Filesystem: FilesystemConfig{
EnableRead: true,
EnableWrite: true,
EnableList: true,
EnableEdit: true,
EnableAppend: true,
},
Skills: SkillsToolsConfig{ Skills: SkillsToolsConfig{
Enabled: true,
Registries: SkillsRegistriesConfig{ Registries: SkillsRegistriesConfig{
ClawHub: ClawHubRegistryConfig{ ClawHub: ClawHubRegistryConfig{
Enabled: true, Enabled: true,