empathy-framework 3.9.2__py3-none-any.whl → 3.9.3__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-3.9.2.dist-info → empathy_framework-3.9.3.dist-info}/METADATA +1 -1
- {empathy_framework-3.9.2.dist-info → empathy_framework-3.9.3.dist-info}/RECORD +27 -27
- empathy_llm_toolkit/agent_factory/crews/health_check.py +36 -29
- empathy_os/__init__.py +1 -1
- empathy_os/cli_unified.py +85 -1
- empathy_os/config.py +7 -4
- empathy_os/hot_reload/integration.py +2 -1
- empathy_os/hot_reload/watcher.py +8 -4
- empathy_os/hot_reload/websocket.py +2 -1
- empathy_os/test_generator/generator.py +1 -1
- empathy_os/tier_recommender.py +3 -3
- empathy_os/workflows/base.py +5 -2
- empathy_os/workflows/tier_tracking.py +1 -1
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +9 -6
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +1 -1
- empathy_software_plugin/wizards/debugging/config_loaders.py +6 -2
- empathy_software_plugin/wizards/debugging/language_patterns.py +4 -2
- empathy_software_plugin/wizards/debugging/linter_parsers.py +1 -1
- empathy_software_plugin/wizards/performance/profiler_parsers.py +7 -7
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +1 -1
- empathy_software_plugin/wizards/security_analysis_wizard.py +2 -2
- empathy_software_plugin/wizards/testing/quality_analyzer.py +3 -9
- empathy_software_plugin/wizards/testing/test_suggester.py +1 -1
- {empathy_framework-3.9.2.dist-info → empathy_framework-3.9.3.dist-info}/WHEEL +0 -0
- {empathy_framework-3.9.2.dist-info → empathy_framework-3.9.3.dist-info}/entry_points.txt +0 -0
- {empathy_framework-3.9.2.dist-info → empathy_framework-3.9.3.dist-info}/licenses/LICENSE +0 -0
- {empathy_framework-3.9.2.dist-info → empathy_framework-3.9.3.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: empathy-framework
|
|
3
|
-
Version: 3.9.
|
|
3
|
+
Version: 3.9.3
|
|
4
4
|
Summary: AI collaboration framework with intelligent caching (up to 57% cache hit rate), tier routing (34-86% cost savings depending on task complexity), XML-enhanced prompts, persistent memory, CrewAI integration, and multi-agent orchestration. Includes HIPAA-compliant healthcare wizards.
|
|
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-3.9.
|
|
23
|
+
empathy_framework-3.9.3.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=GkNh2Yuw9cvuKuPh3mriWtKJZFq_sTxBD7Ci8lFV9gQ,11620
|
|
@@ -64,7 +64,7 @@ empathy_llm_toolkit/agent_factory/adapters/native.py,sha256=lCpR6kvVIlTzbYs3jgMD
|
|
|
64
64
|
empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py,sha256=Qy4_SCQOJU-CUvUIwQoOR66Ji37ICI0CNzy7Oc8Db7c,13326
|
|
65
65
|
empathy_llm_toolkit/agent_factory/crews/__init__.py,sha256=U3D84fRfZb2aqBHKKTuK1fPPzWRx5fcfvpikDGuZnNw,1582
|
|
66
66
|
empathy_llm_toolkit/agent_factory/crews/code_review.py,sha256=deAWBABYd9dhyJ8AiZLo1ZEtxTYzpVrzMI3k3ATKHn0,39323
|
|
67
|
-
empathy_llm_toolkit/agent_factory/crews/health_check.py,sha256=
|
|
67
|
+
empathy_llm_toolkit/agent_factory/crews/health_check.py,sha256=qJlUVSXaxuJBexa14L3jCWrNeHfiYoLgx0VruSPU6_I,43927
|
|
68
68
|
empathy_llm_toolkit/agent_factory/crews/refactoring.py,sha256=kt-PtUxOr4EGa8psnaMaqxoqiw74opWhdhncmu9h5B0,40373
|
|
69
69
|
empathy_llm_toolkit/agent_factory/crews/security_audit.py,sha256=Fuv98e-zDNzqqmGGwtEiSYgyBIj3YxdBGL8zui28X1M,36527
|
|
70
70
|
empathy_llm_toolkit/cli/__init__.py,sha256=-U-ESXUHamUV1vL-4aBfPFdyBysd4PzeiS1W65bDv2U,177
|
|
@@ -93,11 +93,11 @@ empathy_llm_toolkit/wizards/healthcare_wizard.py,sha256=zIdeXqS5jPTRFhUTi0MyPYqh
|
|
|
93
93
|
empathy_llm_toolkit/wizards/patient_assessment_README.md,sha256=DInK_x7LgM8Qi9YSHgXtm7_sQupioJRf0M43_vml4ck,1586
|
|
94
94
|
empathy_llm_toolkit/wizards/patient_assessment_wizard.py,sha256=dsvoOq0AYCBigmn6HPoaSBnBPk9YV7IzAFZkJYx1iZQ,5423
|
|
95
95
|
empathy_llm_toolkit/wizards/technology_wizard.py,sha256=8hQirzzGQp7UVtj1hFCoaoLLtqAtx9HFf4mdUWV1xH0,7533
|
|
96
|
-
empathy_os/__init__.py,sha256=
|
|
96
|
+
empathy_os/__init__.py,sha256=zAvie0wQFlSpv7thmNNtdrPy0YY1NUaQfb1oD_hKmns,5896
|
|
97
97
|
empathy_os/agent_monitoring.py,sha256=s4seLC_J4AtQ3PYWrRPO8YHM-Fbm0Q36kPEdlTHf2HI,13375
|
|
98
98
|
empathy_os/cli.py,sha256=wT131LYtNskfOu8thDjrv724UXyjaRUuuFmylZqr_YM,110271
|
|
99
|
-
empathy_os/cli_unified.py,sha256=
|
|
100
|
-
empathy_os/config.py,sha256=
|
|
99
|
+
empathy_os/cli_unified.py,sha256=M-fLRibRlsDB1kcJsXOXHMTOF4UDFKWZE9mK1zyU7Hw,26452
|
|
100
|
+
empathy_os/config.py,sha256=jsFQuXpZP_jt6UrZtfLlkBZwPUSNbnW5VVtMS5JIhbA,16276
|
|
101
101
|
empathy_os/coordination.py,sha256=E2HvHxKk1xbYswtgxhnVKB6DRxfXUV5pCt-XWHOvNKM,28509
|
|
102
102
|
empathy_os/core.py,sha256=PvrPs8JQPwQjPZZQj6zy6xQTFGHKziaeRxCIlIs3iHA,52951
|
|
103
103
|
empathy_os/cost_tracker.py,sha256=Cd07k2ecpYH2Xq968Ed1YsyqvEXQ5Cn6RqoAENVEE_k,12524
|
|
@@ -114,7 +114,7 @@ empathy_os/platform_utils.py,sha256=VXv3IgK0ykKCBJlsxB4xSwJQteKu3Ds-1UDmHl9fHmo,
|
|
|
114
114
|
empathy_os/redis_config.py,sha256=6khRnNSA3gljmrH4w38h5nrVUfA8DvXRFbDXAJVzl6o,9754
|
|
115
115
|
empathy_os/redis_memory.py,sha256=e8cqZtcnVGLCAI4sgv5zzoZB9xo-UPwJQ8gzbEKWnwM,23119
|
|
116
116
|
empathy_os/templates.py,sha256=uSJQbHE55R8kuuvEyPLxTxFPXstybrsKvGOhhiy93sE,17047
|
|
117
|
-
empathy_os/tier_recommender.py,sha256=
|
|
117
|
+
empathy_os/tier_recommender.py,sha256=LD65r_p7uhKU-18vgLdy78Pe5HiteB6kHrnTAcTqYfQ,14188
|
|
118
118
|
empathy_os/trust_building.py,sha256=plCmSQSzgU2ryMMmJqawQ4l7fIoFmwsx53BDYQv4jhU,18836
|
|
119
119
|
empathy_os/wizard_factory_cli.py,sha256=BMOOTIKf9bAVOuvtHi_HgkIBqnLpLBCkuvA51kxV9iI,4756
|
|
120
120
|
empathy_os/workflow_commands.py,sha256=PqzpsXVB7Vk2raMbSYTDICETb1PZJ4u7IXb7HQdKSYo,25174
|
|
@@ -133,10 +133,10 @@ empathy_os/dashboard/server.py,sha256=dFJCtZb5xfOvY4te5WUqINJc5pZSYsJEdWyXJlDTvs
|
|
|
133
133
|
empathy_os/hot_reload/README.md,sha256=FnQWSX-dfTIJvXHjjiWRWBjMK2DR-eyOfDHJlGIzm0o,10406
|
|
134
134
|
empathy_os/hot_reload/__init__.py,sha256=RZ4Ow7Than1w-FWkqOqkDLpBwUn-AUidv5dKyfcSCI0,1628
|
|
135
135
|
empathy_os/hot_reload/config.py,sha256=y6H36dmkTBmc6rbC8hnlK_QrmIEGFBnf-xxpCme70S8,2322
|
|
136
|
-
empathy_os/hot_reload/integration.py,sha256=
|
|
136
|
+
empathy_os/hot_reload/integration.py,sha256=mBhQgkV266Z753WVuuyMEcm0J25DzSsutQPwZAskdl4,6721
|
|
137
137
|
empathy_os/hot_reload/reloader.py,sha256=akqz5t9nn5kc-yj1Dj2NuyPO1p1cWaAhUf-CVlr0XRE,9365
|
|
138
|
-
empathy_os/hot_reload/watcher.py,sha256=
|
|
139
|
-
empathy_os/hot_reload/websocket.py,sha256=
|
|
138
|
+
empathy_os/hot_reload/watcher.py,sha256=l0dZmfDM5RaCZm7nT8qutPI4fXScrS9_QoJ_pdCdOoY,5198
|
|
139
|
+
empathy_os/hot_reload/websocket.py,sha256=DFJlu2gK3hi5R99J05By7RGlfIJDPLa555VZtzUJxUE,5088
|
|
140
140
|
empathy_os/memory/__init__.py,sha256=QwxOpVux5AKBBEZRHs7FoE39JVdWlJQ6WCAm00Cy3C8,4908
|
|
141
141
|
empathy_os/memory/claude_memory.py,sha256=IIwm3su_vyyyoLy4NrpwVk96KLnIgq1A_TfBhjcUZk4,14878
|
|
142
142
|
empathy_os/memory/config.py,sha256=EoBBZLgyY5sHT3kLeyWjyI4b6hRA3Xiaoo3xdMLLGos,6380
|
|
@@ -215,7 +215,7 @@ empathy_os/telemetry/usage_tracker.py,sha256=qym1FzvWmUi-61kugASITAUR7Fbjoxi1zQG
|
|
|
215
215
|
empathy_os/test_generator/__init__.py,sha256=d7grN2uxoRqcTsiZAC-kgEad48Z9rDunOZ6TycS3fy4,913
|
|
216
216
|
empathy_os/test_generator/__main__.py,sha256=YY_HE1xg4zKZkHHAd6sSzWvJCvLFOtmpawCrNlGjWAc,345
|
|
217
217
|
empathy_os/test_generator/cli.py,sha256=u8WL1X3reqSYfVGjYiET7fmxqQDIIOzAE5HMQquhl7M,6862
|
|
218
|
-
empathy_os/test_generator/generator.py,sha256=
|
|
218
|
+
empathy_os/test_generator/generator.py,sha256=XCEQFkYJy6R1PfcHsHLJ8Y_0d1fJHaFxLCLY2Ue5xOo,9798
|
|
219
219
|
empathy_os/test_generator/risk_analyzer.py,sha256=5vEncQDmxUXglZBX9-DdCcsz4yjvuY9IhJGjIfTH9fE,7486
|
|
220
220
|
empathy_os/trust/__init__.py,sha256=tJj5h5mYsfdWg_xmnHPonKZfTycYI3QlXDUQSjRLEtE,651
|
|
221
221
|
empathy_os/trust/circuit_breaker.py,sha256=VMuVmH_lZ_RB0E-tjE150Qtbk7WnkLQXc-fp_8NR5AQ,20716
|
|
@@ -228,7 +228,7 @@ empathy_os/workflow_patterns/output.py,sha256=EyioUYeXGQWllZdJXHXv2mLwl7fMwihrEb
|
|
|
228
228
|
empathy_os/workflow_patterns/registry.py,sha256=0U_XT0hdQ5fLHuEJlrvzjaCBUyeWDA675_hEyvHxT0o,7461
|
|
229
229
|
empathy_os/workflow_patterns/structural.py,sha256=v1wbBU0pCQQKdNhPXM_fuPO8ptQCbEC_8X-OKgfhrk8,9432
|
|
230
230
|
empathy_os/workflows/__init__.py,sha256=UYXKvpkaLEAGqnMpUHrdR8TZiqmR8k47lpdEs2cs9B0,12022
|
|
231
|
-
empathy_os/workflows/base.py,sha256=
|
|
231
|
+
empathy_os/workflows/base.py,sha256=iNnF89vEicVicH_azn3p_Cf8LPnhNOmnp9jGXux7ueU,66402
|
|
232
232
|
empathy_os/workflows/bug_predict.py,sha256=Td2XtawwTSqBOOIqlziNXcOt4YRMMeya2W1tFOJKytY,35726
|
|
233
233
|
empathy_os/workflows/code_review.py,sha256=SWNXSuJ2v4to8sZiHSQ2Z06gVCJ10L1LQr77Jf1SUyM,35647
|
|
234
234
|
empathy_os/workflows/code_review_adapters.py,sha256=9aGUDAgE1B1EUJ-Haz2Agwo4RAwY2aqHtNYKEbJq2yc,11065
|
|
@@ -259,7 +259,7 @@ empathy_os/workflows/test_lifecycle.py,sha256=c6UDSd6kOQdCHmaJviwAnUVceVQuSdLNQ9
|
|
|
259
259
|
empathy_os/workflows/test_maintenance.py,sha256=jiMeYX7Qg3CnRU5xW8LuOXnARxV7uqfygDKkIsEgL0s,22941
|
|
260
260
|
empathy_os/workflows/test_maintenance_cli.py,sha256=U8t-1uK9iqEg9RoVXbS27KbhqvbXm30anQH4GbCvKBM,17879
|
|
261
261
|
empathy_os/workflows/test_maintenance_crew.py,sha256=mzV45WZ9ABVgDQk4lWglMBhOCop5c5TzG16cJkWZAV8,28709
|
|
262
|
-
empathy_os/workflows/tier_tracking.py,sha256=
|
|
262
|
+
empathy_os/workflows/tier_tracking.py,sha256=GzQXbUyWCBtDxQczxI8SaKwKURrgULBPWTw5F_wvqTg,14034
|
|
263
263
|
empathy_os/workflows/xml_enhanced_crew.py,sha256=SnPb-LdUNn3MWlm5c_6OB1IWKV_D6XjCsgmi_hRFhuk,9000
|
|
264
264
|
empathy_os/workflows/keyboard_shortcuts/__init__.py,sha256=zPY6KTepKXmLF0xUsqxbH9qztHdVdsCzyY-_PiSnuxk,1116
|
|
265
265
|
empathy_os/workflows/keyboard_shortcuts/generators.py,sha256=qjKU3FPHWYaMP3Pi_HgKaXDUm1wV2dm8W-1ThsAbc7o,12599
|
|
@@ -274,7 +274,7 @@ empathy_software_plugin/plugin.py,sha256=jjIrGOtitOUzmLqfsgML5lsGx7bXaI9WURgucPY
|
|
|
274
274
|
empathy_software_plugin/cli/__init__.py,sha256=YM3lWC69nzp07a7_PoRZ3yqkh-109PzLpwWLacL0YZs,4233
|
|
275
275
|
empathy_software_plugin/cli/inspect.py,sha256=Z1f2bV0TtAUY0uODMjEmoM2zryAsM2mwQEAyRMlmhOE,9413
|
|
276
276
|
empathy_software_plugin/wizards/__init__.py,sha256=rfzUdSjNHRq-mb4xfZgDY57VAafRCCK1jWu2UiUIkjE,1508
|
|
277
|
-
empathy_software_plugin/wizards/advanced_debugging_wizard.py,sha256=
|
|
277
|
+
empathy_software_plugin/wizards/advanced_debugging_wizard.py,sha256=64TSxOXT80Fw_Z3wrFbpMvZ2LKaRF4rkA9UZnVKX99w,14896
|
|
278
278
|
empathy_software_plugin/wizards/agent_orchestration_wizard.py,sha256=iRnHZ_NWhNzinwg_GLzpGpFJukFCctaYGGHWrAZgTYI,21428
|
|
279
279
|
empathy_software_plugin/wizards/ai_collaboration_wizard.py,sha256=63WdxxvPoTeHxdAgmLEh-X2D_jDvpKiHN-TRvUi0jE8,22446
|
|
280
280
|
empathy_software_plugin/wizards/ai_context_wizard.py,sha256=T-LWkozjpZMznlH5fgO1Tjg7Fo2apX7_EZ5KSrl8hrs,18788
|
|
@@ -290,29 +290,29 @@ empathy_software_plugin/wizards/pattern_retriever_wizard.py,sha256=6yue042C8a3K6
|
|
|
290
290
|
empathy_software_plugin/wizards/performance_profiling_wizard.py,sha256=7gPzKi7LOc-eD2dIBMAI1xUVEN3pndMCQcFEs8m4HlM,11631
|
|
291
291
|
empathy_software_plugin/wizards/prompt_engineering_wizard.py,sha256=X7NktPg6zKWn-7KLB2JUGemhZX64dyNgTwxMvKLibIs,17209
|
|
292
292
|
empathy_software_plugin/wizards/rag_pattern_wizard.py,sha256=K5GBwo26RDurRXxxiCmGu7sSGg-Erc-ncDS3hGRoUYM,19138
|
|
293
|
-
empathy_software_plugin/wizards/security_analysis_wizard.py,sha256=
|
|
293
|
+
empathy_software_plugin/wizards/security_analysis_wizard.py,sha256=EelZARa3x5DZjK15tzDIa5XyMRmXEQNhgwdZdfRS6Lc,12332
|
|
294
294
|
empathy_software_plugin/wizards/security_learning_wizard.py,sha256=KLGurDpwMw7tqPRlfnsptd9Hc0xOdVLXiS8Og2Hlv-4,27947
|
|
295
295
|
empathy_software_plugin/wizards/tech_debt_wizard.py,sha256=6cwJrSHfQdkudY2bLhthgQ1kF3OEqAdLL2WZLcgl-Kk,26535
|
|
296
296
|
empathy_software_plugin/wizards/testing_wizard.py,sha256=evDrQW90p2Lt3SBdTPjPNDW3K6l2syzNAkzlkFmjU2k,9686
|
|
297
297
|
empathy_software_plugin/wizards/debugging/__init__.py,sha256=5psc3AIKldwSaD2ymeqAr88I7GjE42_lgcnM5Q3ObSU,1387
|
|
298
|
-
empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py,sha256=
|
|
299
|
-
empathy_software_plugin/wizards/debugging/config_loaders.py,sha256=
|
|
298
|
+
empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py,sha256=7Y1NKFcwbRW9J5PSVzZtTAVUzyukBSNZGXA92kmCg8I,15807
|
|
299
|
+
empathy_software_plugin/wizards/debugging/config_loaders.py,sha256=nbXh_bR-PJsmQjWbRNJ-spX8U1PBJZrvZ2XuM7PYPL0,13481
|
|
300
300
|
empathy_software_plugin/wizards/debugging/fix_applier.py,sha256=dmLBoWLkANBE7GlPKaX0ROS5cQ5EMGD1ecoOCnJ277o,14849
|
|
301
|
-
empathy_software_plugin/wizards/debugging/language_patterns.py,sha256=
|
|
302
|
-
empathy_software_plugin/wizards/debugging/linter_parsers.py,sha256=
|
|
301
|
+
empathy_software_plugin/wizards/debugging/language_patterns.py,sha256=s_pk3dYiaM9SwL2Iwtz01J6vqrjbgeA8gAhD8ZGxUDU,15285
|
|
302
|
+
empathy_software_plugin/wizards/debugging/linter_parsers.py,sha256=OI96MRoY78QONsJpknp6LY9z9soTBEMzf8UmP8fgZUg,15524
|
|
303
303
|
empathy_software_plugin/wizards/debugging/verification.py,sha256=6plbuzfURtWJ2WWYiWUvUYMW2wJD-CERUNOpvZQjlIU,11021
|
|
304
304
|
empathy_software_plugin/wizards/performance/__init__.py,sha256=Jsnj_O6ln7lwrpWGq_36_houCSTl1JG38D71_txvyBY,175
|
|
305
305
|
empathy_software_plugin/wizards/performance/bottleneck_detector.py,sha256=rkSkq4MNJ3q3EVD2sINyhYTHaEkntQcmbwIPcP2ukUg,8144
|
|
306
|
-
empathy_software_plugin/wizards/performance/profiler_parsers.py,sha256=
|
|
306
|
+
empathy_software_plugin/wizards/performance/profiler_parsers.py,sha256=Jf9FwtNN-QUaCxRH5NpzBsWFQ425Rk1DKfaM-yPtQY4,8897
|
|
307
307
|
empathy_software_plugin/wizards/performance/trajectory_analyzer.py,sha256=CONUG3WRUX8-jZdOKJSGXZiRNtHrvkXydaSXmC29naE,15846
|
|
308
308
|
empathy_software_plugin/wizards/security/__init__.py,sha256=faXGfP8VmcVFg_4xWRKFQ_30c-QxbHQk4-gQKTzQFIY,723
|
|
309
309
|
empathy_software_plugin/wizards/security/exploit_analyzer.py,sha256=K-V0ycsMRLLTsRiG2ojwzbLIHAZwyIedY6doHGLZHQo,9681
|
|
310
310
|
empathy_software_plugin/wizards/security/owasp_patterns.py,sha256=MARl4_D_r0KQU8Cysft-8OGuxXrbDN1ReTF6kWbcEW4,10234
|
|
311
|
-
empathy_software_plugin/wizards/security/vulnerability_scanner.py,sha256=
|
|
311
|
+
empathy_software_plugin/wizards/security/vulnerability_scanner.py,sha256=lMFPPzRyf4fZZqjhdlhT49ciGuRnwF0a1w89VZB-9aA,23685
|
|
312
312
|
empathy_software_plugin/wizards/testing/__init__.py,sha256=yfVkFo1374ZaJvdgtq9TBprzAFHqlcp8yBydAnnaHIw,707
|
|
313
313
|
empathy_software_plugin/wizards/testing/coverage_analyzer.py,sha256=k37_GJL895OKmZTficg-HKzfMjdm9YC4kpH5ELszHtQ,16113
|
|
314
|
-
empathy_software_plugin/wizards/testing/quality_analyzer.py,sha256=
|
|
315
|
-
empathy_software_plugin/wizards/testing/test_suggester.py,sha256=
|
|
314
|
+
empathy_software_plugin/wizards/testing/quality_analyzer.py,sha256=7hM2aqaMHGq0T-44gwDqKXexURkdWDxQXx0w_XagQxA,17617
|
|
315
|
+
empathy_software_plugin/wizards/testing/test_suggester.py,sha256=DoPEzqqU52QdEVEuORDju2bISWRwNz9ZLHW96wRoBl8,17915
|
|
316
316
|
wizards/__init__.py,sha256=5JJ6rtS5mwJtuZIgO2sYHZlCy0XJP2eyyCK5zMD6ZAc,2452
|
|
317
317
|
wizards/admission_assessment_wizard.py,sha256=-Th9bwu6Sd6V2jA4fciK35QpoFc40U1quZHDMdOH93U,23609
|
|
318
318
|
wizards/care_plan.py,sha256=YVjjmbdUptOSkgkbhCIioHbcgISgzvIhlRiHZ3xvUJQ,10728
|
|
@@ -334,8 +334,8 @@ workflow_scaffolding/__init__.py,sha256=UpX5vjjjPjIaAKyIV1D4GxJzLUZy5DzdzgSkePYM
|
|
|
334
334
|
workflow_scaffolding/__main__.py,sha256=0qspuNoadTDqyskXTlT8Sahqau-XIxN35NHTSGVW6z4,236
|
|
335
335
|
workflow_scaffolding/cli.py,sha256=R4rCTDENRMil2c3v32MnisqteFRDfilS6RHBNlYV39Q,6752
|
|
336
336
|
workflow_scaffolding/generator.py,sha256=whWbBmWEA0rN3M3X9EzTjfbwBxHcF40Jin8-nbj0S0E,8858
|
|
337
|
-
empathy_framework-3.9.
|
|
338
|
-
empathy_framework-3.9.
|
|
339
|
-
empathy_framework-3.9.
|
|
340
|
-
empathy_framework-3.9.
|
|
341
|
-
empathy_framework-3.9.
|
|
337
|
+
empathy_framework-3.9.3.dist-info/METADATA,sha256=lY3RB1JHOHUm4wET6B2oqddzH3hD0zcOPzFn0uH5nVM,50099
|
|
338
|
+
empathy_framework-3.9.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
339
|
+
empathy_framework-3.9.3.dist-info/entry_points.txt,sha256=zMu7sKCiLndbEEXjTecltS-1P_JZoEUKrifuRBBbroc,1268
|
|
340
|
+
empathy_framework-3.9.3.dist-info/top_level.txt,sha256=wrNU1aVMutVDACer58H-udv0P_171Dv6z_42sZtZ-xM,124
|
|
341
|
+
empathy_framework-3.9.3.dist-info/RECORD,,
|
|
@@ -874,9 +874,24 @@ Rules:
|
|
|
874
874
|
issues = []
|
|
875
875
|
passed = True
|
|
876
876
|
|
|
877
|
+
# Only scan production code directories
|
|
878
|
+
production_paths = [
|
|
879
|
+
"src/",
|
|
880
|
+
"empathy_software_plugin/",
|
|
881
|
+
"empathy_healthcare_plugin/",
|
|
882
|
+
"empathy_llm_toolkit/",
|
|
883
|
+
"patterns/",
|
|
884
|
+
"tests/",
|
|
885
|
+
]
|
|
886
|
+
|
|
887
|
+
# Use production paths if checking current directory
|
|
888
|
+
scan_paths = production_paths if path in [".", "./"] else [path]
|
|
889
|
+
|
|
877
890
|
try:
|
|
878
891
|
result = subprocess.run(
|
|
879
|
-
["python", "-m", "mypy"
|
|
892
|
+
["python", "-m", "mypy"]
|
|
893
|
+
+ scan_paths
|
|
894
|
+
+ ["--ignore-missing-imports", "--no-error-summary"],
|
|
880
895
|
check=False,
|
|
881
896
|
capture_output=True,
|
|
882
897
|
text=True,
|
|
@@ -925,44 +940,36 @@ Rules:
|
|
|
925
940
|
issues = []
|
|
926
941
|
passed = True
|
|
927
942
|
|
|
943
|
+
# Only run tests in tests/ directory for production health check
|
|
944
|
+
test_path = "tests/" if path in [".", "./"] else path
|
|
945
|
+
|
|
928
946
|
try:
|
|
929
947
|
result = subprocess.run(
|
|
930
|
-
["python", "-m", "pytest",
|
|
948
|
+
["python", "-m", "pytest", test_path, "--collect-only", "-q"],
|
|
931
949
|
check=False,
|
|
932
950
|
capture_output=True,
|
|
933
951
|
text=True,
|
|
934
|
-
timeout=
|
|
935
|
-
cwd=path if Path(path).is_dir() else ".",
|
|
952
|
+
timeout=60,
|
|
936
953
|
)
|
|
937
954
|
|
|
938
955
|
if result.returncode != 0:
|
|
939
956
|
passed = False
|
|
940
957
|
|
|
941
|
-
#
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
elif "ERROR" in line and "test" in line.lower():
|
|
957
|
-
issues.append(
|
|
958
|
-
HealthIssue(
|
|
959
|
-
title=f"Test error: {line[:50]}",
|
|
960
|
-
description=line,
|
|
961
|
-
category=HealthCategory.TESTS,
|
|
962
|
-
severity=IssueSeverity.CRITICAL,
|
|
963
|
-
tool="pytest",
|
|
964
|
-
),
|
|
965
|
-
)
|
|
958
|
+
# Check for collection errors in stderr
|
|
959
|
+
error_output = result.stderr + result.stdout
|
|
960
|
+
for line in error_output.splitlines()[:50]:
|
|
961
|
+
if "ERROR" in line or "INTERNALERROR" in line:
|
|
962
|
+
# Only report actual errors, not counts
|
|
963
|
+
if "error" in line.lower() and not line.strip().startswith("="):
|
|
964
|
+
issues.append(
|
|
965
|
+
HealthIssue(
|
|
966
|
+
title=f"Test error: {line[:50]}",
|
|
967
|
+
description=line,
|
|
968
|
+
category=HealthCategory.TESTS,
|
|
969
|
+
severity=IssueSeverity.CRITICAL,
|
|
970
|
+
tool="pytest",
|
|
971
|
+
),
|
|
972
|
+
)
|
|
966
973
|
|
|
967
974
|
except (subprocess.TimeoutExpired, FileNotFoundError) as e:
|
|
968
975
|
logger.warning(f"Test check failed: {e}")
|
empathy_os/__init__.py
CHANGED
empathy_os/cli_unified.py
CHANGED
|
@@ -513,6 +513,85 @@ def workflow_recommend(
|
|
|
513
513
|
)
|
|
514
514
|
|
|
515
515
|
|
|
516
|
+
# =============================================================================
|
|
517
|
+
# TELEMETRY SUBCOMMAND GROUP
|
|
518
|
+
# =============================================================================
|
|
519
|
+
|
|
520
|
+
telemetry_app = typer.Typer(help="View and manage local usage telemetry")
|
|
521
|
+
app.add_typer(telemetry_app, name="telemetry")
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
@telemetry_app.command("show")
|
|
525
|
+
def telemetry_show(
|
|
526
|
+
limit: int = typer.Option(20, "--limit", "-l", help="Number of entries to show"),
|
|
527
|
+
days: int | None = typer.Option(None, "--days", "-d", help="Only show last N days"),
|
|
528
|
+
):
|
|
529
|
+
"""Show recent LLM calls and usage stats."""
|
|
530
|
+
args = [sys.executable, "-m", "empathy_os.cli", "telemetry", "show", "--limit", str(limit)]
|
|
531
|
+
if days:
|
|
532
|
+
args.extend(["--days", str(days)])
|
|
533
|
+
subprocess.run(args, check=False)
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
@telemetry_app.command("savings")
|
|
537
|
+
def telemetry_savings(
|
|
538
|
+
days: int = typer.Option(30, "--days", "-d", help="Number of days to analyze"),
|
|
539
|
+
):
|
|
540
|
+
"""Calculate cost savings vs baseline (all PREMIUM)."""
|
|
541
|
+
subprocess.run(
|
|
542
|
+
[sys.executable, "-m", "empathy_os.cli", "telemetry", "savings", "--days", str(days)],
|
|
543
|
+
check=False,
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
@telemetry_app.command("compare")
|
|
548
|
+
def telemetry_compare(
|
|
549
|
+
period1: int = typer.Option(7, "--period1", "-p1", help="First period in days"),
|
|
550
|
+
period2: int = typer.Option(30, "--period2", "-p2", help="Second period in days"),
|
|
551
|
+
):
|
|
552
|
+
"""Compare usage across two time periods."""
|
|
553
|
+
subprocess.run(
|
|
554
|
+
[
|
|
555
|
+
sys.executable,
|
|
556
|
+
"-m",
|
|
557
|
+
"empathy_os.cli",
|
|
558
|
+
"telemetry",
|
|
559
|
+
"compare",
|
|
560
|
+
"--period1",
|
|
561
|
+
str(period1),
|
|
562
|
+
"--period2",
|
|
563
|
+
str(period2),
|
|
564
|
+
],
|
|
565
|
+
check=False,
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
@telemetry_app.command("export")
|
|
570
|
+
def telemetry_export(
|
|
571
|
+
format_type: str = typer.Option("json", "--format", "-f", help="Export format (json, csv)"),
|
|
572
|
+
output: Path | None = typer.Option(None, "--output", "-o", help="Output file path"),
|
|
573
|
+
days: int | None = typer.Option(None, "--days", "-d", help="Only export last N days"),
|
|
574
|
+
):
|
|
575
|
+
"""Export telemetry data to JSON or CSV."""
|
|
576
|
+
args = [sys.executable, "-m", "empathy_os.cli", "telemetry", "export", "--format", format_type]
|
|
577
|
+
if output:
|
|
578
|
+
args.extend(["--output", str(output)])
|
|
579
|
+
if days:
|
|
580
|
+
args.extend(["--days", str(days)])
|
|
581
|
+
subprocess.run(args, check=False)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
@telemetry_app.command("reset")
|
|
585
|
+
def telemetry_reset(
|
|
586
|
+
confirm: bool = typer.Option(False, "--confirm", help="Confirm deletion"),
|
|
587
|
+
):
|
|
588
|
+
"""Clear all telemetry data (use with caution)."""
|
|
589
|
+
args = [sys.executable, "-m", "empathy_os.cli", "telemetry", "reset"]
|
|
590
|
+
if confirm:
|
|
591
|
+
args.append("--confirm")
|
|
592
|
+
subprocess.run(args, check=False)
|
|
593
|
+
|
|
594
|
+
|
|
516
595
|
# =============================================================================
|
|
517
596
|
# TIER RECOMMENDATION SUBCOMMAND GROUP
|
|
518
597
|
# =============================================================================
|
|
@@ -669,7 +748,12 @@ def cheatsheet():
|
|
|
669
748
|
empathy wizard list Show available wizards
|
|
670
749
|
empathy wizard run <name> Execute a wizard
|
|
671
750
|
empathy wizard create <name> -d <domain> Create wizard (12x faster)
|
|
672
|
-
empathy wizard list-patterns List available patterns
|
|
751
|
+
empathy wizard list-patterns List available patterns
|
|
752
|
+
|
|
753
|
+
[bold]Usage Telemetry[/bold]
|
|
754
|
+
empathy telemetry show View recent LLM calls & costs
|
|
755
|
+
empathy telemetry savings Calculate cost savings (tier routing)
|
|
756
|
+
empathy telemetry export Export usage data (JSON/CSV)""",
|
|
673
757
|
title="[bold blue]Empathy Framework Cheatsheet[/bold blue]",
|
|
674
758
|
),
|
|
675
759
|
)
|
empathy_os/config.py
CHANGED
|
@@ -14,7 +14,10 @@ import json
|
|
|
14
14
|
import os
|
|
15
15
|
from dataclasses import asdict, dataclass, field
|
|
16
16
|
from pathlib import Path
|
|
17
|
-
from typing import Any
|
|
17
|
+
from typing import TYPE_CHECKING, Any
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from empathy_os.workflows.config import ModelConfig
|
|
18
21
|
|
|
19
22
|
try:
|
|
20
23
|
import yaml
|
|
@@ -23,8 +26,6 @@ try:
|
|
|
23
26
|
except ImportError:
|
|
24
27
|
YAML_AVAILABLE = False
|
|
25
28
|
|
|
26
|
-
from empathy_os.workflows.config import ModelConfig
|
|
27
|
-
|
|
28
29
|
|
|
29
30
|
def _validate_file_path(path: str, allowed_dir: str | None = None) -> Path:
|
|
30
31
|
"""Validate file path to prevent path traversal and arbitrary writes.
|
|
@@ -120,7 +121,7 @@ class EmpathyConfig:
|
|
|
120
121
|
metadata: dict[str, Any] = field(default_factory=dict)
|
|
121
122
|
|
|
122
123
|
# Model settings
|
|
123
|
-
models: list[ModelConfig] = field(default_factory=list)
|
|
124
|
+
models: list["ModelConfig"] = field(default_factory=list)
|
|
124
125
|
default_model: str | None = None
|
|
125
126
|
log_path: str | None = None
|
|
126
127
|
max_threads: int = 4
|
|
@@ -181,6 +182,8 @@ class EmpathyConfig:
|
|
|
181
182
|
|
|
182
183
|
# Handle nested ModelConfig objects
|
|
183
184
|
if filtered_data.get("models"):
|
|
185
|
+
from empathy_os.workflows.config import ModelConfig
|
|
186
|
+
|
|
184
187
|
filtered_data["models"] = [ModelConfig(**m) for m in filtered_data["models"]]
|
|
185
188
|
|
|
186
189
|
return cls(**filtered_data)
|
|
@@ -7,6 +7,7 @@ Licensed under Fair Source 0.9
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import logging
|
|
10
|
+
from collections.abc import Callable
|
|
10
11
|
|
|
11
12
|
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
12
13
|
|
|
@@ -45,7 +46,7 @@ class HotReloadIntegration:
|
|
|
45
46
|
def __init__(
|
|
46
47
|
self,
|
|
47
48
|
app: FastAPI,
|
|
48
|
-
register_callback:
|
|
49
|
+
register_callback: Callable[[str, type], bool],
|
|
49
50
|
):
|
|
50
51
|
"""Initialize hot-reload integration.
|
|
51
52
|
|
empathy_os/hot_reload/watcher.py
CHANGED
|
@@ -19,16 +19,16 @@ logger = logging.getLogger(__name__)
|
|
|
19
19
|
class WizardFileHandler(FileSystemEventHandler):
|
|
20
20
|
"""Handles file system events for wizard files."""
|
|
21
21
|
|
|
22
|
-
def __init__(self, reload_callback: Callable[[str], None]):
|
|
22
|
+
def __init__(self, reload_callback: Callable[[str, str], None]):
|
|
23
23
|
"""Initialize handler.
|
|
24
24
|
|
|
25
25
|
Args:
|
|
26
|
-
reload_callback: Function to call when wizard file changes
|
|
26
|
+
reload_callback: Function to call when wizard file changes (wizard_id, file_path)
|
|
27
27
|
|
|
28
28
|
"""
|
|
29
29
|
super().__init__()
|
|
30
30
|
self.reload_callback = reload_callback
|
|
31
|
-
self._processing = set() # Prevent duplicate events
|
|
31
|
+
self._processing: set[str] = set() # Prevent duplicate events
|
|
32
32
|
|
|
33
33
|
def on_modified(self, event: FileSystemEvent) -> None:
|
|
34
34
|
"""Handle file modification events.
|
|
@@ -40,7 +40,11 @@ class WizardFileHandler(FileSystemEventHandler):
|
|
|
40
40
|
if event.is_directory:
|
|
41
41
|
return
|
|
42
42
|
|
|
43
|
-
file_path
|
|
43
|
+
# Convert file_path to str if it's bytes
|
|
44
|
+
file_path_raw = event.src_path
|
|
45
|
+
file_path = (
|
|
46
|
+
file_path_raw.decode("utf-8") if isinstance(file_path_raw, bytes) else file_path_raw
|
|
47
|
+
)
|
|
44
48
|
|
|
45
49
|
# Only process Python files
|
|
46
50
|
if not file_path.endswith(".py"):
|
|
@@ -8,6 +8,7 @@ Licensed under Fair Source 0.9
|
|
|
8
8
|
|
|
9
9
|
import asyncio
|
|
10
10
|
import logging
|
|
11
|
+
from collections.abc import Callable
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
13
14
|
from fastapi import WebSocket
|
|
@@ -141,7 +142,7 @@ def get_notification_manager() -> ReloadNotificationManager:
|
|
|
141
142
|
return _notification_manager
|
|
142
143
|
|
|
143
144
|
|
|
144
|
-
def create_notification_callback() ->
|
|
145
|
+
def create_notification_callback() -> Callable[[dict[str, Any]], None]:
|
|
145
146
|
"""Create a callback function for the wizard reloader.
|
|
146
147
|
|
|
147
148
|
Returns:
|
empathy_os/tier_recommender.py
CHANGED
|
@@ -79,7 +79,7 @@ class TierRecommender:
|
|
|
79
79
|
|
|
80
80
|
def _load_patterns(self) -> list[dict]:
|
|
81
81
|
"""Load all enhanced patterns with tier_progression data."""
|
|
82
|
-
patterns = []
|
|
82
|
+
patterns: list[dict] = []
|
|
83
83
|
|
|
84
84
|
if not self.patterns_dir.exists():
|
|
85
85
|
return patterns
|
|
@@ -359,8 +359,8 @@ class TierRecommender:
|
|
|
359
359
|
return {"total_patterns": 0, "message": "No patterns loaded"}
|
|
360
360
|
|
|
361
361
|
# Calculate tier distribution
|
|
362
|
-
tier_dist = defaultdict(int)
|
|
363
|
-
bug_type_dist = defaultdict(int)
|
|
362
|
+
tier_dist: dict[str, int] = defaultdict(int)
|
|
363
|
+
bug_type_dist: dict[str, int] = defaultdict(int)
|
|
364
364
|
total_savings = 0.0
|
|
365
365
|
|
|
366
366
|
for pattern in self.patterns:
|
empathy_os/workflows/base.py
CHANGED
|
@@ -26,6 +26,9 @@ from enum import Enum
|
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
from typing import TYPE_CHECKING, Any
|
|
28
28
|
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from .tier_tracking import WorkflowTierTracker
|
|
31
|
+
|
|
29
32
|
# Load .env file for API keys if python-dotenv is available
|
|
30
33
|
try:
|
|
31
34
|
from dotenv import load_dotenv
|
|
@@ -430,7 +433,7 @@ class BaseWorkflow(ABC):
|
|
|
430
433
|
|
|
431
434
|
# Tier tracking support
|
|
432
435
|
self._enable_tier_tracking = enable_tier_tracking
|
|
433
|
-
self._tier_tracker = None
|
|
436
|
+
self._tier_tracker: WorkflowTierTracker | None = None
|
|
434
437
|
|
|
435
438
|
# Telemetry tracking (singleton instance)
|
|
436
439
|
self._telemetry_tracker: UsageTracker | None = None
|
|
@@ -569,7 +572,7 @@ class BaseWorkflow(ABC):
|
|
|
569
572
|
logger.debug(f"Cache hit for {self.name}:{stage}")
|
|
570
573
|
# Determine cache type
|
|
571
574
|
if hasattr(self._cache, "cache_type"):
|
|
572
|
-
ct = self._cache.cache_type
|
|
575
|
+
ct = self._cache.cache_type
|
|
573
576
|
# Ensure it's a string (not a Mock object)
|
|
574
577
|
cache_type = str(ct) if ct and isinstance(ct, str) else "hash"
|
|
575
578
|
else:
|
|
@@ -369,7 +369,7 @@ class WorkflowTierTracker:
|
|
|
369
369
|
)
|
|
370
370
|
|
|
371
371
|
# Calculate actual cost from stages
|
|
372
|
-
actual_cost = sum(stage.cost for stage in workflow_result.stages)
|
|
372
|
+
actual_cost: float = sum(stage.cost for stage in workflow_result.stages)
|
|
373
373
|
|
|
374
374
|
# Rough estimate: PREMIUM tier is ~15x more expensive than CHEAP
|
|
375
375
|
return actual_cost * 5 # Conservative multiplier
|
|
@@ -47,8 +47,8 @@ class AdvancedDebuggingWizard(BaseWizard):
|
|
|
47
47
|
super().__init__()
|
|
48
48
|
self.bug_analyzer = BugRiskAnalyzer()
|
|
49
49
|
self.pattern_library = get_pattern_library()
|
|
50
|
-
self._name = "Advanced Debugging Wizard"
|
|
51
|
-
self._level = 4
|
|
50
|
+
self._name: str = "Advanced Debugging Wizard"
|
|
51
|
+
self._level: int = 4
|
|
52
52
|
|
|
53
53
|
@property
|
|
54
54
|
def name(self) -> str:
|
|
@@ -126,7 +126,8 @@ class AdvancedDebuggingWizard(BaseWizard):
|
|
|
126
126
|
# Phase 4: Group by fixability
|
|
127
127
|
fixability_by_linter = {}
|
|
128
128
|
for linter_name, result in linter_results.items():
|
|
129
|
-
|
|
129
|
+
issues_for_fixability: list[LintIssue] = result["issues"] # type: ignore[assignment]
|
|
130
|
+
fixability = group_issues_by_fixability(linter_name, issues_for_fixability)
|
|
130
131
|
fixability_by_linter[linter_name] = {
|
|
131
132
|
"auto_fixable": len(fixability["auto_fixable"]),
|
|
132
133
|
"manual": len(fixability["manual"]),
|
|
@@ -138,7 +139,8 @@ class AdvancedDebuggingWizard(BaseWizard):
|
|
|
138
139
|
logger.info("Applying auto-fixes...")
|
|
139
140
|
|
|
140
141
|
for linter_name, result in linter_results.items():
|
|
141
|
-
|
|
142
|
+
issues_for_fixing: list[LintIssue] = result["issues"] # type: ignore[assignment]
|
|
143
|
+
fixes = apply_fixes(linter_name, issues_for_fixing, dry_run=False, auto_only=True)
|
|
142
144
|
|
|
143
145
|
successful = [f for f in fixes if f.success]
|
|
144
146
|
failed = [f for f in fixes if not f.success]
|
|
@@ -155,7 +157,8 @@ class AdvancedDebuggingWizard(BaseWizard):
|
|
|
155
157
|
logger.info("Verifying fixes...")
|
|
156
158
|
|
|
157
159
|
for linter_name, result in linter_results.items():
|
|
158
|
-
|
|
160
|
+
issues_for_verification: list[LintIssue] = result["issues"] # type: ignore[assignment]
|
|
161
|
+
verification = verify_fixes(linter_name, project_path, issues_for_verification)
|
|
159
162
|
|
|
160
163
|
verification_results[linter_name] = verification.to_dict()
|
|
161
164
|
|
|
@@ -201,7 +204,7 @@ class AdvancedDebuggingWizard(BaseWizard):
|
|
|
201
204
|
insights = []
|
|
202
205
|
|
|
203
206
|
# Group issues by language
|
|
204
|
-
by_language = {}
|
|
207
|
+
by_language: dict[str, list[LintIssue]] = {}
|
|
205
208
|
for issue in issues:
|
|
206
209
|
lang = issue.linter
|
|
207
210
|
if lang not in by_language:
|
|
@@ -246,15 +246,19 @@ class PylintConfigLoader(BaseConfigLoader):
|
|
|
246
246
|
"""Load from pyproject.toml"""
|
|
247
247
|
try:
|
|
248
248
|
import tomli
|
|
249
|
+
|
|
250
|
+
toml_loader = tomli
|
|
249
251
|
except ImportError:
|
|
250
252
|
# Fallback for Python 3.11+
|
|
251
253
|
try:
|
|
252
|
-
import tomllib
|
|
254
|
+
import tomllib
|
|
255
|
+
|
|
256
|
+
toml_loader = tomllib
|
|
253
257
|
except ImportError as e:
|
|
254
258
|
raise ImportError("tomli or tomllib required for pyproject.toml") from e
|
|
255
259
|
|
|
256
260
|
with open(path, "rb") as f:
|
|
257
|
-
data =
|
|
261
|
+
data = toml_loader.load(f)
|
|
258
262
|
|
|
259
263
|
pylint_config = data.get("tool", {}).get("pylint", {})
|
|
260
264
|
|
|
@@ -278,6 +278,7 @@ class CrossLanguagePatternLibrary:
|
|
|
278
278
|
UniversalPattern if found, None otherwise
|
|
279
279
|
|
|
280
280
|
"""
|
|
281
|
+
pattern: UniversalPattern
|
|
281
282
|
for pattern in self.patterns.values():
|
|
282
283
|
if linter in pattern.language_manifestations:
|
|
283
284
|
if pattern.language_manifestations[linter] == rule:
|
|
@@ -295,11 +296,12 @@ class CrossLanguagePatternLibrary:
|
|
|
295
296
|
List of fix steps, or None if not found
|
|
296
297
|
|
|
297
298
|
"""
|
|
298
|
-
pattern = self.patterns.get(pattern_name)
|
|
299
|
+
pattern: UniversalPattern | None = self.patterns.get(pattern_name)
|
|
299
300
|
if not pattern:
|
|
300
301
|
return None
|
|
301
302
|
|
|
302
|
-
|
|
303
|
+
result: list[str] | None = pattern.language_specific_fixes.get(language)
|
|
304
|
+
return result
|
|
303
305
|
|
|
304
306
|
def suggest_cross_language_insight(
|
|
305
307
|
self,
|
|
@@ -167,20 +167,20 @@ class ChromeDevToolsParser(BaseProfilerParser):
|
|
|
167
167
|
function_times[name]["call_count"] += 1
|
|
168
168
|
|
|
169
169
|
# Convert to FunctionProfile
|
|
170
|
-
total_time = sum(
|
|
170
|
+
total_time = sum(stats["total_time"] for stats in function_times.values())
|
|
171
171
|
|
|
172
|
-
for func_name,
|
|
172
|
+
for func_name, stats in function_times.items():
|
|
173
173
|
profiles.append(
|
|
174
174
|
FunctionProfile(
|
|
175
175
|
function_name=func_name,
|
|
176
176
|
file_path="", # Chrome doesn't always provide
|
|
177
177
|
line_number=0,
|
|
178
|
-
total_time=
|
|
179
|
-
self_time=
|
|
180
|
-
call_count=
|
|
181
|
-
cumulative_time=
|
|
178
|
+
total_time=stats["total_time"],
|
|
179
|
+
self_time=stats["total_time"],
|
|
180
|
+
call_count=stats["call_count"],
|
|
181
|
+
cumulative_time=stats["total_time"],
|
|
182
182
|
percent_total=(
|
|
183
|
-
(
|
|
183
|
+
(stats["total_time"] / total_time * 100) if total_time > 0 else 0
|
|
184
184
|
),
|
|
185
185
|
profiler=self.profiler_name,
|
|
186
186
|
),
|
|
@@ -225,7 +225,7 @@ class VulnerabilityScanner:
|
|
|
225
225
|
lines: list[str],
|
|
226
226
|
) -> list[Vulnerability]:
|
|
227
227
|
"""Scan for hardcoded secrets"""
|
|
228
|
-
vulnerabilities = []
|
|
228
|
+
vulnerabilities: list[Vulnerability] = []
|
|
229
229
|
|
|
230
230
|
# Skip certain file types
|
|
231
231
|
if file_path.suffix in [".md", ".txt", ".json", ".xml"]:
|
|
@@ -168,10 +168,10 @@ class SecurityAnalysisWizard(BaseWizard):
|
|
|
168
168
|
|
|
169
169
|
def _group_by_category(self, vulnerabilities: list[dict[str, Any]]) -> dict[str, int]:
|
|
170
170
|
"""Group vulnerabilities by OWASP category"""
|
|
171
|
-
by_category = {}
|
|
171
|
+
by_category: dict[str, int] = {}
|
|
172
172
|
|
|
173
173
|
for vuln in vulnerabilities:
|
|
174
|
-
category = vuln.get("category", "unknown")
|
|
174
|
+
category: str = str(vuln.get("category", "unknown"))
|
|
175
175
|
by_category[category] = by_category.get(category, 0) + 1
|
|
176
176
|
|
|
177
177
|
return by_category
|
|
@@ -8,7 +8,7 @@ Licensed under Fair Source License 0.9
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import re
|
|
11
|
-
from dataclasses import dataclass
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
12
|
from enum import Enum
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from typing import Any
|
|
@@ -37,14 +37,8 @@ class TestFunction:
|
|
|
37
37
|
assertions_count: int
|
|
38
38
|
execution_time: float | None = None
|
|
39
39
|
is_async: bool = False
|
|
40
|
-
uses_fixtures: list[str]
|
|
41
|
-
issues: list[TestQualityIssue]
|
|
42
|
-
|
|
43
|
-
def __post_init__(self):
|
|
44
|
-
if self.uses_fixtures is None:
|
|
45
|
-
self.uses_fixtures = []
|
|
46
|
-
if self.issues is None:
|
|
47
|
-
self.issues = []
|
|
40
|
+
uses_fixtures: list[str] = field(default_factory=list)
|
|
41
|
+
issues: list[TestQualityIssue] = field(default_factory=list)
|
|
48
42
|
|
|
49
43
|
@property
|
|
50
44
|
def quality_score(self) -> float:
|
|
@@ -494,7 +494,7 @@ def {test_name}({params_str}):
|
|
|
494
494
|
summary.append("=" * 60)
|
|
495
495
|
|
|
496
496
|
# Group by priority
|
|
497
|
-
by_priority = {
|
|
497
|
+
by_priority: dict[TestPriority, list[TestSuggestion]] = {
|
|
498
498
|
TestPriority.CRITICAL: [],
|
|
499
499
|
TestPriority.HIGH: [],
|
|
500
500
|
TestPriority.MEDIUM: [],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|