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
|
package main
import (
"fmt"
"mm/internal/detector"
"mm/internal/ui"
)
// reportLoop shows the user what the loop detector already tells the model
// (ticket 153): a warning while the model repeats itself, a severe struggle
// once the detector stops the turn — and a warning when calls keep failing
// with different inputs (ticket 160), which the model is not told about.
//
// reportLoop(detector.Loop{Tool: "bash", Repeats: 4}) // ⚠ loop: bash ×4
// reportLoop(detector.Loop{Tool: "bash", Repeats: 6, Stuck: true}) // ✖ stuck: bash ×6
// reportLoop(detector.Loop{Tool: "bash", Repeats: 3, Failing: true}) // ⚠ failing: 3 tool calls in a row
func reportLoop(l detector.Loop) {
ui.ReportStruggle(loopStruggle(l))
}
// loopStruggle is reportLoop's struggle, kept apart so it can be tested
// without a front end.
func loopStruggle(l detector.Loop) ui.Struggle {
if l.Failing {
return ui.Struggle{Label: fmt.Sprintf("failing: %d tool calls in a row", l.Repeats)}
}
if l.Stuck {
return ui.Struggle{Severe: true, Label: fmt.Sprintf("stuck: %s ×%d", l.Tool, l.Repeats)}
}
return ui.Struggle{Label: fmt.Sprintf("loop: %s ×%d", l.Tool, l.Repeats)}
}
|