empathy-framework 5.1.0__py3-none-any.whl → 5.2.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.
Files changed (73) hide show
  1. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/METADATA +52 -3
  2. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/RECORD +71 -30
  3. empathy_os/__init__.py +1 -1
  4. empathy_os/cli_router.py +21 -0
  5. empathy_os/core_modules/__init__.py +15 -0
  6. empathy_os/mcp/__init__.py +10 -0
  7. empathy_os/mcp/server.py +506 -0
  8. empathy_os/memory/control_panel.py +1 -131
  9. empathy_os/memory/control_panel_support.py +145 -0
  10. empathy_os/memory/encryption.py +159 -0
  11. empathy_os/memory/long_term.py +41 -626
  12. empathy_os/memory/long_term_types.py +99 -0
  13. empathy_os/memory/mixins/__init__.py +25 -0
  14. empathy_os/memory/mixins/backend_init_mixin.py +244 -0
  15. empathy_os/memory/mixins/capabilities_mixin.py +199 -0
  16. empathy_os/memory/mixins/handoff_mixin.py +208 -0
  17. empathy_os/memory/mixins/lifecycle_mixin.py +49 -0
  18. empathy_os/memory/mixins/long_term_mixin.py +352 -0
  19. empathy_os/memory/mixins/promotion_mixin.py +109 -0
  20. empathy_os/memory/mixins/short_term_mixin.py +182 -0
  21. empathy_os/memory/short_term.py +7 -0
  22. empathy_os/memory/simple_storage.py +302 -0
  23. empathy_os/memory/storage_backend.py +167 -0
  24. empathy_os/memory/unified.py +21 -1120
  25. empathy_os/meta_workflows/cli_commands/__init__.py +56 -0
  26. empathy_os/meta_workflows/cli_commands/agent_commands.py +321 -0
  27. empathy_os/meta_workflows/cli_commands/analytics_commands.py +442 -0
  28. empathy_os/meta_workflows/cli_commands/config_commands.py +232 -0
  29. empathy_os/meta_workflows/cli_commands/memory_commands.py +182 -0
  30. empathy_os/meta_workflows/cli_commands/template_commands.py +354 -0
  31. empathy_os/meta_workflows/cli_commands/workflow_commands.py +382 -0
  32. empathy_os/meta_workflows/cli_meta_workflows.py +52 -1802
  33. empathy_os/meta_workflows/intent_detector.py +71 -0
  34. empathy_os/models/telemetry/__init__.py +71 -0
  35. empathy_os/models/telemetry/analytics.py +594 -0
  36. empathy_os/models/telemetry/backend.py +196 -0
  37. empathy_os/models/telemetry/data_models.py +431 -0
  38. empathy_os/models/telemetry/storage.py +489 -0
  39. empathy_os/orchestration/__init__.py +35 -0
  40. empathy_os/orchestration/execution_strategies.py +481 -0
  41. empathy_os/orchestration/meta_orchestrator.py +488 -1
  42. empathy_os/routing/workflow_registry.py +36 -0
  43. empathy_os/telemetry/cli.py +19 -724
  44. empathy_os/telemetry/commands/__init__.py +14 -0
  45. empathy_os/telemetry/commands/dashboard_commands.py +696 -0
  46. empathy_os/tools.py +183 -0
  47. empathy_os/workflows/__init__.py +5 -0
  48. empathy_os/workflows/autonomous_test_gen.py +860 -161
  49. empathy_os/workflows/base.py +6 -2
  50. empathy_os/workflows/code_review.py +4 -1
  51. empathy_os/workflows/document_gen/__init__.py +25 -0
  52. empathy_os/workflows/document_gen/config.py +30 -0
  53. empathy_os/workflows/document_gen/report_formatter.py +162 -0
  54. empathy_os/workflows/document_gen/workflow.py +1426 -0
  55. empathy_os/workflows/document_gen.py +22 -1598
  56. empathy_os/workflows/security_audit.py +2 -2
  57. empathy_os/workflows/security_audit_phase3.py +7 -4
  58. empathy_os/workflows/seo_optimization.py +633 -0
  59. empathy_os/workflows/test_gen/__init__.py +52 -0
  60. empathy_os/workflows/test_gen/ast_analyzer.py +249 -0
  61. empathy_os/workflows/test_gen/config.py +88 -0
  62. empathy_os/workflows/test_gen/data_models.py +38 -0
  63. empathy_os/workflows/test_gen/report_formatter.py +289 -0
  64. empathy_os/workflows/test_gen/test_templates.py +381 -0
  65. empathy_os/workflows/test_gen/workflow.py +655 -0
  66. empathy_os/workflows/test_gen.py +42 -1905
  67. empathy_os/memory/types 2.py +0 -441
  68. empathy_os/models/telemetry.py +0 -1660
  69. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/WHEEL +0 -0
  70. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/entry_points.txt +0 -0
  71. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE +0 -0
  72. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -0
  73. {empathy_framework-5.1.0.dist-info → empathy_framework-5.2.1.dist-info}/top_level.txt +0 -0
@@ -1,1809 +1,59 @@
1
- """CLI commands for meta-workflow system.
1
+ """CLI Commands for Meta-Workflow System (Backward Compatible Entry Point).
2
2
 
3
- Provides command-line interface for:
4
- - Listing available workflow templates
5
- - Running meta-workflows
6
- - Viewing analytics and insights
7
- - Managing execution history
3
+ This module maintains backward compatibility by re-exporting all CLI commands
4
+ from the cli_commands package.
8
5
 
9
- Usage:
10
- empathy meta-workflow list-templates
11
- empathy meta-workflow run <template_id>
12
- empathy meta-workflow analytics [template_id]
13
- empathy meta-workflow list-runs
14
- empathy meta-workflow show <run_id>
6
+ For new code, import from the package directly:
7
+ from empathy_os.meta_workflows.cli_commands import meta_workflow_app
15
8
 
16
- Created: 2026-01-17
9
+ Copyright 2025 Smart-AI-Memory
10
+ Licensed under Fair Source License 0.9
17
11
  """
18
12
 
19
- from datetime import datetime, timedelta
20
- from pathlib import Path
21
-
22
- import typer
23
- from rich.console import Console
24
- from rich.panel import Panel
25
- from rich.table import Table
26
- from rich.tree import Tree
27
-
28
- from empathy_os.config import _validate_file_path
29
- from empathy_os.meta_workflows import (
30
- MetaWorkflow,
31
- PatternLearner,
32
- TemplateRegistry,
33
- list_execution_results,
34
- load_execution_result,
13
+ # Re-export all commands and the Typer app from the package
14
+ from .cli_commands import (
15
+ cleanup_executions,
16
+ create_agent,
17
+ create_team,
18
+ detect_intent,
19
+ generate_plan_cmd,
20
+ inspect_template,
21
+ list_runs,
22
+ list_templates,
23
+ meta_workflow_app,
24
+ natural_language_run,
25
+ run_workflow,
26
+ search_memory,
27
+ show_analytics,
28
+ show_execution,
29
+ show_migration_guide,
30
+ show_session_stats,
31
+ suggest_defaults_cmd,
35
32
  )
36
- from empathy_os.meta_workflows.intent_detector import IntentDetector
37
-
38
- # Create Typer app for meta-workflow commands
39
- meta_workflow_app = typer.Typer(
40
- name="meta-workflow",
41
- help="Meta-workflow system for dynamic agent team generation",
42
- no_args_is_help=True,
43
- )
44
-
45
- console = Console()
46
-
47
-
48
- # =============================================================================
49
- # Template Commands
50
- # =============================================================================
51
-
52
-
53
- @meta_workflow_app.command("list-templates")
54
- def list_templates(
55
- storage_dir: str = typer.Option(
56
- ".empathy/meta_workflows/templates",
57
- "--storage-dir",
58
- "-d",
59
- help="Templates storage directory",
60
- ),
61
- ):
62
- """List all available workflow templates.
63
-
64
- Shows template metadata including:
65
- - Template ID and name
66
- - Description
67
- - Estimated cost range
68
- - Number of questions and agent rules
69
- """
70
- try:
71
- registry = TemplateRegistry(storage_dir=storage_dir)
72
- template_ids = registry.list_templates()
73
-
74
- if not template_ids:
75
- console.print("[yellow]No templates found.[/yellow]")
76
- console.print(f"\nLooking in: {storage_dir}")
77
- console.print("\nCreate templates by running workflow workflow or")
78
- console.print("placing template JSON files in the templates directory.")
79
- return
80
-
81
- # Count built-in vs user templates
82
- builtin_count = sum(1 for t in template_ids if registry.is_builtin(t))
83
- user_count = len(template_ids) - builtin_count
84
-
85
- console.print(f"\n[bold]Available Templates[/bold] ({len(template_ids)} total)")
86
- console.print(
87
- f" [cyan]📦 Built-in:[/cyan] {builtin_count} [green]👤 User:[/green] {user_count}\n"
88
- )
89
-
90
- # Show migration hint for users coming from Crew workflows
91
- if builtin_count > 0:
92
- console.print(
93
- "[dim]💡 Tip: Built-in templates replace deprecated Crew workflows.[/dim]"
94
- )
95
- console.print("[dim] See: empathy meta-workflow migrate --help[/dim]\n")
96
-
97
- for template_id in template_ids:
98
- template = registry.load_template(template_id)
99
-
100
- if template:
101
- # Add badge for built-in templates
102
- is_builtin = registry.is_builtin(template_id)
103
- badge = "[cyan]📦 BUILT-IN[/cyan]" if is_builtin else "[green]👤 USER[/green]"
104
-
105
- # Create info panel
106
- info_lines = [
107
- f"[bold]{template.name}[/bold] {badge}",
108
- f"[dim]{template.description}[/dim]",
109
- "",
110
- f"ID: {template.template_id}",
111
- f"Version: {template.version}",
112
- f"Author: {template.author}",
113
- f"Tags: {', '.join(template.tags)}",
114
- "",
115
- f"Questions: {len(template.form_schema.questions)}",
116
- f"Agent Rules: {len(template.agent_composition_rules)}",
117
- "",
118
- f"Est. Cost: ${template.estimated_cost_range[0]:.2f}-${template.estimated_cost_range[1]:.2f}",
119
- f"Est. Duration: ~{template.estimated_duration_minutes} min",
120
- ]
121
-
122
- # Add quick start command
123
- info_lines.append("")
124
- info_lines.append(
125
- f"[bold]Quick Start:[/bold] empathy meta-workflow run {template_id}"
126
- )
127
-
128
- console.print(
129
- Panel("\n".join(info_lines), border_style="blue" if is_builtin else "green")
130
- )
131
- console.print()
132
-
133
- except Exception as e:
134
- console.print(f"[red]Error:[/red] {e}")
135
- raise typer.Exit(code=1)
136
-
137
-
138
- @meta_workflow_app.command("inspect")
139
- def inspect_template(
140
- template_id: str = typer.Argument(..., help="Template ID to inspect"),
141
- storage_dir: str = typer.Option(
142
- ".empathy/meta_workflows/templates",
143
- "--storage-dir",
144
- "-d",
145
- help="Templates storage directory",
146
- ),
147
- show_rules: bool = typer.Option(
148
- False,
149
- "--show-rules",
150
- "-r",
151
- help="Show agent composition rules",
152
- ),
153
- ):
154
- """Inspect a specific template in detail.
155
-
156
- Shows comprehensive template information including:
157
- - Form questions and types
158
- - Agent composition rules (optional)
159
- - Configuration mappings
160
- """
161
- try:
162
- registry = TemplateRegistry(storage_dir=storage_dir)
163
- template = registry.load_template(template_id)
164
-
165
- if not template:
166
- console.print(f"[red]Template not found:[/red] {template_id}")
167
- raise typer.Exit(code=1)
168
-
169
- # Header
170
- console.print(f"\n[bold cyan]Template: {template.name}[/bold cyan]")
171
- console.print(f"[dim]{template.description}[/dim]\n")
172
-
173
- # Form Schema
174
- console.print("[bold]Form Questions:[/bold]")
175
- form_tree = Tree("📋 Questions")
176
-
177
- for i, question in enumerate(template.form_schema.questions, 1):
178
- question_text = f"[cyan]{question.text}[/cyan]"
179
- q_node = form_tree.add(f"{i}. {question_text}")
180
- q_node.add(f"ID: {question.id}")
181
- q_node.add(f"Type: {question.type.value}")
182
- if question.options:
183
- options_str = ", ".join(question.options[:3])
184
- if len(question.options) > 3:
185
- options_str += f", ... ({len(question.options) - 3} more)"
186
- q_node.add(f"Options: {options_str}")
187
- if question.required:
188
- q_node.add("[yellow]Required[/yellow]")
189
- if question.default:
190
- q_node.add(f"Default: {question.default}")
191
-
192
- console.print(form_tree)
193
-
194
- # Agent Composition Rules (optional)
195
- if show_rules:
196
- console.print(
197
- f"\n[bold]Agent Composition Rules:[/bold] ({len(template.agent_composition_rules)})\n"
198
- )
199
-
200
- for i, rule in enumerate(template.agent_composition_rules, 1):
201
- rule_lines = [
202
- f"[bold cyan]{i}. {rule.role}[/bold cyan]",
203
- f" Base Template: {rule.base_template}",
204
- f" Tier Strategy: {rule.tier_strategy.value}",
205
- f" Tools: {', '.join(rule.tools) if rule.tools else 'None'}",
206
- ]
207
-
208
- if rule.required_responses:
209
- rule_lines.append(f" Required When: {rule.required_responses}")
210
-
211
- if rule.config_mapping:
212
- rule_lines.append(f" Config Mapping: {len(rule.config_mapping)} fields")
213
-
214
- console.print("\n".join(rule_lines))
215
- console.print()
216
-
217
- # Summary
218
- console.print("\n[bold]Summary:[/bold]")
219
- console.print(f" Questions: {len(template.form_schema.questions)}")
220
- console.print(f" Agent Rules: {len(template.agent_composition_rules)}")
221
- console.print(
222
- f" Estimated Cost: ${template.estimated_cost_range[0]:.2f}-${template.estimated_cost_range[1]:.2f}"
223
- )
224
- console.print()
225
-
226
- except Exception as e:
227
- console.print(f"[red]Error:[/red] {e}")
228
- raise typer.Exit(code=1)
229
-
230
-
231
- # =============================================================================
232
- # Plan Generation Commands (Claude Code Integration)
233
- # =============================================================================
234
-
235
-
236
- @meta_workflow_app.command("plan")
237
- def generate_plan_cmd(
238
- template_id: str = typer.Argument(..., help="Template ID to generate plan for"),
239
- output_format: str = typer.Option(
240
- "markdown",
241
- "--format",
242
- "-f",
243
- help="Output format: markdown, skill, or json",
244
- ),
245
- output_file: str = typer.Option(
246
- None,
247
- "--output",
248
- "-o",
249
- help="Output file path (default: stdout)",
250
- ),
251
- use_defaults: bool = typer.Option(
252
- True,
253
- "--use-defaults/--interactive",
254
- help="Use default values or ask interactively",
255
- ),
256
- install_skill: bool = typer.Option(
257
- False,
258
- "--install",
259
- "-i",
260
- help="Install as Claude Code skill in .claude/commands/",
261
- ),
262
- ):
263
- """Generate execution plan for Claude Code (no API costs).
264
-
265
- This generates a plan that can be executed by Claude Code using your
266
- Max subscription instead of making API calls.
267
-
268
- Output formats:
269
- - markdown: Human-readable plan to paste into Claude Code
270
- - skill: Claude Code skill format for .claude/commands/
271
- - json: Structured format for programmatic use
272
-
273
- Examples:
274
- empathy meta-workflow plan release-prep
275
- empathy meta-workflow plan release-prep --format skill --install
276
- empathy meta-workflow plan test-coverage-boost -o plan.md
277
- empathy meta-workflow plan manage-docs --format json
278
- """
279
- try:
280
- from empathy_os.meta_workflows.plan_generator import generate_plan
281
-
282
- # Load template
283
- console.print(f"\n[bold]Generating plan for:[/bold] {template_id}")
284
- registry = TemplateRegistry()
285
- template = registry.load_template(template_id)
286
-
287
- if not template:
288
- console.print(f"[red]Template not found:[/red] {template_id}")
289
- raise typer.Exit(code=1)
290
-
291
- # Collect responses if interactive
292
- form_responses = None
293
- if not use_defaults and template.form_schema.questions:
294
- console.print("\n[bold]Configuration:[/bold]")
295
- form_responses = {}
296
- for question in template.form_schema.questions:
297
- if question.options:
298
- # Multiple choice
299
- console.print(f"\n{question.text}")
300
- for i, opt in enumerate(question.options, 1):
301
- default_mark = " (default)" if opt == question.default else ""
302
- console.print(f" {i}. {opt}{default_mark}")
303
- choice = typer.prompt("Choice", default="1")
304
- try:
305
- idx = int(choice) - 1
306
- form_responses[question.id] = question.options[idx]
307
- except (ValueError, IndexError):
308
- form_responses[question.id] = question.default or question.options[0]
309
- else:
310
- # Yes/No or text
311
- default = question.default or "Yes"
312
- response = typer.prompt(question.text, default=default)
313
- form_responses[question.id] = response
314
-
315
- # Generate plan
316
- plan_content = generate_plan(
317
- template_id=template_id,
318
- form_responses=form_responses,
319
- use_defaults=use_defaults,
320
- output_format=output_format,
321
- )
322
-
323
- # Handle output
324
- if install_skill:
325
- # Install as Claude Code skill
326
- skill_dir = Path(".claude/commands")
327
- skill_dir.mkdir(parents=True, exist_ok=True)
328
- skill_path = skill_dir / f"{template_id}.md"
329
-
330
- # Convert to skill format if not already
331
- if output_format != "skill":
332
- plan_content = generate_plan(
333
- template_id=template_id,
334
- form_responses=form_responses,
335
- use_defaults=use_defaults,
336
- output_format="skill",
337
- )
338
-
339
- validated_skill_path = _validate_file_path(str(skill_path))
340
- validated_skill_path.write_text(plan_content)
341
- console.print(
342
- f"\n[green]✓ Installed as Claude Code skill:[/green] {validated_skill_path}"
343
- )
344
- console.print(f"\nRun with: [bold]/project:{template_id}[/bold]")
345
-
346
- elif output_file:
347
- # Write to file
348
- validated_output = _validate_file_path(output_file)
349
- validated_output.write_text(plan_content)
350
- console.print(f"\n[green]✓ Plan saved to:[/green] {validated_output}")
351
-
352
- else:
353
- # Print to stdout
354
- console.print("\n" + "=" * 60)
355
- console.print(plan_content)
356
- console.print("=" * 60)
357
-
358
- # Show usage hints
359
- console.print("\n[bold]Usage Options:[/bold]")
360
- console.print("1. Copy prompts into Claude Code conversation")
361
- console.print("2. Install as skill with: --install")
362
- console.print("3. Use with Claude Code Task tool")
363
- console.print("\n[dim]Cost: $0 (uses your Max subscription)[/dim]")
364
-
365
- except ImportError:
366
- console.print("[red]Plan generator not available.[/red]")
367
- console.print("This feature requires the plan_generator module.")
368
- raise typer.Exit(code=1)
369
- except Exception as e:
370
- console.print(f"[red]Error generating plan:[/red] {e}")
371
- raise typer.Exit(code=1)
372
-
373
-
374
- # =============================================================================
375
- # Execution Commands
376
- # =============================================================================
377
-
378
-
379
- @meta_workflow_app.command("run")
380
- def run_workflow(
381
- template_id: str = typer.Argument(..., help="Template ID to execute"),
382
- mock: bool = typer.Option(
383
- True,
384
- "--mock/--real",
385
- help="Use mock execution (for testing)",
386
- ),
387
- use_memory: bool = typer.Option(
388
- False,
389
- "--use-memory",
390
- "-m",
391
- help="Enable memory integration for enhanced analytics",
392
- ),
393
- use_defaults: bool = typer.Option(
394
- False,
395
- "--use-defaults",
396
- "-d",
397
- help="Use default values instead of asking questions (non-interactive mode)",
398
- ),
399
- user_id: str = typer.Option(
400
- "cli_user",
401
- "--user-id",
402
- "-u",
403
- help="User ID for memory integration",
404
- ),
405
- json_output: bool = typer.Option(
406
- False,
407
- "--json",
408
- "-j",
409
- help="Output result as JSON (for programmatic use)",
410
- ),
411
- ):
412
- """Execute a meta-workflow from template.
413
-
414
- This will:
415
- 1. Load the template
416
- 2. Ask form questions interactively (or use defaults with --use-defaults)
417
- 3. Generate dynamic agent team
418
- 4. Execute agents (mock or real)
419
- 5. Save results (files + optional memory)
420
- 6. Display summary
421
-
422
- Examples:
423
- empathy meta-workflow run release-prep
424
- empathy meta-workflow run test-coverage-boost --real
425
- empathy meta-workflow run manage-docs --use-defaults
426
- empathy meta-workflow run release-prep --json --use-defaults
427
- """
428
- import json
429
-
430
- try:
431
- # Load template
432
- if not json_output:
433
- console.print(f"\n[bold]Loading template:[/bold] {template_id}")
434
- registry = TemplateRegistry()
435
- template = registry.load_template(template_id)
436
-
437
- if not template:
438
- if json_output:
439
- print(json.dumps({"success": False, "error": f"Template not found: {template_id}"}))
440
- else:
441
- console.print(f"[red]Template not found:[/red] {template_id}")
442
- raise typer.Exit(code=1)
443
-
444
- if not json_output:
445
- console.print(f"[green]✓[/green] {template.name}")
446
-
447
- # Setup memory if requested
448
- pattern_learner = None
449
- if use_memory:
450
- if not json_output:
451
- console.print("\n[bold]Initializing memory integration...[/bold]")
452
- from empathy_os.memory.unified import UnifiedMemory
453
-
454
- try:
455
- memory = UnifiedMemory(user_id=user_id)
456
- pattern_learner = PatternLearner(memory=memory)
457
- if not json_output:
458
- console.print("[green]✓[/green] Memory enabled")
459
- except Exception as e:
460
- if not json_output:
461
- console.print(f"[yellow]Warning:[/yellow] Memory initialization failed: {e}")
462
- console.print("[yellow]Continuing without memory integration[/yellow]")
463
-
464
- # Create workflow
465
- workflow = MetaWorkflow(
466
- template=template,
467
- pattern_learner=pattern_learner,
468
- )
469
-
470
- # Execute (will ask questions via AskUserQuestion unless --use-defaults)
471
- if not json_output:
472
- console.print("\n[bold]Executing workflow...[/bold]")
473
- console.print(f"Mode: {'Mock' if mock else 'Real'}")
474
- if use_defaults:
475
- console.print("[cyan]Using default values (non-interactive)[/cyan]")
476
-
477
- result = workflow.execute(mock_execution=mock, use_defaults=use_defaults)
478
-
479
- # JSON output mode - print result as JSON and exit
480
- if json_output:
481
- output = {
482
- "run_id": result.run_id,
483
- "template_id": template_id,
484
- "timestamp": result.timestamp,
485
- "success": result.success,
486
- "error": result.error,
487
- "total_cost": result.total_cost,
488
- "total_duration": result.total_duration,
489
- "agents_created": len(result.agents_created),
490
- "form_responses": {
491
- "template_id": result.form_responses.template_id,
492
- "responses": result.form_responses.responses,
493
- "timestamp": result.form_responses.timestamp,
494
- "response_id": result.form_responses.response_id,
495
- },
496
- "agent_results": [
497
- {
498
- "agent_id": ar.agent_id,
499
- "role": ar.role,
500
- "success": ar.success,
501
- "cost": ar.cost,
502
- "duration": ar.duration,
503
- "tier_used": ar.tier_used,
504
- "output": ar.output,
505
- "error": ar.error,
506
- }
507
- for ar in result.agent_results
508
- ],
509
- }
510
- print(json.dumps(output))
511
- return
512
-
513
- # Display summary (normal mode)
514
- console.print("\n[bold green]Execution Complete![/bold green]\n")
515
-
516
- summary_lines = [
517
- f"[bold]Run ID:[/bold] {result.run_id}",
518
- f"[bold]Status:[/bold] {'✅ Success' if result.success else '❌ Failed'}",
519
- "",
520
- f"[bold]Agents Created:[/bold] {len(result.agents_created)}",
521
- f"[bold]Agents Executed:[/bold] {len(result.agent_results)}",
522
- f"[bold]Total Cost:[/bold] ${result.total_cost:.2f}",
523
- f"[bold]Duration:[/bold] {result.total_duration:.1f}s",
524
- ]
525
-
526
- if result.error:
527
- summary_lines.append(f"\n[bold red]Error:[/bold red] {result.error}")
528
-
529
- console.print(
530
- Panel("\n".join(summary_lines), title="Execution Summary", border_style="green")
531
- )
532
-
533
- # Show agents
534
- console.print("\n[bold]Agents Executed:[/bold]\n")
535
-
536
- for agent_result in result.agent_results:
537
- status = "✅" if agent_result.success else "❌"
538
- console.print(
539
- f" {status} [cyan]{agent_result.role}[/cyan] "
540
- f"(tier: {agent_result.tier_used}, cost: ${agent_result.cost:.2f})"
541
- )
542
-
543
- # Show where results saved
544
- console.print("\n[bold]Results saved to:[/bold]")
545
- console.print(f" 📁 Files: .empathy/meta_workflows/executions/{result.run_id}/")
546
- if use_memory and pattern_learner and pattern_learner.memory:
547
- console.print(" 🧠 Memory: Long-term storage")
548
-
549
- console.print(f"\n[dim]View details: empathy meta-workflow show {result.run_id}[/dim]")
550
- console.print()
551
-
552
- except Exception as e:
553
- if json_output:
554
- print(json.dumps({"success": False, "error": str(e)}))
555
- else:
556
- console.print(f"\n[red]Error:[/red] {e}")
557
- import traceback
558
-
559
- traceback.print_exc()
560
- raise typer.Exit(code=1)
561
-
562
-
563
- @meta_workflow_app.command("ask")
564
- def natural_language_run(
565
- request: str = typer.Argument(..., help="Natural language description of what you need"),
566
- auto_run: bool = typer.Option(
567
- False,
568
- "--auto",
569
- "-a",
570
- help="Automatically run if high confidence match (>60%)",
571
- ),
572
- mock: bool = typer.Option(
573
- True,
574
- "--mock/--real",
575
- help="Use mock execution (for testing)",
576
- ),
577
- use_defaults: bool = typer.Option(
578
- True,
579
- "--use-defaults/--interactive",
580
- "-d/-i",
581
- help="Use default values (non-interactive)",
582
- ),
583
- ):
584
- """Create agent teams using natural language.
585
-
586
- Analyzes your request and suggests appropriate agent teams.
587
- Use --auto to automatically run the best match.
588
-
589
- Examples:
590
- empathy meta-workflow ask "I need to prepare for a release"
591
- empathy meta-workflow ask "improve my test coverage" --auto --real
592
- empathy meta-workflow ask "check if documentation is up to date"
593
- """
594
- try:
595
- detector = IntentDetector()
596
- matches = detector.detect(request)
597
-
598
- if not matches:
599
- console.print(
600
- "\n[yellow]I couldn't identify a matching agent team for your request.[/yellow]"
601
- )
602
- console.print("\n[bold]Available agent teams:[/bold]")
603
- console.print(
604
- " • [cyan]release-prep[/cyan] - Security, testing, code quality, documentation checks"
605
- )
606
- console.print(
607
- " • [cyan]test-coverage-boost[/cyan] - Analyze and improve test coverage"
608
- )
609
- console.print(" • [cyan]test-maintenance[/cyan] - Test lifecycle management")
610
- console.print(" • [cyan]manage-docs[/cyan] - Documentation sync and gap detection")
611
- console.print("\n[dim]Try: empathy meta-workflow run <template-id>[/dim]\n")
612
- return
613
-
614
- # Show detected matches
615
- console.print(f'\n[bold]Analyzing:[/bold] "{request}"\n')
616
-
617
- best_match = matches[0]
618
- confidence_pct = int(best_match.confidence * 100)
619
-
620
- # If auto-run and high confidence, run immediately
621
- if auto_run and best_match.confidence >= 0.6:
622
- console.print(
623
- f"[bold green]Auto-detected:[/bold green] {best_match.template_name} ({confidence_pct}% confidence)"
624
- )
625
- console.print(f"[dim]{best_match.description}[/dim]\n")
626
- console.print(f"[bold]Running {best_match.template_id}...[/bold]\n")
627
-
628
- # Run the workflow
629
- run_workflow(
630
- template_id=best_match.template_id,
631
- mock=mock,
632
- use_memory=False,
633
- use_defaults=use_defaults,
634
- user_id="cli_user",
635
- )
636
- return
637
-
638
- # Show suggestions
639
- console.print("[bold]Suggested Agent Teams:[/bold]\n")
640
-
641
- for i, match in enumerate(matches[:3], 1):
642
- confidence = int(match.confidence * 100)
643
- style = (
644
- "green"
645
- if match.confidence >= 0.6
646
- else "yellow" if match.confidence >= 0.4 else "dim"
647
- )
648
-
649
- console.print(f" {i}. [{style}]{match.template_name}[/{style}] ({confidence}% match)")
650
- console.print(f" [dim]{match.description}[/dim]")
651
- if match.matched_keywords:
652
- keywords = ", ".join(match.matched_keywords[:5])
653
- console.print(f" [dim]Matched: {keywords}[/dim]")
654
- console.print(f" Run: [cyan]empathy meta-workflow run {match.template_id}[/cyan]")
655
- console.print()
656
-
657
- # Prompt to run best match
658
- if best_match.confidence >= 0.5:
659
- console.print(
660
- "[bold]Quick Run:[/bold] Use [cyan]--auto[/cyan] to automatically run the best match"
661
- )
662
- console.print(
663
- f'[dim]Example: empathy meta-workflow ask "{request}" --auto --real[/dim]\n'
664
- )
665
-
666
- except Exception as e:
667
- console.print(f"[red]Error:[/red] {e}")
668
- raise typer.Exit(code=1)
669
-
670
-
671
- @meta_workflow_app.command("detect")
672
- def detect_intent(
673
- request: str = typer.Argument(..., help="Natural language request to analyze"),
674
- threshold: float = typer.Option(
675
- 0.3,
676
- "--threshold",
677
- "-t",
678
- help="Minimum confidence threshold (0.0-1.0)",
679
- ),
680
- ):
681
- """Detect intent from natural language without running.
682
-
683
- Useful for testing what agent teams would be suggested for a given request.
684
-
685
- Examples:
686
- empathy meta-workflow detect "check security vulnerabilities"
687
- empathy meta-workflow detect "generate more tests" --threshold 0.5
688
- """
689
- try:
690
- detector = IntentDetector()
691
- matches = detector.detect(request, threshold=threshold)
692
-
693
- console.print(f'\n[bold]Intent Analysis:[/bold] "{request}"\n')
694
- console.print(f"[dim]Threshold: {threshold:.0%}[/dim]\n")
695
-
696
- if not matches:
697
- console.print("[yellow]No matches above threshold.[/yellow]\n")
698
- return
699
-
700
- # Create table
701
- table = Table(show_header=True)
702
- table.add_column("Template", style="cyan")
703
- table.add_column("Confidence", justify="right")
704
- table.add_column("Matched Keywords")
705
- table.add_column("Would Auto-Run?")
706
-
707
- for match in matches:
708
- confidence = f"{match.confidence:.0%}"
709
- keywords = ", ".join(match.matched_keywords[:4])
710
- auto_run = "✅ Yes" if match.confidence >= 0.6 else "❌ No"
711
-
712
- table.add_row(
713
- match.template_id,
714
- confidence,
715
- keywords or "-",
716
- auto_run,
717
- )
718
-
719
- console.print(table)
720
- console.print()
721
-
722
- except Exception as e:
723
- console.print(f"[red]Error:[/red] {e}")
724
- raise typer.Exit(code=1)
725
-
726
-
727
- # =============================================================================
728
- # Analytics Commands
729
- # =============================================================================
730
-
731
-
732
- @meta_workflow_app.command("analytics")
733
- def show_analytics(
734
- template_id: str | None = typer.Argument(
735
- None,
736
- help="Template ID to analyze (optional, all if not specified)",
737
- ),
738
- min_confidence: float = typer.Option(
739
- 0.5,
740
- "--min-confidence",
741
- "-c",
742
- help="Minimum confidence threshold (0.0-1.0)",
743
- ),
744
- use_memory: bool = typer.Option(
745
- False,
746
- "--use-memory",
747
- "-m",
748
- help="Use memory-enhanced analytics",
749
- ),
750
- ):
751
- """Show pattern learning analytics and recommendations.
752
-
753
- Displays:
754
- - Execution statistics
755
- - Tier performance insights
756
- - Cost analysis
757
- - Recommendations
758
- """
759
- try:
760
- # Initialize pattern learner
761
- pattern_learner = PatternLearner()
762
-
763
- if use_memory:
764
- console.print("[bold]Initializing memory-enhanced analytics...[/bold]\n")
765
- from empathy_os.memory.unified import UnifiedMemory
766
-
767
- memory = UnifiedMemory(user_id="cli_analytics")
768
- pattern_learner = PatternLearner(memory=memory)
769
-
770
- # Generate report
771
- report = pattern_learner.generate_analytics_report(template_id=template_id)
772
-
773
- # Display summary
774
- summary = report["summary"]
775
-
776
- console.print("\n[bold cyan]Meta-Workflow Analytics Report[/bold cyan]")
777
- if template_id:
778
- console.print(f"[dim]Template: {template_id}[/dim]")
779
- console.print()
780
-
781
- summary_table = Table(show_header=False, box=None)
782
- summary_table.add_column("Metric", style="bold")
783
- summary_table.add_column("Value")
784
-
785
- summary_table.add_row("Total Runs", str(summary["total_runs"]))
786
- summary_table.add_row(
787
- "Successful", f"{summary['successful_runs']} ({summary['success_rate']:.0%})"
788
- )
789
- summary_table.add_row("Total Cost", f"${summary['total_cost']:.2f}")
790
- summary_table.add_row("Avg Cost/Run", f"${summary['avg_cost_per_run']:.2f}")
791
- summary_table.add_row("Total Agents", str(summary["total_agents_created"]))
792
- summary_table.add_row("Avg Agents/Run", f"{summary['avg_agents_per_run']:.1f}")
793
-
794
- console.print(Panel(summary_table, title="Summary", border_style="cyan"))
795
-
796
- # Recommendations
797
- recommendations = report.get("recommendations", [])
798
- if recommendations:
799
- console.print("\n[bold]Recommendations:[/bold]\n")
800
- for rec in recommendations:
801
- console.print(f" {rec}")
802
-
803
- # Insights
804
- insights = report.get("insights", {})
805
-
806
- if insights.get("tier_performance"):
807
- console.print("\n[bold]Tier Performance:[/bold]\n")
808
- for insight in insights["tier_performance"][:5]: # Top 5
809
- console.print(f" • {insight['description']}")
810
- console.print(
811
- f" [dim]Confidence: {insight['confidence']:.0%} (n={insight['sample_size']})[/dim]"
812
- )
813
-
814
- if insights.get("cost_analysis"):
815
- console.print("\n[bold]Cost Analysis:[/bold]\n")
816
- for insight in insights["cost_analysis"]:
817
- console.print(f" • {insight['description']}")
818
-
819
- # Tier breakdown
820
- breakdown = insight["data"].get("tier_breakdown", {})
821
- if breakdown:
822
- console.print("\n [dim]By Tier:[/dim]")
823
- for tier, stats in breakdown.items():
824
- console.print(
825
- f" {tier}: ${stats['avg']:.2f} avg "
826
- f"(${stats['total']:.2f} total, {stats['count']} runs)"
827
- )
828
-
829
- if insights.get("failure_analysis"):
830
- console.print("\n[bold yellow]Failure Analysis:[/bold yellow]\n")
831
- for insight in insights["failure_analysis"]:
832
- console.print(f" ⚠️ {insight['description']}")
833
-
834
- console.print()
835
-
836
- except Exception as e:
837
- console.print(f"[red]Error:[/red] {e}")
838
- raise typer.Exit(code=1)
839
-
840
-
841
- # =============================================================================
842
- # Execution History Commands
843
- # =============================================================================
844
-
845
-
846
- @meta_workflow_app.command("list-runs")
847
- def list_runs(
848
- template_id: str | None = typer.Option(
849
- None,
850
- "--template",
851
- "-t",
852
- help="Filter by template ID",
853
- ),
854
- limit: int = typer.Option(
855
- 10,
856
- "--limit",
857
- "-n",
858
- help="Maximum number of results",
859
- ),
860
- ):
861
- """List execution history.
862
-
863
- Shows recent workflow executions with:
864
- - Run ID and timestamp
865
- - Template name
866
- - Success status
867
- - Cost and duration
868
- """
869
- try:
870
- run_ids = list_execution_results()
871
-
872
- if not run_ids:
873
- console.print("[yellow]No execution results found.[/yellow]")
874
- return
875
-
876
- console.print(
877
- f"\n[bold]Recent Executions[/bold] (showing {min(limit, len(run_ids))} of {len(run_ids)}):\n"
878
- )
879
-
880
- # Create table
881
- table = Table(show_header=True)
882
- table.add_column("Run ID", style="cyan")
883
- table.add_column("Template")
884
- table.add_column("Status")
885
- table.add_column("Cost", justify="right")
886
- table.add_column("Duration", justify="right")
887
- table.add_column("Timestamp")
888
-
889
- count = 0
890
- for run_id in run_ids[:limit]:
891
- try:
892
- result = load_execution_result(run_id)
893
-
894
- # Filter by template if specified
895
- if template_id and result.template_id != template_id:
896
- continue
897
-
898
- status = "✅" if result.success else "❌"
899
- cost = f"${result.total_cost:.2f}"
900
- duration = f"{result.total_duration:.1f}s"
901
-
902
- # Parse timestamp
903
- try:
904
- ts = datetime.fromisoformat(result.timestamp)
905
- timestamp = ts.strftime("%Y-%m-%d %H:%M")
906
- except Exception:
907
- timestamp = result.timestamp[:16]
908
-
909
- table.add_row(
910
- run_id,
911
- result.template_id,
912
- status,
913
- cost,
914
- duration,
915
- timestamp,
916
- )
917
-
918
- count += 1
919
-
920
- except Exception as e:
921
- console.print(f"[yellow]Warning:[/yellow] Failed to load {run_id}: {e}")
922
- continue
923
-
924
- if count == 0:
925
- if template_id:
926
- console.print(f"[yellow]No executions found for template: {template_id}[/yellow]")
927
- else:
928
- console.print("[yellow]No valid execution results found.[/yellow]")
929
- return
930
-
931
- console.print(table)
932
- console.print("\n[dim]View details: empathy meta-workflow show <run_id>[/dim]\n")
933
-
934
- except Exception as e:
935
- console.print(f"[red]Error:[/red] {e}")
936
- raise typer.Exit(code=1)
937
-
938
-
939
- @meta_workflow_app.command("show")
940
- def show_execution(
941
- run_id: str = typer.Argument(..., help="Run ID to display"),
942
- format: str = typer.Option(
943
- "text",
944
- "--format",
945
- "-f",
946
- help="Output format (text or json)",
947
- ),
948
- ):
949
- """Show detailed execution report.
950
-
951
- Displays comprehensive information about a specific workflow execution:
952
- - Form responses
953
- - Agents created and executed
954
- - Cost breakdown
955
- - Success/failure details
956
- """
957
- try:
958
- result = load_execution_result(run_id)
959
-
960
- if format == "json":
961
- # JSON output
962
- print(result.to_json())
963
- return
964
-
965
- # Text format (default)
966
- console.print(f"\n[bold cyan]Execution Report: {run_id}[/bold cyan]\n")
967
-
968
- # Status
969
- status = "✅ Success" if result.success else "❌ Failed"
970
- console.print(f"[bold]Status:[/bold] {status}")
971
- console.print(f"[bold]Template:[/bold] {result.template_id}")
972
- console.print(f"[bold]Timestamp:[/bold] {result.timestamp}")
973
-
974
- if result.error:
975
- console.print(f"\n[bold red]Error:[/bold red] {result.error}\n")
976
-
977
- # Summary
978
- console.print("\n[bold]Summary:[/bold]")
979
- console.print(f" Agents Created: {len(result.agents_created)}")
980
- console.print(f" Agents Executed: {len(result.agent_results)}")
981
- console.print(f" Total Cost: ${result.total_cost:.2f}")
982
- console.print(f" Duration: {result.total_duration:.1f}s")
983
-
984
- # Form Responses
985
- console.print("\n[bold]Form Responses:[/bold]\n")
986
- for key, value in result.form_responses.responses.items():
987
- console.print(f" [cyan]{key}:[/cyan] {value}")
988
-
989
- # Agents
990
- console.print("\n[bold]Agents Executed:[/bold]\n")
991
- for i, agent_result in enumerate(result.agent_results, 1):
992
- status_emoji = "✅" if agent_result.success else "❌"
993
- console.print(f" {i}. {status_emoji} [cyan]{agent_result.role}[/cyan]")
994
- console.print(f" Tier: {agent_result.tier_used}")
995
- console.print(f" Cost: ${agent_result.cost:.2f}")
996
- console.print(f" Duration: {agent_result.duration:.1f}s")
997
- if agent_result.error:
998
- console.print(f" [red]Error: {agent_result.error}[/red]")
999
- console.print()
1000
-
1001
- # Cost breakdown
1002
- console.print("[bold]Cost Breakdown by Tier:[/bold]\n")
1003
- tier_costs = {}
1004
- for agent_result in result.agent_results:
1005
- tier = agent_result.tier_used
1006
- tier_costs[tier] = tier_costs.get(tier, 0.0) + agent_result.cost
1007
-
1008
- for tier, cost in sorted(tier_costs.items()):
1009
- console.print(f" {tier}: ${cost:.2f}")
1010
-
1011
- console.print()
1012
-
1013
- except FileNotFoundError:
1014
- console.print(f"[red]Execution not found:[/red] {run_id}")
1015
- console.print("\n[dim]List available runs: empathy meta-workflow list-runs[/dim]")
1016
- raise typer.Exit(code=1)
1017
- except Exception as e:
1018
- console.print(f"[red]Error:[/red] {e}")
1019
- raise typer.Exit(code=1)
1020
-
1021
-
1022
- # =============================================================================
1023
- # Maintenance Commands
1024
- # =============================================================================
1025
-
1026
-
1027
- @meta_workflow_app.command("cleanup")
1028
- def cleanup_executions(
1029
- older_than_days: int = typer.Option(
1030
- 30,
1031
- "--older-than",
1032
- "-d",
1033
- help="Delete executions older than N days",
1034
- ),
1035
- dry_run: bool = typer.Option(
1036
- False,
1037
- "--dry-run",
1038
- help="Show what would be deleted without deleting",
1039
- ),
1040
- template_id: str | None = typer.Option(
1041
- None,
1042
- "--template",
1043
- "-t",
1044
- help="Filter by template ID",
1045
- ),
1046
- ):
1047
- """Clean up old execution results.
1048
-
1049
- Deletes execution directories older than the specified number of days.
1050
- Use --dry-run to preview what would be deleted.
1051
- """
1052
- try:
1053
- cutoff_date = datetime.now() - timedelta(days=older_than_days)
1054
-
1055
- run_ids = list_execution_results()
1056
-
1057
- if not run_ids:
1058
- console.print("[yellow]No execution results found.[/yellow]")
1059
- return
1060
-
1061
- to_delete = []
1062
-
1063
- for run_id in run_ids:
1064
- try:
1065
- result = load_execution_result(run_id)
1066
-
1067
- # Filter by template if specified
1068
- if template_id and result.template_id != template_id:
1069
- continue
1070
-
1071
- # Parse timestamp
1072
- ts = datetime.fromisoformat(result.timestamp)
1073
-
1074
- if ts < cutoff_date:
1075
- to_delete.append((run_id, result, ts))
1076
-
1077
- except Exception as e:
1078
- console.print(f"[yellow]Warning:[/yellow] Failed to load {run_id}: {e}")
1079
- continue
1080
-
1081
- if not to_delete:
1082
- console.print(f"[green]No executions older than {older_than_days} days found.[/green]")
1083
- return
1084
-
1085
- # Show what will be deleted
1086
- console.print(f"\n[bold]Executions to delete:[/bold] ({len(to_delete)})\n")
1087
-
1088
- table = Table(show_header=True)
1089
- table.add_column("Run ID", style="cyan")
1090
- table.add_column("Template")
1091
- table.add_column("Age (days)", justify="right")
1092
- table.add_column("Cost", justify="right")
1093
-
1094
- total_cost_saved = 0.0
1095
- for run_id, result, ts in to_delete:
1096
- age_days = (datetime.now() - ts).days
1097
- table.add_row(
1098
- run_id,
1099
- result.template_id,
1100
- str(age_days),
1101
- f"${result.total_cost:.2f}",
1102
- )
1103
- total_cost_saved += result.total_cost
1104
-
1105
- console.print(table)
1106
- console.print(f"\nTotal cost represented: ${total_cost_saved:.2f}")
1107
-
1108
- if dry_run:
1109
- console.print("\n[yellow]DRY RUN - No files deleted[/yellow]")
1110
- console.print(f"Run without --dry-run to delete {len(to_delete)} executions")
1111
- return
1112
-
1113
- # Confirm deletion
1114
- if not typer.confirm(f"\nDelete {len(to_delete)} execution(s)?"):
1115
- console.print("[yellow]Cancelled[/yellow]")
1116
- return
1117
-
1118
- # Delete
1119
- import shutil
1120
-
1121
- deleted = 0
1122
- for run_id, _, _ in to_delete:
1123
- try:
1124
- run_dir = Path.home() / ".empathy" / "meta_workflows" / "executions" / run_id
1125
- if run_dir.exists():
1126
- shutil.rmtree(run_dir)
1127
- deleted += 1
1128
- except Exception as e:
1129
- console.print(f"[red]Failed to delete {run_id}:[/red] {e}")
1130
-
1131
- console.print(f"\n[green]✓ Deleted {deleted} execution(s)[/green]\n")
1132
-
1133
- except Exception as e:
1134
- console.print(f"[red]Error:[/red] {e}")
1135
- raise typer.Exit(code=1)
1136
-
1137
-
1138
- # =============================================================================
1139
- # Memory Search Commands
1140
- # =============================================================================
1141
-
1142
-
1143
- @meta_workflow_app.command("search-memory")
1144
- def search_memory(
1145
- query: str = typer.Argument(..., help="Search query for patterns"),
1146
- pattern_type: str | None = typer.Option(
1147
- None,
1148
- "--type",
1149
- "-t",
1150
- help="Filter by pattern type (e.g., 'meta_workflow_execution')",
1151
- ),
1152
- limit: int = typer.Option(
1153
- 10,
1154
- "--limit",
1155
- "-l",
1156
- help="Maximum number of results to return",
1157
- ),
1158
- user_id: str = typer.Option(
1159
- "cli_user",
1160
- "--user-id",
1161
- "-u",
1162
- help="User ID for memory access",
1163
- ),
1164
- ):
1165
- """Search memory for patterns using keyword matching.
1166
-
1167
- Searches long-term memory for patterns matching the query.
1168
- Uses relevance scoring: exact phrase (10 pts), keyword in content (2 pts),
1169
- keyword in metadata (1 pt).
1170
-
1171
- Examples:
1172
- empathy meta-workflow search-memory "successful workflow"
1173
- empathy meta-workflow search-memory "test coverage" --type meta_workflow_execution
1174
- empathy meta-workflow search-memory "error" --limit 20
1175
- """
1176
- try:
1177
- from empathy_os.memory.unified import UnifiedMemory
1178
-
1179
- console.print(f"\n[bold]Searching memory for:[/bold] '{query}'")
1180
- if pattern_type:
1181
- console.print(f"[dim]Pattern type: {pattern_type}[/dim]")
1182
- console.print()
1183
-
1184
- # Initialize memory
1185
- memory = UnifiedMemory(user_id=user_id)
1186
-
1187
- # Search
1188
- results = memory.search_patterns(
1189
- query=query,
1190
- pattern_type=pattern_type,
1191
- limit=limit,
1192
- )
1193
-
1194
- if not results:
1195
- console.print("[yellow]No matching patterns found.[/yellow]\n")
1196
- return
1197
-
1198
- # Display results
1199
- console.print(f"[green]Found {len(results)} matching pattern(s):[/green]\n")
1200
-
1201
- for i, pattern in enumerate(results, 1):
1202
- panel = Panel(
1203
- f"[bold]Pattern ID:[/bold] {pattern.get('pattern_id', 'N/A')}\n"
1204
- f"[bold]Type:[/bold] {pattern.get('pattern_type', 'N/A')}\n"
1205
- f"[bold]Classification:[/bold] {pattern.get('classification', 'N/A')}\n\n"
1206
- f"[bold]Content:[/bold]\n{str(pattern.get('content', 'N/A'))[:200]}...\n\n"
1207
- f"[bold]Metadata:[/bold] {pattern.get('metadata', {})}",
1208
- title=f"Result {i}/{len(results)}",
1209
- border_style="blue",
1210
- )
1211
- console.print(panel)
1212
- console.print()
1213
-
1214
- except ImportError:
1215
- console.print(
1216
- "[red]Error:[/red] UnifiedMemory not available. Ensure memory module is installed."
1217
- )
1218
- raise typer.Exit(code=1)
1219
- except Exception as e:
1220
- console.print(f"[red]Error:[/red] {e}")
1221
- raise typer.Exit(code=1)
1222
-
1223
-
1224
- # =============================================================================
1225
- # Session Context Commands
1226
- # =============================================================================
1227
-
1228
-
1229
- @meta_workflow_app.command("session-stats")
1230
- def show_session_stats(
1231
- session_id: str | None = typer.Option(
1232
- None,
1233
- "--session-id",
1234
- "-s",
1235
- help="Session ID (optional, creates new if not specified)",
1236
- ),
1237
- user_id: str = typer.Option(
1238
- "cli_user",
1239
- "--user-id",
1240
- "-u",
1241
- help="User ID for session",
1242
- ),
1243
- ):
1244
- """Show session context statistics.
1245
-
1246
- Displays information about user's session including:
1247
- - Recent form choices
1248
- - Templates used
1249
- - Choice counts
1250
-
1251
- Examples:
1252
- empathy meta-workflow session-stats
1253
- empathy meta-workflow session-stats --session-id sess_123
1254
- """
1255
- try:
1256
- from empathy_os.memory.unified import UnifiedMemory
1257
- from empathy_os.meta_workflows.session_context import SessionContext
1258
-
1259
- # Initialize memory and session
1260
- memory = UnifiedMemory(user_id=user_id)
1261
- session = SessionContext(
1262
- memory=memory,
1263
- session_id=session_id,
1264
- )
1265
-
1266
- console.print("\n[bold]Session Statistics[/bold]")
1267
- console.print(f"[dim]Session ID: {session.session_id}[/dim]")
1268
- console.print(f"[dim]User ID: {session.user_id}[/dim]\n")
1269
-
1270
- # Get stats
1271
- stats = session.get_session_stats()
1272
-
1273
- # Display
1274
- table = Table(show_header=True)
1275
- table.add_column("Metric", style="cyan")
1276
- table.add_column("Value")
1277
-
1278
- table.add_row("Total Choices", str(stats.get("choice_count", 0)))
1279
- table.add_row("Templates Used", str(len(stats.get("templates_used", []))))
1280
- table.add_row("Most Recent Choice", stats.get("most_recent_choice_timestamp", "N/A"))
1281
-
1282
- console.print(table)
1283
- console.print()
1284
-
1285
- # Show templates used
1286
- templates = stats.get("templates_used", [])
1287
- if templates:
1288
- console.print("[bold]Templates Used:[/bold]")
1289
- for template_id in templates:
1290
- console.print(f" • {template_id}")
1291
- console.print()
1292
-
1293
- except ImportError:
1294
- console.print(
1295
- "[red]Error:[/red] Session context not available. "
1296
- "Ensure memory and session modules are installed."
1297
- )
1298
- raise typer.Exit(code=1)
1299
- except Exception as e:
1300
- console.print(f"[red]Error:[/red] {e}")
1301
- raise typer.Exit(code=1)
1302
-
1303
-
1304
- @meta_workflow_app.command("suggest-defaults")
1305
- def suggest_defaults_cmd(
1306
- template_id: str = typer.Argument(..., help="Template ID to get defaults for"),
1307
- session_id: str | None = typer.Option(
1308
- None,
1309
- "--session-id",
1310
- "-s",
1311
- help="Session ID (optional)",
1312
- ),
1313
- user_id: str = typer.Option(
1314
- "cli_user",
1315
- "--user-id",
1316
- "-u",
1317
- help="User ID for session",
1318
- ),
1319
- ):
1320
- """Get suggested default values based on session history.
1321
-
1322
- Analyzes recent choices for the specified template and suggests
1323
- intelligent defaults for the next run.
1324
-
1325
- Examples:
1326
- empathy meta-workflow suggest-defaults test_creation_management_workflow
1327
- empathy meta-workflow suggest-defaults python_package_publish --session-id sess_123
1328
- """
1329
- try:
1330
- from empathy_os.memory.unified import UnifiedMemory
1331
- from empathy_os.meta_workflows.session_context import SessionContext
1332
-
1333
- # Initialize
1334
- memory = UnifiedMemory(user_id=user_id)
1335
- session = SessionContext(memory=memory, session_id=session_id)
1336
-
1337
- # Load template
1338
- registry = TemplateRegistry()
1339
- template = registry.load_template(template_id)
1340
- if not template:
1341
- console.print(f"[red]Error:[/red] Template not found: {template_id}")
1342
- raise typer.Exit(code=1)
1343
-
1344
- console.print(f"\n[bold]Suggested Defaults for:[/bold] {template.name}")
1345
- console.print(f"[dim]Template ID: {template_id}[/dim]\n")
1346
-
1347
- # Get suggestions
1348
- defaults = session.suggest_defaults(
1349
- template_id=template_id,
1350
- form_schema=template.form_schema,
1351
- )
1352
-
1353
- if not defaults:
1354
- console.print("[yellow]No suggestions available (no recent history).[/yellow]\n")
1355
- return
1356
-
1357
- # Display
1358
- console.print(f"[green]Found {len(defaults)} suggested default(s):[/green]\n")
1359
-
1360
- table = Table(show_header=True)
1361
- table.add_column("Question ID", style="cyan")
1362
- table.add_column("Suggested Value")
1363
-
1364
- for question_id, value in defaults.items():
1365
- # Find the question to get the display text
1366
- question = next(
1367
- (q for q in template.form_schema.questions if q.id == question_id), None
1368
- )
1369
- question_text = question.text if question else question_id
1370
-
1371
- value_str = str(value)
1372
- if isinstance(value, list):
1373
- value_str = ", ".join(str(v) for v in value)
1374
-
1375
- table.add_row(question_text, value_str)
1376
-
1377
- console.print(table)
1378
- console.print(
1379
- f"\n[dim]Use these defaults by running:[/dim]\n"
1380
- f" empathy meta-workflow run {template_id} --use-defaults\n"
1381
- )
1382
-
1383
- except ImportError:
1384
- console.print(
1385
- "[red]Error:[/red] Session context not available. "
1386
- "Ensure memory and session modules are installed."
1387
- )
1388
- raise typer.Exit(code=1)
1389
- except Exception as e:
1390
- console.print(f"[red]Error:[/red] {e}")
1391
- raise typer.Exit(code=1)
1392
-
1393
-
1394
- # =============================================================================
1395
- # Migration Commands
1396
- # =============================================================================
1397
-
1398
-
1399
- @meta_workflow_app.command("migrate")
1400
- def show_migration_guide(
1401
- crew_name: str | None = typer.Argument(
1402
- None,
1403
- help="Specific Crew workflow name (optional)",
1404
- ),
1405
- ):
1406
- """Show migration guide from deprecated Crew workflows.
1407
-
1408
- Displays information about migrating from the deprecated Crew-based
1409
- workflows to the new meta-workflow system.
1410
-
1411
- Examples:
1412
- empathy meta-workflow migrate
1413
- empathy meta-workflow migrate ReleasePreparationCrew
1414
- """
1415
- # Migration mapping
1416
- CREW_MIGRATION_MAP = {
1417
- "ReleasePreparationCrew": {
1418
- "template_id": "release-prep",
1419
- "old_import": "from empathy_os.workflows.release_prep_crew import ReleasePreparationCrew",
1420
- "old_usage": "crew = ReleasePreparationCrew(project_root='.')\nresult = await crew.execute()",
1421
- "new_usage": "empathy meta-workflow run release-prep",
1422
- },
1423
- "TestCoverageBoostCrew": {
1424
- "template_id": "test-coverage-boost",
1425
- "old_import": "from empathy_os.workflows.test_coverage_boost_crew import TestCoverageBoostCrew",
1426
- "old_usage": "crew = TestCoverageBoostCrew(target_coverage=85.0)\nresult = await crew.execute()",
1427
- "new_usage": "empathy meta-workflow run test-coverage-boost",
1428
- },
1429
- "TestMaintenanceCrew": {
1430
- "template_id": "test-maintenance",
1431
- "old_import": "from empathy_os.workflows.test_maintenance_crew import TestMaintenanceCrew",
1432
- "old_usage": "crew = TestMaintenanceCrew('.')\nresult = await crew.run(mode='full')",
1433
- "new_usage": "empathy meta-workflow run test-maintenance",
1434
- },
1435
- "ManageDocumentationCrew": {
1436
- "template_id": "manage-docs",
1437
- "old_import": "from empathy_os.workflows.manage_documentation import ManageDocumentationCrew",
1438
- "old_usage": "crew = ManageDocumentationCrew()\nresult = await crew.execute(path='./src')",
1439
- "new_usage": "empathy meta-workflow run manage-docs",
1440
- },
1441
- }
1442
-
1443
- console.print("\n[bold cyan]🔄 Crew → Meta-Workflow Migration Guide[/bold cyan]\n")
1444
-
1445
- if crew_name:
1446
- # Show specific migration
1447
- if crew_name not in CREW_MIGRATION_MAP:
1448
- console.print(f"[red]Unknown Crew workflow:[/red] {crew_name}")
1449
- console.print("\n[bold]Available Crew workflows:[/bold]")
1450
- for name in CREW_MIGRATION_MAP:
1451
- console.print(f" • {name}")
1452
- raise typer.Exit(code=1)
1453
-
1454
- info = CREW_MIGRATION_MAP[crew_name]
1455
- console.print(f"[bold]Migrating:[/bold] {crew_name}\n")
1456
-
1457
- console.print("[bold red]DEPRECATED (Before):[/bold red]")
1458
- console.print(f"[dim]{info['old_import']}[/dim]")
1459
- console.print(f"\n[yellow]{info['old_usage']}[/yellow]\n")
1460
-
1461
- console.print("[bold green]RECOMMENDED (After):[/bold green]")
1462
- console.print(f"[green]{info['new_usage']}[/green]\n")
1463
-
1464
- console.print("[bold]Benefits:[/bold]")
1465
- console.print(" ✓ No CrewAI/LangChain dependency required")
1466
- console.print(" ✓ Interactive configuration via Socratic questions")
1467
- console.print(" ✓ Automatic cost optimization with tier escalation")
1468
- console.print(" ✓ Session context for learning preferences")
1469
- console.print(" ✓ Built-in analytics and pattern learning\n")
1470
-
1471
- console.print(f"[dim]Try it now: empathy meta-workflow run {info['template_id']}[/dim]\n")
1472
-
1473
- else:
1474
- # Show overview
1475
- console.print("[bold]Why Migrate?[/bold]")
1476
- console.print(" The Crew-based workflows are deprecated since v4.3.0.")
1477
- console.print(" The meta-workflow system provides the same functionality")
1478
- console.print(" with better cost optimization and no extra dependencies.\n")
1479
-
1480
- # Show migration table
1481
- table = Table(title="Migration Map", show_header=True)
1482
- table.add_column("Deprecated Crew", style="yellow")
1483
- table.add_column("Meta-Workflow Command", style="green")
1484
- table.add_column("Template ID", style="cyan")
1485
-
1486
- for crew_name, info in CREW_MIGRATION_MAP.items():
1487
- table.add_row(
1488
- crew_name,
1489
- info["new_usage"],
1490
- info["template_id"],
1491
- )
1492
-
1493
- console.print(table)
1494
-
1495
- console.print("\n[bold]Quick Start:[/bold]")
1496
- console.print(
1497
- " 1. List available templates: [cyan]empathy meta-workflow list-templates[/cyan]"
1498
- )
1499
- console.print(" 2. Run a workflow: [cyan]empathy meta-workflow run release-prep[/cyan]")
1500
- console.print(" 3. View results: [cyan]empathy meta-workflow list-runs[/cyan]\n")
1501
-
1502
- console.print("[bold]More Details:[/bold]")
1503
- console.print(" • Migration guide: [dim]empathy meta-workflow migrate <CrewName>[/dim]")
1504
- console.print(" • Full documentation: [dim]docs/CREWAI_MIGRATION.md[/dim]\n")
1505
-
1506
-
1507
- # =============================================================================
1508
- # Dynamic Agent/Team Creation Commands (v4.4)
1509
- # =============================================================================
1510
-
1511
-
1512
- @meta_workflow_app.command("create-agent")
1513
- def create_agent(
1514
- interactive: bool = typer.Option(
1515
- True,
1516
- "--interactive/--quick",
1517
- "-i/-q",
1518
- help="Use interactive Socratic-guided creation",
1519
- ),
1520
- name: str = typer.Option(
1521
- None,
1522
- "--name",
1523
- "-n",
1524
- help="Agent name (for quick mode)",
1525
- ),
1526
- role: str = typer.Option(
1527
- None,
1528
- "--role",
1529
- "-r",
1530
- help="Agent role description (for quick mode)",
1531
- ),
1532
- tier: str = typer.Option(
1533
- "capable",
1534
- "--tier",
1535
- "-t",
1536
- help="Model tier: cheap, capable, or premium",
1537
- ),
1538
- output_file: str = typer.Option(
1539
- None,
1540
- "--output",
1541
- "-o",
1542
- help="Save agent spec to file",
1543
- ),
1544
- ):
1545
- """Create a custom AI agent with Socratic-guided questions.
1546
-
1547
- Interactive mode asks clarifying questions to help you define:
1548
- - Agent capabilities and responsibilities
1549
- - Model tier selection (cost vs quality tradeoff)
1550
- - Tools and success criteria
1551
-
1552
- Quick mode creates an agent directly from provided options.
1553
-
1554
- Examples:
1555
- empathy meta-workflow create-agent --interactive
1556
- empathy meta-workflow create-agent -q --name "SecurityBot" --role "Scan for vulnerabilities"
1557
- """
1558
- import json
1559
-
1560
- if interactive:
1561
- console.print("\n[bold cyan]🤖 Create Custom Agent - Socratic Guide[/bold cyan]\n")
1562
- console.print("[dim]I'll ask you a few questions to help define your agent.[/dim]\n")
1563
-
1564
- # Question 1: Purpose
1565
- console.print("[bold]1. What should this agent do?[/bold]")
1566
- purpose = typer.prompt(" Describe the agent's main purpose")
1567
-
1568
- # Question 2: Specific tasks
1569
- console.print("\n[bold]2. What specific tasks will it perform?[/bold]")
1570
- console.print(
1571
- " [dim]Examples: analyze code, generate tests, review PRs, write docs[/dim]"
1572
- )
1573
- tasks = typer.prompt(" List main tasks (comma-separated)")
1574
-
1575
- # Question 3: Tier selection
1576
- console.print("\n[bold]3. What quality/cost balance do you need?[/bold]")
1577
- console.print(" [dim]cheap[/dim] - Fast & low-cost, good for simple analysis")
1578
- console.print(" [dim]capable[/dim] - Balanced, good for most development tasks")
1579
- console.print(" [dim]premium[/dim] - Highest quality, for complex reasoning")
1580
- tier = typer.prompt(" Select tier", default="capable")
1581
-
1582
- # Question 4: Tools
1583
- console.print("\n[bold]4. What tools should it have access to?[/bold]")
1584
- console.print(" [dim]Examples: file_read, file_write, web_search, code_exec[/dim]")
1585
- tools_input = typer.prompt(" List tools (comma-separated, or 'none')", default="none")
1586
- tools = [t.strip() for t in tools_input.split(",")] if tools_input != "none" else []
1587
-
1588
- # Question 5: Success criteria
1589
- console.print("\n[bold]5. How will you measure success?[/bold]")
1590
- success = typer.prompt(" Describe success criteria")
1591
-
1592
- # Generate name from purpose
1593
- name = purpose.split()[0].title() + "Agent" if not name else name
1594
-
1595
- # Build agent spec
1596
- agent_spec = {
1597
- "name": name,
1598
- "role": purpose,
1599
- "tasks": [t.strip() for t in tasks.split(",")],
1600
- "tier": tier,
1601
- "tools": tools,
1602
- "success_criteria": success,
1603
- "base_template": "generic",
1604
- }
1605
-
1606
- else:
1607
- # Quick mode
1608
- if not name or not role:
1609
- console.print("[red]Error:[/red] --name and --role required in quick mode")
1610
- console.print("[dim]Use --interactive for guided creation[/dim]")
1611
- raise typer.Exit(code=1)
1612
-
1613
- agent_spec = {
1614
- "name": name,
1615
- "role": role,
1616
- "tier": tier,
1617
- "tools": [],
1618
- "success_criteria": "Task completed successfully",
1619
- "base_template": "generic",
1620
- }
1621
-
1622
- # Display result
1623
- console.print("\n[bold green]✓ Agent Specification Created[/bold green]\n")
1624
-
1625
- spec_json = json.dumps(agent_spec, indent=2)
1626
- console.print(Panel(spec_json, title=f"Agent: {agent_spec['name']}", border_style="green"))
1627
-
1628
- # Save if requested
1629
- if output_file:
1630
- validated_output = _validate_file_path(output_file)
1631
- validated_output.write_text(spec_json)
1632
- console.print(f"\n[green]Saved to:[/green] {validated_output}")
1633
-
1634
- # Show usage
1635
- console.print("\n[bold]Next Steps:[/bold]")
1636
- console.print(
1637
- " 1. Use this agent in a custom team: [cyan]empathy meta-workflow create-team[/cyan]"
1638
- )
1639
- console.print(" 2. Or add to an existing template manually")
1640
- console.print(f"\n[dim]Agent tier '{tier}' will cost approximately:")
1641
- costs = {"cheap": "$0.001-0.01", "capable": "$0.01-0.05", "premium": "$0.05-0.20"}
1642
- console.print(f" {costs.get(tier, costs['capable'])} per execution[/dim]\n")
1643
-
1644
-
1645
- @meta_workflow_app.command("create-team")
1646
- def create_team(
1647
- interactive: bool = typer.Option(
1648
- True,
1649
- "--interactive/--quick",
1650
- "-i/-q",
1651
- help="Use interactive Socratic-guided creation",
1652
- ),
1653
- name: str = typer.Option(
1654
- None,
1655
- "--name",
1656
- "-n",
1657
- help="Team name (for quick mode)",
1658
- ),
1659
- goal: str = typer.Option(
1660
- None,
1661
- "--goal",
1662
- "-g",
1663
- help="Team goal description (for quick mode)",
1664
- ),
1665
- output_file: str = typer.Option(
1666
- None,
1667
- "--output",
1668
- "-o",
1669
- help="Save team template to file",
1670
- ),
1671
- ):
1672
- """Create a custom AI agent team with Socratic-guided workflow.
1673
-
1674
- Interactive mode asks clarifying questions to help you define:
1675
- - Team composition and agent roles
1676
- - Collaboration pattern (sequential, parallel, mixed)
1677
- - Success criteria and cost estimates
1678
-
1679
- Examples:
1680
- empathy meta-workflow create-team --interactive
1681
- empathy meta-workflow create-team -q --name "ReviewTeam" --goal "Code review pipeline"
1682
- """
1683
- import json
1684
-
1685
- if interactive:
1686
- console.print("\n[bold cyan]👥 Create Custom Agent Team - Socratic Guide[/bold cyan]\n")
1687
- console.print("[dim]I'll help you design a team of agents that work together.[/dim]\n")
1688
-
1689
- # Question 1: Goal
1690
- console.print("[bold]1. What is the team's overall goal?[/bold]")
1691
- console.print(" [dim]Example: prepare code for production release[/dim]")
1692
- goal = typer.prompt(" Describe the team's mission")
1693
-
1694
- # Question 2: Agent count
1695
- console.print("\n[bold]2. How many agents should be on this team?[/bold]")
1696
- console.print(" [dim]Typical teams have 2-5 agents with specialized roles[/dim]")
1697
- agent_count = typer.prompt(" Number of agents", default="3")
1698
- agent_count = int(agent_count)
1699
-
1700
- # Question 3: Agent roles
1701
- console.print(f"\n[bold]3. Define {agent_count} agent roles:[/bold]")
1702
- console.print(
1703
- " [dim]Common roles: analyst, reviewer, generator, validator, reporter[/dim]"
1704
- )
1705
-
1706
- agents = []
1707
- for i in range(agent_count):
1708
- console.print(f"\n [bold]Agent {i + 1}:[/bold]")
1709
- role = typer.prompt(" Role name")
1710
- purpose = typer.prompt(" What does this agent do?")
1711
- tier = typer.prompt(" Tier (cheap/capable/premium)", default="capable")
1712
-
1713
- agents.append(
1714
- {
1715
- "role": role,
1716
- "purpose": purpose,
1717
- "tier": tier,
1718
- "base_template": "generic",
1719
- }
1720
- )
1721
-
1722
- # Question 4: Collaboration pattern
1723
- console.print("\n[bold]4. How should agents collaborate?[/bold]")
1724
- console.print(" [dim]sequential[/dim] - Each agent waits for the previous one")
1725
- console.print(" [dim]parallel[/dim] - All agents run simultaneously")
1726
- console.print(" [dim]mixed[/dim] - Some parallel, then sequential synthesis")
1727
- pattern = typer.prompt(" Collaboration pattern", default="sequential")
1728
-
1729
- # Question 5: Team name
1730
- console.print("\n[bold]5. What should we call this team?[/bold]")
1731
- name = typer.prompt(" Team name", default=goal.split()[0].title() + "Team")
1732
-
1733
- # Build team template
1734
- team_template = {
1735
- "id": name.lower().replace(" ", "-"),
1736
- "name": name,
1737
- "description": goal,
1738
- "collaboration_pattern": pattern,
1739
- "agents": agents,
1740
- "estimated_cost_range": {
1741
- "min": len(agents) * 0.01,
1742
- "max": len(agents) * 0.15,
1743
- },
1744
- }
1745
-
1746
- else:
1747
- # Quick mode
1748
- if not name or not goal:
1749
- console.print("[red]Error:[/red] --name and --goal required in quick mode")
1750
- console.print("[dim]Use --interactive for guided creation[/dim]")
1751
- raise typer.Exit(code=1)
1752
-
1753
- # Create a default 3-agent team
1754
- team_template = {
1755
- "id": name.lower().replace(" ", "-"),
1756
- "name": name,
1757
- "description": goal,
1758
- "collaboration_pattern": "sequential",
1759
- "agents": [
1760
- {
1761
- "role": "Analyst",
1762
- "purpose": "Analyze requirements",
1763
- "tier": "cheap",
1764
- "base_template": "generic",
1765
- },
1766
- {
1767
- "role": "Executor",
1768
- "purpose": "Perform main task",
1769
- "tier": "capable",
1770
- "base_template": "generic",
1771
- },
1772
- {
1773
- "role": "Validator",
1774
- "purpose": "Verify results",
1775
- "tier": "capable",
1776
- "base_template": "generic",
1777
- },
1778
- ],
1779
- "estimated_cost_range": {"min": 0.03, "max": 0.45},
1780
- }
1781
-
1782
- # Display result
1783
- console.print("\n[bold green]✓ Agent Team Template Created[/bold green]\n")
1784
-
1785
- spec_json = json.dumps(team_template, indent=2)
1786
- console.print(Panel(spec_json, title=f"Team: {team_template['name']}", border_style="green"))
1787
-
1788
- # Save if requested
1789
- if output_file:
1790
- validated_output = _validate_file_path(output_file)
1791
- validated_output.write_text(spec_json)
1792
- console.print(f"\n[green]Saved to:[/green] {validated_output}")
1793
-
1794
- # Show usage
1795
- console.print("\n[bold]Next Steps:[/bold]")
1796
- console.print(
1797
- f" 1. Save as template: [cyan]--output .empathy/meta_workflows/templates/{team_template['id']}.json[/cyan]"
1798
- )
1799
- console.print(
1800
- f" 2. Run the team: [cyan]empathy meta-workflow run {team_template['id']}[/cyan]"
1801
- )
1802
-
1803
- cost_min = team_template["estimated_cost_range"]["min"]
1804
- cost_max = team_template["estimated_cost_range"]["max"]
1805
- console.print(f"\n[dim]Estimated cost: ${cost_min:.2f} - ${cost_max:.2f} per execution[/dim]\n")
1806
-
1807
33
 
1808
- if __name__ == "__main__":
1809
- meta_workflow_app()
34
+ __all__ = [
35
+ # Typer app
36
+ "meta_workflow_app",
37
+ # Template commands
38
+ "list_templates",
39
+ "inspect_template",
40
+ "generate_plan_cmd",
41
+ # Workflow commands
42
+ "run_workflow",
43
+ "natural_language_run",
44
+ "detect_intent",
45
+ # Analytics commands
46
+ "show_analytics",
47
+ "list_runs",
48
+ "show_execution",
49
+ "cleanup_executions",
50
+ # Memory commands
51
+ "search_memory",
52
+ "show_session_stats",
53
+ # Config commands
54
+ "suggest_defaults_cmd",
55
+ "show_migration_guide",
56
+ # Agent commands
57
+ "create_agent",
58
+ "create_team",
59
+ ]