Spaces:
Running
Running
File size: 8,258 Bytes
35d9120 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File Output Implementation Plan
## Overview
This plan implements file writing and return functionality for report-writing agents, enabling reports to be saved as files and returned through the Gradio ChatInterface.
## Current State Analysis
β
**Report Generation**: All agents generate markdown strings
β
**File Output Integration**: `event_to_chat_message()` supports file paths
β
**Graph Orchestrator**: Can handle file paths in results
β **File Writing**: No agents write files to disk
β **File Service**: No utility service for saving reports
---
## Implementation Plan
### PROJECT 1: File Writing Service
**Goal**: Create a reusable service for saving reports to files
#### Activity 1.1: Create Report File Service
**File**: `src/services/report_file_service.py` (NEW)
**Tasks**:
1. Create `ReportFileService` class
2. Implement `save_report()` method
- Accepts: report content (str), filename (optional), output_dir (optional)
- Returns: file path (str)
- Uses temp directory by default
- Supports custom output directory
- Handles file naming with timestamps
3. Implement `save_report_multiple_formats()` method
- Save as .md (always)
- Optionally save as .html, .pdf (future)
4. Add configuration support
- Read from settings
- Enable/disable file saving
- Configurable output directory
5. Add error handling and logging
6. Add file cleanup utilities (optional)
**Line-level subtasks**:
- Line 1-20: Imports and class definition
- Line 21-40: `__init__()` method with settings
- Line 41-80: `save_report()` method
- Line 41-50: Input validation
- Line 51-60: Directory creation
- Line 61-70: File writing
- Line 71-80: Error handling
- Line 81-100: `save_report_multiple_formats()` method
- Line 101-120: Helper methods (filename generation, cleanup)
---
### PROJECT 2: Configuration Updates
**Goal**: Add settings for file output functionality
#### Activity 2.1: Update Settings Model
**File**: `src/utils/config.py`
**Tasks**:
1. Add `save_reports_to_file: bool` field (default: True)
2. Add `report_output_directory: str | None` field (default: None, uses temp)
3. Add `report_file_format: Literal["md", "md_html", "md_pdf"]` field (default: "md")
4. Add `report_filename_template: str` field (default: "report_{timestamp}_{query_hash}.md")
**Line-level subtasks**:
- Line 166-170: Add `save_reports_to_file` field after TTS config
- Line 171-175: Add `report_output_directory` field
- Line 176-180: Add `report_file_format` field
- Line 181-185: Add `report_filename_template` field
---
### PROJECT 3: Graph Orchestrator Integration
**Goal**: Integrate file writing into graph execution
#### Activity 3.1: Update Graph Orchestrator
**File**: `src/orchestrator/graph_orchestrator.py`
**Tasks**:
1. Import `ReportFileService` at top
2. Initialize service in `__init__()` (optional, can be lazy)
3. Modify `_execute_agent_node()` for synthesizer node
- After `long_writer_agent.write_report()`, save to file
- Return dict with `{"message": report, "file": file_path}`
4. Update final event generation to handle file paths
- Already implemented, verify it works correctly
**Line-level subtasks**:
- Line 1-35: Add import for `ReportFileService`
- Line 119-148: Update `__init__()` to accept optional file service
- Line 589-650: Modify `_execute_agent_node()` synthesizer handling
- Line 642-645: After `write_report()`, add file saving
- Line 646-650: Return dict with file path
- Line 534-564: Verify final event generation handles file paths (already done)
---
### PROJECT 4: Research Flow Integration
**Goal**: Integrate file writing into research flows
#### Activity 4.1: Update IterativeResearchFlow
**File**: `src/orchestrator/research_flow.py`
**Tasks**:
1. Import `ReportFileService` at top
2. Add optional file service to `__init__()`
3. Modify `_create_final_report()` method
- After `writer_agent.write_report()`, save to file if enabled
- Return string (backward compatible) OR dict with file path
**Line-level subtasks**:
- Line 1-50: Add import for `ReportFileService`
- Line 48-120: Update `__init__()` to accept optional file service
- Line 622-667: Modify `_create_final_report()` method
- Line 647-652: After `write_report()`, add file saving
- Line 653-667: Return report string (keep backward compatible for now)
#### Activity 4.2: Update DeepResearchFlow
**File**: `src/orchestrator/research_flow.py`
**Tasks**:
1. Add optional file service to `__init__()` (if not already)
2. Modify `_create_final_report()` method
- After `long_writer_agent.write_report()` or `proofreader_agent.proofread()`, save to file
- Return string (backward compatible) OR dict with file path
**Line-level subtasks**:
- Line 670-750: Update `DeepResearchFlow.__init__()` to accept optional file service
- Line 954-1005: Modify `_create_final_report()` method
- Line 979-983: After `write_report()`, add file saving
- Line 984-989: After `proofread()`, add file saving
- Line 990-1005: Return report string (keep backward compatible)
---
### PROJECT 5: Agent Factory Integration
**Goal**: Make file service available to agents if needed
#### Activity 5.1: Update Agent Factory (Optional)
**File**: `src/agent_factory/agents.py`
**Tasks**:
1. Add optional file service parameter to agent creation functions (if needed)
2. Pass file service to agents that need it (currently not needed, agents return strings)
**Line-level subtasks**:
- Not required - agents return strings, file writing happens at orchestrator level
---
### PROJECT 6: Testing & Validation
**Goal**: Ensure file output works end-to-end
#### Activity 6.1: Unit Tests
**File**: `tests/unit/services/test_report_file_service.py` (NEW)
**Tasks**:
1. Test `save_report()` with default settings
2. Test `save_report()` with custom directory
3. Test `save_report()` with custom filename
4. Test error handling (permission errors, disk full, etc.)
5. Test file cleanup
**Line-level subtasks**:
- Line 1-30: Test fixtures and setup
- Line 31-60: Test basic save functionality
- Line 61-90: Test custom directory
- Line 91-120: Test error handling
#### Activity 6.2: Integration Tests
**File**: `tests/integration/test_file_output_integration.py` (NEW)
**Tasks**:
1. Test graph orchestrator with file output
2. Test research flows with file output
3. Test Gradio ChatInterface receives file paths
4. Test file download in Gradio UI
**Line-level subtasks**:
- Line 1-40: Test setup with mock orchestrator
- Line 41-80: Test file generation in graph execution
- Line 81-120: Test file paths in AgentEvent
- Line 121-160: Test Gradio message conversion
---
## Implementation Order
1. **PROJECT 2** (Configuration) - Foundation
2. **PROJECT 1** (File Service) - Core functionality
3. **PROJECT 3** (Graph Orchestrator) - Primary integration point
4. **PROJECT 4** (Research Flows) - Secondary integration points
5. **PROJECT 6** (Testing) - Validation
6. **PROJECT 5** (Agent Factory) - Not needed, skip
---
## File Changes Summary
### New Files
- `src/services/report_file_service.py` - File writing service
- `tests/unit/services/test_report_file_service.py` - Unit tests
- `tests/integration/test_file_output_integration.py` - Integration tests
### Modified Files
- `src/utils/config.py` - Add file output settings
- `src/orchestrator/graph_orchestrator.py` - Add file saving after report generation
- `src/orchestrator/research_flow.py` - Add file saving in both flows
---
## Gradio Integration Notes
According to Gradio ChatInterface documentation:
- File paths in chat message content are automatically converted to download links
- Markdown links like `[Download: filename](file_path)` work
- Files must be accessible from the Gradio server
- Temp files are fine as long as they exist during the session
Current implementation in `event_to_chat_message()` already handles this correctly.
---
## Success Criteria
β
Reports are saved to files when generated
β
File paths are included in AgentEvent data
β
File paths appear as download links in Gradio ChatInterface
β
File saving is configurable (can be disabled)
β
Backward compatible (existing code still works)
β
Error handling prevents crashes if file writing fails
|