empathy-framework 4.4.0__py3-none-any.whl → 4.5.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.4.0.dist-info → empathy_framework-4.5.0.dist-info}/METADATA +1 -1
- {empathy_framework-4.4.0.dist-info → empathy_framework-4.5.0.dist-info}/RECORD +14 -13
- empathy_os/cli_unified.py +262 -0
- empathy_os/memory/__init__.py +21 -0
- empathy_os/memory/cross_session.py +849 -0
- empathy_os/memory/short_term.py +186 -0
- empathy_os/meta_workflows/builtin_templates.py +20 -20
- empathy_os/meta_workflows/cli_meta_workflows.py +70 -15
- empathy_os/meta_workflows/workflow.py +30 -1
- empathy_os/orchestration/agent_templates.py +192 -1
- {empathy_framework-4.4.0.dist-info → empathy_framework-4.5.0.dist-info}/WHEEL +0 -0
- {empathy_framework-4.4.0.dist-info → empathy_framework-4.5.0.dist-info}/entry_points.txt +0 -0
- {empathy_framework-4.4.0.dist-info → empathy_framework-4.5.0.dist-info}/licenses/LICENSE +0 -0
- {empathy_framework-4.4.0.dist-info → empathy_framework-4.5.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: empathy-framework
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.0
|
|
4
4
|
Summary: AI collaboration framework with real LLM agent execution, AskUserQuestion tool integration, Socratic agent generation, progressive tier escalation (70-85% cost savings), meta-orchestration, dynamic agent composition (6 patterns), intelligent caching (85% hit rate), semantic workflow discovery, visual workflow editor, MCP integration for Claude Code, and multi-agent orchestration.
|
|
5
5
|
Author-email: Patrick Roebuck <admin@smartaimemory.com>
|
|
6
6
|
Maintainer-email: Smart-AI-Memory <admin@smartaimemory.com>
|
|
@@ -20,7 +20,7 @@ coach_wizards/refactoring_wizard.py,sha256=X0MTx3BHpOlOMAYDow-3HX5GyryY70JGAF5vA
|
|
|
20
20
|
coach_wizards/scaling_wizard.py,sha256=n1RLtpWmj1RSEGSWssMiUPwCdpskO3z2Z3yhLlTdXro,2598
|
|
21
21
|
coach_wizards/security_wizard.py,sha256=19SOClSxo6N-QqUc_QsFXOE7yEquiZF4kLi7jRomA7g,2605
|
|
22
22
|
coach_wizards/testing_wizard.py,sha256=vKFgFG4uJfAVFmCIQbkrWNvZhIfLC6ve_XbvWZKrPg4,2563
|
|
23
|
-
empathy_framework-4.
|
|
23
|
+
empathy_framework-4.5.0.dist-info/licenses/LICENSE,sha256=IJ9eeI5KSrD5P7alsn7sI_6_1bDihxBA5S4Sen4jf2k,4937
|
|
24
24
|
empathy_healthcare_plugin/__init__.py,sha256=4NioL1_86UXzkd-QNkQZUSZ8rKTQGSP0TC9VXP32kQs,295
|
|
25
25
|
empathy_healthcare_plugin/monitors/__init__.py,sha256=Udp8qfZR504QAq5_eQjvtIaE7v06Yguc7nuF40KllQc,196
|
|
26
26
|
empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py,sha256=MWE5t8tW9HWZn_SNo-inx8-0nhdTNGhbcB8ZeDWyXa0,11648
|
|
@@ -100,7 +100,7 @@ empathy_os/agent_monitoring.py,sha256=s4seLC_J4AtQ3PYWrRPO8YHM-Fbm0Q36kPEdlTHf2H
|
|
|
100
100
|
empathy_os/cache_monitor.py,sha256=DTR8xr9d63czGzzdfrBFWp8hkoWPFsL-hpihPGmkbEc,11072
|
|
101
101
|
empathy_os/cache_stats.py,sha256=rWJPBNFEfhuLwKYKy89D_Qa9GPIyVso2jdCKp_cdJhI,10232
|
|
102
102
|
empathy_os/cli.py,sha256=gr9cUowOsvsfqQzhsLPNCny1tpgJtg1vP6C2NNq8vV0,128006
|
|
103
|
-
empathy_os/cli_unified.py,sha256=
|
|
103
|
+
empathy_os/cli_unified.py,sha256=mDIPbRvaNJNCyD2-LC51z8OsusXNuXP9-FwvamfgXxU,48422
|
|
104
104
|
empathy_os/config.py,sha256=jsFQuXpZP_jt6UrZtfLlkBZwPUSNbnW5VVtMS5JIhbA,16276
|
|
105
105
|
empathy_os/coordination.py,sha256=E2HvHxKk1xbYswtgxhnVKB6DRxfXUV5pCt-XWHOvNKM,28509
|
|
106
106
|
empathy_os/core.py,sha256=PvrPs8JQPwQjPZZQj6zy6xQTFGHKziaeRxCIlIs3iHA,52951
|
|
@@ -142,16 +142,17 @@ empathy_os/hot_reload/integration.py,sha256=mBhQgkV266Z753WVuuyMEcm0J25DzSsutQPw
|
|
|
142
142
|
empathy_os/hot_reload/reloader.py,sha256=akqz5t9nn5kc-yj1Dj2NuyPO1p1cWaAhUf-CVlr0XRE,9365
|
|
143
143
|
empathy_os/hot_reload/watcher.py,sha256=l0dZmfDM5RaCZm7nT8qutPI4fXScrS9_QoJ_pdCdOoY,5198
|
|
144
144
|
empathy_os/hot_reload/websocket.py,sha256=DFJlu2gK3hi5R99J05By7RGlfIJDPLa555VZtzUJxUE,5088
|
|
145
|
-
empathy_os/memory/__init__.py,sha256=
|
|
145
|
+
empathy_os/memory/__init__.py,sha256=TwdCTcd_7HuIB5XDh-4iP1lddntAaaD_Mb1Rngcs8sw,5400
|
|
146
146
|
empathy_os/memory/claude_memory.py,sha256=IIwm3su_vyyyoLy4NrpwVk96KLnIgq1A_TfBhjcUZk4,14878
|
|
147
147
|
empathy_os/memory/config.py,sha256=EoBBZLgyY5sHT3kLeyWjyI4b6hRA3Xiaoo3xdMLLGos,6380
|
|
148
148
|
empathy_os/memory/control_panel.py,sha256=ylU2RODUIXQSMhBLcqPI5KkOAOpcmuABVcd2AleeSaw,47334
|
|
149
|
+
empathy_os/memory/cross_session.py,sha256=3cZl_4QeK63v-JMhOSCRJJ9d-ea2yb0azFW2yXvOt4o,26870
|
|
149
150
|
empathy_os/memory/edges.py,sha256=ljku2CYeetJ7qDnQUJobrPZdBaYFxkn_PfGSNa9sVDE,5891
|
|
150
151
|
empathy_os/memory/graph.py,sha256=Up4PCG8BbK5fmGym7rNEPZsCNjS7TQ3_F9-S6-mS2L4,18820
|
|
151
152
|
empathy_os/memory/long_term.py,sha256=dMKL3a3lZgc5bq7eQAUMp4gPwq-6R6k62M5yDOcbSrw,50882
|
|
152
153
|
empathy_os/memory/nodes.py,sha256=lVLN9pp8cFSBrO2Nh8d0zTOglM3QBaYCtwfO5P8dryc,4752
|
|
153
154
|
empathy_os/memory/redis_bootstrap.py,sha256=G71loEE2LTcn0BCp_mN96Bk37ygFz1ImORiLoEmg9jA,16508
|
|
154
|
-
empathy_os/memory/short_term.py,sha256=
|
|
155
|
+
empathy_os/memory/short_term.py,sha256=wBRb7LPQjyAYqKCZFBZv8KlncwAi0zeuymJE_NkZ0DY,78467
|
|
155
156
|
empathy_os/memory/summary_index.py,sha256=7m_m2xH3KMBJWRJFvk3hAws_tgPD4VCfFBxwAbV9fCo,20777
|
|
156
157
|
empathy_os/memory/unified.py,sha256=L5yZiMOUmrJSKjkOtW5eB0DV9ONRwx3-1XBzFCLcUNo,29168
|
|
157
158
|
empathy_os/memory/security/__init__.py,sha256=f_t-pFO1aHOE8uFJ0icGaCt2xCvWx-bFxBcv9U3Cu3Q,868
|
|
@@ -161,15 +162,15 @@ empathy_os/memory/security/secrets_detector.py,sha256=bJsXTD95yEnfShDMxvCndzF8X7
|
|
|
161
162
|
empathy_os/memory/storage/__init__.py,sha256=sPLdecYJ1z6nZTIl8gmbozjdCPp0SZLKsKoi8L1xhcE,480
|
|
162
163
|
empathy_os/meta_workflows/__init__.py,sha256=REUdSgr5kRxPuzj1R3qy50_BEdImoNOry_UNwn2jRYo,1845
|
|
163
164
|
empathy_os/meta_workflows/agent_creator.py,sha256=f2Bc_Qm4bj7DFpGzhDf41RnUK4rG4jQRpRWYiQ_AdjE,8061
|
|
164
|
-
empathy_os/meta_workflows/builtin_templates.py,sha256=
|
|
165
|
-
empathy_os/meta_workflows/cli_meta_workflows.py,sha256=
|
|
165
|
+
empathy_os/meta_workflows/builtin_templates.py,sha256=5yL7hEKi7hu20jQK3PxJkGfwppyqdEokJiJMnTzTiXk,20722
|
|
166
|
+
empathy_os/meta_workflows/cli_meta_workflows.py,sha256=ICKl50NI9K5RafWmUwvji_bk8xFyHscEo_3e0LALLOQ,58750
|
|
166
167
|
empathy_os/meta_workflows/form_engine.py,sha256=tUeSU_TofTS7ZjhWL5tIw4DxrleaHfFQf2mMDI4IaMg,10877
|
|
167
168
|
empathy_os/meta_workflows/intent_detector.py,sha256=heWc6nm-EyMz-Ru2TfaNnWSLqduhOxfTVK80Plf96y4,10126
|
|
168
169
|
empathy_os/meta_workflows/models.py,sha256=jtuAgSuY-vHbjqVOo4AIoq1SXfp-DxUhPyAcmwqjbcI,18909
|
|
169
170
|
empathy_os/meta_workflows/pattern_learner.py,sha256=9DA6L39zu88ohu5zC9PmmJPaIb15of6GwFP7qyy1SlE,26529
|
|
170
171
|
empathy_os/meta_workflows/session_context.py,sha256=WTdhWAKHq6cLJBLHT-jwjxOwQyUPId_F8GPjQlI7gvY,12366
|
|
171
172
|
empathy_os/meta_workflows/template_registry.py,sha256=eFv4rlHcsuk7tnpLCjTNytYipmgyuruW_VZKdXmSXSE,7488
|
|
172
|
-
empathy_os/meta_workflows/workflow.py,sha256=
|
|
173
|
+
empathy_os/meta_workflows/workflow.py,sha256=Sag47KtDACEAcFnQ30Lu834iNHo08GCx5dnMXL0ILcc,36015
|
|
173
174
|
empathy_os/metrics/__init__.py,sha256=b0lkly5Fz89AvvGqV6lLYx8hWlmttL1ZCPuWlHjwXxY,369
|
|
174
175
|
empathy_os/metrics/prompt_metrics.py,sha256=9ZUxM5zJX7v9MxKbDfuP4zWdFKy2sNZO6zRdSELZgTo,6315
|
|
175
176
|
empathy_os/models/__init__.py,sha256=gP9DDNB6kyQJroon182ZYDJ4-IkREkDwRitZg1Xgw_4,3324
|
|
@@ -192,7 +193,7 @@ empathy_os/monitoring/otel_backend.py,sha256=dqCgiw79bYTeVFSRV3raYk-Mpnu8sNoqik3
|
|
|
192
193
|
empathy_os/optimization/__init__.py,sha256=p9dPGmci7MIASss38ctLpKTl_tV8ApkcyPZovE1EUMA,422
|
|
193
194
|
empathy_os/optimization/context_optimizer.py,sha256=lPWXuG7K1OMVNZKOdQT2SlZhLfjMREKSp5pCPQibXpk,8048
|
|
194
195
|
empathy_os/orchestration/__init__.py,sha256=BuIuXDQ2MWPOIkhVkjFCkKjbiDwAqCmrL096ou2NYFE,876
|
|
195
|
-
empathy_os/orchestration/agent_templates.py,sha256=
|
|
196
|
+
empathy_os/orchestration/agent_templates.py,sha256=eGT_NeIW3lS64En_2L5QccJ-bocdETk2uu1T3v74Dlw,22113
|
|
196
197
|
empathy_os/orchestration/config_store.py,sha256=TZLjzCr1g0nAP1eEZA9fMUy3OjF6XsWIQaJnX_PpLDY,16774
|
|
197
198
|
empathy_os/orchestration/execution_strategies.py,sha256=PRlCJkHgITS4Kuqb6Etk28Yk2wb-ReyBFodfVM87s3g,57002
|
|
198
199
|
empathy_os/orchestration/meta_orchestrator.py,sha256=lFyqXat7wULVzNkED2Uxst5Bol-JPOgUHU5U8LevIgM,21591
|
|
@@ -394,8 +395,8 @@ workflow_scaffolding/__init__.py,sha256=UpX5vjjjPjIaAKyIV1D4GxJzLUZy5DzdzgSkePYM
|
|
|
394
395
|
workflow_scaffolding/__main__.py,sha256=0qspuNoadTDqyskXTlT8Sahqau-XIxN35NHTSGVW6z4,236
|
|
395
396
|
workflow_scaffolding/cli.py,sha256=yLgvMsPbqI-LHt7UKXMuj-Dc0-44EqWiChldysrw1YQ,6763
|
|
396
397
|
workflow_scaffolding/generator.py,sha256=9eEmm324kVzf8BCtXEML090pyke06o0U7aGATzZIaPM,8869
|
|
397
|
-
empathy_framework-4.
|
|
398
|
-
empathy_framework-4.
|
|
399
|
-
empathy_framework-4.
|
|
400
|
-
empathy_framework-4.
|
|
401
|
-
empathy_framework-4.
|
|
398
|
+
empathy_framework-4.5.0.dist-info/METADATA,sha256=_xBGJo7LcvILbPii3pT-tJ_Pj6Pt1pxYOKh7sfzZSs0,56221
|
|
399
|
+
empathy_framework-4.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
400
|
+
empathy_framework-4.5.0.dist-info/entry_points.txt,sha256=41rM9JgcKpkU8dr4VvPcbiPy2GQX68cEj10l3XMH0FQ,1519
|
|
401
|
+
empathy_framework-4.5.0.dist-info/top_level.txt,sha256=wrNU1aVMutVDACer58H-udv0P_171Dv6z_42sZtZ-xM,124
|
|
402
|
+
empathy_framework-4.5.0.dist-info/RECORD,,
|
empathy_os/cli_unified.py
CHANGED
|
@@ -831,6 +831,263 @@ def telemetry_reset(
|
|
|
831
831
|
subprocess.run(args, check=False)
|
|
832
832
|
|
|
833
833
|
|
|
834
|
+
# =============================================================================
|
|
835
|
+
# SERVICE SUBCOMMAND GROUP (Cross-Session Communication)
|
|
836
|
+
# =============================================================================
|
|
837
|
+
|
|
838
|
+
service_app = typer.Typer(help="Cross-session coordination service")
|
|
839
|
+
app.add_typer(service_app, name="service")
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
@service_app.command("start")
|
|
843
|
+
def service_start(
|
|
844
|
+
daemon: bool = typer.Option(False, "--daemon", "-d", help="Run as daemon (auto-start on connect)"),
|
|
845
|
+
):
|
|
846
|
+
"""Start the cross-session coordination service.
|
|
847
|
+
|
|
848
|
+
The service enables communication between multiple Claude Code sessions
|
|
849
|
+
via Redis-backed short-term memory.
|
|
850
|
+
|
|
851
|
+
Requires Redis to be running (empathy memory start).
|
|
852
|
+
"""
|
|
853
|
+
from empathy_os.redis_config import get_redis_memory
|
|
854
|
+
|
|
855
|
+
try:
|
|
856
|
+
memory = get_redis_memory()
|
|
857
|
+
|
|
858
|
+
if memory.use_mock:
|
|
859
|
+
console.print("[yellow]⚠️ Cross-session service requires Redis.[/yellow]")
|
|
860
|
+
console.print("[dim]Start Redis with: empathy memory start[/dim]")
|
|
861
|
+
console.print("[dim]Or set REDIS_HOST/REDIS_PORT environment variables[/dim]")
|
|
862
|
+
raise typer.Exit(code=1)
|
|
863
|
+
|
|
864
|
+
from empathy_os.memory.cross_session import BackgroundService
|
|
865
|
+
|
|
866
|
+
service = BackgroundService(memory, auto_start_on_connect=daemon)
|
|
867
|
+
|
|
868
|
+
if service.start():
|
|
869
|
+
console.print("[bold green]✅ Cross-session service started[/bold green]")
|
|
870
|
+
status = service.get_status()
|
|
871
|
+
console.print(f"[dim]Agent ID: {status['agent_id']}[/dim]")
|
|
872
|
+
console.print(f"[dim]Active sessions: {status['active_sessions']}[/dim]")
|
|
873
|
+
|
|
874
|
+
if daemon:
|
|
875
|
+
console.print("[dim]Running in daemon mode (press Ctrl+C to stop)[/dim]")
|
|
876
|
+
try:
|
|
877
|
+
import time
|
|
878
|
+
while service.is_running:
|
|
879
|
+
time.sleep(1)
|
|
880
|
+
except KeyboardInterrupt:
|
|
881
|
+
service.stop()
|
|
882
|
+
console.print("\n[dim]Service stopped[/dim]")
|
|
883
|
+
else:
|
|
884
|
+
console.print("[yellow]⚠️ Service already running (or couldn't acquire lock)[/yellow]")
|
|
885
|
+
console.print("[dim]Use 'empathy service status' to check[/dim]")
|
|
886
|
+
|
|
887
|
+
except Exception as e:
|
|
888
|
+
console.print(f"[bold red]Error:[/bold red] {e}")
|
|
889
|
+
raise typer.Exit(code=1)
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
@service_app.command("stop")
|
|
893
|
+
def service_stop():
|
|
894
|
+
"""Stop the cross-session coordination service."""
|
|
895
|
+
from empathy_os.redis_config import get_redis_memory
|
|
896
|
+
|
|
897
|
+
try:
|
|
898
|
+
memory = get_redis_memory()
|
|
899
|
+
|
|
900
|
+
if memory.use_mock:
|
|
901
|
+
console.print("[yellow]No service to stop (mock mode)[/yellow]")
|
|
902
|
+
return
|
|
903
|
+
|
|
904
|
+
# Check if service is running and signal it to stop
|
|
905
|
+
client = memory._client
|
|
906
|
+
if client:
|
|
907
|
+
from empathy_os.memory.cross_session import KEY_SERVICE_LOCK
|
|
908
|
+
|
|
909
|
+
lock_holder = client.get(KEY_SERVICE_LOCK)
|
|
910
|
+
if lock_holder:
|
|
911
|
+
client.delete(KEY_SERVICE_LOCK)
|
|
912
|
+
console.print("[green]✅ Service stop signal sent[/green]")
|
|
913
|
+
else:
|
|
914
|
+
console.print("[dim]No service currently running[/dim]")
|
|
915
|
+
else:
|
|
916
|
+
console.print("[yellow]Redis not connected[/yellow]")
|
|
917
|
+
|
|
918
|
+
except Exception as e:
|
|
919
|
+
console.print(f"[bold red]Error:[/bold red] {e}")
|
|
920
|
+
raise typer.Exit(code=1)
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
@service_app.command("status")
|
|
924
|
+
def service_status(
|
|
925
|
+
json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
|
|
926
|
+
):
|
|
927
|
+
"""Show cross-session service status and active sessions."""
|
|
928
|
+
import json as json_mod
|
|
929
|
+
|
|
930
|
+
from empathy_os.redis_config import get_redis_memory
|
|
931
|
+
|
|
932
|
+
try:
|
|
933
|
+
memory = get_redis_memory()
|
|
934
|
+
|
|
935
|
+
if memory.use_mock:
|
|
936
|
+
status = {
|
|
937
|
+
"mode": "mock",
|
|
938
|
+
"cross_session_available": False,
|
|
939
|
+
"message": "Cross-session requires Redis",
|
|
940
|
+
}
|
|
941
|
+
if json_output:
|
|
942
|
+
console.print(json_mod.dumps(status, indent=2))
|
|
943
|
+
else:
|
|
944
|
+
console.print("[yellow]⚠️ Mock mode - cross-session not available[/yellow]")
|
|
945
|
+
console.print("[dim]Start Redis: empathy memory start[/dim]")
|
|
946
|
+
return
|
|
947
|
+
|
|
948
|
+
from empathy_os.memory.cross_session import (
|
|
949
|
+
KEY_ACTIVE_AGENTS,
|
|
950
|
+
KEY_SERVICE_HEARTBEAT,
|
|
951
|
+
KEY_SERVICE_LOCK,
|
|
952
|
+
SessionInfo,
|
|
953
|
+
)
|
|
954
|
+
|
|
955
|
+
client = memory._client
|
|
956
|
+
if not client:
|
|
957
|
+
console.print("[red]Redis not connected[/red]")
|
|
958
|
+
raise typer.Exit(code=1)
|
|
959
|
+
|
|
960
|
+
# Check service status
|
|
961
|
+
service_lock = client.get(KEY_SERVICE_LOCK)
|
|
962
|
+
service_heartbeat = client.get(KEY_SERVICE_HEARTBEAT)
|
|
963
|
+
|
|
964
|
+
# Get active sessions
|
|
965
|
+
all_agents = client.hgetall(KEY_ACTIVE_AGENTS)
|
|
966
|
+
sessions = []
|
|
967
|
+
for agent_id, data in all_agents.items():
|
|
968
|
+
try:
|
|
969
|
+
if isinstance(agent_id, bytes):
|
|
970
|
+
agent_id = agent_id.decode()
|
|
971
|
+
if isinstance(data, bytes):
|
|
972
|
+
data = data.decode()
|
|
973
|
+
info = SessionInfo.from_dict(json_mod.loads(data))
|
|
974
|
+
if not info.is_stale:
|
|
975
|
+
sessions.append(info.to_dict())
|
|
976
|
+
except (json_mod.JSONDecodeError, KeyError, ValueError):
|
|
977
|
+
pass
|
|
978
|
+
|
|
979
|
+
status = {
|
|
980
|
+
"mode": "redis",
|
|
981
|
+
"cross_session_available": True,
|
|
982
|
+
"service_running": bool(service_lock),
|
|
983
|
+
"service_pid": service_lock.decode() if isinstance(service_lock, bytes) else service_lock,
|
|
984
|
+
"last_heartbeat": service_heartbeat.decode() if isinstance(service_heartbeat, bytes) else service_heartbeat,
|
|
985
|
+
"active_sessions": len(sessions),
|
|
986
|
+
"sessions": sessions,
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
if json_output:
|
|
990
|
+
console.print(json_mod.dumps(status, indent=2))
|
|
991
|
+
else:
|
|
992
|
+
console.print()
|
|
993
|
+
console.print("[bold cyan]CROSS-SESSION SERVICE STATUS[/bold cyan]")
|
|
994
|
+
console.print("=" * 50)
|
|
995
|
+
console.print()
|
|
996
|
+
|
|
997
|
+
if status["service_running"]:
|
|
998
|
+
console.print("[green]● Service Running[/green]")
|
|
999
|
+
console.print(f"[dim] PID: {status['service_pid']}[/dim]")
|
|
1000
|
+
if status["last_heartbeat"]:
|
|
1001
|
+
console.print(f"[dim] Last heartbeat: {status['last_heartbeat']}[/dim]")
|
|
1002
|
+
else:
|
|
1003
|
+
console.print("[yellow]○ Service Not Running[/yellow]")
|
|
1004
|
+
console.print("[dim] Start with: empathy service start[/dim]")
|
|
1005
|
+
|
|
1006
|
+
console.print()
|
|
1007
|
+
console.print(f"[bold]Active Sessions:[/bold] {status['active_sessions']}")
|
|
1008
|
+
|
|
1009
|
+
if sessions:
|
|
1010
|
+
console.print()
|
|
1011
|
+
for session in sessions:
|
|
1012
|
+
session_type = session.get("session_type", "unknown")
|
|
1013
|
+
agent_id = session.get("agent_id", "unknown")
|
|
1014
|
+
tier = session.get("access_tier", "unknown")
|
|
1015
|
+
emoji = "🤖" if session_type == "claude" else "⚙️" if session_type == "service" else "👷"
|
|
1016
|
+
console.print(f" {emoji} {agent_id}")
|
|
1017
|
+
console.print(f" [dim]Type: {session_type} | Tier: {tier}[/dim]")
|
|
1018
|
+
|
|
1019
|
+
console.print()
|
|
1020
|
+
console.print("=" * 50)
|
|
1021
|
+
|
|
1022
|
+
except Exception as e:
|
|
1023
|
+
console.print(f"[bold red]Error:[/bold red] {e}")
|
|
1024
|
+
raise typer.Exit(code=1)
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
@service_app.command("sessions")
|
|
1028
|
+
def service_sessions():
|
|
1029
|
+
"""List all active cross-session agents."""
|
|
1030
|
+
import json as json_mod
|
|
1031
|
+
|
|
1032
|
+
from empathy_os.redis_config import get_redis_memory
|
|
1033
|
+
|
|
1034
|
+
try:
|
|
1035
|
+
memory = get_redis_memory()
|
|
1036
|
+
|
|
1037
|
+
if memory.use_mock:
|
|
1038
|
+
console.print("[yellow]No sessions (mock mode)[/yellow]")
|
|
1039
|
+
return
|
|
1040
|
+
|
|
1041
|
+
from empathy_os.memory.cross_session import KEY_ACTIVE_AGENTS, SessionInfo
|
|
1042
|
+
|
|
1043
|
+
client = memory._client
|
|
1044
|
+
if not client:
|
|
1045
|
+
console.print("[red]Redis not connected[/red]")
|
|
1046
|
+
return
|
|
1047
|
+
|
|
1048
|
+
all_agents = client.hgetall(KEY_ACTIVE_AGENTS)
|
|
1049
|
+
|
|
1050
|
+
if not all_agents:
|
|
1051
|
+
console.print("[dim]No active sessions[/dim]")
|
|
1052
|
+
return
|
|
1053
|
+
|
|
1054
|
+
console.print()
|
|
1055
|
+
console.print("[bold]Active Cross-Session Agents[/bold]")
|
|
1056
|
+
console.print("-" * 60)
|
|
1057
|
+
|
|
1058
|
+
for agent_id, data in all_agents.items():
|
|
1059
|
+
try:
|
|
1060
|
+
if isinstance(agent_id, bytes):
|
|
1061
|
+
agent_id = agent_id.decode()
|
|
1062
|
+
if isinstance(data, bytes):
|
|
1063
|
+
data = data.decode()
|
|
1064
|
+
|
|
1065
|
+
info = SessionInfo.from_dict(json_mod.loads(data))
|
|
1066
|
+
|
|
1067
|
+
if info.is_stale:
|
|
1068
|
+
status_str = "[red]STALE[/red]"
|
|
1069
|
+
else:
|
|
1070
|
+
status_str = "[green]ACTIVE[/green]"
|
|
1071
|
+
|
|
1072
|
+
console.print(f"\n{agent_id}")
|
|
1073
|
+
console.print(f" Status: {status_str}")
|
|
1074
|
+
console.print(f" Type: {info.session_type.value}")
|
|
1075
|
+
console.print(f" Tier: {info.access_tier.name}")
|
|
1076
|
+
console.print(f" Started: {info.started_at.isoformat()}")
|
|
1077
|
+
console.print(f" Last heartbeat: {info.last_heartbeat.isoformat()}")
|
|
1078
|
+
if info.capabilities:
|
|
1079
|
+
console.print(f" Capabilities: {', '.join(info.capabilities)}")
|
|
1080
|
+
|
|
1081
|
+
except (json_mod.JSONDecodeError, KeyError, ValueError) as e:
|
|
1082
|
+
console.print(f"\n{agent_id}: [red]Invalid data[/red] - {e}")
|
|
1083
|
+
|
|
1084
|
+
console.print()
|
|
1085
|
+
|
|
1086
|
+
except Exception as e:
|
|
1087
|
+
console.print(f"[bold red]Error:[/bold red] {e}")
|
|
1088
|
+
raise typer.Exit(code=1)
|
|
1089
|
+
|
|
1090
|
+
|
|
834
1091
|
# =============================================================================
|
|
835
1092
|
# META-WORKFLOW SUBCOMMAND GROUP
|
|
836
1093
|
# =============================================================================
|
|
@@ -1065,6 +1322,11 @@ def cheatsheet():
|
|
|
1065
1322
|
empathy memory start Start Redis server
|
|
1066
1323
|
empathy memory patterns List stored patterns
|
|
1067
1324
|
|
|
1325
|
+
[bold]Cross-Session Service[/bold]
|
|
1326
|
+
empathy service start Start coordination service
|
|
1327
|
+
empathy service status Show service & sessions
|
|
1328
|
+
empathy service sessions List active agents
|
|
1329
|
+
|
|
1068
1330
|
[bold]Provider Config[/bold]
|
|
1069
1331
|
empathy provider Show current config
|
|
1070
1332
|
empathy provider --set hybrid Use best-of-breed
|
empathy_os/memory/__init__.py
CHANGED
|
@@ -67,6 +67,18 @@ from .config import check_redis_connection, get_railway_redis, get_redis_config,
|
|
|
67
67
|
# Control Panel
|
|
68
68
|
from .control_panel import ControlPanelConfig, MemoryControlPanel, MemoryStats
|
|
69
69
|
|
|
70
|
+
# Cross-session communication
|
|
71
|
+
from .cross_session import (
|
|
72
|
+
BackgroundService,
|
|
73
|
+
ConflictResult,
|
|
74
|
+
ConflictStrategy,
|
|
75
|
+
CrossSessionCoordinator,
|
|
76
|
+
SessionInfo,
|
|
77
|
+
SessionType,
|
|
78
|
+
check_redis_cross_session_support,
|
|
79
|
+
generate_agent_id,
|
|
80
|
+
)
|
|
81
|
+
|
|
70
82
|
# Memory Graph (Cross-Wizard Intelligence)
|
|
71
83
|
from .edges import REVERSE_EDGE_TYPES, WIZARD_EDGE_PATTERNS, Edge, EdgeType
|
|
72
84
|
from .graph import MemoryGraph
|
|
@@ -132,6 +144,8 @@ __all__ = [
|
|
|
132
144
|
"AuditEvent",
|
|
133
145
|
# Security - Audit
|
|
134
146
|
"AuditLogger",
|
|
147
|
+
# Cross-session communication
|
|
148
|
+
"BackgroundService",
|
|
135
149
|
"BugNode",
|
|
136
150
|
"Classification",
|
|
137
151
|
"ClassificationRules",
|
|
@@ -139,9 +153,12 @@ __all__ = [
|
|
|
139
153
|
"ClaudeMemoryConfig",
|
|
140
154
|
"ClaudeMemoryLoader",
|
|
141
155
|
"ConflictContext",
|
|
156
|
+
"ConflictResult",
|
|
157
|
+
"ConflictStrategy",
|
|
142
158
|
"ControlPanelConfig",
|
|
143
159
|
# Conversation Summary Index
|
|
144
160
|
"ConversationSummaryIndex",
|
|
161
|
+
"CrossSessionCoordinator",
|
|
145
162
|
"Edge",
|
|
146
163
|
"EdgeType",
|
|
147
164
|
"EncryptionManager",
|
|
@@ -176,6 +193,8 @@ __all__ = [
|
|
|
176
193
|
"SecurePattern",
|
|
177
194
|
"SecurityError",
|
|
178
195
|
"SecurityViolation",
|
|
196
|
+
"SessionInfo",
|
|
197
|
+
"SessionType",
|
|
179
198
|
"Severity",
|
|
180
199
|
"StagedPattern",
|
|
181
200
|
"TTLStrategy",
|
|
@@ -183,9 +202,11 @@ __all__ = [
|
|
|
183
202
|
"UnifiedMemory",
|
|
184
203
|
"VulnerabilityNode",
|
|
185
204
|
"check_redis_connection",
|
|
205
|
+
"check_redis_cross_session_support",
|
|
186
206
|
"detect_secrets",
|
|
187
207
|
# Redis Bootstrap
|
|
188
208
|
"ensure_redis",
|
|
209
|
+
"generate_agent_id",
|
|
189
210
|
"get_railway_redis",
|
|
190
211
|
"get_redis_config",
|
|
191
212
|
# Configuration
|