From 3f0a77619b2e5e6243a8844bbfaaaedf4bdc6714 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Tue, 14 Apr 2026 13:07:03 +0200 Subject: [PATCH] execute: add perl support (shebang detection, @ARGV injection, pipe support) Co-Authored-By: Claude Sonnet 4.6 --- pkg/tools/execute/pipe.go | 2 ++ pkg/tools/execute/server.go | 6 ++++-- pkg/tools/execute/tool.go | 17 ++++++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/tools/execute/pipe.go b/pkg/tools/execute/pipe.go index bff400f..73e9ca0 100644 --- a/pkg/tools/execute/pipe.go +++ b/pkg/tools/execute/pipe.go @@ -53,6 +53,8 @@ func BuildPipeline(steps []PipeStep) (string, bool, error) { switch language { case "python3": parts = append(parts, fmt.Sprintf("( python3 -c $'%s' )", ansiCEscape(code))) + case "perl": + parts = append(parts, fmt.Sprintf("( perl -e $'%s' )", ansiCEscape(code))) default: parts = append(parts, fmt.Sprintf("(\n%s\n)", code)) } diff --git a/pkg/tools/execute/server.go b/pkg/tools/execute/server.go index 676e2d6..999a8dc 100644 --- a/pkg/tools/execute/server.go +++ b/pkg/tools/execute/server.go @@ -82,7 +82,7 @@ Examples: Usage: - Scripts located in: ` + ToolsPath() + ` -- Supported languages: bash, python3 (detected from shebang) +- Supported languages: bash, python3, perl (detected from shebang) - Use for named scripts, not inline shell commands - Default timeout: 30 seconds @@ -249,8 +249,10 @@ func (e *Server) Execute(ctx context.Context, code, language string, timeout int interpreter = []string{"bash", "-c", code} case "python3", "python": interpreter = []string{"python3", "-c", code} + case "perl": + interpreter = []string{"perl", "-e", code} default: - return "", fmt.Errorf("unsupported language: %s (supported: bash, python3)", language) + return "", fmt.Errorf("unsupported language: %s (supported: bash, python3, perl)", language) } wrapped := sandbox.WrapCommand(cfg, interpreter, workDir) cmd = exec.CommandContext(ctx, wrapped[0], wrapped[1:]...) diff --git a/pkg/tools/execute/tool.go b/pkg/tools/execute/tool.go index c33fdca..1f69227 100644 --- a/pkg/tools/execute/tool.go +++ b/pkg/tools/execute/tool.go @@ -28,12 +28,17 @@ func ToolsPath() string { } // detectLanguage infers the script language from the shebang line. -// Returns "python3" for Python scripts, "bash" for everything else. +// Returns "python3", "perl", or "bash". func detectLanguage(code string) string { line, _, _ := strings.Cut(code, "\n") line = strings.TrimSpace(line) - if strings.HasPrefix(line, "#!") && strings.Contains(line, "python") { - return "python3" + if strings.HasPrefix(line, "#!") { + if strings.Contains(line, "python") { + return "python3" + } + if strings.Contains(line, "perl") { + return "perl" + } } return "bash" } @@ -47,6 +52,12 @@ func injectArgs(language, name string, args []string, code string) string { quoted[i] = fmt.Sprintf("%q", a) } return fmt.Sprintf("import sys\nsys.argv = [%q, %s]\n%s", name, strings.Join(quoted, ", "), code) + case "perl": + quoted := make([]string, len(args)) + for i, a := range args { + quoted[i] = "'" + strings.ReplaceAll(a, "'", "\\'") + "'" + } + return fmt.Sprintf("@ARGV = (%s);\n%s", strings.Join(quoted, ", "), code) default: // bash escaped := make([]string, len(args)) for i, a := range args {