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,431 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultravisor Card Config Generator
|
|
3
|
+
*
|
|
4
|
+
* Converts a task type Definition object into a PictFlowCard config object.
|
|
5
|
+
* This allows any task type — built-in or user-defined — to automatically
|
|
6
|
+
* produce a matching flow card without writing a class file.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const generateCardConfig = require('./Ultravisor-CardConfigGenerator.js');
|
|
10
|
+
* let cardConfig = generateCardConfig(taskDefinition, { Width: 220 });
|
|
11
|
+
* // cardConfig can be passed directly to `new PictFlowCard(fable, cardConfig)`
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// ── Category color palette ────────────────────────────────────────────
|
|
15
|
+
// Maps lowercase category names to title bar / body style colors.
|
|
16
|
+
// Matches the palette established by the existing hand-crafted card files.
|
|
17
|
+
const _CategoryColors =
|
|
18
|
+
{
|
|
19
|
+
'flow control': { TitleBarColor: '#78909c', BodyStyle: { fill: '#eceff1', stroke: '#78909c' } },
|
|
20
|
+
'core': { TitleBarColor: '#ab47bc', BodyStyle: { fill: '#f3e5f5', stroke: '#ab47bc' } },
|
|
21
|
+
'control': { TitleBarColor: '#ab47bc', BodyStyle: { fill: '#f3e5f5', stroke: '#ab47bc' } },
|
|
22
|
+
'interaction': { TitleBarColor: '#ef5350', BodyStyle: { fill: '#ffebee', stroke: '#ef5350' } },
|
|
23
|
+
'data': { TitleBarColor: '#ff9800', BodyStyle: { fill: '#fff3e0', stroke: '#ff9800' } },
|
|
24
|
+
'file i/o': { TitleBarColor: '#42a5f5', BodyStyle: { fill: '#eaf2f8', stroke: '#42a5f5' } },
|
|
25
|
+
'file-io': { TitleBarColor: '#42a5f5', BodyStyle: { fill: '#eaf2f8', stroke: '#42a5f5' } },
|
|
26
|
+
'rest': { TitleBarColor: '#29b6f6', BodyStyle: { fill: '#e1f5fe', stroke: '#29b6f6' } },
|
|
27
|
+
'meadow': { TitleBarColor: '#66bb6a', BodyStyle: { fill: '#e8f5e9', stroke: '#66bb6a' } },
|
|
28
|
+
'pipeline': { TitleBarColor: '#ec407a', BodyStyle: { fill: '#fce4ec', stroke: '#ec407a' } },
|
|
29
|
+
'llm': { TitleBarColor: '#26a69a', BodyStyle: { fill: '#e0f7fa', stroke: '#26a69a' } },
|
|
30
|
+
'extension': { TitleBarColor: '#9c6afe', BodyStyle: { fill: '#ede9fe', stroke: '#9c6afe' } },
|
|
31
|
+
'content-system': { TitleBarColor: '#42a5f5', BodyStyle: { fill: '#e3f2fd', stroke: '#42a5f5' } }
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// ── Capability color palette ─────────────────────────────────────────
|
|
35
|
+
// Maps lowercase Capability names to colors. Used as a fallback when
|
|
36
|
+
// Category does not have a specific color (e.g. for future task types).
|
|
37
|
+
const _CapabilityColors =
|
|
38
|
+
{
|
|
39
|
+
'flow control': { TitleBarColor: '#78909c', BodyStyle: { fill: '#eceff1', stroke: '#78909c' } },
|
|
40
|
+
'data transform': { TitleBarColor: '#ff9800', BodyStyle: { fill: '#fff3e0', stroke: '#ff9800' } },
|
|
41
|
+
'file system': { TitleBarColor: '#42a5f5', BodyStyle: { fill: '#eaf2f8', stroke: '#42a5f5' } },
|
|
42
|
+
'shell': { TitleBarColor: '#ab47bc', BodyStyle: { fill: '#f3e5f5', stroke: '#ab47bc' } },
|
|
43
|
+
'http client': { TitleBarColor: '#29b6f6', BodyStyle: { fill: '#e1f5fe', stroke: '#29b6f6' } },
|
|
44
|
+
'meadow api': { TitleBarColor: '#66bb6a', BodyStyle: { fill: '#e8f5e9', stroke: '#66bb6a' } },
|
|
45
|
+
'user interaction': { TitleBarColor: '#ef5350', BodyStyle: { fill: '#ffebee', stroke: '#ef5350' } },
|
|
46
|
+
'llm': { TitleBarColor: '#26a69a', BodyStyle: { fill: '#e0f7fa', stroke: '#26a69a' } },
|
|
47
|
+
'extension': { TitleBarColor: '#9c6afe', BodyStyle: { fill: '#ede9fe', stroke: '#9c6afe' } },
|
|
48
|
+
'contentsystem': { TitleBarColor: '#42a5f5', BodyStyle: { fill: '#e3f2fd', stroke: '#42a5f5' } }
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Default colors for unknown categories
|
|
52
|
+
const _DefaultColors =
|
|
53
|
+
{
|
|
54
|
+
TitleBarColor: '#37474f',
|
|
55
|
+
BodyStyle: { fill: '#eceff1', stroke: '#37474f' }
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// ── DataType → PictForm InputType mapping ─────────────────────────────
|
|
59
|
+
const _DataTypeInputMap =
|
|
60
|
+
{
|
|
61
|
+
'String': 'Text',
|
|
62
|
+
'Number': 'Text',
|
|
63
|
+
'Boolean': 'Option',
|
|
64
|
+
'Array': 'TextArea',
|
|
65
|
+
'Object': 'TextArea'
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Capitalize the first letter of each word in a category string.
|
|
73
|
+
*/
|
|
74
|
+
function _titleCase(pString)
|
|
75
|
+
{
|
|
76
|
+
if (!pString || typeof(pString) !== 'string')
|
|
77
|
+
{
|
|
78
|
+
return 'General';
|
|
79
|
+
}
|
|
80
|
+
return pString.replace(/\b\w/g, function (pChar) { return pChar.toUpperCase(); });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get colors for a category (case-insensitive lookup).
|
|
85
|
+
*/
|
|
86
|
+
function _getColorsForCategory(pCategory)
|
|
87
|
+
{
|
|
88
|
+
if (!pCategory || typeof(pCategory) !== 'string')
|
|
89
|
+
{
|
|
90
|
+
return _DefaultColors;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let tmpKey = pCategory.toLowerCase().trim();
|
|
94
|
+
|
|
95
|
+
if (_CategoryColors[tmpKey])
|
|
96
|
+
{
|
|
97
|
+
return _CategoryColors[tmpKey];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return _DefaultColors;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ── Zone geometry lookup tables (mirrors PictProvider-Flow-Geometry) ──
|
|
104
|
+
const _SideToEdge =
|
|
105
|
+
{
|
|
106
|
+
'left-top': 'left', 'left': 'left', 'left-bottom': 'left',
|
|
107
|
+
'right-top': 'right', 'right': 'right', 'right-bottom': 'right',
|
|
108
|
+
'top-left': 'top', 'top': 'top', 'top-right': 'top',
|
|
109
|
+
'bottom-left': 'bottom', 'bottom': 'bottom', 'bottom-right': 'bottom'
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Calculate card dimensions from port arrays.
|
|
114
|
+
*
|
|
115
|
+
* Uses the same adaptive zone sizing as PictProvider-Flow-Geometry:
|
|
116
|
+
* sums the space needed by all occupied zones on each left/right edge.
|
|
117
|
+
* This produces compact cards whose height scales linearly with total
|
|
118
|
+
* port count rather than being inflated by fixed 1/3 zone fractions.
|
|
119
|
+
*
|
|
120
|
+
* @param {Array} pInputs - Input port objects with Side, Direction
|
|
121
|
+
* @param {Array} pOutputs - Output port objects with Side, Direction
|
|
122
|
+
* @returns {{Width: number, Height: number}}
|
|
123
|
+
*/
|
|
124
|
+
function _calculateDimensions(pInputs, pOutputs)
|
|
125
|
+
{
|
|
126
|
+
let tmpTitleBarHeight = 22;
|
|
127
|
+
let tmpMinSpacing = 16;
|
|
128
|
+
let tmpBottomPad = 16;
|
|
129
|
+
let tmpWidth = 180;
|
|
130
|
+
let tmpHeight = 80;
|
|
131
|
+
|
|
132
|
+
let tmpAllPorts = (pInputs || []).concat(pOutputs || []);
|
|
133
|
+
|
|
134
|
+
// Count ports per zone
|
|
135
|
+
let tmpCountBySide = {};
|
|
136
|
+
for (let i = 0; i < tmpAllPorts.length; i++)
|
|
137
|
+
{
|
|
138
|
+
let tmpSide = tmpAllPorts[i].Side || (tmpAllPorts[i].Direction === 'input' ? 'left' : 'right');
|
|
139
|
+
if (!tmpCountBySide[tmpSide])
|
|
140
|
+
{
|
|
141
|
+
tmpCountBySide[tmpSide] = 0;
|
|
142
|
+
}
|
|
143
|
+
tmpCountBySide[tmpSide]++;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Sum space needed per edge across all zones.
|
|
147
|
+
// Each zone needs minSpacing * (count + 1) pixels.
|
|
148
|
+
let tmpSpacePerEdge = {};
|
|
149
|
+
for (let tmpSide in tmpCountBySide)
|
|
150
|
+
{
|
|
151
|
+
let tmpCount = tmpCountBySide[tmpSide];
|
|
152
|
+
let tmpEdge = _SideToEdge[tmpSide] || 'right';
|
|
153
|
+
|
|
154
|
+
if (tmpEdge !== 'left' && tmpEdge !== 'right')
|
|
155
|
+
{
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let tmpZoneSpace = tmpMinSpacing * (tmpCount + 1);
|
|
160
|
+
|
|
161
|
+
if (!tmpSpacePerEdge[tmpEdge])
|
|
162
|
+
{
|
|
163
|
+
tmpSpacePerEdge[tmpEdge] = 0;
|
|
164
|
+
}
|
|
165
|
+
tmpSpacePerEdge[tmpEdge] += tmpZoneSpace;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Height = titleBar + bottomPad + max edge space
|
|
169
|
+
for (let tmpEdge in tmpSpacePerEdge)
|
|
170
|
+
{
|
|
171
|
+
let tmpRequired = tmpTitleBarHeight + tmpBottomPad + tmpSpacePerEdge[tmpEdge];
|
|
172
|
+
tmpHeight = Math.max(tmpHeight, Math.ceil(tmpRequired));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Adjust width for many ports
|
|
176
|
+
let tmpMaxPorts = Math.max((pInputs || []).length, (pOutputs || []).length);
|
|
177
|
+
if (tmpMaxPorts >= 4)
|
|
178
|
+
{
|
|
179
|
+
tmpWidth = Math.max(tmpWidth, 220);
|
|
180
|
+
}
|
|
181
|
+
else if (tmpMaxPorts >= 3)
|
|
182
|
+
{
|
|
183
|
+
tmpWidth = Math.max(tmpWidth, 200);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return { Width: tmpWidth, Height: tmpHeight };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Build a PropertiesPanel configuration from SettingsInputs.
|
|
191
|
+
*
|
|
192
|
+
* Uses the UltravisorSettings panel type which provides per-field
|
|
193
|
+
* mode toggles (Constant / Address / Default) and type-appropriate
|
|
194
|
+
* editors driven by the task definition schema.
|
|
195
|
+
*/
|
|
196
|
+
function _buildPropertiesPanel(pDefinition)
|
|
197
|
+
{
|
|
198
|
+
let tmpSettings = pDefinition.SettingsInputs;
|
|
199
|
+
|
|
200
|
+
if (!Array.isArray(tmpSettings) || tmpSettings.length === 0)
|
|
201
|
+
{
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let tmpDefaults = pDefinition.DefaultSettings || {};
|
|
206
|
+
|
|
207
|
+
// Account for mode-toggle fields (slightly taller per row) plus port summary sections below
|
|
208
|
+
let tmpPortSummaryHeight = 0;
|
|
209
|
+
if (Array.isArray(pDefinition.EventInputs) && pDefinition.EventInputs.length > 0)
|
|
210
|
+
{
|
|
211
|
+
tmpPortSummaryHeight += 30 + (pDefinition.EventInputs.length * 20);
|
|
212
|
+
}
|
|
213
|
+
if (Array.isArray(pDefinition.EventOutputs) && pDefinition.EventOutputs.length > 0)
|
|
214
|
+
{
|
|
215
|
+
tmpPortSummaryHeight += 30 + (pDefinition.EventOutputs.length * 20);
|
|
216
|
+
}
|
|
217
|
+
if (Array.isArray(pDefinition.StateOutputs) && pDefinition.StateOutputs.length > 0)
|
|
218
|
+
{
|
|
219
|
+
tmpPortSummaryHeight += 30 + (pDefinition.StateOutputs.length * 20);
|
|
220
|
+
}
|
|
221
|
+
let tmpPanelHeight = 160 + (tmpSettings.length * 65) + tmpPortSummaryHeight;
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
PanelType: 'UltravisorSettings',
|
|
225
|
+
DefaultWidth: 380,
|
|
226
|
+
DefaultHeight: Math.min(tmpPanelHeight, 550),
|
|
227
|
+
Title: (pDefinition.Name || pDefinition.Hash) + ' Settings',
|
|
228
|
+
Configuration:
|
|
229
|
+
{
|
|
230
|
+
Schema: tmpSettings,
|
|
231
|
+
Defaults: tmpDefaults
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
238
|
+
// MAIN GENERATOR FUNCTION
|
|
239
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Generate a PictFlowCard config object from a task type Definition.
|
|
243
|
+
*
|
|
244
|
+
* The returned object can be passed directly to `new PictFlowCard(fable, config)`
|
|
245
|
+
* to create a card instance ready for the flow editor palette.
|
|
246
|
+
*
|
|
247
|
+
* @param {object} pTaskDefinition - Task type definition with Hash, Name,
|
|
248
|
+
* Description, Category, EventInputs, EventOutputs, SettingsInputs,
|
|
249
|
+
* StateOutputs, DefaultSettings.
|
|
250
|
+
* @param {object} [pOverrides] - Optional overrides merged on top of the
|
|
251
|
+
* generated config. Use for custom colors, sizes, port adjustments, etc.
|
|
252
|
+
* @returns {object|null} PictFlowCard constructor options, or null on failure.
|
|
253
|
+
*/
|
|
254
|
+
function generateCardConfigFromTaskDefinition(pTaskDefinition, pOverrides)
|
|
255
|
+
{
|
|
256
|
+
if (!pTaskDefinition || !pTaskDefinition.Hash)
|
|
257
|
+
{
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let tmpDef = pTaskDefinition;
|
|
262
|
+
let tmpCategory = tmpDef.Category || 'general';
|
|
263
|
+
let tmpColors = _getColorsForCategory(tmpCategory);
|
|
264
|
+
|
|
265
|
+
// Fallback to Capability-based colors when Category has no specific color
|
|
266
|
+
if (tmpColors === _DefaultColors && tmpDef.Capability)
|
|
267
|
+
{
|
|
268
|
+
let tmpCapKey = tmpDef.Capability.toLowerCase().trim();
|
|
269
|
+
if (_CapabilityColors[tmpCapKey])
|
|
270
|
+
{
|
|
271
|
+
tmpColors = _CapabilityColors[tmpCapKey];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ── Build input ports ──────────────────────────────────────────
|
|
276
|
+
let tmpInputs = [];
|
|
277
|
+
|
|
278
|
+
// Event inputs → left-bottom, event-in
|
|
279
|
+
if (Array.isArray(tmpDef.EventInputs))
|
|
280
|
+
{
|
|
281
|
+
for (let i = 0; i < tmpDef.EventInputs.length; i++)
|
|
282
|
+
{
|
|
283
|
+
tmpInputs.push(
|
|
284
|
+
{
|
|
285
|
+
Name: tmpDef.EventInputs[i].Name,
|
|
286
|
+
Side: 'left-bottom',
|
|
287
|
+
PortType: 'event-in',
|
|
288
|
+
MinimumInputCount: 0,
|
|
289
|
+
MaximumInputCount: 1
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Settings inputs → left-top, setting
|
|
295
|
+
if (Array.isArray(tmpDef.SettingsInputs))
|
|
296
|
+
{
|
|
297
|
+
for (let i = 0; i < tmpDef.SettingsInputs.length; i++)
|
|
298
|
+
{
|
|
299
|
+
tmpInputs.push(
|
|
300
|
+
{
|
|
301
|
+
Name: tmpDef.SettingsInputs[i].Name,
|
|
302
|
+
Side: 'left-top',
|
|
303
|
+
PortType: 'setting',
|
|
304
|
+
MinimumInputCount: 0,
|
|
305
|
+
MaximumInputCount: 1
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// ── Build output ports ─────────────────────────────────────────
|
|
311
|
+
let tmpOutputs = [];
|
|
312
|
+
|
|
313
|
+
// Event outputs → right-bottom for normal, bottom for errors
|
|
314
|
+
if (Array.isArray(tmpDef.EventOutputs))
|
|
315
|
+
{
|
|
316
|
+
for (let i = 0; i < tmpDef.EventOutputs.length; i++)
|
|
317
|
+
{
|
|
318
|
+
let tmpEvt = tmpDef.EventOutputs[i];
|
|
319
|
+
|
|
320
|
+
if (tmpEvt.IsError)
|
|
321
|
+
{
|
|
322
|
+
tmpOutputs.push(
|
|
323
|
+
{
|
|
324
|
+
Name: tmpEvt.Name,
|
|
325
|
+
Side: 'bottom',
|
|
326
|
+
PortType: 'error'
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
else
|
|
330
|
+
{
|
|
331
|
+
tmpOutputs.push(
|
|
332
|
+
{
|
|
333
|
+
Name: tmpEvt.Name,
|
|
334
|
+
Side: 'right-bottom',
|
|
335
|
+
PortType: 'event-out'
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// State outputs → right-top, value
|
|
342
|
+
if (Array.isArray(tmpDef.StateOutputs))
|
|
343
|
+
{
|
|
344
|
+
for (let i = 0; i < tmpDef.StateOutputs.length; i++)
|
|
345
|
+
{
|
|
346
|
+
let tmpStateOut =
|
|
347
|
+
{
|
|
348
|
+
Name: tmpDef.StateOutputs[i].Name,
|
|
349
|
+
Side: 'right-top',
|
|
350
|
+
PortType: 'value'
|
|
351
|
+
};
|
|
352
|
+
if (tmpDef.StateOutputs[i].DataType)
|
|
353
|
+
{
|
|
354
|
+
tmpStateOut.DataType = tmpDef.StateOutputs[i].DataType;
|
|
355
|
+
}
|
|
356
|
+
tmpOutputs.push(tmpStateOut);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// ── Calculate dimensions ───────────────────────────────────────
|
|
361
|
+
let tmpDimensions = _calculateDimensions(tmpInputs, tmpOutputs);
|
|
362
|
+
|
|
363
|
+
// ── Build PropertiesPanel ──────────────────────────────────────
|
|
364
|
+
let tmpPropertiesPanel = _buildPropertiesPanel(tmpDef);
|
|
365
|
+
|
|
366
|
+
// ── Assemble the card config ───────────────────────────────────
|
|
367
|
+
let tmpConfig =
|
|
368
|
+
{
|
|
369
|
+
Title: tmpDef.Name || tmpDef.Hash,
|
|
370
|
+
Code: tmpDef.Hash,
|
|
371
|
+
Description: tmpDef.Description || '',
|
|
372
|
+
Category: _titleCase(tmpCategory),
|
|
373
|
+
TitleBarColor: tmpColors.TitleBarColor,
|
|
374
|
+
BodyStyle: { fill: tmpColors.BodyStyle.fill, stroke: tmpColors.BodyStyle.stroke },
|
|
375
|
+
Width: tmpDimensions.Width,
|
|
376
|
+
Height: tmpDimensions.Height,
|
|
377
|
+
Inputs: tmpInputs,
|
|
378
|
+
Outputs: tmpOutputs
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
if (tmpPropertiesPanel)
|
|
382
|
+
{
|
|
383
|
+
tmpConfig.PropertiesPanel = tmpPropertiesPanel;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// ── Apply overrides ────────────────────────────────────────────
|
|
387
|
+
if (pOverrides && typeof(pOverrides) === 'object')
|
|
388
|
+
{
|
|
389
|
+
let tmpKeys = Object.keys(pOverrides);
|
|
390
|
+
|
|
391
|
+
for (let i = 0; i < tmpKeys.length; i++)
|
|
392
|
+
{
|
|
393
|
+
let tmpKey = tmpKeys[i];
|
|
394
|
+
|
|
395
|
+
// Deep merge for known objects; shallow replace for everything else
|
|
396
|
+
if (tmpKey === 'BodyStyle' && typeof(pOverrides.BodyStyle) === 'object')
|
|
397
|
+
{
|
|
398
|
+
tmpConfig.BodyStyle = Object.assign({}, tmpConfig.BodyStyle, pOverrides.BodyStyle);
|
|
399
|
+
}
|
|
400
|
+
else if (tmpKey === 'PropertiesPanel' && typeof(pOverrides.PropertiesPanel) === 'object')
|
|
401
|
+
{
|
|
402
|
+
if (tmpConfig.PropertiesPanel)
|
|
403
|
+
{
|
|
404
|
+
tmpConfig.PropertiesPanel = Object.assign({}, tmpConfig.PropertiesPanel, pOverrides.PropertiesPanel);
|
|
405
|
+
}
|
|
406
|
+
else
|
|
407
|
+
{
|
|
408
|
+
tmpConfig.PropertiesPanel = pOverrides.PropertiesPanel;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else
|
|
412
|
+
{
|
|
413
|
+
tmpConfig[tmpKey] = pOverrides[tmpKey];
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// ── Ensure dimensions accommodate final port layout ───────────
|
|
419
|
+
// Overrides may have replaced Inputs/Outputs, so recompute the
|
|
420
|
+
// minimum dimensions and grow if needed (never shrink).
|
|
421
|
+
let tmpFinalDimensions = _calculateDimensions(tmpConfig.Inputs, tmpConfig.Outputs);
|
|
422
|
+
tmpConfig.Width = Math.max(tmpConfig.Width || 180, tmpFinalDimensions.Width);
|
|
423
|
+
tmpConfig.Height = Math.max(tmpConfig.Height || 80, tmpFinalDimensions.Height);
|
|
424
|
+
|
|
425
|
+
return tmpConfig;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
module.exports = generateCardConfigFromTaskDefinition;
|
|
429
|
+
module.exports.CategoryColors = _CategoryColors;
|
|
430
|
+
module.exports.CapabilityColors = _CapabilityColors;
|
|
431
|
+
module.exports.DefaultColors = _DefaultColors;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example Flow: Config File Processor
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates a file-based config processing pipeline using the new engine task types:
|
|
5
|
+
* Start -> Read File (config template) -> If Conditional (has placeholder?)
|
|
6
|
+
* -> True: Replace String (fill in value) -> Write File (output config) -> End
|
|
7
|
+
* -> False: Error Message (missing placeholder) -> End
|
|
8
|
+
*
|
|
9
|
+
* Shows branching, error handling, and file I/O with the event-driven execution engine.
|
|
10
|
+
*/
|
|
11
|
+
module.exports =
|
|
12
|
+
{
|
|
13
|
+
Nodes:
|
|
14
|
+
[
|
|
15
|
+
// ── Entry ────────────────────────────────────────────────
|
|
16
|
+
{
|
|
17
|
+
Hash: 'cfg-start',
|
|
18
|
+
Type: 'start',
|
|
19
|
+
X: 50,
|
|
20
|
+
Y: 200,
|
|
21
|
+
Width: 140,
|
|
22
|
+
Height: 80,
|
|
23
|
+
Title: 'Start',
|
|
24
|
+
Ports:
|
|
25
|
+
[
|
|
26
|
+
{ Hash: 'cfg-start-out', Direction: 'output', Side: 'right', Label: 'Out' }
|
|
27
|
+
],
|
|
28
|
+
Data: {}
|
|
29
|
+
},
|
|
30
|
+
// ── Read the config template ─────────────────────────────
|
|
31
|
+
{
|
|
32
|
+
Hash: 'cfg-read',
|
|
33
|
+
Type: 'read-file',
|
|
34
|
+
X: 270,
|
|
35
|
+
Y: 180,
|
|
36
|
+
Width: 200,
|
|
37
|
+
Height: 80,
|
|
38
|
+
Title: 'Read Config Template',
|
|
39
|
+
Ports:
|
|
40
|
+
[
|
|
41
|
+
{ Hash: 'cfg-read-in', Direction: 'input', Side: 'left', Label: 'BeginRead' },
|
|
42
|
+
{ Hash: 'cfg-read-done', Direction: 'output', Side: 'right', Label: 'ReadComplete' },
|
|
43
|
+
{ Hash: 'cfg-read-err', Direction: 'output', Side: 'bottom', Label: 'Error' }
|
|
44
|
+
],
|
|
45
|
+
Data: { FilePath: 'config.template.json', Encoding: 'utf8' }
|
|
46
|
+
},
|
|
47
|
+
// ── Check if placeholder exists in the content ───────────
|
|
48
|
+
{
|
|
49
|
+
Hash: 'cfg-check',
|
|
50
|
+
Type: 'if-conditional',
|
|
51
|
+
X: 550,
|
|
52
|
+
Y: 160,
|
|
53
|
+
Width: 220,
|
|
54
|
+
Height: 100,
|
|
55
|
+
Title: 'Has Placeholder?',
|
|
56
|
+
Ports:
|
|
57
|
+
[
|
|
58
|
+
{ Hash: 'cfg-check-in', Direction: 'input', Side: 'left', Label: 'Evaluate' },
|
|
59
|
+
{ Hash: 'cfg-check-true', Direction: 'output', Side: 'right', Label: 'True' },
|
|
60
|
+
{ Hash: 'cfg-check-false', Direction: 'output', Side: 'bottom', Label: 'False' }
|
|
61
|
+
],
|
|
62
|
+
Data: { DataAddress: 'TaskOutput.cfg-read.FileContent', CompareValue: '{{API_KEY}}', Operator: 'contains' }
|
|
63
|
+
},
|
|
64
|
+
// ── Replace the placeholder with the real value ──────────
|
|
65
|
+
{
|
|
66
|
+
Hash: 'cfg-replace',
|
|
67
|
+
Type: 'replace-string',
|
|
68
|
+
X: 850,
|
|
69
|
+
Y: 140,
|
|
70
|
+
Width: 220,
|
|
71
|
+
Height: 80,
|
|
72
|
+
Title: 'Fill In API Key',
|
|
73
|
+
Ports:
|
|
74
|
+
[
|
|
75
|
+
{ Hash: 'cfg-replace-in', Direction: 'input', Side: 'left', Label: 'Replace' },
|
|
76
|
+
{ Hash: 'cfg-replace-done', Direction: 'output', Side: 'right', Label: 'ReplaceComplete' },
|
|
77
|
+
{ Hash: 'cfg-replace-err', Direction: 'output', Side: 'bottom', Label: 'Error' }
|
|
78
|
+
],
|
|
79
|
+
Data: { InputString: '{~D:Record.TaskOutput.cfg-read.FileContent~}', SearchString: '{{API_KEY}}', ReplaceString: 'sk-live-abc123def456' }
|
|
80
|
+
},
|
|
81
|
+
// ── Write the processed config ──────────────────────────
|
|
82
|
+
{
|
|
83
|
+
Hash: 'cfg-write',
|
|
84
|
+
Type: 'write-file',
|
|
85
|
+
X: 1150,
|
|
86
|
+
Y: 140,
|
|
87
|
+
Width: 200,
|
|
88
|
+
Height: 80,
|
|
89
|
+
Title: 'Write Config',
|
|
90
|
+
Ports:
|
|
91
|
+
[
|
|
92
|
+
{ Hash: 'cfg-write-in', Direction: 'input', Side: 'left', Label: 'BeginWrite' },
|
|
93
|
+
{ Hash: 'cfg-write-done', Direction: 'output', Side: 'right', Label: 'WriteComplete' },
|
|
94
|
+
{ Hash: 'cfg-write-err', Direction: 'output', Side: 'bottom', Label: 'Error' }
|
|
95
|
+
],
|
|
96
|
+
Data: { FilePath: 'config.json', Content: '{~D:Record.TaskOutput.cfg-replace.ReplacedString~}', Encoding: 'utf8' }
|
|
97
|
+
},
|
|
98
|
+
// ── Error: placeholder not found ─────────────────────────
|
|
99
|
+
{
|
|
100
|
+
Hash: 'cfg-error',
|
|
101
|
+
Type: 'error-message',
|
|
102
|
+
X: 850,
|
|
103
|
+
Y: 340,
|
|
104
|
+
Width: 220,
|
|
105
|
+
Height: 80,
|
|
106
|
+
Title: 'Missing Placeholder',
|
|
107
|
+
Ports:
|
|
108
|
+
[
|
|
109
|
+
{ Hash: 'cfg-error-in', Direction: 'input', Side: 'left', Label: 'Trigger' },
|
|
110
|
+
{ Hash: 'cfg-error-done', Direction: 'output', Side: 'right', Label: 'Complete' }
|
|
111
|
+
],
|
|
112
|
+
Data: { MessageTemplate: 'Config template does not contain the {{API_KEY}} placeholder' }
|
|
113
|
+
},
|
|
114
|
+
// ── Exit ─────────────────────────────────────────────────
|
|
115
|
+
{
|
|
116
|
+
Hash: 'cfg-end',
|
|
117
|
+
Type: 'end',
|
|
118
|
+
X: 1430,
|
|
119
|
+
Y: 220,
|
|
120
|
+
Width: 140,
|
|
121
|
+
Height: 80,
|
|
122
|
+
Title: 'End',
|
|
123
|
+
Ports:
|
|
124
|
+
[
|
|
125
|
+
{ Hash: 'cfg-end-in', Direction: 'input', Side: 'left', Label: 'In' }
|
|
126
|
+
],
|
|
127
|
+
Data: {}
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
Connections:
|
|
131
|
+
[
|
|
132
|
+
// Start -> Read Config Template
|
|
133
|
+
{
|
|
134
|
+
Hash: 'cfg-c1',
|
|
135
|
+
SourceNodeHash: 'cfg-start',
|
|
136
|
+
SourcePortHash: 'cfg-start-out',
|
|
137
|
+
TargetNodeHash: 'cfg-read',
|
|
138
|
+
TargetPortHash: 'cfg-read-in',
|
|
139
|
+
Data: {}
|
|
140
|
+
},
|
|
141
|
+
// Read Config Template -> Has Placeholder?
|
|
142
|
+
{
|
|
143
|
+
Hash: 'cfg-c2',
|
|
144
|
+
SourceNodeHash: 'cfg-read',
|
|
145
|
+
SourcePortHash: 'cfg-read-done',
|
|
146
|
+
TargetNodeHash: 'cfg-check',
|
|
147
|
+
TargetPortHash: 'cfg-check-in',
|
|
148
|
+
Data: {}
|
|
149
|
+
},
|
|
150
|
+
// Has Placeholder? (True) -> Fill In API Key
|
|
151
|
+
{
|
|
152
|
+
Hash: 'cfg-c3',
|
|
153
|
+
SourceNodeHash: 'cfg-check',
|
|
154
|
+
SourcePortHash: 'cfg-check-true',
|
|
155
|
+
TargetNodeHash: 'cfg-replace',
|
|
156
|
+
TargetPortHash: 'cfg-replace-in',
|
|
157
|
+
Data: {}
|
|
158
|
+
},
|
|
159
|
+
// Fill In API Key -> Write Config
|
|
160
|
+
{
|
|
161
|
+
Hash: 'cfg-c4',
|
|
162
|
+
SourceNodeHash: 'cfg-replace',
|
|
163
|
+
SourcePortHash: 'cfg-replace-done',
|
|
164
|
+
TargetNodeHash: 'cfg-write',
|
|
165
|
+
TargetPortHash: 'cfg-write-in',
|
|
166
|
+
Data: {}
|
|
167
|
+
},
|
|
168
|
+
// Write Config -> End
|
|
169
|
+
{
|
|
170
|
+
Hash: 'cfg-c5',
|
|
171
|
+
SourceNodeHash: 'cfg-write',
|
|
172
|
+
SourcePortHash: 'cfg-write-done',
|
|
173
|
+
TargetNodeHash: 'cfg-end',
|
|
174
|
+
TargetPortHash: 'cfg-end-in',
|
|
175
|
+
Data: {}
|
|
176
|
+
},
|
|
177
|
+
// Has Placeholder? (False) -> Missing Placeholder
|
|
178
|
+
{
|
|
179
|
+
Hash: 'cfg-c6',
|
|
180
|
+
SourceNodeHash: 'cfg-check',
|
|
181
|
+
SourcePortHash: 'cfg-check-false',
|
|
182
|
+
TargetNodeHash: 'cfg-error',
|
|
183
|
+
TargetPortHash: 'cfg-error-in',
|
|
184
|
+
Data: {}
|
|
185
|
+
},
|
|
186
|
+
// Missing Placeholder -> End
|
|
187
|
+
{
|
|
188
|
+
Hash: 'cfg-c7',
|
|
189
|
+
SourceNodeHash: 'cfg-error',
|
|
190
|
+
SourcePortHash: 'cfg-error-done',
|
|
191
|
+
TargetNodeHash: 'cfg-end',
|
|
192
|
+
TargetPortHash: 'cfg-end-in',
|
|
193
|
+
Data: {}
|
|
194
|
+
},
|
|
195
|
+
// Read Config Template error -> End
|
|
196
|
+
{
|
|
197
|
+
Hash: 'cfg-c8',
|
|
198
|
+
SourceNodeHash: 'cfg-read',
|
|
199
|
+
SourcePortHash: 'cfg-read-err',
|
|
200
|
+
TargetNodeHash: 'cfg-end',
|
|
201
|
+
TargetPortHash: 'cfg-end-in',
|
|
202
|
+
Data: {}
|
|
203
|
+
},
|
|
204
|
+
// Fill In API Key error -> End
|
|
205
|
+
{
|
|
206
|
+
Hash: 'cfg-c9',
|
|
207
|
+
SourceNodeHash: 'cfg-replace',
|
|
208
|
+
SourcePortHash: 'cfg-replace-err',
|
|
209
|
+
TargetNodeHash: 'cfg-end',
|
|
210
|
+
TargetPortHash: 'cfg-end-in',
|
|
211
|
+
Data: {}
|
|
212
|
+
},
|
|
213
|
+
// Write Config error -> End
|
|
214
|
+
{
|
|
215
|
+
Hash: 'cfg-c10',
|
|
216
|
+
SourceNodeHash: 'cfg-write',
|
|
217
|
+
SourcePortHash: 'cfg-write-err',
|
|
218
|
+
TargetNodeHash: 'cfg-end',
|
|
219
|
+
TargetPortHash: 'cfg-end-in',
|
|
220
|
+
Data: {}
|
|
221
|
+
}
|
|
222
|
+
],
|
|
223
|
+
ViewState:
|
|
224
|
+
{
|
|
225
|
+
PanX: 0,
|
|
226
|
+
PanY: 0,
|
|
227
|
+
Zoom: 1,
|
|
228
|
+
SelectedNodeHash: null,
|
|
229
|
+
SelectedConnectionHash: null
|
|
230
|
+
}
|
|
231
|
+
};
|