Prune oldest message widgets if we exceed the window size. This removes widgets from the DOM but keeps data in MessageStore for potential re-hydration when scrolling up.
(self)
| 11145 | pass |
| 11146 | |
| 11147 | async def _prune_old_messages(self) -> None: |
| 11148 | """Prune oldest message widgets if we exceed the window size. |
| 11149 | |
| 11150 | This removes widgets from the DOM but keeps data in MessageStore |
| 11151 | for potential re-hydration when scrolling up. |
| 11152 | """ |
| 11153 | if not self._message_store.window_exceeded(): |
| 11154 | return |
| 11155 | |
| 11156 | try: |
| 11157 | messages_container = self.query_one("#messages", Container) |
| 11158 | except NoMatches: |
| 11159 | logger.debug("Skipping pruning: #messages container not found") |
| 11160 | return |
| 11161 | |
| 11162 | to_prune = self._message_store.get_messages_to_prune() |
| 11163 | if not to_prune: |
| 11164 | return |
| 11165 | |
| 11166 | pruned_ids: list[str] = [] |
| 11167 | for msg_data in to_prune: |
| 11168 | try: |
| 11169 | widget = messages_container.query_one(f"#{msg_data.id}") |
| 11170 | footer_id = _message_timestamp_footer_id(msg_data.id) |
| 11171 | with suppress(NoMatches): |
| 11172 | footer = messages_container.query_one(f"#{footer_id}") |
| 11173 | await footer.remove() |
| 11174 | await widget.remove() |
| 11175 | pruned_ids.append(msg_data.id) |
| 11176 | except NoMatches: |
| 11177 | # Widget not found -- do NOT mark as pruned to avoid |
| 11178 | # desyncing the store from the actual DOM state |
| 11179 | logger.debug( |
| 11180 | "Widget %s not found during pruning, skipping", |
| 11181 | msg_data.id, |
| 11182 | ) |
| 11183 | |
| 11184 | if pruned_ids: |
| 11185 | self._message_store.mark_pruned(pruned_ids) |
| 11186 | # Drop any group summaries whose members were all pruned away so a |
| 11187 | # stray collapsed line never lingers above the window. Only reachable |
| 11188 | # when something was actually pruned this pass. |
| 11189 | for summary in list(self.query(ToolGroupSummary)): |
| 11190 | if not summary.has_attached_members: |
| 11191 | try: |
| 11192 | await summary.remove() |
| 11193 | except Exception: |
| 11194 | logger.debug( |
| 11195 | "Failed to remove orphaned tool group summary", |
| 11196 | exc_info=True, |
| 11197 | ) |
| 11198 | |
| 11199 | def _close_active_tool_group(self) -> None: |
| 11200 | """Finalize the open tool group into its collapsed past-tense form.""" |
no test coverage detected