Files
patterm/internal/app/child_input_test.go
Harry Bayliss 178b4437b1 Give injected agent submit Enter a longer settle delay
The trailing CR that submits orchestrator-injected input was written
only 15ms after the body, inside TUI agents' paste-coalescing window,
so codex (and other paste-detecting agents) intermittently swallowed it
as a newline and left the message composed but unsent. Centralize the
per-piece timing in a pure pieceWriteDelay helper: keep 15ms between
body lines but give the final lone Enter a 100ms settle gap so the
agent closes the preceding burst and registers the CR as submit. Covers
send_input, send_message, timers, and the spawn initial prompt (all go
through writeInput).

Resolves the codex composer-submit TODO item.
2026-05-25 13:00:54 +01:00

91 lines
1.9 KiB
Go

package app
import (
"bytes"
"testing"
"time"
)
func TestInputWritePiecesOnlySplitAgentEnters(t *testing.T) {
in := []byte("alpha\nbeta\rgamma")
for _, kind := range []ChildKind{KindTerminal, KindCommand} {
t.Run(string(kind), func(t *testing.T) {
got := inputWritePieces(kind, in)
if len(got) != 1 || !bytes.Equal(got[0], in) {
t.Fatalf("inputWritePieces(%s) = %#v, want one original chunk", kind, got)
}
})
}
got := inputWritePieces(KindAgent, in)
if len(got) != 5 {
t.Fatalf("agent pieces len = %d, want 5 (%#v)", len(got), got)
}
want := [][]byte{[]byte("alpha"), []byte("\n"), []byte("beta"), []byte("\r"), []byte("gamma")}
for i := range want {
if !bytes.Equal(got[i], want[i]) {
t.Fatalf("agent piece %d = %q, want %q", i, got[i], want[i])
}
}
}
func TestPieceWriteDelay(t *testing.T) {
cases := []struct {
name string
index int
total int
piece []byte
want time.Duration
}{
{
name: "first piece",
index: 0,
total: 3,
piece: []byte("body"),
want: 0,
},
{
name: "middle body piece",
index: 1,
total: 3,
piece: []byte("body"),
want: agentInterPieceDelay,
},
{
name: "final carriage return submit",
index: 1,
total: 2,
piece: []byte("\r"),
want: agentSubmitSettleDelay,
},
{
name: "final newline submit",
index: 1,
total: 2,
piece: []byte("\n"),
want: agentSubmitSettleDelay,
},
{
name: "final non-enter piece",
index: 2,
total: 3,
piece: []byte("tail"),
want: agentInterPieceDelay,
},
{
name: "standalone enter fast path",
index: 0,
total: 1,
piece: []byte("\r"),
want: 0,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := pieceWriteDelay(tc.index, tc.total, tc.piece); got != tc.want {
t.Fatalf("pieceWriteDelay(%d, %d, %q) = %s, want %s", tc.index, tc.total, tc.piece, got, tc.want)
}
})
}
}