| 23 | |
| 24 | @dataclass |
| 25 | class RuntimeSession: |
| 26 | prompt: str |
| 27 | context: PortContext |
| 28 | setup: WorkspaceSetup |
| 29 | setup_report: SetupReport |
| 30 | system_init_message: str |
| 31 | history: HistoryLog |
| 32 | routed_matches: list[RoutedMatch] |
| 33 | turn_result: TurnResult |
| 34 | command_execution_messages: tuple[str, ...] |
| 35 | tool_execution_messages: tuple[str, ...] |
| 36 | stream_events: tuple[dict[str, object], ...] |
| 37 | persisted_session_path: str |
| 38 | |
| 39 | def as_markdown(self) -> str: |
| 40 | lines = [ |
| 41 | '# Runtime Session', |
| 42 | '', |
| 43 | f'Prompt: {self.prompt}', |
| 44 | '', |
| 45 | '## Context', |
| 46 | render_context(self.context), |
| 47 | '', |
| 48 | '## Setup', |
| 49 | f'- Python: {self.setup.python_version} ({self.setup.implementation})', |
| 50 | f'- Platform: {self.setup.platform_name}', |
| 51 | f'- Test command: {self.setup.test_command}', |
| 52 | '', |
| 53 | '## Startup Steps', |
| 54 | *(f'- {step}' for step in self.setup.startup_steps()), |
| 55 | '', |
| 56 | '## System Init', |
| 57 | self.system_init_message, |
| 58 | '', |
| 59 | '## Routed Matches', |
| 60 | ] |
| 61 | if self.routed_matches: |
| 62 | lines.extend( |
| 63 | f'- [{match.kind}] {match.name} ({match.score}) — {match.source_hint}' |
| 64 | for match in self.routed_matches |
| 65 | ) |
| 66 | else: |
| 67 | lines.append('- none') |
| 68 | lines.extend([ |
| 69 | '', |
| 70 | '## Command Execution', |
| 71 | *(self.command_execution_messages or ('none',)), |
| 72 | '', |
| 73 | '## Tool Execution', |
| 74 | *(self.tool_execution_messages or ('none',)), |
| 75 | '', |
| 76 | '## Stream Events', |
| 77 | *(f"- {event['type']}: {event}" for event in self.stream_events), |
| 78 | '', |
| 79 | '## Turn Result', |
| 80 | self.turn_result.output, |
| 81 | '', |
| 82 | f'Persisted session path: {self.persisted_session_path}', |