|
32 | 32 | function RenderState:reset() |
33 | 33 | self._messages = {} |
34 | 34 | self._parts = {} |
| 35 | + self._orphan_parts = {} |
| 36 | + self._orphan_parts_index = {} |
35 | 37 | self._part_ranges = {} |
36 | 38 | self._message_ranges = {} |
37 | 39 | self._ranges_valid = false |
@@ -205,6 +207,82 @@ function RenderState:get_message(message_id) |
205 | 207 | return self._messages[message_id] |
206 | 208 | end |
207 | 209 |
|
| 210 | +---@param message_id string |
| 211 | +---@param part OpencodeMessagePart |
| 212 | +function RenderState:upsert_orphan_part(message_id, part) |
| 213 | + if not message_id or not part or not part.id then |
| 214 | + return |
| 215 | + end |
| 216 | + |
| 217 | + local orphan_parts = self._orphan_parts[message_id] |
| 218 | + if not orphan_parts then |
| 219 | + orphan_parts = {} |
| 220 | + self._orphan_parts[message_id] = orphan_parts |
| 221 | + self._orphan_parts_index[message_id] = {} |
| 222 | + end |
| 223 | + |
| 224 | + local orphan_index = self._orphan_parts_index[message_id] |
| 225 | + local idx = orphan_index[part.id] |
| 226 | + if idx then |
| 227 | + orphan_parts[idx] = part |
| 228 | + else |
| 229 | + orphan_parts[#orphan_parts + 1] = part |
| 230 | + orphan_index[part.id] = #orphan_parts |
| 231 | + end |
| 232 | +end |
| 233 | + |
| 234 | +---@param message_id string |
| 235 | +---@return OpencodeMessagePart[] |
| 236 | +function RenderState:consume_orphan_parts(message_id) |
| 237 | + if not message_id then |
| 238 | + return {} |
| 239 | + end |
| 240 | + |
| 241 | + local orphan_parts = self._orphan_parts[message_id] or {} |
| 242 | + self._orphan_parts[message_id] = nil |
| 243 | + self._orphan_parts_index[message_id] = nil |
| 244 | + return orphan_parts |
| 245 | +end |
| 246 | + |
| 247 | +---@param message_id string |
| 248 | +---@param part_id string |
| 249 | +---@return boolean |
| 250 | +function RenderState:remove_orphan_part(message_id, part_id) |
| 251 | + local orphan_parts = message_id and self._orphan_parts[message_id] |
| 252 | + local orphan_index = message_id and self._orphan_parts_index[message_id] |
| 253 | + local idx = orphan_index and orphan_index[part_id] |
| 254 | + if not idx then |
| 255 | + return false |
| 256 | + end |
| 257 | + |
| 258 | + table.remove(orphan_parts, idx) |
| 259 | + orphan_index[part_id] = nil |
| 260 | + |
| 261 | + for i = idx, #orphan_parts do |
| 262 | + local part = orphan_parts[i] |
| 263 | + if part and part.id then |
| 264 | + orphan_index[part.id] = i |
| 265 | + end |
| 266 | + end |
| 267 | + |
| 268 | + if #orphan_parts == 0 then |
| 269 | + self._orphan_parts[message_id] = nil |
| 270 | + self._orphan_parts_index[message_id] = nil |
| 271 | + end |
| 272 | + |
| 273 | + return true |
| 274 | +end |
| 275 | + |
| 276 | +---@param message_id string |
| 277 | +function RenderState:clear_orphan_parts(message_id) |
| 278 | + if not message_id then |
| 279 | + return |
| 280 | + end |
| 281 | + |
| 282 | + self._orphan_parts[message_id] = nil |
| 283 | + self._orphan_parts_index[message_id] = nil |
| 284 | +end |
| 285 | + |
208 | 286 | ---@param line integer 1-indexed |
209 | 287 | ---@return RenderedMessage? |
210 | 288 | function RenderState:get_message_at_line(line) |
|
0 commit comments