text string
}{
{
- name: "reply as it is",
- event: Event{Kind: "reply", Text: "Done."},
- text: "Done.",
+ name: "reply as it is",
+ event: Event{
+ Kind: "reply",
+ Text: "Done.",
+ },
+ text: "Done.",
},
{
- name: "own user message not shown",
- event: Event{Kind: "user", Text: "typed", Source: terminalSource},
- text: "",
+ name: "own user message not shown",
+ event: Event{
+ Kind: "user",
+ Text: "typed",
+ Source: terminalSource,
+ },
+ text: "",
},
{
- name: "user message of another source marked",
- event: Event{Kind: "user", Text: "from the phone", Source: "telegram"},
- text: "[telegram] from the phone",
+ name: "user message of another source marked",
+ event: Event{
+ Kind: "user",
+ Text: "from the phone",
+ Source: "telegram",
+ },
+ text: "[telegram] from the phone",
},
{
- name: "start of a subagent",
- event: Event{Kind: "subagent", Text: "GreenOtter"},
- text: "[GreenOtter] started",
+ name: "start of a subagent",
+ event: Event{
+ Kind: "subagent",
+ Text: "GreenOtter",
+ },
+ text: "[GreenOtter] started",
},
{
- name: "report of a subagent whole",
- event: Event{Kind: "work", Text: "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")", Source: "GreenOtter", Status: subagentFinished},
- text: "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")",
+ name: "report of a subagent whole",
+ event: Event{
+ Kind: "work",
+ Text: "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")",
+ Source: "GreenOtter",
+ Status: subagentFinished,
+ },
+ text: "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")",
},
{
- name: "long result cut",
- event: Event{Kind: "echo", Text: strings.Repeat("line\n", 12)},
- text: "[result] " + strings.Repeat("line\n", 9) + "line\n[2 more lines]",
+ name: "long result cut",
+ event: Event{
+ Kind: "echo",
+ Text: strings.Repeat("line\n", 12),
+ },
+ text: "[result] " + strings.Repeat("line\n", 9) + "line\n[2 more lines]",
},
}
Kind: "work",
Text: "[BlueBird]\n" + text,
})
+
require.Equal(t, text+"\n[BlueBird]\n"+text+"\n", out.String())
}
Kind: "reply",
Text: text,
})
+
require.Zero(t, terminalColumns(out))
contents, err := os.ReadFile(out.Name())
out := TerminalTestOutput{fd: fd}
require.Equal(t, 12, terminalColumns(&out))
terminalTestShowEvents(t, &out,
+ Event{Kind: "busy"},
Event{
Kind: "reply",
Text: "**first next last**",
Event{Kind: "busy"},
Event{Kind: "idle"},
)
- require.Equal(t, "\x1b[1mfirst next\x1b[0m\n\x1b[1mlast\x1b[0m\n[BlueBird]\n\x1b[1mReport\x1b[0m\n"+
+
+ require.Equal(t, "[working]\n\x1b[1mfirst next\x1b[0m\n\x1b[1mlast\x1b[0m\n[BlueBird]\n\x1b[1mReport\x1b[0m\n"+
"[tool] **raw tool**\n[result] **raw result**\n[error] **raw error**\n**raw notice**\n[telegram] **raw input**\n"+
- "[connected to **raw agent**]\n[BlueBird] started\n[working]\n[done]\n", out.String())
+ "[connected to **raw agent**]\n[BlueBird] started\n[working]\n[done]\n> ", out.String())
}
func TestTerminalZeroWidthUsesEightyAndReadsChanges(t *testing.T) {
Kind: "reply",
Text: strings.Repeat("a", 81),
})
- require.Equal(t, strings.Repeat("a", 80)+"\na\n", out.String())
+
+ require.Equal(t, strings.Repeat("a", 80)+"\na\n> ", out.String())
require.NoError(t, unix.IoctlSetWinsize(fd, unix.TIOCSWINSZ, &unix.Winsize{Col: 40}))
require.Equal(t, 40, terminalColumns(&out))
}
+func TestTerminalPromptsAfterIdleEventsAndClearsBeforeShownEvents(t *testing.T) {
+ fd, err := unix.Open("/dev/ptmx", unix.O_RDWR|unix.O_NOCTTY, 0)
+ require.NoError(t, err)
+
+ defer func() {
+ require.NoError(t, unix.Close(fd))
+ }()
+
+ out := TerminalTestOutput{fd: fd}
+ terminalTestShowEvents(t, &out,
+ Event{
+ Kind: "ready",
+ Text: "Example",
+ },
+ Event{
+ Kind: "user",
+ Source: terminalSource,
+ Text: "hidden",
+ },
+ Event{Kind: "unknown"},
+ Event{
+ Kind: "notice",
+ Text: "Idle notice",
+ },
+ Event{
+ Kind: "work",
+ Text: "**Idle report**",
+ },
+ Event{Kind: "busy"},
+ Event{
+ Kind: "notice",
+ Text: "Busy notice",
+ },
+ Event{
+ Kind: "reply",
+ Text: "**Answer**",
+ },
+ Event{Kind: "idle"},
+ Event{
+ Kind: "error",
+ Text: "Idle error",
+ },
+ )
+
+ require.Equal(t, "[connected to Example]\n> "+
+ "\r\x1b[2KIdle notice\n> "+
+ "\r\x1b[2K\x1b[1mIdle report\x1b[0m\n> "+
+ "\r\x1b[2K[working]\nBusy notice\n\x1b[1mAnswer\x1b[0m\n[done]\n> "+
+ "\r\x1b[2K[error] Idle error\n> ", out.String())
+}
+
+func TestTerminalNonterminalEventsHaveNoPromptOrClearCommands(t *testing.T) {
+ var out strings.Builder
+
+ terminalTestShowEvents(t, &out,
+ Event{
+ Kind: "ready",
+ Text: "Example",
+ },
+ Event{
+ Kind: "notice",
+ Text: "Idle notice",
+ },
+ Event{Kind: "busy"},
+ Event{
+ Kind: "notice",
+ Text: "Busy notice",
+ },
+ Event{
+ Kind: "reply",
+ Text: "**Answer**",
+ },
+ Event{Kind: "idle"},
+ Event{
+ Kind: "notice",
+ Text: "Idle again",
+ },
+ )
+
+ require.Equal(t, "[connected to Example]\nIdle notice\n[working]\nBusy notice\n**Answer**\n[done]\nIdle again\n", out.String())
+}
+
// TerminalTestOutput captures text while it supplies a test terminal
// descriptor.
type TerminalTestOutput struct {