snow-flow-test 10.0.1-test.158 → 10.0.1-test.159

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-test.158",
3
+ "version": "10.0.1-test.159",
4
4
  "name": "snow-flow-test",
5
5
  "description": "Snow-Flow Test - ServiceNow Multi-Agent Development Framework",
6
6
  "license": "Elastic-2.0",
@@ -311,6 +311,108 @@ async function addActionViaGraphQL(
311
311
  }
312
312
  }
313
313
 
314
+ // ── FLOW LOGIC (If/Else, For Each, etc.) ─────────────────────────────
315
+
316
+ async function addFlowLogicViaGraphQL(
317
+ client: any,
318
+ flowId: string,
319
+ logicType: string,
320
+ inputs?: Record<string, string>,
321
+ order?: number,
322
+ parentUiId?: string
323
+ ): Promise<{ success: boolean; logicId?: string; steps?: any; error?: string }> {
324
+ const steps: any = {};
325
+
326
+ // Dynamically look up flow logic definition in sys_hub_flow_logic_definition
327
+ let defId: string | null = null;
328
+ let defName = '';
329
+ let defType = logicType;
330
+ // Try exact match on type (IF, FOR_EACH, DO_UNTIL, SWITCH), then name
331
+ for (const field of ['type', 'name']) {
332
+ if (defId) break;
333
+ try {
334
+ const resp = await client.get('/api/now/table/sys_hub_flow_logic_definition', {
335
+ params: { sysparm_query: field + '=' + logicType, sysparm_fields: 'sys_id,type,name,description', sysparm_limit: 1 }
336
+ });
337
+ const found = resp.data.result?.[0];
338
+ if (found?.sys_id) {
339
+ defId = found.sys_id;
340
+ defName = found.name || logicType;
341
+ defType = found.type || logicType;
342
+ steps.def_lookup = { id: found.sys_id, type: found.type, name: found.name, matched: field + '=' + logicType };
343
+ }
344
+ } catch (_) {}
345
+ }
346
+ // Fallback: LIKE search
347
+ if (!defId) {
348
+ try {
349
+ const resp = await client.get('/api/now/table/sys_hub_flow_logic_definition', {
350
+ params: {
351
+ sysparm_query: 'typeLIKE' + logicType + '^ORnameLIKE' + logicType,
352
+ sysparm_fields: 'sys_id,type,name,description', sysparm_limit: 5
353
+ }
354
+ });
355
+ const results = resp.data.result || [];
356
+ steps.def_lookup_fallback_candidates = results.map((r: any) => ({ sys_id: r.sys_id, type: r.type, name: r.name }));
357
+ if (results[0]?.sys_id) {
358
+ defId = results[0].sys_id;
359
+ defName = results[0].name || logicType;
360
+ defType = results[0].type || logicType;
361
+ steps.def_lookup = { id: results[0].sys_id, type: results[0].type, name: results[0].name, matched: 'LIKE ' + logicType };
362
+ }
363
+ } catch (_) {}
364
+ }
365
+ if (!defId) return { success: false, error: 'Flow logic definition not found for: ' + logicType, steps };
366
+
367
+ const uuid = generateUUID();
368
+ const logicResponseFields = 'flowLogics { inserts { sysId uiUniqueIdentifier __typename } updates deletes __typename }';
369
+ try {
370
+ const result = await executeFlowPatchMutation(client, {
371
+ flowId: flowId,
372
+ flowLogics: {
373
+ insert: [{
374
+ order: String(order || 1),
375
+ uiUniqueIdentifier: uuid,
376
+ parent: '',
377
+ metadata: '{"predicates":[]}',
378
+ flowSysId: flowId,
379
+ generationSource: '',
380
+ definitionId: defId,
381
+ type: 'flowlogic',
382
+ parentUiId: parentUiId || '',
383
+ inputs: []
384
+ }]
385
+ }
386
+ }, logicResponseFields);
387
+
388
+ const logicId = result?.flowLogics?.inserts?.[0]?.sysId;
389
+ steps.insert = { success: !!logicId, logicId, uuid };
390
+ if (!logicId) return { success: false, steps, error: 'GraphQL flow logic INSERT returned no ID' };
391
+
392
+ // Update with input values if provided
393
+ if (inputs && Object.keys(inputs).length > 0) {
394
+ const updateInputs = Object.entries(inputs).map(([name, value]) => ({
395
+ name,
396
+ value: { schemaless: false, schemalessValue: '', value: String(value) }
397
+ }));
398
+ try {
399
+ await executeFlowPatchMutation(client, {
400
+ flowId: flowId,
401
+ flowLogics: { update: [{ uiUniqueIdentifier: uuid, type: 'flowlogic', inputs: updateInputs }] }
402
+ }, logicResponseFields);
403
+ steps.value_update = { success: true, inputs: updateInputs.map(i => i.name) };
404
+ } catch (e: any) {
405
+ steps.value_update = { success: false, error: e.message };
406
+ }
407
+ }
408
+
409
+ return { success: true, logicId, steps };
410
+ } catch (e: any) {
411
+ steps.insert = { success: false, error: e.message };
412
+ return { success: false, steps, error: 'GraphQL flow logic INSERT failed: ' + e.message };
413
+ }
414
+ }
415
+
314
416
  async function createFlowViaProcessFlowAPI(
315
417
  client: any,
316
418
  params: {
@@ -419,8 +521,8 @@ export const toolDefinition: MCPToolDefinition = {
419
521
  properties: {
420
522
  action: {
421
523
  type: 'string',
422
- enum: ['create', 'create_subflow', 'list', 'get', 'update', 'activate', 'deactivate', 'delete', 'publish', 'add_trigger', 'update_trigger', 'add_action'],
423
- description: 'Action to perform. Use add_trigger/add_action to add new elements, update_trigger to change an existing trigger type/table/condition.'
524
+ enum: ['create', 'create_subflow', 'list', 'get', 'update', 'activate', 'deactivate', 'delete', 'publish', 'add_trigger', 'update_trigger', 'add_action', 'add_flow_logic'],
525
+ description: 'Action to perform. Use add_trigger/add_action/add_flow_logic to add elements, update_trigger to change an existing trigger. Flow logic types: IF, FOR_EACH, DO_UNTIL, SWITCH.'
424
526
  },
425
527
 
426
528
  flow_id: {
@@ -506,6 +608,18 @@ export const toolDefinition: MCPToolDefinition = {
506
608
  description: 'Activate flow after creation (default: true)',
507
609
  default: true
508
610
  },
611
+ logic_type: {
612
+ type: 'string',
613
+ description: 'Flow logic type for add_flow_logic. Looked up dynamically in sys_hub_flow_logic_definition. Common values: IF, FOR_EACH, DO_UNTIL, SWITCH'
614
+ },
615
+ logic_inputs: {
616
+ type: 'object',
617
+ description: 'Input values for the flow logic block (e.g. {condition: "expression", condition_name: "My Condition"})'
618
+ },
619
+ parent_ui_id: {
620
+ type: 'string',
621
+ description: 'Parent UI unique identifier for nesting flow logic blocks (e.g. placing actions inside an If block)'
622
+ },
509
623
  type: {
510
624
  type: 'string',
511
625
  enum: ['flow', 'subflow', 'all'],
@@ -1444,6 +1558,40 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
1444
1558
  : createErrorResult(addActResult.error || 'Failed to add action');
1445
1559
  }
1446
1560
 
1561
+ // ────────────────────────────────────────────────────────────────
1562
+ // ADD_FLOW_LOGIC — add If/Else, For Each, Do Until, Switch blocks
1563
+ // ────────────────────────────────────────────────────────────────
1564
+ case 'add_flow_logic': {
1565
+ if (!args.flow_id) {
1566
+ throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'flow_id is required for add_flow_logic');
1567
+ }
1568
+ if (!args.logic_type) {
1569
+ throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'logic_type is required for add_flow_logic (e.g. IF, FOR_EACH, DO_UNTIL, SWITCH)');
1570
+ }
1571
+ var addLogicFlowId = await resolveFlowId(client, args.flow_id);
1572
+ var addLogicType = args.logic_type;
1573
+ var addLogicInputs = args.logic_inputs || {};
1574
+ var addLogicOrder = args.order;
1575
+ var addLogicParentUiId = args.parent_ui_id || '';
1576
+
1577
+ var addLogicResult = await addFlowLogicViaGraphQL(client, addLogicFlowId, addLogicType, addLogicInputs, addLogicOrder, addLogicParentUiId);
1578
+
1579
+ var addLogicSummary = summary();
1580
+ if (addLogicResult.success) {
1581
+ addLogicSummary
1582
+ .success('Flow logic added via GraphQL')
1583
+ .field('Flow', addLogicFlowId)
1584
+ .field('Type', addLogicType)
1585
+ .field('Logic ID', addLogicResult.logicId || 'unknown');
1586
+ } else {
1587
+ addLogicSummary.error('Failed to add flow logic: ' + (addLogicResult.error || 'unknown'));
1588
+ }
1589
+
1590
+ return addLogicResult.success
1591
+ ? createSuccessResult({ action: 'add_flow_logic', ...addLogicResult }, {}, addLogicSummary.build())
1592
+ : createErrorResult(addLogicResult.error || 'Failed to add flow logic');
1593
+ }
1594
+
1447
1595
  default:
1448
1596
  throw new SnowFlowError(ErrorType.VALIDATION_ERROR, 'Unknown action: ' + action);
1449
1597
  }