empathy-framework 5.1.1__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.
- {empathy_framework-5.1.1.dist-info → empathy_framework-5.2.1.dist-info}/METADATA +52 -3
- {empathy_framework-5.1.1.dist-info → empathy_framework-5.2.1.dist-info}/RECORD +69 -28
- empathy_os/cli_router.py +9 -0
- empathy_os/core_modules/__init__.py +15 -0
- empathy_os/mcp/__init__.py +10 -0
- empathy_os/mcp/server.py +506 -0
- empathy_os/memory/control_panel.py +1 -131
- empathy_os/memory/control_panel_support.py +145 -0
- empathy_os/memory/encryption.py +159 -0
- empathy_os/memory/long_term.py +41 -626
- empathy_os/memory/long_term_types.py +99 -0
- empathy_os/memory/mixins/__init__.py +25 -0
- empathy_os/memory/mixins/backend_init_mixin.py +244 -0
- empathy_os/memory/mixins/capabilities_mixin.py +199 -0
- empathy_os/memory/mixins/handoff_mixin.py +208 -0
- empathy_os/memory/mixins/lifecycle_mixin.py +49 -0
- empathy_os/memory/mixins/long_term_mixin.py +352 -0
- empathy_os/memory/mixins/promotion_mixin.py +109 -0
- empathy_os/memory/mixins/short_term_mixin.py +182 -0
- empathy_os/memory/short_term.py +7 -0
- empathy_os/memory/simple_storage.py +302 -0
- empathy_os/memory/storage_backend.py +167 -0
- empathy_os/memory/unified.py +21 -1120
- empathy_os/meta_workflows/cli_commands/__init__.py +56 -0
- empathy_os/meta_workflows/cli_commands/agent_commands.py +321 -0
- empathy_os/meta_workflows/cli_commands/analytics_commands.py +442 -0
- empathy_os/meta_workflows/cli_commands/config_commands.py +232 -0
- empathy_os/meta_workflows/cli_commands/memory_commands.py +182 -0
- empathy_os/meta_workflows/cli_commands/template_commands.py +354 -0
- empathy_os/meta_workflows/cli_commands/workflow_commands.py +382 -0
- empathy_os/meta_workflows/cli_meta_workflows.py +52 -1802
- empathy_os/models/telemetry/__init__.py +71 -0
- empathy_os/models/telemetry/analytics.py +594 -0
- empathy_os/models/telemetry/backend.py +196 -0
- empathy_os/models/telemetry/data_models.py +431 -0
- empathy_os/models/telemetry/storage.py +489 -0
- empathy_os/orchestration/__init__.py +35 -0
- empathy_os/orchestration/execution_strategies.py +481 -0
- empathy_os/orchestration/meta_orchestrator.py +488 -1
- empathy_os/routing/workflow_registry.py +36 -0
- empathy_os/telemetry/cli.py +19 -724
- empathy_os/telemetry/commands/__init__.py +14 -0
- empathy_os/telemetry/commands/dashboard_commands.py +696 -0
- empathy_os/tools.py +183 -0
- empathy_os/workflows/__init__.py +5 -0
- empathy_os/workflows/autonomous_test_gen.py +860 -161
- empathy_os/workflows/base.py +6 -2
- empathy_os/workflows/code_review.py +4 -1
- empathy_os/workflows/document_gen/__init__.py +25 -0
- empathy_os/workflows/document_gen/config.py +30 -0
- empathy_os/workflows/document_gen/report_formatter.py +162 -0
- empathy_os/workflows/document_gen/workflow.py +1426 -0
- empathy_os/workflows/document_gen.py +22 -1598
- empathy_os/workflows/security_audit.py +2 -2
- empathy_os/workflows/security_audit_phase3.py +7 -4
- empathy_os/workflows/seo_optimization.py +633 -0
- empathy_os/workflows/test_gen/__init__.py +52 -0
- empathy_os/workflows/test_gen/ast_analyzer.py +249 -0
- empathy_os/workflows/test_gen/config.py +88 -0
- empathy_os/workflows/test_gen/data_models.py +38 -0
- empathy_os/workflows/test_gen/report_formatter.py +289 -0
- empathy_os/workflows/test_gen/test_templates.py +381 -0
- empathy_os/workflows/test_gen/workflow.py +655 -0
- empathy_os/workflows/test_gen.py +42 -1905
- empathy_os/memory/types 2.py +0 -441
- empathy_os/models/telemetry.py +0 -1660
- {empathy_framework-5.1.1.dist-info → empathy_framework-5.2.1.dist-info}/WHEEL +0 -0
- {empathy_framework-5.1.1.dist-info → empathy_framework-5.2.1.dist-info}/entry_points.txt +0 -0
- {empathy_framework-5.1.1.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE +0 -0
- {empathy_framework-5.1.1.dist-info → empathy_framework-5.2.1.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -0
- {empathy_framework-5.1.1.dist-info → empathy_framework-5.2.1.dist-info}/top_level.txt +0 -0
|
@@ -1,1809 +1,59 @@
|
|
|
1
|
-
"""CLI
|
|
1
|
+
"""CLI Commands for Meta-Workflow System (Backward Compatible Entry Point).
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
10
|
-
|
|
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
|
-
|
|
9
|
+
Copyright 2025 Smart-AI-Memory
|
|
10
|
+
Licensed under Fair Source License 0.9
|
|
17
11
|
"""
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
from
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
1809
|
-
|
|
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
|
+
]
|