empathy-framework 5.1.0__py3-none-any.whl → 5.2.1__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.
- {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/METADATA +52 -3
- {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/RECORD +71 -30
- empathy_os/__init__.py +1 -1
- empathy_os/cli_router.py +21 -0
- empathy_os/core_modules/__init__.py +15 -0
- empathy_os/mcp/__init__.py +10 -0
- empathy_os/mcp/server.py +506 -0
- empathy_os/memory/control_panel.py +1 -131
- empathy_os/memory/control_panel_support.py +145 -0
- empathy_os/memory/encryption.py +159 -0
- empathy_os/memory/long_term.py +41 -626
- empathy_os/memory/long_term_types.py +99 -0
- empathy_os/memory/mixins/__init__.py +25 -0
- empathy_os/memory/mixins/backend_init_mixin.py +244 -0
- empathy_os/memory/mixins/capabilities_mixin.py +199 -0
- empathy_os/memory/mixins/handoff_mixin.py +208 -0
- empathy_os/memory/mixins/lifecycle_mixin.py +49 -0
- empathy_os/memory/mixins/long_term_mixin.py +352 -0
- empathy_os/memory/mixins/promotion_mixin.py +109 -0
- empathy_os/memory/mixins/short_term_mixin.py +182 -0
- empathy_os/memory/short_term.py +7 -0
- empathy_os/memory/simple_storage.py +302 -0
- empathy_os/memory/storage_backend.py +167 -0
- empathy_os/memory/unified.py +21 -1120
- empathy_os/meta_workflows/cli_commands/__init__.py +56 -0
- empathy_os/meta_workflows/cli_commands/agent_commands.py +321 -0
- empathy_os/meta_workflows/cli_commands/analytics_commands.py +442 -0
- empathy_os/meta_workflows/cli_commands/config_commands.py +232 -0
- empathy_os/meta_workflows/cli_commands/memory_commands.py +182 -0
- empathy_os/meta_workflows/cli_commands/template_commands.py +354 -0
- empathy_os/meta_workflows/cli_commands/workflow_commands.py +382 -0
- empathy_os/meta_workflows/cli_meta_workflows.py +52 -1802
- empathy_os/meta_workflows/intent_detector.py +71 -0
- empathy_os/models/telemetry/__init__.py +71 -0
- empathy_os/models/telemetry/analytics.py +594 -0
- empathy_os/models/telemetry/backend.py +196 -0
- empathy_os/models/telemetry/data_models.py +431 -0
- empathy_os/models/telemetry/storage.py +489 -0
- empathy_os/orchestration/__init__.py +35 -0
- empathy_os/orchestration/execution_strategies.py +481 -0
- empathy_os/orchestration/meta_orchestrator.py +488 -1
- empathy_os/routing/workflow_registry.py +36 -0
- empathy_os/telemetry/cli.py +19 -724
- empathy_os/telemetry/commands/__init__.py +14 -0
- empathy_os/telemetry/commands/dashboard_commands.py +696 -0
- empathy_os/tools.py +183 -0
- empathy_os/workflows/__init__.py +5 -0
- empathy_os/workflows/autonomous_test_gen.py +860 -161
- empathy_os/workflows/base.py +6 -2
- empathy_os/workflows/code_review.py +4 -1
- empathy_os/workflows/document_gen/__init__.py +25 -0
- empathy_os/workflows/document_gen/config.py +30 -0
- empathy_os/workflows/document_gen/report_formatter.py +162 -0
- empathy_os/workflows/document_gen/workflow.py +1426 -0
- empathy_os/workflows/document_gen.py +22 -1598
- empathy_os/workflows/security_audit.py +2 -2
- empathy_os/workflows/security_audit_phase3.py +7 -4
- empathy_os/workflows/seo_optimization.py +633 -0
- empathy_os/workflows/test_gen/__init__.py +52 -0
- empathy_os/workflows/test_gen/ast_analyzer.py +249 -0
- empathy_os/workflows/test_gen/config.py +88 -0
- empathy_os/workflows/test_gen/data_models.py +38 -0
- empathy_os/workflows/test_gen/report_formatter.py +289 -0
- empathy_os/workflows/test_gen/test_templates.py +381 -0
- empathy_os/workflows/test_gen/workflow.py +655 -0
- empathy_os/workflows/test_gen.py +42 -1905
- empathy_os/memory/types 2.py +0 -441
- empathy_os/models/telemetry.py +0 -1660
- {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/WHEEL +0 -0
- {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/entry_points.txt +0 -0
- {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE +0 -0
- {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -0
- {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/top_level.txt +0 -0
|
@@ -54,12 +54,19 @@ class TaskDomain(Enum):
|
|
|
54
54
|
class CompositionPattern(Enum):
|
|
55
55
|
"""Available composition patterns (grammar rules)."""
|
|
56
56
|
|
|
57
|
+
# Original 7 patterns
|
|
57
58
|
SEQUENTIAL = "sequential" # A → B → C
|
|
58
59
|
PARALLEL = "parallel" # A || B || C
|
|
59
60
|
DEBATE = "debate" # A ⇄ B ⇄ C → Synthesis
|
|
60
61
|
TEACHING = "teaching" # Junior → Expert validation
|
|
61
62
|
REFINEMENT = "refinement" # Draft → Review → Polish
|
|
62
63
|
ADAPTIVE = "adaptive" # Classifier → Specialist
|
|
64
|
+
CONDITIONAL = "conditional" # If-then-else routing
|
|
65
|
+
|
|
66
|
+
# Anthropic-inspired patterns (Patterns 8-10)
|
|
67
|
+
TOOL_ENHANCED = "tool_enhanced" # Single agent with tools
|
|
68
|
+
PROMPT_CACHED_SEQUENTIAL = "prompt_cached_sequential" # Shared cached context
|
|
69
|
+
DELEGATION_CHAIN = "delegation_chain" # Hierarchical delegation (≤3 levels)
|
|
63
70
|
|
|
64
71
|
|
|
65
72
|
@dataclass
|
|
@@ -303,7 +310,7 @@ class MetaOrchestrator:
|
|
|
303
310
|
)
|
|
304
311
|
|
|
305
312
|
def analyze_and_compose(
|
|
306
|
-
self, task: str, context: dict[str, Any] | None = None
|
|
313
|
+
self, task: str, context: dict[str, Any] | None = None, interactive: bool = False
|
|
307
314
|
) -> ExecutionPlan:
|
|
308
315
|
"""Analyze task and create execution plan.
|
|
309
316
|
|
|
@@ -312,6 +319,7 @@ class MetaOrchestrator:
|
|
|
312
319
|
Args:
|
|
313
320
|
task: Task description (e.g., "Boost test coverage to 90%")
|
|
314
321
|
context: Optional context dictionary
|
|
322
|
+
interactive: If True, prompts user for low-confidence cases (default: False)
|
|
315
323
|
|
|
316
324
|
Returns:
|
|
317
325
|
ExecutionPlan with agents and strategy
|
|
@@ -330,6 +338,11 @@ class MetaOrchestrator:
|
|
|
330
338
|
raise ValueError("task must be a non-empty string")
|
|
331
339
|
|
|
332
340
|
context = context or {}
|
|
341
|
+
|
|
342
|
+
# Use interactive mode if requested
|
|
343
|
+
if interactive:
|
|
344
|
+
return self.analyze_and_compose_interactive(task, context)
|
|
345
|
+
|
|
333
346
|
logger.info(f"Analyzing task: {task}")
|
|
334
347
|
|
|
335
348
|
# Step 1: Analyze task requirements
|
|
@@ -353,6 +366,440 @@ class MetaOrchestrator:
|
|
|
353
366
|
|
|
354
367
|
return plan
|
|
355
368
|
|
|
369
|
+
def analyze_and_compose_interactive(
|
|
370
|
+
self, task: str, context: dict[str, Any] | None = None
|
|
371
|
+
) -> ExecutionPlan:
|
|
372
|
+
"""Analyze task with user confirmation for ambiguous cases.
|
|
373
|
+
|
|
374
|
+
This method uses confidence scoring to determine when to ask the user
|
|
375
|
+
for input. High-confidence selections proceed automatically, while
|
|
376
|
+
low-confidence cases prompt the user to choose.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
task: Task description
|
|
380
|
+
context: Optional context dictionary
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
ExecutionPlan with agents and strategy
|
|
384
|
+
|
|
385
|
+
Raises:
|
|
386
|
+
ValueError: If task is invalid
|
|
387
|
+
ImportError: If AskUserQuestion tool is not available
|
|
388
|
+
|
|
389
|
+
Example:
|
|
390
|
+
>>> orchestrator = MetaOrchestrator()
|
|
391
|
+
>>> plan = orchestrator.analyze_and_compose_interactive(
|
|
392
|
+
... task="Complex architectural redesign",
|
|
393
|
+
... context={}
|
|
394
|
+
... )
|
|
395
|
+
# User may be prompted to choose approach if confidence is low
|
|
396
|
+
"""
|
|
397
|
+
if not task or not isinstance(task, str):
|
|
398
|
+
raise ValueError("task must be a non-empty string")
|
|
399
|
+
|
|
400
|
+
context = context or {}
|
|
401
|
+
logger.info(f"Analyzing task interactively: {task}")
|
|
402
|
+
|
|
403
|
+
# Step 1: Analyze task requirements
|
|
404
|
+
requirements = self._analyze_task(task, context)
|
|
405
|
+
logger.info(
|
|
406
|
+
f"Task analysis: complexity={requirements.complexity.value}, "
|
|
407
|
+
f"domain={requirements.domain.value}"
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Step 2: Select agents
|
|
411
|
+
agents = self._select_agents(requirements)
|
|
412
|
+
logger.info(f"Selected {len(agents)} agents: {[a.id for a in agents]}")
|
|
413
|
+
|
|
414
|
+
# Step 3: Choose pattern
|
|
415
|
+
recommended_pattern = self._choose_composition_pattern(requirements, agents)
|
|
416
|
+
logger.info(f"Recommended strategy: {recommended_pattern.value}")
|
|
417
|
+
|
|
418
|
+
# Step 4: Calculate confidence in recommendation
|
|
419
|
+
confidence = self._calculate_confidence(requirements, agents, recommended_pattern)
|
|
420
|
+
logger.info(f"Confidence score: {confidence:.2f}")
|
|
421
|
+
|
|
422
|
+
# Step 5: Branch based on confidence
|
|
423
|
+
if confidence >= 0.8:
|
|
424
|
+
# High confidence → automatic execution
|
|
425
|
+
logger.info("High confidence - proceeding automatically")
|
|
426
|
+
return self.create_execution_plan(requirements, agents, recommended_pattern)
|
|
427
|
+
|
|
428
|
+
else:
|
|
429
|
+
# Low confidence → ask user
|
|
430
|
+
logger.info("Low confidence - prompting user for choice")
|
|
431
|
+
return self._prompt_user_for_approach(
|
|
432
|
+
requirements, agents, recommended_pattern, confidence
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
def _calculate_confidence(
|
|
436
|
+
self,
|
|
437
|
+
requirements: TaskRequirements,
|
|
438
|
+
agents: list[AgentTemplate],
|
|
439
|
+
pattern: CompositionPattern,
|
|
440
|
+
) -> float:
|
|
441
|
+
"""Calculate confidence in automatic pattern selection.
|
|
442
|
+
|
|
443
|
+
Confidence scoring considers:
|
|
444
|
+
- Domain clarity (GENERAL domain reduces confidence)
|
|
445
|
+
- Agent count (many agents = complex coordination)
|
|
446
|
+
- Task complexity (complex tasks have multiple valid approaches)
|
|
447
|
+
- Pattern specificity (Anthropic patterns have clear heuristics)
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
requirements: Task requirements
|
|
451
|
+
agents: Selected agents
|
|
452
|
+
pattern: Recommended composition pattern
|
|
453
|
+
|
|
454
|
+
Returns:
|
|
455
|
+
Confidence score between 0.0 and 1.0
|
|
456
|
+
|
|
457
|
+
Example:
|
|
458
|
+
>>> confidence = orchestrator._calculate_confidence(
|
|
459
|
+
... requirements=TaskRequirements(
|
|
460
|
+
... complexity=TaskComplexity.SIMPLE,
|
|
461
|
+
... domain=TaskDomain.TESTING,
|
|
462
|
+
... capabilities_needed=["analyze_gaps"]
|
|
463
|
+
... ),
|
|
464
|
+
... agents=[test_agent],
|
|
465
|
+
... pattern=CompositionPattern.SEQUENTIAL
|
|
466
|
+
... )
|
|
467
|
+
>>> confidence >= 0.8 # High confidence for simple, clear task
|
|
468
|
+
True
|
|
469
|
+
"""
|
|
470
|
+
confidence = 1.0
|
|
471
|
+
|
|
472
|
+
# Reduce confidence for ambiguous cases
|
|
473
|
+
if requirements.domain == TaskDomain.GENERAL:
|
|
474
|
+
confidence *= 0.7 # Generic tasks are less clear
|
|
475
|
+
|
|
476
|
+
if len(agents) > 5:
|
|
477
|
+
confidence *= 0.8 # Many agents → complex coordination
|
|
478
|
+
|
|
479
|
+
if requirements.complexity == TaskComplexity.COMPLEX:
|
|
480
|
+
confidence *= 0.85 # Complex → multiple valid approaches
|
|
481
|
+
|
|
482
|
+
# Increase confidence for clear patterns
|
|
483
|
+
if pattern in [
|
|
484
|
+
CompositionPattern.TOOL_ENHANCED,
|
|
485
|
+
CompositionPattern.DELEGATION_CHAIN,
|
|
486
|
+
CompositionPattern.PROMPT_CACHED_SEQUENTIAL,
|
|
487
|
+
]:
|
|
488
|
+
confidence *= 1.1 # New Anthropic patterns have clear heuristics
|
|
489
|
+
|
|
490
|
+
# Specific domain patterns also get confidence boost
|
|
491
|
+
if pattern in [
|
|
492
|
+
CompositionPattern.TEACHING,
|
|
493
|
+
CompositionPattern.REFINEMENT,
|
|
494
|
+
] and requirements.domain in [TaskDomain.DOCUMENTATION, TaskDomain.REFACTORING]:
|
|
495
|
+
confidence *= 1.05 # Domain-specific pattern match
|
|
496
|
+
|
|
497
|
+
return min(confidence, 1.0)
|
|
498
|
+
|
|
499
|
+
def _prompt_user_for_approach(
|
|
500
|
+
self,
|
|
501
|
+
requirements: TaskRequirements,
|
|
502
|
+
agents: list[AgentTemplate],
|
|
503
|
+
recommended_pattern: CompositionPattern,
|
|
504
|
+
confidence: float,
|
|
505
|
+
) -> ExecutionPlan:
|
|
506
|
+
"""Prompt user to choose approach when confidence is low.
|
|
507
|
+
|
|
508
|
+
Presents three options:
|
|
509
|
+
1. Use recommended pattern (with confidence score)
|
|
510
|
+
2. Customize team composition
|
|
511
|
+
3. Show all patterns and choose
|
|
512
|
+
|
|
513
|
+
Args:
|
|
514
|
+
requirements: Task requirements
|
|
515
|
+
agents: Selected agents
|
|
516
|
+
recommended_pattern: Recommended pattern
|
|
517
|
+
confidence: Confidence score (0.0-1.0)
|
|
518
|
+
|
|
519
|
+
Returns:
|
|
520
|
+
ExecutionPlan based on user choice
|
|
521
|
+
|
|
522
|
+
Raises:
|
|
523
|
+
ImportError: If AskUserQuestion tool not available
|
|
524
|
+
"""
|
|
525
|
+
try:
|
|
526
|
+
# Import here to avoid circular dependency and allow graceful degradation
|
|
527
|
+
from empathy_os.tools import AskUserQuestion
|
|
528
|
+
except ImportError as e:
|
|
529
|
+
logger.warning(f"AskUserQuestion not available: {e}")
|
|
530
|
+
logger.info("Falling back to automatic selection")
|
|
531
|
+
return self.create_execution_plan(requirements, agents, recommended_pattern)
|
|
532
|
+
|
|
533
|
+
# Format agent list for display
|
|
534
|
+
agent_summary = ", ".join([a.role for a in agents])
|
|
535
|
+
|
|
536
|
+
# Ask user for approach
|
|
537
|
+
response = AskUserQuestion(
|
|
538
|
+
questions=[
|
|
539
|
+
{
|
|
540
|
+
"header": "Approach",
|
|
541
|
+
"question": "How would you like to create the agent team?",
|
|
542
|
+
"multiSelect": False,
|
|
543
|
+
"options": [
|
|
544
|
+
{
|
|
545
|
+
"label": f"Use recommended: {recommended_pattern.value} (Recommended)",
|
|
546
|
+
"description": f"Auto-selected based on task analysis. "
|
|
547
|
+
f"{len(agents)} agents: {agent_summary}. "
|
|
548
|
+
f"Confidence: {confidence:.0%}",
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"label": "Customize team composition",
|
|
552
|
+
"description": "Choose specific agents and pattern manually",
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
"label": "Show all 10 patterns",
|
|
556
|
+
"description": "Learn about patterns and select one",
|
|
557
|
+
},
|
|
558
|
+
],
|
|
559
|
+
}
|
|
560
|
+
]
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
# Handle user response
|
|
564
|
+
user_choice = response.get("Approach", "")
|
|
565
|
+
|
|
566
|
+
if "Use recommended" in user_choice:
|
|
567
|
+
logger.info("User accepted recommended approach")
|
|
568
|
+
return self.create_execution_plan(requirements, agents, recommended_pattern)
|
|
569
|
+
|
|
570
|
+
elif "Customize" in user_choice:
|
|
571
|
+
logger.info("User chose to customize team")
|
|
572
|
+
return self._interactive_team_builder(requirements, agents, recommended_pattern)
|
|
573
|
+
|
|
574
|
+
else: # Show patterns
|
|
575
|
+
logger.info("User chose to explore patterns")
|
|
576
|
+
return self._pattern_chooser_wizard(requirements, agents)
|
|
577
|
+
|
|
578
|
+
def _interactive_team_builder(
|
|
579
|
+
self,
|
|
580
|
+
requirements: TaskRequirements,
|
|
581
|
+
suggested_agents: list[AgentTemplate],
|
|
582
|
+
suggested_pattern: CompositionPattern,
|
|
583
|
+
) -> ExecutionPlan:
|
|
584
|
+
"""Interactive team builder for manual customization.
|
|
585
|
+
|
|
586
|
+
Allows user to:
|
|
587
|
+
1. Review suggested agents and modify selection
|
|
588
|
+
2. Choose composition pattern
|
|
589
|
+
3. Configure quality gates
|
|
590
|
+
|
|
591
|
+
Args:
|
|
592
|
+
requirements: Task requirements
|
|
593
|
+
suggested_agents: Auto-selected agents
|
|
594
|
+
suggested_pattern: Auto-selected pattern
|
|
595
|
+
|
|
596
|
+
Returns:
|
|
597
|
+
ExecutionPlan with user-customized configuration
|
|
598
|
+
"""
|
|
599
|
+
try:
|
|
600
|
+
from empathy_os.tools import AskUserQuestion
|
|
601
|
+
except ImportError:
|
|
602
|
+
logger.warning("AskUserQuestion not available, using defaults")
|
|
603
|
+
return self.create_execution_plan(requirements, suggested_agents, suggested_pattern)
|
|
604
|
+
|
|
605
|
+
# Step 1: Agent selection
|
|
606
|
+
agent_response = AskUserQuestion(
|
|
607
|
+
questions=[
|
|
608
|
+
{
|
|
609
|
+
"header": "Agents",
|
|
610
|
+
"question": "Which agents should be included in the team?",
|
|
611
|
+
"multiSelect": True,
|
|
612
|
+
"options": [
|
|
613
|
+
{
|
|
614
|
+
"label": agent.role,
|
|
615
|
+
"description": f"{agent.id} - {', '.join(agent.capabilities[:3])}",
|
|
616
|
+
}
|
|
617
|
+
for agent in suggested_agents
|
|
618
|
+
],
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
# Filter agents based on user selection
|
|
624
|
+
selected_agent_roles = agent_response.get("Agents", [])
|
|
625
|
+
if not isinstance(selected_agent_roles, list):
|
|
626
|
+
selected_agent_roles = [selected_agent_roles]
|
|
627
|
+
|
|
628
|
+
selected_agents = [a for a in suggested_agents if a.role in selected_agent_roles]
|
|
629
|
+
if not selected_agents:
|
|
630
|
+
# User deselected all - use defaults
|
|
631
|
+
selected_agents = suggested_agents
|
|
632
|
+
|
|
633
|
+
# Step 2: Pattern selection
|
|
634
|
+
pattern_response = AskUserQuestion(
|
|
635
|
+
questions=[
|
|
636
|
+
{
|
|
637
|
+
"header": "Pattern",
|
|
638
|
+
"question": "Which composition pattern should be used?",
|
|
639
|
+
"multiSelect": False,
|
|
640
|
+
"options": [
|
|
641
|
+
{
|
|
642
|
+
"label": f"{suggested_pattern.value} (Recommended)",
|
|
643
|
+
"description": self._get_pattern_description(suggested_pattern),
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
"label": "sequential",
|
|
647
|
+
"description": "Execute agents one after another (A → B → C)",
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
"label": "parallel",
|
|
651
|
+
"description": "Execute agents simultaneously (A || B || C)",
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
"label": "tool_enhanced",
|
|
655
|
+
"description": "Single agent with comprehensive tool access",
|
|
656
|
+
},
|
|
657
|
+
],
|
|
658
|
+
}
|
|
659
|
+
]
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
# Parse pattern choice
|
|
663
|
+
pattern_choice = pattern_response.get("Pattern", suggested_pattern.value)
|
|
664
|
+
if "(Recommended)" in pattern_choice:
|
|
665
|
+
selected_pattern = suggested_pattern
|
|
666
|
+
else:
|
|
667
|
+
# Extract pattern name
|
|
668
|
+
pattern_name = pattern_choice.split()[0]
|
|
669
|
+
try:
|
|
670
|
+
selected_pattern = CompositionPattern(pattern_name)
|
|
671
|
+
except ValueError:
|
|
672
|
+
logger.warning(f"Invalid pattern: {pattern_name}, using suggested")
|
|
673
|
+
selected_pattern = suggested_pattern
|
|
674
|
+
|
|
675
|
+
# Create execution plan with user selections
|
|
676
|
+
return self.create_execution_plan(requirements, selected_agents, selected_pattern)
|
|
677
|
+
|
|
678
|
+
def _pattern_chooser_wizard(
|
|
679
|
+
self,
|
|
680
|
+
requirements: TaskRequirements,
|
|
681
|
+
suggested_agents: list[AgentTemplate],
|
|
682
|
+
) -> ExecutionPlan:
|
|
683
|
+
"""Interactive pattern chooser with educational previews.
|
|
684
|
+
|
|
685
|
+
Shows all 10 composition patterns with:
|
|
686
|
+
- Description and when to use
|
|
687
|
+
- Visual preview of agent flow
|
|
688
|
+
- Estimated cost and duration
|
|
689
|
+
- Examples of similar tasks
|
|
690
|
+
|
|
691
|
+
Args:
|
|
692
|
+
requirements: Task requirements
|
|
693
|
+
suggested_agents: Auto-selected agents
|
|
694
|
+
|
|
695
|
+
Returns:
|
|
696
|
+
ExecutionPlan with user-selected pattern
|
|
697
|
+
"""
|
|
698
|
+
try:
|
|
699
|
+
from empathy_os.tools import AskUserQuestion
|
|
700
|
+
except ImportError:
|
|
701
|
+
logger.warning("AskUserQuestion not available, using defaults")
|
|
702
|
+
suggested_pattern = self._choose_composition_pattern(requirements, suggested_agents)
|
|
703
|
+
return self.create_execution_plan(
|
|
704
|
+
requirements, suggested_agents, suggested_pattern
|
|
705
|
+
)
|
|
706
|
+
|
|
707
|
+
# Present all patterns with descriptions
|
|
708
|
+
pattern_response = AskUserQuestion(
|
|
709
|
+
questions=[
|
|
710
|
+
{
|
|
711
|
+
"header": "Pattern",
|
|
712
|
+
"question": "Choose a composition pattern (with preview):",
|
|
713
|
+
"multiSelect": False,
|
|
714
|
+
"options": [
|
|
715
|
+
{
|
|
716
|
+
"label": "sequential",
|
|
717
|
+
"description": "A → B → C | Step-by-step pipeline | "
|
|
718
|
+
"Example: Parse → Analyze → Report",
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
"label": "parallel",
|
|
722
|
+
"description": "A || B || C | Independent tasks | "
|
|
723
|
+
"Example: Security + Quality + Performance audits",
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
"label": "debate",
|
|
727
|
+
"description": "A ⇄ B ⇄ C → Synthesis | Multiple perspectives | "
|
|
728
|
+
"Example: 3 reviewers discuss approach",
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
"label": "teaching",
|
|
732
|
+
"description": "Junior → Expert validation | Draft + review | "
|
|
733
|
+
"Example: Cheap model drafts, expert validates",
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
"label": "refinement",
|
|
737
|
+
"description": "Draft → Review → Polish | Iterative improvement | "
|
|
738
|
+
"Example: Code → Review → Refine",
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
"label": "adaptive",
|
|
742
|
+
"description": "Classifier → Specialist | Dynamic routing | "
|
|
743
|
+
"Example: Analyze task type → Route to expert",
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
"label": "tool_enhanced (NEW)",
|
|
747
|
+
"description": "Single agent + tools | Most efficient | "
|
|
748
|
+
"Example: File reader with analysis tools",
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
"label": "prompt_cached_sequential (NEW)",
|
|
752
|
+
"description": "Shared large context | Cost-optimized | "
|
|
753
|
+
"Example: 3 agents using same codebase docs",
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
"label": "delegation_chain (NEW)",
|
|
757
|
+
"description": "Coordinator → Specialists | Hierarchical | "
|
|
758
|
+
"Example: Task planner delegates to architects",
|
|
759
|
+
},
|
|
760
|
+
],
|
|
761
|
+
}
|
|
762
|
+
]
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
# Parse pattern choice
|
|
766
|
+
pattern_choice = pattern_response.get("Pattern", "sequential")
|
|
767
|
+
pattern_name = pattern_choice.split()[0] # Extract name before any annotations
|
|
768
|
+
|
|
769
|
+
try:
|
|
770
|
+
selected_pattern = CompositionPattern(pattern_name)
|
|
771
|
+
except ValueError:
|
|
772
|
+
logger.warning(f"Invalid pattern: {pattern_name}, using sequential")
|
|
773
|
+
selected_pattern = CompositionPattern.SEQUENTIAL
|
|
774
|
+
|
|
775
|
+
logger.info(f"User selected pattern: {selected_pattern.value}")
|
|
776
|
+
|
|
777
|
+
# Create execution plan with user-selected pattern
|
|
778
|
+
return self.create_execution_plan(requirements, suggested_agents, selected_pattern)
|
|
779
|
+
|
|
780
|
+
def _get_pattern_description(self, pattern: CompositionPattern) -> str:
|
|
781
|
+
"""Get human-readable description of a pattern.
|
|
782
|
+
|
|
783
|
+
Args:
|
|
784
|
+
pattern: Composition pattern
|
|
785
|
+
|
|
786
|
+
Returns:
|
|
787
|
+
Description string
|
|
788
|
+
"""
|
|
789
|
+
descriptions = {
|
|
790
|
+
CompositionPattern.SEQUENTIAL: "Execute agents one after another (A → B → C)",
|
|
791
|
+
CompositionPattern.PARALLEL: "Execute agents simultaneously (A || B || C)",
|
|
792
|
+
CompositionPattern.DEBATE: "Multiple agents discuss and synthesize (A ⇄ B → Result)",
|
|
793
|
+
CompositionPattern.TEACHING: "Junior agent with expert validation (Draft → Review)",
|
|
794
|
+
CompositionPattern.REFINEMENT: "Iterative improvement (Draft → Review → Polish)",
|
|
795
|
+
CompositionPattern.ADAPTIVE: "Dynamic routing based on classification",
|
|
796
|
+
CompositionPattern.CONDITIONAL: "If-then-else branching logic",
|
|
797
|
+
CompositionPattern.TOOL_ENHANCED: "Single agent with comprehensive tool access",
|
|
798
|
+
CompositionPattern.PROMPT_CACHED_SEQUENTIAL: "Sequential with shared cached context",
|
|
799
|
+
CompositionPattern.DELEGATION_CHAIN: "Hierarchical coordinator → specialists",
|
|
800
|
+
}
|
|
801
|
+
return descriptions.get(pattern, "Custom composition pattern")
|
|
802
|
+
|
|
356
803
|
def _analyze_task(self, task: str, context: dict[str, Any]) -> TaskRequirements:
|
|
357
804
|
"""Analyze task to extract requirements.
|
|
358
805
|
|
|
@@ -578,6 +1025,27 @@ class MetaOrchestrator:
|
|
|
578
1025
|
CompositionPattern to use
|
|
579
1026
|
"""
|
|
580
1027
|
num_agents = len(agents)
|
|
1028
|
+
context = requirements.context
|
|
1029
|
+
|
|
1030
|
+
# Anthropic Pattern 8: Tool-Enhanced (single agent + tools preferred)
|
|
1031
|
+
if num_agents == 1 and context.get("tools"):
|
|
1032
|
+
return CompositionPattern.TOOL_ENHANCED
|
|
1033
|
+
|
|
1034
|
+
# Anthropic Pattern 10: Delegation Chain (hierarchical coordination)
|
|
1035
|
+
# Use when: Complex task + coordinator pattern + 2+ specialists
|
|
1036
|
+
has_coordinator = any("coordinator" in agent.role.lower() for agent in agents)
|
|
1037
|
+
if (
|
|
1038
|
+
requirements.complexity == TaskComplexity.COMPLEX
|
|
1039
|
+
and has_coordinator
|
|
1040
|
+
and num_agents >= 2
|
|
1041
|
+
):
|
|
1042
|
+
return CompositionPattern.DELEGATION_CHAIN
|
|
1043
|
+
|
|
1044
|
+
# Anthropic Pattern 9: Prompt-Cached Sequential (large shared context)
|
|
1045
|
+
# Use when: 3+ agents need same large context (>2000 tokens)
|
|
1046
|
+
large_context = context.get("cached_context") or context.get("shared_knowledge")
|
|
1047
|
+
if num_agents >= 3 and large_context and len(str(large_context)) > 2000:
|
|
1048
|
+
return CompositionPattern.PROMPT_CACHED_SEQUENTIAL
|
|
581
1049
|
|
|
582
1050
|
# Parallelizable tasks: use parallel strategy (check before single agent)
|
|
583
1051
|
if requirements.parallelizable:
|
|
@@ -677,5 +1145,24 @@ class MetaOrchestrator:
|
|
|
677
1145
|
if strategy == CompositionPattern.ADAPTIVE:
|
|
678
1146
|
return int(max_timeout * 1.2)
|
|
679
1147
|
|
|
1148
|
+
# Anthropic Pattern 8: Tool-Enhanced (single agent with tools, efficient)
|
|
1149
|
+
if strategy == CompositionPattern.TOOL_ENHANCED:
|
|
1150
|
+
return max_timeout # Similar to sequential for single agent
|
|
1151
|
+
|
|
1152
|
+
# Anthropic Pattern 9: Prompt-Cached Sequential (faster with cache hits)
|
|
1153
|
+
if strategy == CompositionPattern.PROMPT_CACHED_SEQUENTIAL:
|
|
1154
|
+
# Sequential but 20% faster due to cached context reducing token processing
|
|
1155
|
+
total = sum(agent.resource_requirements.timeout_seconds for agent in agents)
|
|
1156
|
+
return int(total * 0.8)
|
|
1157
|
+
|
|
1158
|
+
# Anthropic Pattern 10: Delegation Chain (coordinator + specialists in sequence)
|
|
1159
|
+
if strategy == CompositionPattern.DELEGATION_CHAIN:
|
|
1160
|
+
# Coordinator analyzes, then specialists execute (sequential-like)
|
|
1161
|
+
return sum(agent.resource_requirements.timeout_seconds for agent in agents)
|
|
1162
|
+
|
|
1163
|
+
# Conditional: branch evaluation + selected path
|
|
1164
|
+
if strategy == CompositionPattern.CONDITIONAL:
|
|
1165
|
+
return int(max_timeout * 1.1)
|
|
1166
|
+
|
|
680
1167
|
# Default: max timeout
|
|
681
1168
|
return max_timeout
|
|
@@ -192,6 +192,42 @@ WORKFLOW_REGISTRY: dict[str, WorkflowInfo] = {
|
|
|
192
192
|
primary_domain="documentation",
|
|
193
193
|
auto_chain=False,
|
|
194
194
|
),
|
|
195
|
+
"seo-optimization": WorkflowInfo(
|
|
196
|
+
name="seo-optimization",
|
|
197
|
+
description="Audit and optimize SEO for documentation sites (meta tags, content structure, technical SEO, links)",
|
|
198
|
+
keywords=[
|
|
199
|
+
"seo",
|
|
200
|
+
"search",
|
|
201
|
+
"optimization",
|
|
202
|
+
"meta",
|
|
203
|
+
"meta tag",
|
|
204
|
+
"meta description",
|
|
205
|
+
"title tag",
|
|
206
|
+
"opengraph",
|
|
207
|
+
"og:title",
|
|
208
|
+
"og:description",
|
|
209
|
+
"twitter card",
|
|
210
|
+
"sitemap",
|
|
211
|
+
"robots.txt",
|
|
212
|
+
"keywords",
|
|
213
|
+
"search engine",
|
|
214
|
+
"google",
|
|
215
|
+
"ranking",
|
|
216
|
+
"visibility",
|
|
217
|
+
"documentation seo",
|
|
218
|
+
"mkdocs seo",
|
|
219
|
+
"content optimization",
|
|
220
|
+
"headings",
|
|
221
|
+
"h1",
|
|
222
|
+
"canonical",
|
|
223
|
+
"broken links",
|
|
224
|
+
"internal links",
|
|
225
|
+
"schema markup",
|
|
226
|
+
],
|
|
227
|
+
primary_domain="documentation",
|
|
228
|
+
handles_file_types=[".md", ".html"],
|
|
229
|
+
auto_chain=False, # SEO fixes require approval
|
|
230
|
+
),
|
|
195
231
|
"dependency-check": WorkflowInfo(
|
|
196
232
|
name="dependency-check",
|
|
197
233
|
description="Audit dependencies for vulnerabilities, updates, and license issues",
|