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.
- package/.claude/launch.json +11 -0
- package/.claude/ultravisor-dev-config.json +3 -0
- package/card-audit.json +1545 -0
- package/docs/_sidebar.md +17 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/features/beacon-authentication.md +209 -0
- package/docs/features/beacon-providers.md +1299 -0
- package/docs/features/beacons.md +530 -0
- package/docs/features/capabilities.md +193 -0
- package/docs/features/llm-model-setup.md +505 -0
- package/docs/features/llm.md +262 -0
- package/docs/features/tasks-content-system.md +110 -0
- package/docs/features/tasks-data-transform.md +233 -0
- package/docs/features/tasks-extension.md +36 -0
- package/docs/features/tasks-file-system.md +203 -0
- package/docs/features/tasks-flow-control.md +125 -0
- package/docs/features/tasks-http-client.md +119 -0
- package/docs/features/tasks-llm.md +118 -0
- package/docs/features/tasks-meadow-api.md +163 -0
- package/docs/features/tasks-user-interaction.md +49 -0
- package/docs/features/tasks.md +14 -0
- package/docs/index.html +1 -1
- package/docs/retold-catalog.json +1 -1
- package/docs/retold-keyword-index.json +17374 -5
- package/operation-library/api-data-pipeline.json +143 -0
- package/operation-library/beacon-remote-command.json +72 -0
- package/operation-library/conditional-file-backup.json +143 -0
- package/operation-library/config-processor.json +136 -0
- package/operation-library/csv-data-analysis.json +228 -0
- package/operation-library/csv-to-json.json +160 -0
- package/operation-library/directory-inventory.json +128 -0
- package/operation-library/expression-calculator.json +114 -0
- package/operation-library/file-search-replace.json +175 -0
- package/operation-library/git-status-report.json +368 -0
- package/operation-library/health-check-ping.json +329 -0
- package/operation-library/json-config-merge.json +313 -0
- package/operation-library/llm-embedding-tool-use.json +314 -0
- package/operation-library/llm-multi-turn-analysis.json +322 -0
- package/operation-library/llm-summarize.json +264 -0
- package/operation-library/log-line-counter.json +185 -0
- package/operation-library/meadow-crud-lifecycle.json +264 -0
- package/operation-library/npm-project-validator.json +193 -0
- package/operation-library/rest-api-orchestrator.json +218 -0
- package/operation-library/shell-system-info.json +137 -0
- package/operation-library/simple-echo.json +95 -0
- package/operation-library/template-processor.json +299 -0
- package/operation-library/text-sanitizer.json +176 -0
- package/package.json +12 -8
- package/source/Ultravisor.cjs +30 -3
- package/source/beacon/Ultravisor-Beacon-CLI.cjs +143 -0
- package/source/beacon/Ultravisor-Beacon-CapabilityProvider.cjs +129 -0
- package/source/beacon/Ultravisor-Beacon-Client.cjs +568 -0
- package/source/beacon/Ultravisor-Beacon-Executor.cjs +500 -0
- package/source/beacon/Ultravisor-Beacon-ProviderRegistry.cjs +330 -0
- package/source/beacon/providers/Ultravisor-Beacon-Provider-FileSystem.cjs +331 -0
- package/source/beacon/providers/Ultravisor-Beacon-Provider-LLM.cjs +966 -0
- package/source/beacon/providers/Ultravisor-Beacon-Provider-Shell.cjs +95 -0
- package/source/cli/Ultravisor-CLIProgram.cjs +44 -22
- package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
- package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
- package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
- package/source/config/Ultravisor-Default-Command-Configuration.cjs +12 -3
- package/source/services/Ultravisor-Beacon-Coordinator.cjs +966 -0
- package/source/services/Ultravisor-ExecutionEngine.cjs +1093 -0
- package/source/services/Ultravisor-ExecutionManifest.cjs +629 -0
- package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
- package/source/services/Ultravisor-Hypervisor.cjs +185 -75
- package/source/services/Ultravisor-Schedule-Persistence-Base.cjs +45 -0
- package/source/services/Ultravisor-StateManager.cjs +253 -0
- package/source/services/Ultravisor-TaskTypeRegistry.cjs +213 -0
- package/source/services/persistence/Ultravisor-Schedule-Persistence-JSONFile.cjs +140 -0
- package/source/services/tasks/Ultravisor-BuiltIn-TaskConfigs.cjs +19 -0
- package/source/services/tasks/Ultravisor-TaskHelper-BeaconDispatch.cjs +107 -0
- package/source/services/tasks/Ultravisor-TaskType-Base.cjs +125 -0
- package/source/services/tasks/content-system/Ultravisor-TaskConfigs-ContentSystem.cjs +90 -0
- package/source/services/tasks/content-system/definitions/content-create-folder.json +24 -0
- package/source/services/tasks/content-system/definitions/content-list-files.json +27 -0
- package/source/services/tasks/content-system/definitions/content-read-file.json +26 -0
- package/source/services/tasks/content-system/definitions/content-save-file.json +26 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskConfigs-DataTransform.cjs +577 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskType-ReplaceString.cjs +80 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskType-SetValues.cjs +74 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskType-StringAppender.cjs +90 -0
- package/source/services/tasks/data-transform/definitions/comprehension-intersect.json +24 -0
- package/source/services/tasks/data-transform/definitions/csv-transform.json +24 -0
- package/source/services/tasks/data-transform/definitions/expression-solver.json +20 -0
- package/source/services/tasks/data-transform/definitions/histogram.json +23 -0
- package/source/services/tasks/data-transform/definitions/parse-csv.json +27 -0
- package/source/services/tasks/data-transform/definitions/replace-string.json +27 -0
- package/source/services/tasks/data-transform/definitions/set-values.json +17 -0
- package/source/services/tasks/data-transform/definitions/string-appender.json +22 -0
- package/source/services/tasks/data-transform/definitions/template-string.json +20 -0
- package/source/services/tasks/extension/Ultravisor-TaskConfigs-Extension.cjs +87 -0
- package/source/services/tasks/extension/definitions/beacon-dispatch.json +32 -0
- package/source/services/tasks/file-system/Ultravisor-TaskConfigs-FileSystem.cjs +509 -0
- package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFile.cjs +96 -0
- package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFileBuffered.cjs +123 -0
- package/source/services/tasks/file-system/Ultravisor-TaskType-WriteFile.cjs +106 -0
- package/source/services/tasks/file-system/definitions/copy-file.json +27 -0
- package/source/services/tasks/file-system/definitions/list-files.json +27 -0
- package/source/services/tasks/file-system/definitions/read-file-buffered.json +31 -0
- package/source/services/tasks/file-system/definitions/read-file.json +26 -0
- package/source/services/tasks/file-system/definitions/read-json.json +23 -0
- package/source/services/tasks/file-system/definitions/write-file.json +29 -0
- package/source/services/tasks/file-system/definitions/write-json.json +30 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskConfigs-FlowControl.cjs +353 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskType-IfConditional.cjs +125 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskType-LaunchOperation.cjs +186 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskType-SplitExecute.cjs +164 -0
- package/source/services/tasks/flow-control/definitions/if-conditional.json +25 -0
- package/source/services/tasks/flow-control/definitions/launch-operation.json +27 -0
- package/source/services/tasks/flow-control/definitions/split-execute.json +32 -0
- package/source/services/tasks/http-client/Ultravisor-TaskConfigs-HttpClient.cjs +281 -0
- package/source/services/tasks/http-client/definitions/get-json.json +26 -0
- package/source/services/tasks/http-client/definitions/get-text.json +26 -0
- package/source/services/tasks/http-client/definitions/rest-request.json +32 -0
- package/source/services/tasks/http-client/definitions/send-json.json +28 -0
- package/source/services/tasks/llm/Ultravisor-TaskConfigs-LLM.cjs +605 -0
- package/source/services/tasks/llm/definitions/llm-chat-completion.json +46 -0
- package/source/services/tasks/llm/definitions/llm-embedding.json +31 -0
- package/source/services/tasks/llm/definitions/llm-tool-use.json +42 -0
- package/source/services/tasks/meadow-api/Ultravisor-TaskConfigs-MeadowApi.cjs +341 -0
- package/source/services/tasks/meadow-api/definitions/meadow-count.json +26 -0
- package/source/services/tasks/meadow-api/definitions/meadow-create.json +26 -0
- package/source/services/tasks/meadow-api/definitions/meadow-delete.json +23 -0
- package/source/services/tasks/meadow-api/definitions/meadow-read.json +26 -0
- package/source/services/tasks/meadow-api/definitions/meadow-reads.json +29 -0
- package/source/services/tasks/meadow-api/definitions/meadow-update.json +26 -0
- package/source/services/tasks/shell/Ultravisor-TaskConfigs-Shell.cjs +63 -0
- package/source/services/tasks/shell/definitions/command.json +29 -0
- package/source/services/tasks/user-interaction/Ultravisor-TaskConfigs-UserInteraction.cjs +64 -0
- package/source/services/tasks/user-interaction/Ultravisor-TaskType-ErrorMessage.cjs +55 -0
- package/source/services/tasks/user-interaction/Ultravisor-TaskType-ValueInput.cjs +47 -0
- package/source/services/tasks/user-interaction/definitions/error-message.json +18 -0
- package/source/services/tasks/user-interaction/definitions/value-input.json +23 -0
- package/source/web_server/Ultravisor-API-Server.cjs +849 -124
- package/test/Ultravisor_browser_tests.js +2226 -0
- package/test/Ultravisor_operation_library_tests.js +894 -0
- package/test/Ultravisor_tests.js +4946 -5044
- package/test/workflows/test-content-concatenate-all.json +339 -0
- package/test/workflows/test-content-full-pipeline.json +159 -0
- package/test/workflows/test-content-list-files.json +76 -0
- package/test/workflows/test-content-save-and-read.json +106 -0
- package/webinterface/css/ultravisor-themes.css +668 -0
- package/webinterface/css/ultravisor.css +37 -14
- package/webinterface/docs/card-help/beacon-dispatch.md +30 -0
- package/webinterface/docs/card-help/command.md +27 -0
- package/webinterface/docs/card-help/comprehension-intersect.md +24 -0
- package/webinterface/docs/card-help/content-create-folder.md +22 -0
- package/webinterface/docs/card-help/content-list-files.md +25 -0
- package/webinterface/docs/card-help/content-read-file.md +24 -0
- package/webinterface/docs/card-help/content-save-file.md +24 -0
- package/webinterface/docs/card-help/copy-file.md +25 -0
- package/webinterface/docs/card-help/csv-transform.md +24 -0
- package/webinterface/docs/card-help/end.md +11 -0
- package/webinterface/docs/card-help/error-message.md +16 -0
- package/webinterface/docs/card-help/expression-solver.md +21 -0
- package/webinterface/docs/card-help/get-json.md +24 -0
- package/webinterface/docs/card-help/get-text.md +24 -0
- package/webinterface/docs/card-help/histogram.md +23 -0
- package/webinterface/docs/card-help/if-conditional.md +23 -0
- package/webinterface/docs/card-help/launch-operation.md +25 -0
- package/webinterface/docs/card-help/list-files.md +25 -0
- package/webinterface/docs/card-help/llm-chat-completion.md +43 -0
- package/webinterface/docs/card-help/llm-embedding.md +24 -0
- package/webinterface/docs/card-help/llm-tool-use.md +39 -0
- package/webinterface/docs/card-help/meadow-count.md +24 -0
- package/webinterface/docs/card-help/meadow-create.md +24 -0
- package/webinterface/docs/card-help/meadow-delete.md +19 -0
- package/webinterface/docs/card-help/meadow-read.md +24 -0
- package/webinterface/docs/card-help/meadow-reads.md +27 -0
- package/webinterface/docs/card-help/meadow-update.md +24 -0
- package/webinterface/docs/card-help/parse-csv.md +27 -0
- package/webinterface/docs/card-help/read-file-buffered.md +29 -0
- package/webinterface/docs/card-help/read-file.md +24 -0
- package/webinterface/docs/card-help/read-json.md +21 -0
- package/webinterface/docs/card-help/replace-string.md +25 -0
- package/webinterface/docs/card-help/rest-request.md +30 -0
- package/webinterface/docs/card-help/send-json.md +26 -0
- package/webinterface/docs/card-help/set-values.md +16 -0
- package/webinterface/docs/card-help/split-execute.md +35 -0
- package/webinterface/docs/card-help/start.md +11 -0
- package/webinterface/docs/card-help/string-appender.md +22 -0
- package/webinterface/docs/card-help/template-string.md +21 -0
- package/webinterface/docs/card-help/value-input.md +24 -0
- package/webinterface/docs/card-help/write-file.md +27 -0
- package/webinterface/docs/card-help/write-json.md +28 -0
- package/webinterface/html/index.html +5 -0
- package/webinterface/package.json +13 -4
- package/webinterface/source/Pict-Application-Ultravisor.js +564 -70
- package/webinterface/source/Ultravisor-TimingUtils.js +99 -0
- package/webinterface/source/card-help-content.js +46 -0
- package/webinterface/source/cards/Ultravisor-BuiltIn-CardConfigs.js +174 -0
- package/webinterface/source/cards/Ultravisor-CardConfigGenerator.js +431 -0
- package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
- package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
- package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
- package/webinterface/source/panels/Ultravisor-CardSettingsPanel.js +902 -0
- package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +20 -8
- package/webinterface/source/views/PictView-Ultravisor-BeaconList.js +817 -0
- package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +5 -5
- package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +25 -25
- package/webinterface/source/views/PictView-Ultravisor-Documentation.js +856 -0
- package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +777 -0
- package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +321 -58
- package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +36 -91
- package/webinterface/source/views/PictView-Ultravisor-OperationList.js +388 -16
- package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
- package/webinterface/source/views/PictView-Ultravisor-Schedule.js +521 -65
- package/webinterface/source/views/PictView-Ultravisor-TimingView.js +333 -71
- package/webinterface/source/views/PictView-Ultravisor-TopBar.js +257 -21
- package/webinterface/theme-sampler.html +645 -0
- package/debug/Harness.js +0 -6
- package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
- package/source/services/Ultravisor-Operation.cjs +0 -200
- package/source/services/Ultravisor-Task.cjs +0 -349
- package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
- package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
- package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
- package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
- package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
- package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
- package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
- package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
- package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
- package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
- package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
- package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
- package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
- package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
- package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
- package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
- package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
- package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
- package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
- package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
- package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
- package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
- 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.
|