snow-flow 10.0.1-dev.484 → 10.0.1-dev.486

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.1-dev.484",
3
+ "version": "10.0.1-dev.486",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -110,6 +110,21 @@ async function executeFlowPatchMutation(
110
110
  return resp.data?.data?.global?.snFlowDesigner?.flow || resp.data;
111
111
  }
112
112
 
113
+ /**
114
+ * Release the Flow Designer editing lock on a flow.
115
+ * The UI calls safeEdit(delete: flowId) when closing the editor.
116
+ * Without this, the flow remains locked to the API user forever.
117
+ */
118
+ async function releaseFlowEditingLock(client: any, flowId: string): Promise<boolean> {
119
+ try {
120
+ var mutation = 'mutation { global { snFlowDesigner { safeEdit(safeEditInput: {delete: "' + flowId + '"}) { deleteResult { deleteSuccess id __typename } __typename } __typename } __typename } }';
121
+ var resp = await client.post('/api/now/graphql', { variables: {}, query: mutation });
122
+ return resp.data?.data?.global?.snFlowDesigner?.safeEdit?.deleteResult?.deleteSuccess === true;
123
+ } catch (_) {
124
+ return false;
125
+ }
126
+ }
127
+
113
128
  /** Safely extract a string from a ServiceNow Table API value (handles reference objects like {value, link}). */
114
129
  const str = (val: any): string =>
115
130
  typeof val === 'object' && val !== null ? (val.display_value || val.value || '') : (val || '');
@@ -1662,7 +1677,7 @@ async function transformActionInputsForRecordAction(
1662
1677
  resolvedInputs: Record<string, string>,
1663
1678
  actionParams: any[],
1664
1679
  uuid: string
1665
- ): Promise<{ inputs: any[]; labelCacheEntries: any[]; steps: any }> {
1680
+ ): Promise<{ inputs: any[]; labelCacheUpdates: any[]; labelCacheInserts: any[]; steps: any }> {
1666
1681
  var steps: any = {};
1667
1682
 
1668
1683
  // Detect if this is a record action: must have both `record` and `table_name` parameters
@@ -1673,7 +1688,7 @@ async function transformActionInputsForRecordAction(
1673
1688
 
1674
1689
  if (!hasRecord || !hasTableName) {
1675
1690
  steps.record_action = false;
1676
- return { inputs: actionInputs, labelCacheEntries: [], steps };
1691
+ return { inputs: actionInputs, labelCacheUpdates: [], labelCacheInserts: [], steps };
1677
1692
  }
1678
1693
  steps.record_action = true;
1679
1694
 
@@ -2490,9 +2505,10 @@ export const toolDefinition: MCPToolDefinition = {
2490
2505
  'add_trigger', 'update_trigger', 'delete_trigger',
2491
2506
  'add_action', 'update_action', 'delete_action',
2492
2507
  'add_flow_logic', 'update_flow_logic', 'delete_flow_logic',
2493
- 'add_subflow', 'update_subflow', 'delete_subflow'
2508
+ 'add_subflow', 'update_subflow', 'delete_subflow',
2509
+ 'close_flow'
2494
2510
  ],
2495
- description: 'Action to perform. add_*/update_*/delete_* for triggers, actions, flow_logic, subflows. update_trigger replaces the trigger type. update_action/update_flow_logic/update_subflow change input values. delete_* removes elements by element_id.'
2511
+ description: 'Action to perform. add_*/update_*/delete_* for triggers, actions, flow_logic, subflows. update_trigger replaces the trigger type. update_action/update_flow_logic/update_subflow change input values. delete_* removes elements by element_id. IMPORTANT: When making multiple edits to a flow (add_action, add_flow_logic, etc.), call close_flow as the LAST step to release the editing lock. Without close_flow, the flow stays locked and cannot be edited in the UI. create_flow auto-releases the lock.'
2496
2512
  },
2497
2513
 
2498
2514
  flow_id: {
@@ -2580,7 +2596,18 @@ export const toolDefinition: MCPToolDefinition = {
2580
2596
  },
2581
2597
  logic_type: {
2582
2598
  type: 'string',
2583
- description: 'Flow logic type for add_flow_logic. Looked up dynamically in sys_hub_flow_logic_definition. Common values: IF, ELSE, FOR_EACH, DO_UNTIL, SWITCH. IMPORTANT: ELSE blocks require connected_to set to the If block\'s uiUniqueIdentifier. IF does NOT require an Else block — only add Else if explicitly requested.'
2599
+ description: 'Flow logic type for add_flow_logic. Looked up dynamically in sys_hub_flow_logic_definition. Available types: ' +
2600
+ 'IF, ELSEIF, ELSE — conditional branching. Use ELSEIF (not nested ELSE+IF) for else-if branches. ELSE and ELSEIF require connected_to set to the If block\'s uiUniqueIdentifier. ' +
2601
+ 'FOR_EACH, DO_UNTIL — loops. SKIP_ITERATION and EXIT_LOOP can be used inside loops. ' +
2602
+ 'PARALLEL — execute branches in parallel. ' +
2603
+ 'DECISION — switch/decision table. ' +
2604
+ 'TRY — error handling (try/catch). ' +
2605
+ 'END — End Flow (stops execution). Always add END as the last element when the flow should terminate cleanly. ' +
2606
+ 'TIMER — Wait for a duration of time. ' +
2607
+ 'GO_BACK_TO — jump back to a previous step. ' +
2608
+ 'SET_FLOW_VARIABLES, APPEND_FLOW_VARIABLES, GET_FLOW_OUTPUT — flow variable management. ' +
2609
+ 'WORKFLOW — call a legacy workflow. DYNAMIC_FLOW — dynamically invoke a flow. ' +
2610
+ 'Best practice: add an END element at the end of your flow for clean termination.'
2584
2611
  },
2585
2612
  logic_inputs: {
2586
2613
  type: 'object',
@@ -3067,6 +3094,12 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
3067
3094
  }
3068
3095
  }
3069
3096
 
3097
+ // Release Flow Designer editing lock (safeEdit delete) so users can edit the flow in the UI
3098
+ if (flowSysId) {
3099
+ var lockReleased = await releaseFlowEditingLock(client, flowSysId);
3100
+ diagnostics.editing_lock_released = lockReleased;
3101
+ }
3102
+
3070
3103
  return createSuccessResult({
3071
3104
  created: true,
3072
3105
  method: usedMethod,
@@ -3555,7 +3588,7 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
3555
3588
  throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'flow_id is required for add_flow_logic');
3556
3589
  }
3557
3590
  if (!args.logic_type) {
3558
- throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'logic_type is required for add_flow_logic (e.g. IF, FOR_EACH, DO_UNTIL, SWITCH)');
3591
+ throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'logic_type is required for add_flow_logic (e.g. IF, ELSEIF, ELSE, FOR_EACH, DO_UNTIL, PARALLEL, DECISION, TRY, END, TIMER, SET_FLOW_VARIABLES)');
3559
3592
  }
3560
3593
  var addLogicFlowId = await resolveFlowId(client, args.flow_id);
3561
3594
  var addLogicType = args.logic_type;
@@ -3673,6 +3706,22 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
3673
3706
  : createErrorResult(delResult.error || 'Failed to delete element');
3674
3707
  }
3675
3708
 
3709
+ // ────────────────────────────────────────────────────────────────
3710
+ // CLOSE_FLOW — release Flow Designer editing lock (safeEdit)
3711
+ // ────────────────────────────────────────────────────────────────
3712
+ case 'close_flow': {
3713
+ if (!args.flow_id) throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'flow_id is required for close_flow');
3714
+ var closeFlowId = await resolveFlowId(client, args.flow_id);
3715
+ var closed = await releaseFlowEditingLock(client, closeFlowId);
3716
+ var closeSummary = summary();
3717
+ if (closed) {
3718
+ closeSummary.success('Flow editing lock released').field('Flow', closeFlowId);
3719
+ } else {
3720
+ closeSummary.warning('Lock release returned false (flow may not have been locked)').field('Flow', closeFlowId);
3721
+ }
3722
+ return createSuccessResult({ action: 'close_flow', flow_id: closeFlowId, lock_released: closed }, {}, closeSummary.build());
3723
+ }
3724
+
3676
3725
  default:
3677
3726
  throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'Unknown action: ' + action);
3678
3727
  }