deepagents-printshop 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. agents/content_editor/__init__.py +1 -0
  2. agents/content_editor/agent.py +279 -0
  3. agents/content_editor/content_reviewer.py +327 -0
  4. agents/content_editor/versioned_agent.py +455 -0
  5. agents/latex_specialist/__init__.py +1 -0
  6. agents/latex_specialist/agent.py +531 -0
  7. agents/latex_specialist/latex_analyzer.py +510 -0
  8. agents/latex_specialist/latex_optimizer.py +1192 -0
  9. agents/qa_orchestrator/__init__.py +1 -0
  10. agents/qa_orchestrator/agent.py +603 -0
  11. agents/qa_orchestrator/langgraph_workflow.py +733 -0
  12. agents/qa_orchestrator/pipeline_types.py +72 -0
  13. agents/qa_orchestrator/quality_gates.py +495 -0
  14. agents/qa_orchestrator/workflow_coordinator.py +139 -0
  15. agents/research_agent/__init__.py +1 -0
  16. agents/research_agent/agent.py +258 -0
  17. agents/research_agent/llm_report_generator.py +1023 -0
  18. agents/research_agent/report_generator.py +536 -0
  19. agents/visual_qa/__init__.py +1 -0
  20. agents/visual_qa/agent.py +410 -0
  21. deepagents_printshop-0.1.0.dist-info/METADATA +744 -0
  22. deepagents_printshop-0.1.0.dist-info/RECORD +37 -0
  23. deepagents_printshop-0.1.0.dist-info/WHEEL +4 -0
  24. deepagents_printshop-0.1.0.dist-info/entry_points.txt +2 -0
  25. deepagents_printshop-0.1.0.dist-info/licenses/LICENSE +86 -0
  26. tools/__init__.py +1 -0
  27. tools/change_tracker.py +419 -0
  28. tools/content_type_loader.py +171 -0
  29. tools/graph_generator.py +281 -0
  30. tools/latex_generator.py +374 -0
  31. tools/llm_latex_generator.py +678 -0
  32. tools/magazine_layout.py +462 -0
  33. tools/pattern_injector.py +250 -0
  34. tools/pattern_learner.py +477 -0
  35. tools/pdf_compiler.py +386 -0
  36. tools/version_manager.py +346 -0
  37. tools/visual_qa.py +799 -0
@@ -0,0 +1,455 @@
1
+ """
2
+ Versioned Content Editor Agent - Milestone 2
3
+
4
+ Enhanced content editor that integrates with version management and change tracking.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Dict, List, Optional
11
+ import json
12
+ from datetime import datetime
13
+
14
+ # Add project root to path
15
+ project_root = Path(__file__).parent.parent.parent
16
+ sys.path.insert(0, str(project_root))
17
+
18
+ from agents.content_editor.content_reviewer import ContentReviewer
19
+ from tools.version_manager import VersionManager
20
+ from tools.change_tracker import ChangeTracker
21
+
22
+
23
+ class VersionedContentEditorAgent:
24
+ """
25
+ Content Editor Agent with version management capabilities.
26
+
27
+ Features:
28
+ - Automatic version creation for improvements
29
+ - Change tracking between versions
30
+ - Quality progression analysis
31
+ - Integration with existing content review workflow
32
+ """
33
+
34
+ def __init__(self, memory_dir: str = ".deepagents/content_editor/memories",
35
+ content_source: str = "research_report"):
36
+ """
37
+ Initialize the versioned content editor agent.
38
+
39
+ Args:
40
+ memory_dir: Directory for storing agent memories
41
+ content_source: Content source folder (e.g., 'research_report', 'magazine')
42
+ """
43
+ self.memory_dir = Path(memory_dir)
44
+ self.memory_dir.mkdir(parents=True, exist_ok=True)
45
+ self.content_source = content_source
46
+
47
+ # Initialize components
48
+ self.content_reviewer = ContentReviewer()
49
+ self.version_manager = VersionManager()
50
+ self.change_tracker = ChangeTracker()
51
+
52
+ # Paths - use content source subdirectory
53
+ self.input_dir = Path(f"artifacts/sample_content/{content_source}")
54
+ self.reports_dir = Path("artifacts/agent_reports/quality")
55
+
56
+ # Ensure directories exist
57
+ self.reports_dir.mkdir(parents=True, exist_ok=True)
58
+
59
+ # Initialize memory
60
+ self.init_memory()
61
+
62
+ def init_memory(self):
63
+ """Initialize agent memory files."""
64
+ memory_files = {
65
+ "version_strategy.md": """# Version Management Strategy
66
+
67
+ ## Version Naming Convention
68
+ - v0_original: Original source content (baseline)
69
+ - v1_content_edited: Content editor improvements
70
+ - v2_latex_optimized: LaTeX specialist improvements
71
+ - v3_visual_refined: Visual QA improvements
72
+
73
+ ## Quality Thresholds
74
+ - Minimum improvement for new version: +5 points
75
+ - Quality gate for human review: 85+ points
76
+ - Rollback threshold: Quality decrease > 10 points
77
+
78
+ ## Change Tracking
79
+ - Track all content modifications
80
+ - Generate diffs for human review
81
+ - Maintain quality progression analysis
82
+ - Store change summaries for learning
83
+ """,
84
+ "improvement_patterns.md": """# Content Improvement Patterns
85
+
86
+ ## Successful Improvements Tracked
87
+ - Grammar and spelling corrections
88
+ - Sentence structure optimization
89
+ - Readability enhancements
90
+ - Academic tone adjustments
91
+
92
+ ## Quality Metrics to Track
93
+ - Flesch Reading Ease improvements
94
+ - Sentence length optimization
95
+ - Passive voice reduction
96
+ - Error count reduction
97
+
98
+ ## Version Comparison Insights
99
+ - Track which types of changes yield best quality improvements
100
+ - Identify content types that benefit most from editing
101
+ - Monitor quality regression patterns
102
+ """,
103
+ "agent_coordination.md": """# Multi-Agent Coordination
104
+
105
+ ## Version Handoff Protocol
106
+ 1. Content Editor creates v1_content_edited
107
+ 2. LaTeX Specialist receives v1, creates v2_latex_optimized
108
+ 3. Visual QA receives v2, creates v3_visual_refined
109
+ 4. Human review at quality gate thresholds
110
+
111
+ ## Quality Progression Management
112
+ - Each agent must improve quality score
113
+ - Rollback if quality decreases significantly
114
+ - Track agent-specific improvement patterns
115
+ - Coordinate version naming and metadata
116
+ """
117
+ }
118
+
119
+ for filename, content in memory_files.items():
120
+ file_path = self.memory_dir / filename
121
+ if not file_path.exists():
122
+ with open(file_path, 'w', encoding='utf-8') as f:
123
+ f.write(content)
124
+
125
+ def load_original_content(self) -> Dict[str, str]:
126
+ """Load original content from sample_content directory."""
127
+ content_dict = {}
128
+
129
+ for file_path in self.input_dir.glob("*.md"):
130
+ with open(file_path, 'r', encoding='utf-8') as f:
131
+ content_dict[file_path.name] = f.read()
132
+
133
+ return content_dict
134
+
135
+ def create_baseline_version(self) -> Dict:
136
+ """
137
+ Create v0_original baseline version from sample content.
138
+
139
+ Returns:
140
+ Version info for the baseline
141
+ """
142
+ original_content = self.load_original_content()
143
+
144
+ if not original_content:
145
+ raise ValueError("No original content found in sample_content directory")
146
+
147
+ # Check if baseline already exists
148
+ baseline_version = self.version_manager.get_version("v0_original")
149
+ if baseline_version:
150
+ print("āœ“ Baseline version v0_original already exists")
151
+ return baseline_version
152
+
153
+ # Create baseline version
154
+ version_info = self.version_manager.create_version(
155
+ content_dict=original_content,
156
+ version_name="v0_original",
157
+ agent_name="baseline",
158
+ parent_version=None,
159
+ metadata={
160
+ "description": "Original source content from sample_content",
161
+ "purpose": "baseline",
162
+ "quality_score": None # Will be calculated
163
+ }
164
+ )
165
+
166
+ print(f"āœ“ Created baseline version: v0_original with {len(original_content)} files")
167
+ return version_info
168
+
169
+ def process_content_with_versioning(self,
170
+ target_version: str = "v1_content_edited",
171
+ parent_version: str = "v0_original") -> Dict:
172
+ """
173
+ Process content with full version management.
174
+
175
+ Args:
176
+ target_version: Name for the new version to create
177
+ parent_version: Parent version to improve from
178
+
179
+ Returns:
180
+ Processing results with version information
181
+ """
182
+ print(f"šŸ”„ Processing content: {parent_version} → {target_version}")
183
+
184
+ # Ensure baseline exists
185
+ self.create_baseline_version()
186
+
187
+ # Load parent version content
188
+ if parent_version == "v0_original":
189
+ parent_content = self.load_original_content()
190
+ else:
191
+ parent_content = self.version_manager.get_version_content(parent_version)
192
+
193
+ # Calculate parent quality scores
194
+ parent_quality_scores = {}
195
+ parent_total_score = 0
196
+
197
+ for filename, content in parent_content.items():
198
+ metrics = self.content_reviewer.analyze_readability(content)
199
+ issues = self.content_reviewer._identify_issues(content, metrics)
200
+ quality_score = self.content_reviewer.calculate_quality_score(metrics, issues)
201
+ parent_quality_scores[filename] = quality_score
202
+ parent_total_score += quality_score
203
+
204
+ parent_avg_quality = parent_total_score / len(parent_content) if parent_content else 0
205
+
206
+ # Process each file for improvements
207
+ improved_content = {}
208
+ improvement_results = {}
209
+
210
+ # config.md is structured data (type IDs, manifest, options) — not prose.
211
+ # Editing it corrupts field names and values the downstream pipeline depends on.
212
+ skip_files = {"config.md"}
213
+
214
+ for filename, content in parent_content.items():
215
+ if filename in skip_files:
216
+ print(f" šŸ“„ Skipping {filename} (structured config)")
217
+ improved_content[filename] = content
218
+ improvement_results[filename] = {
219
+ "original_quality_score": parent_quality_scores[filename],
220
+ "improved_quality_score": parent_quality_scores[filename],
221
+ "quality_improvement": 0,
222
+ "changes_summary": "Skipped — structured configuration file",
223
+ }
224
+ continue
225
+
226
+ print(f" šŸ“„ Processing {filename}...")
227
+
228
+ try:
229
+ # Review and improve content
230
+ review_result = self.content_reviewer.review_text(content)
231
+ improved_content[filename] = review_result["improved_content"]
232
+ improvement_results[filename] = review_result
233
+
234
+ improvement = review_result["quality_improvement"]
235
+ print(f" āœ“ Quality: {review_result['original_quality_score']} → {review_result['improved_quality_score']} (+{improvement})")
236
+
237
+ except Exception as e:
238
+ print(f" āŒ Failed to process {filename}: {e}")
239
+ # Use original content as fallback
240
+ improved_content[filename] = content
241
+ improvement_results[filename] = {
242
+ "original_quality_score": parent_quality_scores[filename],
243
+ "improved_quality_score": parent_quality_scores[filename],
244
+ "quality_improvement": 0,
245
+ "changes_summary": f"Processing failed: {str(e)}"
246
+ }
247
+
248
+ # Calculate improved quality scores
249
+ improved_total_score = sum(r["improved_quality_score"] for r in improvement_results.values())
250
+ improved_avg_quality = improved_total_score / len(improvement_results) if improvement_results else 0
251
+
252
+ # Create new version
253
+ version_metadata = {
254
+ "description": f"Content improved by ContentEditorAgent",
255
+ "purpose": "content_editing",
256
+ "parent_avg_quality": parent_avg_quality,
257
+ "improved_avg_quality": improved_avg_quality,
258
+ "quality_improvement": improved_avg_quality - parent_avg_quality,
259
+ "files_processed": len(improved_content),
260
+ "processing_timestamp": datetime.now().isoformat()
261
+ }
262
+
263
+ version_info = self.version_manager.create_version(
264
+ content_dict=improved_content,
265
+ version_name=target_version,
266
+ agent_name="content_editor",
267
+ parent_version=parent_version,
268
+ metadata=version_metadata
269
+ )
270
+
271
+ # Generate change comparison
272
+ comparison_report = self.change_tracker.create_change_report(
273
+ old_version=parent_version,
274
+ new_version=target_version,
275
+ old_content=parent_content,
276
+ new_content=improved_content,
277
+ old_quality=int(parent_avg_quality),
278
+ new_quality=int(improved_avg_quality)
279
+ )
280
+
281
+ # Create comprehensive processing report
282
+ processing_results = {
283
+ "version_created": version_info,
284
+ "parent_version": parent_version,
285
+ "target_version": target_version,
286
+ "quality_progression": {
287
+ "parent_avg_quality": parent_avg_quality,
288
+ "improved_avg_quality": improved_avg_quality,
289
+ "overall_improvement": improved_avg_quality - parent_avg_quality
290
+ },
291
+ "file_improvements": improvement_results,
292
+ "change_report_path": comparison_report,
293
+ "processing_timestamp": datetime.now().isoformat()
294
+ }
295
+
296
+ # Save processing report
297
+ self.save_processing_report(processing_results, target_version)
298
+
299
+ print(f"āœ… Version created: {target_version}")
300
+ print(f" Quality improvement: +{improved_avg_quality - parent_avg_quality:.2f} points")
301
+ print(f" Change report: {comparison_report}")
302
+
303
+ return processing_results
304
+
305
+ def save_processing_report(self, results: Dict, version_name: str):
306
+ """Save processing results to quality reports directory."""
307
+ # JSON report
308
+ json_path = self.reports_dir / f"{version_name}_processing_report.json"
309
+ with open(json_path, 'w', encoding='utf-8') as f:
310
+ json.dump(results, f, indent=2, ensure_ascii=False)
311
+
312
+ # Markdown report
313
+ md_path = self.reports_dir / f"{version_name}_processing_report.md"
314
+ self.create_processing_markdown(results, md_path)
315
+
316
+ def create_processing_markdown(self, results: Dict, output_path: Path):
317
+ """Create human-readable markdown processing report."""
318
+ version_info = results["version_created"]
319
+ quality = results["quality_progression"]
320
+ parent_version = results["parent_version"]
321
+ target_version = results["target_version"]
322
+
323
+ content = f"""# Processing Report: {target_version}
324
+
325
+ **Generated:** {results["processing_timestamp"]}
326
+ **Parent Version:** {parent_version}
327
+ **Agent:** content_editor
328
+
329
+ ## Quality Improvement Summary
330
+
331
+ | Metric | Value |
332
+ |--------|-------|
333
+ | Parent Avg Quality | {quality["parent_avg_quality"]:.1f}/100 |
334
+ | Improved Avg Quality | {quality["improved_avg_quality"]:.1f}/100 |
335
+ | Overall Improvement | +{quality["overall_improvement"]:.2f} points |
336
+ | Files Processed | {len(results["file_improvements"])} |
337
+
338
+ ## File-by-File Results
339
+
340
+ """
341
+
342
+ for filename, improvement in results["file_improvements"].items():
343
+ original_score = improvement["original_quality_score"]
344
+ improved_score = improvement["improved_quality_score"]
345
+ improvement_points = improvement["quality_improvement"]
346
+
347
+ content += f"""### {filename}
348
+ - **Quality:** {original_score} → {improved_score} (+{improvement_points} points)
349
+ - **Changes:** {improvement.get("changes_summary", "No summary available")}
350
+
351
+ """
352
+
353
+ content += f"""## Version Information
354
+
355
+ - **Version Name:** {version_info["name"]}
356
+ - **Created:** {version_info["created_at"]}
357
+ - **Parent Version:** {version_info["parent_version"]}
358
+ - **Content Hash:** {version_info["content_hash"]}
359
+ - **Files:** {", ".join(version_info["files"])}
360
+
361
+ ## Change Analysis
362
+
363
+ Detailed change comparison available at: `{results["change_report_path"]}`
364
+ """
365
+
366
+ with open(output_path, 'w', encoding='utf-8') as f:
367
+ f.write(content)
368
+
369
+ def get_version_history(self) -> List[Dict]:
370
+ """Get complete version history with quality progression."""
371
+ versions = self.version_manager.list_versions()
372
+
373
+ history = []
374
+ for version in versions:
375
+ # Get quality information from metadata
376
+ metadata = version.get("metadata", {})
377
+ quality_score = metadata.get("improved_avg_quality") or metadata.get("parent_avg_quality")
378
+
379
+ history_entry = {
380
+ "version_name": version["name"],
381
+ "agent": version["agent"],
382
+ "created_at": version["created_at"],
383
+ "parent_version": version.get("parent_version"),
384
+ "quality_score": quality_score,
385
+ "file_count": version["file_count"],
386
+ "description": metadata.get("description", "No description")
387
+ }
388
+
389
+ history.append(history_entry)
390
+
391
+ return history
392
+
393
+ def rollback_to_version(self, version_name: str) -> Dict:
394
+ """Rollback to a specific version and update current symlink."""
395
+ print(f"šŸ”„ Rolling back to version: {version_name}")
396
+
397
+ # Perform rollback
398
+ version_info = self.version_manager.rollback_to_version(version_name)
399
+
400
+ # Log rollback action
401
+ rollback_log = {
402
+ "action": "rollback",
403
+ "target_version": version_name,
404
+ "timestamp": datetime.now().isoformat(),
405
+ "version_info": version_info
406
+ }
407
+
408
+ # Save rollback log
409
+ log_path = self.reports_dir / f"rollback_{version_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
410
+ with open(log_path, 'w', encoding='utf-8') as f:
411
+ json.dump(rollback_log, f, indent=2, ensure_ascii=False)
412
+
413
+ print(f"āœ… Rolled back to {version_name}")
414
+ print(f" Log saved: {log_path}")
415
+
416
+ return rollback_log
417
+
418
+
419
+ def main():
420
+ """Run the versioned content editor agent."""
421
+ print("šŸš€ Starting Versioned Content Editor Agent - Milestone 2")
422
+ print("=" * 60)
423
+
424
+ # Initialize agent
425
+ agent = VersionedContentEditorAgent()
426
+
427
+ try:
428
+ # Process content with versioning
429
+ results = agent.process_content_with_versioning()
430
+
431
+ # Show version history
432
+ print("\nšŸ“œ Version History:")
433
+ history = agent.get_version_history()
434
+ for entry in history:
435
+ quality = f" (Q: {entry['quality_score']:.1f})" if entry['quality_score'] else ""
436
+ print(f" {entry['version_name']}: {entry['description']}{quality}")
437
+
438
+ # Show version statistics
439
+ stats = agent.version_manager.get_version_stats()
440
+ print(f"\nšŸ“Š Version Statistics:")
441
+ print(f" Total versions: {stats['total_versions']}")
442
+ print(f" Agents used: {', '.join(stats['agents_used'])}")
443
+ print(f" Latest version: {stats['latest_version']}")
444
+
445
+ print("\n" + "=" * 60)
446
+ print("āœ… MILESTONE 2: Version management complete!")
447
+
448
+ except Exception as e:
449
+ print(f"āŒ Error: {e}")
450
+ import traceback
451
+ traceback.print_exc()
452
+
453
+
454
+ if __name__ == "__main__":
455
+ main()
@@ -0,0 +1 @@
1
+ """LaTeX Specialist Agent for DeepAgents PrintShop."""