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.
Files changed (248) hide show
  1. package/.claude/launch.json +11 -0
  2. package/.claude/ultravisor-dev-config.json +3 -0
  3. package/card-audit.json +1545 -0
  4. package/docs/_sidebar.md +17 -0
  5. package/docs/css/docuserve.css +73 -0
  6. package/docs/features/beacon-authentication.md +209 -0
  7. package/docs/features/beacon-providers.md +1299 -0
  8. package/docs/features/beacons.md +530 -0
  9. package/docs/features/capabilities.md +193 -0
  10. package/docs/features/llm-model-setup.md +505 -0
  11. package/docs/features/llm.md +262 -0
  12. package/docs/features/tasks-content-system.md +110 -0
  13. package/docs/features/tasks-data-transform.md +233 -0
  14. package/docs/features/tasks-extension.md +36 -0
  15. package/docs/features/tasks-file-system.md +203 -0
  16. package/docs/features/tasks-flow-control.md +125 -0
  17. package/docs/features/tasks-http-client.md +119 -0
  18. package/docs/features/tasks-llm.md +118 -0
  19. package/docs/features/tasks-meadow-api.md +163 -0
  20. package/docs/features/tasks-user-interaction.md +49 -0
  21. package/docs/features/tasks.md +14 -0
  22. package/docs/index.html +1 -1
  23. package/docs/retold-catalog.json +1 -1
  24. package/docs/retold-keyword-index.json +17374 -5
  25. package/operation-library/api-data-pipeline.json +143 -0
  26. package/operation-library/beacon-remote-command.json +72 -0
  27. package/operation-library/conditional-file-backup.json +143 -0
  28. package/operation-library/config-processor.json +136 -0
  29. package/operation-library/csv-data-analysis.json +228 -0
  30. package/operation-library/csv-to-json.json +160 -0
  31. package/operation-library/directory-inventory.json +128 -0
  32. package/operation-library/expression-calculator.json +114 -0
  33. package/operation-library/file-search-replace.json +175 -0
  34. package/operation-library/git-status-report.json +368 -0
  35. package/operation-library/health-check-ping.json +329 -0
  36. package/operation-library/json-config-merge.json +313 -0
  37. package/operation-library/llm-embedding-tool-use.json +314 -0
  38. package/operation-library/llm-multi-turn-analysis.json +322 -0
  39. package/operation-library/llm-summarize.json +264 -0
  40. package/operation-library/log-line-counter.json +185 -0
  41. package/operation-library/meadow-crud-lifecycle.json +264 -0
  42. package/operation-library/npm-project-validator.json +193 -0
  43. package/operation-library/rest-api-orchestrator.json +218 -0
  44. package/operation-library/shell-system-info.json +137 -0
  45. package/operation-library/simple-echo.json +95 -0
  46. package/operation-library/template-processor.json +299 -0
  47. package/operation-library/text-sanitizer.json +176 -0
  48. package/package.json +12 -8
  49. package/source/Ultravisor.cjs +30 -3
  50. package/source/beacon/Ultravisor-Beacon-CLI.cjs +143 -0
  51. package/source/beacon/Ultravisor-Beacon-CapabilityProvider.cjs +129 -0
  52. package/source/beacon/Ultravisor-Beacon-Client.cjs +568 -0
  53. package/source/beacon/Ultravisor-Beacon-Executor.cjs +500 -0
  54. package/source/beacon/Ultravisor-Beacon-ProviderRegistry.cjs +330 -0
  55. package/source/beacon/providers/Ultravisor-Beacon-Provider-FileSystem.cjs +331 -0
  56. package/source/beacon/providers/Ultravisor-Beacon-Provider-LLM.cjs +966 -0
  57. package/source/beacon/providers/Ultravisor-Beacon-Provider-Shell.cjs +95 -0
  58. package/source/cli/Ultravisor-CLIProgram.cjs +44 -22
  59. package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
  60. package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
  61. package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
  62. package/source/config/Ultravisor-Default-Command-Configuration.cjs +12 -3
  63. package/source/services/Ultravisor-Beacon-Coordinator.cjs +966 -0
  64. package/source/services/Ultravisor-ExecutionEngine.cjs +1093 -0
  65. package/source/services/Ultravisor-ExecutionManifest.cjs +629 -0
  66. package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
  67. package/source/services/Ultravisor-Hypervisor.cjs +185 -75
  68. package/source/services/Ultravisor-Schedule-Persistence-Base.cjs +45 -0
  69. package/source/services/Ultravisor-StateManager.cjs +253 -0
  70. package/source/services/Ultravisor-TaskTypeRegistry.cjs +213 -0
  71. package/source/services/persistence/Ultravisor-Schedule-Persistence-JSONFile.cjs +140 -0
  72. package/source/services/tasks/Ultravisor-BuiltIn-TaskConfigs.cjs +19 -0
  73. package/source/services/tasks/Ultravisor-TaskHelper-BeaconDispatch.cjs +107 -0
  74. package/source/services/tasks/Ultravisor-TaskType-Base.cjs +125 -0
  75. package/source/services/tasks/content-system/Ultravisor-TaskConfigs-ContentSystem.cjs +90 -0
  76. package/source/services/tasks/content-system/definitions/content-create-folder.json +24 -0
  77. package/source/services/tasks/content-system/definitions/content-list-files.json +27 -0
  78. package/source/services/tasks/content-system/definitions/content-read-file.json +26 -0
  79. package/source/services/tasks/content-system/definitions/content-save-file.json +26 -0
  80. package/source/services/tasks/data-transform/Ultravisor-TaskConfigs-DataTransform.cjs +577 -0
  81. package/source/services/tasks/data-transform/Ultravisor-TaskType-ReplaceString.cjs +80 -0
  82. package/source/services/tasks/data-transform/Ultravisor-TaskType-SetValues.cjs +74 -0
  83. package/source/services/tasks/data-transform/Ultravisor-TaskType-StringAppender.cjs +90 -0
  84. package/source/services/tasks/data-transform/definitions/comprehension-intersect.json +24 -0
  85. package/source/services/tasks/data-transform/definitions/csv-transform.json +24 -0
  86. package/source/services/tasks/data-transform/definitions/expression-solver.json +20 -0
  87. package/source/services/tasks/data-transform/definitions/histogram.json +23 -0
  88. package/source/services/tasks/data-transform/definitions/parse-csv.json +27 -0
  89. package/source/services/tasks/data-transform/definitions/replace-string.json +27 -0
  90. package/source/services/tasks/data-transform/definitions/set-values.json +17 -0
  91. package/source/services/tasks/data-transform/definitions/string-appender.json +22 -0
  92. package/source/services/tasks/data-transform/definitions/template-string.json +20 -0
  93. package/source/services/tasks/extension/Ultravisor-TaskConfigs-Extension.cjs +87 -0
  94. package/source/services/tasks/extension/definitions/beacon-dispatch.json +32 -0
  95. package/source/services/tasks/file-system/Ultravisor-TaskConfigs-FileSystem.cjs +509 -0
  96. package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFile.cjs +96 -0
  97. package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFileBuffered.cjs +123 -0
  98. package/source/services/tasks/file-system/Ultravisor-TaskType-WriteFile.cjs +106 -0
  99. package/source/services/tasks/file-system/definitions/copy-file.json +27 -0
  100. package/source/services/tasks/file-system/definitions/list-files.json +27 -0
  101. package/source/services/tasks/file-system/definitions/read-file-buffered.json +31 -0
  102. package/source/services/tasks/file-system/definitions/read-file.json +26 -0
  103. package/source/services/tasks/file-system/definitions/read-json.json +23 -0
  104. package/source/services/tasks/file-system/definitions/write-file.json +29 -0
  105. package/source/services/tasks/file-system/definitions/write-json.json +30 -0
  106. package/source/services/tasks/flow-control/Ultravisor-TaskConfigs-FlowControl.cjs +353 -0
  107. package/source/services/tasks/flow-control/Ultravisor-TaskType-IfConditional.cjs +125 -0
  108. package/source/services/tasks/flow-control/Ultravisor-TaskType-LaunchOperation.cjs +186 -0
  109. package/source/services/tasks/flow-control/Ultravisor-TaskType-SplitExecute.cjs +164 -0
  110. package/source/services/tasks/flow-control/definitions/if-conditional.json +25 -0
  111. package/source/services/tasks/flow-control/definitions/launch-operation.json +27 -0
  112. package/source/services/tasks/flow-control/definitions/split-execute.json +32 -0
  113. package/source/services/tasks/http-client/Ultravisor-TaskConfigs-HttpClient.cjs +281 -0
  114. package/source/services/tasks/http-client/definitions/get-json.json +26 -0
  115. package/source/services/tasks/http-client/definitions/get-text.json +26 -0
  116. package/source/services/tasks/http-client/definitions/rest-request.json +32 -0
  117. package/source/services/tasks/http-client/definitions/send-json.json +28 -0
  118. package/source/services/tasks/llm/Ultravisor-TaskConfigs-LLM.cjs +605 -0
  119. package/source/services/tasks/llm/definitions/llm-chat-completion.json +46 -0
  120. package/source/services/tasks/llm/definitions/llm-embedding.json +31 -0
  121. package/source/services/tasks/llm/definitions/llm-tool-use.json +42 -0
  122. package/source/services/tasks/meadow-api/Ultravisor-TaskConfigs-MeadowApi.cjs +341 -0
  123. package/source/services/tasks/meadow-api/definitions/meadow-count.json +26 -0
  124. package/source/services/tasks/meadow-api/definitions/meadow-create.json +26 -0
  125. package/source/services/tasks/meadow-api/definitions/meadow-delete.json +23 -0
  126. package/source/services/tasks/meadow-api/definitions/meadow-read.json +26 -0
  127. package/source/services/tasks/meadow-api/definitions/meadow-reads.json +29 -0
  128. package/source/services/tasks/meadow-api/definitions/meadow-update.json +26 -0
  129. package/source/services/tasks/shell/Ultravisor-TaskConfigs-Shell.cjs +63 -0
  130. package/source/services/tasks/shell/definitions/command.json +29 -0
  131. package/source/services/tasks/user-interaction/Ultravisor-TaskConfigs-UserInteraction.cjs +64 -0
  132. package/source/services/tasks/user-interaction/Ultravisor-TaskType-ErrorMessage.cjs +55 -0
  133. package/source/services/tasks/user-interaction/Ultravisor-TaskType-ValueInput.cjs +47 -0
  134. package/source/services/tasks/user-interaction/definitions/error-message.json +18 -0
  135. package/source/services/tasks/user-interaction/definitions/value-input.json +23 -0
  136. package/source/web_server/Ultravisor-API-Server.cjs +849 -124
  137. package/test/Ultravisor_browser_tests.js +2226 -0
  138. package/test/Ultravisor_operation_library_tests.js +894 -0
  139. package/test/Ultravisor_tests.js +4946 -5044
  140. package/test/workflows/test-content-concatenate-all.json +339 -0
  141. package/test/workflows/test-content-full-pipeline.json +159 -0
  142. package/test/workflows/test-content-list-files.json +76 -0
  143. package/test/workflows/test-content-save-and-read.json +106 -0
  144. package/webinterface/css/ultravisor-themes.css +668 -0
  145. package/webinterface/css/ultravisor.css +37 -14
  146. package/webinterface/docs/card-help/beacon-dispatch.md +30 -0
  147. package/webinterface/docs/card-help/command.md +27 -0
  148. package/webinterface/docs/card-help/comprehension-intersect.md +24 -0
  149. package/webinterface/docs/card-help/content-create-folder.md +22 -0
  150. package/webinterface/docs/card-help/content-list-files.md +25 -0
  151. package/webinterface/docs/card-help/content-read-file.md +24 -0
  152. package/webinterface/docs/card-help/content-save-file.md +24 -0
  153. package/webinterface/docs/card-help/copy-file.md +25 -0
  154. package/webinterface/docs/card-help/csv-transform.md +24 -0
  155. package/webinterface/docs/card-help/end.md +11 -0
  156. package/webinterface/docs/card-help/error-message.md +16 -0
  157. package/webinterface/docs/card-help/expression-solver.md +21 -0
  158. package/webinterface/docs/card-help/get-json.md +24 -0
  159. package/webinterface/docs/card-help/get-text.md +24 -0
  160. package/webinterface/docs/card-help/histogram.md +23 -0
  161. package/webinterface/docs/card-help/if-conditional.md +23 -0
  162. package/webinterface/docs/card-help/launch-operation.md +25 -0
  163. package/webinterface/docs/card-help/list-files.md +25 -0
  164. package/webinterface/docs/card-help/llm-chat-completion.md +43 -0
  165. package/webinterface/docs/card-help/llm-embedding.md +24 -0
  166. package/webinterface/docs/card-help/llm-tool-use.md +39 -0
  167. package/webinterface/docs/card-help/meadow-count.md +24 -0
  168. package/webinterface/docs/card-help/meadow-create.md +24 -0
  169. package/webinterface/docs/card-help/meadow-delete.md +19 -0
  170. package/webinterface/docs/card-help/meadow-read.md +24 -0
  171. package/webinterface/docs/card-help/meadow-reads.md +27 -0
  172. package/webinterface/docs/card-help/meadow-update.md +24 -0
  173. package/webinterface/docs/card-help/parse-csv.md +27 -0
  174. package/webinterface/docs/card-help/read-file-buffered.md +29 -0
  175. package/webinterface/docs/card-help/read-file.md +24 -0
  176. package/webinterface/docs/card-help/read-json.md +21 -0
  177. package/webinterface/docs/card-help/replace-string.md +25 -0
  178. package/webinterface/docs/card-help/rest-request.md +30 -0
  179. package/webinterface/docs/card-help/send-json.md +26 -0
  180. package/webinterface/docs/card-help/set-values.md +16 -0
  181. package/webinterface/docs/card-help/split-execute.md +35 -0
  182. package/webinterface/docs/card-help/start.md +11 -0
  183. package/webinterface/docs/card-help/string-appender.md +22 -0
  184. package/webinterface/docs/card-help/template-string.md +21 -0
  185. package/webinterface/docs/card-help/value-input.md +24 -0
  186. package/webinterface/docs/card-help/write-file.md +27 -0
  187. package/webinterface/docs/card-help/write-json.md +28 -0
  188. package/webinterface/html/index.html +5 -0
  189. package/webinterface/package.json +13 -4
  190. package/webinterface/source/Pict-Application-Ultravisor.js +564 -70
  191. package/webinterface/source/Ultravisor-TimingUtils.js +99 -0
  192. package/webinterface/source/card-help-content.js +46 -0
  193. package/webinterface/source/cards/Ultravisor-BuiltIn-CardConfigs.js +174 -0
  194. package/webinterface/source/cards/Ultravisor-CardConfigGenerator.js +431 -0
  195. package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
  196. package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
  197. package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
  198. package/webinterface/source/panels/Ultravisor-CardSettingsPanel.js +902 -0
  199. package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +20 -8
  200. package/webinterface/source/views/PictView-Ultravisor-BeaconList.js +817 -0
  201. package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +5 -5
  202. package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +25 -25
  203. package/webinterface/source/views/PictView-Ultravisor-Documentation.js +856 -0
  204. package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +777 -0
  205. package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +321 -58
  206. package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +36 -91
  207. package/webinterface/source/views/PictView-Ultravisor-OperationList.js +388 -16
  208. package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
  209. package/webinterface/source/views/PictView-Ultravisor-Schedule.js +521 -65
  210. package/webinterface/source/views/PictView-Ultravisor-TimingView.js +333 -71
  211. package/webinterface/source/views/PictView-Ultravisor-TopBar.js +257 -21
  212. package/webinterface/theme-sampler.html +645 -0
  213. package/debug/Harness.js +0 -6
  214. package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
  215. package/source/services/Ultravisor-Operation.cjs +0 -200
  216. package/source/services/Ultravisor-Task.cjs +0 -349
  217. package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
  218. package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
  219. package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
  220. package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
  221. package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
  222. package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
  223. package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
  224. package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
  225. package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
  226. package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
  227. package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
  228. package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
  229. package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
  230. package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
  231. package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
  232. package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
  233. package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
  234. package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
  235. package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
  236. package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
  237. package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
  238. package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
  239. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
  240. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
  241. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
  242. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
  243. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
  244. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
  245. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
  246. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
  247. package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
  248. package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
@@ -1,5 +1,7 @@
1
1
  const libPictView = require('pict-view');
2
2
 
3
+ const libTimingUtils = require('../Ultravisor-TimingUtils.js');
4
+
3
5
  const _ViewConfiguration =
4
6
  {
5
7
  ViewIdentifier: "Ultravisor-ManifestList",
@@ -21,20 +23,20 @@ const _ViewConfiguration =
21
23
  align-items: center;
22
24
  margin-bottom: 1.5em;
23
25
  padding-bottom: 1em;
24
- border-bottom: 1px solid #2a2a4a;
26
+ border-bottom: 1px solid var(--uv-border-subtle);
25
27
  }
26
28
  .ultravisor-manifestlist-header h1 {
27
29
  margin: 0;
28
30
  font-size: 2em;
29
31
  font-weight: 300;
30
- color: #e0e0e0;
32
+ color: var(--uv-text);
31
33
  }
32
34
  .ultravisor-manifest-table {
33
35
  width: 100%;
34
36
  border-collapse: collapse;
35
37
  }
36
38
  .ultravisor-manifest-table th {
37
- background-color: #16213e;
39
+ background-color: var(--uv-bg-surface);
38
40
  }
39
41
  .ultravisor-manifest-table tr:hover td {
40
42
  background-color: #1a2744;
@@ -51,16 +53,20 @@ const _ViewConfiguration =
51
53
  color: #c8e6c9;
52
54
  }
53
55
  .ultravisor-manifest-status.running {
54
- background-color: #1565c0;
55
- color: #bbdefb;
56
+ background-color: var(--uv-info);
57
+ color: var(--uv-text-heading);
56
58
  }
57
59
  .ultravisor-manifest-status.error {
58
60
  background-color: #c62828;
59
61
  color: #ffcdd2;
60
62
  }
63
+ .ultravisor-manifest-status.waiting {
64
+ background-color: var(--uv-warning);
65
+ color: #fff9c4;
66
+ }
61
67
  .ultravisor-manifest-detail {
62
- background: #16213e;
63
- border: 1px solid #2a2a4a;
68
+ background: var(--uv-bg-surface);
69
+ border: 1px solid var(--uv-border-subtle);
64
70
  border-radius: 8px;
65
71
  padding: 1.5em;
66
72
  margin-top: 1em;
@@ -71,10 +77,10 @@ const _ViewConfiguration =
71
77
  }
72
78
  .ultravisor-manifest-detail h3 {
73
79
  margin: 0 0 1em 0;
74
- color: #b0bec5;
80
+ color: var(--uv-text-secondary);
75
81
  }
76
82
  .ultravisor-manifest-task-result {
77
- background: #1a1a2e;
83
+ background: var(--uv-bg-base);
78
84
  border-radius: 4px;
79
85
  padding: 0.75em;
80
86
  margin-bottom: 0.5em;
@@ -86,7 +92,7 @@ const _ViewConfiguration =
86
92
  margin-bottom: 0.5em;
87
93
  }
88
94
  .ultravisor-manifest-task-result-header code {
89
- color: #4fc3f7;
95
+ color: var(--uv-brand);
90
96
  }
91
97
  .ultravisor-manifest-output {
92
98
  background: #0d1117;
@@ -101,12 +107,6 @@ const _ViewConfiguration =
101
107
  overflow-y: auto;
102
108
  margin-top: 0.5em;
103
109
  }
104
- .ultravisor-manifest-success-true {
105
- color: #66bb6a;
106
- }
107
- .ultravisor-manifest-success-false {
108
- color: #ef5350;
109
- }
110
110
  `,
111
111
 
112
112
  Templates:
@@ -169,28 +169,28 @@ class UltravisorManifestListView extends libPictView
169
169
  }
170
170
 
171
171
  let tmpHTML = '<table class="ultravisor-manifest-table">';
172
- tmpHTML += '<thead><tr><th>Run GUID</th><th>Operation</th><th>Status</th><th>Success</th><th>Started</th><th>Actions</th></tr></thead>';
172
+ tmpHTML += '<thead><tr><th>Run Hash</th><th>Operation</th><th>Status</th><th>Elapsed</th><th>Started</th><th>Actions</th></tr></thead>';
173
173
  tmpHTML += '<tbody>';
174
174
 
175
175
  for (let i = 0; i < tmpManifests.length; i++)
176
176
  {
177
177
  let tmpManifest = tmpManifests[i];
178
- let tmpGUIDRun = tmpManifest.GUIDRun || '';
179
- let tmpEscGUID = tmpGUIDRun.replace(/'/g, "\\'");
178
+ let tmpRunHash = tmpManifest.Hash || '';
179
+ let tmpEscHash = tmpRunHash.replace(/'/g, "\\'");
180
180
  let tmpStatus = tmpManifest.Status || 'Unknown';
181
181
  let tmpStatusClass = tmpStatus.toLowerCase();
182
- if (tmpStatusClass !== 'complete' && tmpStatusClass !== 'running' && tmpStatusClass !== 'error')
182
+ if (tmpStatusClass !== 'complete' && tmpStatusClass !== 'running' && tmpStatusClass !== 'error' && tmpStatusClass !== 'waiting')
183
183
  {
184
184
  tmpStatusClass = '';
185
185
  }
186
186
 
187
187
  tmpHTML += '<tr>';
188
- tmpHTML += '<td><code style="font-size:0.8em;">' + tmpGUIDRun + '</code></td>';
189
- tmpHTML += '<td>' + (tmpManifest.Name || tmpManifest.GUIDOperation || '') + '</td>';
190
- tmpHTML += '<td><span class="ultravisor-manifest-status ' + tmpStatusClass + '">' + tmpStatus + '</span></td>';
191
- tmpHTML += '<td><span class="ultravisor-manifest-success-' + (tmpManifest.Success ? 'true' : 'false') + '">' + (tmpManifest.Success ? 'Yes' : 'No') + '</span></td>';
192
- tmpHTML += '<td>' + (tmpManifest.StartTime || '') + '</td>';
193
- tmpHTML += '<td><button class="ultravisor-btn-sm ultravisor-btn-edit" onclick="' + tmpViewRef + '.showManifestDetail(\'' + tmpEscGUID + '\')">Details</button></td>';
188
+ tmpHTML += '<td><code style="font-size:0.8em;">' + libTimingUtils.escapeHTML(tmpRunHash) + '</code></td>';
189
+ tmpHTML += '<td>' + libTimingUtils.escapeHTML(tmpManifest.OperationHash || '') + '</td>';
190
+ tmpHTML += '<td><span class="ultravisor-manifest-status ' + tmpStatusClass + '">' + libTimingUtils.escapeHTML(tmpStatus) + '</span></td>';
191
+ tmpHTML += '<td>' + (tmpManifest.ElapsedMs ? this.fable.DataFormat.formatTimeSpan(tmpManifest.ElapsedMs) + ' (' + tmpManifest.ElapsedMs + 'ms)' : '') + '</td>';
192
+ tmpHTML += '<td>' + libTimingUtils.escapeHTML(tmpManifest.StartTime || '') + '</td>';
193
+ tmpHTML += '<td><button class="ultravisor-btn-sm ultravisor-btn-edit" onclick="' + tmpViewRef + '.showManifestDetail(\'' + tmpEscHash + '\')">Details</button></td>';
194
194
  tmpHTML += '</tr>';
195
195
  }
196
196
 
@@ -198,62 +198,114 @@ class UltravisorManifestListView extends libPictView
198
198
  this.pict.ContentAssignment.assignContent('#Ultravisor-ManifestList-Body', tmpHTML);
199
199
  }
200
200
 
201
- showManifestDetail(pGUIDRun)
201
+ showManifestDetail(pRunHash)
202
202
  {
203
- this.pict.PictApplication.loadManifest(pGUIDRun,
203
+ this.pict.PictApplication.loadManifest(pRunHash,
204
204
  function (pError, pManifest)
205
205
  {
206
206
  if (pError || !pManifest)
207
207
  {
208
208
  this.pict.ContentAssignment.assignContent('#Ultravisor-ManifestList-Detail',
209
- '<div class="ultravisor-manifest-detail visible"><p style="color:#ef5350;">Error loading manifest details.</p></div>');
209
+ '<div class="ultravisor-manifest-detail visible"><p style="color:var(--uv-error);">Error loading manifest details.</p></div>');
210
210
  return;
211
211
  }
212
212
 
213
213
  let tmpHTML = '<div class="ultravisor-manifest-detail visible">';
214
- tmpHTML += '<h3>Run: ' + (pManifest.GUIDRun || '') + '</h3>';
215
- tmpHTML += '<p><strong>Operation:</strong> ' + (pManifest.Name || pManifest.GUIDOperation || '') + '</p>';
216
- tmpHTML += '<p><strong>Status:</strong> ' + (pManifest.Status || '') + ' &middot; <strong>Success:</strong> ' + (pManifest.Success ? 'Yes' : 'No') + '</p>';
217
- tmpHTML += '<p><strong>Start:</strong> ' + (pManifest.StartTime || '') + ' &middot; <strong>Stop:</strong> ' + (pManifest.StopTime || '') + '</p>';
214
+ tmpHTML += '<h3>Run: ' + libTimingUtils.escapeHTML(pManifest.Hash || '') + '</h3>';
215
+ tmpHTML += '<p><strong>Operation:</strong> ' + libTimingUtils.escapeHTML(pManifest.OperationHash || '') + '</p>';
216
+ tmpHTML += '<p><strong>Status:</strong> ' + libTimingUtils.escapeHTML(pManifest.Status || '') + '</p>';
217
+ tmpHTML += '<p><strong>Start:</strong> ' + libTimingUtils.escapeHTML(pManifest.StartTime || '') + ' &middot; <strong>Stop:</strong> ' + libTimingUtils.escapeHTML(pManifest.StopTime || '') + '</p>';
218
+ tmpHTML += '<p><strong>Elapsed:</strong> ' + this.fable.DataFormat.formatTimeSpan(pManifest.ElapsedMs || 0) + ' (' + (pManifest.ElapsedMs || 0) + 'ms)</p>';
219
+ if (pManifest.RunMode)
220
+ {
221
+ tmpHTML += '<p><strong>Run Mode:</strong> ' + libTimingUtils.escapeHTML(pManifest.RunMode) + '</p>';
222
+ }
223
+
224
+ // Operation Output (always present if non-empty)
225
+ if (pManifest.Output && Object.keys(pManifest.Output).length > 0)
226
+ {
227
+ tmpHTML += '<h3>Output</h3>';
228
+ tmpHTML += '<div class="ultravisor-manifest-output">' + libTimingUtils.escapeHTML(JSON.stringify(pManifest.Output, null, 2)) + '</div>';
229
+ }
230
+
231
+ // Debug-mode state (only present in debug manifests)
232
+ if (pManifest.OperationState && Object.keys(pManifest.OperationState).length > 0)
233
+ {
234
+ tmpHTML += '<h3>Operation State</h3>';
235
+ tmpHTML += '<div class="ultravisor-manifest-output">' + libTimingUtils.escapeHTML(JSON.stringify(pManifest.OperationState, null, 2)) + '</div>';
236
+ }
237
+ if (pManifest.GlobalState && Object.keys(pManifest.GlobalState).length > 0)
238
+ {
239
+ tmpHTML += '<h3>Global State</h3>';
240
+ tmpHTML += '<div class="ultravisor-manifest-output">' + libTimingUtils.escapeHTML(JSON.stringify(pManifest.GlobalState, null, 2)) + '</div>';
241
+ }
218
242
 
219
- if (pManifest.Summary)
243
+ // Task Outputs
244
+ if (pManifest.TaskOutputs && Object.keys(pManifest.TaskOutputs).length > 0)
220
245
  {
221
- tmpHTML += '<p><strong>Summary:</strong> ' + this.escapeHTML(pManifest.Summary) + '</p>';
246
+ tmpHTML += '<h3>Task Outputs</h3>';
247
+ tmpHTML += '<div class="ultravisor-manifest-output">' + libTimingUtils.escapeHTML(JSON.stringify(pManifest.TaskOutputs, null, 2)) + '</div>';
222
248
  }
223
249
 
224
- // Task results
225
- let tmpTaskResults = pManifest.TaskResults || [];
226
- if (tmpTaskResults.length > 0)
250
+ // Task Manifests (object keyed by node hash)
251
+ if (pManifest.TaskManifests && Object.keys(pManifest.TaskManifests).length > 0)
227
252
  {
228
- tmpHTML += '<h3>Task Results</h3>';
229
- for (let i = 0; i < tmpTaskResults.length; i++)
253
+ tmpHTML += '<h3>Task Manifests</h3>';
254
+ let tmpNodeHashes = Object.keys(pManifest.TaskManifests);
255
+ for (let i = 0; i < tmpNodeHashes.length; i++)
230
256
  {
231
- let tmpResult = tmpTaskResults[i];
257
+ let tmpNodeHash = tmpNodeHashes[i];
258
+ let tmpTaskManifest = pManifest.TaskManifests[tmpNodeHash];
232
259
  tmpHTML += '<div class="ultravisor-manifest-task-result">';
233
260
  tmpHTML += '<div class="ultravisor-manifest-task-result-header">';
234
- tmpHTML += '<code>' + (tmpResult.GUIDTask || '') + '</code>';
235
- tmpHTML += '<span class="ultravisor-manifest-status ' + (tmpResult.Status || '').toLowerCase() + '">' + (tmpResult.Status || '') + '</span>';
261
+ tmpHTML += '<code>' + libTimingUtils.escapeHTML(tmpNodeHash) + '</code>';
262
+ tmpHTML += '<span class="ultravisor-manifest-status ' + (tmpTaskManifest.Status || '').toLowerCase() + '">' + libTimingUtils.escapeHTML(tmpTaskManifest.Status || '') + '</span>';
236
263
  tmpHTML += '</div>';
237
- tmpHTML += '<p style="margin:0.25em 0; font-size:0.85em; color:#78909c;">' + (tmpResult.Name || '') + ' (' + (tmpResult.Type || '') + ')</p>';
238
-
239
- if (tmpResult.Output)
240
- {
241
- tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(String(tmpResult.Output)) + '</div>';
242
- }
243
-
244
- if (tmpResult.Log && tmpResult.Log.length > 0)
264
+ if (tmpTaskManifest.Output)
245
265
  {
246
- tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(tmpResult.Log.join('\n')) + '</div>';
266
+ tmpHTML += '<div class="ultravisor-manifest-output">' + libTimingUtils.escapeHTML(JSON.stringify(tmpTaskManifest.Output, null, 2)) + '</div>';
247
267
  }
248
268
  tmpHTML += '</div>';
249
269
  }
250
270
  }
251
271
 
252
- // Operation log
272
+ // Errors
273
+ if (pManifest.Errors && pManifest.Errors.length > 0)
274
+ {
275
+ tmpHTML += '<h3 style="color:var(--uv-error);">Errors</h3>';
276
+ tmpHTML += '<div class="ultravisor-manifest-output" style="border: 1px solid var(--uv-error);">' + libTimingUtils.escapeHTML(pManifest.Errors.join('\n')) + '</div>';
277
+ }
278
+
279
+ // Log
253
280
  if (pManifest.Log && pManifest.Log.length > 0)
254
281
  {
255
- tmpHTML += '<h3>Operation Log</h3>';
256
- tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(pManifest.Log.join('\n')) + '</div>';
282
+ tmpHTML += '<h3>Log</h3>';
283
+ tmpHTML += '<div class="ultravisor-manifest-output">' + libTimingUtils.escapeHTML(pManifest.Log.join('\n')) + '</div>';
284
+ }
285
+
286
+ // ---- Timing Analysis ----
287
+ let tmpHasTimingData = (pManifest.TimingSummary &&
288
+ (pManifest.TimingSummary.ByCategory || pManifest.TimingSummary.ByTaskType)) ||
289
+ (pManifest.TaskManifests && Object.keys(pManifest.TaskManifests).length > 0);
290
+
291
+ if (tmpHasTimingData)
292
+ {
293
+ tmpHTML += '<h3 style="margin-top: 1.5em;">Timing Analysis</h3>';
294
+
295
+ // Task Timeline
296
+ tmpHTML += this._renderTaskTimeline(pManifest);
297
+
298
+ // Category Histogram
299
+ if (pManifest.TimingSummary && pManifest.TimingSummary.ByCategory)
300
+ {
301
+ tmpHTML += this._renderCategoryHistogram(pManifest.TimingSummary.ByCategory);
302
+ }
303
+
304
+ // Task Type Histogram
305
+ if (pManifest.TimingSummary && pManifest.TimingSummary.ByTaskType)
306
+ {
307
+ tmpHTML += this._renderTaskTypeHistogram(pManifest.TimingSummary.ByTaskType);
308
+ }
257
309
  }
258
310
 
259
311
  tmpHTML += '</div>';
@@ -261,10 +313,221 @@ class UltravisorManifestListView extends libPictView
261
313
  }.bind(this));
262
314
  }
263
315
 
264
- escapeHTML(pValue)
316
+ // ── Timing Visualization Methods ─────────────────────────────────────
317
+
318
+ /**
319
+ * Render a horizontal bar chart of individual task durations.
320
+ * Color-coded by status: complete=green, error=red, running=blue.
321
+ *
322
+ * @param {Object} pManifest - The full manifest object
323
+ * @returns {string} HTML string
324
+ */
325
+ _renderTaskTimeline(pManifest)
326
+ {
327
+ // Convert TaskManifests to array with computed elapsed + status
328
+ let tmpTaskResults = [];
329
+ if (pManifest.TaskManifests && typeof pManifest.TaskManifests === 'object')
330
+ {
331
+ let tmpKeys = Object.keys(pManifest.TaskManifests);
332
+ for (let k = 0; k < tmpKeys.length; k++)
333
+ {
334
+ let tmpEntry = pManifest.TaskManifests[tmpKeys[k]];
335
+ tmpEntry._NodeHash = tmpKeys[k];
336
+ tmpEntry._ComputedElapsedMs = libTimingUtils.computeTaskElapsedMs(tmpEntry);
337
+ tmpEntry._ComputedStatus = libTimingUtils.computeTaskStatus(tmpEntry);
338
+ tmpTaskResults.push(tmpEntry);
339
+ }
340
+ }
341
+
342
+ if (tmpTaskResults.length === 0)
343
+ {
344
+ return '';
345
+ }
346
+
347
+ // Find max task duration for bar scaling
348
+ let tmpMaxTaskMs = 0;
349
+ for (let i = 0; i < tmpTaskResults.length; i++)
350
+ {
351
+ let tmpMs = tmpTaskResults[i]._ComputedElapsedMs;
352
+ if (tmpMs > tmpMaxTaskMs)
353
+ {
354
+ tmpMaxTaskMs = tmpMs;
355
+ }
356
+ }
357
+ if (tmpMaxTaskMs <= 0)
358
+ {
359
+ tmpMaxTaskMs = 1;
360
+ }
361
+
362
+ let tmpHTML = '<div class="ultravisor-timing-card">';
363
+ tmpHTML += '<div class="ultravisor-timing-chart">';
364
+ tmpHTML += '<div class="ultravisor-timing-chart-title">Task Timeline</div>';
365
+
366
+ for (let i = 0; i < tmpTaskResults.length; i++)
367
+ {
368
+ let tmpResult = tmpTaskResults[i];
369
+ let tmpTaskMs = tmpResult._ComputedElapsedMs;
370
+ let tmpTaskFormatted = libTimingUtils.formatMs(tmpTaskMs);
371
+ let tmpTaskStatus = tmpResult._ComputedStatus.toLowerCase();
372
+ let tmpBarClass = 'other';
373
+ if (tmpTaskStatus === 'complete')
374
+ {
375
+ tmpBarClass = 'complete';
376
+ }
377
+ else if (tmpTaskStatus === 'error')
378
+ {
379
+ tmpBarClass = 'error';
380
+ }
381
+ else if (tmpTaskStatus === 'running')
382
+ {
383
+ tmpBarClass = 'running';
384
+ }
385
+
386
+ let tmpWidthPercent = Math.max((tmpTaskMs / tmpMaxTaskMs) * 100, 1);
387
+ let tmpNodeHash = tmpResult._NodeHash || '';
388
+ let tmpDisplayName = tmpResult.TaskTypeName || tmpResult._NodeHash || 'Task ' + (i + 1);
389
+
390
+ let tmpRowData =
391
+ {
392
+ Label: libTimingUtils.escapeHTML(tmpDisplayName),
393
+ LabelTitle: libTimingUtils.escapeHTML(tmpNodeHash),
394
+ LabelStyle: '',
395
+ BarClass: tmpBarClass,
396
+ BarStyle: '',
397
+ WidthPercent: tmpWidthPercent.toFixed(1),
398
+ BarText: (tmpWidthPercent > 20) ? '<span class="ultravisor-timing-row-bar-text">' + libTimingUtils.escapeHTML(tmpDisplayName) + '</span>' : '',
399
+ Duration: libTimingUtils.escapeHTML(tmpTaskFormatted),
400
+ CountHTML: ''
401
+ };
402
+ tmpHTML += this.pict.parseTemplateByHash('Ultravisor-Timing-Row-Template', tmpRowData);
403
+ }
404
+
405
+ // Time axis
406
+ tmpHTML += '<div class="ultravisor-timing-axis">';
407
+ tmpHTML += '<div class="ultravisor-timing-axis-line">';
408
+ let tmpTickCount = 5;
409
+ for (let t = 0; t <= tmpTickCount; t++)
410
+ {
411
+ let tmpTickMs = (tmpMaxTaskMs / tmpTickCount) * t;
412
+ tmpHTML += '<span class="ultravisor-timing-axis-tick">' + libTimingUtils.formatMs(tmpTickMs) + '</span>';
413
+ }
414
+ tmpHTML += '</div>';
415
+ tmpHTML += '<div class="ultravisor-timing-axis-spacer"></div>';
416
+ tmpHTML += '</div>';
417
+
418
+ tmpHTML += '</div>';
419
+ tmpHTML += '</div>';
420
+ return tmpHTML;
421
+ }
422
+
423
+ /**
424
+ * Render a category histogram (time aggregated by category).
425
+ *
426
+ * @param {Object} pByCategory - { CategoryName: { TotalMs, Count } }
427
+ * @returns {string} HTML string
428
+ */
429
+ _renderCategoryHistogram(pByCategory)
265
430
  {
266
- if (!pValue) return '';
267
- return String(pValue).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
431
+ let tmpCategories = Object.keys(pByCategory);
432
+ if (tmpCategories.length === 0)
433
+ {
434
+ return '';
435
+ }
436
+
437
+ // Sort by TotalMs descending
438
+ tmpCategories.sort(function (pA, pB)
439
+ {
440
+ return (pByCategory[pB].TotalMs || 0) - (pByCategory[pA].TotalMs || 0);
441
+ });
442
+
443
+ let tmpMaxMs = pByCategory[tmpCategories[0]].TotalMs || 1;
444
+
445
+ let tmpHTML = '<div class="ultravisor-timing-card">';
446
+ tmpHTML += '<div class="ultravisor-timing-chart">';
447
+ tmpHTML += '<div class="ultravisor-timing-chart-title">Time by Category</div>';
448
+
449
+ for (let i = 0; i < tmpCategories.length; i++)
450
+ {
451
+ let tmpCat = tmpCategories[i];
452
+ let tmpData = pByCategory[tmpCat];
453
+ let tmpMs = tmpData.TotalMs || 0;
454
+ let tmpWidthPercent = Math.max((tmpMs / tmpMaxMs) * 100, 1);
455
+ let tmpColors = libTimingUtils.CategoryColors[tmpCat] || libTimingUtils.CategoryColors['Uncategorized'];
456
+
457
+ let tmpRowData =
458
+ {
459
+ Label: libTimingUtils.escapeHTML(tmpCat),
460
+ LabelTitle: '',
461
+ LabelStyle: 'color:' + tmpColors.text + ';',
462
+ BarClass: '',
463
+ BarStyle: ' background: ' + tmpColors.bar + ';',
464
+ WidthPercent: tmpWidthPercent.toFixed(1),
465
+ BarText: (tmpWidthPercent > 15) ? '<span class="ultravisor-timing-row-bar-text">' + libTimingUtils.formatMs(tmpMs) + '</span>' : '',
466
+ Duration: libTimingUtils.formatMs(tmpMs),
467
+ CountHTML: '<div class="ultravisor-timing-row-count">' + tmpData.Count + 'x</div>'
468
+ };
469
+ tmpHTML += this.pict.parseTemplateByHash('Ultravisor-Timing-Row-Template', tmpRowData);
470
+ }
471
+
472
+ tmpHTML += '</div>';
473
+ tmpHTML += '</div>';
474
+ return tmpHTML;
475
+ }
476
+
477
+ /**
478
+ * Render a task type histogram (time broken down by task type).
479
+ *
480
+ * @param {Object} pByTaskType - { TaskTypeId: { TotalMs, Count, Category, Name } }
481
+ * @returns {string} HTML string
482
+ */
483
+ _renderTaskTypeHistogram(pByTaskType)
484
+ {
485
+ let tmpTypes = Object.keys(pByTaskType);
486
+ if (tmpTypes.length === 0)
487
+ {
488
+ return '';
489
+ }
490
+
491
+ // Sort by TotalMs descending
492
+ tmpTypes.sort(function (pA, pB)
493
+ {
494
+ return (pByTaskType[pB].TotalMs || 0) - (pByTaskType[pA].TotalMs || 0);
495
+ });
496
+
497
+ let tmpMaxMs = pByTaskType[tmpTypes[0]].TotalMs || 1;
498
+
499
+ let tmpHTML = '<div class="ultravisor-timing-card">';
500
+ tmpHTML += '<div class="ultravisor-timing-chart">';
501
+ tmpHTML += '<div class="ultravisor-timing-chart-title">Time by Task Type</div>';
502
+
503
+ for (let i = 0; i < tmpTypes.length; i++)
504
+ {
505
+ let tmpType = tmpTypes[i];
506
+ let tmpData = pByTaskType[tmpType];
507
+ let tmpMs = tmpData.TotalMs || 0;
508
+ let tmpWidthPercent = Math.max((tmpMs / tmpMaxMs) * 100, 1);
509
+ let tmpCategory = tmpData.Category || 'Uncategorized';
510
+ let tmpColors = libTimingUtils.CategoryColors[tmpCategory] || libTimingUtils.CategoryColors['Uncategorized'];
511
+ let tmpDisplayName = tmpData.Name || tmpType;
512
+
513
+ let tmpRowData =
514
+ {
515
+ Label: libTimingUtils.escapeHTML(tmpDisplayName),
516
+ LabelTitle: libTimingUtils.escapeHTML(tmpType),
517
+ LabelStyle: '',
518
+ BarClass: '',
519
+ BarStyle: ' background: ' + tmpColors.bar + ';',
520
+ WidthPercent: tmpWidthPercent.toFixed(1),
521
+ BarText: (tmpWidthPercent > 15) ? '<span class="ultravisor-timing-row-bar-text">' + libTimingUtils.formatMs(tmpMs) + '</span>' : '',
522
+ Duration: libTimingUtils.formatMs(tmpMs),
523
+ CountHTML: '<div class="ultravisor-timing-row-count">' + tmpData.Count + 'x</div>'
524
+ };
525
+ tmpHTML += this.pict.parseTemplateByHash('Ultravisor-Timing-Row-Template', tmpRowData);
526
+ }
527
+
528
+ tmpHTML += '</div>';
529
+ tmpHTML += '</div>';
530
+ return tmpHTML;
268
531
  }
269
532
  }
270
533