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,530 @@
1
+ # Beacons
2
+
3
+ Beacons are remote worker nodes that connect to an Ultravisor server and
4
+ execute Extension-tier tasks. They allow you to distribute work across
5
+ multiple machines, offloading specialized or resource-intensive operations
6
+ to purpose-built workers while the orchestrator manages the overall
7
+ operation graph.
8
+
9
+ A Beacon might be a GPU server running inference, a build machine compiling
10
+ code, or a simple shell worker on a different host. The Beacon system is the
11
+ bridge between Ultravisor's operation engine and the outside world.
12
+
13
+ ## Architecture
14
+
15
+ The Beacon system uses the same **WaitingForInput** pause/resume mechanism
16
+ that powers interactive tasks like `value-input`. When a `beacon-dispatch`
17
+ node executes, it does not block the engine — instead it enqueues a work
18
+ item and returns `WaitingForInput`. The operation pauses at that node until
19
+ a Beacon picks up the work, executes it remotely, and reports results.
20
+
21
+ The full cycle looks like this:
22
+
23
+ ```
24
+ ┌──────────────────┐ ┌──────────────────────┐ ┌──────────────┐
25
+ │ Operation Graph │ │ BeaconCoordinator │ │ Beacon │
26
+ │ │ │ (server-side) │ │ (remote) │
27
+ │ beacon-dispatch │──enqueue──▶ Work Queue │ │ │
28
+ │ returns │ │ │◀──poll───│ poll loop │
29
+ │ WaitingForInput │ │ assign work item │──work──▶ │ execute │
30
+ │ ⋮ │ │ │ │ locally │
31
+ │ (paused) │ │ │◀─result──│ report back │
32
+ │ ⋮ │ │ resumeOperation() │ │ │
33
+ │ graph continues │◀──resume──│ │ │ │
34
+ └──────────────────┘ └──────────────────────┘ └──────────────┘
35
+ ```
36
+
37
+ ### Transport Agnostic
38
+
39
+ The BeaconCoordinator's internal API (`enqueueWorkItem`, `completeWorkItem`,
40
+ `failWorkItem`) is transport-agnostic. The built-in REST endpoints drive
41
+ those methods via HTTP polling, but the same coordinator can be fronted by
42
+ WebSocket push, MQTT messages, email/SMS webhooks, or any other signaling
43
+ channel without changing the core dispatch logic.
44
+
45
+ ## Affinity System
46
+
47
+ Many real-world pipelines require that related tasks execute on the same
48
+ worker. For example, a video processing pipeline might split a file across
49
+ multiple encoding passes — each pass needs access to the same local copy of
50
+ the source footage.
51
+
52
+ The **AffinityKey** setting on `beacon-dispatch` nodes solves this.
53
+
54
+ ### How It Works
55
+
56
+ 1. The first `beacon-dispatch` task with a given AffinityKey is claimed by
57
+ whichever Beacon picks it up. The coordinator records a binding:
58
+ `AffinityKey → BeaconID`.
59
+ 2. Subsequent tasks with the **same** AffinityKey are pre-assigned to that
60
+ same Beacon. When the Beacon polls, it receives affinity-assigned items
61
+ first.
62
+ 3. Bindings expire after a configurable TTL (default: one hour). Once
63
+ expired, a new Beacon may claim the key.
64
+
65
+ ### Dynamic Keys with Templates
66
+
67
+ AffinityKey values support Pict template syntax, allowing them to resolve
68
+ dynamically from operation state at execution time:
69
+
70
+ ```
71
+ {~D:Record.TaskOutput.splitter.CurrentToken~}
72
+ ```
73
+
74
+ This is useful inside `split-execute` loops where each iteration should
75
+ pin to its own worker. The template resolves to a unique value per token,
76
+ creating one affinity binding per chunk.
77
+
78
+ ### Manual Clearing
79
+
80
+ Affinity bindings can be cleared manually through the `GET /Beacon/Affinity`
81
+ endpoint (to list them) and will be automatically purged when their TTL
82
+ expires. The coordinator's timeout checker cleans up expired bindings every
83
+ 10 seconds.
84
+
85
+ ## Capabilities
86
+
87
+ Each Beacon advertises the set of **Capabilities** it supports when it
88
+ registers. Capabilities are the same taxonomy used by the task type system
89
+ (see [Capabilities and Actions](capabilities.md)).
90
+
91
+ When the coordinator receives a poll request, it matches the work item's
92
+ `Capability` field against the polling Beacon's advertised capabilities.
93
+ A Beacon only receives work items it is equipped to handle.
94
+
95
+ Common capability names:
96
+
97
+ | Capability | Typical Use |
98
+ |------------|-------------|
99
+ | `Shell` | Execute operating system commands |
100
+ | `FileSystem` | Read, write, copy, and list files |
101
+ | `HTTPClient` | Make outbound HTTP requests |
102
+ | `MLInference` | Run machine-learning model inference |
103
+ | `MediaProcessing` | Transcode video/audio, generate thumbnails |
104
+
105
+ You can define any capability string you like — the coordinator treats them
106
+ as opaque labels for matching purposes.
107
+
108
+ ## API Reference
109
+
110
+ All Beacon endpoints are served under the `/Beacon` path prefix.
111
+
112
+ ### POST /Beacon/Register
113
+
114
+ Register a new Beacon worker with the coordinator.
115
+
116
+ **Request body:**
117
+
118
+ | Field | Type | Required | Description |
119
+ |-------|------|----------|-------------|
120
+ | `Name` | string | yes | Human-readable name for the Beacon |
121
+ | `Capabilities` | array | yes | List of capability strings |
122
+ | `MaxConcurrent` | number | no | Maximum concurrent work items (default: 1) |
123
+ | `Tags` | object | no | Arbitrary key-value metadata |
124
+
125
+ **Response:** The created Beacon record including the assigned `BeaconID`.
126
+
127
+ ---
128
+
129
+ ### GET /Beacon
130
+
131
+ List all registered Beacons.
132
+
133
+ **Response:** Array of Beacon records.
134
+
135
+ ---
136
+
137
+ ### GET /Beacon/:BeaconID
138
+
139
+ Get a specific Beacon by ID.
140
+
141
+ **Response:** Beacon record, or 404 if not found.
142
+
143
+ ---
144
+
145
+ ### DELETE /Beacon/:BeaconID
146
+
147
+ Deregister a Beacon. Any work items currently assigned to it are released
148
+ back to Pending status so another Beacon can pick them up.
149
+
150
+ **Response:** `{ Status: "Deregistered", BeaconID: "..." }`
151
+
152
+ ---
153
+
154
+ ### POST /Beacon/:BeaconID/Heartbeat
155
+
156
+ Send a heartbeat to confirm the Beacon is still alive. The coordinator
157
+ marks Beacons as Offline if they miss heartbeats beyond the configured
158
+ timeout.
159
+
160
+ **Response:** Updated Beacon record.
161
+
162
+ ---
163
+
164
+ ### POST /Beacon/Work/Poll
165
+
166
+ Poll for available work matching the Beacon's capabilities. Also acts as
167
+ an implicit heartbeat.
168
+
169
+ **Request body:**
170
+
171
+ | Field | Type | Required | Description |
172
+ |-------|------|----------|-------------|
173
+ | `BeaconID` | string | yes | The polling Beacon's ID |
174
+
175
+ **Response:** `{ WorkItem: {...} }` with the assigned work item, or
176
+ `{ WorkItem: null }` if no work is available.
177
+
178
+ ---
179
+
180
+ ### POST /Beacon/Work/:WorkItemHash/Complete
181
+
182
+ Report successful completion of a work item. The coordinator calls
183
+ `resumeOperation()` to continue the paused graph.
184
+
185
+ **Request body:**
186
+
187
+ | Field | Type | Required | Description |
188
+ |-------|------|----------|-------------|
189
+ | `Outputs` | object | no | Key-value output data (e.g. `StdOut`, `ExitCode`) |
190
+ | `Log` | array | no | Array of log strings |
191
+
192
+ **Response:** `{ Status: "Completed", WorkItemHash: "..." }`
193
+
194
+ ---
195
+
196
+ ### POST /Beacon/Work/:WorkItemHash/Error
197
+
198
+ Report failure of a work item. The coordinator resumes the graph through
199
+ the Error event path.
200
+
201
+ **Request body:**
202
+
203
+ | Field | Type | Required | Description |
204
+ |-------|------|----------|-------------|
205
+ | `ErrorMessage` | string | no | Description of the error |
206
+ | `Log` | array | no | Array of log strings |
207
+
208
+ **Response:** `{ Status: "Failed", WorkItemHash: "..." }`
209
+
210
+ ---
211
+
212
+ ### GET /Beacon/Work
213
+
214
+ List all work items currently in the queue (all statuses).
215
+
216
+ **Response:** Array of work item records.
217
+
218
+ ---
219
+
220
+ ### GET /Beacon/Affinity
221
+
222
+ List all active affinity bindings.
223
+
224
+ **Response:** Array of affinity binding records, each containing
225
+ `AffinityKey`, `BeaconID`, `CreatedAt`, and `ExpiresAt`.
226
+
227
+ ## Custom Capability Providers
228
+
229
+ Beacons use a pluggable **CapabilityProvider** system. Each provider handles
230
+ one or more capabilities and their associated actions. Two providers ship
231
+ built-in (Shell and FileSystem), and you can add your own.
232
+
233
+ For full, runnable examples (headless Chrome, FFmpeg transcoding), see the
234
+ [Building Beacon Providers](beacon-providers.md) guide.
235
+
236
+ ### The Provider Interface
237
+
238
+ Every provider extends the `UltravisorBeaconCapabilityProvider` base class:
239
+
240
+ ```js
241
+ const libBeaconCapabilityProvider = require('ultravisor').BeaconCapabilityProvider;
242
+
243
+ class MyFFmpegProvider extends libBeaconCapabilityProvider
244
+ {
245
+ constructor(pProviderConfig)
246
+ {
247
+ super(pProviderConfig);
248
+ this.Name = 'FFmpeg';
249
+ this.Capability = 'MediaProcessing';
250
+ }
251
+
252
+ get actions()
253
+ {
254
+ return {
255
+ 'Transcode': { Description: 'Transcode a media file' },
256
+ 'Thumbnail': { Description: 'Extract a thumbnail frame' }
257
+ };
258
+ }
259
+
260
+ execute(pAction, pWorkItem, pContext, fCallback, fReportProgress)
261
+ {
262
+ // pAction is 'Transcode' or 'Thumbnail'
263
+ // pWorkItem.Settings has the task parameters
264
+ // pContext.StagingPath is the local staging directory
265
+ // fReportProgress({ Percent: 50, Message: '...' }) for progress
266
+ // fCallback(null, { Outputs: { ... }, Log: [...] }) when done
267
+ }
268
+ }
269
+
270
+ module.exports = MyFFmpegProvider;
271
+ ```
272
+
273
+ Key methods:
274
+
275
+ | Method | Purpose |
276
+ |--------|---------|
277
+ | `get actions()` | Returns `{ ActionName: { Description } }` map of supported actions |
278
+ | `execute(pAction, pWorkItem, pContext, fCallback, fReportProgress)` | Execute a work item |
279
+ | `getCapabilities()` | Returns capability strings (default: `[this.Capability]`) |
280
+ | `initialize(fCallback)` | Optional async setup (validate prerequisites, etc.) |
281
+ | `shutdown(fCallback)` | Optional cleanup on Beacon stop |
282
+
283
+ ### Loading Providers via Config
284
+
285
+ The `.ultravisor-beacon.json` file supports a `Providers` array that
286
+ specifies which providers to load:
287
+
288
+ ```json
289
+ {
290
+ "ServerURL": "http://orchestrator:54321",
291
+ "Name": "media-worker-1",
292
+ "MaxConcurrent": 4,
293
+ "StagingPath": "/data/staging",
294
+ "Providers": [
295
+ { "Source": "Shell" },
296
+ {
297
+ "Source": "FileSystem",
298
+ "Config": {
299
+ "AllowedPaths": ["/data/staging", "/data/output"],
300
+ "MaxFileSizeBytes": 104857600
301
+ }
302
+ },
303
+ {
304
+ "Source": "./my-ffmpeg-provider.cjs",
305
+ "Config": { "FFmpegPath": "/usr/bin/ffmpeg" }
306
+ }
307
+ ]
308
+ }
309
+ ```
310
+
311
+ Each entry has:
312
+
313
+ | Field | Description |
314
+ |-------|-------------|
315
+ | `Source` | Built-in name (`Shell`, `FileSystem`), local file path (`./my-provider.cjs`), or npm package name |
316
+ | `Config` | Optional per-provider configuration object, available as `this._ProviderConfig` in the provider |
317
+
318
+ The `Source` field determines how the provider is loaded:
319
+
320
+ - **Built-in names** (`Shell`, `FileSystem`) resolve to the `providers/` directory inside the Beacon module.
321
+ - **Paths starting with `.` or `/`** are loaded via `require(path.resolve(source))`.
322
+ - **Everything else** is loaded via `require(source)`, supporting npm packages.
323
+
324
+ ### Backward Compatibility
325
+
326
+ If `Providers` is absent but `Capabilities` is present, the Beacon
327
+ automatically converts each capability string into a provider descriptor.
328
+ For example, `"Capabilities": ["Shell", "FileSystem"]` is equivalent to
329
+ `"Providers": [{ "Source": "Shell" }, { "Source": "FileSystem" }]`.
330
+
331
+ If neither `Providers` nor `Capabilities` is specified, the Beacon defaults
332
+ to loading the Shell provider.
333
+
334
+ ### Provider Lifecycle
335
+
336
+ When the Beacon starts, all providers are initialized in sequence via their
337
+ `initialize()` method. This is the place to validate prerequisites (e.g.,
338
+ check that `ffmpeg` is installed) before the Beacon begins accepting work.
339
+ If any provider fails to initialize, the Beacon does not start.
340
+
341
+ On shutdown, providers are stopped in sequence via `shutdown()`, allowing
342
+ them to release resources, close connections, or clean up temporary files.
343
+
344
+ ### Built-In Providers
345
+
346
+ #### Shell Provider
347
+
348
+ Executes operating system commands via `child_process.exec()`.
349
+
350
+ - **Capability:** `Shell`
351
+ - **Actions:** `Execute`
352
+ - **Settings:** `Command` (string), `Parameters` (string), `WorkingDirectory` (string)
353
+ - **Config:** `MaxBufferBytes` (default: 10MB)
354
+ - **Outputs:** `StdOut`, `ExitCode`, `Result`
355
+
356
+ #### FileSystem Provider
357
+
358
+ Performs local file operations.
359
+
360
+ - **Capability:** `FileSystem`
361
+ - **Actions:** `Read`, `Write`, `List`, `Copy`
362
+ - **Config:** `AllowedPaths` (string array, empty = allow all), `MaxFileSizeBytes` (default: 100MB)
363
+
364
+ Action settings:
365
+
366
+ | Action | Settings |
367
+ |--------|----------|
368
+ | `Read` | `FilePath`, `Encoding` (default: utf8) |
369
+ | `Write` | `FilePath`, `Content`, `Encoding` (default: utf8) |
370
+ | `List` | `Folder`, `Pattern` (glob, default: *) |
371
+ | `Copy` | `Source`, `TargetFile` |
372
+
373
+ Relative paths in settings are resolved against `pContext.StagingPath`.
374
+
375
+ ## Progress Reporting
376
+
377
+ Providers can report progress during long-running operations. Progress
378
+ updates flow from the provider through the Beacon client to the server,
379
+ where they surface in the manifest's WaitingTasks and the work item record.
380
+
381
+ ### Reporting Progress from a Provider
382
+
383
+ The `fReportProgress` callback passed to `execute()` accepts an object with
384
+ these optional fields:
385
+
386
+ | Field | Type | Description |
387
+ |-------|------|-------------|
388
+ | `Percent` | number | Completion percentage (0–100) |
389
+ | `Message` | string | Human-readable status message |
390
+ | `Step` | number | Current step number |
391
+ | `TotalSteps` | number | Total number of steps |
392
+ | `Log` | array | Array of log strings to accumulate |
393
+
394
+ All fields are optional. Use whichever combination makes sense:
395
+
396
+ ```js
397
+ // Percentage-based progress
398
+ fReportProgress({ Percent: 45, Message: 'Extracting frames...' });
399
+
400
+ // Step-based progress
401
+ fReportProgress({ Step: 3, TotalSteps: 10, Message: 'Pass 3 of 10' });
402
+
403
+ // Log-only (no progress bar update)
404
+ fReportProgress({ Log: ['Processing file xyz.mp4'] });
405
+
406
+ // Combined progress + logging
407
+ fReportProgress({ Percent: 80, Log: ['Scene detection pass 2 complete'] });
408
+ ```
409
+
410
+ ### How Progress Flows
411
+
412
+ 1. **Provider** calls `fReportProgress({ Percent: 50, Message: '...' })`.
413
+ 2. **BeaconClient** sends `POST /Beacon/Work/:Hash/Progress` to the server.
414
+ 3. **BeaconCoordinator** updates the work item record with the progress data
415
+ and appends any `Log` entries to the work item's accumulated log.
416
+ 4. **Manifest** `WaitingTasks` entry for the corresponding node is updated
417
+ with the progress data, visible via `GET /Manifest/:RunHash`.
418
+ 5. On completion, the final `Log` from the Complete call is merged with
419
+ previously accumulated log entries.
420
+
421
+ ### POST /Beacon/Work/:WorkItemHash/Progress
422
+
423
+ Report progress on an in-flight work item.
424
+
425
+ **Request body:**
426
+
427
+ | Field | Type | Required | Description |
428
+ |-------|------|----------|-------------|
429
+ | `Percent` | number | no | Completion percentage (0–100) |
430
+ | `Message` | string | no | Human-readable status message |
431
+ | `Step` | number | no | Current step number |
432
+ | `TotalSteps` | number | no | Total number of steps |
433
+ | `Log` | array | no | Array of log strings to accumulate |
434
+
435
+ **Response:** `{ Success: true }`
436
+
437
+ Progress is fire-and-forget from the Beacon's perspective — failures to
438
+ report progress do not affect work item execution.
439
+
440
+ ## Running a Beacon
441
+
442
+ ### CLI
443
+
444
+ Start a Beacon worker from the command line:
445
+
446
+ ```bash
447
+ node source/beacon/Ultravisor-Beacon-CLI.cjs \
448
+ --server http://orchestrator:54321 \
449
+ --name "GPU-Worker-1" \
450
+ --capabilities Shell,FileSystem
451
+ ```
452
+
453
+ #### CLI Options
454
+
455
+ | Flag | Default | Description |
456
+ |------|---------|-------------|
457
+ | `--server URL` | `http://localhost:54321` | Ultravisor server URL |
458
+ | `--name NAME` | `beacon-worker` | Human-readable Beacon name |
459
+ | `--capabilities LIST` | `Shell` | Comma-separated capability list |
460
+ | `--max-concurrent N` | `1` | Maximum concurrent work items |
461
+ | `--poll-interval MS` | `5000` | Poll interval in milliseconds |
462
+ | `--staging-path PATH` | current directory | Local staging directory for file operations |
463
+
464
+ ### Config File
465
+
466
+ Place a `.ultravisor-beacon.json` file in the working directory to set
467
+ defaults. CLI arguments override config file values.
468
+
469
+ For simple Beacons, use `Capabilities`:
470
+
471
+ ```json
472
+ {
473
+ "ServerURL": "http://orchestrator:54321",
474
+ "Name": "GPU-Worker-1",
475
+ "Capabilities": ["Shell", "FileSystem"],
476
+ "MaxConcurrent": 4,
477
+ "StagingPath": "/data/staging",
478
+ "Tags": {
479
+ "GPU": "A100",
480
+ "Region": "us-west-2"
481
+ }
482
+ }
483
+ ```
484
+
485
+ For advanced setups with custom providers and per-provider config, use
486
+ `Providers` instead (see [Loading Providers via Config](#loading-providers-via-config)).
487
+
488
+ ## Configuration
489
+
490
+ Server-side configuration keys control Beacon timeouts and defaults. Set
491
+ these in your Ultravisor configuration file.
492
+
493
+ | Key | Default | Description |
494
+ |-----|---------|-------------|
495
+ | `UltravisorBeaconHeartbeatTimeoutMs` | `60000` | Time in ms before a Beacon with no heartbeat is marked Offline |
496
+ | `UltravisorBeaconWorkItemTimeoutMs` | `300000` | Time in ms before an in-progress work item is considered timed out |
497
+ | `UltravisorBeaconAffinityTTLMs` | `3600000` | Time in ms before an affinity binding expires |
498
+ | `UltravisorBeaconPollIntervalMs` | `5000` | Default poll interval for Beacon clients |
499
+
500
+ The coordinator runs a timeout checker every 10 seconds that:
501
+
502
+ 1. Fails work items that have exceeded their timeout.
503
+ 2. Marks Beacons as Offline if they have missed their heartbeat window.
504
+ 3. Purges expired affinity bindings.
505
+
506
+ ## Example: Video Processing Pipeline
507
+
508
+ Consider a pipeline that transcodes a batch of video files. The source
509
+ footage lives on a shared volume, but encoding is CPU/GPU-intensive and
510
+ should be distributed across a pool of media workers.
511
+
512
+ 1. **Start** node kicks off the operation.
513
+ 2. A `list-files` node scans the input directory for `.mp4` files.
514
+ 3. A `split-execute` node iterates over the file list. For each file:
515
+ - A `beacon-dispatch` node sends the transcode command to a remote
516
+ Beacon with `MediaProcessing` capability. The AffinityKey is set to
517
+ the filename so that if multiple passes are needed (e.g. two-pass
518
+ encoding), both passes land on the same worker that already has the
519
+ file cached locally.
520
+ - The graph pauses at the dispatch node.
521
+ - A Beacon picks up the work, runs `ffmpeg` locally, and reports
522
+ completion.
523
+ - The graph resumes with the output (new file path, duration, etc.).
524
+ 4. A `template-string` node assembles a summary report.
525
+ 5. **End** node completes the operation.
526
+
527
+ Because each iteration's AffinityKey resolves to a unique value
528
+ (`{~D:Record.TaskOutput.splitter.CurrentToken~}`), the coordinator
529
+ distributes files across available Beacons while keeping multi-pass work
530
+ pinned to the same machine.