harden exec defaults and gate bootstrap loading to first-run context

This commit is contained in:
DBT
2026-02-24 08:28:41 +00:00
parent 9478161822
commit 1a6febffe7
4 changed files with 43 additions and 16 deletions

View File

@@ -143,6 +143,7 @@
"enabled": true,
"working_dir": "",
"timeout": 60000000000,
"auto_install_missing": false,
"sandbox": {
"enabled": false,
"image": "alpine:3.20"

View File

@@ -137,7 +137,6 @@ func (cb *ContextBuilder) LoadBootstrapFiles() string {
bootstrapFiles := []string{
"AGENTS.md",
"BOOT.md",
"BOOTSTRAP.md",
"SOUL.md",
"USER.md",
"IDENTITY.md",
@@ -152,9 +151,32 @@ func (cb *ContextBuilder) LoadBootstrapFiles() string {
}
}
// BOOTSTRAP.md is first-run guidance; load only when identity/user is not initialized.
if cb.shouldLoadBootstrap() {
if data, err := os.ReadFile(filepath.Join(cb.workspace, "BOOTSTRAP.md")); err == nil {
result += fmt.Sprintf("## %s\n\n%s\n\n", "BOOTSTRAP.md", string(data))
}
}
return result
}
func (cb *ContextBuilder) shouldLoadBootstrap() bool {
identityPath := filepath.Join(cb.workspace, "IDENTITY.md")
userPath := filepath.Join(cb.workspace, "USER.md")
identityData, idErr := os.ReadFile(identityPath)
userData, userErr := os.ReadFile(userPath)
if idErr != nil || userErr != nil {
return true
}
idText := strings.TrimSpace(string(identityData))
userText := strings.TrimSpace(string(userData))
if idText == "" || userText == "" {
return true
}
return false
}
func (cb *ContextBuilder) BuildMessages(history []providers.Message, summary string, currentMessage string, media []string, channel, chatID, responseLanguage string) []providers.Message {
messages := []providers.Message{}

View File

@@ -217,10 +217,11 @@ type WebToolsConfig struct {
}
type ShellConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_TOOLS_SHELL_ENABLED"`
WorkingDir string `json:"working_dir" env:"CLAWGO_TOOLS_SHELL_WORKING_DIR"`
Timeout time.Duration `json:"timeout" env:"CLAWGO_TOOLS_SHELL_TIMEOUT"`
Sandbox SandboxConfig `json:"sandbox"`
Enabled bool `json:"enabled" env:"CLAWGO_TOOLS_SHELL_ENABLED"`
WorkingDir string `json:"working_dir" env:"CLAWGO_TOOLS_SHELL_WORKING_DIR"`
Timeout time.Duration `json:"timeout" env:"CLAWGO_TOOLS_SHELL_TIMEOUT"`
AutoInstallMissing bool `json:"auto_install_missing" env:"CLAWGO_TOOLS_SHELL_AUTO_INSTALL_MISSING"`
Sandbox SandboxConfig `json:"sandbox"`
}
type SandboxConfig struct {
@@ -441,8 +442,9 @@ func DefaultConfig() *Config {
},
},
Shell: ShellConfig{
Enabled: true,
Timeout: 60 * time.Second,
Enabled: true,
Timeout: 60 * time.Second,
AutoInstallMissing: false,
Sandbox: SandboxConfig{
Enabled: false,
Image: "alpine:3.20",

View File

@@ -18,18 +18,20 @@ import (
type ExecTool struct {
workingDir string
timeout time.Duration
sandboxEnabled bool
sandboxImage string
procManager *ProcessManager
sandboxEnabled bool
sandboxImage string
autoInstallMissing bool
procManager *ProcessManager
}
func NewExecTool(cfg config.ShellConfig, workspace string, pm *ProcessManager) *ExecTool {
return &ExecTool{
workingDir: workspace,
timeout: cfg.Timeout,
sandboxEnabled: cfg.Sandbox.Enabled,
sandboxImage: cfg.Sandbox.Image,
procManager: pm,
workingDir: workspace,
timeout: cfg.Timeout,
sandboxEnabled: cfg.Sandbox.Enabled,
sandboxImage: cfg.Sandbox.Image,
autoInstallMissing: cfg.AutoInstallMissing,
procManager: pm,
}
}
@@ -142,7 +144,7 @@ func (t *ExecTool) executeCommand(ctx context.Context, command, cwd string) (str
return fmt.Sprintf("Error: Command timed out after %v", t.timeout), nil
}
if err != nil {
if err != nil && t.autoInstallMissing {
if missingCmd := detectMissingCommandFromOutput(output); missingCmd != "" {
if installLog, installed := t.tryAutoInstallMissingCommand(ctx, missingCmd, cwd); installed {
output += "\n[AUTO-INSTALL]\n" + installLog