@ema.co/mcp-toolkit 2026.1.25 → 2026.1.26-4
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.
Potentially problematic release.
This version of @ema.co/mcp-toolkit might be problematic. Click here for more details.
- package/README.md +10 -2
- package/dist/mcp/handlers/action/index.js +3 -18
- package/dist/mcp/handlers/data/index.js +385 -41
- package/dist/mcp/handlers/data/templates.js +107 -0
- package/dist/mcp/handlers/deprecation.js +50 -0
- package/dist/mcp/handlers/env/index.js +8 -4
- package/dist/mcp/handlers/knowledge/index.js +44 -237
- package/dist/mcp/handlers/persona/create.js +47 -18
- package/dist/mcp/handlers/persona/index.js +14 -11
- package/dist/mcp/handlers/persona/update.js +4 -2
- package/dist/mcp/handlers/persona/version.js +234 -0
- package/dist/mcp/handlers/sync/index.js +3 -18
- package/dist/mcp/handlers/template/index.js +75 -10
- package/dist/mcp/handlers/workflow/analyze.js +171 -0
- package/dist/mcp/handlers/workflow/compare.js +70 -0
- package/dist/mcp/handlers/workflow/deploy.js +73 -0
- package/dist/mcp/handlers/workflow/generate.js +350 -0
- package/dist/mcp/handlers/workflow/index.js +294 -0
- package/dist/mcp/handlers/workflow/modify.js +456 -0
- package/dist/mcp/handlers/workflow/optimize.js +136 -0
- package/dist/mcp/handlers/workflow/types.js +4 -0
- package/dist/mcp/handlers/workflow/utils.js +30 -0
- package/dist/mcp/handlers-consolidated.js +73 -2696
- package/dist/mcp/prompts.js +83 -43
- package/dist/mcp/resources.js +382 -57
- package/dist/mcp/server.js +199 -391
- package/dist/mcp/{tools-v2.js → tools.js} +20 -54
- package/dist/mcp/workflow-operations.js +2 -2
- package/dist/sdk/client-adapter.js +267 -32
- package/dist/sdk/client.js +45 -16
- package/dist/sdk/ema-client.js +183 -0
- package/dist/sdk/generated/deprecated-actions.js +171 -0
- package/dist/sdk/generated/template-fallbacks.js +123 -0
- package/dist/sdk/guidance.js +65 -11
- package/dist/sdk/index.js +3 -1
- package/dist/sdk/knowledge.js +139 -86
- package/dist/sdk/workflow-intent.js +27 -0
- package/dist/sdk/workflow-transformer.js +0 -342
- package/docs/mcp-tools-guide.md +37 -45
- package/package.json +10 -4
- package/dist/mcp/handlers/persona/analyze.js +0 -275
- package/dist/mcp/handlers/persona/compare.js +0 -32
- package/dist/mcp/tools-consolidated.js +0 -875
- package/dist/mcp/tools-legacy.js +0 -736
- package/docs/CODEBASE-ANALYSIS-2026-01-23.md +0 -936
- package/docs/CODEBASE-ANALYSIS-PRIORITIZED.md +0 -774
- package/docs/api-contracts.md +0 -216
- package/docs/auto-builder-analysis.md +0 -271
- package/docs/blog/mcp-tool-design-lessons.md +0 -309
- package/docs/data-architecture.md +0 -166
- package/docs/demos/ap-invoice-generation.md +0 -347
- package/docs/demos/ap-invoice-processing.md +0 -271
- package/docs/ema-auto-builder-guide.html +0 -394
- package/docs/lessons-learned.md +0 -209
- package/docs/llm-native-workflow-design.md +0 -252
- package/docs/local-generation.md +0 -508
- package/docs/mcp-flow-diagram.md +0 -135
- package/docs/migration/action-composition-migration.md +0 -270
- package/docs/naming-conventions.md +0 -278
- package/docs/proposals/HANDOFF-tool-restructure.md +0 -526
- package/docs/proposals/action-composition.md +0 -490
- package/docs/proposals/explicit-method-restructure.md +0 -328
- package/docs/proposals/mcp-tool-restructure-2026-01.md +0 -366
- package/docs/proposals/self-contained-guidance.md +0 -427
- package/docs/proto-sdk-generation.md +0 -242
- package/docs/release-impact.md +0 -102
- package/docs/release-process.md +0 -157
- package/docs/staging.RULE.md +0 -142
- package/docs/test-persona-creation.md +0 -196
- package/docs/tool-consolidation-v2.md +0 -225
- package/docs/tool-response-standards.md +0 -256
- package/resources/demo-kits/README.md +0 -175
- package/resources/demo-kits/finance-ap/manifest.json +0 -150
- package/resources/demo-kits/tags.json +0 -91
- package/resources/docs/getting-started.md +0 -97
- package/resources/templates/auto-builder-rules.md +0 -224
- package/resources/templates/chat-ai/README.md +0 -119
- package/resources/templates/chat-ai/persona-config.json +0 -111
- package/resources/templates/dashboard-ai/README.md +0 -156
- package/resources/templates/dashboard-ai/persona-config.json +0 -180
- package/resources/templates/demo-scenarios/README.md +0 -63
- package/resources/templates/demo-scenarios/test-published-package.md +0 -116
- package/resources/templates/document-gen-ai/README.md +0 -132
- package/resources/templates/document-gen-ai/persona-config.json +0 -316
- package/resources/templates/voice-ai/README.md +0 -123
- package/resources/templates/voice-ai/persona-config.json +0 -74
- package/resources/templates/voice-ai/workflow-prompt.md +0 -121
package/dist/mcp/server.js
CHANGED
|
@@ -41,22 +41,22 @@ import { createVersionPolicyEngine } from "../sdk/version-policy.js";
|
|
|
41
41
|
import { getToolkitRoot } from "../sdk/paths.js";
|
|
42
42
|
import { SYNC_METADATA_KEY } from "../sdk/models.js";
|
|
43
43
|
// Auto Builder Knowledge
|
|
44
|
-
import { AGENT_CATALOG, WIDGET_CATALOG, WORKFLOW_PATTERNS, QUALIFYING_QUESTIONS, PLATFORM_CONCEPTS, WORKFLOW_EXECUTION_MODEL, COMMON_MISTAKES, DEBUG_CHECKLIST, GUIDANCE_TOPICS,
|
|
44
|
+
import { AGENT_CATALOG, WIDGET_CATALOG, WORKFLOW_PATTERNS, QUALIFYING_QUESTIONS, PLATFORM_CONCEPTS, WORKFLOW_EXECUTION_MODEL, COMMON_MISTAKES, DEBUG_CHECKLIST, GUIDANCE_TOPICS, PROJECT_TYPES, getAgentsByCategory, getAgentByName, getWidgetsForPersonaType, checkTypeCompatibility, getQualifyingQuestionsByCategory, getConceptByTerm, suggestAgentsForUseCase, validateWorkflowPrompt,
|
|
45
45
|
// Workflow Analysis
|
|
46
46
|
analyzeWorkflow, detectWorkflowIssues, validateWorkflowConnections, suggestWorkflowFixes, } from "../sdk/knowledge.js";
|
|
47
|
+
// Template fallbacks (generated from protos, used when API unavailable)
|
|
48
|
+
import { getTemplateFallback, getTemplateFieldDocs, VOICE_TEMPLATE_FALLBACK } from "../sdk/generated/template-fallbacks.js";
|
|
47
49
|
// Workflow Compiler (Template-driven)
|
|
48
50
|
import { compileWorkflow, } from "../sdk/workflow-generator.js";
|
|
49
51
|
// V2 Tools (4 tools: persona, catalog, sync, env) - NEW DEFAULT
|
|
50
|
-
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
const ENABLE_LEGACY_TOOLS = process.env.EMA_ENABLE_LEGACY_TOOLS === "true";
|
|
59
|
-
import { handleEnv, handlePersona, handleWorkflow, handleAction, handleData, handleTemplate, handleKnowledge, handleReference, } from "./handlers-consolidated.js";
|
|
52
|
+
import { generateTools, } from "./tools.js";
|
|
53
|
+
import { handleEnv, handlePersona,
|
|
54
|
+
// handleWorkflow - removed, now using extracted handler from ./handlers/workflow/index.js
|
|
55
|
+
handleAction,
|
|
56
|
+
// handleData - removed, now using extracted handler from ./handlers/data/index.js
|
|
57
|
+
handleTemplate, handleKnowledge, handleReference, } from "./handlers-consolidated.js";
|
|
58
|
+
// Import extracted handlers
|
|
59
|
+
import { handleWorkflow } from "./handlers/workflow/index.js";
|
|
60
60
|
// Import from handler utilities (normalizeTriggerType uses generated enum labels)
|
|
61
61
|
import { normalizeTriggerType } from "./handlers/utils.js";
|
|
62
62
|
// Import from SDK proto-config (CANONICAL widget validation and merging)
|
|
@@ -92,6 +92,9 @@ function summarizeWorkflow(workflowDef) {
|
|
|
92
92
|
if (nodeNames.length > 0) {
|
|
93
93
|
lines.push(`\nNodes: ${nodeNames.slice(0, 20).join(", ")}${nodeNames.length > 20 ? "..." : ""}`);
|
|
94
94
|
}
|
|
95
|
+
// TODO: This uses keyword matching to detect workflow features.
|
|
96
|
+
// Consider using ActionRegistry metadata instead for consistency with LLM-driven architecture.
|
|
97
|
+
// Current approach is acceptable for Auto Builder descriptions but could be improved.
|
|
95
98
|
// Check for categorizer (indicates intent routing)
|
|
96
99
|
const hasCategorizer = Array.from(actionTypes.keys()).some(t => t.includes("categorizer"));
|
|
97
100
|
if (hasCategorizer) {
|
|
@@ -111,8 +114,19 @@ function summarizeWorkflow(workflowDef) {
|
|
|
111
114
|
* Apply automatic fixes to a workflow based on detected issues.
|
|
112
115
|
* This function attempts to fix common issues like missing WORKFLOW_OUTPUT,
|
|
113
116
|
* wrong input sources, and other structural problems.
|
|
117
|
+
*
|
|
118
|
+
* @deprecated This function violates the LLM-driven architecture principle.
|
|
119
|
+
* MCP should not auto-fix workflows - it should return suggestions for the Agent to apply.
|
|
120
|
+
* Per CLAUDE.md: "Auto-fix issues | ❌ FORBIDDEN | ✅ Proposes fixes"
|
|
121
|
+
*
|
|
122
|
+
* This function will be removed in a future version. Instead:
|
|
123
|
+
* 1. Use analyzeWorkflow() to detect issues
|
|
124
|
+
* 2. Return issues as suggestions to the Agent
|
|
125
|
+
* 3. Let Agent apply fixes via persona(id="...", operations=[...])
|
|
114
126
|
*/
|
|
115
127
|
function applyWorkflowFixes(workflowDef, issues, persona) {
|
|
128
|
+
// Log deprecation warning
|
|
129
|
+
console.warn("[DEPRECATED] applyWorkflowFixes() called - this function violates LLM-driven architecture and will be removed");
|
|
116
130
|
// Deep clone the workflow to avoid mutating the original
|
|
117
131
|
const fixedWorkflow = JSON.parse(JSON.stringify(workflowDef));
|
|
118
132
|
const appliedFixes = [];
|
|
@@ -1093,102 +1107,46 @@ function withEnvParam(props, required = []) {
|
|
|
1093
1107
|
// Tool Definitions
|
|
1094
1108
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1095
1109
|
//
|
|
1096
|
-
//
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
// - Defined in: ./tools-consolidated.ts
|
|
1100
|
-
//
|
|
1101
|
-
// 2. LEGACY TOOLS (40+ tools) - Old separate tools for backwards compatibility
|
|
1102
|
-
// - Defined in: ./tools-legacy.ts
|
|
1103
|
-
// - Enable with EMA_ENABLE_LEGACY_TOOLS=true
|
|
1110
|
+
// V2 TOOLS (5 tools) - LLM-optimized minimal interface
|
|
1111
|
+
// - env, persona, catalog, workflow, sync
|
|
1112
|
+
// - Defined in: ./tools.ts
|
|
1104
1113
|
//
|
|
1105
1114
|
// NAMING CONVENTION:
|
|
1106
|
-
// - Tool names are defined as BASE NAMES (e.g., "persona"
|
|
1115
|
+
// - Tool names are defined as BASE NAMES (e.g., "persona")
|
|
1107
1116
|
// - MCP clients prefix with "mcp_{server}_" (e.g., "mcp_ema_persona")
|
|
1108
1117
|
//
|
|
1109
1118
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1110
1119
|
/**
|
|
1111
|
-
* Generate all available tools
|
|
1120
|
+
* Generate all available tools
|
|
1112
1121
|
*
|
|
1113
|
-
*
|
|
1114
|
-
* - V2 (default): 4 tools (persona, catalog, sync, env) - LLM-optimized
|
|
1115
|
-
* - V1: 7 mode-based tools - set EMA_ENABLE_V1_TOOLS=true
|
|
1116
|
-
* - Legacy: Individual tools - set EMA_ENABLE_LEGACY_TOOLS=true
|
|
1122
|
+
* V2: 5 tools (persona, catalog, workflow, sync, env) - LLM-optimized
|
|
1117
1123
|
*
|
|
1118
|
-
* Why V2
|
|
1124
|
+
* Why V2:
|
|
1119
1125
|
* - Minimal tool count optimizes LLM tool selection
|
|
1120
1126
|
* - Data operations under persona (always persona-scoped)
|
|
1121
1127
|
* - Catalog consolidates all reference data (actions, templates, etc.)
|
|
1122
|
-
* - Clear separation: entity (persona), reference (catalog), operation (sync)
|
|
1128
|
+
* - Clear separation: entity (persona), reference (catalog), operation (sync, workflow)
|
|
1123
1129
|
*/
|
|
1124
1130
|
function generateAllTools() {
|
|
1125
1131
|
const envNames = getAvailableEnvironments().map(e => e.name);
|
|
1126
1132
|
const defaultEnv = getDefaultEnvName();
|
|
1127
|
-
|
|
1128
|
-
if (ENABLE_V1_TOOLS) {
|
|
1129
|
-
console.error("[MCP] V1 mode-based tools enabled via EMA_ENABLE_V1_TOOLS=true");
|
|
1130
|
-
const consolidatedTools = generateConsolidatedTools(envNames, defaultEnv);
|
|
1131
|
-
if (ENABLE_LEGACY_TOOLS) {
|
|
1132
|
-
console.error("[MCP] WARNING: Legacy tools also enabled");
|
|
1133
|
-
const legacyTools = generateLegacyTools(envNames, defaultEnv);
|
|
1134
|
-
return [...consolidatedTools, ...legacyTools];
|
|
1135
|
-
}
|
|
1136
|
-
return consolidatedTools;
|
|
1137
|
-
}
|
|
1138
|
-
// V2 minimal tools (default) - 4 tools: persona, catalog, sync, env
|
|
1139
|
-
const v2Tools = generateToolsV2(envNames, defaultEnv);
|
|
1140
|
-
if (ENABLE_LEGACY_TOOLS) {
|
|
1141
|
-
console.error("[MCP] WARNING: Legacy tools enabled alongside V2");
|
|
1142
|
-
const legacyTools = generateLegacyTools(envNames, defaultEnv);
|
|
1143
|
-
return [...v2Tools, ...legacyTools];
|
|
1144
|
-
}
|
|
1145
|
-
return v2Tools;
|
|
1133
|
+
return generateTools(envNames, defaultEnv);
|
|
1146
1134
|
}
|
|
1147
1135
|
// Generate tools (called once at module load)
|
|
1148
1136
|
const TOOLS = generateAllTools();
|
|
1149
1137
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1150
|
-
// ADDITIONAL TOOLS (
|
|
1151
|
-
// These
|
|
1138
|
+
// ADDITIONAL TOOLS (special-purpose inline tools)
|
|
1139
|
+
// These handle specific operations that don't fit the V2 pattern
|
|
1152
1140
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1153
1141
|
const ADDITIONAL_TOOLS = [
|
|
1154
|
-
//
|
|
1155
|
-
// NOTE: Legacy tools (get_persona, find_personas, create_ai_employee, etc.)
|
|
1156
|
-
// have been moved to ./tools-legacy.ts for backwards compatibility.
|
|
1157
|
-
//
|
|
1158
|
-
// Consolidated tools (persona, workflow, action, etc.) are generated from
|
|
1159
|
-
// ./tools-consolidated.ts following Unix CLI patterns.
|
|
1142
|
+
// NOTE: Tools (persona, catalog, workflow, sync, env) are in ./tools.ts
|
|
1160
1143
|
//
|
|
1161
|
-
//
|
|
1162
|
-
// -
|
|
1163
|
-
// - Demo data tools -
|
|
1164
|
-
//
|
|
1165
|
-
// INLINE LEGACY TOOLS REMOVED
|
|
1166
|
-
// All legacy tools (get_workflow_action, find_workflow_actions, compare_ai_employees,
|
|
1167
|
-
// list_ai_employee_templates, sync, sync_info, list_auto_builder_agents, etc.)
|
|
1168
|
-
// have been moved to ./tools-legacy.ts
|
|
1169
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
1170
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1171
|
-
// LEGACY INLINE TOOLS REMOVED - See ./tools-legacy.ts
|
|
1172
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1173
|
-
// The following tools have been removed from this file and are now generated
|
|
1174
|
-
// from tools-legacy.ts: list_auto_builder_agents, get_auto_builder_agent,
|
|
1175
|
-
// suggest_agents_for_use_case, get_workflow_pattern, list_workflow_patterns,
|
|
1176
|
-
// check_type_compatibility, get_widget_reference, get_qualifying_questions,
|
|
1177
|
-
// get_voice_persona_template, validate_workflow_prompt, get_auto_builder_guidance,
|
|
1178
|
-
// get_platform_concept, list_platform_concepts, get_common_mistakes,
|
|
1179
|
-
// get_debug_checklist, get_workflow_execution_model, analyze_workflow,
|
|
1180
|
-
// detect_workflow_issues, validate_workflow_connections, suggest_workflow_fixes,
|
|
1181
|
-
// compare_workflow_versions, get_workflow_metrics, compile_workflow,
|
|
1182
|
-
// upload_data_source, delete_data_source, list_data_sources, get_embedding_status,
|
|
1144
|
+
// Special-purpose tools here:
|
|
1145
|
+
// - compile_workflow - Direct workflow compilation
|
|
1146
|
+
// - Demo data tools - RAG document generation/validation
|
|
1147
|
+
// - Data source tools - Upload/delete/manage knowledge sources
|
|
1183
1148
|
// toggle_embedding
|
|
1184
1149
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1185
|
-
// The remaining legacy tools are handled by the LEGACY_TOOL_MAPPING in
|
|
1186
|
-
// tools-consolidated.ts for routing to consolidated handlers.
|
|
1187
|
-
//
|
|
1188
|
-
// INLINE DEFINITIONS REMOVED - They are now in tools-legacy.ts
|
|
1189
|
-
// (analyze_workflow, detect_workflow_issues, validate_workflow_connections, suggest_workflow_fixes)
|
|
1190
|
-
// (compare_workflow_versions, get_workflow_metrics) - moved to tools-legacy.ts
|
|
1191
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1192
1150
|
// Workflow Compilation - Template-driven, no biased patterns
|
|
1193
1151
|
// Read ema://catalog/patterns for pattern references, then construct nodes
|
|
1194
1152
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -1606,11 +1564,6 @@ Returns:
|
|
|
1606
1564
|
required: ["entity_type"],
|
|
1607
1565
|
},
|
|
1608
1566
|
},
|
|
1609
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
1610
|
-
// CONSOLIDATED TOOLS (Unix CLI pattern)
|
|
1611
|
-
// These 9 tools follow Unix conventions: single command with flags
|
|
1612
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
1613
|
-
...generateConsolidatedTools(getAvailableEnvironments().map(e => e.name), getDefaultEnvName()),
|
|
1614
1567
|
];
|
|
1615
1568
|
const toolHandlers = {
|
|
1616
1569
|
// Environment Management
|
|
@@ -1980,19 +1933,29 @@ const toolHandlers = {
|
|
|
1980
1933
|
if (!analysis.validation_passed) {
|
|
1981
1934
|
validationResults.valid = false;
|
|
1982
1935
|
validationResults.issues = analysis.issues ?? [];
|
|
1983
|
-
// Auto-fix
|
|
1936
|
+
// Auto-fix handling (DEPRECATED - returns suggestions instead of auto-applying)
|
|
1984
1937
|
if (autoFix && validationResults.issues.length > 0) {
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
const reAnalysis = analyzeWorkflow(workflowDef, {
|
|
1938
|
+
// DEPRECATED: autoFix no longer auto-applies fixes.
|
|
1939
|
+
// Per LLM-driven architecture, MCP returns suggestions for Agent to apply.
|
|
1940
|
+
return {
|
|
1941
|
+
environment: client["env"].name,
|
|
1942
|
+
success: false,
|
|
1991
1943
|
persona_id: personaId,
|
|
1992
|
-
persona_name: persona.name
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1944
|
+
persona_name: persona.name,
|
|
1945
|
+
validation_failed: true,
|
|
1946
|
+
issues: validationResults.issues,
|
|
1947
|
+
// Return suggestions instead of applying fixes
|
|
1948
|
+
suggestions: validationResults.issues.map(issue => ({
|
|
1949
|
+
issue_type: issue.type,
|
|
1950
|
+
severity: issue.severity,
|
|
1951
|
+
node: issue.node,
|
|
1952
|
+
reason: issue.reason,
|
|
1953
|
+
suggested_action: `Fix "${issue.type}" on node "${issue.node ?? 'workflow'}": ${issue.reason}`,
|
|
1954
|
+
})),
|
|
1955
|
+
applied_fixes: [], // Empty - no longer auto-applying
|
|
1956
|
+
_deprecated: "autoFix is deprecated. Fixes are no longer auto-applied. Use the suggestions to build explicit workflow modifications.",
|
|
1957
|
+
_tip: "Apply fixes using: persona(id=\"...\", operations=[{type:\"rewire\", ...}]) or persona(id=\"...\", workflow_spec={...})",
|
|
1958
|
+
};
|
|
1996
1959
|
}
|
|
1997
1960
|
}
|
|
1998
1961
|
}
|
|
@@ -2207,130 +2170,62 @@ const toolHandlers = {
|
|
|
2207
2170
|
}
|
|
2208
2171
|
return result;
|
|
2209
2172
|
}
|
|
2210
|
-
// Step 3:
|
|
2211
|
-
|
|
2173
|
+
// Step 3: Return suggestions instead of auto-applying (DEPRECATED behavior)
|
|
2174
|
+
// Per LLM-driven architecture, MCP returns suggestions for Agent to apply.
|
|
2175
|
+
const suggestions = issues.map(issue => ({
|
|
2176
|
+
issue_type: issue.type,
|
|
2177
|
+
severity: issue.severity,
|
|
2178
|
+
node: issue.node,
|
|
2179
|
+
reason: issue.reason,
|
|
2180
|
+
suggested_action: `Fix "${issue.type}" on node "${issue.node ?? 'workflow'}": ${issue.reason}`,
|
|
2181
|
+
}));
|
|
2182
|
+
// DEPRECATED: No longer auto-apply fixes
|
|
2183
|
+
// The appliedFixes array is now always empty
|
|
2212
2184
|
const appliedFixes = [];
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
appliedFixes.push(...fixResult.appliedFixes);
|
|
2217
|
-
}
|
|
2218
|
-
// Re-analyze after fixes
|
|
2219
|
-
const postFixAnalysis = analyzeWorkflow(fixedWorkflow, {
|
|
2220
|
-
persona_id: personaId,
|
|
2221
|
-
persona_name: persona.name ?? "Unknown",
|
|
2222
|
-
});
|
|
2223
|
-
const remainingIssues = postFixAnalysis.issues ?? [];
|
|
2185
|
+
const fixedWorkflow = workflowDef; // Workflow unchanged
|
|
2186
|
+
// No re-analysis needed since we don't auto-fix
|
|
2187
|
+
const remainingIssues = issues;
|
|
2224
2188
|
const remainingCritical = remainingIssues.filter(i => i.severity === "critical");
|
|
2225
|
-
// If preview mode, show
|
|
2189
|
+
// If preview mode, show suggestions (DEPRECATED: no longer auto-applies)
|
|
2226
2190
|
if (preview) {
|
|
2227
|
-
const fixedCount = appliedFixes.filter(f => f.applied).length;
|
|
2228
|
-
const failedCount = appliedFixes.filter(f => !f.applied).length;
|
|
2229
2191
|
const previewResult = {
|
|
2230
2192
|
success: true,
|
|
2231
2193
|
persona: persona.name,
|
|
2232
|
-
status: "📋 Preview -
|
|
2194
|
+
status: "📋 Preview - Suggestions Available",
|
|
2233
2195
|
mode: "optimize",
|
|
2234
2196
|
nodes: fixedWorkflow.actions?.length ?? 0,
|
|
2235
2197
|
found_issues: issues.length,
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
ready_to_deploy: remainingCritical.length === 0,
|
|
2198
|
+
// Return suggestions instead of applied fixes
|
|
2199
|
+
suggestions: suggestions,
|
|
2239
2200
|
issues: issues.length > 0 ? issues.map(i => `${i.severity === "critical" ? "❌" : "⚠️"} ${i.type}: ${i.reason}`) : ["No issues found"],
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
: `${remainingCritical.length} critical issue(s) need manual fix in Ema UI.`,
|
|
2201
|
+
applied_fixes: [], // Empty - no longer auto-applying
|
|
2202
|
+
_deprecated: "Auto-fix is deprecated. Review suggestions and apply fixes explicitly.",
|
|
2203
|
+
_tip: "Apply fixes using: persona(id=\"...\", operations=[...]) or use Ema UI Auto Builder",
|
|
2244
2204
|
};
|
|
2245
2205
|
if (enhancementPrompt) {
|
|
2246
|
-
previewResult.enhancement_note = `Enhancement "${enhancementPrompt}" noted.
|
|
2206
|
+
previewResult.enhancement_note = `Enhancement "${enhancementPrompt}" noted. Use Ema UI Auto Builder to make this change.`;
|
|
2247
2207
|
}
|
|
2248
2208
|
return previewResult;
|
|
2249
2209
|
}
|
|
2250
|
-
// Step 4:
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
// Fix enumTypes - check nested structure
|
|
2268
|
-
const enumTypes = fixedWorkflow.enumTypes;
|
|
2269
|
-
if (Array.isArray(enumTypes)) {
|
|
2270
|
-
const validEnumTypes = enumTypes.filter(e => {
|
|
2271
|
-
const outerName = e.name;
|
|
2272
|
-
const innerName = outerName?.name;
|
|
2273
|
-
const actualName = innerName?.name;
|
|
2274
|
-
return typeof actualName === "string" && actualName.trim().length > 0;
|
|
2275
|
-
});
|
|
2276
|
-
if (validEnumTypes.length > 0) {
|
|
2277
|
-
fixedWorkflow.enumTypes = validEnumTypes;
|
|
2278
|
-
}
|
|
2279
|
-
else {
|
|
2280
|
-
delete fixedWorkflow.enumTypes;
|
|
2281
|
-
}
|
|
2282
|
-
}
|
|
2283
|
-
// Copy workflowName from existing
|
|
2284
|
-
const existingWfName = workflowDef.workflowName;
|
|
2285
|
-
if (existingWfName) {
|
|
2286
|
-
fixedWorkflow.workflowName = JSON.parse(JSON.stringify(existingWfName));
|
|
2287
|
-
}
|
|
2288
|
-
// Sanitize existing proto_config widgets
|
|
2289
|
-
const mergedProtoConfig = mergeProtoConfig(persona.proto_config, undefined);
|
|
2290
|
-
// Build and send request
|
|
2291
|
-
const req = {
|
|
2292
|
-
persona_id: personaId,
|
|
2293
|
-
proto_config: mergedProtoConfig,
|
|
2294
|
-
workflow: fixedWorkflow,
|
|
2210
|
+
// Step 4: Return suggestions for issues (DEPRECATED: no longer auto-deploys)
|
|
2211
|
+
// Per LLM-driven architecture, return suggestions for Agent to review and apply
|
|
2212
|
+
// The Agent should use explicit operations to apply fixes, then deploy separately.
|
|
2213
|
+
return {
|
|
2214
|
+
success: true,
|
|
2215
|
+
persona: persona.name,
|
|
2216
|
+
status: remainingCritical.length > 0
|
|
2217
|
+
? "⚠️ Issues Found - Review Suggestions"
|
|
2218
|
+
: "📋 Minor Issues - Review Suggestions",
|
|
2219
|
+
found_issues: issues.length,
|
|
2220
|
+
critical_issues: remainingCritical.length,
|
|
2221
|
+
suggestions: suggestions,
|
|
2222
|
+
applied_fixes: [], // Empty - no longer auto-applying
|
|
2223
|
+
_deprecated: "Auto-fix and auto-deploy are deprecated. Review suggestions and apply fixes explicitly.",
|
|
2224
|
+
_tip: remainingCritical.length > 0
|
|
2225
|
+
? "Critical issues found. Review suggestions and fix in Ema UI Auto Builder or use explicit operations."
|
|
2226
|
+
: "Apply fixes using: persona(id=\"...\", operations=[...]) or use Ema UI Auto Builder",
|
|
2295
2227
|
};
|
|
2296
|
-
|
|
2297
|
-
try {
|
|
2298
|
-
await client.updateAiEmployee(req);
|
|
2299
|
-
const fixedCount = appliedFixes.filter(f => f.applied).length;
|
|
2300
|
-
const deployResult = {
|
|
2301
|
-
success: true,
|
|
2302
|
-
persona: persona.name,
|
|
2303
|
-
status: "✅ Optimized & Deployed",
|
|
2304
|
-
mode: "optimized",
|
|
2305
|
-
issues_found: issues.length,
|
|
2306
|
-
issues_fixed: fixedCount,
|
|
2307
|
-
nodes: postFixAnalysis.summary?.total_nodes ?? actionsArr.length,
|
|
2308
|
-
message: fixedCount > 0
|
|
2309
|
-
? `Fixed ${fixedCount} issue(s) and deployed!`
|
|
2310
|
-
: "Deployed successfully!",
|
|
2311
|
-
next_step: "Test in the Ema simulator to verify behavior.",
|
|
2312
|
-
};
|
|
2313
|
-
if (enhancementPrompt) {
|
|
2314
|
-
deployResult.enhancement_note = `Fixes applied. Enhancement "${enhancementPrompt}" requires manual implementation via Ema UI Auto Builder.`;
|
|
2315
|
-
}
|
|
2316
|
-
return deployResult;
|
|
2317
|
-
}
|
|
2318
|
-
catch (err) {
|
|
2319
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
2320
|
-
// Extract EmaApiError body if available
|
|
2321
|
-
const apiBody = err?.body;
|
|
2322
|
-
const statusCode = err?.statusCode;
|
|
2323
|
-
return {
|
|
2324
|
-
success: false,
|
|
2325
|
-
persona: persona.name,
|
|
2326
|
-
status: "❌ Deploy Failed",
|
|
2327
|
-
error: errorMessage,
|
|
2328
|
-
status_code: statusCode,
|
|
2329
|
-
api_response: apiBody ? JSON.parse(apiBody) : undefined,
|
|
2330
|
-
fixes_attempted: appliedFixes.filter(f => f.applied).length,
|
|
2331
|
-
suggestion: "Check the api_response field for the actual backend error.",
|
|
2332
|
-
};
|
|
2333
|
-
}
|
|
2228
|
+
// Note: Auto-deploy code removed (was dead code after deprecation)
|
|
2334
2229
|
},
|
|
2335
2230
|
// ─────────────────────────────────────────────────────────────────────────
|
|
2336
2231
|
// Action Handlers (Consolidated)
|
|
@@ -2826,10 +2721,14 @@ const toolHandlers = {
|
|
|
2826
2721
|
};
|
|
2827
2722
|
},
|
|
2828
2723
|
get_voice_persona_template: async () => {
|
|
2724
|
+
// Use generated fallback from proto definitions
|
|
2725
|
+
// In production, prefer API templates via client.getPersonaTemplates()
|
|
2726
|
+
const template = getTemplateFallback("voice");
|
|
2829
2727
|
return {
|
|
2830
|
-
template:
|
|
2831
|
-
|
|
2832
|
-
|
|
2728
|
+
template: template || VOICE_TEMPLATE_FALLBACK,
|
|
2729
|
+
field_docs: getTemplateFieldDocs("voice"),
|
|
2730
|
+
required_fields: ["conversationSettings.welcomeMessage", "conversationSettings.identityAndPurpose", "conversationSettings.takeActionInstructions", "conversationSettings.hangupInstructions"],
|
|
2731
|
+
optional_fields: ["conversationSettings.transferCallInstructions", "conversationSettings.speechCharacteristics", "conversationSettings.systemPrompt", "conversationSettings.formFillingInstructions", "conversationSettings.waitMessage"],
|
|
2833
2732
|
project_type: PROJECT_TYPES.voice,
|
|
2834
2733
|
widget_ids: {
|
|
2835
2734
|
voiceSettings: 38,
|
|
@@ -2837,12 +2736,8 @@ const toolHandlers = {
|
|
|
2837
2736
|
vadSettings: 43,
|
|
2838
2737
|
dataStorageSettings: 42,
|
|
2839
2738
|
},
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
"takeActionInstructions uses </Case N> format for each action",
|
|
2843
|
-
"speechCharacteristics should include TTS pronunciation rules",
|
|
2844
|
-
"systemPrompt defines tool calling behavior",
|
|
2845
|
-
],
|
|
2739
|
+
_source: "generated_fallback",
|
|
2740
|
+
_note: "This template is auto-generated from proto definitions. For live templates, use client.getPersonaTemplates().",
|
|
2846
2741
|
};
|
|
2847
2742
|
},
|
|
2848
2743
|
validate_workflow_prompt: async (args) => {
|
|
@@ -4049,28 +3944,32 @@ const toolHandlers = {
|
|
|
4049
3944
|
const { handleData: handleDataNew } = await import("./handlers/data/index.js");
|
|
4050
3945
|
return handleDataNew({ persona_id: personaId, env: args.env, data }, client);
|
|
4051
3946
|
}
|
|
4052
|
-
// LEGACY FLAG FORMAT (backwards compatibility)
|
|
3947
|
+
// LEGACY FLAG FORMAT (backwards compatibility) - use extracted handler
|
|
3948
|
+
const { handleData: handleDataExtracted } = await import("./handlers/data/index.js");
|
|
3949
|
+
const readFileFn = (path) => fs.readFile(path);
|
|
4053
3950
|
if (data.list === true) {
|
|
4054
|
-
return
|
|
3951
|
+
return handleDataExtracted({ method: "list", persona_id: personaId, env: args.env }, client, readFileFn);
|
|
4055
3952
|
}
|
|
4056
3953
|
if (typeof data.upload === "string") {
|
|
4057
|
-
return
|
|
3954
|
+
return handleDataExtracted({ method: "upload", persona_id: personaId, data: { path: data.upload }, env: args.env }, client, readFileFn);
|
|
4058
3955
|
}
|
|
4059
3956
|
if (typeof data.delete === "string") {
|
|
4060
|
-
return
|
|
3957
|
+
return handleDataExtracted({ method: "delete", persona_id: personaId, data: { file_id: data.delete }, env: args.env }, client, readFileFn);
|
|
4061
3958
|
}
|
|
4062
3959
|
if (typeof data.generate === "string" || data.template) {
|
|
4063
|
-
return
|
|
4064
|
-
|
|
3960
|
+
return handleDataExtracted({
|
|
3961
|
+
method: "generate",
|
|
4065
3962
|
persona_id: personaId,
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
3963
|
+
data: {
|
|
3964
|
+
input: data.generate,
|
|
3965
|
+
from: data.template,
|
|
3966
|
+
count: data.count,
|
|
3967
|
+
},
|
|
4069
3968
|
env: args.env
|
|
4070
|
-
}, client,
|
|
3969
|
+
}, client, readFileFn);
|
|
4071
3970
|
}
|
|
4072
3971
|
if (typeof data.embed === "boolean") {
|
|
4073
|
-
return
|
|
3972
|
+
return handleDataExtracted({ method: "embedding", persona_id: personaId, data: { enabled: data.embed }, env: args.env }, client, readFileFn);
|
|
4074
3973
|
}
|
|
4075
3974
|
if (typeof data.search === "string") {
|
|
4076
3975
|
return handleKnowledge({ mode: "search", persona_id: personaId, query: data.search, env: args.env }, client, (path) => fs.readFile(path));
|
|
@@ -4149,7 +4048,9 @@ const toolHandlers = {
|
|
|
4149
4048
|
data: async (args) => {
|
|
4150
4049
|
const client = createClient(args.env);
|
|
4151
4050
|
const fs = await import("fs/promises");
|
|
4152
|
-
|
|
4051
|
+
// Use extracted handler
|
|
4052
|
+
const { handleData: handleDataExtracted } = await import("./handlers/data/index.js");
|
|
4053
|
+
return handleDataExtracted(args, client, (path) => fs.readFile(path));
|
|
4153
4054
|
},
|
|
4154
4055
|
reference: async (args) => {
|
|
4155
4056
|
// v2: expanded reference handler with envs, actions, templates, patterns support
|
|
@@ -4169,9 +4070,11 @@ const toolHandlers = {
|
|
|
4169
4070
|
// catalog: Consolidated reference data (actions, templates, widgets, voices, patterns, concepts)
|
|
4170
4071
|
catalog: async (args) => {
|
|
4171
4072
|
const catalogType = args.type;
|
|
4073
|
+
const method = args.method;
|
|
4172
4074
|
const id = args.id;
|
|
4173
4075
|
const query = args.query;
|
|
4174
|
-
|
|
4076
|
+
// Note: schema uses 'for' parameter for recommend (not 'recommend')
|
|
4077
|
+
const forUseCase = args.for;
|
|
4175
4078
|
const category = args.category;
|
|
4176
4079
|
const client = createClient(args.env);
|
|
4177
4080
|
if (!catalogType) {
|
|
@@ -4183,9 +4086,16 @@ const toolHandlers = {
|
|
|
4183
4086
|
switch (catalogType) {
|
|
4184
4087
|
case "actions": {
|
|
4185
4088
|
// Route to action handler
|
|
4186
|
-
if (recommend) {
|
|
4187
|
-
const suggestions = suggestAgentsForUseCase(
|
|
4188
|
-
return {
|
|
4089
|
+
if (method === "recommend" && forUseCase) {
|
|
4090
|
+
const suggestions = suggestAgentsForUseCase(forUseCase);
|
|
4091
|
+
return {
|
|
4092
|
+
type: "actions",
|
|
4093
|
+
use_case: forUseCase,
|
|
4094
|
+
recommendations: suggestions,
|
|
4095
|
+
_tip: suggestions.length > 0
|
|
4096
|
+
? `Found ${suggestions.length} relevant agents. Use catalog(method="get", type="actions", id="<name>") for details.`
|
|
4097
|
+
: "No specific recommendations. Try browsing with catalog(method=\"list\", type=\"actions\").",
|
|
4098
|
+
};
|
|
4189
4099
|
}
|
|
4190
4100
|
if (id) {
|
|
4191
4101
|
const action = getAgentByName(id);
|
|
@@ -4209,7 +4119,9 @@ const toolHandlers = {
|
|
|
4209
4119
|
return {
|
|
4210
4120
|
type: "actions",
|
|
4211
4121
|
count: actions.length,
|
|
4212
|
-
actions: actions.map(a => ({ name: a.actionName, displayName: a.displayName, category: a.category, description: a.description }))
|
|
4122
|
+
actions: actions.map(a => ({ name: a.actionName, displayName: a.displayName, category: a.category, description: a.description })),
|
|
4123
|
+
_tip: "Get details: catalog(method=\"get\", type=\"actions\", id=\"<name>\")",
|
|
4124
|
+
_next_step: actions.length > 0 ? `catalog(method="get", type="actions", id="${actions[0].actionName}")` : undefined,
|
|
4213
4125
|
};
|
|
4214
4126
|
}
|
|
4215
4127
|
case "templates": {
|
|
@@ -4231,7 +4143,13 @@ const toolHandlers = {
|
|
|
4231
4143
|
return {
|
|
4232
4144
|
type: "templates",
|
|
4233
4145
|
count: filtered.length,
|
|
4234
|
-
templates: filtered.map(t => ({ id: t.id, name: t.name, description: t.description }))
|
|
4146
|
+
templates: filtered.map(t => ({ id: t.id, name: t.name, description: t.description })),
|
|
4147
|
+
_tip: filtered.length > 0
|
|
4148
|
+
? "Create from template: persona(method=\"create\", name=\"My AI\", from=\"<template_id>\")"
|
|
4149
|
+
: "No templates found. Create from scratch: persona(method=\"create\", name=\"My AI\", type=\"voice|chat|dashboard\")",
|
|
4150
|
+
_next_step: filtered.length > 0
|
|
4151
|
+
? `catalog(method="get", type="templates", id="${filtered[0].id}")`
|
|
4152
|
+
: undefined,
|
|
4235
4153
|
};
|
|
4236
4154
|
}
|
|
4237
4155
|
case "widgets": {
|
|
@@ -4266,13 +4184,20 @@ const toolHandlers = {
|
|
|
4266
4184
|
};
|
|
4267
4185
|
}
|
|
4268
4186
|
case "patterns": {
|
|
4269
|
-
if (recommend) {
|
|
4187
|
+
if (method === "recommend" && forUseCase) {
|
|
4270
4188
|
// Find patterns matching use case
|
|
4271
|
-
const q =
|
|
4189
|
+
const q = forUseCase.toLowerCase();
|
|
4272
4190
|
const matches = WORKFLOW_PATTERNS.filter(p => p.name.toLowerCase().includes(q) ||
|
|
4273
4191
|
p.description.toLowerCase().includes(q) ||
|
|
4274
4192
|
p.useCase.toLowerCase().includes(q));
|
|
4275
|
-
return {
|
|
4193
|
+
return {
|
|
4194
|
+
type: "patterns",
|
|
4195
|
+
use_case: forUseCase,
|
|
4196
|
+
recommendations: matches,
|
|
4197
|
+
_tip: matches.length > 0
|
|
4198
|
+
? `Found ${matches.length} matching patterns. Use catalog(method="get", type="patterns", id="<name>") for full details.`
|
|
4199
|
+
: "No matching patterns. Try catalog(method=\"list\", type=\"patterns\") to see all available.",
|
|
4200
|
+
};
|
|
4276
4201
|
}
|
|
4277
4202
|
if (id) {
|
|
4278
4203
|
const pattern = WORKFLOW_PATTERNS.find(p => p.name === id);
|
|
@@ -4324,14 +4249,14 @@ const toolHandlers = {
|
|
|
4324
4249
|
// Note: demo is handled via a consolidated adapter below
|
|
4325
4250
|
};
|
|
4326
4251
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
4327
|
-
//
|
|
4252
|
+
// V2 Tool Adapters (contract ↔ implementation)
|
|
4328
4253
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
4329
4254
|
//
|
|
4330
|
-
// The tool schemas in tools
|
|
4331
|
-
// This file still contains
|
|
4255
|
+
// The tool schemas in tools.ts are the public MCP contract.
|
|
4256
|
+
// This file still contains proven handlers that we reuse
|
|
4332
4257
|
// (e.g. deploy_workflow, optimize_workflow, compile_workflow, etc.).
|
|
4333
4258
|
//
|
|
4334
|
-
// These adapters ensure the
|
|
4259
|
+
// These adapters ensure the V2 tool surface behaves as documented,
|
|
4335
4260
|
// while preserving the existing internal implementations.
|
|
4336
4261
|
const legacyWorkflowTool = toolHandlers.workflow;
|
|
4337
4262
|
const legacyDeployWorkflow = toolHandlers.deploy_workflow;
|
|
@@ -4347,110 +4272,27 @@ const legacyConsolidateDemoData = toolHandlers.consolidate_demo_data;
|
|
|
4347
4272
|
const legacyGenerateDemoDocument = toolHandlers.generate_demo_document;
|
|
4348
4273
|
const legacyValidateDemoDocument = toolHandlers.validate_demo_document;
|
|
4349
4274
|
const legacyGetDemoDataTemplate = toolHandlers.get_demo_data_template;
|
|
4350
|
-
//
|
|
4275
|
+
// Workflow tool: MCP provides data (get) and executes (deploy). LLM does all thinking.
|
|
4351
4276
|
toolHandlers.workflow = async (args) => {
|
|
4352
|
-
// Normalize persona type alias: tool schema uses "type", internal uses "persona_type"
|
|
4353
4277
|
const normalizedArgs = { ...(args ?? {}) };
|
|
4354
|
-
if (normalizedArgs.persona_type === undefined && normalizedArgs.type !== undefined) {
|
|
4355
|
-
normalizedArgs.persona_type = normalizedArgs.type;
|
|
4356
|
-
}
|
|
4357
4278
|
const personaId = normalizedArgs.persona_id ? String(normalizedArgs.persona_id) : undefined;
|
|
4358
4279
|
const workflowDef = normalizedArgs.workflow_def;
|
|
4359
|
-
const
|
|
4360
|
-
//
|
|
4361
|
-
const
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
(personaId && workflowDef ? "deploy" : // Direct deployment (no input required)
|
|
4371
|
-
personaId && inputProvided ? "modify" : // BROWNFIELD: existing persona + new requirements
|
|
4372
|
-
workflowDef || personaId ? "analyze" : // Inspect existing
|
|
4373
|
-
"generate"); // GREENFIELD: new workflow
|
|
4374
|
-
switch (effectiveMode) {
|
|
4375
|
-
case "generate": {
|
|
4376
|
-
const result = await legacyWorkflowTool({ ...normalizedArgs, mode: "generate" });
|
|
4377
|
-
// Ensure next_steps point at consolidated tools by default
|
|
4378
|
-
if (result && typeof result === "object") {
|
|
4379
|
-
const obj = result;
|
|
4380
|
-
const persona_id = obj.persona_id ? String(obj.persona_id) : personaId;
|
|
4381
|
-
const deployed = obj.deployed === true;
|
|
4382
|
-
obj.next_steps = deployed
|
|
4383
|
-
? persona_id
|
|
4384
|
-
? [`Verify: persona(id="${persona_id}", include_workflow=true)`]
|
|
4385
|
-
: ["Verify the deployed AI Employee in the Ema UI"]
|
|
4386
|
-
: persona_id
|
|
4387
|
-
? [
|
|
4388
|
-
`Deploy: workflow(mode="deploy", persona_id="${persona_id}", workflow_def=<workflow_def>, proto_config=<proto_config>)`,
|
|
4389
|
-
`Verify: persona(id="${persona_id}", include_workflow=true)`,
|
|
4390
|
-
]
|
|
4391
|
-
: [
|
|
4392
|
-
"Create an AI Employee in Ema, then deploy:",
|
|
4393
|
-
`workflow(mode="deploy", persona_id="<persona_id>", workflow_def=<workflow_def>, proto_config=<proto_config>)`,
|
|
4394
|
-
];
|
|
4395
|
-
}
|
|
4396
|
-
return result;
|
|
4397
|
-
}
|
|
4398
|
-
case "analyze": {
|
|
4399
|
-
const include = Array.isArray(normalizedArgs.include)
|
|
4400
|
-
? normalizedArgs.include.map(String)
|
|
4401
|
-
: ["issues", "connections", "fixes", "metrics"];
|
|
4402
|
-
let wf = workflowDef;
|
|
4403
|
-
let meta;
|
|
4404
|
-
if (!wf && personaId) {
|
|
4405
|
-
const client = createClient(normalizedArgs.env);
|
|
4406
|
-
const persona = await client.getPersonaById(personaId);
|
|
4407
|
-
if (!persona)
|
|
4408
|
-
throw new Error(`AI Employee not found: ${personaId}`);
|
|
4409
|
-
wf = persona.workflow_def;
|
|
4410
|
-
meta = {
|
|
4411
|
-
persona_id: personaId,
|
|
4412
|
-
persona_name: persona.name,
|
|
4413
|
-
environment: client["env"].name,
|
|
4414
|
-
};
|
|
4415
|
-
}
|
|
4416
|
-
if (!wf) {
|
|
4417
|
-
return {
|
|
4418
|
-
error: "Missing workflow to analyze. Provide persona_id or workflow_def.",
|
|
4419
|
-
hint: 'Examples: workflow(mode="analyze", persona_id="...") or workflow(mode="analyze", workflow_def={...})',
|
|
4420
|
-
};
|
|
4421
|
-
}
|
|
4422
|
-
const out = { mode: "analyze", ...(meta ?? {}) };
|
|
4423
|
-
// Issues + summary (source of truth)
|
|
4424
|
-
const issuesResult = await legacyDetectWorkflowIssues({ workflow_def: wf });
|
|
4425
|
-
const issues = issuesResult.issues;
|
|
4426
|
-
if (include.includes("issues")) {
|
|
4427
|
-
out.issues = issuesResult.issues;
|
|
4428
|
-
out.issue_summary = issuesResult.summary;
|
|
4429
|
-
out.validation_passed = issuesResult.validation_passed;
|
|
4430
|
-
}
|
|
4431
|
-
if (include.includes("connections")) {
|
|
4432
|
-
out.connections = await legacyValidateWorkflowConnections({ workflow_def: wf });
|
|
4433
|
-
}
|
|
4434
|
-
if (include.includes("fixes")) {
|
|
4435
|
-
out.fixes = Array.isArray(issues) ? await legacySuggestWorkflowFixes({ issues }) : { error: "No issues array available to generate fixes" };
|
|
4436
|
-
}
|
|
4437
|
-
if (include.includes("metrics")) {
|
|
4438
|
-
const actions = wf.actions ?? [];
|
|
4439
|
-
const edges = wf.edges ?? [];
|
|
4440
|
-
out.metrics = {
|
|
4441
|
-
node_count: Array.isArray(actions) ? actions.length : 0,
|
|
4442
|
-
edge_count: Array.isArray(edges) ? edges.length : 0,
|
|
4443
|
-
};
|
|
4444
|
-
}
|
|
4445
|
-
return out;
|
|
4280
|
+
const mode = normalizedArgs.mode ? String(normalizedArgs.mode) : undefined;
|
|
4281
|
+
// Route to handleWorkflow for get/deploy (the only public modes)
|
|
4282
|
+
const client = createClient(normalizedArgs.env);
|
|
4283
|
+
switch (mode) {
|
|
4284
|
+
case "get": {
|
|
4285
|
+
// Return workflow data for LLM to analyze/modify
|
|
4286
|
+
return handleWorkflow({
|
|
4287
|
+
mode: "get",
|
|
4288
|
+
persona_id: personaId,
|
|
4289
|
+
env: normalizedArgs.env,
|
|
4290
|
+
}, client, () => undefined);
|
|
4446
4291
|
}
|
|
4447
4292
|
case "deploy": {
|
|
4448
4293
|
if (!personaId) {
|
|
4449
|
-
|
|
4294
|
+
return { error: 'persona_id is required for workflow(mode="deploy")' };
|
|
4450
4295
|
}
|
|
4451
|
-
// Use clean deploy path via handleWorkflow (no brownfield merge, no excessive validation)
|
|
4452
|
-
// User can still request validation via validate=true, but default is now direct deploy
|
|
4453
|
-
const client = createClient(normalizedArgs.env);
|
|
4454
4296
|
// Optional: pre-deploy version snapshot
|
|
4455
4297
|
const targetEnv = normalizedArgs.env ?? getDefaultEnvName();
|
|
4456
4298
|
let versionCreated;
|
|
@@ -4476,8 +4318,7 @@ toolHandlers.workflow = async (args) => {
|
|
|
4476
4318
|
catch {
|
|
4477
4319
|
// Version tracking is best-effort
|
|
4478
4320
|
}
|
|
4479
|
-
// Route to
|
|
4480
|
-
// This path: sanitizes workflow → calls client.updateAiEmployee → done
|
|
4321
|
+
// Route to handleWorkflow deploy
|
|
4481
4322
|
const deployResult = await handleWorkflow({
|
|
4482
4323
|
mode: "deploy",
|
|
4483
4324
|
persona_id: personaId,
|
|
@@ -4491,58 +4332,25 @@ toolHandlers.workflow = async (args) => {
|
|
|
4491
4332
|
}
|
|
4492
4333
|
return deployResult;
|
|
4493
4334
|
}
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
return legacyOptimizeWorkflow({
|
|
4506
|
-
identifier: idOrIdentifier ?? personaId,
|
|
4507
|
-
persona_id: personaId,
|
|
4508
|
-
prompt,
|
|
4509
|
-
type: normalizedArgs.persona_type,
|
|
4510
|
-
preview,
|
|
4511
|
-
env: normalizedArgs.env,
|
|
4512
|
-
});
|
|
4513
|
-
}
|
|
4514
|
-
case "compare": {
|
|
4515
|
-
if (!personaId) {
|
|
4516
|
-
throw new Error('persona_id is required for workflow(mode="compare")');
|
|
4517
|
-
}
|
|
4518
|
-
const compareTo = normalizedArgs.compare_to ? String(normalizedArgs.compare_to) : undefined;
|
|
4519
|
-
if (!compareTo) {
|
|
4520
|
-
throw new Error('compare_to is required for workflow(mode="compare")');
|
|
4521
|
-
}
|
|
4522
|
-
return legacyCompareWorkflowVersions({
|
|
4523
|
-
persona_id_before: personaId,
|
|
4524
|
-
persona_id_after: compareTo,
|
|
4525
|
-
env: normalizedArgs.env,
|
|
4526
|
-
});
|
|
4527
|
-
}
|
|
4528
|
-
case "compile": {
|
|
4529
|
-
// Compile requires node specs + result mappings.
|
|
4530
|
-
if (!normalizedArgs.name || !normalizedArgs.description) {
|
|
4531
|
-
throw new Error('workflow(mode="compile") requires name and description');
|
|
4532
|
-
}
|
|
4533
|
-
if (!normalizedArgs.persona_type) {
|
|
4534
|
-
throw new Error('workflow(mode="compile") requires persona type via type="voice|chat|dashboard"');
|
|
4535
|
-
}
|
|
4536
|
-
return legacyCompileWorkflow({
|
|
4537
|
-
name: normalizedArgs.name,
|
|
4538
|
-
description: normalizedArgs.description,
|
|
4539
|
-
persona_type: normalizedArgs.persona_type,
|
|
4540
|
-
nodes: normalizedArgs.nodes,
|
|
4541
|
-
result_mappings: normalizedArgs.result_mappings,
|
|
4542
|
-
});
|
|
4335
|
+
// REMOVED modes - LLM does these
|
|
4336
|
+
case "analyze":
|
|
4337
|
+
case "compare":
|
|
4338
|
+
case "compile":
|
|
4339
|
+
case "optimize":
|
|
4340
|
+
case "generate": {
|
|
4341
|
+
return {
|
|
4342
|
+
error: `Mode "${mode}" removed - LLM does this thinking`,
|
|
4343
|
+
hint: "Use workflow(mode='get') to fetch data, then analyze/generate in your reasoning. Deploy with workflow(mode='deploy').",
|
|
4344
|
+
valid_modes: ["get", "deploy"],
|
|
4345
|
+
};
|
|
4543
4346
|
}
|
|
4544
4347
|
default: {
|
|
4545
|
-
|
|
4348
|
+
// No mode or unknown mode - require explicit mode
|
|
4349
|
+
return {
|
|
4350
|
+
error: `Mode required. Valid modes: get, deploy`,
|
|
4351
|
+
hint: "workflow(mode='get') returns data for LLM. workflow(mode='deploy') executes LLM's workflow_def.",
|
|
4352
|
+
example: `workflow(mode="get", persona_id="...")`,
|
|
4353
|
+
};
|
|
4546
4354
|
}
|
|
4547
4355
|
}
|
|
4548
4356
|
};
|
|
@@ -4904,8 +4712,8 @@ function determineOperation(toolName, args) {
|
|
|
4904
4712
|
if (toolName === "catalog") {
|
|
4905
4713
|
if (args.id)
|
|
4906
4714
|
return "get";
|
|
4907
|
-
if (args.
|
|
4908
|
-
return "recommend";
|
|
4715
|
+
if (args.for)
|
|
4716
|
+
return "recommend"; // V2 schema uses 'for' parameter
|
|
4909
4717
|
if (args.query)
|
|
4910
4718
|
return "search";
|
|
4911
4719
|
return "list";
|