snow-flow 10.0.1-dev.461 → 10.0.1-dev.462
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
|
@@ -365,6 +365,216 @@ async function calculateInsertOrder(
|
|
|
365
365
|
return 1;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Flatten an attributes object { key: "val" } into comma-separated "key=val," string (matching UI format).
|
|
370
|
+
* If already a string, returns as-is.
|
|
371
|
+
*/
|
|
372
|
+
function flattenAttributes(attrs: any): string {
|
|
373
|
+
if (!attrs || typeof attrs === 'string') return attrs || '';
|
|
374
|
+
return Object.entries(attrs).map(([k, v]) => k + '=' + v).join(',') + ',';
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Build full trigger input and output objects for the INSERT mutation by fetching from the
|
|
379
|
+
* triggerpicker API (/api/now/hub/triggerpicker/{id}) — the same endpoint Flow Designer UI uses.
|
|
380
|
+
*
|
|
381
|
+
* The UI sends ALL inputs with full parameter definitions (choices, defaults, attributes) and
|
|
382
|
+
* ALL outputs in a single INSERT mutation. This function replicates that format exactly.
|
|
383
|
+
*
|
|
384
|
+
* Fallback: if the triggerpicker API fails, queries sys_hub_trigger_input / sys_hub_trigger_output
|
|
385
|
+
* via the Table API (same approach as buildActionInputsForInsert / buildFlowLogicInputsForInsert).
|
|
386
|
+
*/
|
|
387
|
+
async function buildTriggerInputsForInsert(
|
|
388
|
+
client: any,
|
|
389
|
+
trigDefId: string,
|
|
390
|
+
userTable?: string,
|
|
391
|
+
userCondition?: string
|
|
392
|
+
): Promise<{ inputs: any[]; outputs: any[]; error?: string }> {
|
|
393
|
+
var apiInputs: any[] = [];
|
|
394
|
+
var apiOutputs: any[] = [];
|
|
395
|
+
var fetchError = '';
|
|
396
|
+
|
|
397
|
+
// Strategy 1: triggerpicker API (primary — same as Flow Designer UI)
|
|
398
|
+
try {
|
|
399
|
+
var tpResp = await client.get('/api/now/hub/triggerpicker/' + trigDefId, {
|
|
400
|
+
params: { sysparm_transaction_scope: 'global' },
|
|
401
|
+
headers: { Accept: 'application/json' }
|
|
402
|
+
});
|
|
403
|
+
var tpData = tpResp.data?.result || tpResp.data;
|
|
404
|
+
if (tpData && typeof tpData === 'object') {
|
|
405
|
+
apiInputs = tpData.inputs || tpData.trigger_inputs || [];
|
|
406
|
+
apiOutputs = tpData.outputs || tpData.trigger_outputs || [];
|
|
407
|
+
}
|
|
408
|
+
} catch (tpErr: any) {
|
|
409
|
+
fetchError = 'triggerpicker: ' + (tpErr.message || 'unknown');
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Strategy 2: Table API fallback (query sys_hub_trigger_input / sys_hub_trigger_output)
|
|
413
|
+
if (apiInputs.length === 0) {
|
|
414
|
+
try {
|
|
415
|
+
var tiResp = await client.get('/api/now/table/sys_hub_trigger_input', {
|
|
416
|
+
params: {
|
|
417
|
+
sysparm_query: 'model=' + trigDefId,
|
|
418
|
+
sysparm_fields: 'sys_id,element,label,internal_type,mandatory,default_value,order,max_length,hint,read_only,attributes,reference,reference_display,choice,dependent_on_field,use_dependent_field',
|
|
419
|
+
sysparm_display_value: 'false',
|
|
420
|
+
sysparm_limit: 50
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
var tableInputs = tiResp.data.result || [];
|
|
424
|
+
apiInputs = tableInputs.map(function (rec: any) {
|
|
425
|
+
return {
|
|
426
|
+
id: str(rec.sys_id), name: str(rec.element), label: str(rec.label) || str(rec.element),
|
|
427
|
+
type: str(rec.internal_type) || 'string',
|
|
428
|
+
type_label: TYPE_LABELS[str(rec.internal_type) || 'string'] || str(rec.internal_type),
|
|
429
|
+
mandatory: str(rec.mandatory) === 'true',
|
|
430
|
+
order: parseInt(str(rec.order) || '0', 10),
|
|
431
|
+
maxsize: parseInt(str(rec.max_length) || '4000', 10),
|
|
432
|
+
hint: str(rec.hint), defaultValue: str(rec.default_value),
|
|
433
|
+
reference: str(rec.reference), reference_display: str(rec.reference_display),
|
|
434
|
+
use_dependent: str(rec.use_dependent_field) === 'true',
|
|
435
|
+
dependent_on: str(rec.dependent_on_field),
|
|
436
|
+
attributes: str(rec.attributes)
|
|
437
|
+
};
|
|
438
|
+
});
|
|
439
|
+
fetchError = '';
|
|
440
|
+
} catch (tiErr: any) {
|
|
441
|
+
fetchError += '; table_api_inputs: ' + (tiErr.message || 'unknown');
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
if (apiOutputs.length === 0) {
|
|
445
|
+
try {
|
|
446
|
+
var toResp = await client.get('/api/now/table/sys_hub_trigger_output', {
|
|
447
|
+
params: {
|
|
448
|
+
sysparm_query: 'model=' + trigDefId,
|
|
449
|
+
sysparm_fields: 'sys_id,element,label,internal_type,mandatory,order,max_length,hint,attributes,reference,reference_display,use_dependent_field,dependent_on_field',
|
|
450
|
+
sysparm_display_value: 'false',
|
|
451
|
+
sysparm_limit: 50
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
var tableOutputs = toResp.data.result || [];
|
|
455
|
+
apiOutputs = tableOutputs.map(function (rec: any) {
|
|
456
|
+
return {
|
|
457
|
+
id: str(rec.sys_id), name: str(rec.element), label: str(rec.label) || str(rec.element),
|
|
458
|
+
type: str(rec.internal_type) || 'string',
|
|
459
|
+
type_label: TYPE_LABELS[str(rec.internal_type) || 'string'] || str(rec.internal_type),
|
|
460
|
+
mandatory: str(rec.mandatory) === 'true',
|
|
461
|
+
order: parseInt(str(rec.order) || '0', 10),
|
|
462
|
+
maxsize: parseInt(str(rec.max_length) || '200', 10),
|
|
463
|
+
hint: str(rec.hint), reference: str(rec.reference), reference_display: str(rec.reference_display),
|
|
464
|
+
use_dependent: str(rec.use_dependent_field) === 'true',
|
|
465
|
+
dependent_on: str(rec.dependent_on_field),
|
|
466
|
+
attributes: str(rec.attributes)
|
|
467
|
+
};
|
|
468
|
+
});
|
|
469
|
+
} catch (_) {}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Transform inputs into GraphQL mutation format (matching exact UI structure)
|
|
473
|
+
var inputs = apiInputs.map(function (inp: any) {
|
|
474
|
+
var paramType = inp.type || 'string';
|
|
475
|
+
var name = inp.name || '';
|
|
476
|
+
var label = inp.label || name;
|
|
477
|
+
var attrs = typeof inp.attributes === 'object' ? flattenAttributes(inp.attributes) : (inp.attributes || '');
|
|
478
|
+
|
|
479
|
+
// Determine value: user-provided > default
|
|
480
|
+
var value = '';
|
|
481
|
+
if (name === 'table' && userTable) value = userTable;
|
|
482
|
+
else if (name === 'condition') value = userCondition || '^EQ';
|
|
483
|
+
else if (inp.defaultValue) value = inp.defaultValue;
|
|
484
|
+
|
|
485
|
+
var parameter: any = {
|
|
486
|
+
id: inp.id || '', label: label, name: name, type: paramType,
|
|
487
|
+
type_label: inp.type_label || TYPE_LABELS[paramType] || paramType,
|
|
488
|
+
order: inp.order || 0, extended: inp.extended || false,
|
|
489
|
+
mandatory: inp.mandatory || false, readonly: inp.readonly || false,
|
|
490
|
+
maxsize: inp.maxsize || 4000, data_structure: '',
|
|
491
|
+
reference: inp.reference || '', reference_display: inp.reference_display || '',
|
|
492
|
+
ref_qual: inp.ref_qual || '', choiceOption: inp.choiceOption || '',
|
|
493
|
+
table: '', columnName: '', defaultValue: inp.defaultValue || '',
|
|
494
|
+
use_dependent: inp.use_dependent || false, dependent_on: inp.dependent_on || '',
|
|
495
|
+
internal_link: inp.internal_link || '', show_ref_finder: inp.show_ref_finder || false,
|
|
496
|
+
local: inp.local || false, attributes: attrs, sys_class_name: '', children: []
|
|
497
|
+
};
|
|
498
|
+
if (inp.hint) parameter.hint = inp.hint;
|
|
499
|
+
if (inp.defaultDisplayValue) parameter.defaultDisplayValue = inp.defaultDisplayValue;
|
|
500
|
+
if (inp.choices) parameter.choices = inp.choices;
|
|
501
|
+
if (inp.defaultChoices) parameter.defaultChoices = inp.defaultChoices;
|
|
502
|
+
|
|
503
|
+
var inputObj: any = {
|
|
504
|
+
name: name, label: label, internalType: paramType,
|
|
505
|
+
mandatory: inp.mandatory || false, order: inp.order || 0,
|
|
506
|
+
valueSysId: '', field_name: name, type: paramType, children: [],
|
|
507
|
+
displayValue: { value: '' },
|
|
508
|
+
value: value ? { schemaless: false, schemalessValue: '', value: value } : { value: '' },
|
|
509
|
+
parameter: parameter
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
// Add choiceList for choice-type inputs (top-level, matching UI format)
|
|
513
|
+
if (inp.choices && Array.isArray(inp.choices)) {
|
|
514
|
+
inputObj.choiceList = inp.choices.map(function (c: any) {
|
|
515
|
+
return { label: c.label, value: c.value };
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return inputObj;
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
// Transform outputs into GraphQL mutation format
|
|
523
|
+
var outputs = apiOutputs.map(function (out: any) {
|
|
524
|
+
var paramType = out.type || 'string';
|
|
525
|
+
var name = out.name || '';
|
|
526
|
+
var label = out.label || name;
|
|
527
|
+
var attrs = typeof out.attributes === 'object' ? flattenAttributes(out.attributes) : (out.attributes || '');
|
|
528
|
+
|
|
529
|
+
var parameter: any = {
|
|
530
|
+
id: out.id || '', label: label, name: name, type: paramType,
|
|
531
|
+
type_label: out.type_label || TYPE_LABELS[paramType] || paramType,
|
|
532
|
+
hint: out.hint || '', order: out.order || 0, extended: out.extended || false,
|
|
533
|
+
mandatory: out.mandatory || false, readonly: out.readonly || false,
|
|
534
|
+
maxsize: out.maxsize || 200, data_structure: '',
|
|
535
|
+
reference: out.reference || '', reference_display: out.reference_display || '',
|
|
536
|
+
ref_qual: '', choiceOption: '', table: '', columnName: '', defaultValue: '',
|
|
537
|
+
use_dependent: out.use_dependent || false, dependent_on: out.dependent_on || '',
|
|
538
|
+
internal_link: out.internal_link || '', show_ref_finder: false, local: false,
|
|
539
|
+
attributes: attrs, sys_class_name: ''
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
// Build children for complex types (like array.object)
|
|
543
|
+
var children: any[] = [];
|
|
544
|
+
var paramChildren: any[] = [];
|
|
545
|
+
if (out.children && Array.isArray(out.children)) {
|
|
546
|
+
children = out.children.map(function (child: any) {
|
|
547
|
+
return { id: '', name: child.name || '', scriptActive: false, children: [], value: { value: '' }, script: null };
|
|
548
|
+
});
|
|
549
|
+
paramChildren = out.children.map(function (child: any) {
|
|
550
|
+
return {
|
|
551
|
+
id: '', label: child.label || child.name || '', name: child.name || '',
|
|
552
|
+
type: child.type || 'string', type_label: child.type_label || TYPE_LABELS[child.type || 'string'] || 'String',
|
|
553
|
+
hint: '', order: child.order || 0, extended: false, mandatory: false, readonly: false, maxsize: 0,
|
|
554
|
+
data_structure: '', reference: '', reference_display: '', ref_qual: '', choiceOption: '',
|
|
555
|
+
table: '', columnName: '', defaultValue: '', defaultDisplayValue: '',
|
|
556
|
+
use_dependent: false, dependent_on: false, show_ref_finder: false, local: false,
|
|
557
|
+
attributes: '', sys_class_name: '',
|
|
558
|
+
uiDisplayType: child.uiDisplayType || child.type || 'string',
|
|
559
|
+
uiDisplayTypeLabel: child.type_label || 'String',
|
|
560
|
+
internal_link: '', value: '', display_value: '', scriptActive: false,
|
|
561
|
+
parent: out.id || '',
|
|
562
|
+
fieldFacetMap: 'uiTypeLabel=' + (child.type_label || 'String') + ',',
|
|
563
|
+
children: [], script: null
|
|
564
|
+
};
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
parameter.children = paramChildren;
|
|
568
|
+
|
|
569
|
+
return {
|
|
570
|
+
name: name, value: '', displayValue: '', type: paramType,
|
|
571
|
+
order: out.order || 0, label: label, children: children, parameter: parameter
|
|
572
|
+
};
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
return { inputs, outputs, error: fetchError || undefined };
|
|
576
|
+
}
|
|
577
|
+
|
|
368
578
|
async function addTriggerViaGraphQL(
|
|
369
579
|
client: any,
|
|
370
580
|
flowId: string,
|
|
@@ -432,8 +642,13 @@ async function addTriggerViaGraphQL(
|
|
|
432
642
|
}
|
|
433
643
|
if (!trigDefId) return { success: false, error: 'Trigger definition not found for: ' + triggerType, steps };
|
|
434
644
|
|
|
645
|
+
// Build full trigger inputs and outputs from triggerpicker API (matching UI format)
|
|
646
|
+
var triggerData = await buildTriggerInputsForInsert(client, trigDefId!, table, condition);
|
|
647
|
+
steps.trigger_data = { inputCount: triggerData.inputs.length, outputCount: triggerData.outputs.length, error: triggerData.error };
|
|
648
|
+
|
|
435
649
|
const triggerResponseFields = 'triggerInstances { inserts { sysId uiUniqueIdentifier __typename } updates deletes __typename }';
|
|
436
650
|
try {
|
|
651
|
+
// Single INSERT with full inputs and outputs (matching UI behavior — no separate UPDATE needed)
|
|
437
652
|
const insertResult = await executeFlowPatchMutation(client, {
|
|
438
653
|
flowId: flowId,
|
|
439
654
|
triggerInstances: {
|
|
@@ -445,8 +660,8 @@ async function addTriggerViaGraphQL(
|
|
|
445
660
|
type: trigType,
|
|
446
661
|
hasDynamicOutputs: false,
|
|
447
662
|
metadata: '{"predicates":[]}',
|
|
448
|
-
inputs:
|
|
449
|
-
outputs:
|
|
663
|
+
inputs: triggerData.inputs,
|
|
664
|
+
outputs: triggerData.outputs
|
|
450
665
|
}]
|
|
451
666
|
}
|
|
452
667
|
}, triggerResponseFields);
|
|
@@ -455,31 +670,6 @@ async function addTriggerViaGraphQL(
|
|
|
455
670
|
steps.insert = { success: !!triggerId, triggerId };
|
|
456
671
|
if (!triggerId) return { success: false, steps, error: 'GraphQL trigger INSERT returned no trigger ID' };
|
|
457
672
|
|
|
458
|
-
if (table) {
|
|
459
|
-
const updateInputs: any[] = [
|
|
460
|
-
{
|
|
461
|
-
name: 'table',
|
|
462
|
-
displayField: 'number',
|
|
463
|
-
displayValue: { schemaless: false, schemalessValue: '', value: table.charAt(0).toUpperCase() + table.slice(1) },
|
|
464
|
-
value: { schemaless: false, schemalessValue: '', value: table }
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
name: 'condition',
|
|
468
|
-
displayValue: { schemaless: false, schemalessValue: '', value: condition || '^EQ' },
|
|
469
|
-
value: { schemaless: false, schemalessValue: '', value: condition || '^EQ' }
|
|
470
|
-
}
|
|
471
|
-
];
|
|
472
|
-
try {
|
|
473
|
-
await executeFlowPatchMutation(client, {
|
|
474
|
-
flowId: flowId,
|
|
475
|
-
triggerInstances: { update: [{ id: triggerId, inputs: updateInputs }] }
|
|
476
|
-
}, triggerResponseFields);
|
|
477
|
-
steps.update = { success: true, table, condition: condition || '^EQ' };
|
|
478
|
-
} catch (e: any) {
|
|
479
|
-
steps.update = { success: false, error: e.message };
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
673
|
return { success: true, triggerId, steps };
|
|
484
674
|
} catch (e: any) {
|
|
485
675
|
steps.insert = { success: false, error: e.message };
|
|
@@ -487,6 +677,18 @@ async function addTriggerViaGraphQL(
|
|
|
487
677
|
}
|
|
488
678
|
}
|
|
489
679
|
|
|
680
|
+
// Common short-name aliases for action types — maps user-friendly names to ServiceNow internal names
|
|
681
|
+
const ACTION_TYPE_ALIASES: Record<string, string[]> = {
|
|
682
|
+
script: ['script_step', 'run_script', 'Run Script'],
|
|
683
|
+
log: ['log_message', 'Log Message', 'Log'],
|
|
684
|
+
create_record: ['Create Record'],
|
|
685
|
+
update_record: ['Update Record'],
|
|
686
|
+
notification: ['send_notification', 'send_email', 'Send Notification', 'Send Email'],
|
|
687
|
+
field_update: ['set_field_values', 'Set Field Values'],
|
|
688
|
+
wait: ['wait_for', 'Wait For Duration', 'Wait'],
|
|
689
|
+
approval: ['ask_for_approval', 'create_approval', 'Ask for Approval'],
|
|
690
|
+
};
|
|
691
|
+
|
|
490
692
|
async function addActionViaGraphQL(
|
|
491
693
|
client: any,
|
|
492
694
|
flowId: string,
|
|
@@ -499,7 +701,7 @@ async function addActionViaGraphQL(
|
|
|
499
701
|
): Promise<{ success: boolean; actionId?: string; steps?: any; error?: string }> {
|
|
500
702
|
const steps: any = {};
|
|
501
703
|
|
|
502
|
-
// Dynamically look up action definition in sys_hub_action_type_snapshot
|
|
704
|
+
// Dynamically look up action definition in sys_hub_action_type_snapshot and sys_hub_action_type_definition
|
|
503
705
|
// Prefer global/core actions over spoke-specific ones (e.g. core "Update Record" vs spoke-specific "Update Record")
|
|
504
706
|
const snapshotFields = 'sys_id,internal_name,name,sys_scope,sys_package';
|
|
505
707
|
let actionDefId: string | null = null;
|
|
@@ -527,41 +729,66 @@ async function addActionViaGraphQL(
|
|
|
527
729
|
return candidates[0];
|
|
528
730
|
};
|
|
529
731
|
|
|
530
|
-
for
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
732
|
+
// Helper: search a table for action definitions by exact match and LIKE
|
|
733
|
+
const searchTable = async (tableName: string, searchTerms: string[]): Promise<void> => {
|
|
734
|
+
for (var si = 0; si < searchTerms.length && !actionDefId; si++) {
|
|
735
|
+
var term = searchTerms[si];
|
|
736
|
+
// Exact match on internal_name and name
|
|
737
|
+
for (const field of ['internal_name', 'name']) {
|
|
738
|
+
if (actionDefId) break;
|
|
739
|
+
try {
|
|
740
|
+
const resp = await client.get('/api/now/table/' + tableName, {
|
|
741
|
+
params: { sysparm_query: field + '=' + term, sysparm_fields: snapshotFields, sysparm_limit: 10 }
|
|
742
|
+
});
|
|
743
|
+
const results = resp.data.result || [];
|
|
744
|
+
if (results.length > 1) {
|
|
745
|
+
steps.def_lookup_candidates = results.map((r: any) => ({ sys_id: r.sys_id, internal_name: str(r.internal_name), name: str(r.name), scope: str(r.sys_scope), package: str(r.sys_package) }));
|
|
746
|
+
}
|
|
747
|
+
const found = pickBest(results);
|
|
748
|
+
if (found?.sys_id) {
|
|
749
|
+
actionDefId = found.sys_id;
|
|
750
|
+
steps.def_lookup = { id: found.sys_id, internal_name: str(found.internal_name), name: str(found.name), scope: str(found.sys_scope), package: str(found.sys_package), matched: tableName + ':' + field + '=' + term };
|
|
751
|
+
}
|
|
752
|
+
} catch (_) {}
|
|
539
753
|
}
|
|
540
|
-
|
|
541
|
-
if (
|
|
542
|
-
|
|
543
|
-
|
|
754
|
+
// LIKE search
|
|
755
|
+
if (!actionDefId) {
|
|
756
|
+
try {
|
|
757
|
+
const resp = await client.get('/api/now/table/' + tableName, {
|
|
758
|
+
params: {
|
|
759
|
+
sysparm_query: 'internal_nameLIKE' + term + '^ORnameLIKE' + term,
|
|
760
|
+
sysparm_fields: snapshotFields, sysparm_limit: 10
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
const results = resp.data.result || [];
|
|
764
|
+
if (results.length > 0 && !steps.def_lookup_fallback_candidates) {
|
|
765
|
+
steps.def_lookup_fallback_candidates = results.map((r: any) => ({ sys_id: r.sys_id, internal_name: str(r.internal_name), name: str(r.name), scope: str(r.sys_scope), package: str(r.sys_package) }));
|
|
766
|
+
}
|
|
767
|
+
const found = pickBest(results);
|
|
768
|
+
if (found?.sys_id) {
|
|
769
|
+
actionDefId = found.sys_id;
|
|
770
|
+
steps.def_lookup = { id: found.sys_id, internal_name: str(found.internal_name), name: str(found.name), scope: str(found.sys_scope), package: str(found.sys_package), matched: tableName + ':LIKE ' + term };
|
|
771
|
+
}
|
|
772
|
+
} catch (_) {}
|
|
544
773
|
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
|
|
777
|
+
// Build search terms: original actionType + any alias variations
|
|
778
|
+
var searchTerms = [actionType];
|
|
779
|
+
var aliases = ACTION_TYPE_ALIASES[actionType.toLowerCase()];
|
|
780
|
+
if (aliases) searchTerms = searchTerms.concat(aliases);
|
|
781
|
+
|
|
782
|
+
// Search 1: sys_hub_action_type_snapshot (published action snapshots)
|
|
783
|
+
await searchTable('sys_hub_action_type_snapshot', searchTerms);
|
|
784
|
+
|
|
785
|
+
// Search 2: sys_hub_action_type_definition (action definitions — includes built-in/native actions)
|
|
547
786
|
if (!actionDefId) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
params: {
|
|
551
|
-
sysparm_query: 'internal_nameLIKE' + actionType + '^ORnameLIKE' + actionType,
|
|
552
|
-
sysparm_fields: snapshotFields, sysparm_limit: 10
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
const results = resp.data.result || [];
|
|
556
|
-
steps.def_lookup_fallback_candidates = results.map((r: any) => ({ sys_id: r.sys_id, internal_name: str(r.internal_name), name: str(r.name), scope: str(r.sys_scope), package: str(r.sys_package) }));
|
|
557
|
-
const found = pickBest(results);
|
|
558
|
-
if (found?.sys_id) {
|
|
559
|
-
actionDefId = found.sys_id;
|
|
560
|
-
steps.def_lookup = { id: found.sys_id, internal_name: str(found.internal_name), name: str(found.name), scope: str(found.sys_scope), package: str(found.sys_package), matched: 'LIKE ' + actionType };
|
|
561
|
-
}
|
|
562
|
-
} catch (_) {}
|
|
787
|
+
steps.snapshot_not_found = true;
|
|
788
|
+
await searchTable('sys_hub_action_type_definition', searchTerms);
|
|
563
789
|
}
|
|
564
|
-
|
|
790
|
+
|
|
791
|
+
if (!actionDefId) return { success: false, error: 'Action definition not found for: ' + actionType + ' (searched snapshot + definition tables with terms: ' + searchTerms.join(', ') + ')', steps };
|
|
565
792
|
|
|
566
793
|
// Build full input objects with parameter definitions (matching UI format)
|
|
567
794
|
const inputResult = await buildActionInputsForInsert(client, actionDefId, inputs);
|
|
@@ -1151,8 +1378,7 @@ export const toolDefinition: MCPToolDefinition = {
|
|
|
1151
1378
|
},
|
|
1152
1379
|
action_type: {
|
|
1153
1380
|
type: 'string',
|
|
1154
|
-
|
|
1155
|
-
description: 'Action type to add (for add_action)',
|
|
1381
|
+
description: 'Action type to add (for add_action). Looked up dynamically by internal_name or name in sys_hub_action_type_snapshot and sys_hub_action_type_definition. Common short names: log, script, create_record, update_record, notification, field_update, wait, approval. You can also use the exact ServiceNow internal name (e.g. "sn_fd.script_step", "global.update_record") or display name (e.g. "Run Script", "Update Record").',
|
|
1156
1382
|
default: 'log'
|
|
1157
1383
|
},
|
|
1158
1384
|
action_name: {
|