ultravisor 1.0.8 → 1.0.10
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/docs/_sidebar.md +8 -0
- package/docs/features/api.md +142 -0
- package/docs/features/beacons.md +52 -0
- package/docs/features/case-study-retold-remote.md +223 -0
- package/docs/features/platform-cards.md +145 -0
- package/docs/features/reachability-matrix.md +145 -0
- package/docs/features/tasks-file-system.md +103 -0
- package/docs/features/universal-addressing.md +117 -0
- package/docs/retold-catalog.json +437 -1
- package/docs/retold-keyword-index.json +47567 -7220
- package/operation-library/api-data-pipeline.json +259 -39
- package/operation-library/conditional-file-backup.json +260 -39
- package/operation-library/csv-data-analysis.json +618 -79
- package/operation-library/csv-to-json.json +357 -45
- package/operation-library/directory-inventory.json +297 -36
- package/operation-library/health-check-ping.json +45 -25
- package/operation-library/json-config-merge.json +105 -30
- package/operation-library/log-line-counter.json +445 -59
- package/operation-library/meadow-crud-lifecycle.json +525 -63
- package/operation-library/rest-api-orchestrator.json +471 -56
- package/operation-library/simple-echo.json +228 -24
- package/operation-library/template-processor.json +433 -68
- package/package.json +5 -4
- package/source/beacon/Ultravisor-Beacon-Client.cjs +15 -1
- package/source/beacon/Ultravisor-Beacon-ProviderRegistry.cjs +36 -0
- package/source/cli/Ultravisor-CLIProgram.cjs +64 -3
- package/source/config/Ultravisor-Default-Command-Configuration.cjs +2 -1
- package/source/services/Ultravisor-Beacon-Coordinator.cjs +1029 -1
- package/source/services/Ultravisor-Beacon-Reachability.cjs +403 -0
- package/source/services/Ultravisor-ExecutionEngine.cjs +358 -1
- package/source/services/Ultravisor-ExecutionManifest.cjs +391 -8
- package/source/services/Ultravisor-Hypervisor-State.cjs +50 -0
- package/source/services/persistence/Ultravisor-Beacon-QueueJournal.cjs +474 -0
- package/source/services/tasks/Ultravisor-BuiltIn-TaskConfigs.cjs +2 -0
- package/source/services/tasks/Ultravisor-TaskHelper-BeaconDispatch.cjs +11 -2
- package/source/services/tasks/data-collection/Ultravisor-TaskConfigs-DataCollection.cjs +66 -0
- package/source/services/tasks/data-collection/definitions/event-counter.json +26 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskConfigs-DataTransform.cjs +177 -5
- package/source/services/tasks/data-transform/definitions/add-field-mapping.json +22 -0
- package/source/services/tasks/data-transform/definitions/set-value.json +23 -0
- package/source/services/tasks/extension/Ultravisor-TaskConfigs-Extension.cjs +57 -6
- package/source/services/tasks/http-client/Ultravisor-TaskConfigs-HttpClient.cjs +94 -9
- package/source/services/tasks/http-client/definitions/add-header.json +21 -0
- package/source/services/tasks/llm/Ultravisor-TaskConfigs-LLM.cjs +137 -3
- package/source/services/tasks/llm/definitions/add-message.json +21 -0
- package/source/services/tasks/llm/definitions/add-tool.json +22 -0
- package/source/services/tasks/platform/Ultravisor-TaskConfigs-Platform.cjs +449 -0
- package/source/services/tasks/platform/definitions/base64-decode.json +24 -0
- package/source/services/tasks/platform/definitions/base64-encode.json +25 -0
- package/source/services/tasks/platform/definitions/file-transfer.json +26 -0
- package/source/services/tasks/platform/definitions/resolve-address.json +32 -0
- package/source/services/tasks/platform/definitions/send-result.json +24 -0
- package/source/services/tasks/shell/Ultravisor-TaskConfigs-Shell.cjs +115 -4
- package/source/services/tasks/shell/definitions/add-env-var.json +21 -0
- package/source/services/tasks/user-interaction/Ultravisor-TaskConfigs-UserInteraction.cjs +53 -1
- package/source/services/tasks/user-interaction/definitions/add-option.json +21 -0
- package/source/web_server/Ultravisor-API-Server.cjs +919 -2
- package/test/Ultravisor_browser_tests.js +27 -20
- package/test/Ultravisor_tests.js +621 -65
- package/webinterface/build/build-codemirror-bundle.js +30 -0
- package/webinterface/build/codemirror-entry.js +13 -0
- package/webinterface/html/index.html +3 -1
- package/webinterface/package.json +17 -9
- package/webinterface/source/Pict-Application-Ultravisor.js +183 -0
- package/webinterface/source/panels/Ultravisor-CardSettingsPanel.js +208 -50
- package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +9 -1
- package/webinterface/source/views/PictView-Ultravisor-BeaconList.js +47 -11
- package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +18 -1
- package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +769 -40
- package/webinterface/source/views/PictView-Ultravisor-ManifestDetail.js +733 -0
- package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +504 -315
- package/webinterface/source/views/PictView-Ultravisor-OperationDescriptionEditor.js +68 -0
- package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +1 -1
- package/webinterface/source/views/PictView-Ultravisor-OperationList.js +18 -2
- package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +242 -17
- package/webinterface/source/views/PictView-Ultravisor-ReachabilityMap.js +399 -0
- package/webinterface/source/views/PictView-Ultravisor-Schedule.js +20 -4
- package/webinterface/source/views/PictView-Ultravisor-TopBar.js +0 -3
- package/card-audit.json +0 -1545
- package/source/services/tasks/data-transform/Ultravisor-TaskType-SetValues.cjs +0 -74
package/docs/_sidebar.md
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
- [Capabilities](features/capabilities.md)
|
|
11
11
|
- [Beacons](features/beacons.md)
|
|
12
12
|
- [Building Beacon Providers](features/beacon-providers.md)
|
|
13
|
+
- [Beacon Authentication](features/beacon-authentication.md)
|
|
14
|
+
- [Universal Addressing](features/universal-addressing.md)
|
|
15
|
+
- [Reachability Matrix](features/reachability-matrix.md)
|
|
16
|
+
- [Platform Cards](features/platform-cards.md)
|
|
13
17
|
- [LLM Integration](features/llm.md)
|
|
14
18
|
- [LLM Model Setup Guide](features/llm-model-setup.md)
|
|
15
19
|
- [Operations](features/operations.md)
|
|
@@ -33,3 +37,7 @@
|
|
|
33
37
|
- [API Server](features/api.md)
|
|
34
38
|
- [CLI Commands](features/cli.md)
|
|
35
39
|
- [Configuration](features/configuration.md)
|
|
40
|
+
|
|
41
|
+
- Case Studies
|
|
42
|
+
|
|
43
|
+
- [retold-remote + orator-conversion](features/case-study-retold-remote.md)
|
package/docs/features/api.md
CHANGED
|
@@ -210,6 +210,148 @@ Returns an array of all operation manifests from the current session.
|
|
|
210
210
|
}
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
+
### Beacons
|
|
214
|
+
|
|
215
|
+
| Method | Path | Description |
|
|
216
|
+
|--------|------|-------------|
|
|
217
|
+
| `POST` | `/Beacon/Register` | Register a new Beacon worker |
|
|
218
|
+
| `GET` | `/Beacon` | List all registered Beacons |
|
|
219
|
+
| `GET` | `/Beacon/:BeaconID` | Get a specific Beacon |
|
|
220
|
+
| `DELETE` | `/Beacon/:BeaconID` | Deregister a Beacon |
|
|
221
|
+
| `POST` | `/Beacon/:BeaconID/Heartbeat` | Send a Beacon heartbeat |
|
|
222
|
+
| `POST` | `/Beacon/Work/Poll` | Poll for available work |
|
|
223
|
+
| `POST` | `/Beacon/Work/:WorkItemHash/Complete` | Report work item completion |
|
|
224
|
+
| `POST` | `/Beacon/Work/:WorkItemHash/Error` | Report work item failure |
|
|
225
|
+
| `POST` | `/Beacon/Work/:WorkItemHash/Progress` | Report work item progress |
|
|
226
|
+
| `POST` | `/Beacon/Work/:WorkItemHash/Upload` | Upload a binary result file for a work item |
|
|
227
|
+
| `GET` | `/Beacon/Work` | List all work items |
|
|
228
|
+
| `GET` | `/Beacon/Affinity` | List active affinity bindings |
|
|
229
|
+
| `GET` | `/Beacon/Reachability` | Get the connectivity matrix between all beacon pairs |
|
|
230
|
+
| `POST` | `/Beacon/Reachability/Probe` | Trigger connectivity probes between all online beacon pairs |
|
|
231
|
+
|
|
232
|
+
#### POST /Beacon/Register
|
|
233
|
+
|
|
234
|
+
Register a new Beacon worker with the coordinator.
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
curl -X POST http://localhost:54321/Beacon/Register \
|
|
238
|
+
-H "Content-Type: application/json" \
|
|
239
|
+
-d '{
|
|
240
|
+
"Name": "GPU-Worker-1",
|
|
241
|
+
"Capabilities": ["Shell", "FileSystem"],
|
|
242
|
+
"MaxConcurrent": 4
|
|
243
|
+
}'
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Response:
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"BeaconID": "beacon-abc123",
|
|
251
|
+
"Name": "GPU-Worker-1",
|
|
252
|
+
"Capabilities": ["Shell", "FileSystem"],
|
|
253
|
+
"MaxConcurrent": 4,
|
|
254
|
+
"Status": "Online"
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### POST /Beacon/Work/Poll
|
|
259
|
+
|
|
260
|
+
Poll for available work matching the Beacon's capabilities.
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
curl -X POST http://localhost:54321/Beacon/Work/Poll \
|
|
264
|
+
-H "Content-Type: application/json" \
|
|
265
|
+
-d '{ "BeaconID": "beacon-abc123" }'
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Response:
|
|
269
|
+
|
|
270
|
+
```json
|
|
271
|
+
{
|
|
272
|
+
"WorkItem": {
|
|
273
|
+
"WorkItemHash": "wi-xyz789",
|
|
274
|
+
"Capability": "Shell",
|
|
275
|
+
"Action": "Execute",
|
|
276
|
+
"Settings": { "Command": "echo hello" }
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### POST /Beacon/Work/:WorkItemHash/Complete
|
|
282
|
+
|
|
283
|
+
Report successful completion of a work item.
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
curl -X POST http://localhost:54321/Beacon/Work/wi-xyz789/Complete \
|
|
287
|
+
-H "Content-Type: application/json" \
|
|
288
|
+
-d '{
|
|
289
|
+
"Outputs": { "StdOut": "hello\n", "ExitCode": 0 },
|
|
290
|
+
"Log": ["Command executed successfully"]
|
|
291
|
+
}'
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### POST /Beacon/Work/:WorkItemHash/Upload
|
|
295
|
+
|
|
296
|
+
Upload a binary result file for a work item. The Beacon sends raw file
|
|
297
|
+
bytes with `Content-Type: application/octet-stream` and an
|
|
298
|
+
`X-Output-Filename` header. The file is written to the operation's
|
|
299
|
+
staging directory. Requires session auth.
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
curl -X POST http://localhost:54321/Beacon/Work/wi-xyz789/Upload \
|
|
303
|
+
-H "Content-Type: application/octet-stream" \
|
|
304
|
+
-H "X-Output-Filename: result.bin" \
|
|
305
|
+
--data-binary @result.bin
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Response:
|
|
309
|
+
|
|
310
|
+
```json
|
|
311
|
+
{
|
|
312
|
+
"Status": "Uploaded",
|
|
313
|
+
"WorkItemHash": "wi-xyz789",
|
|
314
|
+
"FilePath": "/data/staging/my-pipeline/result.bin"
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### GET /Beacon/Reachability
|
|
319
|
+
|
|
320
|
+
Returns the connectivity matrix between all beacon pairs. No auth
|
|
321
|
+
required (management UI).
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
curl http://localhost:54321/Beacon/Reachability
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Response:
|
|
328
|
+
|
|
329
|
+
```json
|
|
330
|
+
[
|
|
331
|
+
{
|
|
332
|
+
"SourceBeaconID": "beacon-abc123",
|
|
333
|
+
"TargetBeaconID": "beacon-def456",
|
|
334
|
+
"Status": "Reachable",
|
|
335
|
+
"ProbeLatencyMs": 12,
|
|
336
|
+
"LastProbeAt": "2026-03-21T10:00:00.000Z",
|
|
337
|
+
"ProbeURL": "http://192.168.1.10:54322/probe"
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### POST /Beacon/Reachability/Probe
|
|
343
|
+
|
|
344
|
+
Triggers connectivity probes between all online beacon pairs. Returns
|
|
345
|
+
the updated reachability matrix after probes complete. No auth required
|
|
346
|
+
(management UI).
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
curl -X POST http://localhost:54321/Beacon/Reachability/Probe
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Response: Array of reachability records (same shape as
|
|
353
|
+
`GET /Beacon/Reachability`).
|
|
354
|
+
|
|
213
355
|
## Error Responses
|
|
214
356
|
|
|
215
357
|
All error responses follow this format:
|
package/docs/features/beacons.md
CHANGED
|
@@ -121,6 +121,7 @@ Register a new Beacon worker with the coordinator.
|
|
|
121
121
|
| `Capabilities` | array | yes | List of capability strings |
|
|
122
122
|
| `MaxConcurrent` | number | no | Maximum concurrent work items (default: 1) |
|
|
123
123
|
| `Tags` | object | no | Arbitrary key-value metadata |
|
|
124
|
+
| `BindAddresses` | array | no | Network interfaces the Beacon is listening on. Each entry is `{ IP, Port, Protocol }`. Used by the reachability service to probe connectivity between Beacons. |
|
|
124
125
|
|
|
125
126
|
**Response:** The created Beacon record including the assigned `BeaconID`.
|
|
126
127
|
|
|
@@ -224,6 +225,57 @@ List all active affinity bindings.
|
|
|
224
225
|
**Response:** Array of affinity binding records, each containing
|
|
225
226
|
`AffinityKey`, `BeaconID`, `CreatedAt`, and `ExpiresAt`.
|
|
226
227
|
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
### GET /Beacon/Reachability
|
|
231
|
+
|
|
232
|
+
Returns the connectivity matrix between all beacon pairs. No auth
|
|
233
|
+
required (management UI).
|
|
234
|
+
|
|
235
|
+
**Response:** Array of reachability records:
|
|
236
|
+
|
|
237
|
+
| Field | Type | Description |
|
|
238
|
+
|-------|------|-------------|
|
|
239
|
+
| `SourceBeaconID` | string | Beacon that initiated the probe |
|
|
240
|
+
| `TargetBeaconID` | string | Beacon that was probed |
|
|
241
|
+
| `Status` | string | Connectivity status (e.g. `Reachable`, `Unreachable`) |
|
|
242
|
+
| `ProbeLatencyMs` | number | Round-trip latency of the probe in milliseconds |
|
|
243
|
+
| `LastProbeAt` | string | ISO timestamp of the last probe |
|
|
244
|
+
| `ProbeURL` | string | URL that was probed |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### POST /Beacon/Reachability/Probe
|
|
249
|
+
|
|
250
|
+
Triggers connectivity probes between all online beacon pairs. Returns
|
|
251
|
+
the updated reachability matrix after probes complete. No auth required
|
|
252
|
+
(management UI).
|
|
253
|
+
|
|
254
|
+
**Response:** Array of reachability records (same shape as
|
|
255
|
+
`GET /Beacon/Reachability`).
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
### POST /Beacon/Work/:WorkItemHash/Upload
|
|
260
|
+
|
|
261
|
+
Uploads a binary result file for a work item. The Beacon sends raw file
|
|
262
|
+
bytes with `Content-Type: application/octet-stream` and an
|
|
263
|
+
`X-Output-Filename` header specifying the file name. The file is written
|
|
264
|
+
to the operation's staging directory.
|
|
265
|
+
|
|
266
|
+
Requires session auth.
|
|
267
|
+
|
|
268
|
+
**Request headers:**
|
|
269
|
+
|
|
270
|
+
| Header | Required | Description |
|
|
271
|
+
|--------|----------|-------------|
|
|
272
|
+
| `Content-Type` | yes | Must be `application/octet-stream` |
|
|
273
|
+
| `X-Output-Filename` | yes | Target file name for the uploaded file |
|
|
274
|
+
|
|
275
|
+
**Request body:** Raw binary file bytes.
|
|
276
|
+
|
|
277
|
+
**Response:** `{ Status: "Uploaded", WorkItemHash: "...", FilePath: "..." }`
|
|
278
|
+
|
|
227
279
|
## Custom Capability Providers
|
|
228
280
|
|
|
229
281
|
Beacons use a pluggable **CapabilityProvider** system. Each provider handles
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# Case Study: retold-remote + orator-conversion
|
|
2
|
+
|
|
3
|
+
This case study shows how retold-remote (a media browser) and orator-conversion (a media processing worker) integrate through Ultravisor's operation pipeline to generate thumbnails, previews, waveforms, and other derived media artifacts.
|
|
4
|
+
|
|
5
|
+
## System Overview
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TB
|
|
9
|
+
subgraph "retold-remote (NAS)"
|
|
10
|
+
RR[retold-remote server]
|
|
11
|
+
FS[(Media Files<br/>/Users/steven)]
|
|
12
|
+
RR --- FS
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
subgraph "Ultravisor (Coordinator)"
|
|
16
|
+
UV[Ultravisor API Server]
|
|
17
|
+
OPS[(Operation Graphs)]
|
|
18
|
+
RM[Reachability Matrix]
|
|
19
|
+
UV --- OPS
|
|
20
|
+
UV --- RM
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
subgraph "orator-conversion (Worker)"
|
|
24
|
+
OC[orator-conversion beacon]
|
|
25
|
+
SHARP[Sharp / ffmpeg / pdftoppm]
|
|
26
|
+
OC --- SHARP
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
RR -->|"triggerOperation('rr-image-thumbnail', params)"| UV
|
|
30
|
+
UV -->|"Enqueue MediaConversion/ImageResize"| OC
|
|
31
|
+
OC -->|"Upload result binary"| UV
|
|
32
|
+
UV -->|"Stream binary response"| RR
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## How It Connects
|
|
36
|
+
|
|
37
|
+
### 1. Startup
|
|
38
|
+
|
|
39
|
+
All three services start independently:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Terminal 1: Ultravisor
|
|
43
|
+
ultravisor start -l
|
|
44
|
+
|
|
45
|
+
# Terminal 2: retold-remote
|
|
46
|
+
retold-remote serve ~/Media -u -l
|
|
47
|
+
|
|
48
|
+
# Terminal 3: orator-conversion
|
|
49
|
+
npm start -- -u -l
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Registration
|
|
53
|
+
|
|
54
|
+
```mermaid
|
|
55
|
+
sequenceDiagram
|
|
56
|
+
participant RR as retold-remote
|
|
57
|
+
participant UV as Ultravisor
|
|
58
|
+
participant OC as orator-conversion
|
|
59
|
+
|
|
60
|
+
OC->>UV: POST /Beacon/Register<br/>{Name: "orator-conversion", Capabilities: ["MediaConversion"],<br/>ActionSchemas: [ImageResize, VideoThumbnail, ...],<br/>BindAddresses: [{IP: "127.0.0.1", Port: 8765}]}
|
|
61
|
+
UV->>UV: Register beacon, auto-generate 14 task types
|
|
62
|
+
UV->>UV: Probe reachability (no other beacons yet)
|
|
63
|
+
UV-->>OC: {BeaconID: "bcn-orator-conversion-..."}
|
|
64
|
+
|
|
65
|
+
RR->>UV: WebSocket: BeaconRegister<br/>{Name: "retold-remote", Contexts: {File: {BaseURL: "http://localhost:7827/content/"}},<br/>BindAddresses: [{IP: "127.0.0.1", Port: 7827}],<br/>Operations: [rr-image-thumbnail, rr-video-thumbnail, ...]}
|
|
66
|
+
UV->>UV: Register beacon, store 9 operation definitions
|
|
67
|
+
UV->>UV: Probe: retold-remote ↔ orator-conversion = REACHABLE
|
|
68
|
+
|
|
69
|
+
Note over UV: Both beacons registered.<br/>14 beacon task types available.<br/>9 operations from retold-remote.<br/>Reachability: all pairs reachable.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 3. Auto-Generated Operations
|
|
73
|
+
|
|
74
|
+
retold-remote registers 9 operation definitions during beacon connection. These are complete operation graphs with nodes, connections, and state wiring — built programmatically by `_buildPipelineOperation()`:
|
|
75
|
+
|
|
76
|
+
| Operation | Trigger Parameters | Pipeline |
|
|
77
|
+
|-----------|-------------------|----------|
|
|
78
|
+
| `rr-image-thumbnail` | ImageAddress, Width, Height, Format, Quality | resolve → transfer → resize → send-result |
|
|
79
|
+
| `rr-video-thumbnail` | VideoAddress, Timestamp, Width | resolve → transfer → extract frame → send-result |
|
|
80
|
+
| `rr-video-frame-extraction` | VideoAddress, Timestamp, Width | resolve → transfer → probe → extract → send-result |
|
|
81
|
+
| `rr-audio-waveform` | AudioAddress, SampleRate, Samples | resolve → transfer → waveform → send-result |
|
|
82
|
+
| `rr-audio-segment` | AudioAddress, Start, Duration, Codec | resolve → transfer → extract → send-result |
|
|
83
|
+
| `rr-pdf-page-render` | PdfAddress, Page, LongSidePixels | resolve → transfer → render → send-result |
|
|
84
|
+
| `rr-image-convert` | ImageAddress, Format, Quality | resolve → transfer → convert → send-result |
|
|
85
|
+
| `rr-ebook-convert` | EbookAddress | resolve → transfer → ebook-convert → send-result |
|
|
86
|
+
| `rr-media-probe` | MediaAddress | resolve → transfer → ffprobe → send-result |
|
|
87
|
+
|
|
88
|
+
Each pipeline follows the same pattern:
|
|
89
|
+
|
|
90
|
+
```mermaid
|
|
91
|
+
graph LR
|
|
92
|
+
S[Start] --> R[resolve-address]
|
|
93
|
+
R -->|URL, Filename| T[file-transfer]
|
|
94
|
+
T -->|LocalPath| P[beacon-mediaconversion-*]
|
|
95
|
+
P -->|OutputFile| SR[send-result]
|
|
96
|
+
SR --> E[End]
|
|
97
|
+
|
|
98
|
+
R -.->|Error| E
|
|
99
|
+
T -.->|Error| E
|
|
100
|
+
P -.->|Error| E
|
|
101
|
+
SR -.->|Error| E
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
State connections wire outputs from earlier nodes into inputs of later nodes:
|
|
105
|
+
- `resolve.URL` → `transfer.SourceURL`
|
|
106
|
+
- `resolve.Filename` → `transfer.Filename`
|
|
107
|
+
- `transfer.LocalPath` → `process.InputFile`
|
|
108
|
+
|
|
109
|
+
## End-to-End: Image Thumbnail Generation
|
|
110
|
+
|
|
111
|
+
When a user navigates to a folder in retold-remote, the browser requests thumbnails. Here's the complete flow:
|
|
112
|
+
|
|
113
|
+
```mermaid
|
|
114
|
+
sequenceDiagram
|
|
115
|
+
participant Browser
|
|
116
|
+
participant RR as retold-remote
|
|
117
|
+
participant UV as Ultravisor
|
|
118
|
+
participant OC as orator-conversion
|
|
119
|
+
|
|
120
|
+
Browser->>RR: GET /content/preview/photo.jpg?w=400&h=300
|
|
121
|
+
|
|
122
|
+
Note over RR: Check cache → miss
|
|
123
|
+
|
|
124
|
+
RR->>UV: POST /Operation/rr-image-thumbnail/Trigger<br/>{Parameters: {ImageAddress: ">retold-remote/File/photo.jpg",<br/>Width: 400, Height: 300, Format: "webp", Quality: 80}}
|
|
125
|
+
|
|
126
|
+
Note over UV: Start operation (sync mode)
|
|
127
|
+
|
|
128
|
+
UV->>UV: resolve-address<br/>>retold-remote/File/photo.jpg<br/>→ http://localhost:7827/content/photo.jpg
|
|
129
|
+
|
|
130
|
+
UV->>RR: HTTP GET http://localhost:7827/content/photo.jpg
|
|
131
|
+
RR-->>UV: 200 OK (image bytes)
|
|
132
|
+
UV->>UV: file-transfer saves to staging<br/>/staging/rr-image-thumbnail-.../photo.jpg
|
|
133
|
+
|
|
134
|
+
UV->>UV: beacon-mediaconversion-imageresize<br/>enqueue work item, WaitingForInput
|
|
135
|
+
|
|
136
|
+
OC->>UV: POST /Beacon/Work/Poll
|
|
137
|
+
UV-->>OC: WorkItem: {Action: "ImageResize",<br/>Settings: {InputFile: "/.../photo.jpg",<br/>OutputFile: "/.../thumbnail.jpg", Width: 400, ...}}
|
|
138
|
+
|
|
139
|
+
OC->>OC: Sharp: resize photo.jpg → thumbnail.jpg
|
|
140
|
+
OC->>UV: POST /Beacon/Work/{hash}/Upload<br/>(raw binary: thumbnail.jpg)
|
|
141
|
+
UV->>UV: Write to operation staging
|
|
142
|
+
|
|
143
|
+
OC->>UV: POST /Beacon/Work/{hash}/Complete
|
|
144
|
+
UV->>UV: resumeOperation → send-result<br/>finds thumbnail.jpg in staging
|
|
145
|
+
|
|
146
|
+
UV-->>RR: 200 OK<br/>Content-Type: application/octet-stream<br/>Body: (thumbnail bytes)
|
|
147
|
+
|
|
148
|
+
RR->>RR: Cache the thumbnail
|
|
149
|
+
RR-->>Browser: 200 OK (thumbnail image)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Timing
|
|
153
|
+
|
|
154
|
+
On localhost, the full round-trip takes ~1-3 seconds:
|
|
155
|
+
|
|
156
|
+
| Step | Duration |
|
|
157
|
+
|------|----------|
|
|
158
|
+
| Address resolution | < 1ms |
|
|
159
|
+
| File transfer (50MB image) | ~200ms |
|
|
160
|
+
| Sharp resize | ~500ms |
|
|
161
|
+
| Binary upload | ~100ms |
|
|
162
|
+
| Total | ~1s |
|
|
163
|
+
|
|
164
|
+
### Fallback
|
|
165
|
+
|
|
166
|
+
If Ultravisor is unreachable or the operation fails, retold-remote falls through to local processing:
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
this._dispatcher.triggerOperation('rr-image-thumbnail',
|
|
170
|
+
{ ImageAddress: '>retold-remote/File/' + tmpRelPath, Width, Height, Format, Quality },
|
|
171
|
+
(pTriggerError, pResult) =>
|
|
172
|
+
{
|
|
173
|
+
if (!pTriggerError && pResult && pResult.OutputBuffer)
|
|
174
|
+
{
|
|
175
|
+
return fCallback(null, pResult.OutputBuffer);
|
|
176
|
+
}
|
|
177
|
+
// Fall through to local Sharp/ImageMagick
|
|
178
|
+
this._generateImageThumbnailLocal(pFullPath, pWidth, pHeight, pFormat, fCallback);
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Large File Support
|
|
183
|
+
|
|
184
|
+
orator-conversion handles arbitrarily large images (including 256MB+ scans):
|
|
185
|
+
|
|
186
|
+
- **File-path mode**: Sharp receives the file path directly instead of loading the entire file into a buffer
|
|
187
|
+
- **No pixel limit**: `sharp(filePath, { limitInputPixels: false })` — disables Sharp's default pixel limit
|
|
188
|
+
- **Streaming**: File transfer uses Node.js streams, avoiding full-file buffering
|
|
189
|
+
- **Binary upload**: Result files transfer as raw bytes over HTTP or WebSocket — no base64 encoding
|
|
190
|
+
|
|
191
|
+
## Error Handling
|
|
192
|
+
|
|
193
|
+
When a beacon reports a non-zero exit code (e.g., Sharp can't process a corrupt file), the beacon client reports it as an error. The operation graph's Error event fires, routing to the End node. The trigger returns a JSON response with `Success: false`, and retold-remote falls back to local processing.
|
|
194
|
+
|
|
195
|
+
```mermaid
|
|
196
|
+
flowchart TD
|
|
197
|
+
A[Beacon processes work item] --> B{ExitCode == 0?}
|
|
198
|
+
B -->|Yes| C[Upload output file]
|
|
199
|
+
C --> D[Report completion]
|
|
200
|
+
D --> E[Operation resumes → send-result → binary stream]
|
|
201
|
+
B -->|No| F[Report error]
|
|
202
|
+
F --> G[Operation resumes → Error event → End node]
|
|
203
|
+
G --> H[Trigger returns JSON with Success: false]
|
|
204
|
+
H --> I[retold-remote falls back to local processing]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Logging
|
|
208
|
+
|
|
209
|
+
All three services support `-l` for file logging:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
ultravisor start -l # ultravisor-2026-03-21T...log
|
|
213
|
+
retold-remote serve ~/Media -u -l # retold-remote-2026-03-21T...log
|
|
214
|
+
npm start -- -u -l # orator-conversion-2026-03-21T...log
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Key log prefixes for tracing the pipeline:
|
|
218
|
+
- `[TriggerOp]` — retold-remote dispatcher
|
|
219
|
+
- `[Trigger]` — Ultravisor trigger endpoint
|
|
220
|
+
- `[Engine]` — Ultravisor execution engine
|
|
221
|
+
- `[Coordinator]` — Beacon coordinator (work queue, uploads)
|
|
222
|
+
- `[OratorConversion]` — orator-conversion provider
|
|
223
|
+
- `[Beacon]` — Beacon client (execution, upload, completion)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Platform Cards & Task Types
|
|
2
|
+
|
|
3
|
+
Ultravisor's operation graphs are built from cards (task types). Platform cards handle the infrastructure layer — address resolution, file transfer, and result delivery. Extension cards handle beacon dispatch. Beacon cards are auto-generated from registered beacon capabilities.
|
|
4
|
+
|
|
5
|
+
## Platform Cards
|
|
6
|
+
|
|
7
|
+
### resolve-address
|
|
8
|
+
|
|
9
|
+
Resolves a universal address (`>beacon/context/path`) to a concrete URL with optional transfer strategy selection.
|
|
10
|
+
|
|
11
|
+
See [Universal Addressing](universal-addressing.md) for full details.
|
|
12
|
+
|
|
13
|
+
### file-transfer
|
|
14
|
+
|
|
15
|
+
Downloads a file from a URL to the operation's staging directory.
|
|
16
|
+
|
|
17
|
+
| Setting | Type | Required | Description |
|
|
18
|
+
|---------|------|----------|-------------|
|
|
19
|
+
| `SourceURL` | String | Yes | URL to download from |
|
|
20
|
+
| `Filename` | String | Yes | Filename to save as in staging |
|
|
21
|
+
|
|
22
|
+
| Output | Type | Description |
|
|
23
|
+
|--------|------|-------------|
|
|
24
|
+
| `LocalPath` | String | Absolute path to the downloaded file |
|
|
25
|
+
| `BytesTransferred` | Number | File size in bytes |
|
|
26
|
+
| `DurationMs` | Number | Download duration |
|
|
27
|
+
|
|
28
|
+
Supports HTTP/HTTPS with single-redirect following. 5-minute timeout. Creates staging directory if needed.
|
|
29
|
+
|
|
30
|
+
### send-result
|
|
31
|
+
|
|
32
|
+
Marks a staging file as the operation's binary output. The trigger endpoint streams this file directly to the caller.
|
|
33
|
+
|
|
34
|
+
| Setting | Type | Required | Description |
|
|
35
|
+
|---------|------|----------|-------------|
|
|
36
|
+
| `FilePath` | String | Yes | Path to the result file (relative to staging) |
|
|
37
|
+
| `OutputKey` | String | No | Key name for the output (default: `ResultFile`) |
|
|
38
|
+
|
|
39
|
+
| Output | Type | Description |
|
|
40
|
+
|--------|------|-------------|
|
|
41
|
+
| `StagingFilePath` | String | Absolute path to the result file |
|
|
42
|
+
| `BytesSent` | Number | File size in bytes |
|
|
43
|
+
| `DurationMs` | Number | Processing duration |
|
|
44
|
+
|
|
45
|
+
The trigger endpoint scans all task outputs for `StagingFilePath`. If found and the file exists, it streams the file as `application/octet-stream` with metadata in response headers (`X-Run-Hash`, `X-Status`, `X-Elapsed-Ms`).
|
|
46
|
+
|
|
47
|
+
### base64-encode / base64-decode
|
|
48
|
+
|
|
49
|
+
Encode a staging file to a base64 string or decode a base64 string to a staging file. Used for embedding small binary payloads in operation state.
|
|
50
|
+
|
|
51
|
+
## Extension Cards
|
|
52
|
+
|
|
53
|
+
### beacon-dispatch
|
|
54
|
+
|
|
55
|
+
The generic card for dispatching work to beacon workers. Most users won't use this directly — catalog-generated beacon cards provide typed wrappers.
|
|
56
|
+
|
|
57
|
+
| Setting | Type | Required | Description |
|
|
58
|
+
|---------|------|----------|-------------|
|
|
59
|
+
| `RemoteCapability` | String | Yes | Required capability (e.g., `Shell`, `MediaConversion`) |
|
|
60
|
+
| `RemoteAction` | String | No | Specific action within the capability |
|
|
61
|
+
| `Command` | String | No | Shell command for Shell capability |
|
|
62
|
+
| `InputData` | String | No | JSON data with universal addresses (auto-resolved) |
|
|
63
|
+
| `OutputFile` | String | No | Expected output filename (triggers binary upload) |
|
|
64
|
+
| `AffinityKey` | String | No | Sticky routing key |
|
|
65
|
+
| `TimeoutMs` | Number | No | Work item timeout (default: 300000) |
|
|
66
|
+
|
|
67
|
+
When `OutputFile` is set, the executor:
|
|
68
|
+
1. Sets up a work directory for the output
|
|
69
|
+
2. After processing, collects the output file
|
|
70
|
+
3. Uploads it to Ultravisor's staging directory via HTTP POST or WebSocket binary frame
|
|
71
|
+
4. Reports JSON completion separately
|
|
72
|
+
|
|
73
|
+
## Auto-Generated Beacon Cards
|
|
74
|
+
|
|
75
|
+
When a beacon registers with action schemas, Ultravisor auto-generates typed task cards. For example, orator-conversion's `MediaConversion` capability with `ImageResize` action becomes:
|
|
76
|
+
|
|
77
|
+
**`beacon-mediaconversion-imageresize`**
|
|
78
|
+
|
|
79
|
+
```mermaid
|
|
80
|
+
flowchart LR
|
|
81
|
+
A[Action Schema<br/>from beacon registration] --> B[_registerCatalogTaskTypes]
|
|
82
|
+
B --> C["Task type: beacon-mediaconversion-imageresize<br/>Settings: InputFile, OutputFile, Width, Height, Format, Quality<br/>Execute: beaconDispatch → enqueueWorkItem → WaitingForInput"]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The naming convention is: `beacon-{capability}-{action}` (lowercased, non-alphanumeric replaced with hyphens).
|
|
86
|
+
|
|
87
|
+
### How Auto-Generation Works
|
|
88
|
+
|
|
89
|
+
1. Beacon registers with `ActionSchemas` array containing capability, action name, settings schema, and description
|
|
90
|
+
2. Coordinator's `_updateActionCatalog()` stores them persistently
|
|
91
|
+
3. `_registerCatalogTaskTypes()` iterates the catalog and creates a task type config for each entry
|
|
92
|
+
4. Each config gets an `Execute` function via `_createBeaconDispatchExecutor()` that:
|
|
93
|
+
- Coerces setting types (template-resolved strings → numbers/booleans per schema)
|
|
94
|
+
- Calls `beaconDispatch()` helper to enqueue the work item
|
|
95
|
+
- Returns `WaitingForInput` with `ResumeEventName: 'Complete'`
|
|
96
|
+
5. Built-in task types take precedence — catalog types are only registered if no type with the same hash exists
|
|
97
|
+
|
|
98
|
+
### Current orator-conversion Actions
|
|
99
|
+
|
|
100
|
+
| Hash | Action | Settings |
|
|
101
|
+
|------|--------|----------|
|
|
102
|
+
| `beacon-mediaconversion-imagejpgtopng` | ImageJpgToPng | InputFile, OutputFile |
|
|
103
|
+
| `beacon-mediaconversion-imagepngtojpg` | ImagePngToJpg | InputFile, OutputFile |
|
|
104
|
+
| `beacon-mediaconversion-imageresize` | ImageResize | InputFile, OutputFile, Width, Height, Format, Quality |
|
|
105
|
+
| `beacon-mediaconversion-imagerotate` | ImageRotate | InputFile, OutputFile, Angle |
|
|
106
|
+
| `beacon-mediaconversion-imageconvert` | ImageConvert | InputFile, OutputFile, Format, Quality |
|
|
107
|
+
| `beacon-mediaconversion-pdfpagetopng` | PdfPageToPng | InputFile, OutputFile, Page |
|
|
108
|
+
| `beacon-mediaconversion-pdfpagetojpg` | PdfPageToJpg | InputFile, OutputFile, Page |
|
|
109
|
+
| `beacon-mediaconversion-pdfpagetopngsized` | PdfPageToPngSized | InputFile, OutputFile, Page, LongSidePixels |
|
|
110
|
+
| `beacon-mediaconversion-pdfpagetojpgsized` | PdfPageToJpgSized | InputFile, OutputFile, Page, LongSidePixels |
|
|
111
|
+
| `beacon-mediaconversion-mediaprobe` | MediaProbe | InputFile |
|
|
112
|
+
| `beacon-mediaconversion-videoextractframe` | VideoExtractFrame | InputFile, OutputFile, Timestamp, Width |
|
|
113
|
+
| `beacon-mediaconversion-videothumbnail` | VideoThumbnail | InputFile, OutputFile, Timestamp, Width |
|
|
114
|
+
| `beacon-mediaconversion-audioextractsegment` | AudioExtractSegment | InputFile, OutputFile, Start, Duration, Codec |
|
|
115
|
+
| `beacon-mediaconversion-audiowaveform` | AudioWaveform | InputFile, SampleRate, Samples |
|
|
116
|
+
|
|
117
|
+
## Binary Output Return
|
|
118
|
+
|
|
119
|
+
When a beacon processes a work item that produces a file output, the result is transferred back to Ultravisor's staging directory as raw binary — no base64 encoding.
|
|
120
|
+
|
|
121
|
+
```mermaid
|
|
122
|
+
sequenceDiagram
|
|
123
|
+
participant Beacon as Beacon Worker
|
|
124
|
+
participant Exec as Beacon Executor
|
|
125
|
+
participant Client as Beacon Client
|
|
126
|
+
participant UV as Ultravisor
|
|
127
|
+
|
|
128
|
+
Beacon->>Exec: execute(workItem)
|
|
129
|
+
Exec->>Exec: Download source file
|
|
130
|
+
Exec->>Beacon: provider.execute(action, workItem, context)
|
|
131
|
+
Beacon-->>Exec: { Outputs: { Result: outputPath }, Log }
|
|
132
|
+
Exec->>Exec: _collectOutputFiles → set OutputFilePath
|
|
133
|
+
|
|
134
|
+
alt HTTP Transport
|
|
135
|
+
Client->>UV: POST /Beacon/Work/{hash}/Upload<br/>Content-Type: application/octet-stream<br/>X-Output-Filename: thumbnail.jpg<br/>Body: raw bytes
|
|
136
|
+
UV->>UV: recordResultUpload → write to operation staging
|
|
137
|
+
else WebSocket Transport
|
|
138
|
+
Client->>UV: JSON: { Action: "WorkResultUpload", WorkItemHash, OutputFilename, OutputSize }
|
|
139
|
+
Client->>UV: Binary frame: raw file bytes
|
|
140
|
+
UV->>UV: recordResultUpload → write to operation staging
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
Client->>UV: JSON completion: { Outputs, Log }
|
|
144
|
+
UV->>UV: resumeOperation → send-result finds file in staging
|
|
145
|
+
```
|