diff --git a/misc/crush/Makefile b/misc/crush/Makefile index ed431499b223..ea7ee8b59fd8 100644 --- a/misc/crush/Makefile +++ b/misc/crush/Makefile @@ -1,67 +1,67 @@ PORTNAME= crush DISTVERSIONPREFIX= v -DISTVERSION= 0.81.0 +DISTVERSION= 0.84.0 CATEGORIES= misc devel MAINTAINER= tagattie@FreeBSD.org COMMENT= Glamourous AI coding agent for your favourite terminal WWW= https://github.com/charmbracelet/crush LICENSE= FSL-1.1-MIT LICENSE_NAME= Functional Source License, Version 1.1, MIT Future License LICENSE_FILE= ${WRKSRC}/LICENSE.md LICENSE_PERMS= dist-mirror pkg-mirror auto-accept USES= go:1.26+,modules GO_MODULE= github.com/charmbracelet/crush GO_LDFLAGS= -w -X github.com/charmbracelet/crush/internal/version.Version=${DISTVERSION} PLIST_FILES= bin/${PORTNAME} PORTDOCS= README.md OPTIONS_DEFINE= COMPLETIONS DISABLE_COMMAND_BLOCKING DOCS MANPAGES OPTIONS_DEFAULT= COMPLETIONS DISABLE_COMMAND_BLOCKING MANPAGES COMPLETIONS_DESC= Build and/or install shell completions DISABLE_COMMAND_BLOCKING_DESC= Support for disabling dangerous command blocking COMPLETIONS_PLIST_FILES=etc/bash_completion.d/${PORTNAME} \ share/fish/completions/${PORTNAME}.fish \ share/zsh/site-functions/_${PORTNAME} DISABLE_COMMAND_BLOCKING_EXTRA_PATCHES= ${PATCHDIR}/extra-patch-disable-command-blocking MANPAGES_PLIST_FILES= share/man/man1/${PORTNAME}.1.gz post-build-COMPLETIONS-on: @${MKDIR} ${GO_WRKSRC}/completions .for sh in bash fish zsh ${GO_WRKDIR_BIN}/${PORTNAME} completion ${sh} > \ ${GO_WRKSRC}/completions/${PORTNAME}.${sh} .endfor post-build-MANPAGES-on: @${MKDIR} ${GO_WRKSRC}/manpages ${GO_WRKDIR_BIN}/${PORTNAME} man > ${GO_WRKSRC}/manpages/${PORTNAME}.1 post-install-COMPLETIONS-on: @${MKDIR} ${STAGEDIR}${PREFIX}/etc/bash_completion.d \ ${STAGEDIR}${PREFIX}/share/fish/completions \ ${STAGEDIR}${PREFIX}/share/zsh/site-functions ${INSTALL_DATA} ${GO_WRKSRC}/completions/${PORTNAME}.bash \ ${STAGEDIR}${PREFIX}/etc/bash_completion.d/${PORTNAME} ${INSTALL_DATA} ${GO_WRKSRC}/completions/${PORTNAME}.fish \ ${STAGEDIR}${PREFIX}/share/fish/completions/${PORTNAME}.fish ${INSTALL_DATA} ${GO_WRKSRC}/completions/${PORTNAME}.zsh \ ${STAGEDIR}${PREFIX}/share/zsh/site-functions/_${PORTNAME} post-install-DOCS-on: @${MKDIR} ${STAGEDIR}${DOCSDIR} ${INSTALL_MAN} ${PORTDOCS:S|^|${GO_WRKSRC}/|} ${STAGEDIR}${DOCSDIR} post-install-MANPAGES-on: ${INSTALL_MAN} ${GO_WRKSRC}/manpages/${PORTNAME}.1 \ ${STAGEDIR}/${PREFIX}/share/man/man1 .include diff --git a/misc/crush/distinfo b/misc/crush/distinfo index 8ef2bcd6f379..1b9de142a0f7 100644 --- a/misc/crush/distinfo +++ b/misc/crush/distinfo @@ -1,5 +1,5 @@ -TIMESTAMP = 1782974253 -SHA256 (go/misc_crush/crush-v0.81.0/v0.81.0.mod) = 0e78633eca5405456c2047ce8dc51241dc9912bbbad9c2458675799b29040996 -SIZE (go/misc_crush/crush-v0.81.0/v0.81.0.mod) = 10624 -SHA256 (go/misc_crush/crush-v0.81.0/v0.81.0.zip) = 0238ad4f84149ca67d4dbc73be37c4ce9ff459bb944b70a0a5affce1c6ce48f8 -SIZE (go/misc_crush/crush-v0.81.0/v0.81.0.zip) = 2294639 +TIMESTAMP = 1783649236 +SHA256 (go/misc_crush/crush-v0.84.0/v0.84.0.mod) = 5f17f796624b899417ded1ca9c282f9ffc4b987259adaa31877186fa7bff0e13 +SIZE (go/misc_crush/crush-v0.84.0/v0.84.0.mod) = 10624 +SHA256 (go/misc_crush/crush-v0.84.0/v0.84.0.zip) = ba77fda6a5bb8b172ed2eb6475d8db8d7b1f2e17852d3f7a0e3794a00c4c3eaf +SIZE (go/misc_crush/crush-v0.84.0/v0.84.0.zip) = 2316515 diff --git a/misc/crush/files/extra-patch-disable-command-blocking b/misc/crush/files/extra-patch-disable-command-blocking index 400bcb76fafd..39b236d13e64 100644 --- a/misc/crush/files/extra-patch-disable-command-blocking +++ b/misc/crush/files/extra-patch-disable-command-blocking @@ -1,110 +1,110 @@ --- internal/agent/common_test.go.orig 1979-11-29 15:00:00 UTC +++ internal/agent/common_test.go @@ -167,7 +167,7 @@ func coderAgent(r *vcr.Recorder, env fakeEnv, large, s } allTools := []fantasy.AgentTool{ - tools.NewBashTool(env.permissions, env.workingDir, cfg.Config().Options.Attribution, modelName), + tools.NewBashTool(env.permissions, env.workingDir, cfg.Config().Options.Attribution, modelName, cfg.Config().Options.DisableCommandBlocking), tools.NewDownloadTool(env.permissions, env.workingDir, r.GetDefaultClient()), tools.NewEditTool(nil, env.permissions, env.history, *env.filetracker, env.workingDir), tools.NewMultiEditTool(nil, env.permissions, env.history, *env.filetracker, env.workingDir), --- internal/agent/coordinator.go.orig 1979-11-29 15:00:00 UTC +++ internal/agent/coordinator.go -@@ -647,7 +647,7 @@ func (c *coordinator) buildTools(ctx context.Context, +@@ -656,7 +656,7 @@ func (c *coordinator) buildTools(ctx context.Context, allTools = append( allTools, - tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Config().Options.Attribution, modelID), + tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Config().Options.Attribution, modelID, c.cfg.Config().Options.DisableCommandBlocking), tools.NewCrushInfoTool(c.cfg, c.lspManager, c.allSkills, c.activeSkills, c.skillTracker), tools.NewCrushLogsTool(logFile), tools.NewJobOutputTool(), --- internal/agent/tools/bash.go.orig 1979-11-29 15:00:00 UTC +++ internal/agent/tools/bash.go @@ -145,8 +145,11 @@ var bannedCommands = []string{ "ufw", } -func bashDescription(attribution *config.Attribution, modelID string) string { +func bashDescription(attribution *config.Attribution, modelID string, disableBlocking bool) string { bannedCommandsStr := strings.Join(bannedCommands, ", ") + if disableBlocking { + bannedCommandsStr = "none" + } var out bytes.Buffer if err := bashDescriptionTpl.Execute(&out, bashDescriptionData{ BannedCommands: bannedCommandsStr, @@ -162,7 +165,10 @@ func bashDescription(attribution *config.Attribution, return out.String() } -func blockFuncs() []shell.BlockFunc { +func blockFuncs(disableBlocking bool) []shell.BlockFunc { + if disableBlocking { + return nil + } return []shell.BlockFunc{ shell.CommandsBlocker(bannedCommands), @@ -194,10 +200,10 @@ func blockFuncs() []shell.BlockFunc { } } -func NewBashTool(permissions permission.Service, workingDir string, attribution *config.Attribution, modelID string) fantasy.AgentTool { +func NewBashTool(permissions permission.Service, workingDir string, attribution *config.Attribution, modelID string, disableBlocking bool) fantasy.AgentTool { return fantasy.NewAgentTool( BashToolName, - string(bashDescription(attribution, modelID)), + string(bashDescription(attribution, modelID, disableBlocking)), func(ctx context.Context, params BashParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) { if params.Command == "" { return fantasy.NewTextErrorResponse("missing command"), nil @@ -251,7 +257,7 @@ func NewBashTool(permissions permission.Service, worki bgManager := shell.GetBackgroundShellManager() bgManager.Cleanup() // Use background context so it continues after tool returns - bgShell, err := bgManager.Start(context.Background(), execWorkingDir, blockFuncs(), params.Command, params.Description) + bgShell, err := bgManager.Start(context.Background(), execWorkingDir, blockFuncs(disableBlocking), params.Command, params.Description) if err != nil { return fantasy.ToolResponse{}, fmt.Errorf("error starting background shell: %w", err) } @@ -306,7 +312,7 @@ func NewBashTool(permissions permission.Service, worki // Start with detached context so it can survive if moved to background bgManager := shell.GetBackgroundShellManager() bgManager.Cleanup() - bgShell, err := bgManager.Start(context.Background(), execWorkingDir, blockFuncs(), params.Command, params.Description) + bgShell, err := bgManager.Start(context.Background(), execWorkingDir, blockFuncs(disableBlocking), params.Command, params.Description) if err != nil { return fantasy.ToolResponse{}, fmt.Errorf("error starting shell: %w", err) } --- internal/agent/tools/bash_test.go.orig 1979-11-29 15:00:00 UTC +++ internal/agent/tools/bash_test.go @@ -117,7 +117,7 @@ func newBashToolForTest(workingDir string) fantasy.Age func newBashToolForTest(workingDir string) fantasy.AgentTool { permissions := &mockBashPermissionService{Broker: pubsub.NewBroker[permission.PermissionRequest]()} attribution := &config.Attribution{TrailerStyle: config.TrailerStyleNone} - return NewBashTool(permissions, workingDir, attribution, "test-model") + return NewBashTool(permissions, workingDir, attribution, "test-model", false) } func newBashToolWithRecordingPerms(workingDir string, allow bool) (fantasy.AgentTool, *recordingPermissionService) { @@ -126,7 +126,7 @@ func newBashToolWithRecordingPerms(workingDir string, allow: allow, } attribution := &config.Attribution{TrailerStyle: config.TrailerStyleNone} - return NewBashTool(perms, workingDir, attribution, "test-model"), perms + return NewBashTool(perms, workingDir, attribution, "test-model", false), perms } func TestBashTool_ChainedCommandsRequirePermission(t *testing.T) { --- internal/config/config.go.orig 1979-11-29 15:00:00 UTC +++ internal/config/config.go @@ -281,6 +281,7 @@ type Options struct { Debug bool `json:"debug,omitempty" jsonschema:"description=Enable debug logging,default=false"` DebugLSP bool `json:"debug_lsp,omitempty" jsonschema:"description=Enable debug logging for LSP servers,default=false"` DisableAutoSummarize bool `json:"disable_auto_summarize,omitempty" jsonschema:"description=Disable automatic conversation summarization,default=false"` + DisableCommandBlocking bool `json:"disable_command_blocking,omitempty" jsonschema:"description=Disable blocking of potentially dangerous commands (unsafe),default=false"` // DataDirectory is where Crush keeps per-project state such as // the SQLite database and workspace overrides. Relative paths are // resolved against the working directory; absolute paths are used