| 1 | package cli |
| 2 | |
| 3 | import ( |
| 4 | "slices" |
| 5 | "strings" |
| 6 | |
| 7 | "reasonix/internal/agent" |
| 8 | "reasonix/internal/provider" |
| 9 | ) |
| 10 | |
| 11 | func cliHistoryWithoutPinnedContextRevisions(messages []provider.Message) []provider.Message { |
| 12 | for i, message := range messages { |
| 13 | if !agent.IsPinnedContextRevision(message) { |
| 14 | continue |
| 15 | } |
| 16 | visible := make([]provider.Message, 0, len(messages)-1) |
| 17 | visible = append(visible, messages[:i]...) |
| 18 | for _, candidate := range messages[i+1:] { |
| 19 | if !agent.IsPinnedContextRevision(candidate) { |
| 20 | visible = append(visible, candidate) |
| 21 | } |
| 22 | } |
| 23 | return visible |
| 24 | } |
| 25 | return messages |
| 26 | } |
| 27 | |
| 28 | // copyAssistantParts returns the Content of assistant messages after the last |
| 29 | // user message in msgs, skipping empty strings and model placeholders ("…", "..."). |
| 30 | // The result is chronological (oldest first). |
| 31 | func copyAssistantParts(msgs []provider.Message) []string { |
| 32 | lastUserIdx := -1 |
| 33 | for i, v := range slices.Backward(msgs) { |
| 34 | if v.Role == provider.RoleUser && !agent.IsPinnedContextRevision(v) { |
| 35 | lastUserIdx = i |
| 36 | break |
| 37 | } |
| 38 | } |
| 39 | start := lastUserIdx + 1 |
| 40 | if lastUserIdx < 0 { |
| 41 | start = 0 |
| 42 | } |
| 43 | var parts []string |
| 44 | for i := start; i < len(msgs); i++ { |
| 45 | if msgs[i].Role != provider.RoleAssistant { |
| 46 | continue |
| 47 | } |
| 48 | c := strings.TrimSpace(msgs[i].Content) |
| 49 | if c == "" || c == "..." || c == "…" { |
| 50 | continue |
| 51 | } |
| 52 | parts = append(parts, c) |
| 53 | } |
| 54 | return parts |
| 55 | } |
| 56 |