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,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultravisor Beacon Provider Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages loaded capability providers, routes work items to the
|
|
5
|
+
* correct provider based on Capability:Action, and aggregates the
|
|
6
|
+
* capabilities list for beacon registration.
|
|
7
|
+
*
|
|
8
|
+
* Provider loading supports three sources:
|
|
9
|
+
* - Built-in name ('Shell', 'FileSystem') → resolves to ./providers/
|
|
10
|
+
* - Local file path ('./my-provider.cjs' or absolute) → require(resolved)
|
|
11
|
+
* - npm package name ('ultravisor-provider-ml') → require(name)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const libPath = require('path');
|
|
15
|
+
|
|
16
|
+
class UltravisorBeaconProviderRegistry
|
|
17
|
+
{
|
|
18
|
+
constructor()
|
|
19
|
+
{
|
|
20
|
+
// Map of 'Capability:Action' → { provider, actionDef }
|
|
21
|
+
this._ActionHandlers = {};
|
|
22
|
+
|
|
23
|
+
// Map of 'Capability' → { provider, defaultAction }
|
|
24
|
+
this._DefaultHandlers = {};
|
|
25
|
+
|
|
26
|
+
// All loaded providers by Name
|
|
27
|
+
this._Providers = {};
|
|
28
|
+
|
|
29
|
+
// Aggregate capabilities list (string[])
|
|
30
|
+
this._Capabilities = [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Register a provider instance.
|
|
35
|
+
*
|
|
36
|
+
* @param {object} pProvider - Provider instance (extends CapabilityProvider or duck-types it)
|
|
37
|
+
* @returns {boolean} true if registered successfully
|
|
38
|
+
*/
|
|
39
|
+
registerProvider(pProvider)
|
|
40
|
+
{
|
|
41
|
+
if (!pProvider || !pProvider.Capability)
|
|
42
|
+
{
|
|
43
|
+
console.error('[ProviderRegistry] Provider must have a Capability.');
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let tmpActions = pProvider.actions || {};
|
|
48
|
+
let tmpActionNames = Object.keys(tmpActions);
|
|
49
|
+
|
|
50
|
+
if (tmpActionNames.length === 0)
|
|
51
|
+
{
|
|
52
|
+
console.warn(`[ProviderRegistry] Provider "${pProvider.Name}" declares no actions.`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Index each action by composite key
|
|
56
|
+
for (let i = 0; i < tmpActionNames.length; i++)
|
|
57
|
+
{
|
|
58
|
+
let tmpKey = pProvider.Capability + ':' + tmpActionNames[i];
|
|
59
|
+
this._ActionHandlers[tmpKey] = {
|
|
60
|
+
provider: pProvider,
|
|
61
|
+
actionDef: tmpActions[tmpActionNames[i]]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// First declared action is the default for capability-only routing
|
|
66
|
+
if (tmpActionNames.length > 0)
|
|
67
|
+
{
|
|
68
|
+
this._DefaultHandlers[pProvider.Capability] = {
|
|
69
|
+
provider: pProvider,
|
|
70
|
+
defaultAction: tmpActionNames[0]
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Update aggregate capabilities list
|
|
75
|
+
let tmpCapabilities = pProvider.getCapabilities();
|
|
76
|
+
for (let i = 0; i < tmpCapabilities.length; i++)
|
|
77
|
+
{
|
|
78
|
+
if (this._Capabilities.indexOf(tmpCapabilities[i]) === -1)
|
|
79
|
+
{
|
|
80
|
+
this._Capabilities.push(tmpCapabilities[i]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this._Providers[pProvider.Name] = pProvider;
|
|
85
|
+
|
|
86
|
+
console.log(`[ProviderRegistry] Registered "${pProvider.Name}" → ` +
|
|
87
|
+
`${pProvider.Capability} [${tmpActionNames.join(', ')}]`);
|
|
88
|
+
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Resolve a Capability+Action to a provider and action name.
|
|
94
|
+
*
|
|
95
|
+
* @param {string} pCapability - The capability to match
|
|
96
|
+
* @param {string} [pAction] - Optional action within the capability
|
|
97
|
+
* @returns {{ provider: object, action: string }|null}
|
|
98
|
+
*/
|
|
99
|
+
resolve(pCapability, pAction)
|
|
100
|
+
{
|
|
101
|
+
// Try exact Capability:Action match first
|
|
102
|
+
if (pAction)
|
|
103
|
+
{
|
|
104
|
+
let tmpKey = pCapability + ':' + pAction;
|
|
105
|
+
let tmpHandler = this._ActionHandlers[tmpKey];
|
|
106
|
+
if (tmpHandler)
|
|
107
|
+
{
|
|
108
|
+
return { provider: tmpHandler.provider, action: pAction };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Fall back to default action for the capability
|
|
113
|
+
let tmpDefault = this._DefaultHandlers[pCapability];
|
|
114
|
+
if (tmpDefault)
|
|
115
|
+
{
|
|
116
|
+
return { provider: tmpDefault.provider, action: tmpDefault.defaultAction };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get the aggregate capabilities list for beacon registration.
|
|
124
|
+
*
|
|
125
|
+
* @returns {string[]}
|
|
126
|
+
*/
|
|
127
|
+
getCapabilities()
|
|
128
|
+
{
|
|
129
|
+
return this._Capabilities.slice();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get all loaded providers.
|
|
134
|
+
*
|
|
135
|
+
* @returns {object} Map of provider Name → instance
|
|
136
|
+
*/
|
|
137
|
+
getProviders()
|
|
138
|
+
{
|
|
139
|
+
return this._Providers;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Load a provider from a source descriptor.
|
|
144
|
+
*
|
|
145
|
+
* @param {object} pDescriptor - { Source, Config }
|
|
146
|
+
* Source: 'Shell' (built-in), './my-provider.cjs' (local), 'npm-pkg' (npm)
|
|
147
|
+
* Config: per-provider config object (passed to constructor)
|
|
148
|
+
* @returns {boolean} true if loaded and registered successfully
|
|
149
|
+
*/
|
|
150
|
+
loadProvider(pDescriptor)
|
|
151
|
+
{
|
|
152
|
+
let tmpSource = (pDescriptor && pDescriptor.Source) ? pDescriptor.Source : '';
|
|
153
|
+
let tmpConfig = (pDescriptor && pDescriptor.Config) ? pDescriptor.Config : {};
|
|
154
|
+
|
|
155
|
+
if (!tmpSource)
|
|
156
|
+
{
|
|
157
|
+
console.error('[ProviderRegistry] Provider descriptor must have a Source.');
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let tmpProviderModule = null;
|
|
162
|
+
|
|
163
|
+
// Built-in providers
|
|
164
|
+
let tmpBuiltIns = {
|
|
165
|
+
'Shell': libPath.join(__dirname, 'providers', 'Ultravisor-Beacon-Provider-Shell.cjs'),
|
|
166
|
+
'FileSystem': libPath.join(__dirname, 'providers', 'Ultravisor-Beacon-Provider-FileSystem.cjs'),
|
|
167
|
+
'LLM': libPath.join(__dirname, 'providers', 'Ultravisor-Beacon-Provider-LLM.cjs')
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
try
|
|
171
|
+
{
|
|
172
|
+
if (tmpBuiltIns[tmpSource])
|
|
173
|
+
{
|
|
174
|
+
tmpProviderModule = require(tmpBuiltIns[tmpSource]);
|
|
175
|
+
}
|
|
176
|
+
else if (tmpSource.startsWith('.') || tmpSource.startsWith('/'))
|
|
177
|
+
{
|
|
178
|
+
// Local file path — resolve relative to cwd
|
|
179
|
+
tmpProviderModule = require(libPath.resolve(tmpSource));
|
|
180
|
+
}
|
|
181
|
+
else
|
|
182
|
+
{
|
|
183
|
+
// npm package
|
|
184
|
+
tmpProviderModule = require(tmpSource);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (pError)
|
|
188
|
+
{
|
|
189
|
+
console.error(`[ProviderRegistry] Failed to load provider from "${tmpSource}": ${pError.message}`);
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!tmpProviderModule)
|
|
194
|
+
{
|
|
195
|
+
console.error(`[ProviderRegistry] Could not load provider from: ${tmpSource}`);
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Support class exports, factory functions, and pre-instantiated singletons
|
|
200
|
+
let tmpProvider;
|
|
201
|
+
|
|
202
|
+
if (typeof tmpProviderModule === 'function' &&
|
|
203
|
+
tmpProviderModule.prototype &&
|
|
204
|
+
typeof tmpProviderModule.prototype.execute === 'function')
|
|
205
|
+
{
|
|
206
|
+
// Class with execute on prototype — instantiate it
|
|
207
|
+
tmpProvider = new tmpProviderModule(tmpConfig);
|
|
208
|
+
}
|
|
209
|
+
else if (typeof tmpProviderModule === 'function')
|
|
210
|
+
{
|
|
211
|
+
// Factory function
|
|
212
|
+
tmpProvider = tmpProviderModule(tmpConfig);
|
|
213
|
+
}
|
|
214
|
+
else if (typeof tmpProviderModule === 'object' &&
|
|
215
|
+
typeof tmpProviderModule.execute === 'function')
|
|
216
|
+
{
|
|
217
|
+
// Pre-instantiated singleton
|
|
218
|
+
tmpProvider = tmpProviderModule;
|
|
219
|
+
}
|
|
220
|
+
else
|
|
221
|
+
{
|
|
222
|
+
console.error(`[ProviderRegistry] Invalid provider export from "${tmpSource}": ` +
|
|
223
|
+
`must be a class, factory function, or object with execute().`);
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return this.registerProvider(tmpProvider);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Load all providers from a config array.
|
|
232
|
+
*
|
|
233
|
+
* @param {Array<{ Source: string, Config?: object }>} pDescriptors
|
|
234
|
+
* @returns {number} count of successfully loaded providers
|
|
235
|
+
*/
|
|
236
|
+
loadProviders(pDescriptors)
|
|
237
|
+
{
|
|
238
|
+
if (!Array.isArray(pDescriptors))
|
|
239
|
+
{
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let tmpCount = 0;
|
|
244
|
+
|
|
245
|
+
for (let i = 0; i < pDescriptors.length; i++)
|
|
246
|
+
{
|
|
247
|
+
if (this.loadProvider(pDescriptors[i]))
|
|
248
|
+
{
|
|
249
|
+
tmpCount++;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return tmpCount;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Initialize all loaded providers sequentially.
|
|
258
|
+
* Called before the beacon starts polling.
|
|
259
|
+
*
|
|
260
|
+
* @param {function} fCallback - function(pError)
|
|
261
|
+
*/
|
|
262
|
+
initializeAll(fCallback)
|
|
263
|
+
{
|
|
264
|
+
let tmpProviderNames = Object.keys(this._Providers);
|
|
265
|
+
let tmpIndex = 0;
|
|
266
|
+
|
|
267
|
+
let fNext = (pError) =>
|
|
268
|
+
{
|
|
269
|
+
if (pError)
|
|
270
|
+
{
|
|
271
|
+
return fCallback(pError);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (tmpIndex >= tmpProviderNames.length)
|
|
275
|
+
{
|
|
276
|
+
return fCallback(null);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
let tmpProviderName = tmpProviderNames[tmpIndex++];
|
|
280
|
+
let tmpProvider = this._Providers[tmpProviderName];
|
|
281
|
+
|
|
282
|
+
if (typeof tmpProvider.initialize === 'function')
|
|
283
|
+
{
|
|
284
|
+
tmpProvider.initialize(fNext);
|
|
285
|
+
}
|
|
286
|
+
else
|
|
287
|
+
{
|
|
288
|
+
fNext(null);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
fNext(null);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Shut down all loaded providers sequentially.
|
|
297
|
+
* Called when the beacon is stopping.
|
|
298
|
+
*
|
|
299
|
+
* @param {function} fCallback - function(pError)
|
|
300
|
+
*/
|
|
301
|
+
shutdownAll(fCallback)
|
|
302
|
+
{
|
|
303
|
+
let tmpProviderNames = Object.keys(this._Providers);
|
|
304
|
+
let tmpIndex = 0;
|
|
305
|
+
|
|
306
|
+
let fNext = (pError) =>
|
|
307
|
+
{
|
|
308
|
+
if (tmpIndex >= tmpProviderNames.length)
|
|
309
|
+
{
|
|
310
|
+
return fCallback(pError || null);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let tmpProviderName = tmpProviderNames[tmpIndex++];
|
|
314
|
+
let tmpProvider = this._Providers[tmpProviderName];
|
|
315
|
+
|
|
316
|
+
if (typeof tmpProvider.shutdown === 'function')
|
|
317
|
+
{
|
|
318
|
+
tmpProvider.shutdown(fNext);
|
|
319
|
+
}
|
|
320
|
+
else
|
|
321
|
+
{
|
|
322
|
+
fNext(null);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
fNext(null);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
module.exports = UltravisorBeaconProviderRegistry;
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultravisor Beacon Provider — FileSystem
|
|
3
|
+
*
|
|
4
|
+
* Built-in provider for local file operations on the Beacon worker.
|
|
5
|
+
*
|
|
6
|
+
* Capability: 'FileSystem'
|
|
7
|
+
* Actions: 'Read', 'Write', 'List', 'Copy'
|
|
8
|
+
*
|
|
9
|
+
* Provider config:
|
|
10
|
+
* AllowedPaths {string[]} — path prefixes the provider may access (empty = allow all)
|
|
11
|
+
* MaxFileSizeBytes {number} — max file size for read/write (default: 100MB)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const libFS = require('fs');
|
|
15
|
+
const libPath = require('path');
|
|
16
|
+
|
|
17
|
+
const libBeaconCapabilityProvider = require('../Ultravisor-Beacon-CapabilityProvider.cjs');
|
|
18
|
+
|
|
19
|
+
class UltravisorBeaconProviderFileSystem extends libBeaconCapabilityProvider
|
|
20
|
+
{
|
|
21
|
+
constructor(pProviderConfig)
|
|
22
|
+
{
|
|
23
|
+
super(pProviderConfig);
|
|
24
|
+
|
|
25
|
+
this.Name = 'FileSystem';
|
|
26
|
+
this.Capability = 'FileSystem';
|
|
27
|
+
|
|
28
|
+
this._AllowedPaths = this._ProviderConfig.AllowedPaths || [];
|
|
29
|
+
this._MaxFileSizeBytes = this._ProviderConfig.MaxFileSizeBytes || 104857600;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get actions()
|
|
33
|
+
{
|
|
34
|
+
return {
|
|
35
|
+
'Read':
|
|
36
|
+
{
|
|
37
|
+
Description: 'Read a file from disk.',
|
|
38
|
+
SettingsSchema:
|
|
39
|
+
[
|
|
40
|
+
{ Name: 'FilePath', DataType: 'String', Required: true, Description: 'Path to the file to read' },
|
|
41
|
+
{ Name: 'Encoding', DataType: 'String', Required: false, Description: 'File encoding (default: utf8)' }
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
'Write':
|
|
45
|
+
{
|
|
46
|
+
Description: 'Write content to a file on disk.',
|
|
47
|
+
SettingsSchema:
|
|
48
|
+
[
|
|
49
|
+
{ Name: 'FilePath', DataType: 'String', Required: true, Description: 'Path to the output file' },
|
|
50
|
+
{ Name: 'Content', DataType: 'String', Required: true, Description: 'Content to write' },
|
|
51
|
+
{ Name: 'Encoding', DataType: 'String', Required: false, Description: 'File encoding (default: utf8)' }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
'List':
|
|
55
|
+
{
|
|
56
|
+
Description: 'List files in a directory.',
|
|
57
|
+
SettingsSchema:
|
|
58
|
+
[
|
|
59
|
+
{ Name: 'Folder', DataType: 'String', Required: true, Description: 'Directory path to list' },
|
|
60
|
+
{ Name: 'Pattern', DataType: 'String', Required: false, Description: 'Glob-style pattern filter (e.g. *.txt)' }
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
'Copy':
|
|
64
|
+
{
|
|
65
|
+
Description: 'Copy a file from source to target.',
|
|
66
|
+
SettingsSchema:
|
|
67
|
+
[
|
|
68
|
+
{ Name: 'Source', DataType: 'String', Required: true, Description: 'Source file path' },
|
|
69
|
+
{ Name: 'TargetFile', DataType: 'String', Required: true, Description: 'Target file path' }
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
execute(pAction, pWorkItem, pContext, fCallback, fReportProgress)
|
|
76
|
+
{
|
|
77
|
+
switch (pAction)
|
|
78
|
+
{
|
|
79
|
+
case 'Read':
|
|
80
|
+
return this._executeRead(pWorkItem, pContext, fCallback);
|
|
81
|
+
case 'Write':
|
|
82
|
+
return this._executeWrite(pWorkItem, pContext, fCallback);
|
|
83
|
+
case 'List':
|
|
84
|
+
return this._executeList(pWorkItem, pContext, fCallback);
|
|
85
|
+
case 'Copy':
|
|
86
|
+
return this._executeCopy(pWorkItem, pContext, fCallback);
|
|
87
|
+
default:
|
|
88
|
+
return fCallback(null, {
|
|
89
|
+
Outputs: { StdOut: `Unknown FileSystem action: ${pAction}`, ExitCode: -1, Result: '' },
|
|
90
|
+
Log: [`FileSystem Provider: unsupported action [${pAction}].`]
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ================================================================
|
|
96
|
+
// Path helpers
|
|
97
|
+
// ================================================================
|
|
98
|
+
|
|
99
|
+
_resolvePath(pFilePath, pStagingPath)
|
|
100
|
+
{
|
|
101
|
+
if (!pFilePath) return '';
|
|
102
|
+
if (libPath.isAbsolute(pFilePath)) return pFilePath;
|
|
103
|
+
return libPath.resolve(pStagingPath || process.cwd(), pFilePath);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_isPathAllowed(pResolvedPath)
|
|
107
|
+
{
|
|
108
|
+
if (this._AllowedPaths.length === 0) return true;
|
|
109
|
+
for (let i = 0; i < this._AllowedPaths.length; i++)
|
|
110
|
+
{
|
|
111
|
+
if (pResolvedPath.startsWith(this._AllowedPaths[i])) return true;
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ================================================================
|
|
117
|
+
// Actions
|
|
118
|
+
// ================================================================
|
|
119
|
+
|
|
120
|
+
_executeRead(pWorkItem, pContext, fCallback)
|
|
121
|
+
{
|
|
122
|
+
let tmpSettings = pWorkItem.Settings || {};
|
|
123
|
+
let tmpFilePath = tmpSettings.FilePath || '';
|
|
124
|
+
let tmpEncoding = tmpSettings.Encoding || 'utf8';
|
|
125
|
+
|
|
126
|
+
if (!tmpFilePath)
|
|
127
|
+
{
|
|
128
|
+
return fCallback(null, {
|
|
129
|
+
Outputs: { StdOut: 'No FilePath specified.', ExitCode: -1, Result: '' },
|
|
130
|
+
Log: ['FileSystem Read: no FilePath specified.']
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
tmpFilePath = this._resolvePath(tmpFilePath, pContext.StagingPath);
|
|
135
|
+
|
|
136
|
+
if (!this._isPathAllowed(tmpFilePath))
|
|
137
|
+
{
|
|
138
|
+
return fCallback(null, {
|
|
139
|
+
Outputs: { StdOut: `Path not allowed: ${tmpFilePath}`, ExitCode: -1, Result: '' },
|
|
140
|
+
Log: [`FileSystem Read: path not in AllowedPaths: ${tmpFilePath}`]
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try
|
|
145
|
+
{
|
|
146
|
+
let tmpContent = libFS.readFileSync(tmpFilePath, tmpEncoding);
|
|
147
|
+
let tmpBytesRead = Buffer.byteLength(tmpContent, tmpEncoding);
|
|
148
|
+
|
|
149
|
+
return fCallback(null, {
|
|
150
|
+
Outputs: {
|
|
151
|
+
StdOut: `Read ${tmpBytesRead} bytes from ${tmpFilePath}`,
|
|
152
|
+
ExitCode: 0,
|
|
153
|
+
Result: tmpContent
|
|
154
|
+
},
|
|
155
|
+
Log: [`FileSystem Read: read ${tmpBytesRead} bytes from ${tmpFilePath}`]
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
catch (pError)
|
|
159
|
+
{
|
|
160
|
+
return fCallback(null, {
|
|
161
|
+
Outputs: { StdOut: `Read failed: ${pError.message}`, ExitCode: 1, Result: '' },
|
|
162
|
+
Log: [`FileSystem Read: failed to read ${tmpFilePath}: ${pError.message}`]
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
_executeWrite(pWorkItem, pContext, fCallback)
|
|
168
|
+
{
|
|
169
|
+
let tmpSettings = pWorkItem.Settings || {};
|
|
170
|
+
let tmpFilePath = tmpSettings.FilePath || '';
|
|
171
|
+
let tmpContent = tmpSettings.Content;
|
|
172
|
+
let tmpEncoding = tmpSettings.Encoding || 'utf8';
|
|
173
|
+
|
|
174
|
+
if (!tmpFilePath)
|
|
175
|
+
{
|
|
176
|
+
return fCallback(null, {
|
|
177
|
+
Outputs: { StdOut: 'No FilePath specified.', ExitCode: -1, Result: '' },
|
|
178
|
+
Log: ['FileSystem Write: no FilePath specified.']
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (tmpContent === undefined || tmpContent === null) { tmpContent = ''; }
|
|
183
|
+
if (typeof tmpContent !== 'string') { tmpContent = JSON.stringify(tmpContent, null, '\t'); }
|
|
184
|
+
|
|
185
|
+
tmpFilePath = this._resolvePath(tmpFilePath, pContext.StagingPath);
|
|
186
|
+
|
|
187
|
+
if (!this._isPathAllowed(tmpFilePath))
|
|
188
|
+
{
|
|
189
|
+
return fCallback(null, {
|
|
190
|
+
Outputs: { StdOut: `Path not allowed: ${tmpFilePath}`, ExitCode: -1, Result: '' },
|
|
191
|
+
Log: [`FileSystem Write: path not in AllowedPaths: ${tmpFilePath}`]
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
try
|
|
196
|
+
{
|
|
197
|
+
let tmpDir = libPath.dirname(tmpFilePath);
|
|
198
|
+
if (!libFS.existsSync(tmpDir)) { libFS.mkdirSync(tmpDir, { recursive: true }); }
|
|
199
|
+
libFS.writeFileSync(tmpFilePath, tmpContent, tmpEncoding);
|
|
200
|
+
let tmpBytesWritten = Buffer.byteLength(tmpContent, tmpEncoding);
|
|
201
|
+
|
|
202
|
+
return fCallback(null, {
|
|
203
|
+
Outputs: {
|
|
204
|
+
StdOut: `Wrote ${tmpBytesWritten} bytes to ${tmpFilePath}`,
|
|
205
|
+
ExitCode: 0,
|
|
206
|
+
Result: tmpFilePath
|
|
207
|
+
},
|
|
208
|
+
Log: [`FileSystem Write: wrote ${tmpBytesWritten} bytes to ${tmpFilePath}`]
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
catch (pError)
|
|
212
|
+
{
|
|
213
|
+
return fCallback(null, {
|
|
214
|
+
Outputs: { StdOut: `Write failed: ${pError.message}`, ExitCode: 1, Result: '' },
|
|
215
|
+
Log: [`FileSystem Write: failed to write ${tmpFilePath}: ${pError.message}`]
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
_executeList(pWorkItem, pContext, fCallback)
|
|
221
|
+
{
|
|
222
|
+
let tmpSettings = pWorkItem.Settings || {};
|
|
223
|
+
let tmpFolder = tmpSettings.Folder || '';
|
|
224
|
+
let tmpPattern = tmpSettings.Pattern || '*';
|
|
225
|
+
|
|
226
|
+
if (!tmpFolder)
|
|
227
|
+
{
|
|
228
|
+
return fCallback(null, {
|
|
229
|
+
Outputs: { StdOut: 'No Folder specified.', ExitCode: -1, Result: '' },
|
|
230
|
+
Log: ['FileSystem List: no Folder specified.']
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
tmpFolder = this._resolvePath(tmpFolder, pContext.StagingPath);
|
|
235
|
+
|
|
236
|
+
if (!this._isPathAllowed(tmpFolder))
|
|
237
|
+
{
|
|
238
|
+
return fCallback(null, {
|
|
239
|
+
Outputs: { StdOut: `Path not allowed: ${tmpFolder}`, ExitCode: -1, Result: '' },
|
|
240
|
+
Log: [`FileSystem List: path not in AllowedPaths: ${tmpFolder}`]
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
try
|
|
245
|
+
{
|
|
246
|
+
let tmpFiles = libFS.readdirSync(tmpFolder);
|
|
247
|
+
|
|
248
|
+
// Simple glob: convert * and ? to regex
|
|
249
|
+
if (tmpPattern && tmpPattern !== '*')
|
|
250
|
+
{
|
|
251
|
+
let tmpRegex = new RegExp('^' + tmpPattern.replace(/\*/g, '.*').replace(/\?/g, '.') + '$');
|
|
252
|
+
tmpFiles = tmpFiles.filter(function (pFile) { return tmpRegex.test(pFile); });
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return fCallback(null, {
|
|
256
|
+
Outputs: {
|
|
257
|
+
StdOut: `Found ${tmpFiles.length} files in ${tmpFolder}`,
|
|
258
|
+
ExitCode: 0,
|
|
259
|
+
Result: JSON.stringify(tmpFiles)
|
|
260
|
+
},
|
|
261
|
+
Log: [`FileSystem List: found ${tmpFiles.length} files in ${tmpFolder}`]
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
catch (pError)
|
|
265
|
+
{
|
|
266
|
+
return fCallback(null, {
|
|
267
|
+
Outputs: { StdOut: `List failed: ${pError.message}`, ExitCode: 1, Result: '' },
|
|
268
|
+
Log: [`FileSystem List: failed: ${pError.message}`]
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
_executeCopy(pWorkItem, pContext, fCallback)
|
|
274
|
+
{
|
|
275
|
+
let tmpSettings = pWorkItem.Settings || {};
|
|
276
|
+
let tmpSource = tmpSettings.Source || '';
|
|
277
|
+
let tmpTarget = tmpSettings.TargetFile || '';
|
|
278
|
+
|
|
279
|
+
if (!tmpSource || !tmpTarget)
|
|
280
|
+
{
|
|
281
|
+
return fCallback(null, {
|
|
282
|
+
Outputs: { StdOut: 'Source and TargetFile are required.', ExitCode: -1, Result: '' },
|
|
283
|
+
Log: ['FileSystem Copy: Source and TargetFile are required.']
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
tmpSource = this._resolvePath(tmpSource, pContext.StagingPath);
|
|
288
|
+
tmpTarget = this._resolvePath(tmpTarget, pContext.StagingPath);
|
|
289
|
+
|
|
290
|
+
if (!this._isPathAllowed(tmpSource))
|
|
291
|
+
{
|
|
292
|
+
return fCallback(null, {
|
|
293
|
+
Outputs: { StdOut: `Source path not allowed: ${tmpSource}`, ExitCode: -1, Result: '' },
|
|
294
|
+
Log: [`FileSystem Copy: source not in AllowedPaths: ${tmpSource}`]
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (!this._isPathAllowed(tmpTarget))
|
|
299
|
+
{
|
|
300
|
+
return fCallback(null, {
|
|
301
|
+
Outputs: { StdOut: `Target path not allowed: ${tmpTarget}`, ExitCode: -1, Result: '' },
|
|
302
|
+
Log: [`FileSystem Copy: target not in AllowedPaths: ${tmpTarget}`]
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
try
|
|
307
|
+
{
|
|
308
|
+
let tmpDir = libPath.dirname(tmpTarget);
|
|
309
|
+
if (!libFS.existsSync(tmpDir)) { libFS.mkdirSync(tmpDir, { recursive: true }); }
|
|
310
|
+
libFS.copyFileSync(tmpSource, tmpTarget);
|
|
311
|
+
|
|
312
|
+
return fCallback(null, {
|
|
313
|
+
Outputs: {
|
|
314
|
+
StdOut: `Copied ${tmpSource} → ${tmpTarget}`,
|
|
315
|
+
ExitCode: 0,
|
|
316
|
+
Result: tmpTarget
|
|
317
|
+
},
|
|
318
|
+
Log: [`FileSystem Copy: copied ${tmpSource} → ${tmpTarget}`]
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
catch (pError)
|
|
322
|
+
{
|
|
323
|
+
return fCallback(null, {
|
|
324
|
+
Outputs: { StdOut: `Copy failed: ${pError.message}`, ExitCode: 1, Result: '' },
|
|
325
|
+
Log: [`FileSystem Copy: failed: ${pError.message}`]
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
module.exports = UltravisorBeaconProviderFileSystem;
|