(
deps: SummaryDeps,
segmentId: number,
options: SummaryOptions = {}
)
| 233 | // ==================== Public API ==================== |
| 234 | |
| 235 | export async function generateSessionSummary( |
| 236 | deps: SummaryDeps, |
| 237 | segmentId: number, |
| 238 | options: SummaryOptions = {} |
| 239 | ): Promise<SummaryResult> { |
| 240 | const { locale = 'zh-CN', forceRegenerate = false, strategy = 'standard' } = options |
| 241 | const log = deps.logger |
| 242 | |
| 243 | try { |
| 244 | if (!forceRegenerate) { |
| 245 | const existing = deps.getSummary(segmentId) |
| 246 | if (existing) return { success: true, summary: existing } |
| 247 | } |
| 248 | |
| 249 | const rawMessages = deps.loadMessages(segmentId) |
| 250 | if (!rawMessages) { |
| 251 | return { success: false, error: deps.t('summary.sessionNotFound') } |
| 252 | } |
| 253 | |
| 254 | if (rawMessages.length < MIN_MESSAGE_COUNT) { |
| 255 | return { success: false, error: deps.t('summary.tooFewMessages', { count: MIN_MESSAGE_COUNT }) } |
| 256 | } |
| 257 | |
| 258 | const validMessages = filterValidMessages(rawMessages) |
| 259 | if (validMessages.length < MIN_MESSAGE_COUNT) { |
| 260 | return { success: false, error: deps.t('summary.tooFewValidMessages', { count: MIN_MESSAGE_COUNT }) } |
| 261 | } |
| 262 | |
| 263 | const lengthLimit = getSummaryLengthLimit(validMessages.length, strategy) |
| 264 | const maxTokens = strategy === 'brief' ? 300 : 600 |
| 265 | const subMaxTokens = strategy === 'brief' ? 100 : 200 |
| 266 | const content = formatMessages(validMessages) |
| 267 | |
| 268 | log?.info( |
| 269 | 'Summary', |
| 270 | `Generating summary: sessionId=${segmentId}, strategy=${strategy}, raw=${rawMessages.length}, valid=${validMessages.length}, chars=${content.length}` |
| 271 | ) |
| 272 | |
| 273 | let summary: string |
| 274 | if (content.length <= SEGMENT_THRESHOLD) { |
| 275 | summary = await deps.llmComplete( |
| 276 | deps.t('summary.systemPromptDirect'), |
| 277 | buildSummaryPrompt(content, lengthLimit, locale, strategy), |
| 278 | { temperature: 0.3, maxTokens } |
| 279 | ) |
| 280 | summary = summary.trim() |
| 281 | } else { |
| 282 | const segments = splitIntoSegments(validMessages, MAX_CONTENT_PER_CALL) |
| 283 | log?.info('Summary', `Long session segmented: ${segments.length} segments`) |
| 284 | |
| 285 | const subSummaries: string[] = [] |
| 286 | for (const segment of segments) { |
| 287 | const segContent = formatMessages(segment) |
| 288 | const sub = await deps.llmComplete( |
| 289 | deps.t('summary.systemPromptDirect'), |
| 290 | buildSubSummaryPrompt(segContent, locale, strategy), |
| 291 | { temperature: 0.3, maxTokens: subMaxTokens } |
| 292 | ) |
no test coverage detected