-// tooLong returns the note for a line over nodeBytes: its size and its first
-// nodeBytes bytes, which show the model where the limit cuts it.
-func tooLong(line string) string {
+// compactorTexts returns the texts of the user messages of a first try for the
+// compaction view and the task text. Each whole block of compactorBlock lines,
+// counted from the first line of the view, is one message. The last message
+// holds the rest of the lines, the closing tag, a newline, and the task. The
+// first message starts with the opening tag. Joined, the texts are the view, a
+// newline, and the task.
+func compactorTexts(view, task string) []string {
+ body := strings.TrimSuffix(strings.TrimPrefix(view, "<chat>\n"), "</chat>")
+ lines := strings.SplitAfter(body, "\n")
+ lines = lines[:len(lines)-1]
+ whole := len(lines) - len(lines)%compactorBlock
+
+ var texts []string
+
+ for n := 0; n < whole; n += compactorBlock {
+ texts = append(texts, viewMessage(n == 0, lines[n:n+compactorBlock]))
+ }
+
+ return append(texts, viewMessage(whole == 0, lines[whole:])+"</chat>\n"+task)
+}
+
+// compactorTooLong returns the note for a line over nodeBytes: its size and its
+// first nodeBytes bytes, which show the model where the limit cuts it.
+func compactorTooLong(line string) string {