snow-flow 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/.env.example +49 -0
  2. package/.mcp.json +106 -0
  3. package/.mcp.json.template +106 -0
  4. package/LICENSE +21 -0
  5. package/README.md +236 -0
  6. package/bin/snow-flow +4 -0
  7. package/bin/snow-flow.js +3 -0
  8. package/claude-flow +79 -0
  9. package/claude-flow.bat +18 -0
  10. package/claude-flow.config.json +20 -0
  11. package/claude-flow.ps1 +24 -0
  12. package/dist/agents/app-creator.agent.d.ts +55 -0
  13. package/dist/agents/app-creator.agent.d.ts.map +1 -0
  14. package/dist/agents/app-creator.agent.js +1292 -0
  15. package/dist/agents/app-creator.agent.js.map +1 -0
  16. package/dist/agents/base-snow-agent.d.ts +63 -0
  17. package/dist/agents/base-snow-agent.d.ts.map +1 -0
  18. package/dist/agents/base-snow-agent.js +296 -0
  19. package/dist/agents/base-snow-agent.js.map +1 -0
  20. package/dist/agents/script-generator.agent.d.ts +32 -0
  21. package/dist/agents/script-generator.agent.d.ts.map +1 -0
  22. package/dist/agents/script-generator.agent.js +772 -0
  23. package/dist/agents/script-generator.agent.js.map +1 -0
  24. package/dist/agents/ui-builder.agent.d.ts +50 -0
  25. package/dist/agents/ui-builder.agent.d.ts.map +1 -0
  26. package/dist/agents/ui-builder.agent.js +1539 -0
  27. package/dist/agents/ui-builder.agent.js.map +1 -0
  28. package/dist/agents/widget-builder.agent.d.ts +32 -0
  29. package/dist/agents/widget-builder.agent.d.ts.map +1 -0
  30. package/dist/agents/widget-builder.agent.js +439 -0
  31. package/dist/agents/widget-builder.agent.js.map +1 -0
  32. package/dist/agents/workflow-designer.agent.d.ts +31 -0
  33. package/dist/agents/workflow-designer.agent.d.ts.map +1 -0
  34. package/dist/agents/workflow-designer.agent.js +583 -0
  35. package/dist/agents/workflow-designer.agent.js.map +1 -0
  36. package/dist/api/error-handling.d.ts +214 -0
  37. package/dist/api/error-handling.d.ts.map +1 -0
  38. package/dist/api/error-handling.js +594 -0
  39. package/dist/api/error-handling.js.map +1 -0
  40. package/dist/api/flow-designer-api.d.ts +167 -0
  41. package/dist/api/flow-designer-api.d.ts.map +1 -0
  42. package/dist/api/flow-designer-api.js +555 -0
  43. package/dist/api/flow-designer-api.js.map +1 -0
  44. package/dist/api/natural-language-mapper.d.ts +126 -0
  45. package/dist/api/natural-language-mapper.d.ts.map +1 -0
  46. package/dist/api/natural-language-mapper.js +498 -0
  47. package/dist/api/natural-language-mapper.js.map +1 -0
  48. package/dist/api/performance-optimizer.d.ts +240 -0
  49. package/dist/api/performance-optimizer.d.ts.map +1 -0
  50. package/dist/api/performance-optimizer.js +701 -0
  51. package/dist/api/performance-optimizer.js.map +1 -0
  52. package/dist/api/transaction-manager.d.ts +189 -0
  53. package/dist/api/transaction-manager.d.ts.map +1 -0
  54. package/dist/api/transaction-manager.js +576 -0
  55. package/dist/api/transaction-manager.js.map +1 -0
  56. package/dist/cli/deploy-artifact.d.ts +7 -0
  57. package/dist/cli/deploy-artifact.d.ts.map +1 -0
  58. package/dist/cli/deploy-artifact.js +279 -0
  59. package/dist/cli/deploy-artifact.js.map +1 -0
  60. package/dist/cli.d.ts +6 -0
  61. package/dist/cli.d.ts.map +1 -0
  62. package/dist/cli.js +2057 -0
  63. package/dist/cli.js.map +1 -0
  64. package/dist/index.d.ts +10 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +35 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/managers/scope-manager.d.ts +75 -0
  69. package/dist/managers/scope-manager.d.ts.map +1 -0
  70. package/dist/managers/scope-manager.js +448 -0
  71. package/dist/managers/scope-manager.js.map +1 -0
  72. package/dist/mcp/mcp-wrapper.d.ts +8 -0
  73. package/dist/mcp/mcp-wrapper.d.ts.map +1 -0
  74. package/dist/mcp/mcp-wrapper.js +77 -0
  75. package/dist/mcp/mcp-wrapper.js.map +1 -0
  76. package/dist/mcp/servicenow-automation-mcp.d.ts +8 -0
  77. package/dist/mcp/servicenow-automation-mcp.d.ts.map +1 -0
  78. package/dist/mcp/servicenow-automation-mcp.js +683 -0
  79. package/dist/mcp/servicenow-automation-mcp.js.map +1 -0
  80. package/dist/mcp/servicenow-deployment-mcp.d.ts +7 -0
  81. package/dist/mcp/servicenow-deployment-mcp.d.ts.map +1 -0
  82. package/dist/mcp/servicenow-deployment-mcp.js +972 -0
  83. package/dist/mcp/servicenow-deployment-mcp.js.map +1 -0
  84. package/dist/mcp/servicenow-flow-composer-mcp.d.ts +7 -0
  85. package/dist/mcp/servicenow-flow-composer-mcp.d.ts.map +1 -0
  86. package/dist/mcp/servicenow-flow-composer-mcp.js +1121 -0
  87. package/dist/mcp/servicenow-flow-composer-mcp.js.map +1 -0
  88. package/dist/mcp/servicenow-graph-memory-mcp.d.ts +7 -0
  89. package/dist/mcp/servicenow-graph-memory-mcp.d.ts.map +1 -0
  90. package/dist/mcp/servicenow-graph-memory-mcp.js +703 -0
  91. package/dist/mcp/servicenow-graph-memory-mcp.js.map +1 -0
  92. package/dist/mcp/servicenow-integration-mcp.d.ts +8 -0
  93. package/dist/mcp/servicenow-integration-mcp.d.ts.map +1 -0
  94. package/dist/mcp/servicenow-integration-mcp.js +689 -0
  95. package/dist/mcp/servicenow-integration-mcp.js.map +1 -0
  96. package/dist/mcp/servicenow-intelligent-mcp.d.ts +7 -0
  97. package/dist/mcp/servicenow-intelligent-mcp.d.ts.map +1 -0
  98. package/dist/mcp/servicenow-intelligent-mcp.js +1138 -0
  99. package/dist/mcp/servicenow-intelligent-mcp.js.map +1 -0
  100. package/dist/mcp/servicenow-mcp-server.d.ts +37 -0
  101. package/dist/mcp/servicenow-mcp-server.d.ts.map +1 -0
  102. package/dist/mcp/servicenow-mcp-server.js +648 -0
  103. package/dist/mcp/servicenow-mcp-server.js.map +1 -0
  104. package/dist/mcp/servicenow-operations-mcp.d.ts +15 -0
  105. package/dist/mcp/servicenow-operations-mcp.d.ts.map +1 -0
  106. package/dist/mcp/servicenow-operations-mcp.js +1287 -0
  107. package/dist/mcp/servicenow-operations-mcp.js.map +1 -0
  108. package/dist/mcp/servicenow-platform-development-mcp.d.ts +8 -0
  109. package/dist/mcp/servicenow-platform-development-mcp.d.ts.map +1 -0
  110. package/dist/mcp/servicenow-platform-development-mcp.js +557 -0
  111. package/dist/mcp/servicenow-platform-development-mcp.js.map +1 -0
  112. package/dist/mcp/servicenow-progressive-indexer.d.ts +79 -0
  113. package/dist/mcp/servicenow-progressive-indexer.d.ts.map +1 -0
  114. package/dist/mcp/servicenow-progressive-indexer.js +320 -0
  115. package/dist/mcp/servicenow-progressive-indexer.js.map +1 -0
  116. package/dist/mcp/servicenow-reporting-analytics-mcp.d.ts +8 -0
  117. package/dist/mcp/servicenow-reporting-analytics-mcp.d.ts.map +1 -0
  118. package/dist/mcp/servicenow-reporting-analytics-mcp.js +888 -0
  119. package/dist/mcp/servicenow-reporting-analytics-mcp.js.map +1 -0
  120. package/dist/mcp/servicenow-security-compliance-mcp.d.ts +8 -0
  121. package/dist/mcp/servicenow-security-compliance-mcp.d.ts.map +1 -0
  122. package/dist/mcp/servicenow-security-compliance-mcp.js +812 -0
  123. package/dist/mcp/servicenow-security-compliance-mcp.js.map +1 -0
  124. package/dist/mcp/servicenow-update-set-mcp.d.ts +7 -0
  125. package/dist/mcp/servicenow-update-set-mcp.d.ts.map +1 -0
  126. package/dist/mcp/servicenow-update-set-mcp.js +599 -0
  127. package/dist/mcp/servicenow-update-set-mcp.js.map +1 -0
  128. package/dist/mcp/start-all-mcp-servers.d.ts +6 -0
  129. package/dist/mcp/start-all-mcp-servers.d.ts.map +1 -0
  130. package/dist/mcp/start-all-mcp-servers.js +65 -0
  131. package/dist/mcp/start-all-mcp-servers.js.map +1 -0
  132. package/dist/mcp/start-servicenow-mcp.d.ts +7 -0
  133. package/dist/mcp/start-servicenow-mcp.d.ts.map +1 -0
  134. package/dist/mcp/start-servicenow-mcp.js +64 -0
  135. package/dist/mcp/start-servicenow-mcp.js.map +1 -0
  136. package/dist/mcp/test-simple-mcp.d.ts +6 -0
  137. package/dist/mcp/test-simple-mcp.d.ts.map +1 -0
  138. package/dist/mcp/test-simple-mcp.js +64 -0
  139. package/dist/mcp/test-simple-mcp.js.map +1 -0
  140. package/dist/orchestrator/flow-composer.d.ts +269 -0
  141. package/dist/orchestrator/flow-composer.d.ts.map +1 -0
  142. package/dist/orchestrator/flow-composer.js +2221 -0
  143. package/dist/orchestrator/flow-composer.js.map +1 -0
  144. package/dist/orchestrator/flow-pattern-templates.d.ts +260 -0
  145. package/dist/orchestrator/flow-pattern-templates.d.ts.map +1 -0
  146. package/dist/orchestrator/flow-pattern-templates.js +906 -0
  147. package/dist/orchestrator/flow-pattern-templates.js.map +1 -0
  148. package/dist/orchestrator/flow-subflow-decision-engine.d.ts +202 -0
  149. package/dist/orchestrator/flow-subflow-decision-engine.d.ts.map +1 -0
  150. package/dist/orchestrator/flow-subflow-decision-engine.js +769 -0
  151. package/dist/orchestrator/flow-subflow-decision-engine.js.map +1 -0
  152. package/dist/orchestrator/flow-validation-engine.d.ts +145 -0
  153. package/dist/orchestrator/flow-validation-engine.d.ts.map +1 -0
  154. package/dist/orchestrator/flow-validation-engine.js +663 -0
  155. package/dist/orchestrator/flow-validation-engine.js.map +1 -0
  156. package/dist/orchestrator/snow-orchestrator.d.ts +49 -0
  157. package/dist/orchestrator/snow-orchestrator.d.ts.map +1 -0
  158. package/dist/orchestrator/snow-orchestrator.js +235 -0
  159. package/dist/orchestrator/snow-orchestrator.js.map +1 -0
  160. package/dist/orchestrator/subflow-creation-handler.d.ts +230 -0
  161. package/dist/orchestrator/subflow-creation-handler.d.ts.map +1 -0
  162. package/dist/orchestrator/subflow-creation-handler.js +791 -0
  163. package/dist/orchestrator/subflow-creation-handler.js.map +1 -0
  164. package/dist/strategies/global-scope-strategy.d.ts +123 -0
  165. package/dist/strategies/global-scope-strategy.d.ts.map +1 -0
  166. package/dist/strategies/global-scope-strategy.js +585 -0
  167. package/dist/strategies/global-scope-strategy.js.map +1 -0
  168. package/dist/types/index.d.ts +138 -0
  169. package/dist/types/index.d.ts.map +1 -0
  170. package/dist/types/index.js +4 -0
  171. package/dist/types/index.js.map +1 -0
  172. package/dist/types/servicenow.types.d.ts +260 -0
  173. package/dist/types/servicenow.types.d.ts.map +1 -0
  174. package/dist/types/servicenow.types.js +3 -0
  175. package/dist/types/servicenow.types.js.map +1 -0
  176. package/dist/types/snow-flow.types.d.ts +114 -0
  177. package/dist/types/snow-flow.types.d.ts.map +1 -0
  178. package/dist/types/snow-flow.types.js +3 -0
  179. package/dist/types/snow-flow.types.js.map +1 -0
  180. package/dist/utils/action-type-cache.d.ts +66 -0
  181. package/dist/utils/action-type-cache.d.ts.map +1 -0
  182. package/dist/utils/action-type-cache.js +237 -0
  183. package/dist/utils/action-type-cache.js.map +1 -0
  184. package/dist/utils/agent-detector.d.ts +35 -0
  185. package/dist/utils/agent-detector.d.ts.map +1 -0
  186. package/dist/utils/agent-detector.js +353 -0
  187. package/dist/utils/agent-detector.js.map +1 -0
  188. package/dist/utils/flow-api-discovery.d.ts +151 -0
  189. package/dist/utils/flow-api-discovery.d.ts.map +1 -0
  190. package/dist/utils/flow-api-discovery.js +440 -0
  191. package/dist/utils/flow-api-discovery.js.map +1 -0
  192. package/dist/utils/flow-xml-generator.d.ts +41 -0
  193. package/dist/utils/flow-xml-generator.d.ts.map +1 -0
  194. package/dist/utils/flow-xml-generator.js +258 -0
  195. package/dist/utils/flow-xml-generator.js.map +1 -0
  196. package/dist/utils/logger.d.ts +13 -0
  197. package/dist/utils/logger.d.ts.map +1 -0
  198. package/dist/utils/logger.js +51 -0
  199. package/dist/utils/logger.js.map +1 -0
  200. package/dist/utils/mcp-auth-middleware.d.ts +58 -0
  201. package/dist/utils/mcp-auth-middleware.d.ts.map +1 -0
  202. package/dist/utils/mcp-auth-middleware.js +227 -0
  203. package/dist/utils/mcp-auth-middleware.js.map +1 -0
  204. package/dist/utils/mcp-config-manager.d.ts +126 -0
  205. package/dist/utils/mcp-config-manager.d.ts.map +1 -0
  206. package/dist/utils/mcp-config-manager.js +209 -0
  207. package/dist/utils/mcp-config-manager.js.map +1 -0
  208. package/dist/utils/mcp-server-manager.d.ts +91 -0
  209. package/dist/utils/mcp-server-manager.d.ts.map +1 -0
  210. package/dist/utils/mcp-server-manager.js +338 -0
  211. package/dist/utils/mcp-server-manager.js.map +1 -0
  212. package/dist/utils/scope-utils.d.ts +72 -0
  213. package/dist/utils/scope-utils.d.ts.map +1 -0
  214. package/dist/utils/scope-utils.js +386 -0
  215. package/dist/utils/scope-utils.js.map +1 -0
  216. package/dist/utils/servicenow-client.d.ts +233 -0
  217. package/dist/utils/servicenow-client.d.ts.map +1 -0
  218. package/dist/utils/servicenow-client.js +1465 -0
  219. package/dist/utils/servicenow-client.js.map +1 -0
  220. package/dist/utils/snow-oauth-old.d.ts +65 -0
  221. package/dist/utils/snow-oauth-old.d.ts.map +1 -0
  222. package/dist/utils/snow-oauth-old.js +345 -0
  223. package/dist/utils/snow-oauth-old.js.map +1 -0
  224. package/dist/utils/snow-oauth.d.ts +85 -0
  225. package/dist/utils/snow-oauth.d.ts.map +1 -0
  226. package/dist/utils/snow-oauth.js +512 -0
  227. package/dist/utils/snow-oauth.js.map +1 -0
  228. package/dist/utils/template-engine.d.ts +76 -0
  229. package/dist/utils/template-engine.d.ts.map +1 -0
  230. package/dist/utils/template-engine.js +391 -0
  231. package/dist/utils/template-engine.js.map +1 -0
  232. package/dist/version.d.ts +35 -0
  233. package/dist/version.d.ts.map +1 -0
  234. package/dist/version.js +72 -0
  235. package/dist/version.js.map +1 -0
  236. package/mcp-wrapper.sh +12 -0
  237. package/package.json +77 -0
  238. package/reports/swarm-auto-centralized-1752649029776.json +13 -0
  239. package/scripts/postinstall.js +30 -0
  240. package/scripts/setup-mcp.js +89 -0
@@ -0,0 +1,2221 @@
1
+ "use strict";
2
+ /**
3
+ * Enhanced ServiceNow Flow Composer with Intelligent Artifact Linking
4
+ * Fixes weaknesses in artifact orchestration and linking
5
+ * Now includes intelligent Flow vs Subflow decision making
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.EnhancedFlowComposer = void 0;
9
+ const servicenow_client_js_1 = require("../utils/servicenow-client.js");
10
+ const servicenow_artifact_indexer_js_1 = require("../memory/servicenow-artifact-indexer.js");
11
+ const logger_js_1 = require("../utils/logger.js");
12
+ const flow_subflow_decision_engine_js_1 = require("./flow-subflow-decision-engine.js");
13
+ const subflow_creation_handler_js_1 = require("./subflow-creation-handler.js");
14
+ const flow_pattern_templates_js_1 = require("./flow-pattern-templates.js");
15
+ const flow_validation_engine_js_1 = require("./flow-validation-engine.js");
16
+ const scope_manager_js_1 = require("../managers/scope-manager.js");
17
+ const global_scope_strategy_js_1 = require("../strategies/global-scope-strategy.js");
18
+ class EnhancedFlowComposer {
19
+ constructor() {
20
+ this.artifactRegistry = new Map();
21
+ this.client = new servicenow_client_js_1.ServiceNowClient();
22
+ this.indexer = new servicenow_artifact_indexer_js_1.ServiceNowArtifactIndexer();
23
+ this.logger = new logger_js_1.Logger('EnhancedFlowComposer');
24
+ // Initialize intelligent components
25
+ this.decisionEngine = new flow_subflow_decision_engine_js_1.FlowSubflowDecisionEngine();
26
+ this.subflowHandler = new subflow_creation_handler_js_1.SubflowCreationHandler();
27
+ this.patternTemplates = new flow_pattern_templates_js_1.FlowPatternTemplates();
28
+ this.validationEngine = new flow_validation_engine_js_1.FlowValidationEngine();
29
+ // Initialize global scope management
30
+ this.scopeManager = new scope_manager_js_1.ScopeManager({
31
+ defaultScope: global_scope_strategy_js_1.ScopeType.GLOBAL,
32
+ allowFallback: true,
33
+ validatePermissions: true,
34
+ enableMigration: false
35
+ });
36
+ this.globalScopeStrategy = new global_scope_strategy_js_1.GlobalScopeStrategy();
37
+ }
38
+ /**
39
+ * Analyze artifact API to understand inputs/outputs
40
+ */
41
+ async analyzeArtifactAPI(artifact) {
42
+ this.logger.info('Analyzing artifact API', { name: artifact.name, type: artifact.sys_class_name });
43
+ const artifactInterface = {
44
+ sys_id: artifact.sys_id,
45
+ name: artifact.name,
46
+ type: artifact.sys_class_name,
47
+ inputs: [],
48
+ outputs: [],
49
+ dependencies: [],
50
+ compatibility_score: 0
51
+ };
52
+ // Analyze based on artifact type
53
+ switch (artifact.sys_class_name) {
54
+ case 'sys_script_include':
55
+ artifactInterface.inputs = await this.analyzeScriptIncludeAPI(artifact);
56
+ artifactInterface.outputs = await this.analyzeScriptIncludeOutputs(artifact);
57
+ break;
58
+ case 'sys_script':
59
+ artifactInterface.inputs = await this.analyzeBusinessRuleAPI(artifact);
60
+ artifactInterface.outputs = await this.analyzeBusinessRuleOutputs(artifact);
61
+ break;
62
+ case 'sys_db_object':
63
+ artifactInterface.inputs = await this.analyzeTableAPI(artifact);
64
+ artifactInterface.outputs = await this.analyzeTableOutputs(artifact);
65
+ break;
66
+ }
67
+ // Store in registry
68
+ this.artifactRegistry.set(artifact.sys_id, artifactInterface);
69
+ return artifactInterface;
70
+ }
71
+ /**
72
+ * Analyze Script Include API by parsing the actual script
73
+ */
74
+ async analyzeScriptIncludeAPI(artifact) {
75
+ const script = artifact.script || '';
76
+ const inputs = [];
77
+ // Parse function parameters from script
78
+ const functionMatches = script.match(/function\s+(\w+)\s*\(([^)]*)\)/g);
79
+ if (functionMatches) {
80
+ for (const match of functionMatches) {
81
+ const params = match.match(/\(([^)]*)\)/)?.[1];
82
+ if (params) {
83
+ const paramList = params.split(',').map((p) => p.trim());
84
+ for (const param of paramList) {
85
+ if (param) {
86
+ inputs.push({
87
+ name: param,
88
+ type: this.inferParameterType(param, script),
89
+ required: true,
90
+ description: this.extractParameterDescription(param, script)
91
+ });
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ // Look for API patterns in script
98
+ if (script.includes('translateText')) {
99
+ inputs.push({
100
+ name: 'text',
101
+ type: 'string',
102
+ required: true,
103
+ description: 'Text to translate'
104
+ });
105
+ inputs.push({
106
+ name: 'target_language',
107
+ type: 'string',
108
+ required: true,
109
+ description: 'Target language for translation'
110
+ });
111
+ }
112
+ return inputs;
113
+ }
114
+ /**
115
+ * Analyze Script Include outputs by parsing return statements
116
+ */
117
+ async analyzeScriptIncludeOutputs(artifact) {
118
+ const script = artifact.script || '';
119
+ const outputs = [];
120
+ // Look for return patterns
121
+ if (script.includes('return {')) {
122
+ // Parse object return
123
+ const returnMatches = script.match(/return\s*\{([^}]*)\}/g);
124
+ if (returnMatches) {
125
+ for (const match of returnMatches) {
126
+ const objectContent = match.match(/\{([^}]*)\}/)?.[1];
127
+ if (objectContent) {
128
+ const properties = objectContent.split(',').map((p) => p.trim());
129
+ for (const prop of properties) {
130
+ const [key] = prop.split(':').map((p) => p.trim());
131
+ if (key) {
132
+ outputs.push({
133
+ name: key,
134
+ type: 'string',
135
+ description: `Output property: ${key}`
136
+ });
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+ // Common translation API output
144
+ if (script.includes('translateText') || script.includes('translation')) {
145
+ outputs.push({
146
+ name: 'translated_text',
147
+ type: 'string',
148
+ description: 'Translated text result'
149
+ });
150
+ outputs.push({
151
+ name: 'confidence',
152
+ type: 'number',
153
+ description: 'Translation confidence score'
154
+ });
155
+ outputs.push({
156
+ name: 'success',
157
+ type: 'boolean',
158
+ description: 'Translation success flag'
159
+ });
160
+ }
161
+ return outputs;
162
+ }
163
+ /**
164
+ * Analyze Business Rule API
165
+ */
166
+ async analyzeBusinessRuleAPI(artifact) {
167
+ const script = artifact.script || '';
168
+ const inputs = [];
169
+ // Business rules typically work with current record
170
+ inputs.push({
171
+ name: 'current',
172
+ type: 'object',
173
+ required: true,
174
+ description: 'Current record being processed'
175
+ });
176
+ // Look for specific field access patterns
177
+ const fieldMatches = script.match(/current\.getValue\(['"]([^'"]+)['"]\)/g);
178
+ if (fieldMatches) {
179
+ for (const match of fieldMatches) {
180
+ const field = match.match(/['"]([^'"]+)['"]/)?.[1];
181
+ if (field) {
182
+ inputs.push({
183
+ name: field,
184
+ type: 'string',
185
+ required: false,
186
+ description: `Field: ${field}`
187
+ });
188
+ }
189
+ }
190
+ }
191
+ return inputs;
192
+ }
193
+ /**
194
+ * Analyze Business Rule outputs
195
+ */
196
+ async analyzeBusinessRuleOutputs(artifact) {
197
+ const script = artifact.script || '';
198
+ const outputs = [];
199
+ // Business rules typically create records or modify current record
200
+ if (script.includes('GlideRecord') && script.includes('insert')) {
201
+ outputs.push({
202
+ name: 'created_record_id',
203
+ type: 'string',
204
+ description: 'ID of created record'
205
+ });
206
+ outputs.push({
207
+ name: 'success',
208
+ type: 'boolean',
209
+ description: 'Record creation success'
210
+ });
211
+ }
212
+ return outputs;
213
+ }
214
+ /**
215
+ * Analyze Table API
216
+ */
217
+ async analyzeTableAPI(artifact) {
218
+ const inputs = [];
219
+ // Tables accept field values as inputs
220
+ // This would need to query the actual table schema
221
+ inputs.push({
222
+ name: 'record_data',
223
+ type: 'object',
224
+ required: true,
225
+ description: 'Record data to insert/update'
226
+ });
227
+ return inputs;
228
+ }
229
+ /**
230
+ * Analyze Table outputs
231
+ */
232
+ async analyzeTableOutputs(artifact) {
233
+ const outputs = [];
234
+ // Tables return record information
235
+ outputs.push({
236
+ name: 'sys_id',
237
+ type: 'string',
238
+ description: 'System ID of the record'
239
+ });
240
+ outputs.push({
241
+ name: 'success',
242
+ type: 'boolean',
243
+ description: 'Operation success flag'
244
+ });
245
+ return outputs;
246
+ }
247
+ /**
248
+ * Find compatible artifacts for orchestration
249
+ */
250
+ async findCompatibleArtifacts(requiredCapability, availableArtifacts) {
251
+ const compatible = [];
252
+ for (const artifact of availableArtifacts) {
253
+ const compatibility = await this.calculateCompatibility(artifact, requiredCapability);
254
+ if (compatibility > 0.7) {
255
+ artifact.compatibility_score = compatibility;
256
+ compatible.push(artifact);
257
+ }
258
+ }
259
+ // Sort by compatibility score
260
+ return compatible.sort((a, b) => (b.compatibility_score || 0) - (a.compatibility_score || 0));
261
+ }
262
+ /**
263
+ * Calculate compatibility between artifact and required capability
264
+ */
265
+ async calculateCompatibility(artifact, capability) {
266
+ let score = 0;
267
+ // Name matching
268
+ if (artifact.name.toLowerCase().includes(capability.toLowerCase())) {
269
+ score += 0.3;
270
+ }
271
+ // Input/output matching
272
+ if (capability.includes('translation')) {
273
+ const hasTextInput = artifact.inputs.some(i => i.name.includes('text') || i.name.includes('message'));
274
+ const hasLanguageInput = artifact.inputs.some(i => i.name.includes('language'));
275
+ const hasTranslationOutput = artifact.outputs.some(o => o.name.includes('translated') || o.name.includes('translation'));
276
+ if (hasTextInput)
277
+ score += 0.2;
278
+ if (hasLanguageInput)
279
+ score += 0.2;
280
+ if (hasTranslationOutput)
281
+ score += 0.3;
282
+ }
283
+ if (capability.includes('storage') || capability.includes('save')) {
284
+ const hasRecordInput = artifact.inputs.some(i => i.name.includes('record') || i.name.includes('data'));
285
+ const hasSuccessOutput = artifact.outputs.some(o => o.name.includes('success') || o.name.includes('id'));
286
+ if (hasRecordInput)
287
+ score += 0.3;
288
+ if (hasSuccessOutput)
289
+ score += 0.2;
290
+ }
291
+ return Math.min(score, 1.0);
292
+ }
293
+ /**
294
+ * Create intelligent connections between artifacts
295
+ */
296
+ async createArtifactConnections(activities) {
297
+ const connections = [];
298
+ for (let i = 0; i < activities.length - 1; i++) {
299
+ const currentActivity = activities[i];
300
+ const nextActivity = activities[i + 1];
301
+ // Find matching outputs to inputs
302
+ for (const output of currentActivity.artifact.outputs) {
303
+ for (const input of nextActivity.artifact.inputs) {
304
+ if (this.areCompatible(output, input)) {
305
+ connections.push({
306
+ from_activity: currentActivity.id,
307
+ from_output: output.name,
308
+ to_activity: nextActivity.id,
309
+ to_input: input.name,
310
+ transformation: this.getTransformation(output, input)
311
+ });
312
+ break;
313
+ }
314
+ }
315
+ }
316
+ }
317
+ return connections;
318
+ }
319
+ /**
320
+ * Check if output and input are compatible
321
+ */
322
+ areCompatible(output, input) {
323
+ // Type compatibility
324
+ if (output.type !== input.type && input.type !== 'object') {
325
+ return false;
326
+ }
327
+ // Name similarity
328
+ const similarity = this.calculateNameSimilarity(output.name, input.name);
329
+ return similarity > 0.6;
330
+ }
331
+ /**
332
+ * Calculate name similarity between output and input
333
+ */
334
+ calculateNameSimilarity(output, input) {
335
+ const outputWords = output.toLowerCase().split('_');
336
+ const inputWords = input.toLowerCase().split('_');
337
+ let matches = 0;
338
+ for (const outputWord of outputWords) {
339
+ for (const inputWord of inputWords) {
340
+ if (outputWord === inputWord || outputWord.includes(inputWord) || inputWord.includes(outputWord)) {
341
+ matches++;
342
+ break;
343
+ }
344
+ }
345
+ }
346
+ return matches / Math.max(outputWords.length, inputWords.length);
347
+ }
348
+ /**
349
+ * Get transformation logic for output to input mapping
350
+ */
351
+ getTransformation(output, input) {
352
+ // Simple transformations
353
+ if (output.type === 'string' && input.type === 'object') {
354
+ return 'JSON.parse';
355
+ }
356
+ if (output.type === 'object' && input.type === 'string') {
357
+ return 'JSON.stringify';
358
+ }
359
+ return undefined;
360
+ }
361
+ /**
362
+ * Infer parameter type from script context
363
+ */
364
+ inferParameterType(param, script) {
365
+ if (script.includes(`${param}.length`) || script.includes(`${param}.split`)) {
366
+ return 'string';
367
+ }
368
+ if (script.includes(`${param} > `) || script.includes(`${param} < `)) {
369
+ return 'number';
370
+ }
371
+ if (script.includes(`${param} === true`) || script.includes(`${param} === false`)) {
372
+ return 'boolean';
373
+ }
374
+ if (script.includes(`${param}[`) || script.includes(`${param}.push`)) {
375
+ return 'array';
376
+ }
377
+ if (script.includes(`${param}.`) && !script.includes(`${param}.length`)) {
378
+ return 'object';
379
+ }
380
+ return 'string';
381
+ }
382
+ /**
383
+ * Extract parameter description from script comments
384
+ */
385
+ extractParameterDescription(param, script) {
386
+ // Look for JSDoc comments
387
+ const jsdocMatch = script.match(new RegExp(`@param\\s+\\{[^}]*\\}\\s+${param}\\s+([^\\n]*)`));
388
+ if (jsdocMatch) {
389
+ return jsdocMatch[1].trim();
390
+ }
391
+ // Look for inline comments
392
+ const inlineMatch = script.match(new RegExp(`${param}[^\\n]*//\\s*([^\\n]*)`));
393
+ if (inlineMatch) {
394
+ return inlineMatch[1].trim();
395
+ }
396
+ return `Parameter: ${param}`;
397
+ }
398
+ /**
399
+ * Generate enhanced flow with intelligent artifact linking
400
+ */
401
+ async generateEnhancedFlow(instruction) {
402
+ this.logger.info('Generating enhanced flow with intelligent artifact linking', { instruction });
403
+ // 1. Parse instruction and discover artifacts
404
+ const discoveredArtifacts = await this.discoverAndAnalyzeArtifacts(instruction);
405
+ // 2. Create enhanced activities with proper linking
406
+ const enhancedActivities = await this.createEnhancedActivities(discoveredArtifacts);
407
+ // 3. Generate intelligent connections
408
+ const connections = await this.createArtifactConnections(enhancedActivities);
409
+ // 4. Build complete flow structure
410
+ const flowStructure = {
411
+ name: `enhanced_flow_${Date.now()}`,
412
+ description: `Enhanced flow for: ${instruction}`,
413
+ activities: enhancedActivities,
414
+ connections: connections,
415
+ error_handling: this.generateErrorHandling(enhancedActivities)
416
+ };
417
+ return flowStructure;
418
+ }
419
+ /**
420
+ * Discover and analyze artifacts for instruction
421
+ */
422
+ async discoverAndAnalyzeArtifacts(instruction) {
423
+ this.logger.info(`Discovering artifacts for instruction: ${instruction}`);
424
+ try {
425
+ // First, try to find artifacts from memory/cache
426
+ const cachedArtifacts = await this.searchCachedArtifacts(instruction);
427
+ if (cachedArtifacts.length > 0) {
428
+ this.logger.info(`Found ${cachedArtifacts.length} cached artifacts`);
429
+ return cachedArtifacts;
430
+ }
431
+ // If no cached artifacts, search ServiceNow directly
432
+ const discoveredArtifacts = await this.searchServiceNowArtifacts(instruction);
433
+ // Cache the results for future use
434
+ if (discoveredArtifacts.length > 0) {
435
+ await this.cacheArtifacts(discoveredArtifacts, instruction);
436
+ }
437
+ return discoveredArtifacts;
438
+ }
439
+ catch (error) {
440
+ this.logger.error('Error discovering artifacts:', error);
441
+ // Fallback to basic artifacts if discovery fails
442
+ return await this.createBasicArtifacts(instruction);
443
+ }
444
+ }
445
+ async searchCachedArtifacts(instruction) {
446
+ try {
447
+ const searchResults = await this.indexer.searchMemory(instruction);
448
+ return searchResults.map(result => this.convertToArtifactInterface(result));
449
+ }
450
+ catch (error) {
451
+ this.logger.warn('Failed to search cached artifacts:', error);
452
+ return [];
453
+ }
454
+ }
455
+ async searchServiceNowArtifacts(instruction) {
456
+ const artifacts = [];
457
+ const searchTerms = this.extractSearchTerms(instruction);
458
+ this.logger.info(`Searching ServiceNow with terms: ${searchTerms.join(', ')}`);
459
+ // Search different artifact types based on instruction content
460
+ const searchTables = this.determineSearchTables(instruction);
461
+ for (const table of searchTables) {
462
+ for (const term of searchTerms) {
463
+ try {
464
+ const results = await this.client.searchRecords(table, `nameLIKE${term}^ORshort_descriptionLIKE${term}`, 5);
465
+ if (results.success) {
466
+ for (const result of results.data.result) {
467
+ const analyzed = await this.analyzeArtifactAPI(result);
468
+ artifacts.push(analyzed);
469
+ }
470
+ }
471
+ }
472
+ catch (error) {
473
+ this.logger.warn(`Failed to search ${table} for ${term}:`, error);
474
+ }
475
+ }
476
+ }
477
+ return artifacts;
478
+ }
479
+ determineSearchTables(instruction) {
480
+ const lowerInstruction = instruction.toLowerCase();
481
+ const tables = [];
482
+ // Determine relevant tables based on instruction content
483
+ if (lowerInstruction.includes('script') || lowerInstruction.includes('function')) {
484
+ tables.push('sys_script_include');
485
+ }
486
+ if (lowerInstruction.includes('rule') || lowerInstruction.includes('business')) {
487
+ tables.push('sys_script');
488
+ }
489
+ if (lowerInstruction.includes('table') || lowerInstruction.includes('record')) {
490
+ tables.push('sys_db_object');
491
+ }
492
+ if (lowerInstruction.includes('approval') || lowerInstruction.includes('workflow')) {
493
+ tables.push('sys_hub_flow');
494
+ tables.push('wf_workflow');
495
+ }
496
+ if (lowerInstruction.includes('catalog') || lowerInstruction.includes('item')) {
497
+ tables.push('sc_cat_item');
498
+ }
499
+ if (lowerInstruction.includes('notification') || lowerInstruction.includes('email')) {
500
+ tables.push('sysevent_email_action');
501
+ }
502
+ // Default search tables if no specific indicators found
503
+ if (tables.length === 0) {
504
+ tables.push('sys_script_include', 'sys_script', 'sys_hub_flow');
505
+ }
506
+ return tables;
507
+ }
508
+ extractSearchTerms(instruction) {
509
+ const terms = [];
510
+ const lowerInstruction = instruction.toLowerCase();
511
+ // Extract key terms from instruction
512
+ if (lowerInstruction.includes('iphone'))
513
+ terms.push('iphone');
514
+ if (lowerInstruction.includes('approval'))
515
+ terms.push('approval');
516
+ if (lowerInstruction.includes('catalog'))
517
+ terms.push('catalog');
518
+ if (lowerInstruction.includes('order'))
519
+ terms.push('order');
520
+ if (lowerInstruction.includes('fulfillment'))
521
+ terms.push('fulfillment');
522
+ if (lowerInstruction.includes('task'))
523
+ terms.push('task');
524
+ if (lowerInstruction.includes('pickup'))
525
+ terms.push('pickup');
526
+ if (lowerInstruction.includes('admin'))
527
+ terms.push('admin');
528
+ if (lowerInstruction.includes('user'))
529
+ terms.push('user');
530
+ if (lowerInstruction.includes('notification'))
531
+ terms.push('notification');
532
+ if (lowerInstruction.includes('email'))
533
+ terms.push('email');
534
+ // Extract quoted terms
535
+ const quotedTerms = instruction.match(/"([^"]+)"/g);
536
+ if (quotedTerms) {
537
+ quotedTerms.forEach(term => terms.push(term.replace(/"/g, '')));
538
+ }
539
+ // Extract capitalized terms (likely proper nouns)
540
+ const capitalizedTerms = instruction.match(/\b[A-Z][a-z]+\b/g);
541
+ if (capitalizedTerms) {
542
+ terms.push(...capitalizedTerms.map(term => term.toLowerCase()));
543
+ }
544
+ return [...new Set(terms)]; // Remove duplicates
545
+ }
546
+ async cacheArtifacts(artifacts, instruction) {
547
+ try {
548
+ // Store artifacts in memory for future use
549
+ for (const artifact of artifacts) {
550
+ // Store in memory if possible (method may be private)
551
+ // await this.indexer.storeInMemory(artifact, instruction);
552
+ }
553
+ }
554
+ catch (error) {
555
+ this.logger.warn('Failed to cache artifacts:', error);
556
+ }
557
+ }
558
+ convertToArtifactInterface(memoryResult) {
559
+ return {
560
+ sys_id: memoryResult.sys_id || 'unknown',
561
+ name: memoryResult.name || 'Unknown Artifact',
562
+ type: memoryResult.sys_class_name || 'unknown',
563
+ inputs: memoryResult.data_flow?.inputs?.map((input) => ({
564
+ name: typeof input === 'string' ? input : input.name || 'unknown',
565
+ type: typeof input === 'string' ? 'string' : input.type || 'string',
566
+ required: typeof input === 'string' ? true : input.required || false,
567
+ description: typeof input === 'string' ? input : input.description || ''
568
+ })) || [],
569
+ outputs: memoryResult.data_flow?.outputs?.map((output) => ({
570
+ name: typeof output === 'string' ? output : output.name || 'unknown',
571
+ type: typeof output === 'string' ? 'string' : output.type || 'string',
572
+ description: typeof output === 'string' ? output : output.description || ''
573
+ })) || [],
574
+ dependencies: memoryResult.dependencies || [],
575
+ api_signature: memoryResult.api_methods?.join(', ') || undefined,
576
+ compatibility_score: undefined
577
+ };
578
+ }
579
+ async createBasicArtifacts(instruction) {
580
+ // Create basic artifacts based on instruction if ServiceNow search fails
581
+ const artifacts = [];
582
+ const lowerInstruction = instruction.toLowerCase();
583
+ // For fulfillment workflows, create relevant artifacts
584
+ if (lowerInstruction.includes('fulfillment') || lowerInstruction.includes('order') ||
585
+ lowerInstruction.includes('catalog') || lowerInstruction.includes('iphone')) {
586
+ artifacts.push({
587
+ sys_id: 'catalog_handler',
588
+ name: 'CatalogFulfillmentHandler',
589
+ type: 'sys_script_include',
590
+ inputs: [
591
+ {
592
+ name: 'catalog_item',
593
+ type: 'object',
594
+ required: true,
595
+ description: 'The catalog item being fulfilled'
596
+ }
597
+ ],
598
+ outputs: [
599
+ {
600
+ name: 'fulfillment_status',
601
+ type: 'object',
602
+ description: 'Status of the fulfillment process'
603
+ }
604
+ ],
605
+ dependencies: [],
606
+ api_signature: 'processFulfillment(catalog_item)'
607
+ });
608
+ }
609
+ if (lowerInstruction.includes('approval')) {
610
+ artifacts.push({
611
+ sys_id: 'approval_script',
612
+ name: 'ApprovalHandler',
613
+ type: 'sys_script_include',
614
+ inputs: [
615
+ {
616
+ name: 'record',
617
+ type: 'object',
618
+ required: true,
619
+ description: 'Record to process for approval'
620
+ }
621
+ ],
622
+ outputs: [
623
+ {
624
+ name: 'approval_result',
625
+ type: 'object',
626
+ description: 'Result of approval processing'
627
+ }
628
+ ],
629
+ dependencies: [],
630
+ api_signature: 'processApproval(record)'
631
+ });
632
+ }
633
+ if (lowerInstruction.includes('task')) {
634
+ artifacts.push({
635
+ sys_id: 'task_creator',
636
+ name: 'TaskCreator',
637
+ type: 'sys_script_include',
638
+ inputs: [
639
+ {
640
+ name: 'type',
641
+ type: 'string',
642
+ required: true,
643
+ description: 'Type of task to create'
644
+ },
645
+ {
646
+ name: 'assignee',
647
+ type: 'string',
648
+ required: true,
649
+ description: 'User or group to assign task to'
650
+ },
651
+ {
652
+ name: 'description',
653
+ type: 'string',
654
+ required: true,
655
+ description: 'Task description'
656
+ }
657
+ ],
658
+ outputs: [
659
+ {
660
+ name: 'task_id',
661
+ type: 'string',
662
+ description: 'ID of created task'
663
+ }
664
+ ],
665
+ dependencies: [],
666
+ api_signature: 'createTask(type, assignee, description)'
667
+ });
668
+ }
669
+ if (lowerInstruction.includes('notification')) {
670
+ artifacts.push({
671
+ sys_id: 'notification_sender',
672
+ name: 'NotificationSender',
673
+ type: 'sys_script_include',
674
+ inputs: [
675
+ {
676
+ name: 'recipient',
677
+ type: 'string',
678
+ required: true,
679
+ description: 'Notification recipient'
680
+ },
681
+ {
682
+ name: 'message',
683
+ type: 'string',
684
+ required: true,
685
+ description: 'Notification message'
686
+ }
687
+ ],
688
+ outputs: [
689
+ {
690
+ name: 'notification_result',
691
+ type: 'object',
692
+ description: 'Result of notification sending'
693
+ }
694
+ ],
695
+ dependencies: [],
696
+ api_signature: 'sendNotification(recipient, message)'
697
+ });
698
+ }
699
+ return artifacts;
700
+ }
701
+ /**
702
+ * Create enhanced activities with proper artifact integration
703
+ */
704
+ async createEnhancedActivities(artifacts) {
705
+ const activities = [];
706
+ for (const artifact of artifacts) {
707
+ const activity = {
708
+ id: `activity_${activities.length + 1}`,
709
+ type: this.getActivityType(artifact),
710
+ name: this.generateActivityName(artifact),
711
+ artifact: artifact,
712
+ inputs: this.generateActivityInputs(artifact),
713
+ outputs: this.generateActivityOutputs(artifact),
714
+ connections: [], // Will be populated later
715
+ error_handling: this.generateActivityErrorHandling(artifact)
716
+ };
717
+ activities.push(activity);
718
+ }
719
+ return activities;
720
+ }
721
+ /**
722
+ * Get activity type based on artifact
723
+ */
724
+ getActivityType(artifact) {
725
+ switch (artifact.type) {
726
+ case 'sys_script_include':
727
+ return 'custom_script';
728
+ case 'sys_script':
729
+ return 'business_rule';
730
+ case 'sys_db_object':
731
+ return 'create_record';
732
+ default:
733
+ return 'custom_activity';
734
+ }
735
+ }
736
+ /**
737
+ * Generate activity name based on artifact
738
+ */
739
+ generateActivityName(artifact) {
740
+ return `Execute ${artifact.name}`;
741
+ }
742
+ /**
743
+ * Generate activity inputs based on artifact interface
744
+ */
745
+ generateActivityInputs(artifact) {
746
+ const inputs = {};
747
+ for (const input of artifact.inputs) {
748
+ inputs[input.name] = this.getDefaultInputValue(input);
749
+ }
750
+ return inputs;
751
+ }
752
+ /**
753
+ * Generate activity outputs based on artifact interface
754
+ */
755
+ generateActivityOutputs(artifact) {
756
+ const outputs = {};
757
+ for (const output of artifact.outputs) {
758
+ outputs[output.name] = `\${step.${output.name}}`;
759
+ }
760
+ return outputs;
761
+ }
762
+ /**
763
+ * Get default input value based on input type
764
+ */
765
+ getDefaultInputValue(input) {
766
+ switch (input.type) {
767
+ case 'string':
768
+ return input.required ? '${trigger.field}' : '';
769
+ case 'number':
770
+ return input.required ? '${trigger.number}' : 0;
771
+ case 'boolean':
772
+ return input.required ? '${trigger.boolean}' : false;
773
+ case 'object':
774
+ return input.required ? '${trigger.current}' : {};
775
+ case 'array':
776
+ return input.required ? '${trigger.array}' : [];
777
+ default:
778
+ return null;
779
+ }
780
+ }
781
+ /**
782
+ * Generate activity-specific error handling
783
+ */
784
+ generateActivityErrorHandling(artifact) {
785
+ const errorHandling = [];
786
+ // Common error handling for all activities
787
+ errorHandling.push({
788
+ condition: 'step.success === false',
789
+ action: 'retry',
790
+ parameters: {
791
+ max_retries: 3,
792
+ delay: 2000
793
+ }
794
+ });
795
+ // Specific error handling based on artifact type
796
+ if (artifact.type === 'sys_script_include') {
797
+ errorHandling.push({
798
+ condition: 'step.confidence < 0.7',
799
+ action: 'notify',
800
+ parameters: {
801
+ message: 'Low confidence result, manual review recommended'
802
+ }
803
+ });
804
+ }
805
+ return errorHandling;
806
+ }
807
+ /**
808
+ * Generate error handling for the entire flow
809
+ */
810
+ generateErrorHandling(activities) {
811
+ const errorHandling = [];
812
+ // Global error handling
813
+ errorHandling.push({
814
+ condition: 'any_activity_failed',
815
+ action: 'stop',
816
+ parameters: {
817
+ notification: 'admin@company.com',
818
+ message: 'Flow execution failed, please review'
819
+ }
820
+ });
821
+ return errorHandling;
822
+ }
823
+ /**
824
+ * Create a flow from natural language instruction with intelligent decision making
825
+ * This is the main method used by the MCP - ENHANCED VERSION
826
+ */
827
+ async createFlowFromInstruction(instruction) {
828
+ this.logger.info('Creating intelligent flow from instruction', { instruction });
829
+ try {
830
+ // Step 1: Analyze the instruction to determine flow vs subflow
831
+ const analysisResult = await this.decisionEngine.analyzeAndRecommend(instruction);
832
+ // Step 2: Validate the decision
833
+ const validationResult = this.validationEngine.validateDecision(analysisResult, instruction);
834
+ // Step 3: Find matching templates
835
+ const matchingTemplates = this.patternTemplates.findMatchingTemplates(instruction);
836
+ // Step 4: Create subflows if recommended
837
+ const subflowResults = [];
838
+ if (analysisResult.subflowCandidates.length > 0) {
839
+ for (const candidate of analysisResult.subflowCandidates) {
840
+ const subflowResult = await this.subflowHandler.createSubflow(candidate);
841
+ subflowResults.push(subflowResult);
842
+ }
843
+ }
844
+ // Step 5: Create the main flow structure
845
+ const flowStructure = await this.createIntelligentFlowStructure(instruction, analysisResult, matchingTemplates, subflowResults);
846
+ // Step 6: Return comprehensive result
847
+ return {
848
+ naturalLanguage: instruction,
849
+ // Decision analysis
850
+ decisionAnalysis: {
851
+ recommendedType: analysisResult.recommendedType,
852
+ confidence: analysisResult.confidence,
853
+ rationale: analysisResult.rationale,
854
+ complexity: analysisResult.criteria.complexity,
855
+ reusability: analysisResult.criteria.reusability,
856
+ context: analysisResult.criteria.context
857
+ },
858
+ // Validation results
859
+ validation: {
860
+ isValid: validationResult.isValid,
861
+ severity: validationResult.severity,
862
+ score: validationResult.score,
863
+ maxScore: validationResult.maxScore,
864
+ issues: validationResult.issues,
865
+ recommendations: validationResult.recommendations
866
+ },
867
+ // Template matching
868
+ templateMatching: {
869
+ matches: matchingTemplates.length,
870
+ bestMatch: matchingTemplates[0] || null,
871
+ confidence: matchingTemplates[0]?.confidence || 0
872
+ },
873
+ // Subflow creation results
874
+ subflowCreation: {
875
+ candidatesIdentified: analysisResult.subflowCandidates.length,
876
+ subflowsCreated: subflowResults.filter(r => r.success).length,
877
+ results: subflowResults
878
+ },
879
+ // Main flow structure
880
+ flowStructure,
881
+ // Deployment readiness
882
+ deploymentReady: validationResult.isValid && validationResult.severity !== 'critical',
883
+ // Recommendations
884
+ recommendations: this.generateComprehensiveRecommendations(analysisResult, validationResult, matchingTemplates, subflowResults)
885
+ };
886
+ }
887
+ catch (error) {
888
+ this.logger.error('Failed to create intelligent flow', error);
889
+ // Fallback to simplified flow creation
890
+ this.logger.info('Falling back to simplified flow creation');
891
+ return this.createSimplifiedFlowFromInstruction(instruction);
892
+ }
893
+ }
894
+ /**
895
+ * Create intelligent flow structure based on analysis results
896
+ */
897
+ async createIntelligentFlowStructure(instruction, analysisResult, matchingTemplates, subflowResults) {
898
+ // Use best matching template if available
899
+ const bestTemplate = matchingTemplates[0];
900
+ if (bestTemplate && bestTemplate.confidence > 0.7) {
901
+ this.logger.info('Using template for flow creation', {
902
+ templateId: bestTemplate.template.id,
903
+ confidence: bestTemplate.confidence
904
+ });
905
+ // Customize template based on instruction
906
+ const customizations = this.extractCustomizationsFromInstruction(instruction);
907
+ return this.patternTemplates.generateFlowFromTemplate(bestTemplate.template, customizations);
908
+ }
909
+ // Otherwise, create from scratch using analysis results
910
+ const parsedInstruction = this.parseInstruction(instruction);
911
+ const simpleActions = await this.generateSimpleActions(instruction, parsedInstruction.entities);
912
+ // Enhance with subflow references
913
+ const enhancedActions = this.enhanceActionsWithSubflows(simpleActions, subflowResults);
914
+ return {
915
+ name: parsedInstruction.flowName,
916
+ description: parsedInstruction.description,
917
+ table: parsedInstruction.table,
918
+ trigger: {
919
+ type: parsedInstruction.trigger.type,
920
+ table: parsedInstruction.table,
921
+ condition: parsedInstruction.trigger.condition || ''
922
+ },
923
+ activities: enhancedActions.map((action, index) => ({
924
+ id: `activity_${index + 1}`,
925
+ name: action.name,
926
+ type: action.type,
927
+ artifact_reference: action.discovered_action ? {
928
+ sys_id: action.action_type_id,
929
+ name: action.discovered_action.name || action.name
930
+ } : null,
931
+ subflow_reference: action.subflow_reference || null,
932
+ inputs: action.inputs || {},
933
+ outputs: action.outputs || {}
934
+ })),
935
+ connections: enhancedActions.map((_, index) => {
936
+ if (index === 0)
937
+ return null;
938
+ return {
939
+ from: `activity_${index}`,
940
+ to: `activity_${index + 1}`,
941
+ condition: null
942
+ };
943
+ }).filter(Boolean),
944
+ variables: [],
945
+ error_handling: analysisResult.criteria.complexity === 'high' ? [
946
+ {
947
+ condition: 'any_activity_failed',
948
+ action: 'stop',
949
+ parameters: {
950
+ message: 'Flow execution failed, please review'
951
+ }
952
+ }
953
+ ] : [],
954
+ metadata: {
955
+ intelligence_applied: true,
956
+ decision_confidence: analysisResult.confidence,
957
+ template_used: bestTemplate?.template.id || null,
958
+ subflows_created: subflowResults.filter(r => r.success).length,
959
+ complexity_level: analysisResult.criteria.complexity,
960
+ reusability_level: analysisResult.criteria.reusability
961
+ }
962
+ };
963
+ }
964
+ /**
965
+ * Fallback to simplified flow creation (original method)
966
+ */
967
+ async createSimplifiedFlowFromInstruction(instruction) {
968
+ this.logger.info('Creating simplified flow from instruction', { instruction });
969
+ // Parse the instruction to understand intent
970
+ const parsedInstruction = this.parseInstruction(instruction);
971
+ // Generate simple actions based on the instruction (now async)
972
+ const simpleActions = await this.generateSimpleActions(instruction, parsedInstruction.entities);
973
+ // Build a simplified flow structure focusing on basic actions
974
+ const flowStructure = {
975
+ name: parsedInstruction.flowName,
976
+ description: parsedInstruction.description,
977
+ table: parsedInstruction.table,
978
+ trigger_type: parsedInstruction.trigger.type,
979
+ condition: parsedInstruction.trigger.condition,
980
+ active: true,
981
+ category: 'custom',
982
+ // Simple actions instead of complex activities
983
+ actions: simpleActions
984
+ };
985
+ // Convert to the structure expected by the MCP
986
+ const flowInstructionOutput = {
987
+ naturalLanguage: instruction,
988
+ parsedIntent: parsedInstruction,
989
+ requiredArtifacts: [], // Empty array for simplified flow
990
+ flowStructure: {
991
+ name: flowStructure.name,
992
+ description: flowStructure.description,
993
+ table: flowStructure.table,
994
+ trigger: {
995
+ type: flowStructure.trigger_type,
996
+ table: flowStructure.table,
997
+ condition: flowStructure.condition || ''
998
+ },
999
+ activities: simpleActions.map((action, index) => ({
1000
+ id: `activity_${index + 1}`,
1001
+ name: action.name,
1002
+ type: action.type,
1003
+ artifact_reference: action.discovered_action ? {
1004
+ sys_id: action.action_type_id,
1005
+ name: action.discovered_action.name || action.name
1006
+ } : null,
1007
+ inputs: action.inputs || {},
1008
+ outputs: action.outputs || {}
1009
+ })),
1010
+ connections: simpleActions.map((_, index) => {
1011
+ if (index === 0)
1012
+ return null;
1013
+ return {
1014
+ from: `activity_${index}`,
1015
+ to: `activity_${index + 1}`,
1016
+ condition: null
1017
+ };
1018
+ }).filter(Boolean),
1019
+ variables: [],
1020
+ error_handling: []
1021
+ },
1022
+ deploymentReady: true
1023
+ };
1024
+ return flowInstructionOutput;
1025
+ }
1026
+ /**
1027
+ * Generate simple actions based on instruction - WITH SERVICENOW SEARCH
1028
+ */
1029
+ async generateSimpleActions(instruction, entities) {
1030
+ const actions = [];
1031
+ const lowerInstruction = instruction.toLowerCase();
1032
+ // Notification action
1033
+ if (lowerInstruction.includes('notify') || lowerInstruction.includes('email') ||
1034
+ lowerInstruction.includes('alert')) {
1035
+ const discoveredActions = await this.searchForFlowActions(['notification', 'email', 'send']);
1036
+ const action = {
1037
+ type: 'notification',
1038
+ name: 'Send Notification',
1039
+ to: entities.users?.[0] || 'assigned_to',
1040
+ subject: this.extractNotificationSubject(instruction),
1041
+ message: this.extractNotificationMessage(instruction),
1042
+ inputs: {
1043
+ to: entities.users?.[0] || 'assigned_to',
1044
+ subject: this.extractNotificationSubject(instruction),
1045
+ message: this.extractNotificationMessage(instruction)
1046
+ },
1047
+ outputs: {
1048
+ success: true,
1049
+ notification_id: '${notification.sys_id}'
1050
+ }
1051
+ };
1052
+ if (discoveredActions.length > 0) {
1053
+ action.action_type_id = discoveredActions[0].sys_id;
1054
+ action.discovered_action = discoveredActions[0];
1055
+ }
1056
+ actions.push(action);
1057
+ }
1058
+ // Field update action
1059
+ if (lowerInstruction.includes('update') || lowerInstruction.includes('set') ||
1060
+ lowerInstruction.includes('change')) {
1061
+ const fieldUpdates = this.extractFieldUpdates(instruction);
1062
+ const discoveredActions = await this.searchForFlowActions(['update', 'record', 'field']);
1063
+ // Add null check for fieldUpdates to prevent map() error
1064
+ if (fieldUpdates && fieldUpdates.length > 0) {
1065
+ for (const update of fieldUpdates) {
1066
+ const action = {
1067
+ type: 'field_update',
1068
+ name: `Update ${update.field}`,
1069
+ field: update.field,
1070
+ value: update.value,
1071
+ inputs: {
1072
+ field: update.field,
1073
+ value: update.value
1074
+ },
1075
+ outputs: {
1076
+ success: true,
1077
+ updated_field: update.field
1078
+ }
1079
+ };
1080
+ if (discoveredActions.length > 0) {
1081
+ action.action_type_id = discoveredActions[0].sys_id;
1082
+ action.discovered_action = discoveredActions[0];
1083
+ }
1084
+ actions.push(action);
1085
+ }
1086
+ }
1087
+ }
1088
+ // Create task action
1089
+ if (lowerInstruction.includes('create task') || lowerInstruction.includes('assign') ||
1090
+ lowerInstruction.includes('pickup') || lowerInstruction.includes('fulfillment')) {
1091
+ const discoveredActions = await this.searchForFlowActions(['create', 'task', 'record']);
1092
+ const action = {
1093
+ type: 'create_task',
1094
+ name: 'Create Task',
1095
+ target_table: 'task',
1096
+ fields: {
1097
+ short_description: this.extractTaskDescription(instruction),
1098
+ assigned_to: entities.users?.[0] || 'caller_id.manager'
1099
+ },
1100
+ inputs: {
1101
+ short_description: this.extractTaskDescription(instruction),
1102
+ assigned_to: entities.users?.[0] || 'caller_id.manager'
1103
+ },
1104
+ outputs: {
1105
+ task_id: '${task.sys_id}',
1106
+ task_number: '${task.number}'
1107
+ }
1108
+ };
1109
+ if (discoveredActions.length > 0) {
1110
+ action.action_type_id = discoveredActions[0].sys_id;
1111
+ action.discovered_action = discoveredActions[0];
1112
+ }
1113
+ actions.push(action);
1114
+ }
1115
+ // Approval action
1116
+ if (lowerInstruction.includes('approval') || lowerInstruction.includes('approve')) {
1117
+ const discoveredActions = await this.searchForFlowActions(['approval', 'approve']);
1118
+ const action = {
1119
+ type: 'approval',
1120
+ name: 'Request Approval',
1121
+ approvers: entities.groups?.[0] || 'assignment_group.manager',
1122
+ inputs: {
1123
+ approvers: entities.groups?.[0] || 'assignment_group.manager'
1124
+ },
1125
+ outputs: {
1126
+ approval_state: '${approval.state}',
1127
+ approval_comments: '${approval.comments}'
1128
+ }
1129
+ };
1130
+ if (discoveredActions.length > 0) {
1131
+ action.action_type_id = discoveredActions[0].sys_id;
1132
+ action.discovered_action = discoveredActions[0];
1133
+ }
1134
+ actions.push(action);
1135
+ }
1136
+ // Wait/Timer action
1137
+ if (lowerInstruction.includes('wait') || lowerInstruction.includes('delay') ||
1138
+ lowerInstruction.includes('after')) {
1139
+ const discoveredActions = await this.searchForFlowActions(['wait', 'timer', 'delay']);
1140
+ const duration = this.extractDuration(instruction);
1141
+ const action = {
1142
+ type: 'wait',
1143
+ name: 'Wait Timer',
1144
+ duration: duration,
1145
+ inputs: {
1146
+ duration: duration
1147
+ },
1148
+ outputs: {
1149
+ completed: true
1150
+ }
1151
+ };
1152
+ if (discoveredActions.length > 0) {
1153
+ action.action_type_id = discoveredActions[0].sys_id;
1154
+ action.discovered_action = discoveredActions[0];
1155
+ }
1156
+ actions.push(action);
1157
+ }
1158
+ // Log action
1159
+ if (lowerInstruction.includes('log') || lowerInstruction.includes('record')) {
1160
+ const discoveredActions = await this.searchForFlowActions(['log', 'logging']);
1161
+ const action = {
1162
+ type: 'log',
1163
+ name: 'Log Message',
1164
+ message: this.extractLogMessage(instruction),
1165
+ level: 'info',
1166
+ inputs: {
1167
+ message: this.extractLogMessage(instruction),
1168
+ level: 'info'
1169
+ },
1170
+ outputs: {
1171
+ logged: true
1172
+ }
1173
+ };
1174
+ if (discoveredActions.length > 0) {
1175
+ action.action_type_id = discoveredActions[0].sys_id;
1176
+ action.discovered_action = discoveredActions[0];
1177
+ }
1178
+ actions.push(action);
1179
+ }
1180
+ // If no specific actions found, create basic flow based on context
1181
+ if (actions.length === 0) {
1182
+ // For catalog/order flows
1183
+ if (lowerInstruction.includes('catalog') || lowerInstruction.includes('order') ||
1184
+ lowerInstruction.includes('iphone')) {
1185
+ const updateActions = await this.searchForFlowActions(['update', 'record']);
1186
+ const notifyActions = await this.searchForFlowActions(['notification', 'email']);
1187
+ const updateAction = {
1188
+ type: 'field_update',
1189
+ name: 'Set Fulfillment State',
1190
+ field: 'state',
1191
+ value: 'work_in_progress',
1192
+ inputs: {
1193
+ field: 'state',
1194
+ value: 'work_in_progress'
1195
+ },
1196
+ outputs: {
1197
+ success: true,
1198
+ updated_field: 'state'
1199
+ }
1200
+ };
1201
+ const notifyAction = {
1202
+ type: 'notification',
1203
+ name: 'Notify User',
1204
+ to: 'requested_for',
1205
+ subject: 'Order Update',
1206
+ message: 'Your order is being processed',
1207
+ inputs: {
1208
+ to: 'requested_for',
1209
+ subject: 'Order Update',
1210
+ message: 'Your order is being processed'
1211
+ },
1212
+ outputs: {
1213
+ success: true,
1214
+ notification_id: '${notification.sys_id}'
1215
+ }
1216
+ };
1217
+ if (updateActions.length > 0) {
1218
+ updateAction.action_type_id = updateActions[0].sys_id;
1219
+ updateAction.discovered_action = updateActions[0];
1220
+ }
1221
+ if (notifyActions.length > 0) {
1222
+ notifyAction.action_type_id = notifyActions[0].sys_id;
1223
+ notifyAction.discovered_action = notifyActions[0];
1224
+ }
1225
+ actions.push(updateAction, notifyAction);
1226
+ }
1227
+ else {
1228
+ // Default notification
1229
+ const notifyActions = await this.searchForFlowActions(['notification', 'email']);
1230
+ const action = {
1231
+ type: 'notification',
1232
+ name: 'Flow Executed',
1233
+ to: 'assigned_to',
1234
+ subject: 'Flow Action Completed',
1235
+ message: `Flow executed for: ${instruction}`,
1236
+ inputs: {
1237
+ to: 'assigned_to',
1238
+ subject: 'Flow Action Completed',
1239
+ message: `Flow executed for: ${instruction}`
1240
+ },
1241
+ outputs: {
1242
+ success: true,
1243
+ notification_id: '${notification.sys_id}'
1244
+ }
1245
+ };
1246
+ if (notifyActions.length > 0) {
1247
+ action.action_type_id = notifyActions[0].sys_id;
1248
+ action.discovered_action = notifyActions[0];
1249
+ }
1250
+ actions.push(action);
1251
+ }
1252
+ }
1253
+ return actions;
1254
+ }
1255
+ /**
1256
+ * Search for flow actions in ServiceNow
1257
+ */
1258
+ async searchForFlowActions(searchTerms) {
1259
+ const allActions = [];
1260
+ for (const term of searchTerms) {
1261
+ try {
1262
+ const results = await this.client.searchFlowActions(term);
1263
+ if (results.actionTypes && results.actionTypes.length > 0) {
1264
+ allActions.push(...results.actionTypes);
1265
+ }
1266
+ }
1267
+ catch (error) {
1268
+ this.logger.warn(`Failed to search for flow actions with term: ${term}`, error);
1269
+ }
1270
+ }
1271
+ // Remove duplicates based on sys_id
1272
+ const uniqueActions = allActions.filter((action, index, self) => index === self.findIndex(a => a.sys_id === action.sys_id));
1273
+ this.logger.info(`Found ${uniqueActions.length} unique flow actions for terms: ${searchTerms.join(', ')}`);
1274
+ return uniqueActions;
1275
+ }
1276
+ /**
1277
+ * Helper methods for extracting specific information - NEW METHODS
1278
+ */
1279
+ extractNotificationSubject(instruction) {
1280
+ const subjectMatch = instruction.match(/subject[:\s]+["']([^"']+)["']/i);
1281
+ if (subjectMatch)
1282
+ return subjectMatch[1];
1283
+ const keywords = ['notify', 'alert', 'email'];
1284
+ for (const keyword of keywords) {
1285
+ if (instruction.toLowerCase().includes(keyword)) {
1286
+ return `Notification: ${instruction.substring(0, 50)}`;
1287
+ }
1288
+ }
1289
+ return 'Flow Notification';
1290
+ }
1291
+ extractNotificationMessage(instruction) {
1292
+ const messageMatch = instruction.match(/message[:\s]+["']([^"']+)["']/i);
1293
+ if (messageMatch)
1294
+ return messageMatch[1];
1295
+ return instruction;
1296
+ }
1297
+ extractFieldUpdates(instruction) {
1298
+ const updates = [];
1299
+ // Pattern: "set field to value" or "update field with value"
1300
+ const patterns = [
1301
+ /(?:set|update)\s+(\w+)\s+(?:to|with)\s+["']?([^"']+)["']?/gi,
1302
+ /(\w+)\s*=\s*["']?([^"']+)["']?/gi
1303
+ ];
1304
+ for (const pattern of patterns) {
1305
+ let match;
1306
+ while ((match = pattern.exec(instruction)) !== null) {
1307
+ updates.push({
1308
+ field: match[1],
1309
+ value: match[2]
1310
+ });
1311
+ }
1312
+ }
1313
+ // Common field mappings
1314
+ const fieldMap = {
1315
+ 'status': 'state',
1316
+ 'priority': 'priority',
1317
+ 'assignment': 'assigned_to',
1318
+ 'description': 'short_description'
1319
+ };
1320
+ // Map common field names - add null check to prevent map() error
1321
+ if (!updates || updates.length === 0) {
1322
+ return [];
1323
+ }
1324
+ return updates.map(update => ({
1325
+ field: fieldMap[update.field.toLowerCase()] || update.field,
1326
+ value: update.value
1327
+ }));
1328
+ }
1329
+ extractTaskDescription(instruction) {
1330
+ const taskMatch = instruction.match(/task[:\s]+["']([^"']+)["']/i);
1331
+ if (taskMatch)
1332
+ return taskMatch[1];
1333
+ // For specific contexts
1334
+ const lowerInstruction = instruction.toLowerCase();
1335
+ if (lowerInstruction.includes('pickup')) {
1336
+ return 'User pickup required';
1337
+ }
1338
+ if (lowerInstruction.includes('fulfillment')) {
1339
+ return 'Fulfillment task';
1340
+ }
1341
+ return `Task: ${instruction.substring(0, 80)}`;
1342
+ }
1343
+ extractDuration(instruction) {
1344
+ const durationMatch = instruction.match(/(\d+)\s*(second|minute|hour|day)/i);
1345
+ if (durationMatch) {
1346
+ const value = parseInt(durationMatch[1]);
1347
+ const unit = durationMatch[2].toLowerCase();
1348
+ switch (unit) {
1349
+ case 'second': return value;
1350
+ case 'minute': return value * 60;
1351
+ case 'hour': return value * 3600;
1352
+ case 'day': return value * 86400;
1353
+ default: return 300; // 5 minutes default
1354
+ }
1355
+ }
1356
+ return 300; // 5 minutes default
1357
+ }
1358
+ extractLogMessage(instruction) {
1359
+ const logMatch = instruction.match(/log[:\s]+["']([^"']+)["']/i);
1360
+ if (logMatch)
1361
+ return logMatch[1];
1362
+ return `Flow action: ${instruction}`;
1363
+ }
1364
+ /**
1365
+ * Parse natural language instruction
1366
+ */
1367
+ parseInstruction(instruction) {
1368
+ const lowerInstruction = instruction.toLowerCase();
1369
+ this.logger.info('Parsing instruction:', { instruction, lowerInstruction });
1370
+ // Enhanced flow name extraction
1371
+ const flowName = this.extractFlowName(instruction);
1372
+ // Enhanced table extraction with ServiceNow context
1373
+ const table = this.extractTable(instruction);
1374
+ // Enhanced trigger extraction
1375
+ const trigger = this.extractTrigger(instruction, table);
1376
+ // Extract workflow requirements
1377
+ const requirements = this.extractRequirements(instruction);
1378
+ // Extract entities and context
1379
+ const entities = this.extractEntities(instruction);
1380
+ const parsed = {
1381
+ flowName,
1382
+ description: instruction,
1383
+ table,
1384
+ trigger,
1385
+ intents: this.extractIntents(instruction),
1386
+ dataFlow: this.extractDataFlow(instruction),
1387
+ requirements,
1388
+ entities,
1389
+ flowType: this.determineFlowType(instruction),
1390
+ complexity: this.assessComplexity(instruction)
1391
+ };
1392
+ this.logger.info('Parsed instruction:', parsed);
1393
+ return parsed;
1394
+ }
1395
+ extractFlowName(instruction) {
1396
+ // First check for quoted flow names - more precise matching
1397
+ const quotedPatterns = [
1398
+ /flow\s+named\s+["']([^"']+)["']/i,
1399
+ /flow\s+called\s+["']([^"']+)["']/i,
1400
+ /["']([^"']+)["']\s+flow/i,
1401
+ /create\s+a\s+flow\s+named\s+["']([^"']+)["']/i
1402
+ ];
1403
+ for (const pattern of quotedPatterns) {
1404
+ const match = instruction.match(pattern);
1405
+ if (match && match[1]) {
1406
+ return match[1].trim();
1407
+ }
1408
+ }
1409
+ // Check for any remaining quoted strings as fallback
1410
+ const generalQuotedMatch = instruction.match(/["']([^"']+)["']/i);
1411
+ if (generalQuotedMatch && generalQuotedMatch[1] && generalQuotedMatch[1].toLowerCase().includes('flow')) {
1412
+ return generalQuotedMatch[1].trim();
1413
+ }
1414
+ // Then check for 'flow named X' or 'flow called X' without quotes
1415
+ const namedMatch = instruction.match(/flow\s+(?:named|called)\s+([^\s]+(?:\s+[^\s]+)*?)(?:\s+that|\s+which|\s+to|\.|,|$)/i);
1416
+ if (namedMatch && namedMatch[1]) {
1417
+ return namedMatch[1].trim();
1418
+ }
1419
+ // Try other patterns
1420
+ const patterns = [
1421
+ /(?:create|build|make)\s+(?:a\s+)?(.+?)\s+flow/i,
1422
+ /flow\s+(?:for|to)\s+(.+?)(?:\s+when|\s+if|\.|,|$)/i,
1423
+ /(.+?)\s+(?:workflow|process)(?:\s|$)/i
1424
+ ];
1425
+ for (const pattern of patterns) {
1426
+ const match = instruction.match(pattern);
1427
+ if (match && match[1]) {
1428
+ return match[1].trim();
1429
+ }
1430
+ }
1431
+ // If no specific pattern found, use first part of instruction
1432
+ const words = instruction.split(/\s+/);
1433
+ if (words.length > 2) {
1434
+ return words.slice(0, 3).join(' ');
1435
+ }
1436
+ return 'Custom Flow';
1437
+ }
1438
+ extractTable(instruction) {
1439
+ const lowerInstruction = instruction.toLowerCase();
1440
+ // ServiceNow table mapping
1441
+ const tableMap = {
1442
+ 'incident': 'incident',
1443
+ 'request': 'sc_request',
1444
+ 'service request': 'sc_request',
1445
+ 'catalog': 'sc_req_item',
1446
+ 'catalog item': 'sc_req_item',
1447
+ 'problem': 'problem',
1448
+ 'change': 'change_request',
1449
+ 'change request': 'change_request',
1450
+ 'task': 'task',
1451
+ 'user': 'sys_user',
1452
+ 'cmdb': 'cmdb_ci',
1453
+ 'configuration item': 'cmdb_ci'
1454
+ };
1455
+ // Check for explicit table mentions
1456
+ for (const [key, value] of Object.entries(tableMap)) {
1457
+ if (lowerInstruction.includes(key)) {
1458
+ return value;
1459
+ }
1460
+ }
1461
+ // Check for catalog/fulfillment context
1462
+ if (lowerInstruction.includes('order') || lowerInstruction.includes('fulfillment') ||
1463
+ lowerInstruction.includes('catalog') || lowerInstruction.includes('iphone')) {
1464
+ return 'sc_req_item';
1465
+ }
1466
+ // Check for approval context
1467
+ if (lowerInstruction.includes('approval') || lowerInstruction.includes('approve')) {
1468
+ return 'sc_request';
1469
+ }
1470
+ // Default fallback based on flow type
1471
+ if (lowerInstruction.includes('flow') || lowerInstruction.includes('process')) {
1472
+ return 'task'; // Generic task table for workflows
1473
+ }
1474
+ return 'task'; // Changed from 'incident' to more neutral 'task'
1475
+ }
1476
+ extractTrigger(instruction, table) {
1477
+ const lowerInstruction = instruction.toLowerCase();
1478
+ let triggerType = 'record_created';
1479
+ let condition = '';
1480
+ // Determine trigger type
1481
+ if (lowerInstruction.includes('update') || lowerInstruction.includes('change')) {
1482
+ triggerType = 'record_updated';
1483
+ }
1484
+ else if (lowerInstruction.includes('delete')) {
1485
+ triggerType = 'record_deleted';
1486
+ }
1487
+ else if (lowerInstruction.includes('schedule')) {
1488
+ triggerType = 'scheduled';
1489
+ }
1490
+ // Extract specific conditions
1491
+ if (lowerInstruction.includes('iphone 6')) {
1492
+ condition = 'cat_item.name=iPhone 6';
1493
+ }
1494
+ else if (lowerInstruction.includes('high priority')) {
1495
+ condition = 'priority=1';
1496
+ }
1497
+ else if (lowerInstruction.includes('critical')) {
1498
+ condition = 'priority=1^severity=1';
1499
+ }
1500
+ return {
1501
+ type: triggerType,
1502
+ table,
1503
+ condition
1504
+ };
1505
+ }
1506
+ extractRequirements(instruction) {
1507
+ const requirements = [];
1508
+ const lowerInstruction = instruction.toLowerCase();
1509
+ // Extract sequential requirements
1510
+ if (lowerInstruction.includes('approval')) {
1511
+ requirements.push('approval_required');
1512
+ }
1513
+ if (lowerInstruction.includes('task')) {
1514
+ requirements.push('task_creation');
1515
+ }
1516
+ if (lowerInstruction.includes('notification')) {
1517
+ requirements.push('notification_required');
1518
+ }
1519
+ if (lowerInstruction.includes('admin')) {
1520
+ requirements.push('admin_assignment');
1521
+ }
1522
+ if (lowerInstruction.includes('pickup')) {
1523
+ requirements.push('pickup_scheduling');
1524
+ }
1525
+ if (lowerInstruction.includes('complete')) {
1526
+ requirements.push('completion_tracking');
1527
+ }
1528
+ return requirements;
1529
+ }
1530
+ extractEntities(instruction) {
1531
+ const entities = {};
1532
+ const lowerInstruction = instruction.toLowerCase();
1533
+ // Extract product entities
1534
+ if (lowerInstruction.includes('iphone')) {
1535
+ entities.product = 'iPhone';
1536
+ if (lowerInstruction.includes('iphone 6')) {
1537
+ entities.product_model = 'iPhone 6';
1538
+ }
1539
+ }
1540
+ // Extract role entities
1541
+ if (lowerInstruction.includes('admin')) {
1542
+ entities.admin_role = true;
1543
+ }
1544
+ if (lowerInstruction.includes('user')) {
1545
+ entities.user_role = true;
1546
+ }
1547
+ // Extract action entities
1548
+ if (lowerInstruction.includes('pickup')) {
1549
+ entities.pickup_action = true;
1550
+ }
1551
+ if (lowerInstruction.includes('fulfillment')) {
1552
+ entities.fulfillment_process = true;
1553
+ }
1554
+ return entities;
1555
+ }
1556
+ determineFlowType(instruction) {
1557
+ const lowerInstruction = instruction.toLowerCase();
1558
+ if (lowerInstruction.includes('approval')) {
1559
+ return 'approval_workflow';
1560
+ }
1561
+ if (lowerInstruction.includes('fulfillment') || lowerInstruction.includes('order')) {
1562
+ return 'fulfillment_workflow';
1563
+ }
1564
+ if (lowerInstruction.includes('incident')) {
1565
+ return 'incident_workflow';
1566
+ }
1567
+ if (lowerInstruction.includes('notification')) {
1568
+ return 'notification_workflow';
1569
+ }
1570
+ return 'general_workflow';
1571
+ }
1572
+ assessComplexity(instruction) {
1573
+ const lowerInstruction = instruction.toLowerCase();
1574
+ let complexity = 0;
1575
+ // Count complexity indicators
1576
+ if (lowerInstruction.includes('approval'))
1577
+ complexity += 2;
1578
+ if (lowerInstruction.includes('task'))
1579
+ complexity += 1;
1580
+ if (lowerInstruction.includes('notification'))
1581
+ complexity += 1;
1582
+ if (lowerInstruction.includes('admin'))
1583
+ complexity += 1;
1584
+ if (lowerInstruction.includes('user'))
1585
+ complexity += 1;
1586
+ if (lowerInstruction.includes('pickup'))
1587
+ complexity += 2;
1588
+ if (lowerInstruction.includes('schedule'))
1589
+ complexity += 2;
1590
+ if (complexity >= 5)
1591
+ return 'high';
1592
+ if (complexity >= 3)
1593
+ return 'medium';
1594
+ return 'low';
1595
+ }
1596
+ /**
1597
+ * Create activities based on parsed requirements
1598
+ */
1599
+ async createActivitiesFromRequirements(parsedInstruction) {
1600
+ const activities = [];
1601
+ const requirements = parsedInstruction.requirements;
1602
+ const entities = parsedInstruction.entities;
1603
+ const flowType = parsedInstruction.flowType;
1604
+ this.logger.info('Creating activities from requirements:', { requirements, entities, flowType });
1605
+ // Create activities based on flow type and requirements
1606
+ if (flowType === 'fulfillment_workflow') {
1607
+ activities.push(...this.createFulfillmentActivities(requirements, entities));
1608
+ }
1609
+ else if (flowType === 'approval_workflow') {
1610
+ activities.push(...this.createApprovalActivities(requirements, entities));
1611
+ }
1612
+ else if (flowType === 'incident_workflow') {
1613
+ activities.push(...this.createIncidentActivities(requirements, entities));
1614
+ }
1615
+ else {
1616
+ activities.push(...this.createGeneralActivities(requirements, entities));
1617
+ }
1618
+ return activities;
1619
+ }
1620
+ createFulfillmentActivities(requirements, entities) {
1621
+ const activities = [];
1622
+ let activityIndex = 1;
1623
+ // Always start with validation for fulfillment
1624
+ activities.push({
1625
+ id: `activity_${activityIndex++}`,
1626
+ type: 'condition',
1627
+ name: 'Validate Request',
1628
+ condition: entities.product_model ? `cat_item.name=${entities.product_model}` : 'state=1',
1629
+ inputs: {
1630
+ record: '${trigger.record}',
1631
+ validation_rules: ['product_available', 'user_authorized']
1632
+ },
1633
+ outputs: {
1634
+ validation_result: '${step.validation_result}',
1635
+ next_step: '${step.next_step}'
1636
+ }
1637
+ });
1638
+ // Add approval if required
1639
+ if (requirements.includes('approval_required')) {
1640
+ activities.push({
1641
+ id: `activity_${activityIndex++}`,
1642
+ type: 'approval',
1643
+ name: 'Manager Approval',
1644
+ approval_type: 'manager',
1645
+ inputs: {
1646
+ record: '${trigger.record}',
1647
+ approval_group: 'managers',
1648
+ timeout: '48 hours'
1649
+ },
1650
+ outputs: {
1651
+ approval_result: '${step.approval_result}',
1652
+ approved_by: '${step.approved_by}'
1653
+ }
1654
+ });
1655
+ }
1656
+ // Add task creation for admin
1657
+ if (requirements.includes('admin_assignment')) {
1658
+ activities.push({
1659
+ id: `activity_${activityIndex++}`,
1660
+ type: 'create_task',
1661
+ name: 'Create Admin Task',
1662
+ task_type: 'admin_pickup',
1663
+ inputs: {
1664
+ parent_record: '${trigger.record}',
1665
+ assigned_to: 'admin_group',
1666
+ short_description: entities.product_model ? `Prepare ${entities.product_model} for pickup` : 'Prepare item for pickup',
1667
+ priority: '2'
1668
+ },
1669
+ outputs: {
1670
+ task_id: '${step.task_id}',
1671
+ task_state: '${step.task_state}'
1672
+ }
1673
+ });
1674
+ }
1675
+ // Add task creation for user
1676
+ if (requirements.includes('pickup_scheduling')) {
1677
+ activities.push({
1678
+ id: `activity_${activityIndex++}`,
1679
+ type: 'create_task',
1680
+ name: 'Create User Pickup Task',
1681
+ task_type: 'user_pickup',
1682
+ inputs: {
1683
+ parent_record: '${trigger.record}',
1684
+ assigned_to: '${trigger.record.requested_for}',
1685
+ short_description: entities.product_model ? `Pick up your ${entities.product_model}` : 'Pick up your item',
1686
+ priority: '3'
1687
+ },
1688
+ outputs: {
1689
+ pickup_task_id: '${step.pickup_task_id}',
1690
+ pickup_scheduled: '${step.pickup_scheduled}'
1691
+ }
1692
+ });
1693
+ }
1694
+ // Add notifications
1695
+ if (requirements.includes('notification_required')) {
1696
+ activities.push({
1697
+ id: `activity_${activityIndex++}`,
1698
+ type: 'notification',
1699
+ name: 'Send Notification',
1700
+ notification_type: 'email',
1701
+ inputs: {
1702
+ recipient: '${trigger.record.requested_for}',
1703
+ subject: entities.product_model ? `Your ${entities.product_model} is ready for pickup` : 'Your item is ready for pickup',
1704
+ message: 'Please visit the admin desk to collect your item.'
1705
+ },
1706
+ outputs: {
1707
+ notification_sent: '${step.notification_sent}'
1708
+ }
1709
+ });
1710
+ }
1711
+ // Add completion tracking
1712
+ if (requirements.includes('completion_tracking')) {
1713
+ activities.push({
1714
+ id: `activity_${activityIndex++}`,
1715
+ type: 'update_record',
1716
+ name: 'Update Request Status',
1717
+ inputs: {
1718
+ record: '${trigger.record}',
1719
+ updates: {
1720
+ state: '3',
1721
+ completion_date: '${gs.now()}'
1722
+ }
1723
+ },
1724
+ outputs: {
1725
+ updated_record: '${step.updated_record}'
1726
+ }
1727
+ });
1728
+ }
1729
+ return activities;
1730
+ }
1731
+ createApprovalActivities(requirements, entities) {
1732
+ const activities = [];
1733
+ let activityIndex = 1;
1734
+ // Create approval activity
1735
+ activities.push({
1736
+ id: `activity_${activityIndex++}`,
1737
+ type: 'approval',
1738
+ name: 'Request Approval',
1739
+ approval_type: 'sequential',
1740
+ inputs: {
1741
+ record: '${trigger.record}',
1742
+ approval_group: 'approvers',
1743
+ timeout: '24 hours'
1744
+ },
1745
+ outputs: {
1746
+ approval_result: '${step.approval_result}',
1747
+ approved_by: '${step.approved_by}'
1748
+ }
1749
+ });
1750
+ // Add conditional logic for approval result
1751
+ activities.push({
1752
+ id: `activity_${activityIndex++}`,
1753
+ type: 'condition',
1754
+ name: 'Check Approval Result',
1755
+ condition: 'approval_result=approved',
1756
+ inputs: {
1757
+ approval_result: '${activity_1.approval_result}'
1758
+ },
1759
+ outputs: {
1760
+ proceed: '${step.proceed}'
1761
+ }
1762
+ });
1763
+ return activities;
1764
+ }
1765
+ createIncidentActivities(requirements, entities) {
1766
+ const activities = [];
1767
+ let activityIndex = 1;
1768
+ // Create incident assignment
1769
+ activities.push({
1770
+ id: `activity_${activityIndex++}`,
1771
+ type: 'assignment',
1772
+ name: 'Assign Incident',
1773
+ inputs: {
1774
+ record: '${trigger.record}',
1775
+ assignment_group: 'it_support',
1776
+ priority: '${trigger.record.priority}'
1777
+ },
1778
+ outputs: {
1779
+ assigned_to: '${step.assigned_to}',
1780
+ assignment_group: '${step.assignment_group}'
1781
+ }
1782
+ });
1783
+ return activities;
1784
+ }
1785
+ createGeneralActivities(requirements, entities) {
1786
+ const activities = [];
1787
+ let activityIndex = 1;
1788
+ // Create basic processing activity
1789
+ activities.push({
1790
+ id: `activity_${activityIndex++}`,
1791
+ type: 'script',
1792
+ name: 'Process Request',
1793
+ inputs: {
1794
+ record: '${trigger.record}'
1795
+ },
1796
+ outputs: {
1797
+ result: '${step.result}'
1798
+ }
1799
+ });
1800
+ return activities;
1801
+ }
1802
+ createWorkflowConnections(activities) {
1803
+ const connections = [];
1804
+ // Create sequential connections between activities
1805
+ for (let i = 0; i < activities.length - 1; i++) {
1806
+ connections.push({
1807
+ from: activities[i].id,
1808
+ to: activities[i + 1].id
1809
+ });
1810
+ }
1811
+ // Add conditional connections if needed
1812
+ for (const activity of activities) {
1813
+ if (activity.type === 'condition') {
1814
+ // Add conditional branches (simplified)
1815
+ connections.push({
1816
+ from: activity.id,
1817
+ to: 'end',
1818
+ condition: 'false'
1819
+ });
1820
+ }
1821
+ }
1822
+ return connections;
1823
+ }
1824
+ /**
1825
+ * Extract intents from instruction
1826
+ */
1827
+ extractIntents(instruction) {
1828
+ const intents = [];
1829
+ const lowerInstruction = instruction.toLowerCase();
1830
+ // ServiceNow-specific intents
1831
+ if (lowerInstruction.includes('approve') || lowerInstruction.includes('approval')) {
1832
+ intents.push('approval');
1833
+ }
1834
+ if (lowerInstruction.includes('task') || lowerInstruction.includes('assign')) {
1835
+ intents.push('task_creation');
1836
+ }
1837
+ if (lowerInstruction.includes('notify') || lowerInstruction.includes('notification')) {
1838
+ intents.push('notification');
1839
+ }
1840
+ if (lowerInstruction.includes('pickup') || lowerInstruction.includes('schedule')) {
1841
+ intents.push('scheduling');
1842
+ }
1843
+ if (lowerInstruction.includes('fulfillment') || lowerInstruction.includes('order')) {
1844
+ intents.push('fulfillment');
1845
+ }
1846
+ if (lowerInstruction.includes('catalog') || lowerInstruction.includes('item')) {
1847
+ intents.push('catalog_management');
1848
+ }
1849
+ if (lowerInstruction.includes('admin') || lowerInstruction.includes('administrator')) {
1850
+ intents.push('admin_process');
1851
+ }
1852
+ if (lowerInstruction.includes('user') || lowerInstruction.includes('customer')) {
1853
+ intents.push('user_process');
1854
+ }
1855
+ if (lowerInstruction.includes('complete') || lowerInstruction.includes('finish')) {
1856
+ intents.push('completion');
1857
+ }
1858
+ if (lowerInstruction.includes('escalate') || lowerInstruction.includes('escalation')) {
1859
+ intents.push('escalation');
1860
+ }
1861
+ if (lowerInstruction.includes('validate') || lowerInstruction.includes('validation')) {
1862
+ intents.push('validation');
1863
+ }
1864
+ // Legacy intents (remove these problematic ones)
1865
+ // if (lowerInstruction.includes('translate')) intents.push('translation');
1866
+ return intents;
1867
+ }
1868
+ /**
1869
+ * Extract data flow from instruction
1870
+ */
1871
+ extractDataFlow(instruction) {
1872
+ const flow = [];
1873
+ const lowerInstruction = instruction.toLowerCase();
1874
+ // Extract logical flow based on content
1875
+ if (lowerInstruction.includes('trigger') || lowerInstruction.includes('when')) {
1876
+ flow.push('Trigger Event');
1877
+ }
1878
+ if (lowerInstruction.includes('approval')) {
1879
+ flow.push('Approval Process');
1880
+ }
1881
+ if (lowerInstruction.includes('task') || lowerInstruction.includes('admin')) {
1882
+ flow.push('Task Creation');
1883
+ }
1884
+ if (lowerInstruction.includes('pickup')) {
1885
+ flow.push('Pickup Scheduling');
1886
+ }
1887
+ if (lowerInstruction.includes('notification')) {
1888
+ flow.push('Send Notification');
1889
+ }
1890
+ if (lowerInstruction.includes('complete')) {
1891
+ flow.push('Complete Process');
1892
+ }
1893
+ // If no specific flow detected, use generic
1894
+ if (flow.length === 0) {
1895
+ flow.push('Process Initiated');
1896
+ flow.push('Execute Actions');
1897
+ flow.push('Process Complete');
1898
+ }
1899
+ return flow;
1900
+ }
1901
+ /**
1902
+ * Extract flow variables from activities
1903
+ */
1904
+ extractFlowVariables(activities) {
1905
+ const variables = [];
1906
+ const seen = new Set();
1907
+ // Add common flow variables
1908
+ variables.push({
1909
+ name: 'current_record',
1910
+ type: 'reference',
1911
+ description: 'The current record being processed'
1912
+ });
1913
+ // Extract variables from activity outputs
1914
+ activities.forEach(activity => {
1915
+ // Check if activity has artifact with outputs
1916
+ if (activity.artifact && activity.artifact.outputs) {
1917
+ activity.artifact.outputs.forEach((output) => {
1918
+ const varName = `${activity.id}_${output.name}`;
1919
+ if (!seen.has(varName)) {
1920
+ seen.add(varName);
1921
+ variables.push({
1922
+ name: varName,
1923
+ type: output.type,
1924
+ description: `Output from ${activity.name}: ${output.description}`
1925
+ });
1926
+ }
1927
+ });
1928
+ }
1929
+ else if (activity.outputs) {
1930
+ // Handle activities without artifacts but with outputs
1931
+ Object.entries(activity.outputs).forEach(([key, value]) => {
1932
+ const varName = key.replace('${step.', '').replace('}', '');
1933
+ if (!seen.has(varName)) {
1934
+ seen.add(varName);
1935
+ variables.push({
1936
+ name: varName,
1937
+ type: 'string',
1938
+ description: `Output from ${activity.name}`
1939
+ });
1940
+ }
1941
+ });
1942
+ }
1943
+ });
1944
+ return variables;
1945
+ }
1946
+ /**
1947
+ * Deploy a flow to ServiceNow - ENHANCED WITH GLOBAL SCOPE STRATEGY
1948
+ */
1949
+ async deployFlow(flowData) {
1950
+ this.logger.info('Deploying flow with global scope strategy', { name: flowData.flowStructure.name });
1951
+ try {
1952
+ // Use the simplified flow structure directly
1953
+ const flowDefinition = flowData.flowStructure;
1954
+ // Create deployment context for scope management
1955
+ const deploymentContext = {
1956
+ artifactType: 'flow',
1957
+ artifactData: {
1958
+ name: flowDefinition.name,
1959
+ description: flowDefinition.description,
1960
+ table: flowDefinition.table,
1961
+ trigger_type: flowDefinition.trigger?.type || flowDefinition.trigger_type,
1962
+ condition: flowDefinition.trigger?.condition || flowDefinition.condition || '',
1963
+ active: flowDefinition.active !== false,
1964
+ category: flowDefinition.category || 'custom',
1965
+ activities: flowDefinition.activities || [],
1966
+ // Additional metadata for scope decision
1967
+ complexity: this.assessFlowComplexity(flowDefinition),
1968
+ crossApplicationIntegration: this.hasCrossApplicationIntegration(flowDefinition),
1969
+ sharedUtility: this.isSharedUtility(flowDefinition)
1970
+ },
1971
+ environmentType: process.env.NODE_ENV === 'production' ? 'production' : 'development'
1972
+ };
1973
+ // Use scope manager to deploy with optimal scope
1974
+ const deploymentResult = await this.scopeManager.deployWithScopeManagement(deploymentContext);
1975
+ if (!deploymentResult.success) {
1976
+ throw new Error(deploymentResult.message || 'Failed to deploy flow');
1977
+ }
1978
+ // Log deployment details with scope information
1979
+ this.logger.info('Flow deployed successfully with scope management', {
1980
+ sys_id: deploymentResult.artifactId,
1981
+ name: flowDefinition.name,
1982
+ table: flowDefinition.table,
1983
+ scope: deploymentResult.scope,
1984
+ domain: deploymentResult.domain,
1985
+ fallbackApplied: deploymentResult.fallbackApplied
1986
+ });
1987
+ return {
1988
+ success: true,
1989
+ message: `Flow "${flowDefinition.name}" deployed successfully to ${deploymentResult.scope} scope`,
1990
+ data: {
1991
+ sys_id: deploymentResult.artifactId,
1992
+ name: flowDefinition.name,
1993
+ table: flowDefinition.table,
1994
+ scope: deploymentResult.scope,
1995
+ domain: deploymentResult.domain,
1996
+ url: `https://${process.env.SNOW_INSTANCE}/$flow-designer.do#/flow/${deploymentResult.artifactId}`,
1997
+ actions_created: flowDefinition.activities?.length || 0,
1998
+ scope_strategy: {
1999
+ selectedScope: deploymentResult.scope,
2000
+ fallbackApplied: deploymentResult.fallbackApplied,
2001
+ permissions: deploymentResult.permissions,
2002
+ warnings: deploymentResult.warnings
2003
+ }
2004
+ }
2005
+ };
2006
+ }
2007
+ catch (error) {
2008
+ this.logger.error('Failed to deploy flow with scope management', error);
2009
+ return {
2010
+ success: false,
2011
+ error: error instanceof Error ? error.message : String(error)
2012
+ };
2013
+ }
2014
+ }
2015
+ /**
2016
+ * Assess flow complexity for scope decision
2017
+ */
2018
+ assessFlowComplexity(flowDefinition) {
2019
+ const activityCount = flowDefinition.activities?.length || 0;
2020
+ const hasComplexLogic = flowDefinition.activities?.some((activity) => activity.type === 'script' || activity.type === 'condition' || activity.type === 'loop');
2021
+ const hasIntegrations = flowDefinition.activities?.some((activity) => activity.type === 'rest' || activity.type === 'soap' || activity.type === 'integration');
2022
+ if (activityCount > 10 || hasComplexLogic || hasIntegrations) {
2023
+ return 'high';
2024
+ }
2025
+ else if (activityCount > 5) {
2026
+ return 'medium';
2027
+ }
2028
+ else {
2029
+ return 'low';
2030
+ }
2031
+ }
2032
+ /**
2033
+ * Check if flow has cross-application integration
2034
+ */
2035
+ hasCrossApplicationIntegration(flowDefinition) {
2036
+ // Check for indicators of cross-application integration
2037
+ const integrationIndicators = [
2038
+ 'integration',
2039
+ 'api',
2040
+ 'rest',
2041
+ 'soap',
2042
+ 'external',
2043
+ 'cross',
2044
+ 'global',
2045
+ 'system'
2046
+ ];
2047
+ const flowText = `${flowDefinition.name} ${flowDefinition.description || ''}`.toLowerCase();
2048
+ return integrationIndicators.some(indicator => flowText.includes(indicator));
2049
+ }
2050
+ /**
2051
+ * Check if flow is a shared utility
2052
+ */
2053
+ isSharedUtility(flowDefinition) {
2054
+ // Check for indicators of shared utility
2055
+ const utilityIndicators = [
2056
+ 'util',
2057
+ 'helper',
2058
+ 'common',
2059
+ 'shared',
2060
+ 'library',
2061
+ 'global',
2062
+ 'system'
2063
+ ];
2064
+ const flowText = `${flowDefinition.name} ${flowDefinition.description || ''}`.toLowerCase();
2065
+ return utilityIndicators.some(indicator => flowText.includes(indicator));
2066
+ }
2067
+ /**
2068
+ * Extract customizations from instruction for template application
2069
+ */
2070
+ extractCustomizationsFromInstruction(instruction) {
2071
+ const customizations = {};
2072
+ const lowerInstruction = instruction.toLowerCase();
2073
+ // Extract specific items or entities
2074
+ if (lowerInstruction.includes('iphone')) {
2075
+ customizations.constants = {
2076
+ catalog_item: 'iPhone 6',
2077
+ item_type: 'hardware'
2078
+ };
2079
+ }
2080
+ // Extract specific users or roles
2081
+ if (lowerInstruction.includes('admin')) {
2082
+ customizations.assignments = {
2083
+ admin_group: 'catalog_admins'
2084
+ };
2085
+ }
2086
+ // Extract specific conditions
2087
+ const conditionMatch = lowerInstruction.match(/when\s+(.+?)(?:\s+then|\s+,|$)/);
2088
+ if (conditionMatch) {
2089
+ customizations.condition = conditionMatch[1];
2090
+ }
2091
+ // Extract specific table
2092
+ const tableMatch = lowerInstruction.match(/(?:on|from|for)\s+(\w+)\s+(?:table|record)/);
2093
+ if (tableMatch) {
2094
+ customizations.table = tableMatch[1];
2095
+ }
2096
+ return customizations;
2097
+ }
2098
+ /**
2099
+ * Enhance actions with subflow references
2100
+ */
2101
+ enhanceActionsWithSubflows(actions, subflowResults) {
2102
+ const enhancedActions = [...actions];
2103
+ // Map successful subflows to actions
2104
+ const successfulSubflows = subflowResults.filter(r => r.success);
2105
+ for (const subflowResult of successfulSubflows) {
2106
+ if (subflowResult.subflow) {
2107
+ const subflowName = subflowResult.subflow.name.toLowerCase();
2108
+ // Find matching actions that could use this subflow
2109
+ const matchingActionIndex = enhancedActions.findIndex(action => {
2110
+ const actionName = action.name.toLowerCase();
2111
+ return actionName.includes(subflowName) ||
2112
+ subflowName.includes(actionName) ||
2113
+ this.actionsAreRelated(action, subflowResult.subflow);
2114
+ });
2115
+ if (matchingActionIndex !== -1) {
2116
+ enhancedActions[matchingActionIndex].subflow_reference = {
2117
+ sys_id: subflowResult.sys_id,
2118
+ name: subflowResult.subflow.name,
2119
+ url: subflowResult.url
2120
+ };
2121
+ }
2122
+ }
2123
+ }
2124
+ return enhancedActions;
2125
+ }
2126
+ /**
2127
+ * Check if action and subflow are related
2128
+ */
2129
+ actionsAreRelated(action, subflow) {
2130
+ // Simple heuristic - could be enhanced with more sophisticated matching
2131
+ const actionType = action.type.toLowerCase();
2132
+ const subflowName = subflow.name.toLowerCase();
2133
+ const relatedPairs = [
2134
+ ['approval', 'approval'],
2135
+ ['notification', 'notification'],
2136
+ ['create_task', 'task'],
2137
+ ['update_record', 'update']
2138
+ ];
2139
+ return relatedPairs.some(([actionKeyword, subflowKeyword]) => actionType.includes(actionKeyword) && subflowName.includes(subflowKeyword));
2140
+ }
2141
+ /**
2142
+ * Generate comprehensive recommendations
2143
+ */
2144
+ generateComprehensiveRecommendations(analysisResult, validationResult, matchingTemplates, subflowResults) {
2145
+ const recommendations = [];
2146
+ // Decision confidence recommendations
2147
+ if (analysisResult.confidence < 0.7) {
2148
+ recommendations.push('Consider providing more specific requirements to improve decision confidence');
2149
+ }
2150
+ // Complexity recommendations
2151
+ if (analysisResult.criteria.complexity === 'high' || analysisResult.criteria.complexity === 'very_high') {
2152
+ recommendations.push('Consider breaking complex logic into smaller, more manageable components');
2153
+ }
2154
+ // Reusability recommendations
2155
+ if (analysisResult.criteria.reusability === 'high' && analysisResult.recommendedType === 'main_flow') {
2156
+ recommendations.push('Consider creating reusable subflows for components that may be used elsewhere');
2157
+ }
2158
+ // Template recommendations
2159
+ if (matchingTemplates.length > 0 && matchingTemplates[0].confidence > 0.8) {
2160
+ recommendations.push(`Consider using the ${matchingTemplates[0].template.name} template for consistency`);
2161
+ }
2162
+ // Validation recommendations
2163
+ validationResult.recommendations.forEach(rec => {
2164
+ if (rec.priority === 'high') {
2165
+ recommendations.push(rec.message);
2166
+ }
2167
+ });
2168
+ // Subflow recommendations
2169
+ subflowResults.forEach(result => {
2170
+ if (result.success && result.recommendations) {
2171
+ recommendations.push(...result.recommendations);
2172
+ }
2173
+ });
2174
+ // General best practices
2175
+ recommendations.push('Test the flow thoroughly before deploying to production');
2176
+ recommendations.push('Document the flow purpose and usage for future maintenance');
2177
+ recommendations.push('Consider adding error handling for robust operation');
2178
+ return recommendations;
2179
+ }
2180
+ /**
2181
+ * Get intelligent flow analysis summary
2182
+ */
2183
+ async getFlowAnalysisSummary(instruction) {
2184
+ try {
2185
+ const analysisResult = await this.decisionEngine.analyzeAndRecommend(instruction);
2186
+ const validationResult = this.validationEngine.validateDecision(analysisResult, instruction);
2187
+ const matchingTemplates = this.patternTemplates.findMatchingTemplates(instruction);
2188
+ return {
2189
+ decision: {
2190
+ recommendedType: analysisResult.recommendedType,
2191
+ confidence: analysisResult.confidence,
2192
+ rationale: analysisResult.rationale
2193
+ },
2194
+ complexity: analysisResult.criteria.complexity,
2195
+ reusability: analysisResult.criteria.reusability,
2196
+ context: analysisResult.criteria.context,
2197
+ validation: {
2198
+ isValid: validationResult.isValid,
2199
+ score: validationResult.score,
2200
+ maxScore: validationResult.maxScore
2201
+ },
2202
+ templates: {
2203
+ matchCount: matchingTemplates.length,
2204
+ bestMatch: matchingTemplates[0]?.template.name || null,
2205
+ confidence: matchingTemplates[0]?.confidence || 0
2206
+ },
2207
+ subflowCandidates: analysisResult.subflowCandidates.length,
2208
+ alternatives: analysisResult.alternatives
2209
+ };
2210
+ }
2211
+ catch (error) {
2212
+ this.logger.error('Failed to get flow analysis summary', error);
2213
+ return {
2214
+ error: 'Analysis failed',
2215
+ message: error instanceof Error ? error.message : String(error)
2216
+ };
2217
+ }
2218
+ }
2219
+ }
2220
+ exports.EnhancedFlowComposer = EnhancedFlowComposer;
2221
+ //# sourceMappingURL=flow-composer.js.map