omnimancer-cli 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 (126) hide show
  1. omnimancer/__init__.py +42 -0
  2. omnimancer/__main__.py +9 -0
  3. omnimancer/cli/__init__.py +8 -0
  4. omnimancer/cli/agent_manager.py +826 -0
  5. omnimancer/cli/agent_wizard.py +944 -0
  6. omnimancer/cli/approval_formatter.py +734 -0
  7. omnimancer/cli/approval_integration.py +734 -0
  8. omnimancer/cli/approval_prompt.py +1286 -0
  9. omnimancer/cli/batch_approval_display.py +617 -0
  10. omnimancer/cli/batch_approval_filters.py +729 -0
  11. omnimancer/cli/batch_operation_monitor.py +775 -0
  12. omnimancer/cli/commands/performance_cmd.py +624 -0
  13. omnimancer/cli/commands.py +757 -0
  14. omnimancer/cli/completion_handler.py +281 -0
  15. omnimancer/cli/config_setup_wizard.py +783 -0
  16. omnimancer/cli/dynamic_commands.py +371 -0
  17. omnimancer/cli/handlers/__init__.py +18 -0
  18. omnimancer/cli/handlers/agent_handler.py +865 -0
  19. omnimancer/cli/handlers/agent_persona_handler.py +1048 -0
  20. omnimancer/cli/handlers/custom_agent_handler.py +352 -0
  21. omnimancer/cli/handlers/permissions_handler.py +1609 -0
  22. omnimancer/cli/interface.py +6695 -0
  23. omnimancer/cli/performance_dashboard.py +612 -0
  24. omnimancer/core/__init__.py +34 -0
  25. omnimancer/core/agent/__init__.py +256 -0
  26. omnimancer/core/agent/agent_config.py +715 -0
  27. omnimancer/core/agent/agent_switcher.py +668 -0
  28. omnimancer/core/agent/approval_context.py +460 -0
  29. omnimancer/core/agent/approval_dialog.py +902 -0
  30. omnimancer/core/agent/approval_interface.py +628 -0
  31. omnimancer/core/agent/approval_manager.py +760 -0
  32. omnimancer/core/agent/cli_integration.py +470 -0
  33. omnimancer/core/agent/config.py +845 -0
  34. omnimancer/core/agent/custom_agent_integration.py +654 -0
  35. omnimancer/core/agent/diff_renderer.py +706 -0
  36. omnimancer/core/agent/file_content_display.py +503 -0
  37. omnimancer/core/agent/file_modification_workflow.py +658 -0
  38. omnimancer/core/agent/file_system_manager.py +1790 -0
  39. omnimancer/core/agent/input_handler.py +614 -0
  40. omnimancer/core/agent/metrics_collector.py +771 -0
  41. omnimancer/core/agent/optimization_engine.py +729 -0
  42. omnimancer/core/agent/performance_monitor.py +717 -0
  43. omnimancer/core/agent/persona.py +870 -0
  44. omnimancer/core/agent/persona_validator.py +672 -0
  45. omnimancer/core/agent/program_executor.py +748 -0
  46. omnimancer/core/agent/proposed_changes_integration.py +663 -0
  47. omnimancer/core/agent/read_before_write_errors.py +492 -0
  48. omnimancer/core/agent/read_before_write_ui.py +647 -0
  49. omnimancer/core/agent/rich_renderer.py +763 -0
  50. omnimancer/core/agent/status_config.py +238 -0
  51. omnimancer/core/agent/status_core.py +446 -0
  52. omnimancer/core/agent/status_integrated_engine.py +540 -0
  53. omnimancer/core/agent/status_manager.py +878 -0
  54. omnimancer/core/agent/status_ui_components.py +535 -0
  55. omnimancer/core/agent/template_applicator.py +548 -0
  56. omnimancer/core/agent/terminal_status_listener.py +394 -0
  57. omnimancer/core/agent/token_tracker.py +679 -0
  58. omnimancer/core/agent/types.py +60 -0
  59. omnimancer/core/agent/web_client.py +745 -0
  60. omnimancer/core/agent/workflow_orchestrator.py +826 -0
  61. omnimancer/core/agent_engine.py +1625 -0
  62. omnimancer/core/agent_mode_manager.py +706 -0
  63. omnimancer/core/agent_progress_ui.py +545 -0
  64. omnimancer/core/chat_manager.py +141 -0
  65. omnimancer/core/config_manager.py +2199 -0
  66. omnimancer/core/config_migration.py +772 -0
  67. omnimancer/core/config_provider.py +1974 -0
  68. omnimancer/core/config_security_validator.py +393 -0
  69. omnimancer/core/config_validator.py +768 -0
  70. omnimancer/core/conversation_manager.py +352 -0
  71. omnimancer/core/engine.py +787 -0
  72. omnimancer/core/enhanced_input.py +523 -0
  73. omnimancer/core/env_loader.py +83 -0
  74. omnimancer/core/fallback_manager.py +568 -0
  75. omnimancer/core/health_monitor.py +462 -0
  76. omnimancer/core/history_manager.py +462 -0
  77. omnimancer/core/mcp_integration_layer.py +878 -0
  78. omnimancer/core/models.py +1889 -0
  79. omnimancer/core/provider_capabilities.py +403 -0
  80. omnimancer/core/provider_initializer.py +450 -0
  81. omnimancer/core/provider_registry.py +432 -0
  82. omnimancer/core/security/__init__.py +16 -0
  83. omnimancer/core/security/approval_workflow.py +406 -0
  84. omnimancer/core/security/audit_logger.py +511 -0
  85. omnimancer/core/security/permission_controller.py +511 -0
  86. omnimancer/core/security/sandbox_manager.py +379 -0
  87. omnimancer/core/security/security_manager.py +530 -0
  88. omnimancer/core/setup_wizard.py +345 -0
  89. omnimancer/core/setup_wizard_core.py +449 -0
  90. omnimancer/core/setup_wizard_guide_generator.py +376 -0
  91. omnimancer/core/setup_wizard_provider_setup.py +454 -0
  92. omnimancer/core/setup_wizard_ui.py +317 -0
  93. omnimancer/core/setup_wizard_validation.py +371 -0
  94. omnimancer/core/signal_handler.py +174 -0
  95. omnimancer/mcp/__init__.py +11 -0
  96. omnimancer/mcp/client.py +725 -0
  97. omnimancer/mcp/manager.py +649 -0
  98. omnimancer/providers/__init__.py +24 -0
  99. omnimancer/providers/azure.py +608 -0
  100. omnimancer/providers/base.py +262 -0
  101. omnimancer/providers/bedrock.py +711 -0
  102. omnimancer/providers/claude.py +426 -0
  103. omnimancer/providers/claude_code.py +406 -0
  104. omnimancer/providers/cohere.py +412 -0
  105. omnimancer/providers/factory.py +988 -0
  106. omnimancer/providers/gemini.py +708 -0
  107. omnimancer/providers/mistral.py +554 -0
  108. omnimancer/providers/ollama.py +510 -0
  109. omnimancer/providers/openai.py +362 -0
  110. omnimancer/providers/openrouter.py +709 -0
  111. omnimancer/providers/perplexity.py +476 -0
  112. omnimancer/providers/vertex.py +617 -0
  113. omnimancer/providers/xai.py +484 -0
  114. omnimancer/ui/__init__.py +6 -0
  115. omnimancer/ui/cancellation_handler.py +235 -0
  116. omnimancer/ui/progress_indicator.py +318 -0
  117. omnimancer/utils/__init__.py +22 -0
  118. omnimancer/utils/error_handler.py +589 -0
  119. omnimancer/utils/errors.py +667 -0
  120. omnimancer/utils/retry.py +238 -0
  121. omnimancer_cli-0.1.0.dist-info/METADATA +413 -0
  122. omnimancer_cli-0.1.0.dist-info/RECORD +126 -0
  123. omnimancer_cli-0.1.0.dist-info/WHEEL +5 -0
  124. omnimancer_cli-0.1.0.dist-info/entry_points.txt +4 -0
  125. omnimancer_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  126. omnimancer_cli-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,826 @@
1
+ """
2
+ Workflow Orchestrator for continuous multi-step AI operations.
3
+
4
+ This module provides the capability for the AI agent to execute multiple
5
+ operations in sequence automatically, similar to how Claude Code works.
6
+ """
7
+
8
+ import asyncio
9
+ import logging
10
+ from dataclasses import dataclass, field
11
+ from datetime import datetime
12
+ from enum import Enum
13
+ from pathlib import Path
14
+ from typing import Any, Callable, Dict, List, Optional
15
+
16
+ from rich.console import Console
17
+ from rich.markdown import Markdown
18
+ from rich.panel import Panel
19
+
20
+ from ...cli.batch_approval_display import BatchApprovalPanel
21
+
22
+ # Import existing UI components
23
+ from ...ui.progress_indicator import OperationType as ProgressOperationType
24
+ from ...ui.progress_indicator import (
25
+ ProgressIndicator,
26
+ )
27
+ from ..agent.approval_manager import EnhancedApprovalManager
28
+ from ..agent.file_system_manager import FileSystemManager
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ class WorkflowStepType(Enum):
34
+ """Types of workflow steps."""
35
+
36
+ ANALYZE = "analyze"
37
+ LIST_FILES = "list_files"
38
+ READ_FILE = "read_file"
39
+ WRITE_FILE = "write_file"
40
+ EXECUTE_COMMAND = "execute_command"
41
+ CHECK_CONFIG = "check_config"
42
+ DETECT_TECH_STACK = "detect_tech_stack"
43
+ CREATE_STRUCTURE = "create_structure"
44
+ INSTALL_DEPENDENCIES = "install_dependencies"
45
+ RUN_TESTS = "run_tests"
46
+ VALIDATE = "validate"
47
+ CUSTOM = "custom"
48
+
49
+
50
+ class WorkflowStatus(Enum):
51
+ """Status of workflow execution."""
52
+
53
+ PENDING = "pending"
54
+ RUNNING = "running"
55
+ PAUSED = "paused"
56
+ COMPLETED = "completed"
57
+ FAILED = "failed"
58
+ CANCELLED = "cancelled"
59
+
60
+
61
+ @dataclass
62
+ class WorkflowStep:
63
+ """Represents a single step in a workflow."""
64
+
65
+ name: str
66
+ type: WorkflowStepType
67
+ description: str
68
+ action: Optional[Callable] = None
69
+ parameters: Dict[str, Any] = field(default_factory=dict)
70
+ requires_approval: bool = False
71
+ continue_on_error: bool = False
72
+ dependencies: List[str] = field(default_factory=list)
73
+ result: Optional[Any] = None
74
+ status: WorkflowStatus = WorkflowStatus.PENDING
75
+ started_at: Optional[datetime] = None
76
+ completed_at: Optional[datetime] = None
77
+ error: Optional[str] = None
78
+
79
+
80
+ @dataclass
81
+ class WorkflowContext:
82
+ """Context shared across workflow steps."""
83
+
84
+ working_directory: Path
85
+ data: Dict[str, Any] = field(default_factory=dict)
86
+ console: Console = field(default_factory=Console)
87
+ history: List[WorkflowStep] = field(default_factory=list)
88
+
89
+ def set(self, key: str, value: Any) -> None:
90
+ """Set a value in the context."""
91
+ self.data[key] = value
92
+
93
+ def get(self, key: str, default: Any = None) -> Any:
94
+ """Get a value from the context."""
95
+ return self.data.get(key, default)
96
+
97
+ def update(self, **kwargs) -> None:
98
+ """Update multiple values in the context."""
99
+ self.data.update(kwargs)
100
+
101
+
102
+ class WorkflowOrchestrator:
103
+ """
104
+ Orchestrates multi-step workflows for autonomous AI operations.
105
+
106
+ This enables the AI to execute a series of operations automatically,
107
+ continuing through each step without stopping, similar to Claude Code.
108
+ """
109
+
110
+ def __init__(
111
+ self,
112
+ file_system: Optional[FileSystemManager] = None,
113
+ approval_manager: Optional[EnhancedApprovalManager] = None,
114
+ executor: Optional[Any] = None,
115
+ console: Optional[Console] = None,
116
+ engine: Optional[Any] = None,
117
+ ):
118
+ """Initialize the workflow orchestrator."""
119
+ self.file_system = file_system
120
+ self.approval_manager = approval_manager
121
+ self.executor = executor
122
+ self.console = console or Console()
123
+ self.engine = engine # Reference to the main engine for AI calls
124
+ self.workflows: Dict[str, List[WorkflowStep]] = {}
125
+ self.current_workflow: Optional[str] = None
126
+ self.context: Optional[WorkflowContext] = None
127
+
128
+ # Initialize UI components for clean display
129
+ self.progress_indicator = ProgressIndicator(self.console)
130
+ self.approval_panel = BatchApprovalPanel(self.console)
131
+
132
+ # Register built-in workflows
133
+ self._register_builtin_workflows()
134
+
135
+ def _register_builtin_workflows(self) -> None:
136
+ """Register built-in workflow templates."""
137
+
138
+ # General Action Workflow - handles any user request
139
+ self.register_workflow(
140
+ "general_action",
141
+ [
142
+ WorkflowStep(
143
+ name="understand_request",
144
+ type=WorkflowStepType.ANALYZE,
145
+ description="Understanding user request and requirements",
146
+ action=self._understand_request_action,
147
+ parameters={},
148
+ ),
149
+ WorkflowStep(
150
+ name="plan_approach",
151
+ type=WorkflowStepType.ANALYZE,
152
+ description="Planning approach and identifying needed actions",
153
+ action=self._plan_approach_action,
154
+ dependencies=["understand_request"],
155
+ ),
156
+ WorkflowStep(
157
+ name="execute_action",
158
+ type=WorkflowStepType.CUSTOM,
159
+ description="Executing the planned actions",
160
+ action=self._execute_action,
161
+ dependencies=["plan_approach"],
162
+ ),
163
+ WorkflowStep(
164
+ name="verify_results",
165
+ type=WorkflowStepType.VALIDATE,
166
+ description="Verifying action completion and results",
167
+ action=self._verify_results_action,
168
+ dependencies=["execute_action"],
169
+ ),
170
+ WorkflowStep(
171
+ name="provide_summary",
172
+ type=WorkflowStepType.CUSTOM,
173
+ description="Providing summary of completed work",
174
+ action=self._provide_summary_action,
175
+ dependencies=["verify_results"],
176
+ ),
177
+ ],
178
+ )
179
+
180
+ # Project Analysis Workflow
181
+ self.register_workflow(
182
+ "project_analysis",
183
+ [
184
+ WorkflowStep(
185
+ name="list_directory",
186
+ type=WorkflowStepType.LIST_FILES,
187
+ description="List files and directories in the project",
188
+ action=self._list_directory_action,
189
+ parameters={"path": "."},
190
+ ),
191
+ WorkflowStep(
192
+ name="detect_tech_stack",
193
+ type=WorkflowStepType.DETECT_TECH_STACK,
194
+ description="Detect technology stack from project files",
195
+ action=self._detect_tech_stack_action,
196
+ dependencies=["list_directory"],
197
+ ),
198
+ WorkflowStep(
199
+ name="check_configuration",
200
+ type=WorkflowStepType.CHECK_CONFIG,
201
+ description="Check for configuration files",
202
+ action=self._check_configuration_action,
203
+ dependencies=["list_directory"],
204
+ ),
205
+ WorkflowStep(
206
+ name="analyze_structure",
207
+ type=WorkflowStepType.ANALYZE,
208
+ description="Analyze project structure and patterns",
209
+ action=self._analyze_structure_action,
210
+ dependencies=["list_directory", "detect_tech_stack"],
211
+ ),
212
+ WorkflowStep(
213
+ name="generate_summary",
214
+ type=WorkflowStepType.CUSTOM,
215
+ description="Generate project analysis summary",
216
+ action=self._generate_summary_action,
217
+ dependencies=[
218
+ "detect_tech_stack",
219
+ "check_configuration",
220
+ "analyze_structure",
221
+ ],
222
+ ),
223
+ ],
224
+ )
225
+
226
+ # File Modification Workflow
227
+ self.register_workflow(
228
+ "file_modification",
229
+ [
230
+ WorkflowStep(
231
+ name="read_original",
232
+ type=WorkflowStepType.READ_FILE,
233
+ description="Read the original file content",
234
+ action=self._read_file_action,
235
+ ),
236
+ WorkflowStep(
237
+ name="prepare_changes",
238
+ type=WorkflowStepType.CUSTOM,
239
+ description="Prepare file modifications",
240
+ action=self._prepare_changes_action,
241
+ dependencies=["read_original"],
242
+ ),
243
+ WorkflowStep(
244
+ name="show_diff",
245
+ type=WorkflowStepType.CUSTOM,
246
+ description="Display changes for review",
247
+ action=self._show_diff_action,
248
+ dependencies=["prepare_changes"],
249
+ requires_approval=True,
250
+ ),
251
+ WorkflowStep(
252
+ name="apply_changes",
253
+ type=WorkflowStepType.WRITE_FILE,
254
+ description="Apply approved changes to file",
255
+ action=self._write_file_action,
256
+ dependencies=["show_diff"],
257
+ ),
258
+ WorkflowStep(
259
+ name="validate_changes",
260
+ type=WorkflowStepType.VALIDATE,
261
+ description="Validate the applied changes",
262
+ action=self._validate_changes_action,
263
+ dependencies=["apply_changes"],
264
+ ),
265
+ ],
266
+ )
267
+
268
+ def register_workflow(self, name: str, steps: List[WorkflowStep]) -> None:
269
+ """Register a workflow template."""
270
+ self.workflows[name] = steps
271
+
272
+ async def execute_workflow(
273
+ self,
274
+ workflow_name: str,
275
+ context: Optional[WorkflowContext] = None,
276
+ parameters: Optional[Dict[str, Any]] = None,
277
+ ) -> WorkflowContext:
278
+ """
279
+ Execute a complete workflow automatically.
280
+
281
+ This is the main entry point that enables continuous execution
282
+ of multiple steps without stopping.
283
+ """
284
+ if workflow_name not in self.workflows:
285
+ raise ValueError(f"Unknown workflow: {workflow_name}")
286
+
287
+ # Initialize context
288
+ self.context = context or WorkflowContext(
289
+ working_directory=Path.cwd(), console=self.console
290
+ )
291
+
292
+ # Pass engine reference to context
293
+ self.context.engine = self.engine
294
+
295
+ if parameters:
296
+ self.context.update(**parameters)
297
+
298
+ self.current_workflow = workflow_name
299
+ steps = self.workflows[workflow_name].copy()
300
+
301
+ # Display workflow plan
302
+ await self._display_workflow_plan(workflow_name, steps)
303
+
304
+ # Execute workflow steps with progress tracking
305
+ for i, step in enumerate(steps, 1):
306
+ # Check dependencies
307
+ if not self._check_dependencies(step, self.context.history):
308
+ step.status = WorkflowStatus.FAILED
309
+ step.error = "Dependencies not met"
310
+ self.context.history.append(step)
311
+
312
+ if not step.continue_on_error:
313
+ break
314
+ continue
315
+
316
+ # Start progress tracking for this step
317
+ operation_id = f"step_{i}"
318
+ progress_type = self._get_progress_operation_type(step.type)
319
+ self.progress_indicator.start_operation(
320
+ operation_id, progress_type, f"{step.name}: {step.description}"
321
+ )
322
+
323
+ try:
324
+ step.status = WorkflowStatus.RUNNING
325
+ step.started_at = datetime.now()
326
+
327
+ # Request approval if needed
328
+ if step.requires_approval and self.approval_manager:
329
+ if not await self._request_approval(step):
330
+ step.status = WorkflowStatus.CANCELLED
331
+ self.context.history.append(step)
332
+ self.progress_indicator.complete_operation(
333
+ operation_id, "cancelled"
334
+ )
335
+ break
336
+
337
+ # Execute the step action
338
+ if step.action:
339
+ # Merge step parameters with context parameters
340
+ merged_params = {**step.parameters, **self.context.data}
341
+ step.result = await step.action(self.context, merged_params)
342
+
343
+ step.status = WorkflowStatus.COMPLETED
344
+ step.completed_at = datetime.now()
345
+
346
+ # Complete progress tracking
347
+ self.progress_indicator.complete_operation(operation_id, "completed")
348
+
349
+ except Exception as e:
350
+ step.status = WorkflowStatus.FAILED
351
+ step.error = str(e)
352
+ step.completed_at = datetime.now()
353
+
354
+ logger.error(f"Step {step.name} failed: {e}")
355
+ self.progress_indicator.complete_operation(operation_id, "failed")
356
+
357
+ if not step.continue_on_error:
358
+ break
359
+
360
+ finally:
361
+ self.context.history.append(step)
362
+
363
+ # Display workflow summary
364
+ await self._display_workflow_summary()
365
+
366
+ return self.context
367
+
368
+ async def _display_workflow_plan(
369
+ self, name: str, steps: List[WorkflowStep]
370
+ ) -> None:
371
+ """Display the workflow execution plan using clean UI."""
372
+ self.console.print(f"\n[bold cyan]🚀 Starting workflow: {name}[/bold cyan]")
373
+ self.console.print(f"[dim]Will execute {len(steps)} steps...[/dim]\n")
374
+
375
+ def _check_dependencies(
376
+ self, step: WorkflowStep, history: List[WorkflowStep]
377
+ ) -> bool:
378
+ """Check if all dependencies for a step are satisfied."""
379
+ if not step.dependencies:
380
+ return True
381
+
382
+ completed_steps = {
383
+ s.name for s in history if s.status == WorkflowStatus.COMPLETED
384
+ }
385
+ return all(dep in completed_steps for dep in step.dependencies)
386
+
387
+ async def _request_approval(self, step: WorkflowStep) -> bool:
388
+ """Request approval for a step that requires it."""
389
+ self.console.print(f"\n[yellow]⚠ Step '{step.name}' requires approval[/yellow]")
390
+ self.console.print(f"Description: {step.description}")
391
+
392
+ # Use the approval manager if available
393
+ if self.approval_manager and hasattr(self.approval_manager, "request_approval"):
394
+ # Create a basic operation object for the approval manager
395
+ from .types import Operation, OperationType
396
+
397
+ operation = Operation(
398
+ type=OperationType.WORKFLOW_STEP,
399
+ description=step.description,
400
+ data={"step_name": step.name, "description": step.description},
401
+ requires_approval=True,
402
+ )
403
+ approved = await self.approval_manager.request_approval(operation)
404
+ if approved:
405
+ self.console.print("[green]✓ Approved[/green]")
406
+ else:
407
+ self.console.print("[red]✗ Denied[/red]")
408
+ return approved
409
+
410
+ # Default behavior for demo/test purposes
411
+ await asyncio.sleep(0.5) # Simulate approval delay
412
+ self.console.print("[green]✓ Approved[/green]")
413
+ return True
414
+
415
+ def _display_step_result(self, step: WorkflowStep) -> None:
416
+ """Display the result of a completed step."""
417
+ status_symbol = "✓" if step.status == WorkflowStatus.COMPLETED else "✗"
418
+ status_color = "green" if step.status == WorkflowStatus.COMPLETED else "red"
419
+
420
+ self.console.print(
421
+ f"[{status_color}]{status_symbol}[/{status_color}] {step.name}: {step.description}"
422
+ )
423
+
424
+ if step.error:
425
+ self.console.print(f" [red]Error: {step.error}[/red]")
426
+
427
+ async def _display_workflow_summary(self) -> None:
428
+ """Display a clean summary of the workflow execution."""
429
+ completed = sum(
430
+ 1 for s in self.context.history if s.status == WorkflowStatus.COMPLETED
431
+ )
432
+ failed = sum(
433
+ 1 for s in self.context.history if s.status == WorkflowStatus.FAILED
434
+ )
435
+ total = len(self.context.history)
436
+
437
+ if failed == 0:
438
+ self.console.print(
439
+ f"\n[bold green]✅ Workflow completed successfully![/bold green]"
440
+ )
441
+ else:
442
+ self.console.print(
443
+ f"\n[yellow]⚠️ Workflow completed with {failed} issues[/yellow]"
444
+ )
445
+
446
+ self.console.print(f"[dim]Executed {completed}/{total} steps[/dim]")
447
+
448
+ def _get_progress_operation_type(
449
+ self, workflow_step_type: WorkflowStepType
450
+ ) -> ProgressOperationType:
451
+ """Map workflow step types to progress indicator operation types."""
452
+ type_mapping = {
453
+ WorkflowStepType.READ_FILE: ProgressOperationType.READ,
454
+ WorkflowStepType.WRITE_FILE: ProgressOperationType.WRITE,
455
+ WorkflowStepType.ANALYZE: ProgressOperationType.ANALYZE,
456
+ WorkflowStepType.VALIDATE: ProgressOperationType.VALIDATE,
457
+ WorkflowStepType.CUSTOM: ProgressOperationType.OTHER,
458
+ }
459
+ return type_mapping.get(workflow_step_type, ProgressOperationType.OTHER)
460
+
461
+ # Built-in action implementations
462
+
463
+ async def _list_directory_action(
464
+ self, context: WorkflowContext, params: Dict[str, Any]
465
+ ) -> List[str]:
466
+ """List directory contents."""
467
+ path = Path(params.get("path", "."))
468
+ files = []
469
+
470
+ context.console.print(f"\n[cyan]Listing directory: {path}[/cyan]")
471
+
472
+ for item in path.iterdir():
473
+ if item.is_dir():
474
+ files.append(f"📁 {item.name}/")
475
+ else:
476
+ files.append(f"📄 {item.name}")
477
+
478
+ # Display first 10 items
479
+ for file in files[:10]:
480
+ context.console.print(f" {file}")
481
+
482
+ if len(files) > 10:
483
+ context.console.print(f" ... and {len(files) - 10} more items")
484
+
485
+ context.set("project_files", files)
486
+ return files
487
+
488
+ async def _detect_tech_stack_action(
489
+ self, context: WorkflowContext, params: Dict[str, Any]
490
+ ) -> Dict[str, Any]:
491
+ """Detect technology stack from project files."""
492
+ context.console.print("\n[cyan]Detecting technology stack...[/cyan]")
493
+
494
+ tech_stack = {}
495
+ files = context.get("project_files", [])
496
+
497
+ # Check for common tech indicators
498
+ file_names = [f.replace("📄 ", "").replace("📁 ", "").strip("/") for f in files]
499
+
500
+ if "package.json" in file_names:
501
+ tech_stack["javascript"] = "Node.js/npm"
502
+ context.console.print(" ✓ Found: Node.js project (package.json)")
503
+
504
+ if (
505
+ "requirements.txt" in file_names
506
+ or "setup.py" in file_names
507
+ or "pyproject.toml" in file_names
508
+ ):
509
+ tech_stack["python"] = "Python/pip"
510
+ context.console.print(" ✓ Found: Python project")
511
+
512
+ if "Cargo.toml" in file_names:
513
+ tech_stack["rust"] = "Rust/Cargo"
514
+ context.console.print(" ✓ Found: Rust project")
515
+
516
+ if ".git" in file_names:
517
+ tech_stack["vcs"] = "Git"
518
+ context.console.print(" ✓ Found: Git repository")
519
+
520
+ if ".mcp.json" in file_names:
521
+ tech_stack["mcp"] = "Model Context Protocol"
522
+ context.console.print(" ✓ Found: MCP server configuration")
523
+
524
+ # Check for Omnimancer specific patterns
525
+ if any("omnimancer" in f.lower() for f in file_names):
526
+ tech_stack["omnimancer"] = "Omnimancer CLI Framework"
527
+ context.console.print(" ✓ Found: Omnimancer framework")
528
+
529
+ context.set("tech_stack", tech_stack)
530
+ return tech_stack
531
+
532
+ async def _check_configuration_action(
533
+ self, context: WorkflowContext, params: Dict[str, Any]
534
+ ) -> Dict[str, Any]:
535
+ """Check for configuration files."""
536
+ context.console.print("\n[cyan]Checking configuration files...[/cyan]")
537
+
538
+ config_files = {}
539
+ files = context.get("project_files", [])
540
+ file_names = [f.replace("📄 ", "").replace("📁 ", "").strip("/") for f in files]
541
+
542
+ config_patterns = {
543
+ ".env": "Environment variables",
544
+ "config.json": "JSON configuration",
545
+ "config.yaml": "YAML configuration",
546
+ ".gitignore": "Git ignore rules",
547
+ "Dockerfile": "Docker configuration",
548
+ ".github": "GitHub workflows",
549
+ ".mcp.json": "MCP server configuration",
550
+ "pyproject.toml": "Python project configuration",
551
+ ".taskmaster": "Task Master AI configuration",
552
+ ".claude": "Claude Code configuration",
553
+ }
554
+
555
+ for pattern, description in config_patterns.items():
556
+ if pattern in file_names:
557
+ config_files[pattern] = description
558
+ context.console.print(f" ✓ Found: {description} ({pattern})")
559
+
560
+ context.set("config_files", config_files)
561
+ return config_files
562
+
563
+ async def _analyze_structure_action(
564
+ self, context: WorkflowContext, params: Dict[str, Any]
565
+ ) -> Dict[str, Any]:
566
+ """Analyze project structure."""
567
+ context.console.print("\n[cyan]Analyzing project structure...[/cyan]")
568
+
569
+ analysis = {"type": "Unknown", "patterns": []}
570
+
571
+ tech_stack = context.get("tech_stack", {})
572
+
573
+ if "python" in tech_stack:
574
+ analysis["type"] = "Python Application"
575
+ analysis["patterns"].append("Python package structure detected")
576
+ context.console.print(" ✓ Identified as Python application")
577
+
578
+ if "javascript" in tech_stack:
579
+ analysis["type"] = "Node.js Application"
580
+ analysis["patterns"].append("Node.js project structure detected")
581
+ context.console.print(" ✓ Identified as Node.js application")
582
+
583
+ context.set("structure_analysis", analysis)
584
+ return analysis
585
+
586
+ async def _generate_summary_action(
587
+ self, context: WorkflowContext, params: Dict[str, Any]
588
+ ) -> str:
589
+ """Generate a summary of the analysis."""
590
+ context.console.print("\n[cyan]Generating analysis summary...[/cyan]")
591
+
592
+ tech_stack = context.get("tech_stack", {})
593
+ config_files = context.get("config_files", {})
594
+ analysis = context.get("structure_analysis", {})
595
+
596
+ summary = f"""
597
+ ### Project Analysis Complete
598
+
599
+ **Project Type:** {analysis.get('type', 'Unknown')}
600
+
601
+ **Technology Stack:**
602
+ {chr(10).join(f"- {tech}: {desc}" for tech, desc in tech_stack.items())}
603
+
604
+ **Configuration Files:**
605
+ {chr(10).join(f"- {file}: {desc}" for file, desc in config_files.items())}
606
+
607
+ **Patterns Detected:**
608
+ {chr(10).join(f"- {pattern}" for pattern in analysis.get('patterns', []))}
609
+ """
610
+
611
+ context.console.print(
612
+ Panel(
613
+ Markdown(summary),
614
+ title="[bold]Analysis Summary[/bold]",
615
+ border_style="green",
616
+ )
617
+ )
618
+
619
+ context.set("summary", summary)
620
+ return summary
621
+
622
+ async def _read_file_action(
623
+ self, context: WorkflowContext, params: Dict[str, Any]
624
+ ) -> str:
625
+ """Read file content."""
626
+ file_path = params.get("file_path")
627
+ if not file_path:
628
+ raise ValueError("file_path parameter required")
629
+
630
+ if self.file_system:
631
+ content = await self.file_system.read_file(file_path)
632
+ context.set("original_content", content)
633
+ return content
634
+ return ""
635
+
636
+ async def _prepare_changes_action(
637
+ self, context: WorkflowContext, params: Dict[str, Any]
638
+ ) -> Dict[str, Any]:
639
+ """Prepare file changes."""
640
+ original = context.get("original_content", "")
641
+ changes = params.get("changes", {})
642
+
643
+ # Prepare the modified content
644
+ modified = changes.get("content", original)
645
+
646
+ context.set("modified_content", modified)
647
+ context.set("changes", changes)
648
+
649
+ return {"original": original, "modified": modified}
650
+
651
+ async def _show_diff_action(
652
+ self, context: WorkflowContext, params: Dict[str, Any]
653
+ ) -> None:
654
+ """Show diff for review."""
655
+ context.get("original_content", "")
656
+ context.get("modified_content", "")
657
+
658
+ # In a real implementation, this would use the diff renderer
659
+ context.console.print("\n[yellow]Changes to review:[/yellow]")
660
+ context.console.print("(Diff display would appear here)")
661
+
662
+ async def _write_file_action(
663
+ self, context: WorkflowContext, params: Dict[str, Any]
664
+ ) -> bool:
665
+ """Write file content."""
666
+ file_path = params.get("file_path")
667
+ content = context.get("modified_content", "")
668
+
669
+ if not file_path:
670
+ raise ValueError("file_path parameter required")
671
+
672
+ if self.file_system:
673
+ await self.file_system.write_file(file_path, content)
674
+ return True
675
+ return False
676
+
677
+ async def _validate_changes_action(
678
+ self, context: WorkflowContext, params: Dict[str, Any]
679
+ ) -> bool:
680
+ """Validate applied changes."""
681
+ # In a real implementation, this would verify the changes were applied correctly
682
+ context.console.print("[green]✓ Changes validated successfully[/green]")
683
+ return True
684
+
685
+ # General Action Workflow Methods
686
+
687
+ async def _understand_request_action(
688
+ self, context: WorkflowContext, params: Dict[str, Any]
689
+ ) -> Dict[str, Any]:
690
+ """Understand and analyze the user's request."""
691
+ user_request = params.get("user_request", context.get("user_request", ""))
692
+
693
+ # Simulate analyzing the request
694
+ context.console.print(f"[cyan]📝 Analyzing request: '{user_request}'[/cyan]")
695
+
696
+ # Parse the request to understand intent and extract key information
697
+ analysis = {
698
+ "original_request": user_request,
699
+ "intent": "general_action",
700
+ "complexity": "medium",
701
+ "estimated_steps": 3,
702
+ }
703
+
704
+ # Store analysis in context for next steps
705
+ context.set("request_analysis", analysis)
706
+ return analysis
707
+
708
+ async def _plan_approach_action(
709
+ self, context: WorkflowContext, params: Dict[str, Any]
710
+ ) -> Dict[str, Any]:
711
+ """Plan the approach to fulfill the user's request."""
712
+ analysis = context.get("request_analysis", {})
713
+ user_request = analysis.get("original_request", "")
714
+
715
+ context.console.print(f"[cyan]🎯 Planning approach for: {user_request}[/cyan]")
716
+
717
+ # Create a basic plan based on the request
718
+ plan = {
719
+ "approach": "autonomous_execution",
720
+ "steps": [
721
+ "Prepare AI prompt with user request",
722
+ "Execute action using agent capabilities",
723
+ "Capture and process results",
724
+ "Verify completion",
725
+ ],
726
+ "requires_approval": False,
727
+ }
728
+
729
+ context.set("execution_plan", plan)
730
+ return plan
731
+
732
+ async def _execute_action(
733
+ self, context: WorkflowContext, params: Dict[str, Any]
734
+ ) -> Dict[str, Any]:
735
+ """Execute the planned action autonomously."""
736
+ user_request = context.get("user_request", "")
737
+
738
+ context.console.print(f"[cyan]🚀 Executing autonomous action...[/cyan]")
739
+
740
+ # Actually execute the user request with AI provider if available
741
+ try:
742
+ # Send the request to AI with agent capabilities enabled
743
+ if hasattr(context, "engine") and context.engine:
744
+ # The agent engine inherits from core engine which has send_message
745
+ response = await context.engine.send_message(user_request)
746
+
747
+ if response.is_success:
748
+ result = {
749
+ "status": "completed",
750
+ "action_taken": f"AI processed request: {user_request}",
751
+ "details": response.content,
752
+ "ai_response": response.content,
753
+ "timestamp": "just now",
754
+ }
755
+ else:
756
+ result = {
757
+ "status": "failed",
758
+ "action_taken": f"Failed to process: {user_request}",
759
+ "details": f"Error: {response.error}",
760
+ "error": response.error,
761
+ "timestamp": "just now",
762
+ }
763
+ else:
764
+ # Fallback: simulate execution
765
+ result = {
766
+ "status": "completed",
767
+ "action_taken": f"Processed request: {user_request}",
768
+ "details": "Action executed using autonomous workflow system (simulated)",
769
+ "timestamp": "just now",
770
+ }
771
+
772
+ except Exception as e:
773
+ result = {
774
+ "status": "failed",
775
+ "action_taken": f"Error processing: {user_request}",
776
+ "details": f"Exception: {str(e)}",
777
+ "error": str(e),
778
+ "timestamp": "just now",
779
+ }
780
+
781
+ context.set("execution_result", result)
782
+ return result
783
+
784
+ async def _verify_results_action(
785
+ self, context: WorkflowContext, params: Dict[str, Any]
786
+ ) -> bool:
787
+ """Verify that the action was completed successfully."""
788
+ result = context.get("execution_result", {})
789
+
790
+ context.console.print("[cyan]✅ Verifying action completion...[/cyan]")
791
+
792
+ # Check if execution was successful
793
+ success = result.get("status") == "completed"
794
+
795
+ if success:
796
+ context.console.print("[green]✓ Action completed successfully[/green]")
797
+ else:
798
+ context.console.print("[red]✗ Action may not have completed fully[/red]")
799
+
800
+ context.set("verification_success", success)
801
+ return success
802
+
803
+ async def _provide_summary_action(
804
+ self, context: WorkflowContext, params: Dict[str, Any]
805
+ ) -> str:
806
+ """Provide a summary of what was accomplished."""
807
+ user_request = context.get("user_request", "")
808
+ result = context.get("execution_result", {})
809
+ success = context.get("verification_success", False)
810
+
811
+ if success:
812
+ if "ai_response" in result:
813
+ # Don't show summary if we have the actual AI response - it will be shown in interface
814
+ summary = f"✅ Successfully completed: {user_request}"
815
+ context.console.print(f"[bold green]📋 Summary:[/bold green] {summary}")
816
+ else:
817
+ summary = f"✅ Successfully completed: {user_request}\n\nAction taken: {result.get('action_taken', 'Autonomous workflow execution')}"
818
+ context.console.print(
819
+ f"[bold green]📋 Summary:[/bold green]\n{summary}"
820
+ )
821
+ else:
822
+ summary = f"⚠️ Partially completed: {user_request}\n\nStatus: Some issues may have occurred during execution"
823
+ context.console.print(f"[bold yellow]📋 Summary:[/bold yellow]\n{summary}")
824
+
825
+ context.set("final_summary", summary)
826
+ return summary