Preamble returns the last preambleSessionCount session summaries as a compact block ready to concatenate to the system prompt. Bounded size so a year of daily sessions doesn't bloat the per-turn token cost.
(_ context.Context)
| 160 | // compact block ready to concatenate to the system prompt. Bounded size |
| 161 | // so a year of daily sessions doesn't bloat the per-turn token cost. |
| 162 | func (s *SessionFiles) Preamble(_ context.Context) (string, error) { |
| 163 | s.mu.Lock() |
| 164 | records := append([]SessionRecord(nil), s.index...) |
| 165 | s.mu.Unlock() |
| 166 | if len(records) == 0 { |
| 167 | return "", nil |
| 168 | } |
| 169 | sort.Slice(records, func(i, j int) bool { |
| 170 | return records[i].Date.After(records[j].Date) |
| 171 | }) |
| 172 | if len(records) > preambleSessionCount { |
| 173 | records = records[:preambleSessionCount] |
| 174 | } |
| 175 | var b strings.Builder |
| 176 | b.WriteString("\n\n# Recent sessions (most recent first)\n\n") |
| 177 | for _, r := range records { |
| 178 | b.WriteString("- ") |
| 179 | b.WriteString(r.Date.Format("2006-01-02 15:04")) |
| 180 | if len(r.Tags) > 0 { |
| 181 | b.WriteString(" (") |
| 182 | b.WriteString(strings.Join(r.Tags, ", ")) |
| 183 | b.WriteString(")") |
| 184 | } |
| 185 | b.WriteString(": ") |
| 186 | b.WriteString(r.Summary) |
| 187 | b.WriteString("\n") |
| 188 | } |
| 189 | return b.String(), nil |
| 190 | } |
| 191 | |
| 192 | // Close flushes the current session draft to a markdown file and adds a |
| 193 | // record to index.json. An empty draft (no Save calls) is a no-op — empty |
no outgoing calls