* Build the normalized transcript view from a Pi AgentMessage[]. * * Walks the source array once, grouping toolResult runs with the * following user message. Each TranscriptMessage holds its parts * generated lazily (so part proxies can write back to `working`).
( working: PiAgentMessage[], sessionId: string | undefined, markDirty: (messageIndex: number) => void, entryIds: readonly (string | undefined)[] | undefined, )
| 237 | * generated lazily (so part proxies can write back to `working`). |
| 238 | */ |
| 239 | function buildTranscriptView( |
| 240 | working: PiAgentMessage[], |
| 241 | sessionId: string | undefined, |
| 242 | markDirty: (messageIndex: number) => void, |
| 243 | entryIds: readonly (string | undefined)[] | undefined, |
| 244 | ): TranscriptMessage[] { |
| 245 | const result: TranscriptMessage[] = []; |
| 246 | |
| 247 | let i = 0; |
| 248 | while (i < working.length) { |
| 249 | const msg = working[i]; |
| 250 | if (msg === undefined) { |
| 251 | i += 1; |
| 252 | continue; |
| 253 | } |
| 254 | |
| 255 | if (msg.role === "toolResult") { |
| 256 | // Collect contiguous toolResult run. |
| 257 | const toolResultRun: { msg: PiToolResultMessage; index: number }[] = []; |
| 258 | while (i < working.length) { |
| 259 | const candidate = working[i]; |
| 260 | if (candidate === undefined || candidate.role !== "toolResult") break; |
| 261 | toolResultRun.push({ msg: candidate, index: i }); |
| 262 | i += 1; |
| 263 | } |
| 264 | |
| 265 | // Look ahead: if the next message is a user message, fold |
| 266 | // the tool results into it. Otherwise emit a synthetic user |
| 267 | // message for the run. |
| 268 | const next = i < working.length ? working[i] : undefined; |
| 269 | if (next?.role === "user") { |
| 270 | result.push( |
| 271 | createUserTranscriptMessage( |
| 272 | working, |
| 273 | i, |
| 274 | sessionId, |
| 275 | toolResultRun, |
| 276 | markDirty, |
| 277 | entryIds, |
| 278 | ), |
| 279 | ); |
| 280 | i += 1; |
| 281 | } else { |
| 282 | result.push( |
| 283 | createSyntheticToolResultUserMessage( |
| 284 | working, |
| 285 | sessionId, |
| 286 | toolResultRun, |
| 287 | markDirty, |
| 288 | entryIds, |
| 289 | ), |
| 290 | ); |
| 291 | } |
| 292 | continue; |
| 293 | } |
| 294 | |
| 295 | if (msg.role === "user") { |
| 296 | result.push( |
no test coverage detected