aiecs 1.0.8__py3-none-any.whl → 1.2.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.

Potentially problematic release.


This version of aiecs might be problematic. Click here for more details.

Files changed (81) hide show
  1. aiecs/__init__.py +1 -1
  2. aiecs/aiecs_client.py +159 -1
  3. aiecs/config/config.py +6 -0
  4. aiecs/domain/__init__.py +95 -0
  5. aiecs/domain/community/__init__.py +159 -0
  6. aiecs/domain/community/agent_adapter.py +516 -0
  7. aiecs/domain/community/analytics.py +465 -0
  8. aiecs/domain/community/collaborative_workflow.py +99 -7
  9. aiecs/domain/community/communication_hub.py +649 -0
  10. aiecs/domain/community/community_builder.py +322 -0
  11. aiecs/domain/community/community_integration.py +365 -12
  12. aiecs/domain/community/community_manager.py +481 -5
  13. aiecs/domain/community/decision_engine.py +459 -13
  14. aiecs/domain/community/exceptions.py +238 -0
  15. aiecs/domain/community/models/__init__.py +36 -0
  16. aiecs/domain/community/resource_manager.py +1 -1
  17. aiecs/domain/community/shared_context_manager.py +621 -0
  18. aiecs/domain/context/__init__.py +24 -0
  19. aiecs/domain/context/context_engine.py +37 -33
  20. aiecs/main.py +20 -2
  21. aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
  22. aiecs/scripts/aid/__init__.py +15 -0
  23. aiecs/scripts/aid/version_manager.py +224 -0
  24. aiecs/scripts/dependance_check/__init__.py +18 -0
  25. aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +51 -8
  26. aiecs/scripts/dependance_patch/__init__.py +8 -0
  27. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +12 -0
  28. aiecs/scripts/tools_develop/README.md +340 -0
  29. aiecs/scripts/tools_develop/__init__.py +16 -0
  30. aiecs/scripts/tools_develop/check_type_annotations.py +263 -0
  31. aiecs/scripts/tools_develop/validate_tool_schemas.py +346 -0
  32. aiecs/tools/__init__.py +53 -34
  33. aiecs/tools/docs/__init__.py +106 -0
  34. aiecs/tools/docs/ai_document_orchestrator.py +556 -0
  35. aiecs/tools/docs/ai_document_writer_orchestrator.py +2222 -0
  36. aiecs/tools/docs/content_insertion_tool.py +1234 -0
  37. aiecs/tools/docs/document_creator_tool.py +1179 -0
  38. aiecs/tools/docs/document_layout_tool.py +1105 -0
  39. aiecs/tools/docs/document_parser_tool.py +924 -0
  40. aiecs/tools/docs/document_writer_tool.py +1636 -0
  41. aiecs/tools/langchain_adapter.py +102 -51
  42. aiecs/tools/schema_generator.py +265 -0
  43. aiecs/tools/statistics/__init__.py +82 -0
  44. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +581 -0
  45. aiecs/tools/statistics/ai_insight_generator_tool.py +473 -0
  46. aiecs/tools/statistics/ai_report_orchestrator_tool.py +629 -0
  47. aiecs/tools/statistics/data_loader_tool.py +518 -0
  48. aiecs/tools/statistics/data_profiler_tool.py +599 -0
  49. aiecs/tools/statistics/data_transformer_tool.py +531 -0
  50. aiecs/tools/statistics/data_visualizer_tool.py +460 -0
  51. aiecs/tools/statistics/model_trainer_tool.py +470 -0
  52. aiecs/tools/statistics/statistical_analyzer_tool.py +426 -0
  53. aiecs/tools/task_tools/chart_tool.py +2 -1
  54. aiecs/tools/task_tools/image_tool.py +43 -43
  55. aiecs/tools/task_tools/office_tool.py +48 -36
  56. aiecs/tools/task_tools/pandas_tool.py +37 -33
  57. aiecs/tools/task_tools/report_tool.py +67 -56
  58. aiecs/tools/task_tools/research_tool.py +32 -31
  59. aiecs/tools/task_tools/scraper_tool.py +53 -46
  60. aiecs/tools/task_tools/search_tool.py +1123 -0
  61. aiecs/tools/task_tools/stats_tool.py +20 -15
  62. {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/METADATA +5 -1
  63. aiecs-1.2.0.dist-info/RECORD +135 -0
  64. aiecs-1.2.0.dist-info/entry_points.txt +10 -0
  65. aiecs/tools/task_tools/search_api.py +0 -7
  66. aiecs-1.0.8.dist-info/RECORD +0 -98
  67. aiecs-1.0.8.dist-info/entry_points.txt +0 -7
  68. /aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +0 -0
  69. /aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +0 -0
  70. /aiecs/scripts/{dependency_checker.py → dependance_check/dependency_checker.py} +0 -0
  71. /aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +0 -0
  72. /aiecs/scripts/{quick_dependency_check.py → dependance_check/quick_dependency_check.py} +0 -0
  73. /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
  74. /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
  75. /aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +0 -0
  76. /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
  77. /aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +0 -0
  78. /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
  79. {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/WHEEL +0 -0
  80. {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/licenses/LICENSE +0 -0
  81. {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,2222 @@
1
+ import os
2
+ import asyncio
3
+ import logging
4
+ import tempfile
5
+ from typing import Dict, Any, List, Optional, Union, Callable
6
+ from enum import Enum
7
+ from datetime import datetime
8
+
9
+ from pydantic import BaseModel, Field, ValidationError, ConfigDict
10
+
11
+ from aiecs.tools.base_tool import BaseTool
12
+ from aiecs.tools import register_tool
13
+
14
+
15
+ class ContentGenerationMode(str, Enum):
16
+ """AI content generation modes"""
17
+ GENERATE = "generate" # 生成全新内容
18
+ ENHANCE = "enhance" # 增强现有内容
19
+ REWRITE = "rewrite" # 重写内容
20
+ TRANSLATE = "translate" # 翻译内容
21
+ CONVERT_FORMAT = "convert_format" # 格式转换
22
+ TEMPLATE_FILL = "template_fill" # 模板填充
23
+ FORMAT_CONTENT = "format_content" # 格式化内容
24
+ EDIT_CONTENT = "edit_content" # 编辑内容
25
+
26
+
27
+ class AIEditOperation(str, Enum):
28
+ """AI-driven editing operations"""
29
+ SMART_FORMAT = "smart_format" # AI智能格式化
30
+ STYLE_ENHANCE = "style_enhance" # 样式增强
31
+ CONTENT_RESTRUCTURE = "content_restructure" # 内容重构
32
+ INTELLIGENT_HIGHLIGHT = "intelligent_highlight" # 智能高亮
33
+ AUTO_BOLD_KEYWORDS = "auto_bold_keywords" # 自动加粗关键词
34
+ SMART_PARAGRAPH = "smart_paragraph" # 智能段落优化
35
+ AI_PROOFREADING = "ai_proofreading" # AI校对
36
+
37
+
38
+ class WriteStrategy(str, Enum):
39
+ """Document writing strategies"""
40
+ IMMEDIATE = "immediate" # 立即写入
41
+ REVIEW = "review" # 审核后写入
42
+ DRAFT = "draft" # 保存为草稿
43
+ STAGED = "staged" # 分阶段写入
44
+
45
+
46
+ class AIProvider(str, Enum):
47
+ """Supported AI providers"""
48
+ OPENAI = "openai"
49
+ VERTEX_AI = "vertex_ai"
50
+ XAI = "xai"
51
+ LOCAL = "local"
52
+
53
+
54
+
55
+
56
+ class AIDocumentWriterOrchestratorError(Exception):
57
+ """Base exception for AI Document Writer Orchestrator errors"""
58
+ pass
59
+
60
+
61
+ class ContentGenerationError(AIDocumentWriterOrchestratorError):
62
+ """Raised when content generation fails"""
63
+ pass
64
+
65
+
66
+ class WriteOrchestrationError(AIDocumentWriterOrchestratorError):
67
+ """Raised when write orchestration fails"""
68
+ pass
69
+
70
+
71
+ @register_tool("ai_document_writer_orchestrator")
72
+ class AIDocumentWriterOrchestrator(BaseTool):
73
+ """
74
+ AI-powered document writing orchestrator that:
75
+ 1. Coordinates AI content generation with document writing
76
+ 2. Manages complex writing workflows
77
+ 3. Provides intelligent content enhancement and formatting
78
+ 4. Handles review and approval processes
79
+ 5. Supports template-based document generation
80
+
81
+ Integrates with:
82
+ - DocumentWriterTool for document writing operations
83
+ - Various AI providers for content generation
84
+ - Existing AIECS infrastructure
85
+ """
86
+
87
+ # Configuration schema
88
+ class Config(BaseModel):
89
+ """Configuration for the AI document writer orchestrator tool"""
90
+ model_config = ConfigDict(env_prefix="AI_DOC_WRITER_")
91
+
92
+ default_ai_provider: str = Field(
93
+ default="openai",
94
+ description="Default AI provider to use"
95
+ )
96
+ max_content_length: int = Field(
97
+ default=50000,
98
+ description="Maximum content length for AI generation"
99
+ )
100
+ max_concurrent_writes: int = Field(
101
+ default=5,
102
+ description="Maximum concurrent write operations"
103
+ )
104
+ default_temperature: float = Field(
105
+ default=0.3,
106
+ description="Default temperature for AI model"
107
+ )
108
+ max_tokens: int = Field(
109
+ default=4000,
110
+ description="Maximum tokens for AI response"
111
+ )
112
+ timeout: int = Field(
113
+ default=60,
114
+ description="Timeout in seconds for AI operations"
115
+ )
116
+ enable_draft_mode: bool = Field(
117
+ default=True,
118
+ description="Whether to enable draft mode"
119
+ )
120
+ enable_content_review: bool = Field(
121
+ default=True,
122
+ description="Whether to enable content review"
123
+ )
124
+ auto_backup_on_ai_write: bool = Field(
125
+ default=True,
126
+ description="Whether to automatically backup before AI writes"
127
+ )
128
+ temp_dir: str = Field(
129
+ default=tempfile.gettempdir(),
130
+ description="Temporary directory for processing"
131
+ )
132
+
133
+ def __init__(self, config: Optional[Dict] = None):
134
+ """Initialize AI Document Writer Orchestrator with settings"""
135
+ super().__init__(config)
136
+
137
+ # Parse configuration
138
+ self.config = self.Config(**(config or {}))
139
+
140
+ self.logger = logging.getLogger(__name__)
141
+
142
+ # Initialize document writer
143
+ self._init_document_writer()
144
+
145
+ # Initialize document creation tools
146
+ self._init_document_creation_tools()
147
+
148
+ # Initialize AI providers
149
+ self._init_ai_providers()
150
+
151
+ # Initialize content generation templates
152
+ self._init_content_templates()
153
+
154
+ def _init_document_writer(self):
155
+ """Initialize document writer tool"""
156
+ try:
157
+ from aiecs.tools.docs.document_writer_tool import DocumentWriterTool
158
+ self.document_writer = DocumentWriterTool()
159
+ except ImportError:
160
+ self.logger.error("DocumentWriterTool not available")
161
+ self.document_writer = None
162
+
163
+ def _init_document_creation_tools(self):
164
+ """Initialize document creation and layout tools"""
165
+ self.creation_tools = {}
166
+
167
+ # Initialize DocumentCreatorTool
168
+ try:
169
+ from aiecs.tools.docs.document_creator_tool import (
170
+ DocumentCreatorTool, DocumentFormat, DocumentType, TemplateType
171
+ )
172
+ self.creation_tools['creator'] = DocumentCreatorTool()
173
+ # Store classes for later use
174
+ self.DocumentFormat = DocumentFormat
175
+ self.DocumentType = DocumentType
176
+ self.TemplateType = TemplateType
177
+ self.logger.info("DocumentCreatorTool initialized successfully")
178
+ except ImportError:
179
+ self.logger.warning("DocumentCreatorTool not available")
180
+
181
+ # Initialize DocumentLayoutTool
182
+ try:
183
+ from aiecs.tools.docs.document_layout_tool import DocumentLayoutTool
184
+ self.creation_tools['layout'] = DocumentLayoutTool()
185
+ self.logger.info("DocumentLayoutTool initialized successfully")
186
+ except ImportError:
187
+ self.logger.warning("DocumentLayoutTool not available")
188
+
189
+ # Initialize ContentInsertionTool
190
+ try:
191
+ from aiecs.tools.docs.content_insertion_tool import ContentInsertionTool
192
+ self.creation_tools['content'] = ContentInsertionTool()
193
+ self.logger.info("ContentInsertionTool initialized successfully")
194
+ except ImportError:
195
+ self.logger.warning("ContentInsertionTool not available")
196
+
197
+ def _init_ai_providers(self):
198
+ """Initialize AI providers"""
199
+ self.ai_providers = {}
200
+
201
+ try:
202
+ # Initialize AIECS client for AI operations
203
+ from aiecs import AIECS
204
+ self.aiecs_client = AIECS()
205
+ self.ai_providers["aiecs"] = self.aiecs_client
206
+ except ImportError:
207
+ self.logger.warning("AIECS client not available")
208
+ self.aiecs_client = None
209
+
210
+ def _init_content_templates(self):
211
+ """Initialize content generation templates"""
212
+ self.content_templates = {
213
+ ContentGenerationMode.GENERATE: {
214
+ "system_prompt": "You are an expert content writer. Generate high-quality, well-structured content based on the given requirements.",
215
+ "user_prompt_template": "Generate content for: {content_type}\n\nRequirements:\n{requirements}\n\nTarget audience: {audience}\n\nPlease provide well-structured, engaging content that meets these requirements."
216
+ },
217
+ ContentGenerationMode.ENHANCE: {
218
+ "system_prompt": "You are an expert content editor. Enhance and improve existing content while maintaining its core message.",
219
+ "user_prompt_template": "Enhance the following content:\n\n{existing_content}\n\nImprovement goals:\n{enhancement_goals}\n\nPlease provide an enhanced version that is more engaging, clear, and effective."
220
+ },
221
+ ContentGenerationMode.REWRITE: {
222
+ "system_prompt": "You are an expert content rewriter. Rewrite content to improve clarity, style, and effectiveness.",
223
+ "user_prompt_template": "Rewrite the following content:\n\n{existing_content}\n\nRewriting goals:\n{rewrite_goals}\n\nTarget style: {target_style}\n\nPlease provide a completely rewritten version that maintains the core information but improves presentation."
224
+ },
225
+ ContentGenerationMode.TRANSLATE: {
226
+ "system_prompt": "You are an expert translator. Provide accurate, natural translations that preserve meaning and context.",
227
+ "user_prompt_template": "Translate the following content to {target_language}:\n\n{content}\n\nPlease provide a natural, accurate translation that preserves the original meaning and tone."
228
+ },
229
+ ContentGenerationMode.CONVERT_FORMAT: {
230
+ "system_prompt": "You are an expert document formatter. Convert content between different formats while preserving structure and meaning.",
231
+ "user_prompt_template": "Convert the following content from {source_format} to {target_format}:\n\n{content}\n\nPlease maintain the structure and ensure the converted format is properly formatted and readable."
232
+ },
233
+ ContentGenerationMode.TEMPLATE_FILL: {
234
+ "system_prompt": "You are an expert template processor. Fill templates with appropriate content based on provided data.",
235
+ "user_prompt_template": "Fill the following template with the provided data:\n\nTemplate:\n{template}\n\nData:\n{data}\n\nPlease generate complete, coherent content that properly fills all template sections."
236
+ }
237
+ }
238
+
239
+ # Schema definitions
240
+ class AIWriteDocumentSchema(BaseModel):
241
+ """Schema for ai_write_document operation"""
242
+ target_path: str = Field(description="Target file path")
243
+ content_requirements: str = Field(description="Content requirements and specifications")
244
+ generation_mode: ContentGenerationMode = Field(description="Content generation mode")
245
+ document_format: str = Field(description="Target document format")
246
+ write_strategy: WriteStrategy = Field(default=WriteStrategy.IMMEDIATE, description="Write strategy")
247
+ ai_provider: Optional[AIProvider] = Field(default=None, description="AI provider to use")
248
+ generation_params: Optional[Dict[str, Any]] = Field(default=None, description="AI generation parameters")
249
+ write_params: Optional[Dict[str, Any]] = Field(default=None, description="Document write parameters")
250
+
251
+ class EnhanceDocumentSchema(BaseModel):
252
+ """Schema for enhance_document operation"""
253
+ source_path: str = Field(description="Source document path")
254
+ target_path: Optional[str] = Field(default=None, description="Target path (if different)")
255
+ enhancement_goals: str = Field(description="Enhancement goals and requirements")
256
+ ai_provider: Optional[AIProvider] = Field(default=None, description="AI provider to use")
257
+ preserve_format: bool = Field(default=True, description="Preserve original format")
258
+
259
+ class BatchWriteSchema(BaseModel):
260
+ """Schema for batch_ai_write operation"""
261
+ write_requests: List[Dict[str, Any]] = Field(description="List of write requests")
262
+ coordination_strategy: str = Field(default="parallel", description="Coordination strategy")
263
+ max_concurrent: Optional[int] = Field(default=None, description="Maximum concurrent operations")
264
+
265
+ class AIEditDocumentSchema(BaseModel):
266
+ """Schema for ai_edit_document operation"""
267
+ target_path: str = Field(description="Target document path")
268
+ edit_operation: AIEditOperation = Field(description="AI editing operation to perform")
269
+ edit_instructions: str = Field(description="Specific editing instructions")
270
+ ai_provider: Optional[AIProvider] = Field(default=None, description="AI provider to use")
271
+ preserve_structure: bool = Field(default=True, description="Preserve document structure")
272
+ format_options: Optional[Dict[str, Any]] = Field(default=None, description="Format-specific options")
273
+
274
+ class SmartFormatSchema(BaseModel):
275
+ """Schema for smart_format_document operation"""
276
+ target_path: str = Field(description="Target document path")
277
+ format_goals: str = Field(description="Formatting goals and requirements")
278
+ target_format: str = Field(description="Target document format")
279
+ style_preferences: Optional[Dict[str, Any]] = Field(default=None, description="Style preferences")
280
+
281
+ class ContentAnalysisSchema(BaseModel):
282
+ """Schema for analyze_document_content operation"""
283
+ source_path: str = Field(description="Source document path")
284
+ analysis_type: str = Field(description="Type of analysis to perform")
285
+ analysis_params: Optional[Dict[str, Any]] = Field(default=None, description="Analysis parameters")
286
+
287
+ class CreateRichDocumentSchema(BaseModel):
288
+ """Schema for create_rich_document operation"""
289
+ document_template: str = Field(description="Document template type")
290
+ content_plan: Dict[str, Any] = Field(description="Content planning configuration")
291
+ layout_config: Optional[Dict[str, Any]] = Field(default=None, description="Layout configuration")
292
+ output_path: Optional[str] = Field(default=None, description="Custom output path")
293
+ ai_assistance: bool = Field(default=True, description="Use AI assistance for content generation")
294
+
295
+ class GenerateDocumentWithChartsSchema(BaseModel):
296
+ """Schema for generate_document_with_charts operation"""
297
+ requirements: str = Field(description="Document requirements and specifications")
298
+ data_sources: List[Dict[str, Any]] = Field(description="Data sources for charts and tables")
299
+ document_type: str = Field(description="Type of document to generate")
300
+ include_analysis: bool = Field(default=True, description="Include data analysis sections")
301
+ chart_preferences: Optional[Dict[str, Any]] = Field(default=None, description="Chart style preferences")
302
+
303
+ class OptimizeDocumentLayoutSchema(BaseModel):
304
+ """Schema for optimize_document_layout operation"""
305
+ document_path: str = Field(description="Path to document to optimize")
306
+ optimization_goals: List[str] = Field(description="Layout optimization goals")
307
+ preserve_content: bool = Field(default=True, description="Preserve existing content")
308
+ layout_style: Optional[str] = Field(default=None, description="Target layout style")
309
+
310
+ class BatchContentInsertionSchema(BaseModel):
311
+ """Schema for batch_content_insertion operation"""
312
+ document_path: str = Field(description="Target document path")
313
+ content_plan: List[Dict[str, Any]] = Field(description="Content insertion plan")
314
+ insertion_strategy: str = Field(default="sequential", description="Insertion strategy")
315
+ ai_optimization: bool = Field(default=True, description="Use AI for content optimization")
316
+
317
+ def ai_write_document(self,
318
+ target_path: str,
319
+ content_requirements: str,
320
+ generation_mode: ContentGenerationMode,
321
+ document_format: str = "txt",
322
+ write_strategy: WriteStrategy = WriteStrategy.IMMEDIATE,
323
+ ai_provider: Optional[AIProvider] = None,
324
+ generation_params: Optional[Dict[str, Any]] = None,
325
+ write_params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
326
+ """
327
+ Generate content using AI and write to document
328
+
329
+ Args:
330
+ target_path: Target file path
331
+ content_requirements: Content requirements and specifications
332
+ generation_mode: Content generation mode
333
+ document_format: Target document format
334
+ write_strategy: Write strategy (immediate, review, draft, staged)
335
+ ai_provider: AI provider to use
336
+ generation_params: AI generation parameters
337
+ write_params: Document write parameters
338
+
339
+ Returns:
340
+ Dict containing generation and write results
341
+ """
342
+ try:
343
+ start_time = datetime.now()
344
+ # Use microsecond precision for unique IDs
345
+ operation_id = f"ai_write_{int(start_time.timestamp() * 1000000)}"
346
+
347
+ self.logger.info(f"Starting AI write operation {operation_id}: {target_path}")
348
+
349
+ # Step 1: Generate content using AI
350
+ ai_result = self._generate_content_with_ai(
351
+ content_requirements,
352
+ generation_mode,
353
+ document_format,
354
+ ai_provider or self.config.default_ai_provider,
355
+ generation_params or {}
356
+ )
357
+
358
+ # Step 2: Process generated content
359
+ processed_content = self._process_generated_content(
360
+ ai_result["generated_content"],
361
+ document_format,
362
+ generation_mode
363
+ )
364
+
365
+ # Step 3: Handle write strategy
366
+ write_result = self._execute_write_strategy(
367
+ target_path,
368
+ processed_content,
369
+ document_format,
370
+ write_strategy,
371
+ write_params or {}
372
+ )
373
+
374
+ # Step 4: Post-processing
375
+ post_process_result = self._post_process_ai_write(
376
+ operation_id,
377
+ target_path,
378
+ ai_result,
379
+ write_result,
380
+ write_strategy
381
+ )
382
+
383
+ result = {
384
+ "operation_id": operation_id,
385
+ "target_path": target_path,
386
+ "generation_mode": generation_mode,
387
+ "document_format": document_format,
388
+ "write_strategy": write_strategy,
389
+ "ai_provider": ai_provider or self.config.default_ai_provider,
390
+ "ai_result": ai_result,
391
+ "write_result": write_result,
392
+ "post_process_result": post_process_result,
393
+ "processing_metadata": {
394
+ "start_time": start_time.isoformat(),
395
+ "end_time": datetime.now().isoformat(),
396
+ "duration": (datetime.now() - start_time).total_seconds()
397
+ }
398
+ }
399
+
400
+ self.logger.info(f"AI write operation {operation_id} completed successfully")
401
+ return result
402
+
403
+ except Exception as e:
404
+ raise WriteOrchestrationError(f"AI write operation failed: {str(e)}")
405
+
406
+ async def ai_write_document_async(self,
407
+ target_path: str,
408
+ content_requirements: str,
409
+ generation_mode: ContentGenerationMode,
410
+ document_format: str = "txt",
411
+ write_strategy: WriteStrategy = WriteStrategy.IMMEDIATE,
412
+ ai_provider: Optional[AIProvider] = None,
413
+ generation_params: Optional[Dict[str, Any]] = None,
414
+ write_params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
415
+ """Async version of ai_write_document"""
416
+ return await asyncio.to_thread(
417
+ self.ai_write_document,
418
+ target_path=target_path,
419
+ content_requirements=content_requirements,
420
+ generation_mode=generation_mode,
421
+ document_format=document_format,
422
+ write_strategy=write_strategy,
423
+ ai_provider=ai_provider,
424
+ generation_params=generation_params,
425
+ write_params=write_params
426
+ )
427
+
428
+ def enhance_document(self,
429
+ source_path: str,
430
+ enhancement_goals: str,
431
+ target_path: Optional[str] = None,
432
+ ai_provider: Optional[AIProvider] = None,
433
+ preserve_format: bool = True) -> Dict[str, Any]:
434
+ """
435
+ Enhance existing document using AI
436
+
437
+ Args:
438
+ source_path: Source document path
439
+ enhancement_goals: Enhancement goals and requirements
440
+ target_path: Target path (if different from source)
441
+ ai_provider: AI provider to use
442
+ preserve_format: Preserve original document format
443
+
444
+ Returns:
445
+ Dict containing enhancement results
446
+ """
447
+ try:
448
+ start_time = datetime.now()
449
+
450
+ # Step 1: Read existing document
451
+ existing_content = self._read_existing_document(source_path)
452
+
453
+ # Step 2: Generate enhanced content
454
+ ai_result = self._enhance_content_with_ai(
455
+ existing_content,
456
+ enhancement_goals,
457
+ ai_provider or self.config.default_ai_provider
458
+ )
459
+
460
+ # Step 3: Write enhanced content
461
+ target = target_path or source_path
462
+ write_mode = "overwrite" if target == source_path else "create"
463
+
464
+ if self.config.auto_backup_on_ai_write and target == source_path:
465
+ write_mode = "backup_write"
466
+
467
+ write_result = self.document_writer.write_document(
468
+ target_path=target,
469
+ content=ai_result["enhanced_content"],
470
+ format=existing_content["format"],
471
+ mode=write_mode
472
+ )
473
+
474
+ result = {
475
+ "source_path": source_path,
476
+ "target_path": target,
477
+ "enhancement_goals": enhancement_goals,
478
+ "preserve_format": preserve_format,
479
+ "original_content": existing_content,
480
+ "ai_result": ai_result,
481
+ "write_result": write_result,
482
+ "processing_metadata": {
483
+ "start_time": start_time.isoformat(),
484
+ "end_time": datetime.now().isoformat(),
485
+ "duration": (datetime.now() - start_time).total_seconds()
486
+ }
487
+ }
488
+
489
+ return result
490
+
491
+ except Exception as e:
492
+ raise WriteOrchestrationError(f"Document enhancement failed: {str(e)}")
493
+
494
+ def batch_ai_write(self,
495
+ write_requests: List[Dict[str, Any]],
496
+ coordination_strategy: str = "parallel",
497
+ max_concurrent: Optional[int] = None) -> Dict[str, Any]:
498
+ """
499
+ Batch AI write operations with coordination
500
+
501
+ Args:
502
+ write_requests: List of write request dictionaries
503
+ coordination_strategy: Coordination strategy (parallel, sequential, smart)
504
+ max_concurrent: Maximum concurrent operations
505
+
506
+ Returns:
507
+ Dict containing batch processing results
508
+ """
509
+ try:
510
+ start_time = datetime.now()
511
+ batch_id = f"batch_ai_write_{int(start_time.timestamp())}"
512
+ max_concurrent = max_concurrent or self.config.max_concurrent_writes
513
+
514
+ self.logger.info(f"Starting batch AI write {batch_id}: {len(write_requests)} requests")
515
+
516
+ if coordination_strategy == "parallel":
517
+ results = asyncio.run(self._batch_write_parallel(
518
+ write_requests, max_concurrent
519
+ ))
520
+ elif coordination_strategy == "sequential":
521
+ results = self._batch_write_sequential(write_requests)
522
+ elif coordination_strategy == "smart":
523
+ results = asyncio.run(self._batch_write_smart(
524
+ write_requests, max_concurrent
525
+ ))
526
+ else:
527
+ raise ValueError(f"Unknown coordination strategy: {coordination_strategy}")
528
+
529
+ batch_result = {
530
+ "batch_id": batch_id,
531
+ "coordination_strategy": coordination_strategy,
532
+ "total_requests": len(write_requests),
533
+ "successful_requests": len([r for r in results if r.get("status") == "success"]),
534
+ "failed_requests": len([r for r in results if r.get("status") == "error"]),
535
+ "results": results,
536
+ "batch_metadata": {
537
+ "start_time": start_time.isoformat(),
538
+ "end_time": datetime.now().isoformat(),
539
+ "duration": (datetime.now() - start_time).total_seconds()
540
+ }
541
+ }
542
+
543
+ return batch_result
544
+
545
+ except Exception as e:
546
+ raise WriteOrchestrationError(f"Batch AI write failed: {str(e)}")
547
+
548
+ def ai_edit_document(self,
549
+ target_path: str,
550
+ edit_operation: AIEditOperation,
551
+ edit_instructions: str,
552
+ ai_provider: Optional[AIProvider] = None,
553
+ preserve_structure: bool = True,
554
+ format_options: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
555
+ """
556
+ Perform AI-driven editing operations on documents
557
+
558
+ Args:
559
+ target_path: Target document path
560
+ edit_operation: AI editing operation to perform
561
+ edit_instructions: Specific editing instructions
562
+ ai_provider: AI provider to use
563
+ preserve_structure: Preserve document structure
564
+ format_options: Format-specific options
565
+
566
+ Returns:
567
+ Dict containing editing results
568
+ """
569
+ try:
570
+ start_time = datetime.now()
571
+ operation_id = f"ai_edit_{int(start_time.timestamp())}"
572
+
573
+ self.logger.info(f"Starting AI edit operation {operation_id}: {edit_operation} on {target_path}")
574
+
575
+ if not self.document_writer:
576
+ raise WriteOrchestrationError("DocumentWriterTool not available")
577
+
578
+ # Step 1: Read current document content
579
+ current_content = self._read_document_for_editing(target_path)
580
+
581
+ # Step 2: Analyze content for editing
582
+ analysis_result = self._analyze_document_for_editing(
583
+ current_content,
584
+ edit_operation,
585
+ edit_instructions
586
+ )
587
+
588
+ # Step 3: Generate editing instructions using AI
589
+ ai_edit_plan = self._generate_ai_edit_plan(
590
+ current_content,
591
+ edit_operation,
592
+ edit_instructions,
593
+ analysis_result,
594
+ ai_provider or self.config.default_ai_provider
595
+ )
596
+
597
+ # Step 4: Execute editing operations
598
+ edit_results = self._execute_ai_editing_plan(
599
+ target_path,
600
+ ai_edit_plan,
601
+ format_options
602
+ )
603
+
604
+ # Step 5: Post-process and validate
605
+ validation_result = self._validate_ai_editing_result(
606
+ target_path,
607
+ current_content,
608
+ edit_results,
609
+ preserve_structure
610
+ )
611
+
612
+ result = {
613
+ "operation_id": operation_id,
614
+ "target_path": target_path,
615
+ "edit_operation": edit_operation,
616
+ "edit_instructions": edit_instructions,
617
+ "preserve_structure": preserve_structure,
618
+ "analysis_result": analysis_result,
619
+ "ai_edit_plan": ai_edit_plan,
620
+ "edit_results": edit_results,
621
+ "validation_result": validation_result,
622
+ "processing_metadata": {
623
+ "start_time": start_time.isoformat(),
624
+ "end_time": datetime.now().isoformat(),
625
+ "duration": (datetime.now() - start_time).total_seconds()
626
+ }
627
+ }
628
+
629
+ self.logger.info(f"AI edit operation {operation_id} completed successfully")
630
+ return result
631
+
632
+ except Exception as e:
633
+ raise WriteOrchestrationError(f"AI edit operation failed: {str(e)}")
634
+
635
+ def smart_format_document(self,
636
+ target_path: str,
637
+ format_goals: str,
638
+ target_format: str,
639
+ style_preferences: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
640
+ """
641
+ Intelligently format document using AI analysis
642
+
643
+ Args:
644
+ target_path: Target document path
645
+ format_goals: Formatting goals and requirements
646
+ target_format: Target document format
647
+ style_preferences: Style preferences
648
+
649
+ Returns:
650
+ Dict containing formatting results
651
+ """
652
+ try:
653
+ start_time = datetime.now()
654
+
655
+ if not self.document_writer:
656
+ raise WriteOrchestrationError("DocumentWriterTool not available")
657
+
658
+ # Step 1: Analyze document structure
659
+ structure_analysis = self._analyze_document_structure(target_path, target_format)
660
+
661
+ # Step 2: Generate smart formatting plan
662
+ format_plan = self._generate_smart_format_plan(
663
+ structure_analysis,
664
+ format_goals,
665
+ target_format,
666
+ style_preferences
667
+ )
668
+
669
+ # Step 3: Execute formatting operations
670
+ format_results = self._execute_smart_formatting(
671
+ target_path,
672
+ format_plan,
673
+ target_format
674
+ )
675
+
676
+ result = {
677
+ "target_path": target_path,
678
+ "format_goals": format_goals,
679
+ "target_format": target_format,
680
+ "structure_analysis": structure_analysis,
681
+ "format_plan": format_plan,
682
+ "format_results": format_results,
683
+ "processing_metadata": {
684
+ "start_time": start_time.isoformat(),
685
+ "end_time": datetime.now().isoformat(),
686
+ "duration": (datetime.now() - start_time).total_seconds()
687
+ }
688
+ }
689
+
690
+ return result
691
+
692
+ except Exception as e:
693
+ raise WriteOrchestrationError(f"Smart formatting failed: {str(e)}")
694
+
695
+ def analyze_document_content(self,
696
+ source_path: str,
697
+ analysis_type: str,
698
+ analysis_params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
699
+ """
700
+ Perform AI-driven content analysis
701
+
702
+ Args:
703
+ source_path: Source document path
704
+ analysis_type: Type of analysis to perform
705
+ analysis_params: Analysis parameters
706
+
707
+ Returns:
708
+ Dict containing analysis results
709
+ """
710
+ try:
711
+ if not self.document_writer:
712
+ raise WriteOrchestrationError("DocumentWriterTool not available")
713
+
714
+ # Read document content
715
+ content = self._read_document_for_editing(source_path)
716
+
717
+ # Perform analysis based on type
718
+ if analysis_type == "structure":
719
+ format_param = analysis_params.get("format", "txt") if analysis_params else "txt"
720
+ result = self._analyze_document_structure(source_path, format_param)
721
+ elif analysis_type == "readability":
722
+ result = self._analyze_readability(content, analysis_params)
723
+ elif analysis_type == "keywords":
724
+ result = self._analyze_keywords(content, analysis_params)
725
+ elif analysis_type == "formatting_issues":
726
+ result = self._analyze_formatting_issues(content, analysis_params)
727
+ elif analysis_type == "content_quality":
728
+ result = self._analyze_content_quality(content, analysis_params)
729
+ else:
730
+ raise ValueError(f"Unsupported analysis type: {analysis_type}")
731
+
732
+ return {
733
+ "source_path": source_path,
734
+ "analysis_type": analysis_type,
735
+ "analysis_result": result,
736
+ "content_metadata": {
737
+ "content_length": len(content),
738
+ "analysis_timestamp": datetime.now().isoformat()
739
+ }
740
+ }
741
+
742
+ except Exception as e:
743
+ raise WriteOrchestrationError(f"Document analysis failed: {str(e)}")
744
+
745
+ # Helper methods for AI editing operations
746
+ def _read_document_for_editing(self, file_path: str) -> str:
747
+ """Read document content for editing operations"""
748
+ try:
749
+ with open(file_path, 'r', encoding='utf-8') as f:
750
+ return f.read()
751
+ except Exception as e:
752
+ raise WriteOrchestrationError(f"Cannot read document {file_path}: {str(e)}")
753
+
754
+ def _analyze_document_for_editing(self, content: str, operation: AIEditOperation, instructions: str) -> Dict[str, Any]:
755
+ """Analyze document content for editing operations"""
756
+ analysis = {
757
+ "content_length": len(content),
758
+ "line_count": len(content.split('\n')),
759
+ "word_count": len(content.split()),
760
+ "operation": operation,
761
+ "instructions": instructions
762
+ }
763
+
764
+ # Specific analysis based on operation type
765
+ if operation == AIEditOperation.SMART_FORMAT:
766
+ analysis["formatting_issues"] = self._detect_formatting_issues(content)
767
+ elif operation == AIEditOperation.AUTO_BOLD_KEYWORDS:
768
+ analysis["potential_keywords"] = self._extract_potential_keywords(content)
769
+ elif operation == AIEditOperation.INTELLIGENT_HIGHLIGHT:
770
+ analysis["important_sections"] = self._identify_important_sections(content)
771
+ elif operation == AIEditOperation.CONTENT_RESTRUCTURE:
772
+ analysis["structure_analysis"] = self._analyze_content_structure(content)
773
+
774
+ return analysis
775
+
776
+ def _generate_ai_edit_plan(self, content: str, operation: AIEditOperation,
777
+ instructions: str, analysis: Dict[str, Any],
778
+ ai_provider: AIProvider) -> Dict[str, Any]:
779
+ """Generate AI editing plan"""
780
+ try:
781
+ if not self.aiecs_client:
782
+ # Fallback to rule-based editing plan
783
+ return self._generate_fallback_edit_plan(content, operation, instructions, analysis)
784
+
785
+ # Prepare AI prompt for editing plan
786
+ system_prompt = f"""You are an expert document editor. Create a detailed editing plan based on the operation type and user instructions.
787
+
788
+ Operation: {operation}
789
+ Analysis: {analysis}
790
+
791
+ Provide a structured editing plan with specific actions, positions, and formatting details."""
792
+
793
+ user_prompt = f"""Content to edit:
794
+ {content[:2000]}...
795
+
796
+ Instructions: {instructions}
797
+
798
+ Please provide a detailed editing plan with:
799
+ 1. Specific edit operations
800
+ 2. Text positions (line numbers, character offsets)
801
+ 3. Format options
802
+ 4. Expected outcomes"""
803
+
804
+ # Generate editing plan using AI
805
+ ai_response = self._call_ai_provider(
806
+ ai_provider,
807
+ system_prompt,
808
+ user_prompt,
809
+ {"max_tokens": 2000, "temperature": 0.3}
810
+ )
811
+
812
+ # Parse AI response into structured plan
813
+ edit_plan = self._parse_ai_edit_response(ai_response, operation)
814
+
815
+ return edit_plan
816
+
817
+ except Exception as e:
818
+ self.logger.warning(f"AI edit plan generation failed: {e}, using fallback")
819
+ return self._generate_fallback_edit_plan(content, operation, instructions, analysis)
820
+
821
+ def _execute_ai_editing_plan(self, target_path: str, edit_plan: Dict[str, Any],
822
+ format_options: Optional[Dict[str, Any]]) -> List[Dict[str, Any]]:
823
+ """Execute the AI-generated editing plan"""
824
+ edit_results = []
825
+
826
+ try:
827
+ for edit_action in edit_plan.get("edit_actions", []):
828
+ operation_type = edit_action.get("operation")
829
+
830
+ if operation_type in ["bold", "italic", "underline", "strikethrough", "highlight"]:
831
+ # Text formatting operations
832
+ result = self.document_writer.edit_document(
833
+ target_path=target_path,
834
+ operation=operation_type,
835
+ selection=edit_action.get("selection"),
836
+ format_options=format_options or edit_action.get("format_options", {})
837
+ )
838
+ elif operation_type == "find_replace":
839
+ # Find and replace operations
840
+ result = self.document_writer.find_replace(
841
+ target_path=target_path,
842
+ find_text=edit_action.get("find_text"),
843
+ replace_text=edit_action.get("replace_text"),
844
+ replace_all=edit_action.get("replace_all", False),
845
+ case_sensitive=edit_action.get("case_sensitive", True),
846
+ regex_mode=edit_action.get("regex_mode", False)
847
+ )
848
+ elif operation_type == "format_text":
849
+ # Format specific text
850
+ result = self.document_writer.format_text(
851
+ target_path=target_path,
852
+ text_to_format=edit_action.get("text_to_format"),
853
+ format_type=edit_action.get("format_type"),
854
+ format_options=format_options or edit_action.get("format_options", {})
855
+ )
856
+ else:
857
+ # General edit operations
858
+ result = self.document_writer.edit_document(
859
+ target_path=target_path,
860
+ operation=edit_action.get("operation"),
861
+ content=edit_action.get("content"),
862
+ position=edit_action.get("position"),
863
+ selection=edit_action.get("selection"),
864
+ format_options=format_options or edit_action.get("format_options", {})
865
+ )
866
+
867
+ edit_results.append({
868
+ "action": edit_action,
869
+ "result": result,
870
+ "success": True
871
+ })
872
+
873
+ except Exception as e:
874
+ edit_results.append({
875
+ "action": edit_action,
876
+ "error": str(e),
877
+ "success": False
878
+ })
879
+
880
+ return edit_results
881
+
882
+ def _validate_ai_editing_result(self, target_path: str, original_content: str,
883
+ edit_results: List[Dict[str, Any]],
884
+ preserve_structure: bool) -> Dict[str, Any]:
885
+ """Validate AI editing results"""
886
+ try:
887
+ # Read edited content
888
+ edited_content = self._read_document_for_editing(target_path)
889
+
890
+ validation = {
891
+ "original_length": len(original_content),
892
+ "edited_length": len(edited_content),
893
+ "successful_operations": sum(1 for r in edit_results if r.get("success")),
894
+ "failed_operations": sum(1 for r in edit_results if not r.get("success")),
895
+ "content_changed": original_content != edited_content,
896
+ "structure_preserved": True # TODO: Implement structure validation
897
+ }
898
+
899
+ if preserve_structure:
900
+ validation["structure_check"] = self._check_structure_preservation(
901
+ original_content, edited_content
902
+ )
903
+
904
+ return validation
905
+
906
+ except Exception as e:
907
+ return {"validation_error": str(e)}
908
+
909
+ # Additional helper methods for specific operations
910
+ def _generate_fallback_edit_plan(self, content: str, operation: AIEditOperation,
911
+ instructions: str, analysis: Dict[str, Any]) -> Dict[str, Any]:
912
+ """Generate fallback editing plan when AI is not available"""
913
+ plan = {"edit_actions": []}
914
+
915
+ if operation == AIEditOperation.AUTO_BOLD_KEYWORDS:
916
+ # Auto-bold common keywords
917
+ keywords = ["重要", "关键", "注意", "警告", "错误", "成功"]
918
+ for keyword in keywords:
919
+ if keyword in content:
920
+ plan["edit_actions"].append({
921
+ "operation": "format_text",
922
+ "text_to_format": keyword,
923
+ "format_type": "bold",
924
+ "format_options": {"format_type": "markdown"}
925
+ })
926
+
927
+ elif operation == AIEditOperation.SMART_FORMAT:
928
+ # Basic formatting improvements
929
+ plan["edit_actions"].append({
930
+ "operation": "find_replace",
931
+ "find_text": " ",
932
+ "replace_text": " ",
933
+ "replace_all": True,
934
+ "description": "Remove double spaces"
935
+ })
936
+
937
+ return plan
938
+
939
+ def _detect_formatting_issues(self, content: str) -> List[str]:
940
+ """Detect common formatting issues"""
941
+ issues = []
942
+
943
+ if " " in content:
944
+ issues.append("Multiple consecutive spaces")
945
+ if "\n\n\n" in content:
946
+ issues.append("Multiple consecutive line breaks")
947
+ if content.count("**") % 2 != 0:
948
+ issues.append("Unmatched bold markdown markers")
949
+
950
+ return issues
951
+
952
+ def _extract_potential_keywords(self, content: str) -> List[str]:
953
+ """Extract potential keywords for bolding"""
954
+ # Simple keyword extraction - could be enhanced with NLP
955
+ import re
956
+ words = re.findall(r'\b[A-Z][a-z]+\b', content) # Capitalized words
957
+ return list(set(words))[:10] # Top 10 unique words
958
+
959
+ def _identify_important_sections(self, content: str) -> List[Dict[str, Any]]:
960
+ """Identify sections that might need highlighting"""
961
+ sections = []
962
+ lines = content.split('\n')
963
+
964
+ for i, line in enumerate(lines):
965
+ if any(keyword in line.lower() for keyword in ['重要', '注意', '警告', '关键']):
966
+ sections.append({
967
+ "line": i,
968
+ "content": line,
969
+ "reason": "Contains important keywords"
970
+ })
971
+
972
+ return sections
973
+
974
+ def _analyze_content_structure(self, content: str) -> Dict[str, Any]:
975
+ """Analyze content structure"""
976
+ lines = content.split('\n')
977
+ return {
978
+ "total_lines": len(lines),
979
+ "empty_lines": sum(1 for line in lines if not line.strip()),
980
+ "header_lines": sum(1 for line in lines if line.startswith('#')),
981
+ "list_items": sum(1 for line in lines if line.strip().startswith(('-', '*', '+'))),
982
+ "paragraphs": len([line for line in lines if line.strip() and not line.startswith('#')])
983
+ }
984
+
985
+ def _parse_ai_edit_response(self, ai_response: str, operation: AIEditOperation) -> Dict[str, Any]:
986
+ """Parse AI response into structured editing plan"""
987
+ # This is a simplified parser - could be enhanced with more sophisticated parsing
988
+ plan = {"edit_actions": []}
989
+
990
+ # Try to extract structured actions from AI response
991
+ # For now, return a basic plan
992
+ plan["ai_response"] = ai_response
993
+ plan["operation"] = operation
994
+
995
+ return plan
996
+
997
+ def _check_structure_preservation(self, original: str, edited: str) -> Dict[str, Any]:
998
+ """Check if document structure is preserved after editing"""
999
+ original_structure = self._analyze_content_structure(original)
1000
+ edited_structure = self._analyze_content_structure(edited)
1001
+
1002
+ return {
1003
+ "headers_preserved": original_structure["header_lines"] == edited_structure["header_lines"],
1004
+ "structure_similarity": self._calculate_structure_similarity(original_structure, edited_structure)
1005
+ }
1006
+
1007
+ def _calculate_structure_similarity(self, struct1: Dict, struct2: Dict) -> float:
1008
+ """Calculate similarity between two document structures"""
1009
+ # Simple similarity calculation
1010
+ if struct1["total_lines"] == 0:
1011
+ return 1.0 if struct2["total_lines"] == 0 else 0.0
1012
+
1013
+ similarity = 1.0 - abs(struct1["total_lines"] - struct2["total_lines"]) / max(struct1["total_lines"], struct2["total_lines"])
1014
+ return max(0.0, similarity)
1015
+
1016
+ def _analyze_document_structure(self, file_path: str, format_type: str) -> Dict[str, Any]:
1017
+ """Analyze document structure for formatting"""
1018
+ content = self._read_document_for_editing(file_path)
1019
+ return self._analyze_content_structure(content)
1020
+
1021
+ def _generate_smart_format_plan(self, structure: Dict[str, Any], goals: str,
1022
+ target_format: str, style_prefs: Optional[Dict[str, Any]]) -> Dict[str, Any]:
1023
+ """Generate smart formatting plan"""
1024
+ return {
1025
+ "format_actions": [],
1026
+ "structure_analysis": structure,
1027
+ "goals": goals,
1028
+ "target_format": target_format,
1029
+ "style_preferences": style_prefs or {}
1030
+ }
1031
+
1032
+ def _execute_smart_formatting(self, target_path: str, plan: Dict[str, Any], target_format: str) -> Dict[str, Any]:
1033
+ """Execute smart formatting plan"""
1034
+ return {
1035
+ "target_path": target_path,
1036
+ "plan_executed": plan,
1037
+ "target_format": target_format,
1038
+ "formatting_completed": True
1039
+ }
1040
+
1041
+ def _analyze_readability(self, content: str, params: Optional[Dict[str, Any]]) -> Dict[str, Any]:
1042
+ """Analyze content readability"""
1043
+ words = content.split()
1044
+ sentences = content.split('.')
1045
+
1046
+ return {
1047
+ "word_count": len(words),
1048
+ "sentence_count": len(sentences),
1049
+ "avg_words_per_sentence": len(words) / max(len(sentences), 1),
1050
+ "readability_score": "good" # Simplified
1051
+ }
1052
+
1053
+ def _analyze_keywords(self, content: str, params: Optional[Dict[str, Any]]) -> Dict[str, Any]:
1054
+ """Analyze content keywords"""
1055
+ words = content.lower().split()
1056
+ word_freq = {}
1057
+ for word in words:
1058
+ word_freq[word] = word_freq.get(word, 0) + 1
1059
+
1060
+ # Get top keywords
1061
+ top_keywords = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:10]
1062
+
1063
+ return {
1064
+ "total_words": len(words),
1065
+ "unique_words": len(word_freq),
1066
+ "top_keywords": top_keywords
1067
+ }
1068
+
1069
+ def _analyze_formatting_issues(self, content: str, params: Optional[Dict[str, Any]]) -> Dict[str, Any]:
1070
+ """Analyze formatting issues in content"""
1071
+ issues = self._detect_formatting_issues(content)
1072
+
1073
+ return {
1074
+ "issues_found": len(issues),
1075
+ "issue_list": issues,
1076
+ "content_length": len(content)
1077
+ }
1078
+
1079
+ def _analyze_content_quality(self, content: str, params: Optional[Dict[str, Any]]) -> Dict[str, Any]:
1080
+ """Analyze overall content quality"""
1081
+ return {
1082
+ "content_length": len(content),
1083
+ "structure_score": 0.8, # Simplified scoring
1084
+ "readability_score": 0.7,
1085
+ "formatting_score": 0.9,
1086
+ "overall_quality": 0.8
1087
+ }
1088
+
1089
+ def create_rich_document(self,
1090
+ document_template: str,
1091
+ content_plan: Dict[str, Any],
1092
+ layout_config: Optional[Dict[str, Any]] = None,
1093
+ output_path: Optional[str] = None,
1094
+ ai_assistance: bool = True) -> Dict[str, Any]:
1095
+ """
1096
+ Create rich document with comprehensive content and layout
1097
+
1098
+ Args:
1099
+ document_template: Document template type
1100
+ content_plan: Content planning configuration
1101
+ layout_config: Layout configuration
1102
+ output_path: Custom output path
1103
+ ai_assistance: Use AI assistance for content generation
1104
+
1105
+ Returns:
1106
+ Dict containing rich document creation results
1107
+ """
1108
+ try:
1109
+ start_time = datetime.now()
1110
+ operation_id = f"create_rich_{int(start_time.timestamp())}"
1111
+
1112
+ self.logger.info(f"Starting rich document creation {operation_id}")
1113
+
1114
+ # Check tool availability
1115
+ creator = self.creation_tools.get('creator')
1116
+ layout_tool = self.creation_tools.get('layout')
1117
+ content_tool = self.creation_tools.get('content')
1118
+
1119
+ if not creator:
1120
+ raise WriteOrchestrationError("DocumentCreatorTool not available")
1121
+
1122
+ # Step 1: Create document from template
1123
+ document_metadata = content_plan.get('metadata', {})
1124
+ document_format_str = content_plan.get('format', 'markdown')
1125
+
1126
+ # Convert string to DocumentFormat enum
1127
+ try:
1128
+ document_format = self.DocumentFormat(document_format_str)
1129
+ except (ValueError, AttributeError):
1130
+ # Fallback if DocumentFormat not available
1131
+ from aiecs.tools.docs.document_creator_tool import DocumentFormat
1132
+ document_format = DocumentFormat.MARKDOWN
1133
+
1134
+ # Get enum classes
1135
+ try:
1136
+ DocumentType = self.DocumentType
1137
+ TemplateType = self.TemplateType
1138
+ except AttributeError:
1139
+ from aiecs.tools.docs.document_creator_tool import DocumentType, TemplateType
1140
+
1141
+ # Parse document_type with fallback
1142
+ doc_type_str = content_plan.get('document_type', 'custom')
1143
+ try:
1144
+ doc_type = DocumentType(doc_type_str)
1145
+ except ValueError:
1146
+ # Try to find a matching type or use a sensible default
1147
+ if 'technical' in doc_type_str.lower():
1148
+ doc_type = DocumentType.TECHNICAL
1149
+ elif 'report' in doc_type_str.lower():
1150
+ doc_type = DocumentType.REPORT
1151
+ elif 'article' in doc_type_str.lower():
1152
+ doc_type = DocumentType.ARTICLE
1153
+ else:
1154
+ doc_type = DocumentType.TECHNICAL # Default fallback
1155
+ self.logger.warning(f"Unknown document type '{doc_type_str}', using {doc_type.value}")
1156
+
1157
+ # Parse template_type with fallback
1158
+ try:
1159
+ tmpl_type = TemplateType(document_template)
1160
+ except ValueError:
1161
+ # Default to basic template
1162
+ tmpl_type = TemplateType.BASIC
1163
+ self.logger.warning(f"Unknown template type '{document_template}', using basic")
1164
+
1165
+ creation_result = creator.create_document(
1166
+ document_type=doc_type,
1167
+ template_type=tmpl_type,
1168
+ output_format=document_format,
1169
+ metadata=document_metadata,
1170
+ output_path=output_path
1171
+ )
1172
+
1173
+ document_path = creation_result['output_path']
1174
+
1175
+ # Step 2: Setup document structure
1176
+ if content_plan.get('sections'):
1177
+ structure_result = creator.setup_document_structure(
1178
+ document_path=document_path,
1179
+ sections=content_plan['sections'],
1180
+ generate_toc=content_plan.get('generate_toc', True),
1181
+ numbering_style=content_plan.get('numbering_style')
1182
+ )
1183
+
1184
+ # Step 3: Apply layout configuration
1185
+ if layout_tool and layout_config:
1186
+ layout_result = layout_tool.set_page_layout(
1187
+ document_path=document_path,
1188
+ **layout_config
1189
+ )
1190
+
1191
+ # Setup headers/footers if specified
1192
+ if layout_config.get('headers_footers'):
1193
+ hf_result = layout_tool.setup_headers_footers(
1194
+ document_path=document_path,
1195
+ **layout_config['headers_footers']
1196
+ )
1197
+
1198
+ # Step 4: Generate and insert content with AI assistance
1199
+ content_results = []
1200
+ if ai_assistance and content_plan.get('content_items'):
1201
+ content_results = self._generate_and_insert_content_items(
1202
+ document_path, content_plan['content_items']
1203
+ )
1204
+
1205
+ # Step 5: Insert complex content (charts, tables, images)
1206
+ insertion_results = []
1207
+ if content_tool and content_plan.get('insertions'):
1208
+ insertion_results = self._batch_insert_complex_content(
1209
+ document_path, content_plan['insertions'], content_tool
1210
+ )
1211
+
1212
+ # Step 6: Final optimization
1213
+ if ai_assistance:
1214
+ optimization_result = self._optimize_rich_document(
1215
+ document_path, content_plan.get('optimization_goals', [])
1216
+ )
1217
+
1218
+ result = {
1219
+ "operation_id": operation_id,
1220
+ "document_path": document_path,
1221
+ "document_template": document_template,
1222
+ "content_plan": content_plan,
1223
+ "layout_config": layout_config,
1224
+ "creation_result": creation_result,
1225
+ "content_results": content_results,
1226
+ "insertion_results": insertion_results,
1227
+ "ai_assistance_used": ai_assistance,
1228
+ "processing_metadata": {
1229
+ "start_time": start_time.isoformat(),
1230
+ "end_time": datetime.now().isoformat(),
1231
+ "duration": (datetime.now() - start_time).total_seconds()
1232
+ }
1233
+ }
1234
+
1235
+ self.logger.info(f"Rich document creation {operation_id} completed successfully")
1236
+ return result
1237
+
1238
+ except Exception as e:
1239
+ raise WriteOrchestrationError(f"Rich document creation failed: {str(e)}")
1240
+
1241
+ def generate_document_with_charts(self,
1242
+ requirements: str,
1243
+ data_sources: List[Dict[str, Any]],
1244
+ document_type: str,
1245
+ include_analysis: bool = True,
1246
+ chart_preferences: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
1247
+ """
1248
+ Generate document with AI-driven charts and data visualization
1249
+
1250
+ Args:
1251
+ requirements: Document requirements and specifications
1252
+ data_sources: Data sources for charts and tables
1253
+ document_type: Type of document to generate
1254
+ include_analysis: Include data analysis sections
1255
+ chart_preferences: Chart style preferences
1256
+
1257
+ Returns:
1258
+ Dict containing document generation results
1259
+ """
1260
+ try:
1261
+ start_time = datetime.now()
1262
+ operation_id = f"gen_charts_{int(start_time.timestamp())}"
1263
+
1264
+ self.logger.info(f"Starting document generation with charts {operation_id}")
1265
+
1266
+ # Step 1: Analyze data sources and generate content plan
1267
+ content_plan = self._analyze_data_and_create_plan(
1268
+ data_sources, requirements, document_type, include_analysis
1269
+ )
1270
+
1271
+ # Step 2: Generate charts from data sources
1272
+ chart_results = self._generate_charts_from_data(
1273
+ data_sources, chart_preferences
1274
+ )
1275
+
1276
+ # Step 3: Create document with integrated charts
1277
+ rich_doc_result = self.create_rich_document(
1278
+ document_template=self._select_template_for_data_document(document_type),
1279
+ content_plan=content_plan,
1280
+ ai_assistance=True
1281
+ )
1282
+
1283
+ # Step 4: Insert generated charts
1284
+ chart_insertion_results = self._insert_generated_charts(
1285
+ rich_doc_result['document_path'], chart_results, content_plan
1286
+ )
1287
+
1288
+ # Step 5: Generate AI analysis content
1289
+ if include_analysis:
1290
+ analysis_results = self._generate_ai_analysis_content(
1291
+ rich_doc_result['document_path'], data_sources, chart_results
1292
+ )
1293
+
1294
+ result = {
1295
+ "operation_id": operation_id,
1296
+ "document_path": rich_doc_result['document_path'],
1297
+ "requirements": requirements,
1298
+ "data_sources": data_sources,
1299
+ "document_type": document_type,
1300
+ "content_plan": content_plan,
1301
+ "chart_results": chart_results,
1302
+ "rich_doc_result": rich_doc_result,
1303
+ "chart_insertion_results": chart_insertion_results,
1304
+ "include_analysis": include_analysis,
1305
+ "processing_metadata": {
1306
+ "start_time": start_time.isoformat(),
1307
+ "end_time": datetime.now().isoformat(),
1308
+ "duration": (datetime.now() - start_time).total_seconds()
1309
+ }
1310
+ }
1311
+
1312
+ self.logger.info(f"Document with charts generation {operation_id} completed successfully")
1313
+ return result
1314
+
1315
+ except Exception as e:
1316
+ raise WriteOrchestrationError(f"Document with charts generation failed: {str(e)}")
1317
+
1318
+ def optimize_document_layout(self,
1319
+ document_path: str,
1320
+ optimization_goals: List[str],
1321
+ preserve_content: bool = True,
1322
+ layout_style: Optional[str] = None) -> Dict[str, Any]:
1323
+ """
1324
+ Optimize document layout using AI analysis
1325
+
1326
+ Args:
1327
+ document_path: Path to document to optimize
1328
+ optimization_goals: Layout optimization goals
1329
+ preserve_content: Preserve existing content
1330
+ layout_style: Target layout style
1331
+
1332
+ Returns:
1333
+ Dict containing layout optimization results
1334
+ """
1335
+ try:
1336
+ start_time = datetime.now()
1337
+ operation_id = f"optimize_layout_{int(start_time.timestamp())}"
1338
+
1339
+ self.logger.info(f"Starting layout optimization {operation_id} for: {document_path}")
1340
+
1341
+ layout_tool = self.creation_tools.get('layout')
1342
+ if not layout_tool:
1343
+ raise WriteOrchestrationError("DocumentLayoutTool not available")
1344
+
1345
+ # Step 1: Analyze current document content
1346
+ content_analysis = self.analyze_document_content(
1347
+ source_path=document_path,
1348
+ analysis_type="structure"
1349
+ )
1350
+
1351
+ # Step 2: Generate optimization plan
1352
+ optimization_plan = self._generate_layout_optimization_plan(
1353
+ document_path, content_analysis, optimization_goals, layout_style
1354
+ )
1355
+
1356
+ # Step 3: Apply optimizations
1357
+ optimization_results = layout_tool.optimize_layout_for_content(
1358
+ document_path=document_path,
1359
+ content_analysis=content_analysis['analysis_result'],
1360
+ optimization_goals=optimization_goals
1361
+ )
1362
+
1363
+ # Step 4: Validate optimization results
1364
+ if preserve_content:
1365
+ validation_result = self._validate_content_preservation(
1366
+ document_path, content_analysis
1367
+ )
1368
+
1369
+ result = {
1370
+ "operation_id": operation_id,
1371
+ "document_path": document_path,
1372
+ "optimization_goals": optimization_goals,
1373
+ "layout_style": layout_style,
1374
+ "content_analysis": content_analysis,
1375
+ "optimization_plan": optimization_plan,
1376
+ "optimization_results": optimization_results,
1377
+ "preserve_content": preserve_content,
1378
+ "processing_metadata": {
1379
+ "start_time": start_time.isoformat(),
1380
+ "end_time": datetime.now().isoformat(),
1381
+ "duration": (datetime.now() - start_time).total_seconds()
1382
+ }
1383
+ }
1384
+
1385
+ self.logger.info(f"Layout optimization {operation_id} completed successfully")
1386
+ return result
1387
+
1388
+ except Exception as e:
1389
+ raise WriteOrchestrationError(f"Layout optimization failed: {str(e)}")
1390
+
1391
+ def batch_content_insertion(self,
1392
+ document_path: str,
1393
+ content_plan: List[Dict[str, Any]],
1394
+ insertion_strategy: str = "sequential",
1395
+ ai_optimization: bool = True) -> Dict[str, Any]:
1396
+ """
1397
+ Batch insertion of multiple content types with AI coordination
1398
+
1399
+ Args:
1400
+ document_path: Target document path
1401
+ content_plan: Content insertion plan
1402
+ insertion_strategy: Insertion strategy (sequential, parallel, optimized)
1403
+ ai_optimization: Use AI for content optimization
1404
+
1405
+ Returns:
1406
+ Dict containing batch insertion results
1407
+ """
1408
+ try:
1409
+ start_time = datetime.now()
1410
+ operation_id = f"batch_insert_{int(start_time.timestamp())}"
1411
+
1412
+ self.logger.info(f"Starting batch content insertion {operation_id} for: {document_path}")
1413
+
1414
+ content_tool = self.creation_tools.get('content')
1415
+ if not content_tool:
1416
+ raise WriteOrchestrationError("ContentInsertionTool not available")
1417
+
1418
+ # Step 1: Optimize insertion order if AI optimization is enabled
1419
+ if ai_optimization:
1420
+ optimized_plan = self._optimize_content_insertion_plan(
1421
+ document_path, content_plan
1422
+ )
1423
+ else:
1424
+ optimized_plan = content_plan
1425
+
1426
+ # Step 2: Execute insertions based on strategy
1427
+ if insertion_strategy == "sequential":
1428
+ insertion_results = self._execute_sequential_insertions(
1429
+ document_path, optimized_plan, content_tool
1430
+ )
1431
+ elif insertion_strategy == "parallel":
1432
+ insertion_results = self._execute_parallel_insertions(
1433
+ document_path, optimized_plan, content_tool
1434
+ )
1435
+ else: # optimized
1436
+ insertion_results = self._execute_optimized_insertions(
1437
+ document_path, optimized_plan, content_tool
1438
+ )
1439
+
1440
+ # Step 3: Post-insertion optimization
1441
+ if ai_optimization:
1442
+ post_optimization_result = self._post_insertion_optimization(
1443
+ document_path, insertion_results
1444
+ )
1445
+
1446
+ result = {
1447
+ "operation_id": operation_id,
1448
+ "document_path": document_path,
1449
+ "content_plan": content_plan,
1450
+ "optimized_plan": optimized_plan,
1451
+ "insertion_strategy": insertion_strategy,
1452
+ "ai_optimization": ai_optimization,
1453
+ "insertion_results": insertion_results,
1454
+ "processing_metadata": {
1455
+ "start_time": start_time.isoformat(),
1456
+ "end_time": datetime.now().isoformat(),
1457
+ "duration": (datetime.now() - start_time).total_seconds()
1458
+ }
1459
+ }
1460
+
1461
+ self.logger.info(f"Batch content insertion {operation_id} completed successfully")
1462
+ return result
1463
+
1464
+ except Exception as e:
1465
+ raise WriteOrchestrationError(f"Batch content insertion failed: {str(e)}")
1466
+
1467
+ # Helper methods for new functionality
1468
+ def _generate_and_insert_content_items(self, document_path: str, content_items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
1469
+ """Generate and insert content items with AI assistance"""
1470
+ results = []
1471
+
1472
+ for item in content_items:
1473
+ try:
1474
+ # Generate content based on type
1475
+ if item.get('type') == 'ai_generated':
1476
+ generated_content = self._generate_content_with_ai(
1477
+ item.get('requirements', ''),
1478
+ ContentGenerationMode.GENERATE,
1479
+ 'markdown',
1480
+ self.config.default_ai_provider,
1481
+ item.get('generation_params', {})
1482
+ )
1483
+
1484
+ # Insert generated content
1485
+ if self.document_writer:
1486
+ write_result = self.document_writer.write_document(
1487
+ target_path=document_path,
1488
+ content=generated_content['generated_content'],
1489
+ format='markdown',
1490
+ mode='append'
1491
+ )
1492
+
1493
+ results.append({
1494
+ "item": item,
1495
+ "generated_content": generated_content,
1496
+ "write_result": write_result,
1497
+ "success": True
1498
+ })
1499
+
1500
+ except Exception as e:
1501
+ results.append({
1502
+ "item": item,
1503
+ "error": str(e),
1504
+ "success": False
1505
+ })
1506
+ self.logger.warning(f"Failed to generate/insert content item: {e}")
1507
+
1508
+ return results
1509
+
1510
+ def _batch_insert_complex_content(self, document_path: str, insertions: List[Dict[str, Any]], content_tool) -> List[Dict[str, Any]]:
1511
+ """Batch insert complex content using ContentInsertionTool"""
1512
+ try:
1513
+ # Use the content tool's batch insertion capability
1514
+ return content_tool.batch_insert_content(
1515
+ document_path=document_path,
1516
+ content_items=insertions
1517
+ )
1518
+ except Exception as e:
1519
+ self.logger.warning(f"Batch insertion failed: {e}")
1520
+ return []
1521
+
1522
+ def _optimize_rich_document(self, document_path: str, optimization_goals: List[str]) -> Dict[str, Any]:
1523
+ """Optimize rich document based on goals"""
1524
+ try:
1525
+ if 'layout' in self.creation_tools:
1526
+ return self.creation_tools['layout'].optimize_layout_for_content(
1527
+ document_path=document_path,
1528
+ content_analysis={'content_length': 0}, # Simplified
1529
+ optimization_goals=optimization_goals
1530
+ )
1531
+ except Exception as e:
1532
+ self.logger.warning(f"Document optimization failed: {e}")
1533
+
1534
+ return {"optimization_applied": False}
1535
+
1536
+ def _analyze_data_and_create_plan(self, data_sources: List[Dict[str, Any]],
1537
+ requirements: str, document_type: str,
1538
+ include_analysis: bool) -> Dict[str, Any]:
1539
+ """Analyze data sources and create content plan"""
1540
+ plan = {
1541
+ "document_type": document_type,
1542
+ "format": "markdown",
1543
+ "metadata": {
1544
+ "title": f"{document_type.title()} Report",
1545
+ "author": "AI Document Generator",
1546
+ "date": datetime.now().strftime("%Y-%m-%d")
1547
+ },
1548
+ "sections": [
1549
+ {"title": "Executive Summary", "level": 2, "required": True},
1550
+ {"title": "Data Overview", "level": 2, "required": True},
1551
+ {"title": "Visualizations", "level": 2, "required": True}
1552
+ ],
1553
+ "generate_toc": True,
1554
+ "insertions": []
1555
+ }
1556
+
1557
+ if include_analysis:
1558
+ plan["sections"].append({"title": "Analysis", "level": 2, "required": True})
1559
+ plan["sections"].append({"title": "Insights", "level": 2, "required": True})
1560
+
1561
+ # Add chart insertions for each data source
1562
+ for i, data_source in enumerate(data_sources):
1563
+ plan["insertions"].append({
1564
+ "content_type": "chart",
1565
+ "chart_data": data_source.get("data", {}),
1566
+ "chart_type": data_source.get("chart_type", "bar"),
1567
+ "position": {"marker": f"<!-- CHART_{i+1} -->"},
1568
+ "caption": f"Chart {i+1}: {data_source.get('title', 'Data Visualization')}"
1569
+ })
1570
+
1571
+ return plan
1572
+
1573
+ def _generate_charts_from_data(self, data_sources: List[Dict[str, Any]],
1574
+ preferences: Optional[Dict[str, Any]]) -> List[Dict[str, Any]]:
1575
+ """Generate charts from data sources"""
1576
+ results = []
1577
+
1578
+ if 'content' not in self.creation_tools:
1579
+ return results
1580
+
1581
+ content_tool = self.creation_tools['content']
1582
+
1583
+ for data_source in data_sources:
1584
+ try:
1585
+ chart_result = content_tool._generate_chart(
1586
+ chart_data=data_source.get("data", {}),
1587
+ chart_type=data_source.get("chart_type", "bar"),
1588
+ config=preferences
1589
+ )
1590
+ results.append({
1591
+ "data_source": data_source,
1592
+ "chart_result": chart_result,
1593
+ "success": True
1594
+ })
1595
+ except Exception as e:
1596
+ results.append({
1597
+ "data_source": data_source,
1598
+ "error": str(e),
1599
+ "success": False
1600
+ })
1601
+
1602
+ return results
1603
+
1604
+ def _select_template_for_data_document(self, document_type: str) -> str:
1605
+ """Select appropriate template for data document"""
1606
+ type_template_map = {
1607
+ "report": "business_report",
1608
+ "analysis": "technical_doc",
1609
+ "presentation": "presentation",
1610
+ "academic": "academic_paper"
1611
+ }
1612
+ return type_template_map.get(document_type, "business_report")
1613
+
1614
+ def _insert_generated_charts(self, document_path: str, chart_results: List[Dict[str, Any]],
1615
+ content_plan: Dict[str, Any]) -> List[Dict[str, Any]]:
1616
+ """Insert generated charts into document"""
1617
+ results = []
1618
+
1619
+ if 'content' not in self.creation_tools:
1620
+ return results
1621
+
1622
+ content_tool = self.creation_tools['content']
1623
+
1624
+ for i, chart_result in enumerate(chart_results):
1625
+ if chart_result.get('success'):
1626
+ try:
1627
+ insertion_result = content_tool.insert_chart(
1628
+ document_path=document_path,
1629
+ chart_data=chart_result['data_source'].get('data', {}),
1630
+ chart_type=chart_result['data_source'].get('chart_type', 'bar'),
1631
+ position={"marker": f"<!-- CHART_{i+1} -->"},
1632
+ caption=f"Chart {i+1}: {chart_result['data_source'].get('title', 'Data Visualization')}"
1633
+ )
1634
+ results.append(insertion_result)
1635
+ except Exception as e:
1636
+ self.logger.warning(f"Failed to insert chart {i+1}: {e}")
1637
+
1638
+ return results
1639
+
1640
+ def _generate_ai_analysis_content(self, document_path: str, data_sources: List[Dict[str, Any]],
1641
+ chart_results: List[Dict[str, Any]]) -> Dict[str, Any]:
1642
+ """Generate AI-driven analysis content"""
1643
+ try:
1644
+ # Generate analysis based on data
1645
+ analysis_prompt = f"""
1646
+ Analyze the following data sources and provide insights:
1647
+ Data Sources: {len(data_sources)} datasets
1648
+ Charts Generated: {len([r for r in chart_results if r.get('success')])}
1649
+
1650
+ Please provide:
1651
+ 1. Key findings from the data
1652
+ 2. Trends and patterns observed
1653
+ 3. Recommendations based on the analysis
1654
+ """
1655
+
1656
+ analysis_result = self._generate_content_with_ai(
1657
+ analysis_prompt,
1658
+ ContentGenerationMode.GENERATE,
1659
+ 'markdown',
1660
+ self.config.default_ai_provider,
1661
+ {}
1662
+ )
1663
+
1664
+ # Insert analysis content into document
1665
+ if self.document_writer:
1666
+ write_result = self.document_writer.write_document(
1667
+ target_path=document_path,
1668
+ content=analysis_result['generated_content'],
1669
+ format='markdown',
1670
+ mode='append'
1671
+ )
1672
+
1673
+ return {
1674
+ "analysis_generated": True,
1675
+ "analysis_content": analysis_result,
1676
+ "write_result": write_result
1677
+ }
1678
+
1679
+ except Exception as e:
1680
+ self.logger.warning(f"Failed to generate AI analysis: {e}")
1681
+
1682
+ return {"analysis_generated": False}
1683
+
1684
+ def _generate_layout_optimization_plan(self, document_path: str, content_analysis: Dict[str, Any],
1685
+ optimization_goals: List[str], layout_style: Optional[str]) -> Dict[str, Any]:
1686
+ """Generate layout optimization plan"""
1687
+ return {
1688
+ "document_path": document_path,
1689
+ "optimization_goals": optimization_goals,
1690
+ "layout_style": layout_style,
1691
+ "content_analysis": content_analysis,
1692
+ "recommended_actions": [
1693
+ "Optimize spacing",
1694
+ "Improve typography",
1695
+ "Enhance readability"
1696
+ ]
1697
+ }
1698
+
1699
+ def _validate_content_preservation(self, document_path: str, original_analysis: Dict[str, Any]) -> Dict[str, Any]:
1700
+ """Validate that content was preserved during optimization"""
1701
+ try:
1702
+ # Re-analyze document after optimization
1703
+ new_analysis = self.analyze_document_content(
1704
+ source_path=document_path,
1705
+ analysis_type="structure"
1706
+ )
1707
+
1708
+ # Compare analyses
1709
+ original_length = original_analysis.get('analysis_result', {}).get('content_length', 0)
1710
+ new_length = new_analysis.get('analysis_result', {}).get('content_length', 0)
1711
+
1712
+ content_preserved = abs(original_length - new_length) / max(original_length, 1) < 0.1
1713
+
1714
+ return {
1715
+ "content_preserved": content_preserved,
1716
+ "original_length": original_length,
1717
+ "new_length": new_length,
1718
+ "difference_ratio": abs(original_length - new_length) / max(original_length, 1)
1719
+ }
1720
+
1721
+ except Exception as e:
1722
+ return {"validation_error": str(e)}
1723
+
1724
+ def _optimize_content_insertion_plan(self, document_path: str, content_plan: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
1725
+ """Optimize content insertion plan using AI"""
1726
+ # For now, return original plan
1727
+ # In a full implementation, this would use AI to optimize the order
1728
+ return content_plan
1729
+
1730
+ def _execute_sequential_insertions(self, document_path: str, plan: List[Dict[str, Any]], content_tool) -> Dict[str, Any]:
1731
+ """Execute content insertions sequentially"""
1732
+ return content_tool.batch_insert_content(
1733
+ document_path=document_path,
1734
+ content_items=plan
1735
+ )
1736
+
1737
+ def _execute_parallel_insertions(self, document_path: str, plan: List[Dict[str, Any]], content_tool) -> Dict[str, Any]:
1738
+ """Execute content insertions in parallel (simplified to sequential for now)"""
1739
+ return self._execute_sequential_insertions(document_path, plan, content_tool)
1740
+
1741
+ def _execute_optimized_insertions(self, document_path: str, plan: List[Dict[str, Any]], content_tool) -> Dict[str, Any]:
1742
+ """Execute optimized content insertions"""
1743
+ return self._execute_sequential_insertions(document_path, plan, content_tool)
1744
+
1745
+ def _post_insertion_optimization(self, document_path: str, insertion_results: Dict[str, Any]) -> Dict[str, Any]:
1746
+ """Perform post-insertion optimization"""
1747
+ return {
1748
+ "optimization_performed": True,
1749
+ "document_path": document_path,
1750
+ "insertion_results": insertion_results
1751
+ }
1752
+
1753
+ def create_content_template(self,
1754
+ template_name: str,
1755
+ template_content: str,
1756
+ template_variables: List[str],
1757
+ metadata: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
1758
+ """
1759
+ Create reusable content template
1760
+
1761
+ Args:
1762
+ template_name: Name of the template
1763
+ template_content: Template content with variables
1764
+ template_variables: List of template variables
1765
+ metadata: Additional template metadata
1766
+
1767
+ Returns:
1768
+ Dict containing template information
1769
+ """
1770
+ template_info = {
1771
+ "name": template_name,
1772
+ "content": template_content,
1773
+ "variables": template_variables,
1774
+ "metadata": metadata or {},
1775
+ "created_at": datetime.now().isoformat(),
1776
+ "version": "1.0"
1777
+ }
1778
+
1779
+ # Save template
1780
+ temp_dir = tempfile.gettempdir()
1781
+ template_file = os.path.join(temp_dir, f"template_{template_name}.json")
1782
+ with open(template_file, 'w') as f:
1783
+ import json
1784
+ json.dump(template_info, f, indent=2)
1785
+
1786
+ return template_info
1787
+
1788
+ def use_content_template(self,
1789
+ template_name: str,
1790
+ template_data: Dict[str, Any],
1791
+ target_path: str,
1792
+ ai_enhancement: bool = True) -> Dict[str, Any]:
1793
+ """
1794
+ Use content template to generate document
1795
+
1796
+ Args:
1797
+ template_name: Name of the template to use
1798
+ template_data: Data to fill template variables
1799
+ target_path: Target document path
1800
+ ai_enhancement: Whether to enhance with AI
1801
+
1802
+ Returns:
1803
+ Dict containing template usage results
1804
+ """
1805
+ try:
1806
+ # Load template
1807
+ template_file = os.path.join(self.config.temp_dir, f"template_{template_name}.json")
1808
+ with open(template_file, 'r') as f:
1809
+ import json
1810
+ template_info = json.load(f)
1811
+
1812
+ # Fill template
1813
+ filled_content = self._fill_template(
1814
+ template_info["content"],
1815
+ template_data
1816
+ )
1817
+
1818
+ # Enhance with AI if requested
1819
+ if ai_enhancement:
1820
+ ai_result = self._generate_content_with_ai(
1821
+ f"Template: {template_name}",
1822
+ ContentGenerationMode.TEMPLATE_FILL,
1823
+ "txt",
1824
+ self.config.default_ai_provider,
1825
+ {
1826
+ "template": template_info["content"],
1827
+ "data": template_data
1828
+ }
1829
+ )
1830
+ filled_content = ai_result["generated_content"]
1831
+
1832
+ # Write document
1833
+ write_result = self.document_writer.write_document(
1834
+ target_path=target_path,
1835
+ content=filled_content,
1836
+ format="txt",
1837
+ mode="create"
1838
+ )
1839
+
1840
+ return {
1841
+ "template_name": template_name,
1842
+ "template_data": template_data,
1843
+ "target_path": target_path,
1844
+ "ai_enhancement": ai_enhancement,
1845
+ "filled_content": filled_content,
1846
+ "write_result": write_result
1847
+ }
1848
+
1849
+ except Exception as e:
1850
+ raise WriteOrchestrationError(f"Template usage failed: {str(e)}")
1851
+
1852
+ def _generate_content_with_ai(self,
1853
+ requirements: str,
1854
+ generation_mode: ContentGenerationMode,
1855
+ document_format: str,
1856
+ ai_provider: AIProvider,
1857
+ generation_params: Dict[str, Any]) -> Dict[str, Any]:
1858
+ """Generate content using AI based on requirements"""
1859
+
1860
+ try:
1861
+ # Get content generation template
1862
+ template = self.content_templates.get(generation_mode)
1863
+ if not template:
1864
+ raise ContentGenerationError(f"No template found for generation mode: {generation_mode}")
1865
+
1866
+ # Prepare AI prompt
1867
+ prompt_params = {
1868
+ "content_type": document_format,
1869
+ "requirements": requirements,
1870
+ "audience": generation_params.get("audience", "general"),
1871
+ **generation_params
1872
+ }
1873
+
1874
+ prompt = self._format_content_prompt(template, prompt_params)
1875
+
1876
+ # Call AI provider
1877
+ ai_response = self._call_ai_provider(prompt, ai_provider, generation_params)
1878
+
1879
+ return {
1880
+ "generation_mode": generation_mode,
1881
+ "requirements": requirements,
1882
+ "prompt_used": prompt,
1883
+ "generated_content": ai_response,
1884
+ "ai_provider": ai_provider,
1885
+ "generation_params": generation_params
1886
+ }
1887
+
1888
+ except Exception as e:
1889
+ raise ContentGenerationError(f"AI content generation failed: {str(e)}")
1890
+
1891
+ def _enhance_content_with_ai(self,
1892
+ existing_content: Dict[str, Any],
1893
+ enhancement_goals: str,
1894
+ ai_provider: AIProvider) -> Dict[str, Any]:
1895
+ """Enhance existing content using AI"""
1896
+
1897
+ try:
1898
+ template = self.content_templates[ContentGenerationMode.ENHANCE]
1899
+
1900
+ prompt_params = {
1901
+ "existing_content": existing_content["content"],
1902
+ "enhancement_goals": enhancement_goals
1903
+ }
1904
+
1905
+ prompt = self._format_content_prompt(template, prompt_params)
1906
+ ai_response = self._call_ai_provider(prompt, ai_provider, {})
1907
+
1908
+ return {
1909
+ "original_content": existing_content["content"],
1910
+ "enhancement_goals": enhancement_goals,
1911
+ "enhanced_content": ai_response,
1912
+ "ai_provider": ai_provider
1913
+ }
1914
+
1915
+ except Exception as e:
1916
+ raise ContentGenerationError(f"AI content enhancement failed: {str(e)}")
1917
+
1918
+ def _process_generated_content(self,
1919
+ content: str,
1920
+ document_format: str,
1921
+ generation_mode: ContentGenerationMode) -> str:
1922
+ """Process generated content for specific format"""
1923
+
1924
+ # Format-specific processing
1925
+ if document_format.lower() == "markdown":
1926
+ # Ensure proper markdown formatting
1927
+ content = self._ensure_markdown_formatting(content)
1928
+ elif document_format.lower() == "html":
1929
+ # Ensure proper HTML structure
1930
+ content = self._ensure_html_structure(content)
1931
+ elif document_format.lower() == "json":
1932
+ # Validate and format JSON
1933
+ content = self._ensure_json_format(content)
1934
+
1935
+ return content
1936
+
1937
+ def _execute_write_strategy(self,
1938
+ target_path: str,
1939
+ content: str,
1940
+ document_format: str,
1941
+ write_strategy: WriteStrategy,
1942
+ write_params: Dict[str, Any]) -> Dict[str, Any]:
1943
+ """Execute write strategy"""
1944
+
1945
+ if not self.document_writer:
1946
+ raise WriteOrchestrationError("DocumentWriterTool not available")
1947
+
1948
+ if write_strategy == WriteStrategy.IMMEDIATE:
1949
+ # Write immediately
1950
+ return self.document_writer.write_document(
1951
+ target_path=target_path,
1952
+ content=content,
1953
+ format=document_format,
1954
+ mode="create",
1955
+ **write_params
1956
+ )
1957
+
1958
+ elif write_strategy == WriteStrategy.DRAFT:
1959
+ # Save as draft
1960
+ draft_path = f"{target_path}.draft"
1961
+ return self.document_writer.write_document(
1962
+ target_path=draft_path,
1963
+ content=content,
1964
+ format=document_format,
1965
+ mode="create",
1966
+ **write_params
1967
+ )
1968
+
1969
+ elif write_strategy == WriteStrategy.REVIEW:
1970
+ # Save for review
1971
+ review_path = f"{target_path}.review"
1972
+ return self.document_writer.write_document(
1973
+ target_path=review_path,
1974
+ content=content,
1975
+ format=document_format,
1976
+ mode="create",
1977
+ **write_params
1978
+ )
1979
+
1980
+ elif write_strategy == WriteStrategy.STAGED:
1981
+ # Staged write (implement custom logic)
1982
+ return self._execute_staged_write(target_path, content, document_format, write_params)
1983
+
1984
+ else:
1985
+ raise ValueError(f"Unknown write strategy: {write_strategy}")
1986
+
1987
+ def _execute_staged_write(self,
1988
+ target_path: str,
1989
+ content: str,
1990
+ document_format: str,
1991
+ write_params: Dict[str, Any]) -> Dict[str, Any]:
1992
+ """Execute staged write operation"""
1993
+
1994
+ # Split content into stages (simplified implementation)
1995
+ content_parts = content.split('\n\n') # Split by paragraphs
1996
+ stage_results = []
1997
+
1998
+ for i, part in enumerate(content_parts):
1999
+ stage_path = f"{target_path}.stage_{i+1}"
2000
+ stage_result = self.document_writer.write_document(
2001
+ target_path=stage_path,
2002
+ content=part,
2003
+ format=document_format,
2004
+ mode="create",
2005
+ **write_params
2006
+ )
2007
+ stage_results.append(stage_result)
2008
+
2009
+ return {
2010
+ "strategy": "staged",
2011
+ "total_stages": len(content_parts),
2012
+ "stage_results": stage_results
2013
+ }
2014
+
2015
+ def _read_existing_document(self, source_path: str) -> Dict[str, Any]:
2016
+ """Read existing document for enhancement"""
2017
+
2018
+ try:
2019
+ # Try to use document parser for reading
2020
+ try:
2021
+ from aiecs.tools.docs.document_parser_tool import DocumentParserTool
2022
+ parser = DocumentParserTool()
2023
+ parse_result = parser.parse_document(source_path)
2024
+
2025
+ return {
2026
+ "content": parse_result["content"],
2027
+ "format": parse_result["document_type"],
2028
+ "metadata": parse_result.get("metadata", {})
2029
+ }
2030
+
2031
+ except ImportError:
2032
+ # Fallback to simple file reading
2033
+ with open(source_path, 'r', encoding='utf-8') as f:
2034
+ content = f.read()
2035
+
2036
+ file_ext = os.path.splitext(source_path)[1].lower()
2037
+ return {
2038
+ "content": content,
2039
+ "format": file_ext.lstrip('.') or "txt",
2040
+ "metadata": {}
2041
+ }
2042
+
2043
+ except Exception as e:
2044
+ raise WriteOrchestrationError(f"Failed to read existing document: {str(e)}")
2045
+
2046
+ def _call_ai_provider(self, prompt: str, ai_provider: AIProvider, params: Dict[str, Any]) -> str:
2047
+ """Call AI provider with prompt"""
2048
+
2049
+ try:
2050
+ if self.aiecs_client:
2051
+ # Use AIECS client for AI operations
2052
+ from aiecs.domain.task.task_context import TaskContext
2053
+
2054
+ task_context = TaskContext(
2055
+ data={
2056
+ "user_id": "test_user",
2057
+ "chat_id": f"content_gen_{datetime.now().timestamp()}",
2058
+ "metadata": params,
2059
+ "aiPreference": params.get("ai_provider", "default")
2060
+ }
2061
+ )
2062
+
2063
+ result = self.aiecs_client.process_task(task_context)
2064
+ return result.get("response", "")
2065
+ else:
2066
+ # Fallback to mock response
2067
+ return self._generate_mock_content(prompt, params)
2068
+
2069
+ except Exception as e:
2070
+ raise ContentGenerationError(f"AI provider call failed: {str(e)}")
2071
+
2072
+ def _generate_mock_content(self, prompt: str, params: Dict[str, Any]) -> str:
2073
+ """Generate mock content for testing"""
2074
+ self.logger.warning("Using mock content generation - implement actual AI provider integration")
2075
+
2076
+ # Generate simple mock content based on prompt
2077
+ if "requirements" in params:
2078
+ return f"Generated content based on: {params['requirements']}\n\nThis is mock content for testing purposes."
2079
+ else:
2080
+ return f"Mock generated content for prompt: {prompt[:100]}..."
2081
+
2082
+ def _format_content_prompt(self, template: Dict[str, str], params: Dict[str, Any]) -> str:
2083
+ """Format content generation prompt using template"""
2084
+
2085
+ user_prompt = template["user_prompt_template"]
2086
+
2087
+ # Replace placeholders
2088
+ for key, value in params.items():
2089
+ placeholder = f"{{{key}}}"
2090
+ if placeholder in user_prompt:
2091
+ user_prompt = user_prompt.replace(placeholder, str(value))
2092
+
2093
+ return user_prompt
2094
+
2095
+ def _fill_template(self, template_content: str, template_data: Dict[str, Any]) -> str:
2096
+ """Fill template with provided data"""
2097
+
2098
+ filled_content = template_content
2099
+ for key, value in template_data.items():
2100
+ placeholder = f"{{{key}}}"
2101
+ filled_content = filled_content.replace(placeholder, str(value))
2102
+
2103
+ return filled_content
2104
+
2105
+ # Content formatting helpers
2106
+ def _ensure_markdown_formatting(self, content: str) -> str:
2107
+ """Ensure proper markdown formatting"""
2108
+ # Add basic markdown formatting if missing
2109
+ lines = content.split('\n')
2110
+ formatted_lines = []
2111
+
2112
+ for line in lines:
2113
+ line = line.strip()
2114
+ if line and not line.startswith('#') and not line.startswith('-') and not line.startswith('*'):
2115
+ # Add paragraph spacing
2116
+ formatted_lines.append(line + '\n')
2117
+ else:
2118
+ formatted_lines.append(line)
2119
+
2120
+ return '\n'.join(formatted_lines)
2121
+
2122
+ def _ensure_html_structure(self, content: str) -> str:
2123
+ """Ensure proper HTML structure"""
2124
+ if not content.strip().startswith('<html'):
2125
+ content = f"<html><body>{content}</body></html>"
2126
+ return content
2127
+
2128
+ def _ensure_json_format(self, content: str) -> str:
2129
+ """Ensure proper JSON format"""
2130
+ try:
2131
+ import json
2132
+ # Try to parse and reformat
2133
+ parsed = json.loads(content)
2134
+ return json.dumps(parsed, indent=2, ensure_ascii=False)
2135
+ except json.JSONDecodeError:
2136
+ # Wrap in basic JSON structure
2137
+ return json.dumps({"content": content}, indent=2, ensure_ascii=False)
2138
+
2139
+ # Batch processing methods
2140
+ async def _batch_write_parallel(self, write_requests: List[Dict[str, Any]], max_concurrent: int) -> List[Dict[str, Any]]:
2141
+ """Process write requests in parallel"""
2142
+
2143
+ semaphore = asyncio.Semaphore(max_concurrent)
2144
+
2145
+ async def process_single_request(request: Dict[str, Any]) -> Dict[str, Any]:
2146
+ async with semaphore:
2147
+ try:
2148
+ result = await self.ai_write_document_async(**request)
2149
+ return {"status": "success", "request": request, "result": result}
2150
+ except Exception as e:
2151
+ return {"status": "error", "request": request, "error": str(e)}
2152
+
2153
+ tasks = [process_single_request(req) for req in write_requests]
2154
+ return await asyncio.gather(*tasks)
2155
+
2156
+ def _batch_write_sequential(self, write_requests: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
2157
+ """Process write requests sequentially"""
2158
+
2159
+ results = []
2160
+ for request in write_requests:
2161
+ try:
2162
+ result = self.ai_write_document(**request)
2163
+ results.append({"status": "success", "request": request, "result": result})
2164
+ except Exception as e:
2165
+ results.append({"status": "error", "request": request, "error": str(e)})
2166
+
2167
+ return results
2168
+
2169
+ async def _batch_write_smart(self, write_requests: List[Dict[str, Any]], max_concurrent: int) -> List[Dict[str, Any]]:
2170
+ """Smart batch processing with dependency awareness"""
2171
+
2172
+ # Analyze dependencies (simplified implementation)
2173
+ independent_requests = []
2174
+ dependent_requests = []
2175
+
2176
+ for request in write_requests:
2177
+ # Check if request depends on others (simplified logic)
2178
+ if any(req.get("target_path") == request.get("source_path") for req in write_requests):
2179
+ dependent_requests.append(request)
2180
+ else:
2181
+ independent_requests.append(request)
2182
+
2183
+ # Process independent requests in parallel
2184
+ results = []
2185
+ if independent_requests:
2186
+ parallel_results = await self._batch_write_parallel(independent_requests, max_concurrent)
2187
+ results.extend(parallel_results)
2188
+
2189
+ # Process dependent requests sequentially
2190
+ if dependent_requests:
2191
+ sequential_results = self._batch_write_sequential(dependent_requests)
2192
+ results.extend(sequential_results)
2193
+
2194
+ return results
2195
+
2196
+ def _post_process_ai_write(self,
2197
+ operation_id: str,
2198
+ target_path: str,
2199
+ ai_result: Dict[str, Any],
2200
+ write_result: Dict[str, Any],
2201
+ write_strategy: WriteStrategy) -> Dict[str, Any]:
2202
+ """Post-process AI write operation"""
2203
+
2204
+ post_process_info = {
2205
+ "operation_id": operation_id,
2206
+ "target_path": target_path,
2207
+ "write_strategy": write_strategy,
2208
+ "content_length": len(ai_result.get("generated_content", "")),
2209
+ "write_success": write_result.get("write_result", {}).get("path") is not None,
2210
+ "timestamp": datetime.now().isoformat()
2211
+ }
2212
+
2213
+ # Log operation
2214
+ try:
2215
+ log_file = os.path.join(self.config.temp_dir, "ai_write_operations.log")
2216
+ with open(log_file, "a") as f:
2217
+ import json
2218
+ f.write(json.dumps(post_process_info) + "\n")
2219
+ except Exception as e:
2220
+ self.logger.warning(f"Operation logging failed: {e}")
2221
+
2222
+ return post_process_info