1package modes
2
3import (
4 "context"
5 "runtime"
6 "strings"
7 "testing"
8 "time"
9
10 "github.com/bnema/zut/packages/core"
11)
12
13func TestShellEscapeAddsOutputToAgentContext(t *testing.T) {
14 agent := core.NewAgent(nil, "", "", nil)
15 i := NewInteractive(InteractiveConfig{Agent: agent, CWD: t.TempDir()})
16 cmd := "printf zut-shell-context"
17 if runtime.GOOS == "windows" {
18 cmd = "echo zut-shell-context"
19 }
20
21 i.startShellEscape(context.Background(), cmd)
22
23 deadline := time.Now().Add(5 * time.Second)
24 for time.Now().Before(deadline) {
25 messages := agent.Messages()
26 i.mu.Lock()
27 running := i.shellRunning
28 i.mu.Unlock()
29 if len(messages) == 1 && !running {
30 text := userMessageText(messages[0])
31 if !strings.Contains(text, "zut-shell-context") {
32 t.Fatalf("shell context = %q, want command output", text)
33 }
34 if messages[0].Meta[shellEscapeMetaKey] != "true" {
35 t.Fatalf("shell context metadata = %v", messages[0].Meta)
36 }
37 return
38 }
39 time.Sleep(10 * time.Millisecond)
40 }
41 t.Fatal("shell output was not appended to agent context")
42}
43
44func TestShellEscapeCommand(t *testing.T) {
45 cases := []struct {
46 in string
47 wantCmd string
48 wantOK bool
49 }{
50 {"!ls -la", "ls -la", true},
51 {" !pwd", "pwd", true},
52 {"! go test ./... ", "go test ./...", true},
53 {"!", "", false},
54 {"! ", "", false},
55 {"ls -la", "", false},
56 {"/help", "", false},
57 {"hello !world", "", false},
58 }
59 for _, c := range cases {
60 cmd, ok := shellEscapeCommand(c.in)
61 if ok != c.wantOK || cmd != c.wantCmd {
62 t.Errorf("shellEscapeCommand(%q) = (%q,%v); want (%q,%v)",
63 c.in, cmd, ok, c.wantCmd, c.wantOK)
64 }
65 }
66}