empathy-framework 3.5.6__py3-none-any.whl → 3.7.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.
- agents/compliance_anticipation_agent.py +113 -118
- agents/compliance_db.py +339 -0
- agents/epic_integration_wizard.py +37 -48
- agents/notifications.py +291 -0
- agents/trust_building_behaviors.py +66 -85
- coach_wizards/__init__.py +11 -12
- coach_wizards/accessibility_wizard.py +12 -12
- coach_wizards/api_wizard.py +12 -12
- coach_wizards/base_wizard.py +26 -20
- coach_wizards/cicd_wizard.py +15 -13
- coach_wizards/compliance_wizard.py +12 -12
- coach_wizards/database_wizard.py +12 -12
- coach_wizards/debugging_wizard.py +12 -12
- coach_wizards/documentation_wizard.py +12 -12
- coach_wizards/generate_wizards.py +1 -2
- coach_wizards/localization_wizard.py +21 -14
- coach_wizards/migration_wizard.py +12 -12
- coach_wizards/monitoring_wizard.py +12 -12
- coach_wizards/observability_wizard.py +12 -12
- coach_wizards/performance_wizard.py +12 -12
- coach_wizards/prompt_engineering_wizard.py +22 -25
- coach_wizards/refactoring_wizard.py +12 -12
- coach_wizards/scaling_wizard.py +12 -12
- coach_wizards/security_wizard.py +12 -12
- coach_wizards/testing_wizard.py +12 -12
- {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/METADATA +234 -30
- empathy_framework-3.7.0.dist-info/RECORD +105 -0
- empathy_healthcare_plugin/__init__.py +1 -2
- empathy_llm_toolkit/__init__.py +5 -6
- empathy_llm_toolkit/claude_memory.py +14 -15
- empathy_llm_toolkit/code_health.py +27 -19
- empathy_llm_toolkit/contextual_patterns.py +11 -12
- empathy_llm_toolkit/core.py +43 -49
- empathy_llm_toolkit/git_pattern_extractor.py +16 -12
- empathy_llm_toolkit/levels.py +6 -13
- empathy_llm_toolkit/pattern_confidence.py +14 -18
- empathy_llm_toolkit/pattern_resolver.py +10 -12
- empathy_llm_toolkit/pattern_summary.py +13 -11
- empathy_llm_toolkit/providers.py +27 -38
- empathy_llm_toolkit/session_status.py +18 -20
- empathy_llm_toolkit/state.py +20 -21
- empathy_os/__init__.py +72 -73
- empathy_os/cli.py +193 -98
- empathy_os/cli_unified.py +68 -41
- empathy_os/config.py +31 -31
- empathy_os/coordination.py +48 -54
- empathy_os/core.py +90 -99
- empathy_os/cost_tracker.py +20 -23
- empathy_os/discovery.py +9 -11
- empathy_os/emergence.py +20 -21
- empathy_os/exceptions.py +18 -30
- empathy_os/feedback_loops.py +27 -30
- empathy_os/levels.py +31 -34
- empathy_os/leverage_points.py +27 -28
- empathy_os/logging_config.py +11 -12
- empathy_os/monitoring.py +27 -27
- empathy_os/pattern_library.py +29 -28
- empathy_os/persistence.py +30 -34
- empathy_os/platform_utils.py +46 -47
- empathy_os/redis_config.py +14 -15
- empathy_os/redis_memory.py +53 -56
- empathy_os/templates.py +12 -11
- empathy_os/trust_building.py +44 -36
- empathy_os/workflow_commands.py +123 -31
- empathy_software_plugin/__init__.py +1 -2
- empathy_software_plugin/cli.py +32 -25
- empathy_software_plugin/plugin.py +4 -8
- empathy_framework-3.5.6.dist-info/RECORD +0 -103
- {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/WHEEL +0 -0
- {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/entry_points.txt +0 -0
- {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/licenses/LICENSE +0 -0
- {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/top_level.txt +0 -0
empathy_os/platform_utils.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Cross-Platform Utilities for Empathy Framework
|
|
1
|
+
"""Cross-Platform Utilities for Empathy Framework
|
|
3
2
|
|
|
4
3
|
Provides platform-independent utilities for:
|
|
5
4
|
- File paths and directories
|
|
@@ -34,93 +33,93 @@ def is_linux() -> bool:
|
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
def get_default_log_dir() -> Path:
|
|
37
|
-
"""
|
|
38
|
-
Get the default log directory for the current platform.
|
|
36
|
+
"""Get the default log directory for the current platform.
|
|
39
37
|
|
|
40
38
|
Returns:
|
|
41
39
|
Path: Platform-appropriate log directory
|
|
42
40
|
- Windows: %APPDATA%/empathy/logs
|
|
43
41
|
- macOS: ~/Library/Logs/empathy
|
|
44
42
|
- Linux: /var/log/empathy (if writable) or ~/.local/share/empathy/logs
|
|
43
|
+
|
|
45
44
|
"""
|
|
46
45
|
if is_windows():
|
|
47
46
|
appdata = os.environ.get("APPDATA", os.path.expanduser("~"))
|
|
48
47
|
return Path(appdata) / "empathy" / "logs"
|
|
49
|
-
|
|
48
|
+
if is_macos():
|
|
50
49
|
return Path.home() / "Library" / "Logs" / "empathy"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
# Linux and other Unix
|
|
51
|
+
var_log = Path("/var/log/empathy")
|
|
52
|
+
if var_log.exists() or (var_log.parent.exists() and os.access(var_log.parent, os.W_OK)):
|
|
53
|
+
return var_log
|
|
54
|
+
# Fallback to user directory
|
|
55
|
+
return Path.home() / ".local" / "share" / "empathy" / "logs"
|
|
57
56
|
|
|
58
57
|
|
|
59
58
|
def get_default_data_dir() -> Path:
|
|
60
|
-
"""
|
|
61
|
-
Get the default data directory for the current platform.
|
|
59
|
+
"""Get the default data directory for the current platform.
|
|
62
60
|
|
|
63
61
|
Returns:
|
|
64
62
|
Path: Platform-appropriate data directory
|
|
65
63
|
- Windows: %APPDATA%/empathy
|
|
66
64
|
- macOS: ~/Library/Application Support/empathy
|
|
67
65
|
- Linux: ~/.local/share/empathy
|
|
66
|
+
|
|
68
67
|
"""
|
|
69
68
|
if is_windows():
|
|
70
69
|
appdata = os.environ.get("APPDATA", os.path.expanduser("~"))
|
|
71
70
|
return Path(appdata) / "empathy"
|
|
72
|
-
|
|
71
|
+
if is_macos():
|
|
73
72
|
return Path.home() / "Library" / "Application Support" / "empathy"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
# Linux and other Unix
|
|
74
|
+
xdg_data = os.environ.get("XDG_DATA_HOME", str(Path.home() / ".local" / "share"))
|
|
75
|
+
return Path(xdg_data) / "empathy"
|
|
77
76
|
|
|
78
77
|
|
|
79
78
|
def get_default_config_dir() -> Path:
|
|
80
|
-
"""
|
|
81
|
-
Get the default configuration directory for the current platform.
|
|
79
|
+
"""Get the default configuration directory for the current platform.
|
|
82
80
|
|
|
83
81
|
Returns:
|
|
84
82
|
Path: Platform-appropriate config directory
|
|
85
83
|
- Windows: %APPDATA%/empathy
|
|
86
84
|
- macOS: ~/Library/Preferences/empathy
|
|
87
85
|
- Linux: ~/.config/empathy
|
|
86
|
+
|
|
88
87
|
"""
|
|
89
88
|
if is_windows():
|
|
90
89
|
appdata = os.environ.get("APPDATA", os.path.expanduser("~"))
|
|
91
90
|
return Path(appdata) / "empathy"
|
|
92
|
-
|
|
91
|
+
if is_macos():
|
|
93
92
|
return Path.home() / "Library" / "Preferences" / "empathy"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
# Linux and other Unix
|
|
94
|
+
xdg_config = os.environ.get("XDG_CONFIG_HOME", str(Path.home() / ".config"))
|
|
95
|
+
return Path(xdg_config) / "empathy"
|
|
97
96
|
|
|
98
97
|
|
|
99
98
|
def get_default_cache_dir() -> Path:
|
|
100
|
-
"""
|
|
101
|
-
Get the default cache directory for the current platform.
|
|
99
|
+
"""Get the default cache directory for the current platform.
|
|
102
100
|
|
|
103
101
|
Returns:
|
|
104
102
|
Path: Platform-appropriate cache directory
|
|
105
103
|
- Windows: %LOCALAPPDATA%/empathy/cache
|
|
106
104
|
- macOS: ~/Library/Caches/empathy
|
|
107
105
|
- Linux: ~/.cache/empathy
|
|
106
|
+
|
|
108
107
|
"""
|
|
109
108
|
if is_windows():
|
|
110
109
|
localappdata = os.environ.get(
|
|
111
|
-
"LOCALAPPDATA",
|
|
110
|
+
"LOCALAPPDATA",
|
|
111
|
+
os.environ.get("APPDATA", os.path.expanduser("~")),
|
|
112
112
|
)
|
|
113
113
|
return Path(localappdata) / "empathy" / "cache"
|
|
114
|
-
|
|
114
|
+
if is_macos():
|
|
115
115
|
return Path.home() / "Library" / "Caches" / "empathy"
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
# Linux and other Unix
|
|
117
|
+
xdg_cache = os.environ.get("XDG_CACHE_HOME", str(Path.home() / ".cache"))
|
|
118
|
+
return Path(xdg_cache) / "empathy"
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
def setup_asyncio_policy() -> None:
|
|
122
|
-
"""
|
|
123
|
-
Configure asyncio event loop policy for the current platform.
|
|
122
|
+
"""Configure asyncio event loop policy for the current platform.
|
|
124
123
|
|
|
125
124
|
On Windows, this uses WindowsSelectorEventLoopPolicy to avoid issues
|
|
126
125
|
with the default ProactorEventLoop, particularly with subprocesses
|
|
@@ -132,12 +131,11 @@ def setup_asyncio_policy() -> None:
|
|
|
132
131
|
if is_windows():
|
|
133
132
|
# Windows requires WindowsSelectorEventLoopPolicy for compatibility
|
|
134
133
|
# with many libraries and subprocess operations
|
|
135
|
-
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
|
134
|
+
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # type: ignore[attr-defined]
|
|
136
135
|
|
|
137
136
|
|
|
138
137
|
def safe_run_async(coro: Any, debug: bool = False) -> Any:
|
|
139
|
-
"""
|
|
140
|
-
Run an async coroutine with platform-appropriate event loop handling.
|
|
138
|
+
"""Run an async coroutine with platform-appropriate event loop handling.
|
|
141
139
|
|
|
142
140
|
This is a cross-platform wrapper for asyncio.run() that handles
|
|
143
141
|
Windows-specific event loop requirements.
|
|
@@ -148,14 +146,14 @@ def safe_run_async(coro: Any, debug: bool = False) -> Any:
|
|
|
148
146
|
|
|
149
147
|
Returns:
|
|
150
148
|
Result of the coroutine
|
|
149
|
+
|
|
151
150
|
"""
|
|
152
151
|
setup_asyncio_policy()
|
|
153
152
|
return asyncio.run(coro, debug=debug)
|
|
154
153
|
|
|
155
154
|
|
|
156
155
|
def open_text_file(path: str | Path, mode: str = "r", **kwargs: Any):
|
|
157
|
-
"""
|
|
158
|
-
Open a text file with UTF-8 encoding by default.
|
|
156
|
+
"""Open a text file with UTF-8 encoding by default.
|
|
159
157
|
|
|
160
158
|
This ensures consistent encoding across platforms, as Windows
|
|
161
159
|
defaults to cp1252 while Unix defaults to UTF-8.
|
|
@@ -167,14 +165,14 @@ def open_text_file(path: str | Path, mode: str = "r", **kwargs: Any):
|
|
|
167
165
|
|
|
168
166
|
Returns:
|
|
169
167
|
File object
|
|
168
|
+
|
|
170
169
|
"""
|
|
171
170
|
kwargs.setdefault("encoding", "utf-8")
|
|
172
171
|
return open(path, mode, **kwargs)
|
|
173
172
|
|
|
174
173
|
|
|
175
174
|
def read_text_file(path: str | Path, encoding: str = "utf-8") -> str:
|
|
176
|
-
"""
|
|
177
|
-
Read a text file with UTF-8 encoding by default.
|
|
175
|
+
"""Read a text file with UTF-8 encoding by default.
|
|
178
176
|
|
|
179
177
|
Args:
|
|
180
178
|
path: File path to read
|
|
@@ -182,13 +180,13 @@ def read_text_file(path: str | Path, encoding: str = "utf-8") -> str:
|
|
|
182
180
|
|
|
183
181
|
Returns:
|
|
184
182
|
File contents as string
|
|
183
|
+
|
|
185
184
|
"""
|
|
186
185
|
return Path(path).read_text(encoding=encoding)
|
|
187
186
|
|
|
188
187
|
|
|
189
188
|
def write_text_file(path: str | Path, content: str, encoding: str = "utf-8") -> int:
|
|
190
|
-
"""
|
|
191
|
-
Write content to a text file with UTF-8 encoding by default.
|
|
189
|
+
"""Write content to a text file with UTF-8 encoding by default.
|
|
192
190
|
|
|
193
191
|
Args:
|
|
194
192
|
path: File path to write
|
|
@@ -197,13 +195,13 @@ def write_text_file(path: str | Path, content: str, encoding: str = "utf-8") ->
|
|
|
197
195
|
|
|
198
196
|
Returns:
|
|
199
197
|
Number of characters written
|
|
198
|
+
|
|
200
199
|
"""
|
|
201
200
|
return Path(path).write_text(content, encoding=encoding)
|
|
202
201
|
|
|
203
202
|
|
|
204
203
|
def normalize_path(path: str | Path) -> Path:
|
|
205
|
-
"""
|
|
206
|
-
Normalize a path for the current platform.
|
|
204
|
+
"""Normalize a path for the current platform.
|
|
207
205
|
|
|
208
206
|
Converts forward slashes to backslashes on Windows and
|
|
209
207
|
resolves any relative path components.
|
|
@@ -213,16 +211,17 @@ def normalize_path(path: str | Path) -> Path:
|
|
|
213
211
|
|
|
214
212
|
Returns:
|
|
215
213
|
Normalized Path object
|
|
214
|
+
|
|
216
215
|
"""
|
|
217
216
|
return Path(path).resolve()
|
|
218
217
|
|
|
219
218
|
|
|
220
219
|
def get_temp_dir() -> Path:
|
|
221
|
-
"""
|
|
222
|
-
Get the system temporary directory.
|
|
220
|
+
"""Get the system temporary directory.
|
|
223
221
|
|
|
224
222
|
Returns:
|
|
225
223
|
Path to the system temp directory
|
|
224
|
+
|
|
226
225
|
"""
|
|
227
226
|
import tempfile
|
|
228
227
|
|
|
@@ -230,14 +229,14 @@ def get_temp_dir() -> Path:
|
|
|
230
229
|
|
|
231
230
|
|
|
232
231
|
def ensure_dir(path: str | Path) -> Path:
|
|
233
|
-
"""
|
|
234
|
-
Ensure a directory exists, creating it if necessary.
|
|
232
|
+
"""Ensure a directory exists, creating it if necessary.
|
|
235
233
|
|
|
236
234
|
Args:
|
|
237
235
|
path: Directory path to ensure
|
|
238
236
|
|
|
239
237
|
Returns:
|
|
240
238
|
Path object for the directory
|
|
239
|
+
|
|
241
240
|
"""
|
|
242
241
|
dir_path = Path(path)
|
|
243
242
|
dir_path.mkdir(parents=True, exist_ok=True)
|
empathy_os/redis_config.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Redis Configuration for Empathy Framework
|
|
1
|
+
"""Redis Configuration for Empathy Framework
|
|
3
2
|
|
|
4
3
|
Handles connection to Redis from environment variables.
|
|
5
4
|
Supports Railway, redis.com, local Docker, managed Redis, or mock mode.
|
|
@@ -61,8 +60,7 @@ from .memory.short_term import RedisConfig, RedisShortTermMemory
|
|
|
61
60
|
|
|
62
61
|
|
|
63
62
|
def parse_redis_url(url: str) -> dict:
|
|
64
|
-
"""
|
|
65
|
-
Parse Redis URL into connection parameters.
|
|
63
|
+
"""Parse Redis URL into connection parameters.
|
|
66
64
|
|
|
67
65
|
Supports:
|
|
68
66
|
- redis://user:pass@host:port/db (standard)
|
|
@@ -73,6 +71,7 @@ def parse_redis_url(url: str) -> dict:
|
|
|
73
71
|
|
|
74
72
|
Returns:
|
|
75
73
|
Dict with host, port, password, db, ssl
|
|
74
|
+
|
|
76
75
|
"""
|
|
77
76
|
parsed = urlparse(url)
|
|
78
77
|
|
|
@@ -89,8 +88,7 @@ def parse_redis_url(url: str) -> dict:
|
|
|
89
88
|
|
|
90
89
|
|
|
91
90
|
def get_redis_config() -> RedisConfig:
|
|
92
|
-
"""
|
|
93
|
-
Get Redis configuration from environment variables.
|
|
91
|
+
"""Get Redis configuration from environment variables.
|
|
94
92
|
|
|
95
93
|
Priority:
|
|
96
94
|
1. REDIS_URL (full URL, used by Railway/Heroku/managed services)
|
|
@@ -99,6 +97,7 @@ def get_redis_config() -> RedisConfig:
|
|
|
99
97
|
|
|
100
98
|
Returns:
|
|
101
99
|
RedisConfig with all connection parameters
|
|
100
|
+
|
|
102
101
|
"""
|
|
103
102
|
# Check for mock mode
|
|
104
103
|
if os.getenv("EMPATHY_REDIS_MOCK", "").lower() == "true":
|
|
@@ -149,11 +148,11 @@ def get_redis_config() -> RedisConfig:
|
|
|
149
148
|
|
|
150
149
|
|
|
151
150
|
def get_redis_config_dict() -> dict:
|
|
152
|
-
"""
|
|
153
|
-
Get Redis configuration as a dictionary (legacy compatibility).
|
|
151
|
+
"""Get Redis configuration as a dictionary (legacy compatibility).
|
|
154
152
|
|
|
155
153
|
Returns:
|
|
156
154
|
Dict with connection parameters
|
|
155
|
+
|
|
157
156
|
"""
|
|
158
157
|
config = get_redis_config()
|
|
159
158
|
return {
|
|
@@ -171,8 +170,7 @@ def get_redis_memory(
|
|
|
171
170
|
use_mock: bool | None = None,
|
|
172
171
|
config: RedisConfig | None = None,
|
|
173
172
|
) -> RedisShortTermMemory:
|
|
174
|
-
"""
|
|
175
|
-
Create a RedisShortTermMemory instance with environment-based config.
|
|
173
|
+
"""Create a RedisShortTermMemory instance with environment-based config.
|
|
176
174
|
|
|
177
175
|
Args:
|
|
178
176
|
url: Optional explicit Redis URL (overrides env vars)
|
|
@@ -201,6 +199,7 @@ def get_redis_memory(
|
|
|
201
199
|
retry_max_attempts=5,
|
|
202
200
|
)
|
|
203
201
|
memory = get_redis_memory(config=config)
|
|
202
|
+
|
|
204
203
|
"""
|
|
205
204
|
# Explicit config takes highest priority
|
|
206
205
|
if config is not None:
|
|
@@ -229,8 +228,7 @@ def get_redis_memory(
|
|
|
229
228
|
|
|
230
229
|
|
|
231
230
|
def check_redis_connection() -> dict:
|
|
232
|
-
"""
|
|
233
|
-
Check Redis connection and return status.
|
|
231
|
+
"""Check Redis connection and return status.
|
|
234
232
|
|
|
235
233
|
Returns:
|
|
236
234
|
Dict with connection status and info
|
|
@@ -239,6 +237,7 @@ def check_redis_connection() -> dict:
|
|
|
239
237
|
>>> status = check_redis_connection()
|
|
240
238
|
>>> if status["connected"]:
|
|
241
239
|
... print(f"Connected to {status['host']}:{status['port']}")
|
|
240
|
+
|
|
242
241
|
"""
|
|
243
242
|
config = get_redis_config()
|
|
244
243
|
|
|
@@ -281,8 +280,7 @@ def check_redis_connection() -> dict:
|
|
|
281
280
|
|
|
282
281
|
# Convenience function for Railway deployments
|
|
283
282
|
def get_railway_redis() -> RedisShortTermMemory:
|
|
284
|
-
"""
|
|
285
|
-
Get Redis configured for Railway deployment.
|
|
283
|
+
"""Get Redis configured for Railway deployment.
|
|
286
284
|
|
|
287
285
|
Railway automatically sets REDIS_URL when you add a Redis service.
|
|
288
286
|
|
|
@@ -291,13 +289,14 @@ def get_railway_redis() -> RedisShortTermMemory:
|
|
|
291
289
|
|
|
292
290
|
Raises:
|
|
293
291
|
EnvironmentError: If REDIS_URL is not set
|
|
292
|
+
|
|
294
293
|
"""
|
|
295
294
|
redis_url = os.getenv("REDIS_URL") or os.getenv("REDIS_PRIVATE_URL")
|
|
296
295
|
|
|
297
296
|
if not redis_url:
|
|
298
297
|
raise OSError(
|
|
299
298
|
"REDIS_URL not found. Make sure Redis is added to your Railway project.\n"
|
|
300
|
-
"Run: railway add --database redis"
|
|
299
|
+
"Run: railway add --database redis",
|
|
301
300
|
)
|
|
302
301
|
|
|
303
302
|
return get_redis_memory(url=redis_url)
|