1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
package tmuxedit
import (
"fmt"
"strings"
"testing"
)
func TestCursorAgent_ExtractPrompt(t *testing.T) {
agent := newCursorAgent()
tests := []struct {
name string
content string
want string
}{
{
name: "box with arrow",
content: "Cursor Agent\n │ → fix the bug INSERT │",
want: "fix the bug",
},
{
name: "box without arrow",
content: "Cursor Agent\n │ fix the bug │",
want: "fix the bug",
},
{
name: "strips follow-up placeholder",
content: "Cursor\n │ → Add a follow-up │",
want: "",
},
{
name: "multi-line prompt",
content: " │ → first line of prompt │\n │ second line here │\n │ third line end │",
want: "first line of prompt\nsecond line here\nthird line end",
},
{
name: "multi-line with noise",
content: " │ → fix the bug INSERT │\n │ also refactor tests │",
want: "fix the bug\nalso refactor tests",
},
{
name: "multi-box takes last box only",
content: " ┌──────────────┐\n" +
" │ $ git push │\n" +
" └──────────────┘\n" +
" ┌──────────────┐\n" +
" │ Run command? │\n" +
" │ → Yes (enter) │\n" +
" │ No (esc) │\n" +
" └──────────────┘\n" +
" ┌──────────────┐\n" +
" │ → hello world │\n" +
" └──────────────┘\n",
want: "hello world",
},
{
name: "multi-box multi-line prompt",
content: " ┌──────────────┐\n" +
" │ $ git push │\n" +
" └──────────────┘\n" +
" ┌──────────────┐\n" +
" │ → first line │\n" +
" │ second line │\n" +
" │ third line │\n" +
" └──────────────┘\n",
want: "first line\nsecond line\nthird line",
},
{
name: "no match",
content: "no prompt here",
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := agent.ExtractPrompt(tt.content)
if got != tt.want {
t.Errorf("ExtractPrompt() = %q, want %q", got, tt.want)
}
})
}
}
func TestCursorAgent_ClearInput(t *testing.T) {
noSleep(t)
var calls []string
oldSend := sendKeys
oldRepeat := sendRepeatedKey
defer func() {
sendKeys = oldSend
sendRepeatedKey = oldRepeat
}()
sendKeys = func(paneID string, keys ...string) error {
calls = append(calls, fmt.Sprintf("send:%s:%s", paneID, strings.Join(keys, ",")))
return nil
}
sendRepeatedKey = func(paneID, key string, count int) error {
calls = append(calls, fmt.Sprintf("repeat:%s:%s*%d", paneID, key, count))
return nil
}
agent := newCursorAgent()
err := agent.ClearInput("%5")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// "End BSpace*200" should send End normally, then BSpace 200 times via -N
want := []string{
"send:%5:End",
"repeat:%5:BSpace*200",
}
if len(calls) != len(want) {
t.Fatalf("got %d calls, want %d: %v", len(calls), len(want), calls)
}
for i, w := range want {
if calls[i] != w {
t.Errorf("call[%d] = %q, want %q", i, calls[i], w)
}
}
}
func TestCursorAgent_Detect(t *testing.T) {
agent := newCursorAgent()
tests := []struct {
name string
content string
want bool
}{
{"box with arrow", "│ → type here │", true},
{"commands footer", "/ commands · @ files", true},
{"no match", "some text", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := agent.Detect(tt.content); got != tt.want {
t.Errorf("Detect() = %v, want %v", got, tt.want)
}
})
}
}
|