( history: readonly ContextMessage[], turns: readonly ContextMessage[][], )
| 182 | } |
| 183 | |
| 184 | function buildOverview( |
| 185 | history: readonly ContextMessage[], |
| 186 | turns: readonly ContextMessage[][], |
| 187 | ): string { |
| 188 | let topic = ''; |
| 189 | for (const msg of history) { |
| 190 | if (msg.role === 'user' && !isInternalMessage(msg)) { |
| 191 | const textParts = msg.content |
| 192 | .filter((p): p is { type: 'text'; text: string } => p.type === 'text') |
| 193 | .map((p) => p.text); |
| 194 | topic = shorten(textParts.join(' '), 80); |
| 195 | break; |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | const toolCallCount = history.reduce( |
| 200 | (sum, msg) => sum + msg.toolCalls.length, |
| 201 | 0, |
| 202 | ); |
| 203 | |
| 204 | return [ |
| 205 | '## Overview', |
| 206 | '', |
| 207 | topic ? `- **Topic**: ${topic}` : '- **Topic**: (empty)', |
| 208 | `- **Conversation**: ${String(turns.length)} turns | ${String(toolCallCount)} tool calls`, |
| 209 | '', |
| 210 | '---', |
| 211 | ].join('\n'); |
| 212 | } |
| 213 | |
| 214 | export interface BuildExportMarkdownInput { |
| 215 | readonly sessionId: string; |
no test coverage detected