ultravisor 1.0.0 → 1.0.2

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 (96) hide show
  1. package/.babelrc +6 -0
  2. package/.browserslistrc +1 -0
  3. package/.browserslistrc-BACKUP +1 -0
  4. package/.gulpfile-quackage-config.json +7 -0
  5. package/.gulpfile-quackage.js +2 -0
  6. package/CONTRIBUTING.md +50 -0
  7. package/README.md +34 -0
  8. package/debug/Harness.js +2 -1
  9. package/docs/.nojekyll +0 -0
  10. package/docs/_sidebar.md +18 -0
  11. package/docs/_topbar.md +7 -0
  12. package/docs/architecture.md +103 -0
  13. package/docs/cover.md +15 -0
  14. package/docs/features/api.md +230 -0
  15. package/docs/features/cli.md +182 -0
  16. package/docs/features/configuration.md +245 -0
  17. package/docs/features/manifests.md +177 -0
  18. package/docs/features/operations.md +292 -0
  19. package/docs/features/scheduling.md +179 -0
  20. package/docs/features/tasks.md +1857 -0
  21. package/docs/index.html +39 -0
  22. package/docs/overview.md +75 -0
  23. package/docs/quickstart.md +167 -0
  24. package/docs/retold-catalog.json +24 -0
  25. package/docs/retold-keyword-index.json +19 -0
  26. package/package.json +5 -2
  27. package/source/Ultravisor.cjs +2 -2
  28. package/source/cli/Ultravisor-CLIProgram.cjs +38 -0
  29. package/source/cli/commands/Ultravisor-Command-ScheduleOperation.cjs +26 -2
  30. package/source/cli/commands/Ultravisor-Command-ScheduleTask.cjs +26 -2
  31. package/source/cli/commands/Ultravisor-Command-ScheduleView.cjs +22 -0
  32. package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +49 -1
  33. package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +51 -1
  34. package/source/cli/commands/Ultravisor-Command-Stop.cjs +4 -0
  35. package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +91 -0
  36. package/source/config/Ultravisor-Default-Command-Configuration.cjs +6 -1
  37. package/source/services/Ultravisor-Hypervisor-Event-Base.cjs +18 -1
  38. package/source/services/Ultravisor-Hypervisor-State.cjs +213 -0
  39. package/source/services/Ultravisor-Hypervisor.cjs +225 -1
  40. package/source/services/Ultravisor-Operation-Manifest.cjs +150 -1
  41. package/source/services/Ultravisor-Operation.cjs +190 -1
  42. package/source/services/Ultravisor-Task.cjs +339 -1
  43. package/source/services/events/Ultravisor-Hypervisor-Event-Cron.cjs +71 -1
  44. package/source/services/tasks/Ultravisor-Task-Base.cjs +264 -0
  45. package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +188 -0
  46. package/source/services/tasks/Ultravisor-Task-Command.cjs +65 -0
  47. package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +190 -0
  48. package/source/services/tasks/Ultravisor-Task-Conditional.cjs +104 -0
  49. package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +72 -0
  50. package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +336 -0
  51. package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +143 -0
  52. package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +146 -0
  53. package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +158 -0
  54. package/source/services/tasks/Ultravisor-Task-Request.cjs +56 -0
  55. package/source/services/tasks/Ultravisor-Task-Solver.cjs +89 -0
  56. package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +93 -0
  57. package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +127 -0
  58. package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +119 -0
  59. package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +109 -0
  60. package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +112 -0
  61. package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +499 -0
  62. package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +150 -0
  63. package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +110 -0
  64. package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +89 -0
  65. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +87 -0
  66. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +67 -0
  67. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +66 -0
  68. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +69 -0
  69. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +95 -0
  70. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +96 -0
  71. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +99 -0
  72. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +102 -0
  73. package/source/web_server/Ultravisor-API-Server.cjs +463 -3
  74. package/test/Ultravisor_tests.js +6097 -1
  75. package/webinterface/.babelrc +6 -0
  76. package/webinterface/.browserslistrc +1 -0
  77. package/webinterface/.browserslistrc-BACKUP +1 -0
  78. package/webinterface/.gulpfile-quackage-config.json +7 -0
  79. package/webinterface/.gulpfile-quackage.js +2 -0
  80. package/webinterface/css/ultravisor.css +121 -0
  81. package/webinterface/html/index.html +32 -0
  82. package/webinterface/package.json +39 -0
  83. package/webinterface/source/Pict-Application-Ultravisor-Configuration.json +15 -0
  84. package/webinterface/source/Pict-Application-Ultravisor.js +414 -0
  85. package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +42 -0
  86. package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +65 -0
  87. package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +236 -0
  88. package/webinterface/source/views/PictView-Ultravisor-Layout.js +83 -0
  89. package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +273 -0
  90. package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +243 -0
  91. package/webinterface/source/views/PictView-Ultravisor-OperationList.js +141 -0
  92. package/webinterface/source/views/PictView-Ultravisor-Schedule.js +280 -0
  93. package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +220 -0
  94. package/webinterface/source/views/PictView-Ultravisor-TaskList.js +248 -0
  95. package/webinterface/source/views/PictView-Ultravisor-TimingView.js +420 -0
  96. package/webinterface/source/views/PictView-Ultravisor-TopBar.js +147 -0
@@ -0,0 +1,245 @@
1
+ # Configuration
2
+
3
+ Ultravisor uses a layered JSON configuration system. Configuration is
4
+ gathered automatically at startup and merged into a single object.
5
+
6
+ ## Configuration File
7
+
8
+ The primary configuration file is `.ultravisor.json`, located in the
9
+ working directory. This file stores both runtime settings and persisted
10
+ task/operation definitions.
11
+
12
+ ### Minimal Configuration
13
+
14
+ ```json
15
+ {
16
+ "UltravisorAPIServerPort": 54321
17
+ }
18
+ ```
19
+
20
+ ### Full Configuration
21
+
22
+ ```json
23
+ {
24
+ "UltravisorAPIServerPort": 54321,
25
+ "UltravisorFileStorePath": "/var/data/ultravisor_datastore",
26
+ "UltravisorStagingRoot": "/var/data/ultravisor_staging",
27
+ "UltravisorTickIntervalMilliseconds": 60000,
28
+ "Tasks": {
29
+ "my-task": {
30
+ "GUIDTask": "my-task",
31
+ "Name": "My Task",
32
+ "Type": "Command",
33
+ "Command": "echo hello"
34
+ }
35
+ },
36
+ "Operations": {
37
+ "my-op": {
38
+ "GUIDOperation": "my-op",
39
+ "Name": "My Operation",
40
+ "Tasks": ["my-task"]
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## Configuration Options
47
+
48
+ | Key | Type | Default | Description |
49
+ |-----|------|---------|-------------|
50
+ | `UltravisorAPIServerPort` | Number | `54321` | Port for the REST API server |
51
+ | `UltravisorFileStorePath` | String | `${cwd}/dist/ultravisor_datastore` | Path for the output file store |
52
+ | `UltravisorStagingRoot` | String | `${cwd}/dist/ultravisor_staging` | Root folder for per-operation staging directories |
53
+ | `UltravisorTickIntervalMilliseconds` | Number | `60000` | Base tick interval in milliseconds |
54
+ | `UltravisorCommandTimeoutMilliseconds` | Number | `300000` | Timeout for command task execution (5 minutes) |
55
+ | `UltravisorCommandMaxBufferBytes` | Number | `10485760` | Max stdout/stderr buffer size for commands (10 MB) |
56
+ | `Tasks` | Object | `{}` | Map of task GUIDs to task definitions |
57
+ | `Operations` | Object | `{}` | Map of operation GUIDs to operation definitions |
58
+
59
+ ## Configuration Layering
60
+
61
+ Configuration is resolved in order (later layers override earlier):
62
+
63
+ 1. **Default Program Configuration** -- hardcoded defaults in
64
+ `source/config/Ultravisor-Default-Command-Configuration.cjs`:
65
+
66
+ ```json
67
+ {
68
+ "UltravisorAPIServerPort": 54321,
69
+ "UltravisorFileStorePath": "${cwd}/dist/ultravisor_datastore",
70
+ "UltravisorStagingRoot": "${cwd}/dist/ultravisor_staging",
71
+ "UltravisorTickIntervalMilliseconds": 60000,
72
+ "UltravisorCommandTimeoutMilliseconds": 300000,
73
+ "UltravisorCommandMaxBufferBytes": 10485760
74
+ }
75
+ ```
76
+
77
+ 2. **`.ultravisor.json`** -- project-level file searched from the current
78
+ working directory upward through parent directories
79
+
80
+ The merged result is available as `fable.ProgramConfiguration` within
81
+ services.
82
+
83
+ ## Viewing Configuration Resolution
84
+
85
+ Use the built-in `configuration` command to see how Ultravisor resolved
86
+ its configuration:
87
+
88
+ ```bash
89
+ ultravisor configuration
90
+ ```
91
+
92
+ This shows each gather phase, what file was loaded, and what values came
93
+ from where.
94
+
95
+ ## State Persistence
96
+
97
+ When tasks or operations are created/updated via the CLI (`updatetask`)
98
+ or the API (`POST /Task`, `POST /Operation`), the state service merges
99
+ the changes back into the `.ultravisor.json` file.
100
+
101
+ The merge logic:
102
+ - The existing file is read
103
+ - New or updated tasks/operations are merged (existing fields preserved,
104
+ new fields added)
105
+ - The entire configuration is written back to the file
106
+
107
+ This means the `.ultravisor.json` file serves as both configuration and
108
+ persistent storage.
109
+
110
+ ## Example Configurations
111
+
112
+ ### Simple API monitoring
113
+
114
+ ```json
115
+ {
116
+ "UltravisorAPIServerPort": 8080,
117
+ "Tasks": {
118
+ "health-check": {
119
+ "GUIDTask": "health-check",
120
+ "Name": "API Health Check",
121
+ "Type": "Request",
122
+ "URL": "https://api.example.com/health"
123
+ }
124
+ },
125
+ "Operations": {}
126
+ }
127
+ ```
128
+
129
+ ### Multi-task data pipeline
130
+
131
+ ```json
132
+ {
133
+ "UltravisorAPIServerPort": 54321,
134
+ "UltravisorFileStorePath": "/data/ultravisor",
135
+ "Tasks": {
136
+ "extract": {
137
+ "GUIDTask": "extract",
138
+ "Name": "Extract Data",
139
+ "Type": "Command",
140
+ "Command": "python3 /scripts/extract.py --output /tmp/extract.json"
141
+ },
142
+ "transform": {
143
+ "GUIDTask": "transform",
144
+ "Name": "Transform Data",
145
+ "Type": "Command",
146
+ "Command": "python3 /scripts/transform.py --input /tmp/extract.json --output /tmp/transformed.json"
147
+ },
148
+ "load": {
149
+ "GUIDTask": "load",
150
+ "Name": "Load Data",
151
+ "Type": "Command",
152
+ "Command": "python3 /scripts/load.py --input /tmp/transformed.json"
153
+ }
154
+ },
155
+ "Operations": {
156
+ "etl": {
157
+ "GUIDOperation": "etl",
158
+ "Name": "Full ETL Pipeline",
159
+ "Tasks": ["extract", "transform", "load"]
160
+ }
161
+ }
162
+ }
163
+ ```
164
+
165
+ ### IoT sensor monitoring
166
+
167
+ ```json
168
+ {
169
+ "UltravisorAPIServerPort": 9000,
170
+ "Tasks": {
171
+ "read-temp-living": {
172
+ "GUIDTask": "read-temp-living",
173
+ "Name": "Read Living Room Temperature",
174
+ "Type": "Request",
175
+ "URL": "http://192.168.1.100/api/temperature"
176
+ },
177
+ "read-temp-bedroom": {
178
+ "GUIDTask": "read-temp-bedroom",
179
+ "Name": "Read Bedroom Temperature",
180
+ "Type": "Request",
181
+ "URL": "http://192.168.1.101/api/temperature"
182
+ },
183
+ "read-temp-garage": {
184
+ "GUIDTask": "read-temp-garage",
185
+ "Name": "Read Garage Temperature",
186
+ "Type": "Request",
187
+ "URL": "http://192.168.1.102/api/temperature"
188
+ },
189
+ "log-readings": {
190
+ "GUIDTask": "log-readings",
191
+ "Name": "Log Temperature Readings",
192
+ "Type": "Command",
193
+ "Command": "python3 /scripts/log_temps.py"
194
+ }
195
+ },
196
+ "Operations": {
197
+ "temp-sweep": {
198
+ "GUIDOperation": "temp-sweep",
199
+ "Name": "Temperature Sweep",
200
+ "Tasks": [
201
+ "read-temp-living",
202
+ "read-temp-bedroom",
203
+ "read-temp-garage",
204
+ "log-readings"
205
+ ]
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ ### Media processing
212
+
213
+ ```json
214
+ {
215
+ "UltravisorAPIServerPort": 54321,
216
+ "UltravisorFileStorePath": "/media/output",
217
+ "Tasks": {
218
+ "scan-input": {
219
+ "GUIDTask": "scan-input",
220
+ "Name": "Scan Input Directory",
221
+ "Type": "Command",
222
+ "Command": "ls -1 /media/input/*.avi > /tmp/pending_files.txt"
223
+ },
224
+ "transcode-batch": {
225
+ "GUIDTask": "transcode-batch",
226
+ "Name": "Transcode Video Batch",
227
+ "Type": "Command",
228
+ "Command": "bash /scripts/transcode_batch.sh /tmp/pending_files.txt /media/output"
229
+ },
230
+ "generate-thumbnails": {
231
+ "GUIDTask": "generate-thumbnails",
232
+ "Name": "Generate Thumbnails",
233
+ "Type": "Command",
234
+ "Command": "bash /scripts/thumbnails.sh /media/output"
235
+ }
236
+ },
237
+ "Operations": {
238
+ "media-ingest": {
239
+ "GUIDOperation": "media-ingest",
240
+ "Name": "Media Ingest Pipeline",
241
+ "Tasks": ["scan-input", "transcode-batch", "generate-thumbnails"]
242
+ }
243
+ }
244
+ }
245
+ ```
@@ -0,0 +1,177 @@
1
+ # Manifests (Metaoutput)
2
+
3
+ Manifests track the output from executing operations. Every operation
4
+ execution produces a manifest that records timing, success/failure, task
5
+ results and logs.
6
+
7
+ ## Manifest Model
8
+
9
+ ```json
10
+ {
11
+ "GUIDOperation": "etl-pipeline",
12
+ "GUIDRun": "etl-pipeline-1707566400000",
13
+ "Name": "ETL Pipeline",
14
+ "StagingPath": "/var/data/ultravisor_staging/etl-pipeline",
15
+ "ManifestFilePath": "/var/data/ultravisor_staging/etl-pipeline/Manifest_etl-pipeline.json",
16
+ "StartTime": "2026-02-10T02:00:00.000Z",
17
+ "StopTime": "2026-02-10T02:00:12.500Z",
18
+ "Status": "Complete",
19
+ "Success": true,
20
+ "Summary": "Operation etl-pipeline Complete: 3 task(s) executed.",
21
+ "TaskResults": [
22
+ {
23
+ "GUIDTask": "pull-data",
24
+ "Name": "Pull Data from API",
25
+ "Type": "Request",
26
+ "StartTime": "2026-02-10T02:00:00.100Z",
27
+ "StopTime": "2026-02-10T02:00:03.200Z",
28
+ "Status": "Complete",
29
+ "Success": true,
30
+ "Output": "{\"records\": 150}",
31
+ "Log": ["..."]
32
+ },
33
+ {
34
+ "GUIDTask": "process-data",
35
+ "Name": "Process Downloaded Data",
36
+ "Type": "Command",
37
+ "StartTime": "2026-02-10T02:00:03.300Z",
38
+ "StopTime": "2026-02-10T02:00:10.100Z",
39
+ "Status": "Complete",
40
+ "Success": true,
41
+ "Output": "Processed 150 records\n",
42
+ "Log": ["..."]
43
+ },
44
+ {
45
+ "GUIDTask": "notify",
46
+ "Name": "Send Notification",
47
+ "Type": "Command",
48
+ "StartTime": "2026-02-10T02:00:10.200Z",
49
+ "StopTime": "2026-02-10T02:00:12.400Z",
50
+ "Status": "Complete",
51
+ "Success": true,
52
+ "Output": "",
53
+ "Log": ["..."]
54
+ }
55
+ ],
56
+ "Log": [
57
+ "Operation etl-pipeline started at 2026-02-10T02:00:00.000Z",
58
+ "Task pull-data completed with status: Complete",
59
+ "Task process-data completed with status: Complete",
60
+ "Task notify completed with status: Complete",
61
+ "Operation etl-pipeline Complete: 3 task(s) executed."
62
+ ]
63
+ }
64
+ ```
65
+
66
+ ### Fields
67
+
68
+ | Field | Description |
69
+ |-------|-------------|
70
+ | `GUIDOperation` | The operation that was executed |
71
+ | `GUIDRun` | Unique ID for this specific execution run |
72
+ | `Name` | Operation name |
73
+ | `StartTime` | ISO timestamp when the operation started |
74
+ | `StopTime` | ISO timestamp when the operation finished |
75
+ | `Status` | `Running`, `Complete`, or `Error` |
76
+ | `Success` | `true` if all tasks succeeded, `false` otherwise |
77
+ | `Summary` | Human-readable one-line summary |
78
+ | `StagingPath` | Absolute path to the operation's staging folder |
79
+ | `ManifestFilePath` | Absolute path to the manifest JSON file on disk |
80
+ | `TaskResults` | Array of task manifest entries (see below) |
81
+ | `Log` | Array of log messages from the operation lifecycle |
82
+
83
+ ### Task Result Fields
84
+
85
+ | Field | Description |
86
+ |-------|-------------|
87
+ | `GUIDTask` | The task that was executed |
88
+ | `Name` | Task name |
89
+ | `Type` | Task type (Command, Request, etc.) |
90
+ | `StartTime` | ISO timestamp when the task started |
91
+ | `StopTime` | ISO timestamp when the task finished |
92
+ | `Status` | `Running`, `Complete`, `Error`, or `Unsupported` |
93
+ | `Success` | `true` if the task succeeded |
94
+ | `Output` | stdout or response body from the execution |
95
+ | `Log` | Array of log messages from the task execution |
96
+
97
+ ## Manifest Lifecycle
98
+
99
+ 1. **Create** -- `createManifest()` initializes a new manifest with status
100
+ `Running` and assigns a `GUIDRun`
101
+ 2. **Add Results** -- as each task completes, `addTaskResult()` appends the
102
+ task result to `TaskResults`
103
+ 3. **Finalize** -- `finalizeManifest()` sets `StopTime`, calculates overall
104
+ `Success` (all tasks must succeed), sets `Status` and `Summary`, and
105
+ writes the manifest JSON to the operation's staging folder
106
+
107
+ ## Success Determination
108
+
109
+ An operation manifest is marked as `Success: true` only if **every** task
110
+ in the `TaskResults` array has `Success: true`. If any task has
111
+ `Success: false`, the entire operation is marked as failed.
112
+
113
+ ## Storage
114
+
115
+ Manifests are stored in two places:
116
+
117
+ 1. **In memory** -- for the duration of the server session, accessible via
118
+ the API. Restarting the server clears the in-memory manifest store.
119
+
120
+ 2. **On disk** -- when an operation completes, a
121
+ `Manifest_{GUIDOperation}.json` file is written to the operation's
122
+ staging folder. This provides a persistent record that survives
123
+ restarts. The file path is recorded in the manifest's
124
+ `ManifestFilePath` field.
125
+
126
+ The on-disk manifest contains the complete manifest object including all
127
+ task results, timing data and logs. It is written as pretty-printed JSON
128
+ (4-space indentation).
129
+
130
+ The staging folder location defaults to
131
+ `./dist/ultravisor_staging/{GUIDOperation}/` and can be configured via
132
+ `UltravisorStagingRoot` in `.ultravisor.json` (see
133
+ [Configuration](configuration.md)).
134
+
135
+ ## Accessing Manifests
136
+
137
+ ### Via API
138
+
139
+ ```bash
140
+ # List all manifests
141
+ curl http://localhost:54321/Manifest
142
+
143
+ # Get a specific manifest
144
+ curl http://localhost:54321/Manifest/etl-pipeline-1707566400000
145
+ ```
146
+
147
+ ### Example: Checking if the last run succeeded
148
+
149
+ ```bash
150
+ # Get the manifest list and check the last entry
151
+ curl -s http://localhost:54321/Manifest | jq '.[-1].Success'
152
+ ```
153
+
154
+ ## Example: Partial Failure
155
+
156
+ When one task fails in an operation, the manifest captures it:
157
+
158
+ ```json
159
+ {
160
+ "GUIDOperation": "data-sync",
161
+ "Status": "Error",
162
+ "Success": false,
163
+ "Summary": "Operation data-sync Error: 2 task(s) executed.",
164
+ "TaskResults": [
165
+ {
166
+ "GUIDTask": "fetch-data",
167
+ "Status": "Complete",
168
+ "Success": true
169
+ },
170
+ {
171
+ "GUIDTask": "upload-data",
172
+ "Status": "Error",
173
+ "Success": false
174
+ }
175
+ ]
176
+ }
177
+ ```