snow-flow-test 10.0.1-test.183 → 10.0.1-test.185

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.183",
3
+ "version": "10.0.1-test.185",
4
4
  "name": "snow-flow-test",
5
5
  "description": "Snow-Flow Test - ServiceNow Multi-Agent Development Framework",
6
6
  "license": "Elastic-2.0",
@@ -1323,58 +1323,81 @@ function transformConditionToDataPills(conditionValue: string, dataPillBase: str
1323
1323
  * Build labelCache entries for field-level data pills used in flow logic conditions.
1324
1324
  *
1325
1325
  * Each field referenced in the condition needs a labelCache entry so the Flow Designer UI
1326
- * can display the data pill correctly. Also registers the record-level parent pill.
1326
+ * can display the data pill correctly. Queries sys_dictionary for actual field types/labels.
1327
1327
  *
1328
- * Example for "category=software":
1329
- * - Record pill: { name: "Created or Updated_1.current", type: "reference", reference: "incident" }
1330
- * - Field pill: { name: "Created or Updated_1.current.category", type: "string" }
1328
+ * The UI only sends field-level pills (NOT a record-level parent pill).
1329
+ * Each entry includes parent_table_name and column_name for the UI to resolve the field.
1330
+ *
1331
+ * Example for "category=inquiry" on incident table:
1332
+ * - { name: "Created or Updated_1.current.category", type: "choice", parent_table_name: "incident", column_name: "category" }
1331
1333
  */
1332
- function buildConditionLabelCache(
1334
+ async function buildConditionLabelCache(
1335
+ client: any,
1333
1336
  conditionValue: string,
1334
1337
  dataPillBase: string,
1335
1338
  triggerName: string,
1336
1339
  table: string,
1337
1340
  tableLabel: string,
1338
1341
  logicUiId: string
1339
- ): any[] {
1342
+ ): Promise<any[]> {
1340
1343
  if (!dataPillBase) return [];
1341
1344
 
1342
1345
  var clauses = parseEncodedQuery(conditionValue);
1343
- var entries: any[] = [];
1344
- var seen: Record<string, boolean> = {};
1346
+ if (clauses.length === 0) return [];
1345
1347
 
1346
- // Register the record-level parent pill (always needed as context)
1347
- entries.push({
1348
- name: dataPillBase,
1349
- label: 'Trigger - Record ' + triggerName + '\u27a1' + tableLabel + ' Record',
1350
- reference: table,
1351
- reference_display: tableLabel,
1352
- type: 'reference',
1353
- base_type: 'reference',
1354
- attributes: '',
1355
- usedInstances: [{ uiUniqueIdentifier: logicUiId, inputName: 'condition' }],
1356
- choices: {}
1357
- });
1358
- seen[dataPillBase] = true;
1359
-
1360
- // Register each field-level pill
1348
+ // Collect unique field names
1349
+ var uniqueFields: string[] = [];
1350
+ var seen: Record<string, boolean> = {};
1361
1351
  for (var i = 0; i < clauses.length; i++) {
1362
1352
  var field = clauses[i].field;
1363
- if (!field) continue;
1364
- var pillName = dataPillBase + '.' + field;
1365
- if (seen[pillName]) continue;
1366
- seen[pillName] = true;
1353
+ if (field && !seen[field]) {
1354
+ seen[field] = true;
1355
+ uniqueFields.push(field);
1356
+ }
1357
+ }
1358
+ if (uniqueFields.length === 0) return [];
1359
+
1360
+ // Batch-query sys_dictionary for field metadata (type, label)
1361
+ var fieldMeta: Record<string, { type: string; label: string }> = {};
1362
+ try {
1363
+ var dictResp = await client.get('/api/now/table/sys_dictionary', {
1364
+ params: {
1365
+ sysparm_query: 'name=' + table + '^elementIN' + uniqueFields.join(','),
1366
+ sysparm_fields: 'element,column_label,internal_type',
1367
+ sysparm_display_value: 'false',
1368
+ sysparm_limit: uniqueFields.length + 5
1369
+ }
1370
+ });
1371
+ var dictResults = dictResp.data.result || [];
1372
+ for (var d = 0; d < dictResults.length; d++) {
1373
+ var rec = dictResults[d];
1374
+ var elName = str(rec.element);
1375
+ var intType = str(rec.internal_type?.value || rec.internal_type || 'string');
1376
+ var colLabel = str(rec.column_label);
1377
+ if (elName) fieldMeta[elName] = { type: intType, label: colLabel };
1378
+ }
1379
+ } catch (_) {
1380
+ // Fallback: use "string" type and generated labels if dictionary lookup fails
1381
+ }
1367
1382
 
1368
- var fieldLabel = field.replace(/_/g, ' ').replace(/\b\w/g, function (c: string) { return c.toUpperCase(); });
1383
+ // Build field-level labelCache entries (no record-level parent UI doesn't send one)
1384
+ var entries: any[] = [];
1385
+ for (var j = 0; j < uniqueFields.length; j++) {
1386
+ var f = uniqueFields[j];
1387
+ var meta = fieldMeta[f];
1388
+ var fType = meta ? meta.type : 'string';
1389
+ var fLabel = meta ? meta.label : f.replace(/_/g, ' ').replace(/\b\w/g, function (c: string) { return c.toUpperCase(); });
1390
+ var pillName = dataPillBase + '.' + f;
1369
1391
 
1370
1392
  entries.push({
1371
1393
  name: pillName,
1372
- label: 'Trigger - Record ' + triggerName + '\u27a1' + tableLabel + ' Record\u27a1' + fieldLabel,
1394
+ label: 'Trigger - Record ' + triggerName + '\u27a1' + tableLabel + ' Record\u27a1' + fLabel,
1373
1395
  reference: '',
1374
- reference_display: '',
1375
- type: 'string',
1376
- base_type: 'string',
1377
- attributes: '',
1396
+ reference_display: fLabel,
1397
+ type: fType,
1398
+ base_type: fType,
1399
+ parent_table_name: table,
1400
+ column_name: f,
1378
1401
  usedInstances: [{ uiUniqueIdentifier: logicUiId, inputName: 'condition' }],
1379
1402
  choices: {}
1380
1403
  });
@@ -1537,22 +1560,79 @@ async function transformActionInputsForRecordAction(
1537
1560
  // ── 4. Build labelCache entries for data pills ────────────────────
1538
1561
  if (dataPillBase && usedInstances.length > 0) {
1539
1562
  var tableRef = triggerInfo.tableRef || triggerInfo.table || '';
1540
- var tableLabel = triggerInfo.tableLabel || '';
1563
+ var tblLabel = triggerInfo.tableLabel || '';
1541
1564
 
1542
- // Record-level data pill entry
1565
+ // Record-level data pill entry (for the `record` input — selecting the whole record)
1543
1566
  labelCacheEntries.push({
1544
1567
  name: dataPillBase,
1545
- label: 'Trigger - Record ' + triggerInfo.triggerName + '\u27a1' + tableLabel + ' Record',
1568
+ label: 'Trigger - Record ' + triggerInfo.triggerName + '\u27a1' + tblLabel + ' Record',
1546
1569
  reference: tableRef,
1547
- reference_display: tableLabel,
1570
+ reference_display: tblLabel,
1548
1571
  type: 'reference',
1549
1572
  base_type: 'reference',
1550
- attributes: '',
1573
+ parent_table_name: tableRef,
1574
+ column_name: '',
1551
1575
  usedInstances: usedInstances,
1552
1576
  choices: {}
1553
1577
  });
1554
1578
 
1555
- steps.label_cache = { count: labelCacheEntries.length, pills: [dataPillBase], usedInstances: usedInstances.length };
1579
+ // Field-level data pill entries for any field references in the `values` string
1580
+ var valuesStr = '';
1581
+ var valuesInp = actionInputs.find(function (inp: any) { return inp.name === 'values'; });
1582
+ if (valuesInp) valuesStr = valuesInp.value?.value || '';
1583
+
1584
+ if (valuesStr && valuesStr.includes('{{')) {
1585
+ // Extract field-level pills from values like "assigned_to={{dataPillBase.assigned_to}}"
1586
+ var pillRegex = /\{\{([^}]+)\}\}/g;
1587
+ var pillMatch;
1588
+ var seenPills: Record<string, boolean> = {};
1589
+ seenPills[dataPillBase] = true;
1590
+
1591
+ while ((pillMatch = pillRegex.exec(valuesStr)) !== null) {
1592
+ var fullPillName = pillMatch[1];
1593
+ if (seenPills[fullPillName]) continue;
1594
+ seenPills[fullPillName] = true;
1595
+
1596
+ // Extract field name from pill (e.g. "Created or Updated_1.current.assigned_to" → "assigned_to")
1597
+ var dotParts = fullPillName.split('.');
1598
+ var fieldCol = dotParts.length > 2 ? dotParts[dotParts.length - 1] : '';
1599
+
1600
+ if (fieldCol) {
1601
+ // Look up field metadata from sys_dictionary
1602
+ var fMeta: { type: string; label: string } = { type: 'string', label: fieldCol.replace(/_/g, ' ').replace(/\b\w/g, function (c: string) { return c.toUpperCase(); }) };
1603
+ try {
1604
+ var dictResp = await client.get('/api/now/table/sys_dictionary', {
1605
+ params: {
1606
+ sysparm_query: 'name=' + tableRef + '^element=' + fieldCol,
1607
+ sysparm_fields: 'element,column_label,internal_type',
1608
+ sysparm_display_value: 'false',
1609
+ sysparm_limit: 1
1610
+ }
1611
+ });
1612
+ var dictRec = dictResp.data.result?.[0];
1613
+ if (dictRec) {
1614
+ fMeta.type = str(dictRec.internal_type?.value || dictRec.internal_type || 'string');
1615
+ fMeta.label = str(dictRec.column_label) || fMeta.label;
1616
+ }
1617
+ } catch (_) {}
1618
+
1619
+ labelCacheEntries.push({
1620
+ name: fullPillName,
1621
+ label: 'Trigger - Record ' + triggerInfo.triggerName + '\u27a1' + tblLabel + ' Record\u27a1' + fMeta.label,
1622
+ reference: '',
1623
+ reference_display: fMeta.label,
1624
+ type: fMeta.type,
1625
+ base_type: fMeta.type,
1626
+ parent_table_name: tableRef,
1627
+ column_name: fieldCol,
1628
+ usedInstances: [{ uiUniqueIdentifier: uuid, inputName: fieldCol }],
1629
+ choices: {}
1630
+ });
1631
+ }
1632
+ }
1633
+ }
1634
+
1635
+ steps.label_cache = { count: labelCacheEntries.length, pills: labelCacheEntries.map(function (e: any) { return e.name; }), usedInstances: usedInstances.length };
1556
1636
  }
1557
1637
 
1558
1638
  return { inputs: actionInputs, labelCacheEntries, steps };
@@ -1710,8 +1790,8 @@ async function addFlowLogicViaGraphQL(
1710
1790
  if (needsConditionUpdate && conditionTriggerInfo) {
1711
1791
  var dataPillBase = conditionTriggerInfo.dataPillBase;
1712
1792
  var transformedCondition = transformConditionToDataPills(rawCondition, dataPillBase);
1713
- var labelCacheEntries = buildConditionLabelCache(
1714
- rawCondition, dataPillBase, conditionTriggerInfo.triggerName,
1793
+ var labelCacheEntries = await buildConditionLabelCache(
1794
+ client, rawCondition, dataPillBase, conditionTriggerInfo.triggerName,
1715
1795
  conditionTriggerInfo.tableRef, conditionTriggerInfo.tableLabel, returnedUuid
1716
1796
  );
1717
1797
 
@@ -1728,8 +1808,13 @@ async function addFlowLogicViaGraphQL(
1728
1808
  type: 'flowlogic',
1729
1809
  inputs: [{
1730
1810
  name: 'condition',
1811
+ displayValue: { value: '' },
1731
1812
  value: { schemaless: false, schemalessValue: '', value: transformedCondition }
1732
- }]
1813
+ }],
1814
+ flowLogicDefinition: {
1815
+ inputs: [{ name: 'condition_name', attributes: 'use_basic_input=true,' }],
1816
+ variables: 'undefined'
1817
+ }
1733
1818
  }]
1734
1819
  }
1735
1820
  };