empathy-framework 5.1.1__py3-none-any.whl → 5.3.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 (106) hide show
  1. {empathy_framework-5.1.1.dist-info → empathy_framework-5.3.0.dist-info}/METADATA +79 -6
  2. {empathy_framework-5.1.1.dist-info → empathy_framework-5.3.0.dist-info}/RECORD +83 -64
  3. empathy_os/__init__.py +1 -1
  4. empathy_os/cache/hybrid.py +5 -1
  5. empathy_os/cli/commands/batch.py +8 -0
  6. empathy_os/cli/commands/profiling.py +4 -0
  7. empathy_os/cli/commands/workflow.py +8 -4
  8. empathy_os/cli_router.py +9 -0
  9. empathy_os/config.py +15 -2
  10. empathy_os/core_modules/__init__.py +15 -0
  11. empathy_os/dashboard/simple_server.py +62 -30
  12. empathy_os/mcp/__init__.py +10 -0
  13. empathy_os/mcp/server.py +506 -0
  14. empathy_os/memory/control_panel.py +1 -131
  15. empathy_os/memory/control_panel_support.py +145 -0
  16. empathy_os/memory/encryption.py +159 -0
  17. empathy_os/memory/long_term.py +46 -631
  18. empathy_os/memory/long_term_types.py +99 -0
  19. empathy_os/memory/mixins/__init__.py +25 -0
  20. empathy_os/memory/mixins/backend_init_mixin.py +249 -0
  21. empathy_os/memory/mixins/capabilities_mixin.py +208 -0
  22. empathy_os/memory/mixins/handoff_mixin.py +208 -0
  23. empathy_os/memory/mixins/lifecycle_mixin.py +49 -0
  24. empathy_os/memory/mixins/long_term_mixin.py +352 -0
  25. empathy_os/memory/mixins/promotion_mixin.py +109 -0
  26. empathy_os/memory/mixins/short_term_mixin.py +182 -0
  27. empathy_os/memory/short_term.py +61 -12
  28. empathy_os/memory/simple_storage.py +302 -0
  29. empathy_os/memory/storage_backend.py +167 -0
  30. empathy_os/memory/types.py +8 -3
  31. empathy_os/memory/unified.py +21 -1120
  32. empathy_os/meta_workflows/cli_commands/__init__.py +56 -0
  33. empathy_os/meta_workflows/cli_commands/agent_commands.py +321 -0
  34. empathy_os/meta_workflows/cli_commands/analytics_commands.py +442 -0
  35. empathy_os/meta_workflows/cli_commands/config_commands.py +232 -0
  36. empathy_os/meta_workflows/cli_commands/memory_commands.py +182 -0
  37. empathy_os/meta_workflows/cli_commands/template_commands.py +354 -0
  38. empathy_os/meta_workflows/cli_commands/workflow_commands.py +382 -0
  39. empathy_os/meta_workflows/cli_meta_workflows.py +52 -1802
  40. empathy_os/models/telemetry/__init__.py +71 -0
  41. empathy_os/models/telemetry/analytics.py +594 -0
  42. empathy_os/models/telemetry/backend.py +196 -0
  43. empathy_os/models/telemetry/data_models.py +431 -0
  44. empathy_os/models/telemetry/storage.py +489 -0
  45. empathy_os/orchestration/__init__.py +35 -0
  46. empathy_os/orchestration/execution_strategies.py +481 -0
  47. empathy_os/orchestration/meta_orchestrator.py +488 -1
  48. empathy_os/routing/workflow_registry.py +36 -0
  49. empathy_os/telemetry/agent_coordination.py +2 -3
  50. empathy_os/telemetry/agent_tracking.py +26 -7
  51. empathy_os/telemetry/approval_gates.py +18 -24
  52. empathy_os/telemetry/cli.py +19 -724
  53. empathy_os/telemetry/commands/__init__.py +14 -0
  54. empathy_os/telemetry/commands/dashboard_commands.py +696 -0
  55. empathy_os/telemetry/event_streaming.py +7 -3
  56. empathy_os/telemetry/feedback_loop.py +28 -15
  57. empathy_os/tools.py +183 -0
  58. empathy_os/workflows/__init__.py +5 -0
  59. empathy_os/workflows/autonomous_test_gen.py +860 -161
  60. empathy_os/workflows/base.py +6 -2
  61. empathy_os/workflows/code_review.py +4 -1
  62. empathy_os/workflows/document_gen/__init__.py +25 -0
  63. empathy_os/workflows/document_gen/config.py +30 -0
  64. empathy_os/workflows/document_gen/report_formatter.py +162 -0
  65. empathy_os/workflows/{document_gen.py → document_gen/workflow.py} +5 -184
  66. empathy_os/workflows/output.py +4 -1
  67. empathy_os/workflows/progress.py +8 -2
  68. empathy_os/workflows/security_audit.py +2 -2
  69. empathy_os/workflows/security_audit_phase3.py +7 -4
  70. empathy_os/workflows/seo_optimization.py +633 -0
  71. empathy_os/workflows/test_gen/__init__.py +52 -0
  72. empathy_os/workflows/test_gen/ast_analyzer.py +249 -0
  73. empathy_os/workflows/test_gen/config.py +88 -0
  74. empathy_os/workflows/test_gen/data_models.py +38 -0
  75. empathy_os/workflows/test_gen/report_formatter.py +289 -0
  76. empathy_os/workflows/test_gen/test_templates.py +381 -0
  77. empathy_os/workflows/test_gen/workflow.py +655 -0
  78. empathy_os/workflows/test_gen.py +42 -1905
  79. empathy_os/cli/parsers/cache 2.py +0 -65
  80. empathy_os/cli_router 2.py +0 -416
  81. empathy_os/dashboard/app 2.py +0 -512
  82. empathy_os/dashboard/simple_server 2.py +0 -403
  83. empathy_os/dashboard/standalone_server 2.py +0 -536
  84. empathy_os/memory/types 2.py +0 -441
  85. empathy_os/models/adaptive_routing 2.py +0 -437
  86. empathy_os/models/telemetry.py +0 -1660
  87. empathy_os/project_index/scanner_parallel 2.py +0 -291
  88. empathy_os/telemetry/agent_coordination 2.py +0 -478
  89. empathy_os/telemetry/agent_tracking 2.py +0 -350
  90. empathy_os/telemetry/approval_gates 2.py +0 -563
  91. empathy_os/telemetry/event_streaming 2.py +0 -405
  92. empathy_os/telemetry/feedback_loop 2.py +0 -557
  93. empathy_os/vscode_bridge 2.py +0 -173
  94. empathy_os/workflows/progressive/__init__ 2.py +0 -92
  95. empathy_os/workflows/progressive/cli 2.py +0 -242
  96. empathy_os/workflows/progressive/core 2.py +0 -488
  97. empathy_os/workflows/progressive/orchestrator 2.py +0 -701
  98. empathy_os/workflows/progressive/reports 2.py +0 -528
  99. empathy_os/workflows/progressive/telemetry 2.py +0 -280
  100. empathy_os/workflows/progressive/test_gen 2.py +0 -514
  101. empathy_os/workflows/progressive/workflow 2.py +0 -628
  102. {empathy_framework-5.1.1.dist-info → empathy_framework-5.3.0.dist-info}/WHEEL +0 -0
  103. {empathy_framework-5.1.1.dist-info → empathy_framework-5.3.0.dist-info}/entry_points.txt +0 -0
  104. {empathy_framework-5.1.1.dist-info → empathy_framework-5.3.0.dist-info}/licenses/LICENSE +0 -0
  105. {empathy_framework-5.1.1.dist-info → empathy_framework-5.3.0.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -0
  106. {empathy_framework-5.1.1.dist-info → empathy_framework-5.3.0.dist-info}/top_level.txt +0 -0
@@ -53,6 +53,7 @@ class AgentHeartbeat:
53
53
  current_task: str
54
54
  last_beat: datetime
55
55
  metadata: dict[str, Any] = field(default_factory=dict)
56
+ display_name: str | None = None # Optional human-readable name for dashboard
56
57
 
57
58
  def to_dict(self) -> dict[str, Any]:
58
59
  """Convert to dictionary for serialization."""
@@ -63,6 +64,7 @@ class AgentHeartbeat:
63
64
  "current_task": self.current_task,
64
65
  "last_beat": self.last_beat.isoformat() if isinstance(self.last_beat, datetime) else self.last_beat,
65
66
  "metadata": self.metadata,
67
+ "display_name": self.display_name,
66
68
  }
67
69
 
68
70
  @classmethod
@@ -82,6 +84,7 @@ class AgentHeartbeat:
82
84
  current_task=data["current_task"],
83
85
  last_beat=last_beat,
84
86
  metadata=data.get("metadata", {}),
87
+ display_name=data.get("display_name"),
85
88
  )
86
89
 
87
90
 
@@ -110,6 +113,7 @@ class HeartbeatCoordinator:
110
113
  """
111
114
  self.memory = memory
112
115
  self.agent_id: str | None = None
116
+ self.display_name: str | None = None
113
117
  self._enable_streaming = enable_streaming
114
118
  self._event_streamer = None
115
119
 
@@ -142,20 +146,28 @@ class HeartbeatCoordinator:
142
146
 
143
147
  return self._event_streamer
144
148
 
145
- def start_heartbeat(self, agent_id: str, metadata: dict[str, Any] | None = None) -> None:
149
+ def start_heartbeat(
150
+ self, agent_id: str, metadata: dict[str, Any] | None = None, display_name: str | None = None
151
+ ) -> None:
146
152
  """Start heartbeat for an agent.
147
153
 
148
154
  Args:
149
155
  agent_id: Unique agent identifier
150
156
  metadata: Initial metadata (workflow, run_id, etc.)
157
+ display_name: Optional human-readable name for dashboard display
151
158
  """
152
159
  if not self.memory:
153
160
  logger.debug("Heartbeat tracking disabled (no memory backend)")
154
161
  return
155
162
 
156
163
  self.agent_id = agent_id
164
+ self.display_name = display_name
157
165
  self._publish_heartbeat(
158
- status="starting", progress=0.0, current_task="initializing", metadata=metadata or {}
166
+ status="starting",
167
+ progress=0.0,
168
+ current_task="initializing",
169
+ metadata=metadata or {},
170
+ display_name=display_name,
159
171
  )
160
172
 
161
173
  def beat(self, status: str = "running", progress: float = 0.0, current_task: str = "") -> None:
@@ -169,7 +181,13 @@ class HeartbeatCoordinator:
169
181
  if not self.agent_id or not self.memory:
170
182
  return
171
183
 
172
- self._publish_heartbeat(status=status, progress=progress, current_task=current_task, metadata={})
184
+ self._publish_heartbeat(
185
+ status=status,
186
+ progress=progress,
187
+ current_task=current_task,
188
+ metadata={},
189
+ display_name=self.display_name,
190
+ )
173
191
 
174
192
  def stop_heartbeat(self, final_status: str = "completed") -> None:
175
193
  """Stop heartbeat (agent finished).
@@ -192,7 +210,7 @@ class HeartbeatCoordinator:
192
210
  self.agent_id = None
193
211
 
194
212
  def _publish_heartbeat(
195
- self, status: str, progress: float, current_task: str, metadata: dict[str, Any]
213
+ self, status: str, progress: float, current_task: str, metadata: dict[str, Any], display_name: str | None = None
196
214
  ) -> None:
197
215
  """Publish heartbeat to Redis with TTL and optionally to event stream."""
198
216
  if not self.memory or not self.agent_id:
@@ -205,10 +223,11 @@ class HeartbeatCoordinator:
205
223
  current_task=current_task,
206
224
  last_beat=datetime.utcnow(),
207
225
  metadata=metadata,
226
+ display_name=display_name,
208
227
  )
209
228
 
210
229
  # Store in Redis with TTL (Pattern 1)
211
- key = f"heartbeat:{self.agent_id}"
230
+ key = f"empathy:heartbeat:{self.agent_id}"
212
231
  try:
213
232
  # Use direct Redis access for heartbeats (need custom 30s TTL)
214
233
  if hasattr(self.memory, "_client") and self.memory._client:
@@ -243,9 +262,9 @@ class HeartbeatCoordinator:
243
262
  return []
244
263
 
245
264
  try:
246
- # Scan for heartbeat:* keys
265
+ # Scan for empathy:heartbeat:* keys
247
266
  if hasattr(self.memory, "_client") and self.memory._client:
248
- keys = self.memory._client.keys("heartbeat:*")
267
+ keys = self.memory._client.keys("empathy:heartbeat:*")
249
268
  else:
250
269
  logger.warning("Cannot scan for heartbeats: no Redis access")
251
270
  return []
@@ -458,19 +458,16 @@ class ApprovalGate:
458
458
  if isinstance(key, bytes):
459
459
  key = key.decode("utf-8")
460
460
 
461
- # Retrieve request
462
- if hasattr(self.memory, "retrieve"):
463
- data = self.memory.retrieve(key, credentials=None)
464
- else:
465
- import json
461
+ # Retrieve request - use direct Redis access (approval keys are stored without prefix)
462
+ import json
466
463
 
467
- raw_data = self.memory._client.get(key)
468
- if raw_data:
469
- if isinstance(raw_data, bytes):
470
- raw_data = raw_data.decode("utf-8")
471
- data = json.loads(raw_data)
472
- else:
473
- data = None
464
+ raw_data = self.memory._client.get(key)
465
+ if raw_data:
466
+ if isinstance(raw_data, bytes):
467
+ raw_data = raw_data.decode("utf-8")
468
+ data = json.loads(raw_data)
469
+ else:
470
+ data = None
474
471
 
475
472
  if not data:
476
473
  continue
@@ -513,19 +510,16 @@ class ApprovalGate:
513
510
  if isinstance(key, bytes):
514
511
  key = key.decode("utf-8")
515
512
 
516
- # Retrieve request
517
- if hasattr(self.memory, "retrieve"):
518
- data = self.memory.retrieve(key, credentials=None)
519
- else:
520
- import json
513
+ # Retrieve request - use direct Redis access (approval keys are stored without prefix)
514
+ import json
521
515
 
522
- raw_data = self.memory._client.get(key)
523
- if raw_data:
524
- if isinstance(raw_data, bytes):
525
- raw_data = raw_data.decode("utf-8")
526
- data = json.loads(raw_data)
527
- else:
528
- data = None
516
+ raw_data = self.memory._client.get(key)
517
+ if raw_data:
518
+ if isinstance(raw_data, bytes):
519
+ raw_data = raw_data.decode("utf-8")
520
+ data = json.loads(raw_data)
521
+ else:
522
+ data = None
529
523
 
530
524
  if not data:
531
525
  continue