(parent: ChunkMessageInput[], config: ChunkerConfig)
| 258 | } |
| 259 | |
| 260 | function buildChildDrafts(parent: ChunkMessageInput[], config: ChunkerConfig): ChunkMessageInput[][] { |
| 261 | const drafts: ChunkMessageInput[][] = [] |
| 262 | let current: ChunkMessageInput[] = [] |
| 263 | let newCount = 0 |
| 264 | |
| 265 | const closeAndSeed = () => { |
| 266 | drafts.push(current) |
| 267 | const seed = config.overlapMessages > 0 ? current.slice(-config.overlapMessages) : [] |
| 268 | current = [...seed] |
| 269 | newCount = 0 |
| 270 | } |
| 271 | |
| 272 | for (const m of parent) { |
| 273 | current.push(m) |
| 274 | newCount++ |
| 275 | const effectiveChars = sumEffectiveChars(current) |
| 276 | const messageCount = current.length |
| 277 | const overChars = effectiveChars >= config.childTargetMaxChars |
| 278 | const overTokens = estimateTokens(current.map((x) => effectiveContentOf(x)).join('\n')) >= config.childHardMaxTokens |
| 279 | // 消息数软上限:高频短消息群聊里,攒够消息数且有效字符达标即关闭,避免单 chunk 混入过多消息 |
| 280 | const overSoftMessages = messageCount >= config.childSoftMaxMessages && effectiveChars >= config.childTargetMinChars |
| 281 | // 消息数硬上限:即使有效字符不足 min 也强制关闭,避免极端短消息无限堆积 |
| 282 | const overHardMessages = messageCount >= config.childHardMaxMessages |
| 283 | if (overChars || overTokens || overSoftMessages || overHardMessages) closeAndSeed() |
| 284 | } |
| 285 | |
| 286 | // flush:仅当还有新消息(避免重复上一个 child 的 overlap 尾巴) |
| 287 | if (current.length > 0 && (newCount > 0 || drafts.length === 0)) { |
| 288 | drafts.push(current) |
| 289 | } |
| 290 | return drafts |
| 291 | } |
| 292 | |
| 293 | export function chunkMessages(input: ChunkMessagesInput): ChunkResult { |
| 294 | const config = input.config ?? DEFAULT_CHUNKER_CONFIG |
no test coverage detected