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.
Files changed (73) hide show
  1. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/METADATA +52 -3
  2. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/RECORD +71 -30
  3. empathy_os/__init__.py +1 -1
  4. empathy_os/cli_router.py +21 -0
  5. empathy_os/core_modules/__init__.py +15 -0
  6. empathy_os/mcp/__init__.py +10 -0
  7. empathy_os/mcp/server.py +506 -0
  8. empathy_os/memory/control_panel.py +1 -131
  9. empathy_os/memory/control_panel_support.py +145 -0
  10. empathy_os/memory/encryption.py +159 -0
  11. empathy_os/memory/long_term.py +41 -626
  12. empathy_os/memory/long_term_types.py +99 -0
  13. empathy_os/memory/mixins/__init__.py +25 -0
  14. empathy_os/memory/mixins/backend_init_mixin.py +244 -0
  15. empathy_os/memory/mixins/capabilities_mixin.py +199 -0
  16. empathy_os/memory/mixins/handoff_mixin.py +208 -0
  17. empathy_os/memory/mixins/lifecycle_mixin.py +49 -0
  18. empathy_os/memory/mixins/long_term_mixin.py +352 -0
  19. empathy_os/memory/mixins/promotion_mixin.py +109 -0
  20. empathy_os/memory/mixins/short_term_mixin.py +182 -0
  21. empathy_os/memory/short_term.py +7 -0
  22. empathy_os/memory/simple_storage.py +302 -0
  23. empathy_os/memory/storage_backend.py +167 -0
  24. empathy_os/memory/unified.py +21 -1120
  25. empathy_os/meta_workflows/cli_commands/__init__.py +56 -0
  26. empathy_os/meta_workflows/cli_commands/agent_commands.py +321 -0
  27. empathy_os/meta_workflows/cli_commands/analytics_commands.py +442 -0
  28. empathy_os/meta_workflows/cli_commands/config_commands.py +232 -0
  29. empathy_os/meta_workflows/cli_commands/memory_commands.py +182 -0
  30. empathy_os/meta_workflows/cli_commands/template_commands.py +354 -0
  31. empathy_os/meta_workflows/cli_commands/workflow_commands.py +382 -0
  32. empathy_os/meta_workflows/cli_meta_workflows.py +52 -1802
  33. empathy_os/meta_workflows/intent_detector.py +71 -0
  34. empathy_os/models/telemetry/__init__.py +71 -0
  35. empathy_os/models/telemetry/analytics.py +594 -0
  36. empathy_os/models/telemetry/backend.py +196 -0
  37. empathy_os/models/telemetry/data_models.py +431 -0
  38. empathy_os/models/telemetry/storage.py +489 -0
  39. empathy_os/orchestration/__init__.py +35 -0
  40. empathy_os/orchestration/execution_strategies.py +481 -0
  41. empathy_os/orchestration/meta_orchestrator.py +488 -1
  42. empathy_os/routing/workflow_registry.py +36 -0
  43. empathy_os/telemetry/cli.py +19 -724
  44. empathy_os/telemetry/commands/__init__.py +14 -0
  45. empathy_os/telemetry/commands/dashboard_commands.py +696 -0
  46. empathy_os/tools.py +183 -0
  47. empathy_os/workflows/__init__.py +5 -0
  48. empathy_os/workflows/autonomous_test_gen.py +860 -161
  49. empathy_os/workflows/base.py +6 -2
  50. empathy_os/workflows/code_review.py +4 -1
  51. empathy_os/workflows/document_gen/__init__.py +25 -0
  52. empathy_os/workflows/document_gen/config.py +30 -0
  53. empathy_os/workflows/document_gen/report_formatter.py +162 -0
  54. empathy_os/workflows/document_gen/workflow.py +1426 -0
  55. empathy_os/workflows/document_gen.py +22 -1598
  56. empathy_os/workflows/security_audit.py +2 -2
  57. empathy_os/workflows/security_audit_phase3.py +7 -4
  58. empathy_os/workflows/seo_optimization.py +633 -0
  59. empathy_os/workflows/test_gen/__init__.py +52 -0
  60. empathy_os/workflows/test_gen/ast_analyzer.py +249 -0
  61. empathy_os/workflows/test_gen/config.py +88 -0
  62. empathy_os/workflows/test_gen/data_models.py +38 -0
  63. empathy_os/workflows/test_gen/report_formatter.py +289 -0
  64. empathy_os/workflows/test_gen/test_templates.py +381 -0
  65. empathy_os/workflows/test_gen/workflow.py +655 -0
  66. empathy_os/workflows/test_gen.py +42 -1905
  67. empathy_os/memory/types 2.py +0 -441
  68. empathy_os/models/telemetry.py +0 -1660
  69. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/WHEEL +0 -0
  70. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/entry_points.txt +0 -0
  71. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE +0 -0
  72. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -0
  73. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/top_level.txt +0 -0
empathy_os/tools.py ADDED
@@ -0,0 +1,183 @@
1
+ """Interactive user prompting tools.
2
+
3
+ Provides tools for asking users questions and getting structured responses.
4
+ This module implements the AskUserQuestion functionality used by the
5
+ meta-orchestrator for interactive agent team creation.
6
+
7
+ Integration with Claude Code:
8
+ When running Python code that calls this function, Claude Code will
9
+ detect the call and use its AskUserQuestion tool to prompt the user
10
+ in the IDE. This is implemented via a request/response IPC mechanism.
11
+
12
+ Created: 2026-01-29
13
+ """
14
+ import json
15
+ import logging
16
+ import os
17
+ import tempfile
18
+ from collections.abc import Callable
19
+ from pathlib import Path
20
+ from typing import Any
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # Global callback for custom AskUserQuestion implementations
25
+ _custom_ask_function: Callable | None = None
26
+
27
+
28
+ def set_ask_user_question_handler(handler: Callable) -> None:
29
+ """Set a custom handler for AskUserQuestion.
30
+
31
+ This allows integration with different UI systems (CLI, web, IDE).
32
+
33
+ Args:
34
+ handler: Callable that takes questions list and returns response dict
35
+
36
+ Example:
37
+ >>> def my_handler(questions):
38
+ ... # Custom UI logic
39
+ ... return {"Pattern": "sequential"}
40
+ >>> set_ask_user_question_handler(my_handler)
41
+ """
42
+ global _custom_ask_function
43
+ _custom_ask_function = handler
44
+ logger.info("Custom AskUserQuestion handler registered")
45
+
46
+
47
+ def AskUserQuestion(questions: list[dict[str, Any]]) -> dict[str, Any]:
48
+ """Ask user questions and get structured responses.
49
+
50
+ This function supports multiple integration modes:
51
+ 1. Custom handler (via set_ask_user_question_handler)
52
+ 2. Claude Code IPC (when running in Claude Code environment)
53
+ 3. Fallback to NotImplementedError (prompts caller to use automatic mode)
54
+
55
+ Args:
56
+ questions: List of question dictionaries, each with:
57
+ - header: Short label for the question (str, max 12 chars)
58
+ - question: Full question text (str)
59
+ - multiSelect: Allow multiple selections (bool)
60
+ - options: List of option dicts with label and description
61
+
62
+ Returns:
63
+ Dictionary mapping question headers to selected answers
64
+
65
+ Raises:
66
+ NotImplementedError: If no handler available and not in Claude Code
67
+ RuntimeError: If user cancels or interaction fails
68
+
69
+ Example:
70
+ >>> response = AskUserQuestion(
71
+ ... questions=[{
72
+ ... "header": "Pattern",
73
+ ... "question": "Which pattern to use?",
74
+ ... "multiSelect": False,
75
+ ... "options": [
76
+ ... {"label": "sequential", "description": "One after another"},
77
+ ... {"label": "parallel", "description": "All at once"}
78
+ ... ]
79
+ ... }]
80
+ ... )
81
+ >>> response
82
+ {"Pattern": "sequential"}
83
+ """
84
+ # Mode 1: Custom handler
85
+ if _custom_ask_function is not None:
86
+ logger.info("Using custom AskUserQuestion handler")
87
+ return _custom_ask_function(questions)
88
+
89
+ # Mode 2: Claude Code IPC
90
+ # When running inside Claude Code, we can use a file-based IPC mechanism
91
+ if _is_running_in_claude_code():
92
+ logger.info("Using Claude Code IPC for AskUserQuestion")
93
+ return _ask_via_claude_code_ipc(questions)
94
+
95
+ # Mode 3: Fallback - raise error with helpful message
96
+ logger.warning("No AskUserQuestion handler available")
97
+ raise NotImplementedError(
98
+ "AskUserQuestion requires either:\n"
99
+ "1. Custom handler via set_ask_user_question_handler()\n"
100
+ "2. Running in Claude Code environment\n"
101
+ "3. Using interactive=False for automatic mode\n\n"
102
+ "Use: orchestrator.analyze_and_compose(task, interactive=False)"
103
+ )
104
+
105
+
106
+ def _is_running_in_claude_code() -> bool:
107
+ """Check if code is running inside Claude Code environment.
108
+
109
+ Returns:
110
+ True if running in Claude Code, False otherwise
111
+ """
112
+ # Check for Claude Code environment markers
113
+ return (
114
+ os.getenv("CLAUDE_CODE_SESSION") is not None
115
+ or os.getenv("CLAUDE_AGENT_MODE") is not None
116
+ or Path("/tmp/.claude-code").exists()
117
+ )
118
+
119
+
120
+ def _ask_via_claude_code_ipc(questions: list[dict[str, Any]]) -> dict[str, Any]:
121
+ """Ask user questions via Claude Code IPC mechanism.
122
+
123
+ This creates a request file that Claude Code monitors, then waits for
124
+ the response file to be created with the user's answers.
125
+
126
+ Args:
127
+ questions: List of question dictionaries
128
+
129
+ Returns:
130
+ User's responses as a dictionary
131
+
132
+ Raises:
133
+ RuntimeError: If communication fails or times out
134
+ """
135
+ import time
136
+ import uuid
137
+
138
+ request_id = str(uuid.uuid4())
139
+ ipc_dir = Path(tempfile.gettempdir()) / ".claude-code-ipc"
140
+ ipc_dir.mkdir(exist_ok=True)
141
+
142
+ request_file = ipc_dir / f"ask-request-{request_id}.json"
143
+ response_file = ipc_dir / f"ask-response-{request_id}.json"
144
+
145
+ try:
146
+ # Write request
147
+ request_data = {
148
+ "request_id": request_id,
149
+ "questions": questions,
150
+ "timestamp": time.time(),
151
+ }
152
+
153
+ request_file.write_text(json.dumps(request_data, indent=2))
154
+ logger.info(f"Wrote IPC request: {request_file}")
155
+
156
+ # Wait for response (max 60 seconds)
157
+ timeout = 60
158
+ start_time = time.time()
159
+
160
+ while time.time() - start_time < timeout:
161
+ if response_file.exists():
162
+ # Read response
163
+ response_data = json.loads(response_file.read_text())
164
+ logger.info(f"Received IPC response: {response_data}")
165
+
166
+ # Cleanup
167
+ request_file.unlink(missing_ok=True)
168
+ response_file.unlink(missing_ok=True)
169
+
170
+ return response_data.get("answers", {})
171
+
172
+ time.sleep(0.1) # Poll every 100ms
173
+
174
+ raise RuntimeError(
175
+ f"Timeout waiting for user response (waited {timeout}s). "
176
+ "User may have cancelled or Claude Code IPC is not active."
177
+ )
178
+
179
+ except Exception as e:
180
+ # Cleanup on error
181
+ request_file.unlink(missing_ok=True)
182
+ response_file.unlink(missing_ok=True)
183
+ raise RuntimeError(f"Claude Code IPC failed: {e}") from e
@@ -62,6 +62,7 @@ if TYPE_CHECKING:
62
62
  from .research_synthesis import ResearchSynthesisWorkflow
63
63
  from .secure_release import SecureReleasePipeline, SecureReleaseResult
64
64
  from .security_audit import SecurityAuditWorkflow
65
+ from .seo_optimization import SEOOptimizationWorkflow
65
66
  from .step_config import WorkflowStepConfig
66
67
  from .test5 import Test5Workflow
67
68
  from .test_coverage_boost_crew import TestCoverageBoostCrew, TestCoverageBoostCrewResult
@@ -134,6 +135,7 @@ _LAZY_WORKFLOW_IMPORTS: dict[str, tuple[str, str]] = {
134
135
  "SecureReleasePipeline": (".secure_release", "SecureReleasePipeline"),
135
136
  "SecureReleaseResult": (".secure_release", "SecureReleaseResult"),
136
137
  "SecurityAuditWorkflow": (".security_audit", "SecurityAuditWorkflow"),
138
+ "SEOOptimizationWorkflow": (".seo_optimization", "SEOOptimizationWorkflow"),
137
139
  "Test5Workflow": (".test5", "Test5Workflow"),
138
140
  "TestCoverageBoostCrew": (".test_coverage_boost_crew", "TestCoverageBoostCrew"),
139
141
  "TestCoverageBoostCrewResult": (".test_coverage_boost_crew", "TestCoverageBoostCrewResult"),
@@ -210,7 +212,9 @@ def _load_cli_commands() -> None:
210
212
  _DEFAULT_WORKFLOW_NAMES: dict[str, str] = {
211
213
  # Core workflows
212
214
  "code-review": "CodeReviewWorkflow",
215
+ # Documentation workflows
213
216
  "doc-gen": "DocumentGenerationWorkflow",
217
+ "seo-optimization": "SEOOptimizationWorkflow",
214
218
  # Analysis workflows
215
219
  "bug-predict": "BugPredictionWorkflow",
216
220
  "security-audit": "SecurityAuditWorkflow",
@@ -489,6 +493,7 @@ __all__ = [
489
493
  "SecureReleasePipeline",
490
494
  "SecureReleaseResult",
491
495
  "SecurityAuditWorkflow",
496
+ "SEOOptimizationWorkflow",
492
497
  "TestGenerationWorkflow",
493
498
  "BehavioralTestGenerationWorkflow",
494
499
  "ParallelTestGenerationWorkflow",