Skip to content

Commit d803fc0

Browse files
committed
more robust user input removal
1 parent 69540b1 commit d803fc0

File tree

3 files changed

+75
-26
lines changed

3 files changed

+75
-26
lines changed

lib/msgfmt/msgfmt.go

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,40 +99,43 @@ func findUserInputStartIdx(msg []rune, msgRuneLineLocations []int, userInput []r
9999
return IndexSubslice(msgPrefix, userInputPrefix)
100100
}
101101

102+
// Find the next match between the message and the user input.
103+
// We're assuming that user input likely won't be truncated much,
104+
// but it's likely some characters will be missing (e.g. OpenAI Codex strips
105+
// "```" and instead formats enclosed text as a code block).
106+
// We're going to see if any of the next 5 runes in the message
107+
// match any of the next 5 runes in the user input.
108+
func findNextMatch(knownMsgMatchIdx int, knownUserInputMatchIdx int, msg []rune, userInput []rune) (int, int) {
109+
for i := range 5 {
110+
for j := range 5 {
111+
userInputIdx := knownUserInputMatchIdx + i + 1
112+
msgIdx := knownMsgMatchIdx + j + 1
113+
114+
if userInputIdx >= len(userInput) || msgIdx >= len(msg) {
115+
return -1, -1
116+
}
117+
if userInput[userInputIdx] == msg[msgIdx] {
118+
return msgIdx, userInputIdx
119+
}
120+
}
121+
}
122+
return -1, -1
123+
}
124+
102125
// Find where the user input ends in the message. Returns the index of the last rune
103126
// of the user input in the message.
104127
func findUserInputEndIdx(userInputStartIdx int, msg []rune, userInput []rune) int {
105128
userInputIdx := 0
106129
msgIdx := userInputStartIdx
107-
OuterLoop:
108130
for {
109-
if userInputIdx >= len(userInput) {
131+
m, u := findNextMatch(msgIdx, userInputIdx, msg, userInput)
132+
if m == -1 || u == -1 {
110133
break
111134
}
112-
if msgIdx >= len(msg) {
113-
break
114-
}
115-
if userInput[userInputIdx] == msg[msgIdx] {
116-
userInputIdx++
117-
msgIdx++
118-
continue
119-
}
120-
// If we haven't found a match, we'll search the next 5 runes of the message.
121-
// If we can't find a match, we'll assume the echoed user input was truncated.
122-
// 5 is arbitrary.
123-
for i := 1; i <= 5; i++ {
124-
if msgIdx+i >= len(msg) {
125-
break
126-
}
127-
if userInput[userInputIdx] == msg[msgIdx+i] {
128-
userInputIdx++
129-
msgIdx = msgIdx + i
130-
continue OuterLoop
131-
}
132-
}
133-
break
135+
msgIdx = m
136+
userInputIdx = u
134137
}
135-
return msgIdx - 1
138+
return msgIdx
136139
}
137140

138141
// RemoveUserInput removes the user input from the message.

lib/msgfmt/msgfmt_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ func TestFindUserInputEndIdx(t *testing.T) {
168168
msg := "Hello,World!"
169169
userInput := "/init"
170170
userInputEndIdx := findUserInputEndIdx(len(msg), []rune(msg), []rune(userInput))
171-
assert.Equal(t, len(msg)-1, userInputEndIdx)
171+
// returns the same index as userInputStartIdx
172+
assert.Equal(t, len(msg), userInputEndIdx)
172173
})
173174
}
174175

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
thinking for 10s
2+
3+
command
4+
5+
$ grep -R "Process) Close" -n .
6+
7+
command.stdout (code: 0, duration: 6.9s)
8+
9+
./lib/termexec/termexec.go:76:func (p *Process) Close(logger *slog.Logger,
10+
timeout time.Duration) error {
11+
./lib/msgfmt/testdata/format/codex/multi_line2/msg.txt:9:│ func (p *Process)
12+
Close(logger *slog.Logger, timeout time.Duration) error { │
13+
./lib/msgfmt/testdata/format/codex/multi_line2/msg.txt:37: func (p
14+
*Process) Close(logger *slog.Logger, timeout time.Duration) error {
15+
./lib/msgfmt/testdata/format/codex/multi_line/user.txt:6:func (p *Process)
16+
Close(logger *slog.Logger, timeout time.Duration) error {
17+
... (2 more lines)
18+
19+
thinking for 20s
20+
21+
command
22+
23+
$ sed -n '1,150p' lib/termexec/termexec.go
24+
25+
command.stdout (code: 0, duration: 0s)
26+
27+
package termexec
28+
29+
import (
30+
"context"
31+
... (113 more lines)
32+
33+
thinking for 26s
34+
35+
codex
36+
That’s the Close method on the Process type in the termexec package. You can
37+
find it here:
38+
39+
lib/termexec/termexec.go, starting at line 76:
40+
41+
// Closecloses the process using a SIGINT signal …
42+
func (p *Process) Close(logger *slog.Logger, timeout time.Duration)
43+
error {
44+
45+
}

0 commit comments

Comments
 (0)