empathy-framework 4.6.6__py3-none-any.whl → 4.7.1__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.7.1.dist-info/METADATA +690 -0
- empathy_framework-4.7.1.dist-info/RECORD +379 -0
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/top_level.txt +1 -2
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
- empathy_llm_toolkit/agent_factory/__init__.py +6 -6
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +7 -10
- empathy_llm_toolkit/agents_md/__init__.py +22 -0
- empathy_llm_toolkit/agents_md/loader.py +218 -0
- empathy_llm_toolkit/agents_md/parser.py +271 -0
- empathy_llm_toolkit/agents_md/registry.py +307 -0
- empathy_llm_toolkit/commands/__init__.py +51 -0
- empathy_llm_toolkit/commands/context.py +375 -0
- empathy_llm_toolkit/commands/loader.py +301 -0
- empathy_llm_toolkit/commands/models.py +231 -0
- empathy_llm_toolkit/commands/parser.py +371 -0
- empathy_llm_toolkit/commands/registry.py +429 -0
- empathy_llm_toolkit/config/__init__.py +8 -8
- empathy_llm_toolkit/config/unified.py +3 -7
- empathy_llm_toolkit/context/__init__.py +22 -0
- empathy_llm_toolkit/context/compaction.py +455 -0
- empathy_llm_toolkit/context/manager.py +434 -0
- empathy_llm_toolkit/hooks/__init__.py +24 -0
- empathy_llm_toolkit/hooks/config.py +306 -0
- empathy_llm_toolkit/hooks/executor.py +289 -0
- empathy_llm_toolkit/hooks/registry.py +302 -0
- empathy_llm_toolkit/hooks/scripts/__init__.py +39 -0
- empathy_llm_toolkit/hooks/scripts/evaluate_session.py +201 -0
- empathy_llm_toolkit/hooks/scripts/first_time_init.py +285 -0
- empathy_llm_toolkit/hooks/scripts/pre_compact.py +207 -0
- empathy_llm_toolkit/hooks/scripts/session_end.py +183 -0
- empathy_llm_toolkit/hooks/scripts/session_start.py +163 -0
- empathy_llm_toolkit/hooks/scripts/suggest_compact.py +225 -0
- empathy_llm_toolkit/learning/__init__.py +30 -0
- empathy_llm_toolkit/learning/evaluator.py +438 -0
- empathy_llm_toolkit/learning/extractor.py +514 -0
- empathy_llm_toolkit/learning/storage.py +560 -0
- empathy_llm_toolkit/providers.py +4 -11
- empathy_llm_toolkit/security/__init__.py +17 -17
- empathy_llm_toolkit/utils/tokens.py +2 -5
- empathy_os/__init__.py +202 -70
- empathy_os/cache_monitor.py +5 -3
- empathy_os/cli/__init__.py +11 -55
- empathy_os/cli/__main__.py +29 -15
- empathy_os/cli/commands/inspection.py +21 -12
- empathy_os/cli/commands/memory.py +4 -12
- empathy_os/cli/commands/profiling.py +198 -0
- empathy_os/cli/commands/utilities.py +27 -7
- empathy_os/cli.py +28 -57
- empathy_os/cli_unified.py +525 -1164
- empathy_os/cost_tracker.py +9 -3
- empathy_os/dashboard/server.py +200 -2
- empathy_os/hot_reload/__init__.py +7 -7
- empathy_os/hot_reload/config.py +6 -7
- empathy_os/hot_reload/integration.py +35 -35
- empathy_os/hot_reload/reloader.py +57 -57
- empathy_os/hot_reload/watcher.py +28 -28
- empathy_os/hot_reload/websocket.py +2 -2
- empathy_os/memory/__init__.py +11 -4
- empathy_os/memory/claude_memory.py +1 -1
- empathy_os/memory/cross_session.py +8 -12
- empathy_os/memory/edges.py +6 -6
- empathy_os/memory/file_session.py +770 -0
- empathy_os/memory/graph.py +30 -30
- empathy_os/memory/nodes.py +6 -6
- empathy_os/memory/short_term.py +15 -9
- empathy_os/memory/unified.py +606 -140
- empathy_os/meta_workflows/agent_creator.py +3 -9
- empathy_os/meta_workflows/cli_meta_workflows.py +113 -53
- empathy_os/meta_workflows/form_engine.py +6 -18
- empathy_os/meta_workflows/intent_detector.py +64 -24
- empathy_os/meta_workflows/models.py +3 -1
- empathy_os/meta_workflows/pattern_learner.py +13 -31
- empathy_os/meta_workflows/plan_generator.py +55 -47
- empathy_os/meta_workflows/session_context.py +2 -3
- empathy_os/meta_workflows/workflow.py +20 -51
- empathy_os/models/cli.py +2 -2
- empathy_os/models/tasks.py +1 -2
- empathy_os/models/telemetry.py +4 -1
- empathy_os/models/token_estimator.py +3 -1
- empathy_os/monitoring/alerts.py +938 -9
- empathy_os/monitoring/alerts_cli.py +346 -183
- empathy_os/orchestration/execution_strategies.py +12 -29
- empathy_os/orchestration/pattern_learner.py +20 -26
- empathy_os/orchestration/real_tools.py +6 -15
- empathy_os/platform_utils.py +2 -1
- empathy_os/plugins/__init__.py +2 -2
- empathy_os/plugins/base.py +64 -64
- empathy_os/plugins/registry.py +32 -32
- empathy_os/project_index/index.py +49 -15
- empathy_os/project_index/models.py +1 -2
- empathy_os/project_index/reports.py +1 -1
- empathy_os/project_index/scanner.py +1 -0
- empathy_os/redis_memory.py +10 -7
- empathy_os/resilience/__init__.py +1 -1
- empathy_os/resilience/health.py +10 -10
- empathy_os/routing/__init__.py +7 -7
- empathy_os/routing/chain_executor.py +37 -37
- empathy_os/routing/classifier.py +36 -36
- empathy_os/routing/smart_router.py +40 -40
- empathy_os/routing/{wizard_registry.py → workflow_registry.py} +47 -47
- empathy_os/scaffolding/__init__.py +8 -8
- empathy_os/scaffolding/__main__.py +1 -1
- empathy_os/scaffolding/cli.py +28 -28
- empathy_os/socratic/__init__.py +3 -19
- empathy_os/socratic/ab_testing.py +25 -36
- empathy_os/socratic/blueprint.py +38 -38
- empathy_os/socratic/cli.py +34 -20
- empathy_os/socratic/collaboration.py +30 -28
- empathy_os/socratic/domain_templates.py +9 -1
- empathy_os/socratic/embeddings.py +17 -13
- empathy_os/socratic/engine.py +135 -70
- empathy_os/socratic/explainer.py +70 -60
- empathy_os/socratic/feedback.py +24 -19
- empathy_os/socratic/forms.py +15 -10
- empathy_os/socratic/generator.py +51 -35
- empathy_os/socratic/llm_analyzer.py +25 -23
- empathy_os/socratic/mcp_server.py +99 -159
- empathy_os/socratic/session.py +19 -13
- empathy_os/socratic/storage.py +98 -67
- empathy_os/socratic/success.py +38 -27
- empathy_os/socratic/visual_editor.py +51 -39
- empathy_os/socratic/web_ui.py +99 -66
- empathy_os/telemetry/cli.py +3 -1
- empathy_os/telemetry/usage_tracker.py +1 -3
- empathy_os/test_generator/__init__.py +3 -3
- empathy_os/test_generator/cli.py +28 -28
- empathy_os/test_generator/generator.py +64 -66
- empathy_os/test_generator/risk_analyzer.py +11 -11
- empathy_os/vscode_bridge 2.py +173 -0
- empathy_os/vscode_bridge.py +173 -0
- empathy_os/workflows/__init__.py +212 -120
- empathy_os/workflows/batch_processing.py +8 -24
- empathy_os/workflows/bug_predict.py +1 -1
- empathy_os/workflows/code_review.py +20 -5
- empathy_os/workflows/code_review_pipeline.py +13 -8
- empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
- empathy_os/workflows/manage_documentation.py +1 -0
- empathy_os/workflows/orchestrated_health_check.py +6 -11
- empathy_os/workflows/orchestrated_release_prep.py +3 -3
- empathy_os/workflows/pr_review.py +18 -10
- empathy_os/workflows/progressive/README 2.md +454 -0
- empathy_os/workflows/progressive/__init__ 2.py +92 -0
- empathy_os/workflows/progressive/__init__.py +2 -12
- empathy_os/workflows/progressive/cli 2.py +242 -0
- empathy_os/workflows/progressive/cli.py +14 -37
- empathy_os/workflows/progressive/core 2.py +488 -0
- empathy_os/workflows/progressive/core.py +12 -12
- empathy_os/workflows/progressive/orchestrator 2.py +701 -0
- empathy_os/workflows/progressive/orchestrator.py +166 -144
- empathy_os/workflows/progressive/reports 2.py +528 -0
- empathy_os/workflows/progressive/reports.py +22 -31
- empathy_os/workflows/progressive/telemetry 2.py +280 -0
- empathy_os/workflows/progressive/telemetry.py +8 -14
- empathy_os/workflows/progressive/test_gen 2.py +514 -0
- empathy_os/workflows/progressive/test_gen.py +29 -48
- empathy_os/workflows/progressive/workflow 2.py +628 -0
- empathy_os/workflows/progressive/workflow.py +31 -70
- empathy_os/workflows/release_prep.py +21 -6
- empathy_os/workflows/release_prep_crew.py +1 -0
- empathy_os/workflows/secure_release.py +13 -6
- empathy_os/workflows/security_audit.py +8 -3
- empathy_os/workflows/test_coverage_boost_crew.py +3 -2
- empathy_os/workflows/test_maintenance_crew.py +1 -0
- empathy_os/workflows/test_runner.py +16 -12
- empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
- empathy_software_plugin/cli.py +0 -122
- patterns/README.md +119 -0
- patterns/__init__.py +95 -0
- patterns/behavior.py +298 -0
- patterns/code_review_memory.json +441 -0
- patterns/core.py +97 -0
- patterns/debugging.json +3763 -0
- patterns/empathy.py +268 -0
- patterns/health_check_memory.json +505 -0
- patterns/input.py +161 -0
- patterns/memory_graph.json +8 -0
- patterns/refactoring_memory.json +1113 -0
- patterns/registry.py +663 -0
- patterns/security_memory.json +8 -0
- patterns/structural.py +415 -0
- patterns/validation.py +194 -0
- coach_wizards/__init__.py +0 -45
- coach_wizards/accessibility_wizard.py +0 -91
- coach_wizards/api_wizard.py +0 -91
- coach_wizards/base_wizard.py +0 -209
- coach_wizards/cicd_wizard.py +0 -91
- coach_wizards/code_reviewer_README.md +0 -60
- coach_wizards/code_reviewer_wizard.py +0 -180
- coach_wizards/compliance_wizard.py +0 -91
- coach_wizards/database_wizard.py +0 -91
- coach_wizards/debugging_wizard.py +0 -91
- coach_wizards/documentation_wizard.py +0 -91
- coach_wizards/generate_wizards.py +0 -347
- coach_wizards/localization_wizard.py +0 -173
- coach_wizards/migration_wizard.py +0 -91
- coach_wizards/monitoring_wizard.py +0 -91
- coach_wizards/observability_wizard.py +0 -91
- coach_wizards/performance_wizard.py +0 -91
- coach_wizards/prompt_engineering_wizard.py +0 -661
- coach_wizards/refactoring_wizard.py +0 -91
- coach_wizards/scaling_wizard.py +0 -90
- coach_wizards/security_wizard.py +0 -92
- coach_wizards/testing_wizard.py +0 -91
- empathy_framework-4.6.6.dist-info/METADATA +0 -1597
- empathy_framework-4.6.6.dist-info/RECORD +0 -410
- empathy_llm_toolkit/wizards/__init__.py +0 -43
- empathy_llm_toolkit/wizards/base_wizard.py +0 -364
- empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
- empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
- empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
- empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
- empathy_os/wizard_factory_cli.py +0 -170
- empathy_software_plugin/wizards/__init__.py +0 -42
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
- empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
- empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
- empathy_software_plugin/wizards/base_wizard.py +0 -288
- empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
- empathy_software_plugin/wizards/code_review_wizard.py +0 -604
- empathy_software_plugin/wizards/debugging/__init__.py +0 -50
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
- empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
- empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
- empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
- empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
- empathy_software_plugin/wizards/debugging/verification.py +0 -369
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
- empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
- empathy_software_plugin/wizards/performance/__init__.py +0 -9
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
- empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
- empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
- empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
- empathy_software_plugin/wizards/security/__init__.py +0 -32
- empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
- empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
- empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
- empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
- empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
- empathy_software_plugin/wizards/testing/__init__.py +0 -27
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
- empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
- empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
- empathy_software_plugin/wizards/testing_wizard.py +0 -274
- wizards/__init__.py +0 -82
- wizards/admission_assessment_wizard.py +0 -644
- wizards/care_plan.py +0 -321
- wizards/clinical_assessment.py +0 -769
- wizards/discharge_planning.py +0 -77
- wizards/discharge_summary_wizard.py +0 -468
- wizards/dosage_calculation.py +0 -497
- wizards/incident_report_wizard.py +0 -454
- wizards/medication_reconciliation.py +0 -85
- wizards/nursing_assessment.py +0 -171
- wizards/patient_education.py +0 -654
- wizards/quality_improvement.py +0 -705
- wizards/sbar_report.py +0 -324
- wizards/sbar_wizard.py +0 -608
- wizards/shift_handoff_wizard.py +0 -535
- wizards/soap_note_wizard.py +0 -679
- wizards/treatment_plan.py +0 -15
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/WHEEL +0 -0
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/entry_points.txt +0 -0
- {empathy_framework-4.6.6.dist-info → empathy_framework-4.7.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -149,7 +149,7 @@ class TFIDFEmbeddingProvider(EmbeddingProvider):
|
|
|
149
149
|
"""Tokenize text into words."""
|
|
150
150
|
# Simple tokenization: lowercase, split on non-alphanumeric
|
|
151
151
|
text = text.lower()
|
|
152
|
-
tokens = re.findall(r
|
|
152
|
+
tokens = re.findall(r"\b[a-z][a-z0-9_]*\b", text)
|
|
153
153
|
return tokens
|
|
154
154
|
|
|
155
155
|
def _compute_tf(self, tokens: list[str]) -> dict[str, float]:
|
|
@@ -255,6 +255,7 @@ class AnthropicEmbeddingProvider(EmbeddingProvider):
|
|
|
255
255
|
if self._client is None and self.api_key:
|
|
256
256
|
try:
|
|
257
257
|
import anthropic
|
|
258
|
+
|
|
258
259
|
self._client = anthropic.Anthropic(api_key=self.api_key)
|
|
259
260
|
except ImportError:
|
|
260
261
|
logger.warning("anthropic package not installed")
|
|
@@ -268,13 +269,13 @@ class AnthropicEmbeddingProvider(EmbeddingProvider):
|
|
|
268
269
|
fallback = TFIDFEmbeddingProvider(dimension=self._dimension)
|
|
269
270
|
return fallback.embed(text)
|
|
270
271
|
|
|
271
|
-
aspects = self.ASPECTS[:self._dimension]
|
|
272
|
+
aspects = self.ASPECTS[: self._dimension]
|
|
272
273
|
prompt = f"""Rate how relevant this goal is to each aspect on a scale of 0.0 to 1.0.
|
|
273
274
|
|
|
274
275
|
Goal: "{text}"
|
|
275
276
|
|
|
276
277
|
Aspects to rate:
|
|
277
|
-
{chr(10).join(f
|
|
278
|
+
{chr(10).join(f"{i + 1}. {aspect}" for i, aspect in enumerate(aspects))}
|
|
278
279
|
|
|
279
280
|
Respond with ONLY a JSON array of numbers, one per aspect, in order.
|
|
280
281
|
Example: [0.8, 0.2, 0.5, ...]"""
|
|
@@ -290,7 +291,7 @@ Example: [0.8, 0.2, 0.5, ...]"""
|
|
|
290
291
|
# Parse JSON array
|
|
291
292
|
scores = json.loads(content.strip())
|
|
292
293
|
if isinstance(scores, list) and len(scores) >= self._dimension:
|
|
293
|
-
return [float(s) for s in scores[:self._dimension]]
|
|
294
|
+
return [float(s) for s in scores[: self._dimension]]
|
|
294
295
|
|
|
295
296
|
except Exception as e:
|
|
296
297
|
logger.warning(f"Anthropic embedding failed: {e}")
|
|
@@ -331,6 +332,7 @@ class SentenceTransformerProvider(EmbeddingProvider):
|
|
|
331
332
|
if self._model is None:
|
|
332
333
|
try:
|
|
333
334
|
from sentence_transformers import SentenceTransformer
|
|
335
|
+
|
|
334
336
|
self._model = SentenceTransformer(self.model_name)
|
|
335
337
|
self._dimension = self._model.get_sentence_embedding_dimension()
|
|
336
338
|
except ImportError:
|
|
@@ -677,15 +679,17 @@ class SemanticGoalMatcher:
|
|
|
677
679
|
formatted = []
|
|
678
680
|
for result in results:
|
|
679
681
|
if result.goal.success_score >= min_success_score:
|
|
680
|
-
formatted.append(
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
682
|
+
formatted.append(
|
|
683
|
+
{
|
|
684
|
+
"goal_id": result.goal.goal_id,
|
|
685
|
+
"goal_text": result.goal.goal_text,
|
|
686
|
+
"similarity": round(result.similarity, 3),
|
|
687
|
+
"workflow_id": result.goal.workflow_id,
|
|
688
|
+
"domains": result.goal.domains,
|
|
689
|
+
"success_score": result.goal.success_score,
|
|
690
|
+
"metadata": result.goal.metadata,
|
|
691
|
+
}
|
|
692
|
+
)
|
|
689
693
|
|
|
690
694
|
if len(formatted) >= top_k:
|
|
691
695
|
break
|
empathy_os/socratic/engine.py
CHANGED
|
@@ -144,9 +144,32 @@ def extract_keywords(goal: str) -> list[str]:
|
|
|
144
144
|
"""Extract important keywords from goal."""
|
|
145
145
|
# Remove common words
|
|
146
146
|
stop_words = {
|
|
147
|
-
"i",
|
|
148
|
-
"
|
|
149
|
-
"
|
|
147
|
+
"i",
|
|
148
|
+
"want",
|
|
149
|
+
"to",
|
|
150
|
+
"the",
|
|
151
|
+
"a",
|
|
152
|
+
"an",
|
|
153
|
+
"my",
|
|
154
|
+
"our",
|
|
155
|
+
"for",
|
|
156
|
+
"with",
|
|
157
|
+
"that",
|
|
158
|
+
"this",
|
|
159
|
+
"is",
|
|
160
|
+
"are",
|
|
161
|
+
"be",
|
|
162
|
+
"will",
|
|
163
|
+
"would",
|
|
164
|
+
"could",
|
|
165
|
+
"should",
|
|
166
|
+
"can",
|
|
167
|
+
"help",
|
|
168
|
+
"me",
|
|
169
|
+
"us",
|
|
170
|
+
"please",
|
|
171
|
+
"need",
|
|
172
|
+
"like",
|
|
150
173
|
}
|
|
151
174
|
|
|
152
175
|
# Extract words
|
|
@@ -162,7 +185,10 @@ def identify_ambiguities(goal: str, domain: str) -> list[str]:
|
|
|
162
185
|
ambiguities = []
|
|
163
186
|
|
|
164
187
|
# Check for missing specifics
|
|
165
|
-
if not any(
|
|
188
|
+
if not any(
|
|
189
|
+
lang in goal.lower()
|
|
190
|
+
for lang in ["python", "javascript", "typescript", "java", "go", "rust"]
|
|
191
|
+
):
|
|
166
192
|
ambiguities.append("Programming language not specified")
|
|
167
193
|
|
|
168
194
|
# Check for vague scope
|
|
@@ -223,50 +249,78 @@ def generate_initial_questions(
|
|
|
223
249
|
|
|
224
250
|
# Domain-specific questions
|
|
225
251
|
if goal_analysis.domain == "code_review":
|
|
226
|
-
fields.append(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
252
|
+
fields.append(
|
|
253
|
+
FormField(
|
|
254
|
+
id="review_scope",
|
|
255
|
+
field_type=FieldType.SINGLE_SELECT,
|
|
256
|
+
label="What scope of review do you need?",
|
|
257
|
+
options=[
|
|
258
|
+
FieldOption(
|
|
259
|
+
"pr",
|
|
260
|
+
"Pull Request/Diff",
|
|
261
|
+
description="Review specific changes",
|
|
262
|
+
recommended=True,
|
|
263
|
+
),
|
|
264
|
+
FieldOption("file", "Single File", description="Deep review of one file"),
|
|
265
|
+
FieldOption(
|
|
266
|
+
"directory", "Directory/Module", description="Review entire module"
|
|
267
|
+
),
|
|
268
|
+
FieldOption(
|
|
269
|
+
"project", "Full Project", description="Comprehensive codebase review"
|
|
270
|
+
),
|
|
271
|
+
],
|
|
272
|
+
validation=FieldValidation(required=True),
|
|
273
|
+
category="scope",
|
|
274
|
+
)
|
|
275
|
+
)
|
|
239
276
|
|
|
240
277
|
if goal_analysis.domain == "security":
|
|
241
|
-
fields.append(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
278
|
+
fields.append(
|
|
279
|
+
FormField(
|
|
280
|
+
id="security_focus",
|
|
281
|
+
field_type=FieldType.MULTI_SELECT,
|
|
282
|
+
label="What security aspects are most important?",
|
|
283
|
+
options=[
|
|
284
|
+
FieldOption("owasp", "OWASP Top 10", description="Common web vulnerabilities"),
|
|
285
|
+
FieldOption("injection", "Injection Attacks", description="SQL, command, XSS"),
|
|
286
|
+
FieldOption(
|
|
287
|
+
"auth", "Authentication/Authorization", description="Access control issues"
|
|
288
|
+
),
|
|
289
|
+
FieldOption(
|
|
290
|
+
"crypto", "Cryptography", description="Encryption, hashing, secrets"
|
|
291
|
+
),
|
|
292
|
+
FieldOption("deps", "Dependencies", description="Vulnerable dependencies"),
|
|
293
|
+
],
|
|
294
|
+
validation=FieldValidation(required=True),
|
|
295
|
+
category="security",
|
|
296
|
+
)
|
|
297
|
+
)
|
|
255
298
|
|
|
256
299
|
if goal_analysis.domain == "testing":
|
|
257
|
-
fields.append(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
300
|
+
fields.append(
|
|
301
|
+
FormField(
|
|
302
|
+
id="test_type",
|
|
303
|
+
field_type=FieldType.MULTI_SELECT,
|
|
304
|
+
label="What types of tests do you need?",
|
|
305
|
+
options=[
|
|
306
|
+
FieldOption(
|
|
307
|
+
"unit",
|
|
308
|
+
"Unit Tests",
|
|
309
|
+
description="Test individual functions",
|
|
310
|
+
recommended=True,
|
|
311
|
+
),
|
|
312
|
+
FieldOption(
|
|
313
|
+
"integration",
|
|
314
|
+
"Integration Tests",
|
|
315
|
+
description="Test component interactions",
|
|
316
|
+
),
|
|
317
|
+
FieldOption("e2e", "End-to-End Tests", description="Test full user flows"),
|
|
318
|
+
FieldOption("edge", "Edge Cases", description="Test boundary conditions"),
|
|
319
|
+
],
|
|
320
|
+
validation=FieldValidation(required=True),
|
|
321
|
+
category="testing",
|
|
322
|
+
)
|
|
323
|
+
)
|
|
270
324
|
|
|
271
325
|
# Automation level (always relevant)
|
|
272
326
|
fields.append(create_automation_level_field())
|
|
@@ -280,7 +334,7 @@ def generate_initial_questions(
|
|
|
280
334
|
return Form(
|
|
281
335
|
id=f"round_{session.current_round + 1}",
|
|
282
336
|
title="Help Us Understand Your Needs",
|
|
283
|
-
description=f
|
|
337
|
+
description=f'Based on your goal: "{goal_analysis.raw_goal[:100]}..."',
|
|
284
338
|
fields=fields,
|
|
285
339
|
round_number=session.current_round + 1,
|
|
286
340
|
progress=0.3,
|
|
@@ -305,14 +359,16 @@ def generate_followup_questions(
|
|
|
305
359
|
|
|
306
360
|
# If no must-haves, ask for priorities
|
|
307
361
|
if not reqs.must_have:
|
|
308
|
-
fields.append(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
362
|
+
fields.append(
|
|
363
|
+
FormField(
|
|
364
|
+
id="priorities",
|
|
365
|
+
field_type=FieldType.TEXT_AREA,
|
|
366
|
+
label="What are your top 3 priorities for this workflow?",
|
|
367
|
+
help_text="Be as specific as possible about what success looks like.",
|
|
368
|
+
validation=FieldValidation(required=True, min_length=20),
|
|
369
|
+
category="priorities",
|
|
370
|
+
)
|
|
371
|
+
)
|
|
316
372
|
|
|
317
373
|
# If technical constraints missing
|
|
318
374
|
if not reqs.technical_constraints.get("languages"):
|
|
@@ -320,18 +376,28 @@ def generate_followup_questions(
|
|
|
320
376
|
|
|
321
377
|
# Domain-specific follow-ups
|
|
322
378
|
if session.goal_analysis and session.goal_analysis.domain == "code_review":
|
|
323
|
-
if
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
379
|
+
if (
|
|
380
|
+
"review_depth" not in [r.get("id") for r in session.question_rounds[-1]["questions"]]
|
|
381
|
+
if session.question_rounds
|
|
382
|
+
else True
|
|
383
|
+
):
|
|
384
|
+
fields.append(
|
|
385
|
+
FormField(
|
|
386
|
+
id="review_depth",
|
|
387
|
+
field_type=FieldType.SINGLE_SELECT,
|
|
388
|
+
label="How thorough should the review be?",
|
|
389
|
+
options=[
|
|
390
|
+
FieldOption(
|
|
391
|
+
"quick", "Quick Scan", description="Fast, surface-level review"
|
|
392
|
+
),
|
|
393
|
+
FieldOption(
|
|
394
|
+
"standard", "Standard", description="Balanced depth", recommended=True
|
|
395
|
+
),
|
|
396
|
+
FieldOption("deep", "Deep Dive", description="Thorough, detailed analysis"),
|
|
397
|
+
],
|
|
398
|
+
category="depth",
|
|
399
|
+
)
|
|
400
|
+
)
|
|
335
401
|
|
|
336
402
|
if not fields:
|
|
337
403
|
return None
|
|
@@ -513,10 +579,7 @@ class SocraticWorkflowBuilder:
|
|
|
513
579
|
current_form = self.get_next_questions(session)
|
|
514
580
|
questions_data = []
|
|
515
581
|
if current_form:
|
|
516
|
-
questions_data = [
|
|
517
|
-
{"id": f.id, "label": f.label}
|
|
518
|
-
for f in current_form.fields
|
|
519
|
-
]
|
|
582
|
+
questions_data = [{"id": f.id, "label": f.label} for f in current_form.fields]
|
|
520
583
|
|
|
521
584
|
session.add_question_round(questions_data, answers)
|
|
522
585
|
|
|
@@ -725,5 +788,7 @@ class SocraticWorkflowBuilder:
|
|
|
725
788
|
"rounds_completed": session.current_round,
|
|
726
789
|
"requirements_completeness": session.requirements.completeness_score(),
|
|
727
790
|
"ready_to_generate": self.is_ready_to_generate(session),
|
|
728
|
-
"ambiguities_remaining":
|
|
791
|
+
"ambiguities_remaining": (
|
|
792
|
+
len(session.goal_analysis.ambiguities) if session.goal_analysis else 0
|
|
793
|
+
),
|
|
729
794
|
}
|
empathy_os/socratic/explainer.py
CHANGED
|
@@ -206,29 +206,37 @@ class WorkflowExplainer:
|
|
|
206
206
|
sections: list[dict[str, str]] = []
|
|
207
207
|
|
|
208
208
|
# Overview section
|
|
209
|
-
sections.append(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
sections.append(
|
|
210
|
+
{
|
|
211
|
+
"heading": "Overview",
|
|
212
|
+
"content": self._explain_overview(blueprint),
|
|
213
|
+
}
|
|
214
|
+
)
|
|
213
215
|
|
|
214
216
|
# Agents section
|
|
215
|
-
sections.append(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
sections.append(
|
|
218
|
+
{
|
|
219
|
+
"heading": "Agents Involved",
|
|
220
|
+
"content": self._explain_agents(blueprint.agents),
|
|
221
|
+
}
|
|
222
|
+
)
|
|
219
223
|
|
|
220
224
|
# Process section
|
|
221
|
-
sections.append(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
+
sections.append(
|
|
226
|
+
{
|
|
227
|
+
"heading": "How It Works",
|
|
228
|
+
"content": self._explain_process(blueprint.stages, blueprint.agents),
|
|
229
|
+
}
|
|
230
|
+
)
|
|
225
231
|
|
|
226
232
|
# Success criteria section (if provided)
|
|
227
233
|
if success_criteria:
|
|
228
|
-
sections.append(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
234
|
+
sections.append(
|
|
235
|
+
{
|
|
236
|
+
"heading": "Success Metrics",
|
|
237
|
+
"content": self._explain_success_criteria(success_criteria),
|
|
238
|
+
}
|
|
239
|
+
)
|
|
232
240
|
|
|
233
241
|
# Summary
|
|
234
242
|
summary = self._generate_summary(blueprint)
|
|
@@ -256,22 +264,28 @@ class WorkflowExplainer:
|
|
|
256
264
|
role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
|
|
257
265
|
agent.role, "performs automated tasks"
|
|
258
266
|
)
|
|
259
|
-
sections.append(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
267
|
+
sections.append(
|
|
268
|
+
{
|
|
269
|
+
"heading": "Role",
|
|
270
|
+
"content": f"This agent {role_desc}.",
|
|
271
|
+
}
|
|
272
|
+
)
|
|
263
273
|
|
|
264
274
|
# Capabilities section
|
|
265
|
-
sections.append(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
275
|
+
sections.append(
|
|
276
|
+
{
|
|
277
|
+
"heading": "Capabilities",
|
|
278
|
+
"content": self._explain_tools(agent.tools),
|
|
279
|
+
}
|
|
280
|
+
)
|
|
269
281
|
|
|
270
282
|
# How it helps section
|
|
271
|
-
sections.append(
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
283
|
+
sections.append(
|
|
284
|
+
{
|
|
285
|
+
"heading": "How It Helps",
|
|
286
|
+
"content": self._explain_agent_value(agent),
|
|
287
|
+
}
|
|
288
|
+
)
|
|
275
289
|
|
|
276
290
|
summary = f"{agent.name} is a {agent.role.value} agent that {agent.goal.lower()}"
|
|
277
291
|
|
|
@@ -298,7 +312,9 @@ class WorkflowExplainer:
|
|
|
298
312
|
f"Target domain: {blueprint.domain}."
|
|
299
313
|
)
|
|
300
314
|
else:
|
|
301
|
-
generated_at =
|
|
315
|
+
generated_at = (
|
|
316
|
+
blueprint.generated_at.strftime("%Y-%m-%d") if blueprint.generated_at else "N/A"
|
|
317
|
+
)
|
|
302
318
|
return (
|
|
303
319
|
f"Multi-agent workflow with {len(blueprint.agents)} agents, "
|
|
304
320
|
f"{len(blueprint.stages)} stages. "
|
|
@@ -317,15 +333,15 @@ class WorkflowExplainer:
|
|
|
317
333
|
for agent_blueprint in agents:
|
|
318
334
|
# Access the AgentSpec via .spec
|
|
319
335
|
spec = agent_blueprint.spec
|
|
320
|
-
role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
|
|
321
|
-
spec.role, "works on the task"
|
|
322
|
-
)
|
|
336
|
+
role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(spec.role, "works on the task")
|
|
323
337
|
|
|
324
338
|
if self.detail_level == DetailLevel.BRIEF:
|
|
325
339
|
lines.append(f"• {spec.name}: {role_desc}")
|
|
326
340
|
else:
|
|
327
341
|
tool_count = len(spec.tools)
|
|
328
|
-
tool_str =
|
|
342
|
+
tool_str = (
|
|
343
|
+
f" ({tool_count} tools)" if self.detail_level == DetailLevel.DETAILED else ""
|
|
344
|
+
)
|
|
329
345
|
lines.append(f"• **{spec.name}**{tool_str}: {spec.goal}")
|
|
330
346
|
|
|
331
347
|
return "\n".join(lines)
|
|
@@ -341,11 +357,7 @@ class WorkflowExplainer:
|
|
|
341
357
|
lines = []
|
|
342
358
|
|
|
343
359
|
for i, stage in enumerate(stages, 1):
|
|
344
|
-
agent_names = [
|
|
345
|
-
agent_lookup[aid].name
|
|
346
|
-
for aid in stage.agent_ids
|
|
347
|
-
if aid in agent_lookup
|
|
348
|
-
]
|
|
360
|
+
agent_names = [agent_lookup[aid].name for aid in stage.agent_ids if aid in agent_lookup]
|
|
349
361
|
|
|
350
362
|
if self.audience == AudienceLevel.BEGINNER:
|
|
351
363
|
if stage.parallel:
|
|
@@ -358,9 +370,7 @@ class WorkflowExplainer:
|
|
|
358
370
|
)
|
|
359
371
|
else:
|
|
360
372
|
parallel_str = " (parallel)" if stage.parallel else ""
|
|
361
|
-
lines.append(
|
|
362
|
-
f"{i}. **{stage.name}**{parallel_str}: {', '.join(agent_names)}"
|
|
363
|
-
)
|
|
373
|
+
lines.append(f"{i}. **{stage.name}**{parallel_str}: {', '.join(agent_names)}")
|
|
364
374
|
|
|
365
375
|
if self.detail_level == DetailLevel.DETAILED and stage.depends_on:
|
|
366
376
|
lines.append(f" Depends on: {', '.join(stage.depends_on)}")
|
|
@@ -384,7 +394,7 @@ class WorkflowExplainer:
|
|
|
384
394
|
|
|
385
395
|
lines = ["This agent can:"]
|
|
386
396
|
for tool in tools:
|
|
387
|
-
tool_id = tool.id if hasattr(tool,
|
|
397
|
+
tool_id = tool.id if hasattr(tool, "id") else str(tool)
|
|
388
398
|
explanation = tool_explanations.get(tool_id, f"use {tool_id}")
|
|
389
399
|
lines.append(f"• {explanation}")
|
|
390
400
|
|
|
@@ -418,7 +428,9 @@ class WorkflowExplainer:
|
|
|
418
428
|
if self.audience == AudienceLevel.BEGINNER:
|
|
419
429
|
lines.append(f"• {metric.name}: {metric.description}")
|
|
420
430
|
else:
|
|
421
|
-
target =
|
|
431
|
+
target = (
|
|
432
|
+
f" (target: {metric.target_value})" if metric.target_value is not None else ""
|
|
433
|
+
)
|
|
422
434
|
lines.append(f"• **{metric.name}**{target}: {metric.description}")
|
|
423
435
|
|
|
424
436
|
return "\n".join(lines)
|
|
@@ -438,7 +450,10 @@ class WorkflowExplainer:
|
|
|
438
450
|
f"to deliver results efficiently and consistently."
|
|
439
451
|
)
|
|
440
452
|
else:
|
|
441
|
-
return
|
|
453
|
+
return (
|
|
454
|
+
blueprint.description
|
|
455
|
+
or f"A {len(blueprint.stages)}-stage workflow for {blueprint.domain}."
|
|
456
|
+
)
|
|
442
457
|
|
|
443
458
|
def generate_narrative(self, blueprint: WorkflowBlueprint) -> str:
|
|
444
459
|
"""Generate a narrative story-like explanation.
|
|
@@ -473,22 +488,16 @@ class WorkflowExplainer:
|
|
|
473
488
|
lines.append(f"### Step {i}: {stage.name}")
|
|
474
489
|
lines.append("")
|
|
475
490
|
|
|
476
|
-
agents_in_stage = [
|
|
477
|
-
agent_lookup[aid] for aid in stage.agent_ids if aid in agent_lookup
|
|
478
|
-
]
|
|
491
|
+
agents_in_stage = [agent_lookup[aid] for aid in stage.agent_ids if aid in agent_lookup]
|
|
479
492
|
|
|
480
493
|
if stage.parallel and len(agents_in_stage) > 1:
|
|
481
494
|
lines.append("Working in parallel:")
|
|
482
495
|
for agent in agents_in_stage:
|
|
483
|
-
role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
|
|
484
|
-
agent.role, "works"
|
|
485
|
-
)
|
|
496
|
+
role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(agent.role, "works")
|
|
486
497
|
lines.append(f"- **{agent.name}** {role_desc}")
|
|
487
498
|
else:
|
|
488
499
|
for agent in agents_in_stage:
|
|
489
|
-
role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(
|
|
490
|
-
agent.role, "works"
|
|
491
|
-
)
|
|
500
|
+
role_desc = ROLE_DESCRIPTIONS.get(self.audience, {}).get(agent.role, "works")
|
|
492
501
|
lines.append(f"**{agent.name}** {role_desc}.")
|
|
493
502
|
|
|
494
503
|
lines.append("")
|
|
@@ -542,6 +551,7 @@ Format as markdown with clear sections."""
|
|
|
542
551
|
if self._client is None and self.api_key:
|
|
543
552
|
try:
|
|
544
553
|
import anthropic
|
|
554
|
+
|
|
545
555
|
self._client = anthropic.Anthropic(api_key=self.api_key)
|
|
546
556
|
except ImportError:
|
|
547
557
|
pass
|
|
@@ -571,13 +581,11 @@ Format as markdown with clear sections."""
|
|
|
571
581
|
|
|
572
582
|
# Format workflow info for prompt
|
|
573
583
|
agents_str = "\n".join(
|
|
574
|
-
f"- {a.name} ({a.role.value}): {a.description}"
|
|
575
|
-
for a in blueprint.agents
|
|
584
|
+
f"- {a.name} ({a.role.value}): {a.description}" for a in blueprint.agents
|
|
576
585
|
)
|
|
577
586
|
|
|
578
587
|
stages_str = "\n".join(
|
|
579
|
-
f"- {s.name}: {', '.join(s.agent_ids)}"
|
|
580
|
-
+ (" (parallel)" if s.parallel else "")
|
|
588
|
+
f"- {s.name}: {', '.join(s.agent_ids)}" + (" (parallel)" if s.parallel else "")
|
|
581
589
|
for s in blueprint.stages
|
|
582
590
|
)
|
|
583
591
|
|
|
@@ -645,9 +653,10 @@ def explain_workflow(
|
|
|
645
653
|
elif format == OutputFormat.TEXT:
|
|
646
654
|
# Simple markdown to text conversion
|
|
647
655
|
import re
|
|
648
|
-
|
|
649
|
-
text = re.sub(r
|
|
650
|
-
text = re.sub(r
|
|
656
|
+
|
|
657
|
+
text = re.sub(r"#{1,6}\s+", "", markdown) # Remove headers
|
|
658
|
+
text = re.sub(r"\*\*([^*]+)\*\*", r"\1", text) # Remove bold
|
|
659
|
+
text = re.sub(r"\*([^*]+)\*", r"\1", text) # Remove italic
|
|
651
660
|
return text
|
|
652
661
|
elif format == OutputFormat.HTML:
|
|
653
662
|
# Simple markdown to HTML
|
|
@@ -667,6 +676,7 @@ def explain_workflow(
|
|
|
667
676
|
return explanation.to_html()
|
|
668
677
|
elif format == OutputFormat.JSON:
|
|
669
678
|
import json
|
|
679
|
+
|
|
670
680
|
return json.dumps(explanation.to_dict(), indent=2)
|
|
671
681
|
else:
|
|
672
682
|
return explanation.to_markdown()
|