chore: initial commit

This commit is contained in:
whlaoding
2026-02-21 23:01:39 +08:00
commit c2bebb3457
21 changed files with 1913 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
package shelltool
import (
"context"
"fmt"
"os/exec"
"path/filepath"
"strings"
"time"
"laodingbot/internal/logger"
)
type Tool struct {
allowedCommands map[string]struct{}
workDir string
timeout time.Duration
log *logger.Logger
}
func New(allowed []string, workDir string, timeout time.Duration, log *logger.Logger) *Tool {
set := make(map[string]struct{}, len(allowed))
for _, c := range allowed {
cmd := strings.TrimSpace(c)
if cmd != "" {
set[cmd] = struct{}{}
}
}
absDir, err := filepath.Abs(workDir)
if err != nil {
absDir = workDir
}
if timeout <= 0 {
timeout = 15 * time.Second
}
if log != nil {
log.Infof("shell tool initialized allowed_commands=%d work_dir=%s timeout=%s", len(set), absDir, timeout)
}
return &Tool{allowedCommands: set, workDir: absDir, timeout: timeout, log: log}
}
func (t *Tool) Name() string { return "shell" }
func (t *Tool) Description() string {
return "Execute allowlisted shell commands in Linux"
}
func (t *Tool) Call(ctx context.Context, input string) (string, error) {
trimmed := strings.TrimSpace(input)
if trimmed == "" {
if t.log != nil {
t.log.Warnf("shell tool rejected empty command")
}
return "", fmt.Errorf("empty command")
}
parts := strings.Fields(trimmed)
base := parts[0]
if _, ok := t.allowedCommands[base]; !ok {
if t.log != nil {
t.log.Warnf("shell command denied command=%s", base)
}
return "", fmt.Errorf("command not allowed: %s", base)
}
if t.log != nil {
t.log.Infof("shell command start command=%s args=%d", base, len(parts)-1)
}
runCtx, cancel := context.WithTimeout(ctx, t.timeout)
defer cancel()
cmd := exec.CommandContext(runCtx, base, parts[1:]...)
cmd.Dir = t.workDir
out, err := cmd.CombinedOutput()
if err != nil {
if t.log != nil {
t.log.Errorf("shell command failed command=%s err=%v output_bytes=%d", base, err, len(out))
}
return string(out), err
}
if t.log != nil {
t.log.Debugf("shell command success command=%s output_bytes=%d", base, len(out))
}
return string(out), nil
}