snow-flow 10.0.56 → 10.0.57

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "10.0.56",
3
+ "version": "10.0.57",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -2800,27 +2800,41 @@ async function addFlowLogicViaGraphQL(
2800
2800
  logicType = normalizedType;
2801
2801
  }
2802
2802
 
2803
+ // ELSE and ELSEIF are variants of IF in ServiceNow's GraphQL API.
2804
+ // They share the IF definition — the distinction is made through connectedTo + condition.
2805
+ // The GraphQL API rejects flowLogicDefinition.type='ELSEIF'/'ELSE' with
2806
+ // "Unsupported flowLogic type", so we must always look up the IF definition.
2807
+ var requestedLogicType = logicType;
2808
+ var isElseVariant = ['ELSE', 'ELSEIF'].includes(logicType.toUpperCase());
2809
+ var defLookupType = isElseVariant ? 'IF' : logicType;
2810
+
2811
+ // ELSE/ELSEIF blocks MUST be connected to an If block via connectedTo (the If block's uiUniqueIdentifier)
2812
+ // Unlike other flow logic, Else is NOT a child (parent="") — it uses connectedTo to link to the If block.
2813
+ if (isElseVariant && !connectedTo) {
2814
+ return { success: false, error: requestedLogicType.toUpperCase() + ' blocks require connected_to set to the If block\'s uiUniqueIdentifier (returned from the add_flow_logic response for the If block). Else is NOT a child of If — it uses connectedTo to link to it.', steps };
2815
+ }
2816
+
2803
2817
  // Dynamically look up flow logic definition in sys_hub_flow_logic_definition
2804
2818
  // Fetch extra fields needed for the flowLogicDefinition object in the mutation
2805
2819
  const defFields = 'sys_id,type,name,description,order,attributes,compilation_class,quiescence,visible,category,connected_to';
2806
2820
  let defId: string | null = null;
2807
2821
  let defName = '';
2808
- let defType = logicType;
2822
+ let defType = defLookupType;
2809
2823
  let defRecord: any = {};
2810
- // Try exact match on type (IF, ELSE, FOREACH, DOUNTIL, etc.), then name
2824
+ // Try exact match on type (IF, FOREACH, DOUNTIL, etc.), then name
2811
2825
  for (const field of ['type', 'name']) {
2812
2826
  if (defId) break;
2813
2827
  try {
2814
2828
  const resp = await client.get('/api/now/table/sys_hub_flow_logic_definition', {
2815
- params: { sysparm_query: field + '=' + logicType, sysparm_fields: defFields, sysparm_limit: 1 }
2829
+ params: { sysparm_query: field + '=' + defLookupType, sysparm_fields: defFields, sysparm_limit: 1 }
2816
2830
  });
2817
2831
  const found = resp.data.result?.[0];
2818
2832
  if (found?.sys_id) {
2819
2833
  defId = found.sys_id;
2820
- defName = found.name || logicType;
2821
- defType = found.type || logicType;
2834
+ defName = found.name || defLookupType;
2835
+ defType = found.type || defLookupType;
2822
2836
  defRecord = found;
2823
- steps.def_lookup = { id: found.sys_id, type: found.type, name: found.name, matched: field + '=' + logicType };
2837
+ steps.def_lookup = { id: found.sys_id, type: found.type, name: found.name, matched: field + '=' + defLookupType, requested: requestedLogicType };
2824
2838
  }
2825
2839
  } catch (_) {}
2826
2840
  }
@@ -2829,7 +2843,7 @@ async function addFlowLogicViaGraphQL(
2829
2843
  try {
2830
2844
  const resp = await client.get('/api/now/table/sys_hub_flow_logic_definition', {
2831
2845
  params: {
2832
- sysparm_query: 'typeLIKE' + logicType + '^ORnameLIKE' + logicType,
2846
+ sysparm_query: 'typeLIKE' + defLookupType + '^ORnameLIKE' + defLookupType,
2833
2847
  sysparm_fields: defFields, sysparm_limit: 5
2834
2848
  }
2835
2849
  });
@@ -2837,20 +2851,16 @@ async function addFlowLogicViaGraphQL(
2837
2851
  steps.def_lookup_fallback_candidates = results.map((r: any) => ({ sys_id: r.sys_id, type: r.type, name: r.name }));
2838
2852
  if (results[0]?.sys_id) {
2839
2853
  defId = results[0].sys_id;
2840
- defName = results[0].name || logicType;
2841
- defType = results[0].type || logicType;
2854
+ defName = results[0].name || defLookupType;
2855
+ defType = results[0].type || defLookupType;
2842
2856
  defRecord = results[0];
2843
- steps.def_lookup = { id: results[0].sys_id, type: results[0].type, name: results[0].name, matched: 'LIKE ' + logicType };
2857
+ steps.def_lookup = { id: results[0].sys_id, type: results[0].type, name: results[0].name, matched: 'LIKE ' + defLookupType };
2844
2858
  }
2845
2859
  } catch (_) {}
2846
2860
  }
2847
- if (!defId) return { success: false, error: 'Flow logic definition not found for: ' + logicType, steps };
2848
-
2849
- // ELSE/ELSEIF blocks MUST be connected to an If block via connectedTo (the If block's uiUniqueIdentifier)
2850
- // Unlike other flow logic, Else is NOT a child (parent="") — it uses connectedTo to link to the If block.
2851
- const upperType = defType.toUpperCase();
2852
- if ((upperType === 'ELSE' || upperType === 'ELSEIF') && !connectedTo) {
2853
- return { success: false, error: upperType + ' blocks require connected_to set to the If block\'s uiUniqueIdentifier (returned from the add_flow_logic response for the If block). Else is NOT a child of If — it uses connectedTo to link to it.', steps };
2861
+ if (!defId) return { success: false, error: 'Flow logic definition not found for: ' + requestedLogicType, steps };
2862
+ if (isElseVariant) {
2863
+ steps.else_variant = { requested: requestedLogicType, using_definition: defType, note: 'ELSE/ELSEIF use IF definition in GraphQL API' };
2854
2864
  }
2855
2865
 
2856
2866
  // Build full input objects with parameter definitions (matching UI format)
@@ -2860,9 +2870,14 @@ async function addFlowLogicViaGraphQL(
2860
2870
  steps.input_query_stats = { defParamsFound: inputResult.defParamsCount, inputsBuilt: inputResult.inputs.length, error: inputResult.inputQueryError };
2861
2871
 
2862
2872
  // Validate mandatory fields (e.g. condition for IF/ELSEIF)
2863
- if (inputResult.missingMandatory && inputResult.missingMandatory.length > 0) {
2864
- steps.missing_mandatory = inputResult.missingMandatory;
2865
- return { success: false, error: 'Missing required inputs for ' + logicType + ': ' + inputResult.missingMandatory.join(', ') + '. These fields are mandatory in Flow Designer.', steps };
2873
+ // ELSE blocks use the IF definition but don't need a condition — skip mandatory check for condition
2874
+ var effectiveMissing = inputResult.missingMandatory
2875
+ if (requestedLogicType.toUpperCase() === 'ELSE' && effectiveMissing.length > 0) {
2876
+ effectiveMissing = effectiveMissing.filter(function (m: string) { return !m.startsWith('condition'); })
2877
+ }
2878
+ if (effectiveMissing.length > 0) {
2879
+ steps.missing_mandatory = effectiveMissing;
2880
+ return { success: false, error: 'Missing required inputs for ' + requestedLogicType + ': ' + effectiveMissing.join(', ') + '. These fields are mandatory in Flow Designer.', steps };
2866
2881
  }
2867
2882
 
2868
2883
  // ── Detect condition that needs data pill transformation ────────────