(reasoningDetails: ReasoningDetail[])
| 39 | * @see https://github.com/cline/cline/issues/8214 |
| 40 | */ |
| 41 | export function consolidateReasoningDetails(reasoningDetails: ReasoningDetail[]): ReasoningDetail[] { |
| 42 | if (!reasoningDetails || reasoningDetails.length === 0) { |
| 43 | return [] |
| 44 | } |
| 45 | |
| 46 | // Group by index |
| 47 | const groupedByIndex = new Map<number, ReasoningDetail[]>() |
| 48 | |
| 49 | for (const detail of reasoningDetails) { |
| 50 | // Drop corrupted encrypted reasoning blocks that would otherwise trigger: |
| 51 | // "Invalid input: expected string, received undefined" for reasoning_details.*.data |
| 52 | // See: https://github.com/cline/cline/issues/8214 |
| 53 | if (detail.type === "reasoning.encrypted" && !detail.data) { |
| 54 | continue |
| 55 | } |
| 56 | |
| 57 | const index = detail.index ?? 0 |
| 58 | if (!groupedByIndex.has(index)) { |
| 59 | groupedByIndex.set(index, []) |
| 60 | } |
| 61 | groupedByIndex.get(index)!.push(detail) |
| 62 | } |
| 63 | |
| 64 | // Consolidate each group |
| 65 | const consolidated: ReasoningDetail[] = [] |
| 66 | |
| 67 | for (const [index, details] of groupedByIndex.entries()) { |
| 68 | // Concatenate all text parts |
| 69 | let concatenatedText = "" |
| 70 | let concatenatedSummary = "" |
| 71 | let signature: string | undefined |
| 72 | let id: string | undefined |
| 73 | let format = "unknown" |
| 74 | let type = "reasoning.text" |
| 75 | |
| 76 | for (const detail of details) { |
| 77 | if (detail.text) { |
| 78 | concatenatedText += detail.text |
| 79 | } |
| 80 | if (detail.summary) { |
| 81 | concatenatedSummary += detail.summary |
| 82 | } |
| 83 | // Keep the signature from the last item that has one |
| 84 | if (detail.signature) { |
| 85 | signature = detail.signature |
| 86 | } |
| 87 | // Keep the id from the last item that has one |
| 88 | if (detail.id) { |
| 89 | id = detail.id |
| 90 | } |
| 91 | // Keep format and type from any item (they should all be the same) |
| 92 | if (detail.format) { |
| 93 | format = detail.format |
| 94 | } |
| 95 | if (detail.type) { |
| 96 | type = detail.type |
| 97 | } |
| 98 | } |
no test coverage detected