ultravisor 1.0.3 → 1.0.8

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.
Files changed (248) hide show
  1. package/.claude/launch.json +11 -0
  2. package/.claude/ultravisor-dev-config.json +3 -0
  3. package/card-audit.json +1545 -0
  4. package/docs/_sidebar.md +17 -0
  5. package/docs/css/docuserve.css +73 -0
  6. package/docs/features/beacon-authentication.md +209 -0
  7. package/docs/features/beacon-providers.md +1299 -0
  8. package/docs/features/beacons.md +530 -0
  9. package/docs/features/capabilities.md +193 -0
  10. package/docs/features/llm-model-setup.md +505 -0
  11. package/docs/features/llm.md +262 -0
  12. package/docs/features/tasks-content-system.md +110 -0
  13. package/docs/features/tasks-data-transform.md +233 -0
  14. package/docs/features/tasks-extension.md +36 -0
  15. package/docs/features/tasks-file-system.md +203 -0
  16. package/docs/features/tasks-flow-control.md +125 -0
  17. package/docs/features/tasks-http-client.md +119 -0
  18. package/docs/features/tasks-llm.md +118 -0
  19. package/docs/features/tasks-meadow-api.md +163 -0
  20. package/docs/features/tasks-user-interaction.md +49 -0
  21. package/docs/features/tasks.md +14 -0
  22. package/docs/index.html +1 -1
  23. package/docs/retold-catalog.json +1 -1
  24. package/docs/retold-keyword-index.json +17374 -5
  25. package/operation-library/api-data-pipeline.json +143 -0
  26. package/operation-library/beacon-remote-command.json +72 -0
  27. package/operation-library/conditional-file-backup.json +143 -0
  28. package/operation-library/config-processor.json +136 -0
  29. package/operation-library/csv-data-analysis.json +228 -0
  30. package/operation-library/csv-to-json.json +160 -0
  31. package/operation-library/directory-inventory.json +128 -0
  32. package/operation-library/expression-calculator.json +114 -0
  33. package/operation-library/file-search-replace.json +175 -0
  34. package/operation-library/git-status-report.json +368 -0
  35. package/operation-library/health-check-ping.json +329 -0
  36. package/operation-library/json-config-merge.json +313 -0
  37. package/operation-library/llm-embedding-tool-use.json +314 -0
  38. package/operation-library/llm-multi-turn-analysis.json +322 -0
  39. package/operation-library/llm-summarize.json +264 -0
  40. package/operation-library/log-line-counter.json +185 -0
  41. package/operation-library/meadow-crud-lifecycle.json +264 -0
  42. package/operation-library/npm-project-validator.json +193 -0
  43. package/operation-library/rest-api-orchestrator.json +218 -0
  44. package/operation-library/shell-system-info.json +137 -0
  45. package/operation-library/simple-echo.json +95 -0
  46. package/operation-library/template-processor.json +299 -0
  47. package/operation-library/text-sanitizer.json +176 -0
  48. package/package.json +12 -8
  49. package/source/Ultravisor.cjs +30 -3
  50. package/source/beacon/Ultravisor-Beacon-CLI.cjs +143 -0
  51. package/source/beacon/Ultravisor-Beacon-CapabilityProvider.cjs +129 -0
  52. package/source/beacon/Ultravisor-Beacon-Client.cjs +568 -0
  53. package/source/beacon/Ultravisor-Beacon-Executor.cjs +500 -0
  54. package/source/beacon/Ultravisor-Beacon-ProviderRegistry.cjs +330 -0
  55. package/source/beacon/providers/Ultravisor-Beacon-Provider-FileSystem.cjs +331 -0
  56. package/source/beacon/providers/Ultravisor-Beacon-Provider-LLM.cjs +966 -0
  57. package/source/beacon/providers/Ultravisor-Beacon-Provider-Shell.cjs +95 -0
  58. package/source/cli/Ultravisor-CLIProgram.cjs +44 -22
  59. package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
  60. package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
  61. package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
  62. package/source/config/Ultravisor-Default-Command-Configuration.cjs +12 -3
  63. package/source/services/Ultravisor-Beacon-Coordinator.cjs +966 -0
  64. package/source/services/Ultravisor-ExecutionEngine.cjs +1093 -0
  65. package/source/services/Ultravisor-ExecutionManifest.cjs +629 -0
  66. package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
  67. package/source/services/Ultravisor-Hypervisor.cjs +185 -75
  68. package/source/services/Ultravisor-Schedule-Persistence-Base.cjs +45 -0
  69. package/source/services/Ultravisor-StateManager.cjs +253 -0
  70. package/source/services/Ultravisor-TaskTypeRegistry.cjs +213 -0
  71. package/source/services/persistence/Ultravisor-Schedule-Persistence-JSONFile.cjs +140 -0
  72. package/source/services/tasks/Ultravisor-BuiltIn-TaskConfigs.cjs +19 -0
  73. package/source/services/tasks/Ultravisor-TaskHelper-BeaconDispatch.cjs +107 -0
  74. package/source/services/tasks/Ultravisor-TaskType-Base.cjs +125 -0
  75. package/source/services/tasks/content-system/Ultravisor-TaskConfigs-ContentSystem.cjs +90 -0
  76. package/source/services/tasks/content-system/definitions/content-create-folder.json +24 -0
  77. package/source/services/tasks/content-system/definitions/content-list-files.json +27 -0
  78. package/source/services/tasks/content-system/definitions/content-read-file.json +26 -0
  79. package/source/services/tasks/content-system/definitions/content-save-file.json +26 -0
  80. package/source/services/tasks/data-transform/Ultravisor-TaskConfigs-DataTransform.cjs +577 -0
  81. package/source/services/tasks/data-transform/Ultravisor-TaskType-ReplaceString.cjs +80 -0
  82. package/source/services/tasks/data-transform/Ultravisor-TaskType-SetValues.cjs +74 -0
  83. package/source/services/tasks/data-transform/Ultravisor-TaskType-StringAppender.cjs +90 -0
  84. package/source/services/tasks/data-transform/definitions/comprehension-intersect.json +24 -0
  85. package/source/services/tasks/data-transform/definitions/csv-transform.json +24 -0
  86. package/source/services/tasks/data-transform/definitions/expression-solver.json +20 -0
  87. package/source/services/tasks/data-transform/definitions/histogram.json +23 -0
  88. package/source/services/tasks/data-transform/definitions/parse-csv.json +27 -0
  89. package/source/services/tasks/data-transform/definitions/replace-string.json +27 -0
  90. package/source/services/tasks/data-transform/definitions/set-values.json +17 -0
  91. package/source/services/tasks/data-transform/definitions/string-appender.json +22 -0
  92. package/source/services/tasks/data-transform/definitions/template-string.json +20 -0
  93. package/source/services/tasks/extension/Ultravisor-TaskConfigs-Extension.cjs +87 -0
  94. package/source/services/tasks/extension/definitions/beacon-dispatch.json +32 -0
  95. package/source/services/tasks/file-system/Ultravisor-TaskConfigs-FileSystem.cjs +509 -0
  96. package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFile.cjs +96 -0
  97. package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFileBuffered.cjs +123 -0
  98. package/source/services/tasks/file-system/Ultravisor-TaskType-WriteFile.cjs +106 -0
  99. package/source/services/tasks/file-system/definitions/copy-file.json +27 -0
  100. package/source/services/tasks/file-system/definitions/list-files.json +27 -0
  101. package/source/services/tasks/file-system/definitions/read-file-buffered.json +31 -0
  102. package/source/services/tasks/file-system/definitions/read-file.json +26 -0
  103. package/source/services/tasks/file-system/definitions/read-json.json +23 -0
  104. package/source/services/tasks/file-system/definitions/write-file.json +29 -0
  105. package/source/services/tasks/file-system/definitions/write-json.json +30 -0
  106. package/source/services/tasks/flow-control/Ultravisor-TaskConfigs-FlowControl.cjs +353 -0
  107. package/source/services/tasks/flow-control/Ultravisor-TaskType-IfConditional.cjs +125 -0
  108. package/source/services/tasks/flow-control/Ultravisor-TaskType-LaunchOperation.cjs +186 -0
  109. package/source/services/tasks/flow-control/Ultravisor-TaskType-SplitExecute.cjs +164 -0
  110. package/source/services/tasks/flow-control/definitions/if-conditional.json +25 -0
  111. package/source/services/tasks/flow-control/definitions/launch-operation.json +27 -0
  112. package/source/services/tasks/flow-control/definitions/split-execute.json +32 -0
  113. package/source/services/tasks/http-client/Ultravisor-TaskConfigs-HttpClient.cjs +281 -0
  114. package/source/services/tasks/http-client/definitions/get-json.json +26 -0
  115. package/source/services/tasks/http-client/definitions/get-text.json +26 -0
  116. package/source/services/tasks/http-client/definitions/rest-request.json +32 -0
  117. package/source/services/tasks/http-client/definitions/send-json.json +28 -0
  118. package/source/services/tasks/llm/Ultravisor-TaskConfigs-LLM.cjs +605 -0
  119. package/source/services/tasks/llm/definitions/llm-chat-completion.json +46 -0
  120. package/source/services/tasks/llm/definitions/llm-embedding.json +31 -0
  121. package/source/services/tasks/llm/definitions/llm-tool-use.json +42 -0
  122. package/source/services/tasks/meadow-api/Ultravisor-TaskConfigs-MeadowApi.cjs +341 -0
  123. package/source/services/tasks/meadow-api/definitions/meadow-count.json +26 -0
  124. package/source/services/tasks/meadow-api/definitions/meadow-create.json +26 -0
  125. package/source/services/tasks/meadow-api/definitions/meadow-delete.json +23 -0
  126. package/source/services/tasks/meadow-api/definitions/meadow-read.json +26 -0
  127. package/source/services/tasks/meadow-api/definitions/meadow-reads.json +29 -0
  128. package/source/services/tasks/meadow-api/definitions/meadow-update.json +26 -0
  129. package/source/services/tasks/shell/Ultravisor-TaskConfigs-Shell.cjs +63 -0
  130. package/source/services/tasks/shell/definitions/command.json +29 -0
  131. package/source/services/tasks/user-interaction/Ultravisor-TaskConfigs-UserInteraction.cjs +64 -0
  132. package/source/services/tasks/user-interaction/Ultravisor-TaskType-ErrorMessage.cjs +55 -0
  133. package/source/services/tasks/user-interaction/Ultravisor-TaskType-ValueInput.cjs +47 -0
  134. package/source/services/tasks/user-interaction/definitions/error-message.json +18 -0
  135. package/source/services/tasks/user-interaction/definitions/value-input.json +23 -0
  136. package/source/web_server/Ultravisor-API-Server.cjs +849 -124
  137. package/test/Ultravisor_browser_tests.js +2226 -0
  138. package/test/Ultravisor_operation_library_tests.js +894 -0
  139. package/test/Ultravisor_tests.js +4946 -5044
  140. package/test/workflows/test-content-concatenate-all.json +339 -0
  141. package/test/workflows/test-content-full-pipeline.json +159 -0
  142. package/test/workflows/test-content-list-files.json +76 -0
  143. package/test/workflows/test-content-save-and-read.json +106 -0
  144. package/webinterface/css/ultravisor-themes.css +668 -0
  145. package/webinterface/css/ultravisor.css +37 -14
  146. package/webinterface/docs/card-help/beacon-dispatch.md +30 -0
  147. package/webinterface/docs/card-help/command.md +27 -0
  148. package/webinterface/docs/card-help/comprehension-intersect.md +24 -0
  149. package/webinterface/docs/card-help/content-create-folder.md +22 -0
  150. package/webinterface/docs/card-help/content-list-files.md +25 -0
  151. package/webinterface/docs/card-help/content-read-file.md +24 -0
  152. package/webinterface/docs/card-help/content-save-file.md +24 -0
  153. package/webinterface/docs/card-help/copy-file.md +25 -0
  154. package/webinterface/docs/card-help/csv-transform.md +24 -0
  155. package/webinterface/docs/card-help/end.md +11 -0
  156. package/webinterface/docs/card-help/error-message.md +16 -0
  157. package/webinterface/docs/card-help/expression-solver.md +21 -0
  158. package/webinterface/docs/card-help/get-json.md +24 -0
  159. package/webinterface/docs/card-help/get-text.md +24 -0
  160. package/webinterface/docs/card-help/histogram.md +23 -0
  161. package/webinterface/docs/card-help/if-conditional.md +23 -0
  162. package/webinterface/docs/card-help/launch-operation.md +25 -0
  163. package/webinterface/docs/card-help/list-files.md +25 -0
  164. package/webinterface/docs/card-help/llm-chat-completion.md +43 -0
  165. package/webinterface/docs/card-help/llm-embedding.md +24 -0
  166. package/webinterface/docs/card-help/llm-tool-use.md +39 -0
  167. package/webinterface/docs/card-help/meadow-count.md +24 -0
  168. package/webinterface/docs/card-help/meadow-create.md +24 -0
  169. package/webinterface/docs/card-help/meadow-delete.md +19 -0
  170. package/webinterface/docs/card-help/meadow-read.md +24 -0
  171. package/webinterface/docs/card-help/meadow-reads.md +27 -0
  172. package/webinterface/docs/card-help/meadow-update.md +24 -0
  173. package/webinterface/docs/card-help/parse-csv.md +27 -0
  174. package/webinterface/docs/card-help/read-file-buffered.md +29 -0
  175. package/webinterface/docs/card-help/read-file.md +24 -0
  176. package/webinterface/docs/card-help/read-json.md +21 -0
  177. package/webinterface/docs/card-help/replace-string.md +25 -0
  178. package/webinterface/docs/card-help/rest-request.md +30 -0
  179. package/webinterface/docs/card-help/send-json.md +26 -0
  180. package/webinterface/docs/card-help/set-values.md +16 -0
  181. package/webinterface/docs/card-help/split-execute.md +35 -0
  182. package/webinterface/docs/card-help/start.md +11 -0
  183. package/webinterface/docs/card-help/string-appender.md +22 -0
  184. package/webinterface/docs/card-help/template-string.md +21 -0
  185. package/webinterface/docs/card-help/value-input.md +24 -0
  186. package/webinterface/docs/card-help/write-file.md +27 -0
  187. package/webinterface/docs/card-help/write-json.md +28 -0
  188. package/webinterface/html/index.html +5 -0
  189. package/webinterface/package.json +13 -4
  190. package/webinterface/source/Pict-Application-Ultravisor.js +564 -70
  191. package/webinterface/source/Ultravisor-TimingUtils.js +99 -0
  192. package/webinterface/source/card-help-content.js +46 -0
  193. package/webinterface/source/cards/Ultravisor-BuiltIn-CardConfigs.js +174 -0
  194. package/webinterface/source/cards/Ultravisor-CardConfigGenerator.js +431 -0
  195. package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
  196. package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
  197. package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
  198. package/webinterface/source/panels/Ultravisor-CardSettingsPanel.js +902 -0
  199. package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +20 -8
  200. package/webinterface/source/views/PictView-Ultravisor-BeaconList.js +817 -0
  201. package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +5 -5
  202. package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +25 -25
  203. package/webinterface/source/views/PictView-Ultravisor-Documentation.js +856 -0
  204. package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +777 -0
  205. package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +321 -58
  206. package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +36 -91
  207. package/webinterface/source/views/PictView-Ultravisor-OperationList.js +388 -16
  208. package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
  209. package/webinterface/source/views/PictView-Ultravisor-Schedule.js +521 -65
  210. package/webinterface/source/views/PictView-Ultravisor-TimingView.js +333 -71
  211. package/webinterface/source/views/PictView-Ultravisor-TopBar.js +257 -21
  212. package/webinterface/theme-sampler.html +645 -0
  213. package/debug/Harness.js +0 -6
  214. package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
  215. package/source/services/Ultravisor-Operation.cjs +0 -200
  216. package/source/services/Ultravisor-Task.cjs +0 -349
  217. package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
  218. package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
  219. package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
  220. package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
  221. package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
  222. package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
  223. package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
  224. package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
  225. package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
  226. package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
  227. package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
  228. package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
  229. package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
  230. package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
  231. package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
  232. package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
  233. package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
  234. package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
  235. package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
  236. package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
  237. package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
  238. package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
  239. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
  240. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
  241. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
  242. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
  243. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
  244. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
  245. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
  246. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
  247. package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
  248. package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Flow Control task configurations for Ultravisor.
3
+ *
4
+ * Contains task types for controlling execution flow:
5
+ * if-conditional, split-execute, launch-operation
6
+ *
7
+ * Each entry defines a task type as a config object with:
8
+ * Definition {object} - Port schema, metadata, default settings
9
+ * Execute {function} - Runtime logic: function(pTask, pSettings, pContext, fCb, fFireEvent)
10
+ */
11
+
12
+
13
+ // ── Module-scoped helpers ───────────────────────────────────────────
14
+
15
+ /**
16
+ * Get a service instance from the fable services map.
17
+ */
18
+ function _getService(pTask, pTypeName)
19
+ {
20
+ if (pTask.fable.servicesMap[pTypeName])
21
+ {
22
+ return Object.values(pTask.fable.servicesMap[pTypeName])[0];
23
+ }
24
+ return null;
25
+ }
26
+
27
+ /**
28
+ * Compare two values using an operator (used by if-conditional).
29
+ */
30
+ function _compare(pLeft, pRight, pOperator)
31
+ {
32
+ switch (pOperator)
33
+ {
34
+ case '==':
35
+ return String(pLeft) == String(pRight);
36
+ case '===':
37
+ return pLeft === pRight;
38
+ case '!=':
39
+ return String(pLeft) != String(pRight);
40
+ case '!==':
41
+ return pLeft !== pRight;
42
+ case '>':
43
+ return Number(pLeft) > Number(pRight);
44
+ case '<':
45
+ return Number(pLeft) < Number(pRight);
46
+ case '>=':
47
+ return Number(pLeft) >= Number(pRight);
48
+ case '<=':
49
+ return Number(pLeft) <= Number(pRight);
50
+ case 'contains':
51
+ return String(pLeft).indexOf(String(pRight)) > -1;
52
+ case 'startsWith':
53
+ return String(pLeft).startsWith(String(pRight));
54
+ case 'endsWith':
55
+ return String(pLeft).endsWith(String(pRight));
56
+ case 'truthy':
57
+ return !!pLeft;
58
+ case 'falsy':
59
+ return !pLeft;
60
+ default:
61
+ return String(pLeft) == String(pRight);
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Handle PerformSplit event for split-execute.
67
+ */
68
+ function _handlePerformSplit(pSettings, pContext, fCallback)
69
+ {
70
+ let tmpInputString = pSettings.InputString;
71
+ let tmpDelimiter = pSettings.SplitDelimiter;
72
+
73
+ if (typeof(tmpInputString) !== 'string')
74
+ {
75
+ return fCallback(null, {
76
+ EventToFire: 'Error',
77
+ Outputs: { CurrentToken: '', TokenIndex: 0, TokenCount: 0, CompletedCount: 0 },
78
+ Log: ['InputString is not a string.']
79
+ });
80
+ }
81
+
82
+ if (tmpDelimiter === undefined || tmpDelimiter === null)
83
+ {
84
+ tmpDelimiter = '\n';
85
+ }
86
+
87
+ let tmpTokens = tmpInputString.split(tmpDelimiter);
88
+ if (pSettings.TrimTokens)
89
+ {
90
+ tmpTokens = tmpTokens.map(function (pT) { return pT.trim(); });
91
+ }
92
+ if (pSettings.SkipEmpty)
93
+ {
94
+ tmpTokens = tmpTokens.filter(function (pT) { return pT.length > 0; });
95
+ }
96
+ let tmpTokenCount = tmpTokens.length;
97
+ let tmpLog = [`Splitting input (${tmpInputString.length} chars) by "${tmpDelimiter}" into ${tmpTokenCount} tokens.`];
98
+
99
+ if (tmpTokenCount === 0)
100
+ {
101
+ return fCallback(null, {
102
+ EventToFire: 'CompletedAllSubtasks',
103
+ Outputs: { CurrentToken: '', TokenIndex: 0, TokenCount: 0, CompletedCount: 0 },
104
+ Log: tmpLog.concat(['No tokens to process.'])
105
+ });
106
+ }
107
+
108
+ let tmpFirstToken = tmpTokens[0];
109
+ tmpLog.push(`Emitting token 1/${tmpTokenCount}: "${tmpFirstToken.substring(0, 50)}"`);
110
+
111
+ return fCallback(null, {
112
+ EventToFire: 'TokenDataSent',
113
+ Outputs: {
114
+ _Tokens: tmpTokens,
115
+ CurrentToken: tmpFirstToken,
116
+ TokenIndex: 0,
117
+ TokenCount: tmpTokenCount,
118
+ CompletedCount: 0
119
+ },
120
+ Log: tmpLog
121
+ });
122
+ }
123
+
124
+ /**
125
+ * Handle StepComplete event for split-execute.
126
+ */
127
+ function _handleStepComplete(pContext, fCallback)
128
+ {
129
+ let tmpStoredState = pContext.TaskOutputs[pContext.NodeHash] || {};
130
+ let tmpTokens = tmpStoredState._Tokens;
131
+
132
+ if (!Array.isArray(tmpTokens))
133
+ {
134
+ return fCallback(null, {
135
+ EventToFire: 'Error',
136
+ Outputs: { CurrentToken: '', TokenIndex: 0, TokenCount: 0, CompletedCount: 0 },
137
+ Log: ['StepComplete received but no stored tokens found. Was PerformSplit called first?']
138
+ });
139
+ }
140
+
141
+ let tmpTokenCount = tmpTokens.length;
142
+ let tmpPreviousIndex = tmpStoredState.TokenIndex || 0;
143
+ let tmpCompletedCount = (tmpStoredState.CompletedCount || 0) + 1;
144
+ let tmpNextIndex = tmpPreviousIndex + 1;
145
+
146
+ if (tmpNextIndex >= tmpTokenCount)
147
+ {
148
+ return fCallback(null, {
149
+ EventToFire: 'CompletedAllSubtasks',
150
+ Outputs: {
151
+ _Tokens: tmpTokens,
152
+ CurrentToken: tmpTokens[tmpTokenCount - 1],
153
+ TokenIndex: tmpTokenCount - 1,
154
+ TokenCount: tmpTokenCount,
155
+ CompletedCount: tmpCompletedCount
156
+ },
157
+ Log: [`All ${tmpTokenCount} tokens processed (${tmpCompletedCount} completed).`]
158
+ });
159
+ }
160
+
161
+ let tmpNextToken = tmpTokens[tmpNextIndex];
162
+
163
+ return fCallback(null, {
164
+ EventToFire: 'TokenDataSent',
165
+ Outputs: {
166
+ _Tokens: tmpTokens,
167
+ CurrentToken: tmpNextToken,
168
+ TokenIndex: tmpNextIndex,
169
+ TokenCount: tmpTokenCount,
170
+ CompletedCount: tmpCompletedCount
171
+ },
172
+ Log: [`Emitting token ${tmpNextIndex + 1}/${tmpTokenCount}: "${tmpNextToken.substring(0, 50)}"`]
173
+ });
174
+ }
175
+
176
+
177
+ // ═══════════════════════════════════════════════════════════════════
178
+ // FLOW CONTROL TASK CONFIGS
179
+ // ═══════════════════════════════════════════════════════════════════
180
+
181
+ module.exports =
182
+ [
183
+ // ── if-conditional ─────────────────────────────────────────
184
+ {
185
+ Definition: require('./definitions/if-conditional.json'),
186
+ Execute: function (pTask, pResolvedSettings, pExecutionContext, fCallback)
187
+ {
188
+ let tmpResult = false;
189
+
190
+ if (pResolvedSettings.Expression && typeof(pResolvedSettings.Expression) === 'string')
191
+ {
192
+ try
193
+ {
194
+ if (pTask.fable.ExpressionParser)
195
+ {
196
+ tmpResult = pTask.fable.ExpressionParser.resolve(pResolvedSettings.Expression, pExecutionContext);
197
+ }
198
+ else
199
+ {
200
+ tmpResult = !!pResolvedSettings.Expression;
201
+ }
202
+ }
203
+ catch (pError)
204
+ {
205
+ return fCallback(null, {
206
+ EventToFire: 'False',
207
+ Outputs: { Result: false },
208
+ Log: [`Expression error: ${pError.message}`]
209
+ });
210
+ }
211
+ }
212
+ else if (pResolvedSettings.DataAddress)
213
+ {
214
+ let tmpDataValue = undefined;
215
+ let tmpStateManager = pExecutionContext.StateManager;
216
+
217
+ if (tmpStateManager)
218
+ {
219
+ tmpDataValue = tmpStateManager.resolveAddress(pResolvedSettings.DataAddress, pExecutionContext, pExecutionContext.NodeHash);
220
+ }
221
+
222
+ tmpResult = _compare(tmpDataValue, pResolvedSettings.CompareValue, pResolvedSettings.Operator || '==');
223
+ }
224
+
225
+ return fCallback(null, {
226
+ EventToFire: tmpResult ? 'True' : 'False',
227
+ Outputs: { Result: tmpResult },
228
+ Log: [`Condition evaluated to ${tmpResult}.`]
229
+ });
230
+ }
231
+ },
232
+
233
+ // ── split-execute ──────────────────────────────────────────
234
+ {
235
+ Definition: require('./definitions/split-execute.json'),
236
+ Execute: function (pTask, pResolvedSettings, pExecutionContext, fCallback)
237
+ {
238
+ if (pExecutionContext.TriggeringEventName === 'StepComplete')
239
+ {
240
+ return _handleStepComplete(pExecutionContext, fCallback);
241
+ }
242
+
243
+ return _handlePerformSplit(pResolvedSettings, pExecutionContext, fCallback);
244
+ }
245
+ },
246
+
247
+ // ── launch-operation ───────────────────────────────────────
248
+ {
249
+ Definition: require('./definitions/launch-operation.json'),
250
+ Execute: function (pTask, pResolvedSettings, pExecutionContext, fCallback)
251
+ {
252
+ let tmpOperationHash = pResolvedSettings.OperationHash;
253
+
254
+ if (!tmpOperationHash || typeof(tmpOperationHash) !== 'string' || tmpOperationHash.length === 0)
255
+ {
256
+ return fCallback(null, { EventToFire: 'Error', Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 }, Log: ['No OperationHash specified.'] });
257
+ }
258
+
259
+ let tmpStateService = _getService(pTask, 'UltravisorHypervisorState');
260
+ if (!tmpStateService)
261
+ {
262
+ return fCallback(null, { EventToFire: 'Error', Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 }, Log: ['UltravisorHypervisorState service not found.'] });
263
+ }
264
+
265
+ let tmpEngine = _getService(pTask, 'UltravisorExecutionEngine');
266
+ if (!tmpEngine)
267
+ {
268
+ return fCallback(null, { EventToFire: 'Error', Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 }, Log: ['UltravisorExecutionEngine service not found.'] });
269
+ }
270
+
271
+ tmpStateService.getOperation(tmpOperationHash,
272
+ function (pError, pOperation)
273
+ {
274
+ if (pError)
275
+ {
276
+ return fCallback(null, { EventToFire: 'Error', Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 }, Log: [`Operation [${tmpOperationHash}] not found: ${pError.message}`] });
277
+ }
278
+
279
+ let tmpInitialState = {
280
+ GlobalState: (pResolvedSettings.InheritGlobalState === false) ? {} : JSON.parse(JSON.stringify(pExecutionContext.GlobalState || {})),
281
+ OperationState: {},
282
+ RunMode: pExecutionContext.RunMode || 'standard'
283
+ };
284
+
285
+ if (pResolvedSettings.InputData && typeof(pResolvedSettings.InputData) === 'string' && pResolvedSettings.InputData.length > 0)
286
+ {
287
+ try
288
+ {
289
+ let tmpInputData = JSON.parse(pResolvedSettings.InputData);
290
+ if (typeof(tmpInputData) === 'object' && tmpInputData !== null)
291
+ {
292
+ tmpInitialState.OperationState = tmpInputData;
293
+ }
294
+ }
295
+ catch (pParseError)
296
+ {
297
+ tmpInitialState.OperationState.InputData = pResolvedSettings.InputData;
298
+ }
299
+ }
300
+
301
+ let tmpStartTime = Date.now();
302
+ let tmpTimeoutMs = parseInt(pResolvedSettings.TimeoutMs, 10) || 0;
303
+ let tmpCompleted = false;
304
+ let tmpTimeoutHandle = null;
305
+
306
+ if (tmpTimeoutMs > 0)
307
+ {
308
+ tmpTimeoutHandle = setTimeout(function()
309
+ {
310
+ if (!tmpCompleted)
311
+ {
312
+ tmpCompleted = true;
313
+ let tmpElapsedMs = Date.now() - tmpStartTime;
314
+ return fCallback(null, {
315
+ EventToFire: 'Error',
316
+ Outputs: { Result: 'Operation timed out', Status: 'Timeout', ElapsedMs: tmpElapsedMs },
317
+ Log: [`Child operation [${tmpOperationHash}] timed out after ${tmpTimeoutMs}ms`]
318
+ });
319
+ }
320
+ }, tmpTimeoutMs);
321
+ }
322
+
323
+ tmpEngine.executeOperation(pOperation, tmpInitialState,
324
+ function (pExecError, pContext)
325
+ {
326
+ if (tmpCompleted) { return; }
327
+ tmpCompleted = true;
328
+ if (tmpTimeoutHandle) { clearTimeout(tmpTimeoutHandle); }
329
+
330
+ let tmpElapsedMs = Date.now() - tmpStartTime;
331
+
332
+ if (pExecError)
333
+ {
334
+ return fCallback(null, {
335
+ EventToFire: 'Error',
336
+ Outputs: { Result: pExecError.message, Status: 'Error', ElapsedMs: tmpElapsedMs },
337
+ Log: [`Child operation [${tmpOperationHash}] failed: ${pExecError.message}`]
338
+ });
339
+ }
340
+
341
+ let tmpStatus = pContext.Status || 'Unknown';
342
+ let tmpResultSummary = JSON.stringify({ Status: tmpStatus, TaskOutputs: pContext.TaskOutputs || {}, Errors: pContext.Errors || [] });
343
+
344
+ return fCallback(null, {
345
+ EventToFire: 'Completed',
346
+ Outputs: { Result: tmpResultSummary, Status: tmpStatus, ElapsedMs: tmpElapsedMs },
347
+ Log: [`Child operation [${tmpOperationHash}] completed with status: ${tmpStatus} (${tmpElapsedMs}ms)`]
348
+ });
349
+ });
350
+ });
351
+ }
352
+ }
353
+ ];
@@ -0,0 +1,125 @@
1
+ const libTaskTypeBase = require('../Ultravisor-TaskType-Base.cjs');
2
+
3
+ /**
4
+ * IfConditional Task Type
5
+ *
6
+ * Evaluates a simple expression and fires either the True or False event.
7
+ * Supports comparisons via DataAddress and CompareValue, or a direct Expression string.
8
+ *
9
+ * If DataAddress is set, reads the value at that address and compares
10
+ * it to CompareValue using the Operator (default: '==').
11
+ *
12
+ * If Expression is set instead, evaluates it using fable.ExpressionParser.
13
+ */
14
+ class UltravisorTaskTypeIfConditional extends libTaskTypeBase
15
+ {
16
+ constructor(pFable, pOptions, pServiceHash)
17
+ {
18
+ super(pFable, pOptions, pServiceHash);
19
+
20
+ this.serviceType = 'UltravisorTaskTypeIfConditional';
21
+ }
22
+
23
+ get definition()
24
+ {
25
+ return require('./definitions/if-conditional.json');
26
+ }
27
+
28
+ execute(pResolvedSettings, pExecutionContext, fCallback, fFireIntermediateEvent)
29
+ {
30
+ let tmpResult = false;
31
+
32
+ if (pResolvedSettings.Expression && typeof(pResolvedSettings.Expression) === 'string')
33
+ {
34
+ // Expression-based evaluation using Fable's ExpressionParser
35
+ try
36
+ {
37
+ if (this.fable.ExpressionParser)
38
+ {
39
+ tmpResult = this.fable.ExpressionParser.resolve(pResolvedSettings.Expression, pExecutionContext);
40
+ }
41
+ else
42
+ {
43
+ // Simple truthy evaluation fallback
44
+ tmpResult = !!pResolvedSettings.Expression;
45
+ }
46
+ }
47
+ catch (pError)
48
+ {
49
+ return fCallback(null, {
50
+ EventToFire: 'False',
51
+ Outputs: { Result: false },
52
+ Log: [`Expression error: ${pError.message}`]
53
+ });
54
+ }
55
+ }
56
+ else if (pResolvedSettings.DataAddress)
57
+ {
58
+ // Address-based comparison
59
+ let tmpDataValue = undefined;
60
+ let tmpStateManager = pExecutionContext.StateManager;
61
+
62
+ if (tmpStateManager)
63
+ {
64
+ tmpDataValue = tmpStateManager.resolveAddress(
65
+ pResolvedSettings.DataAddress, pExecutionContext, pExecutionContext.NodeHash);
66
+ }
67
+
68
+ let tmpCompareValue = pResolvedSettings.CompareValue;
69
+ let tmpOperator = pResolvedSettings.Operator || '==';
70
+
71
+ tmpResult = this._compare(tmpDataValue, tmpCompareValue, tmpOperator);
72
+ }
73
+
74
+ return fCallback(null, {
75
+ EventToFire: tmpResult ? 'True' : 'False',
76
+ Outputs: { Result: tmpResult },
77
+ Log: [`Condition evaluated to ${tmpResult}.`]
78
+ });
79
+ }
80
+
81
+ /**
82
+ * Compare two values using an operator.
83
+ *
84
+ * @param {*} pLeft - Left operand.
85
+ * @param {*} pRight - Right operand.
86
+ * @param {string} pOperator - The comparison operator.
87
+ * @returns {boolean} Result of comparison.
88
+ */
89
+ _compare(pLeft, pRight, pOperator)
90
+ {
91
+ switch (pOperator)
92
+ {
93
+ case '==':
94
+ return String(pLeft) == String(pRight);
95
+ case '===':
96
+ return pLeft === pRight;
97
+ case '!=':
98
+ return String(pLeft) != String(pRight);
99
+ case '!==':
100
+ return pLeft !== pRight;
101
+ case '>':
102
+ return Number(pLeft) > Number(pRight);
103
+ case '<':
104
+ return Number(pLeft) < Number(pRight);
105
+ case '>=':
106
+ return Number(pLeft) >= Number(pRight);
107
+ case '<=':
108
+ return Number(pLeft) <= Number(pRight);
109
+ case 'contains':
110
+ return String(pLeft).indexOf(String(pRight)) > -1;
111
+ case 'startsWith':
112
+ return String(pLeft).startsWith(String(pRight));
113
+ case 'endsWith':
114
+ return String(pLeft).endsWith(String(pRight));
115
+ case 'truthy':
116
+ return !!pLeft;
117
+ case 'falsy':
118
+ return !pLeft;
119
+ default:
120
+ return String(pLeft) == String(pRight);
121
+ }
122
+ }
123
+ }
124
+
125
+ module.exports = UltravisorTaskTypeIfConditional;
@@ -0,0 +1,186 @@
1
+ const libTaskTypeBase = require('../Ultravisor-TaskType-Base.cjs');
2
+
3
+ /**
4
+ * LaunchOperation Task Type
5
+ *
6
+ * Executes a child operation within the current operation's graph.
7
+ * Looks up the target operation by hash from the Hypervisor's state,
8
+ * creates an isolated execution context for it, and runs it via the
9
+ * ExecutionEngine.
10
+ *
11
+ * The child operation gets its own OperationState (optionally seeded
12
+ * from InputData) but shares the parent's GlobalState (as a copy).
13
+ *
14
+ * Flow:
15
+ * Launch -> (execute child operation) -> Completed or Error
16
+ */
17
+ class UltravisorTaskTypeLaunchOperation extends libTaskTypeBase
18
+ {
19
+ constructor(pFable, pOptions, pServiceHash)
20
+ {
21
+ super(pFable, pOptions, pServiceHash);
22
+
23
+ this.serviceType = 'UltravisorTaskTypeLaunchOperation';
24
+ }
25
+
26
+ get definition()
27
+ {
28
+ return require('./definitions/launch-operation.json');
29
+ }
30
+
31
+ execute(pResolvedSettings, pExecutionContext, fCallback, fFireIntermediateEvent)
32
+ {
33
+ let tmpOperationHash = pResolvedSettings.OperationHash;
34
+
35
+ if (!tmpOperationHash || typeof(tmpOperationHash) !== 'string' || tmpOperationHash.length === 0)
36
+ {
37
+ return fCallback(null, {
38
+ EventToFire: 'Error',
39
+ Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 },
40
+ Log: ['No OperationHash specified.']
41
+ });
42
+ }
43
+
44
+ // Get the Hypervisor state service to look up the operation
45
+ let tmpStateService = this._getService('UltravisorHypervisorState');
46
+
47
+ if (!tmpStateService)
48
+ {
49
+ return fCallback(null, {
50
+ EventToFire: 'Error',
51
+ Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 },
52
+ Log: ['UltravisorHypervisorState service not found.']
53
+ });
54
+ }
55
+
56
+ // Get the ExecutionEngine to run the child operation
57
+ let tmpEngine = this._getService('UltravisorExecutionEngine');
58
+
59
+ if (!tmpEngine)
60
+ {
61
+ return fCallback(null, {
62
+ EventToFire: 'Error',
63
+ Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 },
64
+ Log: ['UltravisorExecutionEngine service not found.']
65
+ });
66
+ }
67
+
68
+ // Look up the target operation
69
+ tmpStateService.getOperation(tmpOperationHash,
70
+ (pError, pOperation) =>
71
+ {
72
+ if (pError)
73
+ {
74
+ return fCallback(null, {
75
+ EventToFire: 'Error',
76
+ Outputs: { Result: '', Status: 'Error', ElapsedMs: 0 },
77
+ Log: [`Operation [${tmpOperationHash}] not found: ${pError.message}`]
78
+ });
79
+ }
80
+
81
+ // Build initial state for the child operation
82
+ let tmpInitialState = {
83
+ // Share a copy of the parent's global state (unless InheritGlobalState is false)
84
+ GlobalState: (pResolvedSettings.InheritGlobalState === false) ? {} : JSON.parse(JSON.stringify(pExecutionContext.GlobalState || {})),
85
+ // Isolated operation state, optionally seeded from InputData
86
+ OperationState: {},
87
+ RunMode: pExecutionContext.RunMode || 'standard'
88
+ };
89
+
90
+ // Parse InputData if provided (expects JSON string)
91
+ if (pResolvedSettings.InputData && typeof(pResolvedSettings.InputData) === 'string' && pResolvedSettings.InputData.length > 0)
92
+ {
93
+ try
94
+ {
95
+ let tmpInputData = JSON.parse(pResolvedSettings.InputData);
96
+ if (typeof(tmpInputData) === 'object' && tmpInputData !== null)
97
+ {
98
+ tmpInitialState.OperationState = tmpInputData;
99
+ }
100
+ }
101
+ catch (pParseError)
102
+ {
103
+ // If not valid JSON, store as a raw string in OperationState.InputData
104
+ tmpInitialState.OperationState.InputData = pResolvedSettings.InputData;
105
+ }
106
+ }
107
+
108
+ let tmpStartTime = Date.now();
109
+ let tmpTimeoutMs = parseInt(pResolvedSettings.TimeoutMs, 10) || 0;
110
+ let tmpCompleted = false;
111
+ let tmpTimeoutHandle = null;
112
+
113
+ if (tmpTimeoutMs > 0)
114
+ {
115
+ tmpTimeoutHandle = setTimeout(function()
116
+ {
117
+ if (!tmpCompleted)
118
+ {
119
+ tmpCompleted = true;
120
+ let tmpElapsedMs = Date.now() - tmpStartTime;
121
+ return fCallback(null, {
122
+ EventToFire: 'Error',
123
+ Outputs: { Result: 'Operation timed out', Status: 'Timeout', ElapsedMs: tmpElapsedMs },
124
+ Log: [`Child operation [${tmpOperationHash}] timed out after ${tmpTimeoutMs}ms`]
125
+ });
126
+ }
127
+ }, tmpTimeoutMs);
128
+ }
129
+
130
+ // Execute the child operation
131
+ tmpEngine.executeOperation(pOperation, tmpInitialState,
132
+ (pExecError, pContext) =>
133
+ {
134
+ if (tmpCompleted) { return; }
135
+ tmpCompleted = true;
136
+ if (tmpTimeoutHandle) { clearTimeout(tmpTimeoutHandle); }
137
+
138
+ let tmpElapsedMs = Date.now() - tmpStartTime;
139
+
140
+ if (pExecError)
141
+ {
142
+ return fCallback(null, {
143
+ EventToFire: 'Error',
144
+ Outputs: {
145
+ Result: pExecError.message,
146
+ Status: 'Error',
147
+ ElapsedMs: tmpElapsedMs
148
+ },
149
+ Log: [`Child operation [${tmpOperationHash}] failed: ${pExecError.message}`]
150
+ });
151
+ }
152
+
153
+ let tmpStatus = pContext.Status || 'Unknown';
154
+ let tmpResultSummary = JSON.stringify({
155
+ Status: tmpStatus,
156
+ TaskOutputs: pContext.TaskOutputs || {},
157
+ Errors: pContext.Errors || []
158
+ });
159
+
160
+ return fCallback(null, {
161
+ EventToFire: 'Completed',
162
+ Outputs: {
163
+ Result: tmpResultSummary,
164
+ Status: tmpStatus,
165
+ ElapsedMs: tmpElapsedMs
166
+ },
167
+ Log: [`Child operation [${tmpOperationHash}] completed with status: ${tmpStatus} (${tmpElapsedMs}ms)`]
168
+ });
169
+ });
170
+ });
171
+ }
172
+
173
+ /**
174
+ * Get a service instance from the fable services map.
175
+ */
176
+ _getService(pTypeName)
177
+ {
178
+ if (this.fable.servicesMap[pTypeName])
179
+ {
180
+ return Object.values(this.fable.servicesMap[pTypeName])[0];
181
+ }
182
+ return null;
183
+ }
184
+ }
185
+
186
+ module.exports = UltravisorTaskTypeLaunchOperation;