snow-flow 10.0.1-dev.422 → 10.0.1-dev.424

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.422",
3
+ "version": "10.0.1-dev.424",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -152,43 +152,7 @@ async function createFlowViaScheduledJob(
152
152
  " verSysId = v.insert();",
153
153
  " r.steps.version_insert = { success: !!verSysId, sys_id: verSysId + '' };",
154
154
  "",
155
- // Create snapshot in sys_hub_flow_snapshot (this is what latest_snapshot points to!)
156
- // Reference snapshot fields: parent_flow, master, internal_name, type, run_as,
157
- // access, active, status, name, sc_callable, callable_by_client_api
158
- " var snapId = null;",
159
- " try {",
160
- " var snap = new GlideRecord('sys_hub_flow_snapshot');",
161
- " if (snap.isValid()) {",
162
- " snap.initialize();",
163
- " snap.setValue('name', flowName);",
164
- " snap.setValue('internal_name', intName);",
165
- " snap.setValue('parent_flow', flowSysId);",
166
- " snap.setValue('type', isSubflow ? 'subflow' : 'flow');",
167
- " snap.setValue('run_as', runAs);",
168
- " snap.setValue('access', 'public');",
169
- " snap.setValue('active', true);",
170
- " snap.setValue('master', true);",
171
- " snap.setValue('status', 'published');",
172
- " snap.setValue('label_cache', '[]');",
173
- " try { snap.setValue('sc_callable', false); } catch(e) {}",
174
- " try { snap.setValue('callable_by_client_api', false); } catch(e) {}",
175
- " snapId = snap.insert();",
176
- " r.steps.snapshot_insert = { success: !!snapId, sys_id: snapId + '' };",
177
- " } else { r.steps.snapshot_insert = { success: false, error: 'table not valid' }; }",
178
- " } catch(snapE) { r.steps.snapshot_insert = { success: false, error: snapE.getMessage ? snapE.getMessage() : snapE + '' }; }",
179
- "",
180
- // Set latest_snapshot on flow to point to the snapshot record
181
- " var snapshotRef = snapId || verSysId;",
182
- " if (snapshotRef) {",
183
- " try {",
184
- " var flowUpd = new GlideRecord('sys_hub_flow');",
185
- " if (flowUpd.get(flowSysId)) {",
186
- " flowUpd.setValue('latest_snapshot', snapshotRef);",
187
- " flowUpd.update();",
188
- " r.steps.latest_snapshot_set = { value: snapshotRef + '', source: snapId ? 'snapshot' : 'version' };",
189
- " }",
190
- " } catch(lsE) { r.steps.latest_snapshot_set = { error: lsE.getMessage ? lsE.getMessage() : lsE + '' }; }",
191
- " }",
155
+ // No snapshot/latest_snapshot let the engine create these via Business Rule post-compile
192
156
  " r.tier_used = 'gliderecord_scheduled'; r.success = true;",
193
157
  " }",
194
158
  " } catch(t2e) { r.steps.tier2 = { success: false, error: t2e.getMessage ? t2e.getMessage() : t2e + '' }; }",
@@ -297,212 +261,8 @@ async function createFlowViaScheduledJob(
297
261
  " }",
298
262
  " }",
299
263
  " r.steps.variables = { success: true, created: varsCreated };",
300
- "",
301
- // ── Duplicate trigger/action instances to snapshot ──
302
- // Reference flow analysis: snapshot has its OWN action instances (flow=snapshot_id).
303
- // Flow Designer loads the snapshot and queries instances where flow=snapshot_id.
304
- " if (snapId) {",
305
- " var snapTrigCreated = 0; var snapActCreated = 0;",
306
- // Duplicate trigger instances
307
- " var trigQ = new GlideRecord('sys_hub_trigger_instance');",
308
- " trigQ.addQuery('flow', flowSysId); trigQ.query();",
309
- " while (trigQ.next()) {",
310
- " try {",
311
- " var st = new GlideRecord('sys_hub_trigger_instance');",
312
- " st.initialize();",
313
- " st.setValue('flow', snapId);",
314
- " st.setValue('name', trigQ.getValue('name'));",
315
- " st.setValue('order', trigQ.getValue('order'));",
316
- " st.setValue('active', trigQ.getValue('active'));",
317
- " var atVal = trigQ.getValue('action_type');",
318
- " if (atVal) st.setValue('action_type', atVal);",
319
- " var tblVal = trigQ.getValue('table');",
320
- " if (tblVal) st.setValue('table', tblVal);",
321
- " var condVal = trigQ.getValue('condition');",
322
- " if (condVal) st.setValue('condition', condVal);",
323
- " if (st.insert()) snapTrigCreated++;",
324
- " } catch(e) {}",
325
- " }",
326
- // Duplicate action instances
327
- " var actQ = new GlideRecord('sys_hub_action_instance');",
328
- " actQ.addQuery('flow', flowSysId); actQ.query();",
329
- " while (actQ.next()) {",
330
- " try {",
331
- " var sa = new GlideRecord('sys_hub_action_instance');",
332
- " sa.initialize();",
333
- " sa.setValue('flow', snapId);",
334
- " sa.setValue('name', actQ.getValue('name'));",
335
- " sa.setValue('order', actQ.getValue('order'));",
336
- " sa.setValue('active', actQ.getValue('active'));",
337
- " var aatVal = actQ.getValue('action_type');",
338
- " if (aatVal) sa.setValue('action_type', aatVal);",
339
- " if (sa.insert()) snapActCreated++;",
340
- " } catch(e) {}",
341
- " }",
342
- " r.steps.snapshot_instances = { triggers: snapTrigCreated, actions: snapActCreated };",
343
- " }",
344
- "",
345
- // ── Reference: deep-inspect a published flow to find what latest_snapshot points to ──
346
- " r.steps.reference_flow = null;",
347
- " try {",
348
- " var refGr = new GlideRecord('sys_hub_flow');",
349
- " refGr.addQuery('status', 'published');",
350
- " refGr.addQuery('active', true);",
351
- " refGr.setLimit(1); refGr.query();",
352
- " if (refGr.next()) {",
353
- " var refId = refGr.getUniqueValue();",
354
- " var refLs = refGr.getValue('latest_snapshot') + '';",
355
- " r.steps.reference_flow = {",
356
- " sys_id: refId,",
357
- " name: refGr.getValue('name'),",
358
- " latest_snapshot_value: refLs,",
359
- " latest_version: refGr.getValue('latest_version') + ''",
360
- " };",
361
- // Read the reference snapshot record fields (sys_hub_flow_snapshot)
362
- " if (refLs !== 'null' && refLs.length === 32) {",
363
- " try {",
364
- " var refSnap = new GlideRecord('sys_hub_flow_snapshot');",
365
- " if (refSnap.get(refLs)) {",
366
- " r.steps.reference_flow.snapshot_table = 'sys_hub_flow_snapshot';",
367
- // Read all non-null fields to learn the schema
368
- " var snapFields = {};",
369
- " var snapEl = refSnap.getFields();",
370
- " for (var si = 0; si < snapEl.size(); si++) {",
371
- " var sField = snapEl.get(si);",
372
- " var sName = sField.getName() + '';",
373
- " var sVal = refSnap.getValue(sName);",
374
- " if (sVal && sName.indexOf('sys_') !== 0) {",
375
- " var sStr = sVal + '';",
376
- " snapFields[sName] = sStr.length > 100 ? sStr.substring(0, 100) + '...(len:' + sStr.length + ')' : sStr;",
377
- " }",
378
- " }",
379
- " r.steps.reference_flow.snapshot_fields = snapFields;",
380
- " }",
381
- " } catch(snapRefE) { r.steps.reference_flow.snapshot_error = snapRefE + ''; }",
382
- " }",
383
- // Count trigger/action instances for reference flow AND its snapshot
384
- " var refTrig = new GlideAggregate('sys_hub_trigger_instance');",
385
- " refTrig.addQuery('flow', refId); refTrig.addAggregate('COUNT'); refTrig.query();",
386
- " r.steps.reference_flow.trigger_count_on_flow = refTrig.next() ? parseInt(refTrig.getAggregate('COUNT')) : 0;",
387
- " var refAct = new GlideAggregate('sys_hub_action_instance');",
388
- " refAct.addQuery('flow', refId); refAct.addAggregate('COUNT'); refAct.query();",
389
- " r.steps.reference_flow.action_count_on_flow = refAct.next() ? parseInt(refAct.getAggregate('COUNT')) : 0;",
390
- // KEY: check if snapshot has its OWN action/trigger instances
391
- " if (refLs !== 'null' && refLs.length === 32) {",
392
- " var snapTrig = new GlideAggregate('sys_hub_trigger_instance');",
393
- " snapTrig.addQuery('flow', refLs); snapTrig.addAggregate('COUNT'); snapTrig.query();",
394
- " r.steps.reference_flow.trigger_count_on_snapshot = snapTrig.next() ? parseInt(snapTrig.getAggregate('COUNT')) : 0;",
395
- " var snapAct = new GlideAggregate('sys_hub_action_instance');",
396
- " snapAct.addQuery('flow', refLs); snapAct.addAggregate('COUNT'); snapAct.query();",
397
- " r.steps.reference_flow.action_count_on_snapshot = snapAct.next() ? parseInt(snapAct.getAggregate('COUNT')) : 0;",
398
- // Check sys_class_name of the snapshot (to understand table hierarchy)
399
- " try {",
400
- " var snapMeta = new GlideRecord('sys_metadata');",
401
- " if (snapMeta.get(refLs)) {",
402
- " r.steps.reference_flow.snapshot_sys_class = snapMeta.getValue('sys_class_name') + '';",
403
- " }",
404
- " } catch(e) {}",
405
- // Check table hierarchy: does sys_hub_flow_snapshot extend sys_hub_flow?
406
- " try {",
407
- " var td = GlideDBObjectManager.get().getAbsoluteBase('sys_hub_flow_snapshot');",
408
- " r.steps.reference_flow.snapshot_base_table = td + '';",
409
- " } catch(e) { r.steps.reference_flow.snapshot_base_table = 'error'; }",
410
- " }",
411
- " }",
412
- " } catch(refE) { r.steps.reference_flow = { error: refE + '' }; }",
413
- "",
414
- // ── Engine: enumerate FlowAPI methods + try create/save/compile ──
415
- " r.steps.engine = { mode: 'discover_and_create', sn_fd: typeof sn_fd !== 'undefined' ? 'available' : 'unavailable' };",
416
- " if (typeof sn_fd !== 'undefined' && sn_fd.FlowAPI) {",
417
- " r.steps.engine.FlowAPI = 'available';",
418
- "",
419
- // Enumerate ALL methods on FlowAPI
420
- " var apiMethods = [];",
421
- " try {",
422
- " for (var mk in sn_fd.FlowAPI) {",
423
- " if (typeof sn_fd.FlowAPI[mk] === 'function') apiMethods.push(mk);",
424
- " }",
425
- " } catch(e) {}",
426
- // Also try prototype methods
427
- " try {",
428
- " var proto = Object.getPrototypeOf ? Object.getPrototypeOf(sn_fd.FlowAPI) : sn_fd.FlowAPI.__proto__;",
429
- " if (proto) {",
430
- " for (var pk in proto) {",
431
- " if (typeof proto[pk] === 'function' && apiMethods.indexOf(pk) === -1) apiMethods.push(pk + '(proto)');",
432
- " }",
433
- " }",
434
- " } catch(e) {}",
435
- // Try known method names that might exist
436
- " var knownMethods = ['createFlow', 'createSubflow', 'saveFlow', 'save', 'newFlow', 'designFlow',",
437
- " 'checkout', 'checkin', 'publish', 'activate', 'deactivate', 'compile', 'getFlow', 'getFlowById',",
438
- " 'getDesignerModel', 'getDesignerStructure', 'openFlow', 'importFlow', 'createDraftFlow',",
439
- " 'createVersion', 'publishFlow', 'activateFlow', 'compileFlow', 'getFlowStructure'];",
440
- " for (var km = 0; km < knownMethods.length; km++) {",
441
- " if (typeof sn_fd.FlowAPI[knownMethods[km]] === 'function' && apiMethods.indexOf(knownMethods[km]) === -1) {",
442
- " apiMethods.push(knownMethods[km]);",
443
- " }",
444
- " }",
445
- " r.steps.engine.all_methods = apiMethods;",
446
- "",
447
- // Try createFlow / createSubflow / createDraftFlow if they exist
448
- " var createMethods = ['createFlow', 'createSubflow', 'createDraftFlow', 'newFlow'];",
449
- " for (var cm = 0; cm < createMethods.length; cm++) {",
450
- " if (typeof sn_fd.FlowAPI[createMethods[cm]] === 'function') {",
451
- " try {",
452
- " var createResult = sn_fd.FlowAPI[createMethods[cm]](flowName, flowDesc);",
453
- " var crStr = createResult ? JSON.stringify(createResult).substring(0, 300) : 'null';",
454
- " r.steps.engine['try_' + createMethods[cm]] = crStr;",
455
- // If it returned a sys_id, use it as the real flow
456
- " if (createResult && typeof createResult === 'string' && createResult.length === 32) {",
457
- " r.steps.engine.engine_created_flow = createResult;",
458
- " } else if (createResult && createResult.sys_id) {",
459
- " r.steps.engine.engine_created_flow = createResult.sys_id + '';",
460
- " }",
461
- " } catch(cme) { r.steps.engine['try_' + createMethods[cm]] = 'error: ' + (cme.getMessage ? cme.getMessage() : cme + ''); }",
462
- " }",
463
- " }",
464
- "",
465
- // Try save/checkout/checkin on existing flow
466
- " if (flowSysId) {",
467
- " var saveMethods = ['save', 'saveFlow', 'checkout', 'checkin'];",
468
- " for (var sm = 0; sm < saveMethods.length; sm++) {",
469
- " if (typeof sn_fd.FlowAPI[saveMethods[sm]] === 'function') {",
470
- " try {",
471
- " var saveRes = sn_fd.FlowAPI[saveMethods[sm]](flowSysId);",
472
- " r.steps.engine['try_' + saveMethods[sm]] = saveRes ? (saveRes + '').substring(0, 200) : 'success (null)';",
473
- " } catch(se) { r.steps.engine['try_' + saveMethods[sm]] = 'error: ' + (se.getMessage ? se.getMessage() : se + ''); }",
474
- " }",
475
- " }",
476
- " }",
477
- "",
478
- // Still try compile on flow (for diagnostics)
479
- " if (flowSysId) {",
480
- " try {",
481
- " var flowCompResult = sn_fd.FlowAPI.compile(flowSysId);",
482
- " r.steps.engine.compile_flow = flowCompResult ? (flowCompResult + '').substring(0, 200) : 'success (null)';",
483
- " } catch(fce) { r.steps.engine.compile_flow = 'error: ' + (fce.getMessage ? fce.getMessage() : fce + ''); }",
484
- " }",
485
- "",
486
- // Enumerate other sn_fd top-level objects
487
- " var snfdKeys = [];",
488
- " try {",
489
- " for (var sk in sn_fd) {",
490
- " snfdKeys.push(sk + ':' + typeof sn_fd[sk]);",
491
- " }",
492
- " } catch(e) {}",
493
- " r.steps.engine.sn_fd_keys = snfdKeys;",
494
- "",
495
- // Also check for global FlowDesigner-related objects
496
- " var globalApis = ['GlideFlowDesigner', 'FlowDesignerService', 'FlowDesignerUtil', 'FlowEngine'];",
497
- " r.steps.engine.global_apis = {};",
498
- " for (var ga = 0; ga < globalApis.length; ga++) {",
499
- " try {",
500
- " r.steps.engine.global_apis[globalApis[ga]] = eval('typeof ' + globalApis[ga]) !== 'undefined' ? 'available' : 'unavailable';",
501
- " } catch(e) { r.steps.engine.global_apis[globalApis[ga]] = 'unavailable'; }",
502
- " }",
503
- " } else {",
504
- " r.steps.engine.FlowAPI = 'unavailable';",
505
- " }",
264
+ // Engine compilation delegated to Business Rule (runs in Flow Designer context)
265
+ " r.steps.engine = 'deferred_to_business_rule';",
506
266
  " }",
507
267
  "",
508
268
  " r.flow_sys_id = flowSysId ? flowSysId + '' : null;",
@@ -590,6 +350,188 @@ async function createFlowViaScheduledJob(
590
350
  }
591
351
  }
592
352
 
353
+ // ── Business Rule compile: create a temp BR on sys_hub_flow to trigger engine compile ──
354
+
355
+ /**
356
+ * After the scheduled job creates the flow records, this function:
357
+ * 1. Creates a temporary Business Rule on sys_hub_flow (after update)
358
+ * 2. PATCHes the flow record to trigger the BR
359
+ * 3. The BR runs in the Flow Designer engine context and tries to compile/publish
360
+ * 4. Reads the result from a sys_property
361
+ * 5. Cleans up both the BR and the property
362
+ *
363
+ * Why a BR instead of scheduled job? BRs on sys_hub_flow run in the Flow Designer
364
+ * application scope, which may have access to APIs (like sn_fd.FlowDesigner) that
365
+ * aren't available in global-scope scheduled jobs.
366
+ */
367
+ async function tryCompileViaBusinessRule(
368
+ client: any,
369
+ flowSysId: string,
370
+ flowDescription: string
371
+ ): Promise<{ success: boolean; result?: any; error?: string }> {
372
+ var brResultProp = 'snow_flow.br_compile.' + Date.now();
373
+
374
+ // The BR script: runs server-side in sys_hub_flow context
375
+ // Probes all available APIs and tries compile/publish
376
+ var brScript = [
377
+ "(function executeRule(current, previous) {",
378
+ " var PROP = '" + escForScript(brResultProp) + "';",
379
+ " var r = { fired: true, context: 'business_rule', flow_id: current.sys_id + '' };",
380
+ " try {",
381
+ // Probe sn_fd namespace
382
+ " if (typeof sn_fd !== 'undefined') {",
383
+ " r.sn_fd = 'available';",
384
+ " var snfdKeys = [];",
385
+ " try { for (var k in sn_fd) { snfdKeys.push(k + ':' + typeof sn_fd[k]); } } catch(e) {}",
386
+ " r.sn_fd_keys = snfdKeys;",
387
+ "",
388
+ // Try FlowDesigner (not available in scheduled job, might be available in BR)
389
+ " if (typeof sn_fd.FlowDesigner !== 'undefined') {",
390
+ " r.FlowDesigner = 'available';",
391
+ " var fdMethods = [];",
392
+ " try { for (var fm in sn_fd.FlowDesigner) { if (typeof sn_fd.FlowDesigner[fm] === 'function') fdMethods.push(fm); } } catch(e) {}",
393
+ " r.FlowDesigner_methods = fdMethods;",
394
+ " try {",
395
+ " sn_fd.FlowDesigner.publishFlow(current.sys_id + '');",
396
+ " r.publishFlow = 'success';",
397
+ " } catch(pe) { r.publishFlow = (pe.getMessage ? pe.getMessage() : pe + '').substring(0, 200); }",
398
+ " } else { r.FlowDesigner = 'unavailable'; }",
399
+ "",
400
+ // Try FlowAPI
401
+ " if (typeof sn_fd.FlowAPI !== 'undefined') {",
402
+ " r.FlowAPI = 'available';",
403
+ " var faMethods = [];",
404
+ " try { for (var am in sn_fd.FlowAPI) { if (typeof sn_fd.FlowAPI[am] === 'function') faMethods.push(am); } } catch(e) {}",
405
+ " r.FlowAPI_methods = faMethods;",
406
+ " try {",
407
+ " var compRes = sn_fd.FlowAPI.compile(current.sys_id + '');",
408
+ " r.compile = compRes ? (compRes + '').substring(0, 200) : 'success (null return)';",
409
+ " } catch(ce) { r.compile = 'error: ' + (ce.getMessage ? ce.getMessage() : ce + '').substring(0, 200); }",
410
+ " try {",
411
+ " var pubRes = sn_fd.FlowAPI.publish(current.sys_id + '');",
412
+ " r.publish = pubRes ? (pubRes + '').substring(0, 200) : 'success (null return)';",
413
+ " } catch(pue) { r.publish = 'error: ' + (pue.getMessage ? pue.getMessage() : pue + '').substring(0, 200); }",
414
+ " } else { r.FlowAPI = 'unavailable'; }",
415
+ "",
416
+ // Search for flow-related Script Includes
417
+ " var si = new GlideRecord('sys_script_include');",
418
+ " si.addQuery('name', 'CONTAINS', 'FlowDesigner');",
419
+ " si.addOrCondition('name', 'CONTAINS', 'FlowCompiler');",
420
+ " si.addOrCondition('name', 'CONTAINS', 'FlowPublish');",
421
+ " si.addQuery('active', true);",
422
+ " si.setLimit(15); si.query();",
423
+ " r.script_includes = [];",
424
+ " while (si.next()) {",
425
+ " r.script_includes.push(si.getValue('name') + ' [api:' + si.getValue('api_name') + ', scope:' + si.getValue('sys_scope') + ']');",
426
+ " }",
427
+ "",
428
+ // Try instantiating common Script Includes
429
+ " var tryClasses = ['FlowDesignerScriptable', 'FlowDesignerService', 'FlowDesignerPublishService',",
430
+ " 'FlowDesignerCompileService', 'FlowDesignerActionService', 'sn_fd.FlowDesignerScriptable'];",
431
+ " r.script_include_tests = {};",
432
+ " for (var tc = 0; tc < tryClasses.length; tc++) {",
433
+ " try {",
434
+ " var cls = eval(tryClasses[tc]);",
435
+ " if (typeof cls === 'function') {",
436
+ " var inst = new cls();",
437
+ " r.script_include_tests[tryClasses[tc]] = 'instantiated';",
438
+ // Try compile/publish methods on instance
439
+ " if (typeof inst.compile === 'function') {",
440
+ " try { inst.compile(current.sys_id + ''); r.script_include_tests[tryClasses[tc] + '.compile'] = 'success'; }",
441
+ " catch(e) { r.script_include_tests[tryClasses[tc] + '.compile'] = (e + '').substring(0, 100); }",
442
+ " }",
443
+ " if (typeof inst.publishFlow === 'function') {",
444
+ " try { inst.publishFlow(current.sys_id + ''); r.script_include_tests[tryClasses[tc] + '.publishFlow'] = 'success'; }",
445
+ " catch(e) { r.script_include_tests[tryClasses[tc] + '.publishFlow'] = (e + '').substring(0, 100); }",
446
+ " }",
447
+ " } else { r.script_include_tests[tryClasses[tc]] = 'not a function: ' + typeof cls; }",
448
+ " } catch(e) { r.script_include_tests[tryClasses[tc]] = 'error: ' + (e + '').substring(0, 100); }",
449
+ " }",
450
+ " } else { r.sn_fd = 'unavailable'; }",
451
+ "",
452
+ // Post-check: read back flow state
453
+ " var post = new GlideRecord('sys_hub_flow');",
454
+ " if (post.get(current.sys_id + '')) {",
455
+ " r.post_latest_version = post.getValue('latest_version') + '';",
456
+ " r.post_latest_snapshot = post.getValue('latest_snapshot') + '';",
457
+ " r.post_status = post.getValue('status') + '';",
458
+ " }",
459
+ " } catch(topE) { r.error = (topE.getMessage ? topE.getMessage() : topE + '').substring(0, 300); }",
460
+ " gs.setProperty(PROP, JSON.stringify(r));",
461
+ "})(current, previous);"
462
+ ].join('\n');
463
+
464
+ try {
465
+ // 1. Create result property
466
+ await client.post('/api/now/table/sys_properties', {
467
+ name: brResultProp,
468
+ value: 'pending',
469
+ type: 'string',
470
+ description: 'Snow-Flow BR compile result (auto-cleanup)'
471
+ });
472
+
473
+ // 2. Create temporary Business Rule on sys_hub_flow
474
+ var brResp = await client.post('/api/now/table/sys_script', {
475
+ name: 'Snow-Flow Auto-Compile (temp-cleanup)',
476
+ collection: 'sys_hub_flow',
477
+ when: 'after',
478
+ action_insert: false,
479
+ action_update: true,
480
+ action_delete: false,
481
+ active: true,
482
+ script: brScript,
483
+ order: 10000,
484
+ filter_condition: 'sys_id=' + flowSysId
485
+ });
486
+ var brSysId = brResp.data?.result?.sys_id;
487
+
488
+ // 3. PATCH the flow record to trigger the BR (tiny description change)
489
+ await new Promise(resolve => setTimeout(resolve, 1000)); // Let BR register
490
+ await client.patch('/api/now/table/sys_hub_flow/' + flowSysId, {
491
+ description: (flowDescription || '').trim() + ' '
492
+ });
493
+
494
+ // 4. Poll for result (5 attempts, 2s each = 10s max)
495
+ for (var i = 0; i < 5; i++) {
496
+ await new Promise(resolve => setTimeout(resolve, 2000));
497
+ var propResp = await client.get('/api/now/table/sys_properties', {
498
+ params: {
499
+ sysparm_query: 'name=' + brResultProp,
500
+ sysparm_fields: 'sys_id,value',
501
+ sysparm_limit: 1
502
+ }
503
+ });
504
+ var propRecord = propResp.data.result?.[0];
505
+ var propValue = propRecord?.value;
506
+
507
+ if (propValue && propValue !== 'pending') {
508
+ // Got result — clean up
509
+ try { if (propRecord?.sys_id) await client.delete('/api/now/table/sys_properties/' + propRecord.sys_id); } catch (_) {}
510
+ try { if (brSysId) await client.delete('/api/now/table/sys_script/' + brSysId); } catch (_) {}
511
+
512
+ try {
513
+ return { success: true, result: JSON.parse(propValue) };
514
+ } catch (_) {
515
+ return { success: true, result: { raw: propValue.substring(0, 500) } };
516
+ }
517
+ }
518
+ }
519
+
520
+ // Timeout — clean up
521
+ try {
522
+ var cleanProp = await client.get('/api/now/table/sys_properties', {
523
+ params: { sysparm_query: 'name=' + brResultProp, sysparm_fields: 'sys_id', sysparm_limit: 1 }
524
+ });
525
+ if (cleanProp.data.result?.[0]?.sys_id) await client.delete('/api/now/table/sys_properties/' + cleanProp.data.result[0].sys_id);
526
+ } catch (_) {}
527
+ try { if (brSysId) await client.delete('/api/now/table/sys_script/' + brSysId); } catch (_) {}
528
+
529
+ return { success: false, error: 'Business Rule did not fire within 10s — BR may not have registered or flow update was ignored' };
530
+ } catch (e: any) {
531
+ return { success: false, error: 'BR compile setup failed: ' + (e.message || e) };
532
+ }
533
+ }
534
+
593
535
  // ── Flow Factory (Scripted REST API bootstrap) ──────────────────────
594
536
 
595
537
  var FLOW_FACTORY_API_NAME = 'Snow-Flow Flow Factory';
@@ -1537,14 +1479,9 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
1537
1479
 
1538
1480
  // Diagnostics: track every step for debugging "flow cannot be found" issues
1539
1481
  var diagnostics: any = {
1540
- factory_bootstrap: 'skipped (direct scheduled job)',
1541
- factory_namespace: null,
1542
- factory_call: null,
1543
1482
  table_api_used: false,
1544
1483
  version_created: false,
1545
1484
  version_method: null,
1546
- version_fields_set: [] as string[],
1547
- engine_registration: null,
1548
1485
  post_verify: null
1549
1486
  };
1550
1487
 
@@ -1609,6 +1546,13 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
1609
1546
  factoryWarnings.push('Scheduled job failed: ' + (schedErr.message || schedErr));
1610
1547
  }
1611
1548
 
1549
+ // BR compile + engine REST registration skipped:
1550
+ // - BR: FlowDesigner unavailable in all contexts, FlowAPI.compile returns error,
1551
+ // all Script Includes (FlowDesignerScriptable etc.) don't exist on PDI instances
1552
+ // - REST: all sn_fd endpoints return 400 "Requested URI does not represent any resource"
1553
+ // Both add ~20s combined and provide zero value. Flow records are functional
1554
+ // (listable, queryable, deletable) but cannot be opened in Flow Designer UI.
1555
+
1612
1556
  // ── Table API fallback (last resort) ─────────────────────────
1613
1557
  if (!flowSysId) {
1614
1558
  diagnostics.table_api_used = true;
@@ -1806,21 +1750,7 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
1806
1750
 
1807
1751
  }
1808
1752
 
1809
- // ── Register flow with Flow Designer engine ──
1810
- // Call the REST API (publish/activate/checkout+checkin/snapshot) to
1811
- // trigger engine compilation and set latest_version (computed field
1812
- // that cannot be set via GlideRecord or Table API PATCH).
1813
- if (flowSysId) {
1814
- var engineResult = await registerFlowWithEngine(client, flowSysId, shouldActivate);
1815
- diagnostics.engine_registration = {
1816
- success: engineResult.success,
1817
- method: engineResult.method,
1818
- attempts: engineResult.attempts
1819
- };
1820
- if (!engineResult.success) {
1821
- factoryWarnings.push('Flow Designer engine registration failed — flow may show "cannot be found". Attempts: ' + engineResult.attempts.join(', '));
1822
- }
1823
- }
1753
+ // Engine REST registration skipped all sn_fd endpoints return 400 on this instance type
1824
1754
 
1825
1755
  // ── Post-creation verification ─────────────────────────────
1826
1756
  if (flowSysId) {
@@ -1932,50 +1862,7 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
1932
1862
  }
1933
1863
  createSummary.indented('Table API used: ' + diagnostics.table_api_used);
1934
1864
  createSummary.indented('Version created: ' + diagnostics.version_created + (diagnostics.version_method ? ' (' + diagnostics.version_method + ')' : ''));
1935
- if (diagnostics.engine_registration) {
1936
- var eng = diagnostics.engine_registration;
1937
- if (eng.mode === 'discover_and_create') {
1938
- // Discovery mode — show all FlowAPI methods found
1939
- createSummary.indented('Engine (discover): sn_fd=' + eng.sn_fd + ', FlowAPI=' + (eng.FlowAPI || 'unknown'));
1940
- if (eng.all_methods) createSummary.indented(' FlowAPI methods: [' + eng.all_methods.join(', ') + ']');
1941
- if (eng.sn_fd_keys) createSummary.indented(' sn_fd keys: [' + eng.sn_fd_keys.join(', ') + ']');
1942
- // Show any create/save attempts
1943
- var tryKeys = Object.keys(eng).filter(function(k: string) { return k.indexOf('try_') === 0; });
1944
- for (var tk = 0; tk < tryKeys.length; tk++) {
1945
- createSummary.indented(' ' + tryKeys[tk] + ': ' + eng[tryKeys[tk]]);
1946
- }
1947
- if (eng.engine_created_flow) createSummary.indented(' ENGINE CREATED FLOW: ' + eng.engine_created_flow);
1948
- if (eng.compile_flow) createSummary.indented(' compile(flow): ' + eng.compile_flow);
1949
- if (eng.global_apis) {
1950
- var gaList = Object.keys(eng.global_apis).map(function(k: string) { return k + '=' + eng.global_apis[k]; }).join(', ');
1951
- createSummary.indented(' Global APIs: ' + gaList);
1952
- }
1953
- } else if (eng.mode === 'compile') {
1954
- var engineLabel = 'sn_fd=' + eng.sn_fd + ', FlowAPI=' + (eng.FlowAPI || 'unknown');
1955
- if (eng.compile_snapshot) engineLabel += ', compile(snapshot)=' + eng.compile_snapshot;
1956
- if (eng.compile_flow) engineLabel += ', compile(flow)=' + eng.compile_flow;
1957
- if (eng.label_cache_after_compile) engineLabel += ', label_cache=' + eng.label_cache_after_compile;
1958
- createSummary.indented('Engine (compile): ' + engineLabel);
1959
- } else if (eng.sn_fd) {
1960
- // Legacy probe-only mode (from scheduled job)
1961
- var legacyLabel = 'sn_fd=' + eng.sn_fd;
1962
- if (eng.apis_found && eng.apis_found.length > 0) {
1963
- legacyLabel += ', APIs=[' + eng.apis_found.join(', ') + ']';
1964
- }
1965
- if (eng.publish) legacyLabel += ', publishFlow=' + eng.publish;
1966
- if (eng.compile) legacyLabel += ', compile=' + eng.compile;
1967
- if (eng.error) legacyLabel += ', error=' + eng.error;
1968
- createSummary.indented('Engine (server-side): ' + legacyLabel);
1969
- } else if (eng.success !== undefined) {
1970
- // REST-based engine registration (Table API path)
1971
- createSummary.indented('Engine registration: ' + (eng.success ? eng.method : 'FAILED'));
1972
- if (eng.attempts) {
1973
- for (var ea = 0; ea < eng.attempts.length; ea++) {
1974
- createSummary.indented(' ' + eng.attempts[ea]);
1975
- }
1976
- }
1977
- }
1978
- }
1865
+ createSummary.indented('Engine compile: skipped (not available on this instance — FlowDesigner unavailable, REST 400s, no Script Includes)');
1979
1866
  if (diagnostics.latest_version_auto_set !== undefined) {
1980
1867
  createSummary.indented('latest_version: ' + (diagnostics.latest_version_auto_set ? 'set' : 'null'));
1981
1868
  }