(self, user_input: str)
| 278 | _print_tool_call(name, args) |
| 279 | |
| 280 | async def _run_investigation(self, user_input: str) -> None: |
| 281 | self._session_prompts.append(user_input) |
| 282 | |
| 283 | console.print() |
| 284 | console.print(" [dim]Thinking...[/]") |
| 285 | |
| 286 | response = await self._agent.run( |
| 287 | prompt=user_input, |
| 288 | on_tool_call=self._handle_tool_call, |
| 289 | ) |
| 290 | |
| 291 | if response.error: |
| 292 | _print_error(response.error) |
| 293 | return |
| 294 | |
| 295 | # Track tools and targets from this turn |
| 296 | for tc in response.tool_calls: |
| 297 | if tc.name not in self._session_tools: |
| 298 | self._session_tools.append(tc.name) |
| 299 | for v in tc.input.values(): |
| 300 | if isinstance(v, str) and v not in self._session_targets: |
| 301 | self._session_targets.append(v) |
| 302 | |
| 303 | if response.content: |
| 304 | self._last_response = response.content |
| 305 | _print_result(response.content) |
| 306 | |
| 307 | # Auto-save structured report |
| 308 | if "##" in response.content and len(response.content) > _MIN_REPORT_CHARS: |
| 309 | try: |
| 310 | path = _save_report(response.content) |
| 311 | self._session_report_path = str(path) |
| 312 | console.print(f" [dim]✓ Report saved → {path}[/]") |
| 313 | if not self._is_pdf_disabled: |
| 314 | await self._generate_pdf(path) |
| 315 | console.print() |
| 316 | except Exception: |
| 317 | logger.debug("Report save failed.", exc_info=True) |
| 318 | |
| 319 | async def _generate_pdf(self, md_path: Path) -> None: |
| 320 | try: |
no test coverage detected