empathy-framework 4.7.0__py3-none-any.whl → 4.8.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.
- empathy_framework-4.8.0.dist-info/METADATA +753 -0
- {empathy_framework-4.7.0.dist-info → empathy_framework-4.8.0.dist-info}/RECORD +83 -37
- {empathy_framework-4.7.0.dist-info → empathy_framework-4.8.0.dist-info}/WHEEL +1 -1
- {empathy_framework-4.7.0.dist-info → empathy_framework-4.8.0.dist-info}/entry_points.txt +2 -1
- empathy_os/__init__.py +2 -0
- empathy_os/cache/hash_only.py +6 -3
- empathy_os/cache/hybrid.py +6 -3
- empathy_os/cli/__init__.py +128 -238
- empathy_os/cli/__main__.py +5 -33
- empathy_os/cli/commands/__init__.py +1 -8
- empathy_os/cli/commands/help.py +331 -0
- empathy_os/cli/commands/info.py +140 -0
- empathy_os/cli/commands/inspect.py +437 -0
- empathy_os/cli/commands/metrics.py +92 -0
- empathy_os/cli/commands/orchestrate.py +184 -0
- empathy_os/cli/commands/patterns.py +207 -0
- empathy_os/cli/commands/provider.py +93 -81
- empathy_os/cli/commands/setup.py +96 -0
- empathy_os/cli/commands/status.py +235 -0
- empathy_os/cli/commands/sync.py +166 -0
- empathy_os/cli/commands/tier.py +121 -0
- empathy_os/cli/commands/workflow.py +574 -0
- empathy_os/cli/parsers/__init__.py +62 -0
- empathy_os/cli/parsers/help.py +41 -0
- empathy_os/cli/parsers/info.py +26 -0
- empathy_os/cli/parsers/inspect.py +66 -0
- empathy_os/cli/parsers/metrics.py +42 -0
- empathy_os/cli/parsers/orchestrate.py +61 -0
- empathy_os/cli/parsers/patterns.py +54 -0
- empathy_os/cli/parsers/provider.py +40 -0
- empathy_os/cli/parsers/setup.py +42 -0
- empathy_os/cli/parsers/status.py +47 -0
- empathy_os/cli/parsers/sync.py +31 -0
- empathy_os/cli/parsers/tier.py +33 -0
- empathy_os/cli/parsers/workflow.py +77 -0
- empathy_os/cli/utils/__init__.py +1 -0
- empathy_os/cli/utils/data.py +242 -0
- empathy_os/cli/utils/helpers.py +68 -0
- empathy_os/{cli.py → cli_legacy.py} +27 -27
- empathy_os/cli_minimal.py +662 -0
- empathy_os/cli_router.py +384 -0
- empathy_os/cli_unified.py +38 -2
- empathy_os/memory/__init__.py +19 -5
- empathy_os/memory/short_term.py +14 -404
- empathy_os/memory/types.py +437 -0
- empathy_os/memory/unified.py +61 -48
- empathy_os/models/fallback.py +1 -1
- empathy_os/models/provider_config.py +59 -344
- empathy_os/models/registry.py +31 -180
- empathy_os/monitoring/alerts.py +14 -20
- empathy_os/monitoring/alerts_cli.py +24 -7
- empathy_os/project_index/__init__.py +2 -0
- empathy_os/project_index/index.py +210 -5
- empathy_os/project_index/scanner.py +45 -14
- empathy_os/project_index/scanner_parallel.py +291 -0
- empathy_os/socratic/ab_testing.py +1 -1
- empathy_os/vscode_bridge 2.py +173 -0
- empathy_os/workflows/__init__.py +31 -2
- empathy_os/workflows/base.py +349 -325
- empathy_os/workflows/bug_predict.py +8 -0
- empathy_os/workflows/builder.py +273 -0
- empathy_os/workflows/caching.py +253 -0
- empathy_os/workflows/code_review_pipeline.py +1 -0
- empathy_os/workflows/history.py +510 -0
- empathy_os/workflows/output.py +410 -0
- empathy_os/workflows/perf_audit.py +125 -19
- empathy_os/workflows/progress.py +324 -22
- empathy_os/workflows/progressive/README 2.md +454 -0
- empathy_os/workflows/progressive/__init__ 2.py +92 -0
- empathy_os/workflows/progressive/cli 2.py +242 -0
- empathy_os/workflows/progressive/core 2.py +488 -0
- empathy_os/workflows/progressive/orchestrator 2.py +701 -0
- empathy_os/workflows/progressive/reports 2.py +528 -0
- empathy_os/workflows/progressive/telemetry 2.py +280 -0
- empathy_os/workflows/progressive/test_gen 2.py +514 -0
- empathy_os/workflows/progressive/workflow 2.py +628 -0
- empathy_os/workflows/routing.py +168 -0
- empathy_os/workflows/secure_release.py +1 -0
- empathy_os/workflows/security_audit.py +190 -0
- empathy_os/workflows/security_audit_phase3.py +328 -0
- empathy_os/workflows/telemetry_mixin.py +269 -0
- empathy_framework-4.7.0.dist-info/METADATA +0 -1598
- empathy_os/dashboard/__init__.py +0 -15
- empathy_os/dashboard/server.py +0 -941
- {empathy_framework-4.7.0.dist-info → empathy_framework-4.8.0.dist-info}/licenses/LICENSE +0 -0
- {empathy_framework-4.7.0.dist-info → empathy_framework-4.8.0.dist-info}/top_level.txt +0 -0
empathy_os/cli_router.py
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"""Hybrid CLI Router - Slash Commands + Natural Language
|
|
2
|
+
|
|
3
|
+
Supports both structured slash commands and natural language routing:
|
|
4
|
+
- Slash commands: empathy /dev commit
|
|
5
|
+
- Natural language: empathy "commit my changes"
|
|
6
|
+
- Single word: empathy commit (infers /dev commit)
|
|
7
|
+
|
|
8
|
+
Copyright 2025 Smart-AI-Memory
|
|
9
|
+
Licensed under Fair Source License 0.9
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
import yaml
|
|
19
|
+
|
|
20
|
+
from empathy_os.routing import SmartRouter
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class RoutingPreference:
|
|
25
|
+
"""User's learned routing preferences."""
|
|
26
|
+
|
|
27
|
+
keyword: str
|
|
28
|
+
slash_command: str
|
|
29
|
+
usage_count: int = 0
|
|
30
|
+
confidence: float = 1.0
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class HybridRouter:
|
|
34
|
+
"""Routes user input to appropriate commands or workflows.
|
|
35
|
+
|
|
36
|
+
Supports three input modes:
|
|
37
|
+
1. Slash commands: /dev commit (direct, structured)
|
|
38
|
+
2. Single words: commit (infers /dev commit from context)
|
|
39
|
+
3. Natural language: "I need to commit" (uses SmartRouter)
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
router = HybridRouter()
|
|
43
|
+
|
|
44
|
+
# Direct slash command
|
|
45
|
+
result = await router.route("/dev commit")
|
|
46
|
+
# → {type: "slash", hub: "dev", command: "commit"}
|
|
47
|
+
|
|
48
|
+
# Single word inference
|
|
49
|
+
result = await router.route("commit")
|
|
50
|
+
# → {type: "inferred", hub: "dev", command: "commit", confidence: 0.9}
|
|
51
|
+
|
|
52
|
+
# Natural language
|
|
53
|
+
result = await router.route("I want to commit my changes")
|
|
54
|
+
# → {type: "natural", workflow: "commit", slash_equivalent: "/dev commit"}
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, preferences_path: str | None = None):
|
|
58
|
+
"""Initialize hybrid router.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
preferences_path: Path to user preferences YAML
|
|
62
|
+
Default: .empathy/routing_preferences.yaml
|
|
63
|
+
"""
|
|
64
|
+
self.preferences_path = Path(
|
|
65
|
+
preferences_path or Path.home() / ".empathy" / "routing_preferences.yaml"
|
|
66
|
+
)
|
|
67
|
+
self.smart_router = SmartRouter()
|
|
68
|
+
self.preferences: dict[str, RoutingPreference] = {}
|
|
69
|
+
|
|
70
|
+
# Command to slash command mapping
|
|
71
|
+
self._command_map = {
|
|
72
|
+
# Dev commands
|
|
73
|
+
"commit": "/dev commit",
|
|
74
|
+
"review": "/dev review-pr",
|
|
75
|
+
"review-pr": "/dev review-pr",
|
|
76
|
+
"refactor": "/dev refactor",
|
|
77
|
+
"perf": "/dev perf-audit",
|
|
78
|
+
"perf-audit": "/dev perf-audit",
|
|
79
|
+
# Testing commands
|
|
80
|
+
"test": "/testing run",
|
|
81
|
+
"tests": "/testing run",
|
|
82
|
+
"coverage": "/testing coverage",
|
|
83
|
+
"generate-tests": "/testing gen",
|
|
84
|
+
"test-gen": "/testing gen",
|
|
85
|
+
# Learning commands
|
|
86
|
+
"evaluate": "/learning evaluate",
|
|
87
|
+
"patterns": "/learning patterns",
|
|
88
|
+
"improve": "/learning improve",
|
|
89
|
+
# Workflow commands
|
|
90
|
+
"security": "/workflows security-audit",
|
|
91
|
+
"security-audit": "/workflows security-audit",
|
|
92
|
+
"bug-predict": "/workflows bug-predict",
|
|
93
|
+
"bugs": "/workflows bug-predict",
|
|
94
|
+
# Context commands
|
|
95
|
+
"status": "/context status",
|
|
96
|
+
"memory": "/context memory",
|
|
97
|
+
"state": "/context state",
|
|
98
|
+
# Doc commands
|
|
99
|
+
"explain": "/docs explain",
|
|
100
|
+
"document": "/docs generate",
|
|
101
|
+
"overview": "/docs overview",
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Hub descriptions for disambiguation
|
|
105
|
+
self._hub_descriptions = {
|
|
106
|
+
"dev": "Development tools (commits, reviews, refactoring)",
|
|
107
|
+
"testing": "Test generation and coverage analysis",
|
|
108
|
+
"learning": "Session evaluation and pattern learning",
|
|
109
|
+
"workflows": "AI-powered workflows (security, bugs, performance)",
|
|
110
|
+
"context": "Memory and state management",
|
|
111
|
+
"docs": "Documentation generation",
|
|
112
|
+
"plan": "Development planning and architecture",
|
|
113
|
+
"release": "Release preparation and publishing",
|
|
114
|
+
"utilities": "Utility tools (profiling, dependencies)",
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
self._load_preferences()
|
|
118
|
+
|
|
119
|
+
def _load_preferences(self) -> None:
|
|
120
|
+
"""Load user routing preferences from disk."""
|
|
121
|
+
if not self.preferences_path.exists():
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
with open(self.preferences_path) as f:
|
|
126
|
+
data = yaml.safe_load(f) or {}
|
|
127
|
+
|
|
128
|
+
for keyword, pref_data in data.get("preferences", {}).items():
|
|
129
|
+
self.preferences[keyword] = RoutingPreference(
|
|
130
|
+
keyword=keyword,
|
|
131
|
+
slash_command=pref_data["slash_command"],
|
|
132
|
+
usage_count=pref_data.get("usage_count", 0),
|
|
133
|
+
confidence=pref_data.get("confidence", 1.0),
|
|
134
|
+
)
|
|
135
|
+
except Exception as e:
|
|
136
|
+
print(f"Warning: Could not load routing preferences: {e}")
|
|
137
|
+
|
|
138
|
+
def _save_preferences(self) -> None:
|
|
139
|
+
"""Save user routing preferences to disk."""
|
|
140
|
+
self.preferences_path.parent.mkdir(parents=True, exist_ok=True)
|
|
141
|
+
|
|
142
|
+
data = {
|
|
143
|
+
"preferences": {
|
|
144
|
+
pref.keyword: {
|
|
145
|
+
"slash_command": pref.slash_command,
|
|
146
|
+
"usage_count": pref.usage_count,
|
|
147
|
+
"confidence": pref.confidence,
|
|
148
|
+
}
|
|
149
|
+
for pref in self.preferences.values()
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
with open(self.preferences_path, "w") as f:
|
|
154
|
+
yaml.dump(data, f, default_flow_style=False)
|
|
155
|
+
|
|
156
|
+
async def route(
|
|
157
|
+
self, user_input: str, context: dict[str, Any] | None = None
|
|
158
|
+
) -> dict[str, Any]:
|
|
159
|
+
"""Route user input to appropriate command or workflow.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
user_input: User's input (slash command, keyword, or natural language)
|
|
163
|
+
context: Optional context (current file, project info, etc.)
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Routing result with type, command/workflow, and metadata
|
|
167
|
+
"""
|
|
168
|
+
user_input = user_input.strip()
|
|
169
|
+
|
|
170
|
+
# Level 1: Slash command (direct execution)
|
|
171
|
+
if user_input.startswith("/"):
|
|
172
|
+
return self._route_slash_command(user_input)
|
|
173
|
+
|
|
174
|
+
# Level 2: Single word or known command (inference)
|
|
175
|
+
words = user_input.split()
|
|
176
|
+
if len(words) <= 2:
|
|
177
|
+
inferred = self._infer_command(user_input)
|
|
178
|
+
if inferred:
|
|
179
|
+
return inferred
|
|
180
|
+
|
|
181
|
+
# Level 3: Natural language (SmartRouter)
|
|
182
|
+
return await self._route_natural_language(user_input, context)
|
|
183
|
+
|
|
184
|
+
def _route_slash_command(self, command: str) -> dict[str, Any]:
|
|
185
|
+
"""Route slash command directly.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
command: Slash command like "/dev commit"
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Routing result
|
|
192
|
+
"""
|
|
193
|
+
parts = command[1:].split(maxsplit=1) # Remove leading /
|
|
194
|
+
hub = parts[0] if parts else "help"
|
|
195
|
+
subcommand = parts[1] if len(parts) > 1 else None
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
"type": "slash",
|
|
199
|
+
"hub": hub,
|
|
200
|
+
"command": subcommand,
|
|
201
|
+
"original": command,
|
|
202
|
+
"confidence": 1.0,
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
def _infer_command(self, keyword: str) -> dict[str, Any] | None:
|
|
206
|
+
"""Infer slash command from keyword or short phrase.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
keyword: Single word or short phrase
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
Routing result if inference successful, None otherwise
|
|
213
|
+
"""
|
|
214
|
+
keyword_lower = keyword.lower().strip()
|
|
215
|
+
|
|
216
|
+
# Check learned preferences first
|
|
217
|
+
if keyword_lower in self.preferences:
|
|
218
|
+
pref = self.preferences[keyword_lower]
|
|
219
|
+
slash_cmd = pref.slash_command
|
|
220
|
+
|
|
221
|
+
# Update usage count
|
|
222
|
+
pref.usage_count += 1
|
|
223
|
+
self._save_preferences()
|
|
224
|
+
|
|
225
|
+
return self._parse_inferred(slash_cmd, keyword, pref.confidence, "learned")
|
|
226
|
+
|
|
227
|
+
# Check built-in command map
|
|
228
|
+
if keyword_lower in self._command_map:
|
|
229
|
+
slash_cmd = self._command_map[keyword_lower]
|
|
230
|
+
return self._parse_inferred(slash_cmd, keyword, 0.9, "builtin")
|
|
231
|
+
|
|
232
|
+
# Check for hub names (show hub menu)
|
|
233
|
+
if keyword_lower in self._hub_descriptions:
|
|
234
|
+
return {
|
|
235
|
+
"type": "hub_menu",
|
|
236
|
+
"hub": keyword_lower,
|
|
237
|
+
"original": keyword,
|
|
238
|
+
"confidence": 1.0,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return None
|
|
242
|
+
|
|
243
|
+
def _parse_inferred(
|
|
244
|
+
self, slash_cmd: str, original: str, confidence: float, source: str
|
|
245
|
+
) -> dict[str, Any]:
|
|
246
|
+
"""Parse inferred slash command."""
|
|
247
|
+
parts = slash_cmd[1:].split(maxsplit=1) # Remove leading /
|
|
248
|
+
hub = parts[0] if parts else "help"
|
|
249
|
+
subcommand = parts[1] if len(parts) > 1 else None
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
"type": "inferred",
|
|
253
|
+
"hub": hub,
|
|
254
|
+
"command": subcommand,
|
|
255
|
+
"original": original,
|
|
256
|
+
"slash_equivalent": slash_cmd,
|
|
257
|
+
"confidence": confidence,
|
|
258
|
+
"source": source, # learned, builtin
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async def _route_natural_language(
|
|
262
|
+
self, text: str, context: dict[str, Any] | None = None
|
|
263
|
+
) -> dict[str, Any]:
|
|
264
|
+
"""Route natural language input using SmartRouter.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
text: Natural language input
|
|
268
|
+
context: Optional context
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
Routing result with workflow and slash equivalent
|
|
272
|
+
"""
|
|
273
|
+
# Use SmartRouter for classification
|
|
274
|
+
decision = await self.smart_router.route(text, context)
|
|
275
|
+
|
|
276
|
+
# Map workflow to slash command
|
|
277
|
+
slash_equivalent = self._workflow_to_slash(decision.primary_workflow)
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
"type": "natural",
|
|
281
|
+
"workflow": decision.primary_workflow,
|
|
282
|
+
"secondary_workflows": decision.secondary_workflows,
|
|
283
|
+
"slash_equivalent": slash_equivalent,
|
|
284
|
+
"confidence": decision.confidence,
|
|
285
|
+
"reasoning": decision.reasoning,
|
|
286
|
+
"original": text,
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
def _workflow_to_slash(self, workflow: str) -> str:
|
|
290
|
+
"""Map workflow name to slash command equivalent.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
workflow: Workflow name (e.g., "security-audit")
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
Slash command equivalent
|
|
297
|
+
"""
|
|
298
|
+
# Workflow to slash command mapping
|
|
299
|
+
workflow_map = {
|
|
300
|
+
"security-audit": "/workflows security-audit",
|
|
301
|
+
"bug-predict": "/workflows bug-predict",
|
|
302
|
+
"code-review": "/dev review",
|
|
303
|
+
"test-gen": "/testing gen",
|
|
304
|
+
"perf-audit": "/dev perf-audit",
|
|
305
|
+
"commit": "/dev commit",
|
|
306
|
+
"refactor": "/dev refactor",
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return workflow_map.get(workflow, f"/workflows {workflow}")
|
|
310
|
+
|
|
311
|
+
def learn_preference(self, keyword: str, slash_command: str) -> None:
|
|
312
|
+
"""Learn user's routing preference.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
keyword: Keyword user typed
|
|
316
|
+
slash_command: Command that was executed
|
|
317
|
+
"""
|
|
318
|
+
if keyword in self.preferences:
|
|
319
|
+
pref = self.preferences[keyword]
|
|
320
|
+
pref.usage_count += 1
|
|
321
|
+
# Increase confidence with repeated usage
|
|
322
|
+
pref.confidence = min(1.0, pref.confidence + 0.05)
|
|
323
|
+
else:
|
|
324
|
+
self.preferences[keyword] = RoutingPreference(
|
|
325
|
+
keyword=keyword,
|
|
326
|
+
slash_command=slash_command,
|
|
327
|
+
usage_count=1,
|
|
328
|
+
confidence=0.8,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
self._save_preferences()
|
|
332
|
+
|
|
333
|
+
def get_suggestions(self, partial: str) -> list[str]:
|
|
334
|
+
"""Get command suggestions based on partial input.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
partial: Partial command input
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
List of suggested commands
|
|
341
|
+
"""
|
|
342
|
+
suggestions = []
|
|
343
|
+
partial_lower = partial.lower()
|
|
344
|
+
|
|
345
|
+
# Suggest slash commands
|
|
346
|
+
for cmd in self._command_map.values():
|
|
347
|
+
if partial_lower in cmd.lower():
|
|
348
|
+
suggestions.append(cmd)
|
|
349
|
+
|
|
350
|
+
# Suggest learned preferences
|
|
351
|
+
for pref in self.preferences.values():
|
|
352
|
+
if partial_lower in pref.keyword.lower():
|
|
353
|
+
suggestions.append(f"{pref.keyword} → {pref.slash_command}")
|
|
354
|
+
|
|
355
|
+
return suggestions[:5] # Top 5 suggestions
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
# Convenience functions
|
|
359
|
+
async def route_user_input(
|
|
360
|
+
user_input: str, context: dict[str, Any] | None = None
|
|
361
|
+
) -> dict[str, Any]:
|
|
362
|
+
"""Quick routing helper.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
user_input: User's input
|
|
366
|
+
context: Optional context
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Routing result
|
|
370
|
+
"""
|
|
371
|
+
router = HybridRouter()
|
|
372
|
+
return await router.route(user_input, context)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def is_slash_command(text: str) -> bool:
|
|
376
|
+
"""Check if text is a slash command.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
text: Input text
|
|
380
|
+
|
|
381
|
+
Returns:
|
|
382
|
+
True if slash command, False otherwise
|
|
383
|
+
"""
|
|
384
|
+
return text.strip().startswith("/")
|
empathy_os/cli_unified.py
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
"""Unified CLI for Empathy Framework
|
|
2
2
|
|
|
3
|
+
DEPRECATED: This module is deprecated as of v5.0.0.
|
|
4
|
+
Use the minimal CLI instead: `empathy` (empathy_os.cli_minimal)
|
|
5
|
+
|
|
6
|
+
The minimal CLI provides:
|
|
7
|
+
- `empathy workflow list|info|run` - Workflow management
|
|
8
|
+
- `empathy telemetry show|savings|export` - Usage tracking
|
|
9
|
+
- `empathy provider show|set` - Provider configuration
|
|
10
|
+
- `empathy validate` - Configuration validation
|
|
11
|
+
|
|
12
|
+
For interactive features, use Claude Code slash commands:
|
|
13
|
+
- /dev, /testing, /docs, /release, /help
|
|
14
|
+
|
|
15
|
+
Migration guide: https://smartaimemory.com/framework-docs/migration/cli/
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
3
19
|
A simplified, intelligent CLI using Socratic questioning.
|
|
4
20
|
|
|
5
21
|
Usage:
|
|
@@ -14,6 +30,15 @@ Copyright 2025 Smart-AI-Memory
|
|
|
14
30
|
Licensed under Fair Source License 0.9
|
|
15
31
|
"""
|
|
16
32
|
|
|
33
|
+
import warnings
|
|
34
|
+
|
|
35
|
+
warnings.warn(
|
|
36
|
+
"empathy-unified CLI is deprecated. Use 'empathy' (cli_minimal) instead. "
|
|
37
|
+
"See: https://smartaimemory.com/framework-docs/reference/cli-reference/",
|
|
38
|
+
DeprecationWarning,
|
|
39
|
+
stacklevel=2,
|
|
40
|
+
)
|
|
41
|
+
|
|
17
42
|
import json
|
|
18
43
|
import subprocess
|
|
19
44
|
import sys
|
|
@@ -542,7 +567,9 @@ def utilities_status():
|
|
|
542
567
|
@utilities_app.command("scan")
|
|
543
568
|
def utilities_scan(
|
|
544
569
|
path: Path = typer.Argument(Path("."), help="Path to scan"),
|
|
545
|
-
scan_type: str = typer.Option(
|
|
570
|
+
scan_type: str = typer.Option(
|
|
571
|
+
"all", "--type", "-t", help="Scan type: security, performance, or all"
|
|
572
|
+
),
|
|
546
573
|
):
|
|
547
574
|
"""Scan codebase for issues.
|
|
548
575
|
|
|
@@ -649,7 +676,16 @@ def telemetry_export(
|
|
|
649
676
|
):
|
|
650
677
|
"""Export telemetry data."""
|
|
651
678
|
subprocess.run(
|
|
652
|
-
[
|
|
679
|
+
[
|
|
680
|
+
sys.executable,
|
|
681
|
+
"-m",
|
|
682
|
+
"empathy_os.cli",
|
|
683
|
+
"telemetry",
|
|
684
|
+
"export",
|
|
685
|
+
str(output),
|
|
686
|
+
"--format",
|
|
687
|
+
format_type,
|
|
688
|
+
],
|
|
653
689
|
check=False,
|
|
654
690
|
)
|
|
655
691
|
|
empathy_os/memory/__init__.py
CHANGED
|
@@ -123,17 +123,24 @@ from .security import ( # Audit Logging; PII Scrubbing; Secrets Detection
|
|
|
123
123
|
Severity,
|
|
124
124
|
detect_secrets,
|
|
125
125
|
)
|
|
126
|
-
from .short_term import
|
|
126
|
+
from .short_term import RedisShortTermMemory
|
|
127
|
+
|
|
128
|
+
# Conversation Summary Index
|
|
129
|
+
from .summary_index import AgentContext, ConversationSummaryIndex
|
|
130
|
+
|
|
131
|
+
# Types (extracted to types.py for cleaner separation)
|
|
132
|
+
from .types import (
|
|
127
133
|
AccessTier,
|
|
128
134
|
AgentCredentials,
|
|
129
135
|
ConflictContext,
|
|
130
|
-
|
|
136
|
+
PaginatedResult,
|
|
137
|
+
RedisConfig,
|
|
138
|
+
RedisMetrics,
|
|
131
139
|
StagedPattern,
|
|
140
|
+
TimeWindowQuery,
|
|
132
141
|
TTLStrategy,
|
|
133
142
|
)
|
|
134
|
-
|
|
135
|
-
# Conversation Summary Index
|
|
136
|
-
from .summary_index import AgentContext, ConversationSummaryIndex
|
|
143
|
+
from .types import SecurityError as ShortTermSecurityError
|
|
137
144
|
|
|
138
145
|
# Unified memory interface
|
|
139
146
|
from .unified import Environment, MemoryConfig, UnifiedMemory
|
|
@@ -180,6 +187,8 @@ __all__ = [
|
|
|
180
187
|
"MemoryStats",
|
|
181
188
|
"Node",
|
|
182
189
|
"NodeType",
|
|
190
|
+
# Pagination and Query Types
|
|
191
|
+
"PaginatedResult",
|
|
183
192
|
"PIIDetection",
|
|
184
193
|
"PIIPattern",
|
|
185
194
|
# Security - PII
|
|
@@ -187,6 +196,9 @@ __all__ = [
|
|
|
187
196
|
"PatternMetadata",
|
|
188
197
|
"PatternNode",
|
|
189
198
|
"PerformanceNode",
|
|
199
|
+
# Redis Configuration and Metrics
|
|
200
|
+
"RedisConfig",
|
|
201
|
+
"RedisMetrics",
|
|
190
202
|
# Short-term Memory
|
|
191
203
|
"RedisShortTermMemory",
|
|
192
204
|
"RedisStartMethod",
|
|
@@ -203,8 +215,10 @@ __all__ = [
|
|
|
203
215
|
"SessionInfo",
|
|
204
216
|
"SessionType",
|
|
205
217
|
"Severity",
|
|
218
|
+
"ShortTermSecurityError",
|
|
206
219
|
"StagedPattern",
|
|
207
220
|
"TTLStrategy",
|
|
221
|
+
"TimeWindowQuery",
|
|
208
222
|
# Unified Memory Interface (recommended)
|
|
209
223
|
"UnifiedMemory",
|
|
210
224
|
"VulnerabilityNode",
|