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,164 @@
1
+ const libTaskTypeBase = require('../Ultravisor-TaskType-Base.cjs');
2
+
3
+ /**
4
+ * SplitExecute Task Type
5
+ *
6
+ * Splits an input string by a delimiter and fires an event for each token.
7
+ * Operates as a state machine: each invocation processes exactly one token.
8
+ *
9
+ * Flow (driven by graph connections):
10
+ * PerformSplit -> split input, store tokens, emit first token via TokenDataSent
11
+ * StepComplete -> advance to next token, emit via TokenDataSent
12
+ * (or fire CompletedAllSubtasks when all tokens are done)
13
+ *
14
+ * The loop is driven by explicit graph connections:
15
+ * SplitExecute.TokenDataSent -> downstream tasks -> ... -> SplitExecute.StepComplete
16
+ *
17
+ * State is persisted between invocations in TaskOutputs[NodeHash]:
18
+ * _Tokens {Array} - the split token array (internal)
19
+ * CurrentToken {string} - the current token being processed
20
+ * TokenIndex {number} - 0-based index of the current token
21
+ * TokenCount {number} - total number of tokens
22
+ * CompletedCount {number} - number of tokens fully processed
23
+ */
24
+ class UltravisorTaskTypeSplitExecute extends libTaskTypeBase
25
+ {
26
+ constructor(pFable, pOptions, pServiceHash)
27
+ {
28
+ super(pFable, pOptions, pServiceHash);
29
+
30
+ this.serviceType = 'UltravisorTaskTypeSplitExecute';
31
+ }
32
+
33
+ get definition()
34
+ {
35
+ return require('./definitions/split-execute.json');
36
+ }
37
+
38
+ execute(pResolvedSettings, pExecutionContext, fCallback, fFireIntermediateEvent)
39
+ {
40
+ let tmpTriggeringEvent = pExecutionContext.TriggeringEventName;
41
+
42
+ if (tmpTriggeringEvent === 'StepComplete')
43
+ {
44
+ return this._handleStepComplete(pExecutionContext, fCallback);
45
+ }
46
+
47
+ // Default: PerformSplit (initial trigger)
48
+ return this._handlePerformSplit(pResolvedSettings, pExecutionContext, fCallback);
49
+ }
50
+
51
+ /**
52
+ * Handle the PerformSplit event: split input and emit the first token.
53
+ */
54
+ _handlePerformSplit(pResolvedSettings, pExecutionContext, fCallback)
55
+ {
56
+ let tmpInputString = pResolvedSettings.InputString;
57
+ let tmpDelimiter = pResolvedSettings.SplitDelimiter;
58
+
59
+ if (typeof(tmpInputString) !== 'string')
60
+ {
61
+ return fCallback(null, {
62
+ EventToFire: 'Error',
63
+ Outputs: { CurrentToken: '', TokenIndex: 0, TokenCount: 0, CompletedCount: 0 },
64
+ Log: ['InputString is not a string.']
65
+ });
66
+ }
67
+
68
+ if (tmpDelimiter === undefined || tmpDelimiter === null)
69
+ {
70
+ tmpDelimiter = '\n';
71
+ }
72
+
73
+ let tmpTokens = tmpInputString.split(tmpDelimiter);
74
+ if (pResolvedSettings.TrimTokens)
75
+ {
76
+ tmpTokens = tmpTokens.map(function (pT) { return pT.trim(); });
77
+ }
78
+ if (pResolvedSettings.SkipEmpty)
79
+ {
80
+ tmpTokens = tmpTokens.filter(function (pT) { return pT.length > 0; });
81
+ }
82
+ let tmpTokenCount = tmpTokens.length;
83
+ let tmpLog = [`Splitting input (${tmpInputString.length} chars) by "${tmpDelimiter}" into ${tmpTokenCount} tokens.`];
84
+
85
+ if (tmpTokenCount === 0)
86
+ {
87
+ return fCallback(null, {
88
+ EventToFire: 'CompletedAllSubtasks',
89
+ Outputs: { CurrentToken: '', TokenIndex: 0, TokenCount: 0, CompletedCount: 0 },
90
+ Log: tmpLog.concat(['No tokens to process.'])
91
+ });
92
+ }
93
+
94
+ let tmpFirstToken = tmpTokens[0];
95
+ tmpLog.push(`Emitting token 1/${tmpTokenCount}: "${tmpFirstToken.substring(0, 50)}"`);
96
+
97
+ return fCallback(null, {
98
+ EventToFire: 'TokenDataSent',
99
+ Outputs: {
100
+ _Tokens: tmpTokens,
101
+ CurrentToken: tmpFirstToken,
102
+ TokenIndex: 0,
103
+ TokenCount: tmpTokenCount,
104
+ CompletedCount: 0
105
+ },
106
+ Log: tmpLog
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Handle the StepComplete event: advance to the next token or finish.
112
+ */
113
+ _handleStepComplete(pExecutionContext, fCallback)
114
+ {
115
+ let tmpStoredState = pExecutionContext.TaskOutputs[pExecutionContext.NodeHash] || {};
116
+ let tmpTokens = tmpStoredState._Tokens;
117
+
118
+ if (!Array.isArray(tmpTokens))
119
+ {
120
+ return fCallback(null, {
121
+ EventToFire: 'Error',
122
+ Outputs: { CurrentToken: '', TokenIndex: 0, TokenCount: 0, CompletedCount: 0 },
123
+ Log: ['StepComplete received but no stored tokens found. Was PerformSplit called first?']
124
+ });
125
+ }
126
+
127
+ let tmpTokenCount = tmpTokens.length;
128
+ let tmpPreviousIndex = tmpStoredState.TokenIndex || 0;
129
+ let tmpCompletedCount = (tmpStoredState.CompletedCount || 0) + 1;
130
+ let tmpNextIndex = tmpPreviousIndex + 1;
131
+
132
+ if (tmpNextIndex >= tmpTokenCount)
133
+ {
134
+ // All tokens processed
135
+ return fCallback(null, {
136
+ EventToFire: 'CompletedAllSubtasks',
137
+ Outputs: {
138
+ _Tokens: tmpTokens,
139
+ CurrentToken: tmpTokens[tmpTokenCount - 1],
140
+ TokenIndex: tmpTokenCount - 1,
141
+ TokenCount: tmpTokenCount,
142
+ CompletedCount: tmpCompletedCount
143
+ },
144
+ Log: [`All ${tmpTokenCount} tokens processed (${tmpCompletedCount} completed).`]
145
+ });
146
+ }
147
+
148
+ let tmpNextToken = tmpTokens[tmpNextIndex];
149
+
150
+ return fCallback(null, {
151
+ EventToFire: 'TokenDataSent',
152
+ Outputs: {
153
+ _Tokens: tmpTokens,
154
+ CurrentToken: tmpNextToken,
155
+ TokenIndex: tmpNextIndex,
156
+ TokenCount: tmpTokenCount,
157
+ CompletedCount: tmpCompletedCount
158
+ },
159
+ Log: [`Emitting token ${tmpNextIndex + 1}/${tmpTokenCount}: "${tmpNextToken.substring(0, 50)}"`]
160
+ });
161
+ }
162
+ }
163
+
164
+ module.exports = UltravisorTaskTypeSplitExecute;
@@ -0,0 +1,25 @@
1
+ {
2
+ "Hash": "if-conditional",
3
+ "Type": "if-conditional",
4
+ "Name": "If Conditional",
5
+ "Description": "Evaluates a condition and branches execution to True or False.",
6
+ "Category": "control",
7
+ "Capability": "Flow Control",
8
+ "Action": "Branch",
9
+ "Tier": "Engine",
10
+ "EventInputs": [{ "Name": "Evaluate" }],
11
+ "EventOutputs": [
12
+ { "Name": "True" },
13
+ { "Name": "False" }
14
+ ],
15
+ "SettingsInputs": [
16
+ { "Name": "DataAddress", "DataType": "String", "Required": false },
17
+ { "Name": "CompareValue", "DataType": "String", "Required": false },
18
+ { "Name": "Operator", "DataType": "String", "Required": false },
19
+ { "Name": "Expression", "DataType": "String", "Required": false }
20
+ ],
21
+ "StateOutputs": [
22
+ { "Name": "Result", "DataType": "Boolean" }
23
+ ],
24
+ "DefaultSettings": { "DataAddress": "", "CompareValue": "", "Operator": "==", "Expression": "" }
25
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "Hash": "launch-operation",
3
+ "Type": "launch-operation",
4
+ "Name": "Launch Operation",
5
+ "Description": "Executes a child operation by hash, with isolated operation state.",
6
+ "Category": "control",
7
+ "Capability": "Flow Control",
8
+ "Action": "LaunchOperation",
9
+ "Tier": "Engine",
10
+ "EventInputs": [{ "Name": "Launch" }],
11
+ "EventOutputs": [
12
+ { "Name": "Completed" },
13
+ { "Name": "Error", "IsError": true }
14
+ ],
15
+ "SettingsInputs": [
16
+ { "Name": "OperationHash", "DataType": "String", "Required": true },
17
+ { "Name": "InputData", "DataType": "String" },
18
+ { "Name": "TimeoutMs", "DataType": "Number", "Required": false, "Description": "Maximum execution time for the child operation in milliseconds (0 = unlimited)" },
19
+ { "Name": "InheritGlobalState", "DataType": "Boolean", "Required": false, "Description": "Copy parent GlobalState into child operation (default true)" }
20
+ ],
21
+ "StateOutputs": [
22
+ { "Name": "Result", "DataType": "String" },
23
+ { "Name": "Status", "DataType": "String" },
24
+ { "Name": "ElapsedMs", "DataType": "Number" }
25
+ ],
26
+ "DefaultSettings": { "OperationHash": "", "InputData": "", "TimeoutMs": 0, "InheritGlobalState": true }
27
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "Hash": "split-execute",
3
+ "Type": "split-execute",
4
+ "Name": "Split Execute",
5
+ "Description": "Splits a string by delimiter and processes each token through a sub-graph.",
6
+ "Category": "control",
7
+ "Capability": "Flow Control",
8
+ "Action": "Iterate",
9
+ "Tier": "Engine",
10
+ "EventInputs": [
11
+ { "Name": "PerformSplit" },
12
+ { "Name": "StepComplete" }
13
+ ],
14
+ "EventOutputs": [
15
+ { "Name": "TokenDataSent" },
16
+ { "Name": "CompletedAllSubtasks" },
17
+ { "Name": "Error", "IsError": true }
18
+ ],
19
+ "SettingsInputs": [
20
+ { "Name": "InputString", "DataType": "String", "Required": true },
21
+ { "Name": "SplitDelimiter", "DataType": "String", "Required": true },
22
+ { "Name": "SkipEmpty", "DataType": "Boolean", "Required": false, "Description": "Skip empty tokens after splitting" },
23
+ { "Name": "TrimTokens", "DataType": "Boolean", "Required": false, "Description": "Trim whitespace from each token" }
24
+ ],
25
+ "StateOutputs": [
26
+ { "Name": "CurrentToken", "DataType": "String" },
27
+ { "Name": "TokenIndex", "DataType": "Number" },
28
+ { "Name": "TokenCount", "DataType": "Number" },
29
+ { "Name": "CompletedCount", "DataType": "Number" }
30
+ ],
31
+ "DefaultSettings": { "InputString": "", "SplitDelimiter": "\n", "SkipEmpty": false, "TrimTokens": false }
32
+ }
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Task configurations for the "HTTP Client" capability.
3
+ *
4
+ * General-purpose REST / HTTP request tasks.
5
+ *
6
+ * Contains:
7
+ * - get-json — Performs an HTTP GET request and parses the response as JSON.
8
+ * - get-text — Performs an HTTP GET request and returns the response as text.
9
+ * - send-json — Sends JSON data via HTTP POST or PUT.
10
+ * - rest-request — Performs a fully configurable HTTP REST request.
11
+ */
12
+
13
+
14
+ // ── Module-scoped helpers ───────────────────────────────────────────
15
+
16
+ /**
17
+ * Get a service instance from the fable services map.
18
+ */
19
+ function _getService(pTask, pTypeName)
20
+ {
21
+ if (pTask.fable.servicesMap[pTypeName])
22
+ {
23
+ return Object.values(pTask.fable.servicesMap[pTypeName])[0];
24
+ }
25
+ return null;
26
+ }
27
+
28
+ /**
29
+ * Parse headers from a JSON string or return empty object.
30
+ */
31
+ function _parseHeaders(pHeadersString)
32
+ {
33
+ if (!pHeadersString || typeof(pHeadersString) !== 'string' || pHeadersString.trim().length === 0)
34
+ {
35
+ return {};
36
+ }
37
+
38
+ try
39
+ {
40
+ let tmpHeaders = JSON.parse(pHeadersString);
41
+ if (typeof(tmpHeaders) === 'object' && tmpHeaders !== null)
42
+ {
43
+ return tmpHeaders;
44
+ }
45
+ }
46
+ catch (pError)
47
+ {
48
+ // Not valid JSON — ignore
49
+ }
50
+
51
+ return {};
52
+ }
53
+
54
+
55
+ module.exports =
56
+ [
57
+ // ── get-json ───────────────────────────────────────────────
58
+ {
59
+ Definition: require('./definitions/get-json.json'),
60
+ Execute: function (pTask, pResolvedSettings, pExecutionContext, fCallback)
61
+ {
62
+ let tmpURL = pResolvedSettings.URL || '';
63
+ if (!tmpURL)
64
+ {
65
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['GetJSON: no URL specified.'] });
66
+ }
67
+
68
+ let tmpRestClient = _getService(pTask, 'RestClient');
69
+ if (!tmpRestClient)
70
+ {
71
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['GetJSON: RestClient service not found.'] });
72
+ }
73
+
74
+ let tmpRequestOptions = { url: tmpURL, headers: _parseHeaders(pResolvedSettings.Headers), timeout: pResolvedSettings.TimeoutMs || 30000 };
75
+
76
+ tmpRestClient.getJSON(tmpRequestOptions,
77
+ function (pError, pResponse, pData)
78
+ {
79
+ if (pError)
80
+ {
81
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: [`GetJSON: request failed: ${pError.message}`] });
82
+ }
83
+
84
+ let tmpStateWrites = {};
85
+ if (pResolvedSettings.Destination)
86
+ {
87
+ tmpStateWrites[pResolvedSettings.Destination] = pData;
88
+ }
89
+
90
+ return fCallback(null, {
91
+ EventToFire: 'Complete',
92
+ Outputs: { Data: pData, StatusCode: (pResponse && pResponse.statusCode) ? pResponse.statusCode : 0 },
93
+ StateWrites: tmpStateWrites,
94
+ Log: [`GetJSON: received response from ${tmpURL}`]
95
+ });
96
+ });
97
+ }
98
+ },
99
+
100
+ // ── get-text ───────────────────────────────────────────────
101
+ {
102
+ Definition: require('./definitions/get-text.json'),
103
+ Execute: function (pTask, pResolvedSettings, pExecutionContext, fCallback)
104
+ {
105
+ let tmpURL = pResolvedSettings.URL || '';
106
+ if (!tmpURL)
107
+ {
108
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['GetText: no URL specified.'] });
109
+ }
110
+
111
+ let tmpRestClient = _getService(pTask, 'RestClient');
112
+ if (!tmpRestClient)
113
+ {
114
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['GetText: RestClient service not found.'] });
115
+ }
116
+
117
+ let tmpRequestOptions = { url: tmpURL, headers: _parseHeaders(pResolvedSettings.Headers), timeout: pResolvedSettings.TimeoutMs || 30000 };
118
+
119
+ tmpRestClient.getRawText(tmpRequestOptions,
120
+ function (pError, pResponse, pData)
121
+ {
122
+ if (pError)
123
+ {
124
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: [`GetText: request failed: ${pError.message}`] });
125
+ }
126
+
127
+ let tmpStateWrites = {};
128
+ if (pResolvedSettings.Destination)
129
+ {
130
+ tmpStateWrites[pResolvedSettings.Destination] = pData;
131
+ }
132
+
133
+ return fCallback(null, {
134
+ EventToFire: 'Complete',
135
+ Outputs: { Data: pData, StatusCode: (pResponse && pResponse.statusCode) ? pResponse.statusCode : 0 },
136
+ StateWrites: tmpStateWrites,
137
+ Log: [`GetText: received ${(pData || '').length} chars from ${tmpURL}`]
138
+ });
139
+ });
140
+ }
141
+ },
142
+
143
+ // ── send-json ──────────────────────────────────────────────
144
+ {
145
+ Definition: require('./definitions/send-json.json'),
146
+ Execute: function (pTask, pResolvedSettings, pExecutionContext, fCallback)
147
+ {
148
+ let tmpURL = pResolvedSettings.URL || '';
149
+ if (!tmpURL)
150
+ {
151
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['SendJSON: no URL specified.'] });
152
+ }
153
+
154
+ let tmpRestClient = _getService(pTask, 'RestClient');
155
+ if (!tmpRestClient)
156
+ {
157
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['SendJSON: RestClient service not found.'] });
158
+ }
159
+
160
+ let tmpDataAddress = pResolvedSettings.DataAddress || '';
161
+ let tmpBody = {};
162
+ if (tmpDataAddress && pExecutionContext.StateManager)
163
+ {
164
+ tmpBody = pExecutionContext.StateManager.resolveAddress(tmpDataAddress, pExecutionContext, pExecutionContext.NodeHash);
165
+ if (typeof(tmpBody) !== 'object') { tmpBody = { value: tmpBody }; }
166
+ }
167
+
168
+ let tmpMethod = (pResolvedSettings.Method || 'POST').toUpperCase();
169
+ let tmpOptions = { url: tmpURL, body: tmpBody, headers: _parseHeaders(pResolvedSettings.Headers), timeout: pResolvedSettings.TimeoutMs || 30000 };
170
+
171
+ let tmpDoRequest = (tmpMethod === 'PUT') ? tmpRestClient.putJSON.bind(tmpRestClient) : tmpRestClient.postJSON.bind(tmpRestClient);
172
+
173
+ tmpDoRequest(tmpOptions,
174
+ function (pError, pResponse, pData)
175
+ {
176
+ if (pError)
177
+ {
178
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: [`SendJSON: request failed: ${pError.message}`] });
179
+ }
180
+
181
+ let tmpStateWrites = {};
182
+ if (pResolvedSettings.Destination)
183
+ {
184
+ tmpStateWrites[pResolvedSettings.Destination] = pData;
185
+ }
186
+
187
+ return fCallback(null, {
188
+ EventToFire: 'Complete',
189
+ Outputs: { Response: pData, StatusCode: (pResponse && pResponse.statusCode) ? pResponse.statusCode : 0 },
190
+ StateWrites: tmpStateWrites,
191
+ Log: [`SendJSON: ${tmpMethod} to ${tmpURL} complete`]
192
+ });
193
+ });
194
+ }
195
+ },
196
+
197
+ // ── rest-request ───────────────────────────────────────────
198
+ {
199
+ Definition: require('./definitions/rest-request.json'),
200
+ Execute: function (pTask, pResolvedSettings, pExecutionContext, fCallback)
201
+ {
202
+ let tmpURL = pResolvedSettings.URL || '';
203
+ if (!tmpURL)
204
+ {
205
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['RestRequest: no URL specified.'] });
206
+ }
207
+
208
+ let tmpRestClient = _getService(pTask, 'RestClient');
209
+ if (!tmpRestClient)
210
+ {
211
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: ['RestRequest: RestClient service not found.'] });
212
+ }
213
+
214
+ let tmpMethod = (pResolvedSettings.Method || 'GET').toUpperCase();
215
+ let tmpHeaders = _parseHeaders(pResolvedSettings.Headers);
216
+ if (pResolvedSettings.ContentType)
217
+ {
218
+ tmpHeaders['Content-Type'] = pResolvedSettings.ContentType;
219
+ }
220
+
221
+ let tmpRequestOptions = { url: tmpURL, method: tmpMethod, headers: tmpHeaders, timeout: pResolvedSettings.TimeoutMs || 30000 };
222
+
223
+ // Parse body for non-GET methods
224
+ if (tmpMethod !== 'GET' && pResolvedSettings.Body)
225
+ {
226
+ try
227
+ {
228
+ tmpRequestOptions.body = JSON.parse(pResolvedSettings.Body);
229
+ }
230
+ catch (pParseError)
231
+ {
232
+ tmpRequestOptions.body = pResolvedSettings.Body;
233
+ }
234
+ }
235
+
236
+ let tmpRetryDelayMs = pResolvedSettings.RetryDelayMs || 1000;
237
+
238
+ function _doRequest(pRetriesLeft)
239
+ {
240
+ tmpRestClient.executeChunkedRequest(tmpRequestOptions,
241
+ function (pError, pResponse, pData)
242
+ {
243
+ if (pError)
244
+ {
245
+ if (pRetriesLeft > 0)
246
+ {
247
+ return setTimeout(function () { _doRequest(pRetriesLeft - 1); }, tmpRetryDelayMs);
248
+ }
249
+ return fCallback(null, { EventToFire: 'Error', Outputs: {}, Log: [`RestRequest: ${tmpMethod} ${tmpURL} failed: ${pError.message}`] });
250
+ }
251
+
252
+ // Try to parse as JSON, fall back to raw string
253
+ let tmpParsedData = pData;
254
+ try
255
+ {
256
+ tmpParsedData = JSON.parse(pData);
257
+ }
258
+ catch (pParseError)
259
+ {
260
+ // keep raw string
261
+ }
262
+
263
+ let tmpStateWrites = {};
264
+ if (pResolvedSettings.Destination)
265
+ {
266
+ tmpStateWrites[pResolvedSettings.Destination] = tmpParsedData;
267
+ }
268
+
269
+ return fCallback(null, {
270
+ EventToFire: 'Complete',
271
+ Outputs: { Response: tmpParsedData, StatusCode: (pResponse && pResponse.statusCode) ? pResponse.statusCode : 0, ResponseHeaders: (pResponse && pResponse.headers) ? JSON.stringify(pResponse.headers) : '{}' },
272
+ StateWrites: tmpStateWrites,
273
+ Log: [`RestRequest: ${tmpMethod} ${tmpURL} -> ${pResponse ? pResponse.statusCode : '?'}`]
274
+ });
275
+ });
276
+ }
277
+
278
+ _doRequest(pResolvedSettings.Retries || 0);
279
+ }
280
+ }
281
+ ];
@@ -0,0 +1,26 @@
1
+ {
2
+ "Hash": "get-json",
3
+ "Type": "get-json",
4
+ "Name": "Get JSON",
5
+ "Description": "Performs an HTTP GET request and parses the response as JSON.",
6
+ "Category": "rest",
7
+ "Capability": "HTTP Client",
8
+ "Action": "GetJSON",
9
+ "Tier": "Platform",
10
+ "EventInputs": [{ "Name": "Trigger" }],
11
+ "EventOutputs": [
12
+ { "Name": "Complete" },
13
+ { "Name": "Error", "IsError": true }
14
+ ],
15
+ "SettingsInputs": [
16
+ { "Name": "URL", "DataType": "String", "Required": true, "Description": "URL to GET" },
17
+ { "Name": "Headers", "DataType": "String", "Required": false, "Description": "JSON string of request headers" },
18
+ { "Name": "Destination", "DataType": "String", "Required": false, "Description": "State address to store response data" },
19
+ { "Name": "TimeoutMs", "DataType": "Number", "Required": false, "Description": "Request timeout in milliseconds" }
20
+ ],
21
+ "StateOutputs": [
22
+ { "Name": "Data", "DataType": "Object", "Description": "Parsed JSON response" },
23
+ { "Name": "StatusCode", "DataType": "Number", "Description": "HTTP response status code" }
24
+ ],
25
+ "DefaultSettings": { "URL": "", "Headers": "", "Destination": "", "TimeoutMs": 30000 }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "Hash": "get-text",
3
+ "Type": "get-text",
4
+ "Name": "Get Text",
5
+ "Description": "Performs an HTTP GET request and returns the response as text.",
6
+ "Category": "rest",
7
+ "Capability": "HTTP Client",
8
+ "Action": "GetText",
9
+ "Tier": "Platform",
10
+ "EventInputs": [{ "Name": "Trigger" }],
11
+ "EventOutputs": [
12
+ { "Name": "Complete" },
13
+ { "Name": "Error", "IsError": true }
14
+ ],
15
+ "SettingsInputs": [
16
+ { "Name": "URL", "DataType": "String", "Required": true, "Description": "URL to GET" },
17
+ { "Name": "Destination", "DataType": "String", "Required": false, "Description": "State address to store response text" },
18
+ { "Name": "Headers", "DataType": "String", "Required": false, "Description": "JSON string of request headers" },
19
+ { "Name": "TimeoutMs", "DataType": "Number", "Required": false, "Description": "Request timeout in milliseconds" }
20
+ ],
21
+ "StateOutputs": [
22
+ { "Name": "Data", "DataType": "String", "Description": "Response text" },
23
+ { "Name": "StatusCode", "DataType": "Number", "Description": "HTTP response status code" }
24
+ ],
25
+ "DefaultSettings": { "URL": "", "Destination": "", "Headers": "", "TimeoutMs": 30000 }
26
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "Hash": "rest-request",
3
+ "Type": "rest-request",
4
+ "Name": "REST Request",
5
+ "Description": "Performs a fully configurable HTTP REST request.",
6
+ "Category": "rest",
7
+ "Capability": "HTTP Client",
8
+ "Action": "Request",
9
+ "Tier": "Platform",
10
+ "EventInputs": [{ "Name": "In" }],
11
+ "EventOutputs": [
12
+ { "Name": "Complete" },
13
+ { "Name": "Error", "IsError": true }
14
+ ],
15
+ "SettingsInputs": [
16
+ { "Name": "URL", "DataType": "String", "Required": true, "Description": "URL to request" },
17
+ { "Name": "Method", "DataType": "String", "Required": false, "Description": "HTTP method (GET, POST, PUT, DELETE, etc.)" },
18
+ { "Name": "ContentType", "DataType": "String", "Required": false, "Description": "Content-Type header" },
19
+ { "Name": "Headers", "DataType": "String", "Required": false, "Description": "JSON string of request headers" },
20
+ { "Name": "Body", "DataType": "String", "Required": false, "Description": "Request body (JSON string or raw text)" },
21
+ { "Name": "Destination", "DataType": "String", "Required": false, "Description": "State address to store response" },
22
+ { "Name": "Retries", "DataType": "Number", "Required": false, "Description": "Number of retries on failure" },
23
+ { "Name": "TimeoutMs", "DataType": "Number", "Required": false, "Description": "Request timeout in milliseconds" },
24
+ { "Name": "RetryDelayMs", "DataType": "Number", "Required": false, "Description": "Delay between retry attempts in milliseconds" }
25
+ ],
26
+ "StateOutputs": [
27
+ { "Name": "Response", "DataType": "Object", "Description": "Response data" },
28
+ { "Name": "StatusCode", "DataType": "Number", "Description": "HTTP response status code" },
29
+ { "Name": "ResponseHeaders", "DataType": "String", "Description": "JSON string of response headers" }
30
+ ],
31
+ "DefaultSettings": { "URL": "", "Method": "GET", "ContentType": "application/json", "Headers": "", "Body": "", "Destination": "", "Retries": 0, "TimeoutMs": 30000, "RetryDelayMs": 1000 }
32
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "Hash": "send-json",
3
+ "Type": "send-json",
4
+ "Name": "Send JSON",
5
+ "Description": "Sends JSON data via HTTP POST or PUT.",
6
+ "Category": "rest",
7
+ "Capability": "HTTP Client",
8
+ "Action": "SendJSON",
9
+ "Tier": "Platform",
10
+ "EventInputs": [{ "Name": "Trigger" }],
11
+ "EventOutputs": [
12
+ { "Name": "Complete" },
13
+ { "Name": "Error", "IsError": true }
14
+ ],
15
+ "SettingsInputs": [
16
+ { "Name": "URL", "DataType": "String", "Required": true, "Description": "URL to send data to" },
17
+ { "Name": "Method", "DataType": "String", "Required": false, "Description": "HTTP method (POST or PUT)" },
18
+ { "Name": "DataAddress", "DataType": "String", "Required": false, "Description": "State address of the data to send" },
19
+ { "Name": "Headers", "DataType": "String", "Required": false, "Description": "JSON string of request headers" },
20
+ { "Name": "Destination", "DataType": "String", "Required": false, "Description": "State address to store response" },
21
+ { "Name": "TimeoutMs", "DataType": "Number", "Required": false, "Description": "Request timeout in milliseconds" }
22
+ ],
23
+ "StateOutputs": [
24
+ { "Name": "Response", "DataType": "Object", "Description": "Response data" },
25
+ { "Name": "StatusCode", "DataType": "Number", "Description": "HTTP response status code" }
26
+ ],
27
+ "DefaultSettings": { "URL": "", "Method": "POST", "DataAddress": "", "Headers": "", "Destination": "", "TimeoutMs": 30000 }
28
+ }