flow-frame-core 0.1.0

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 (416) hide show
  1. package/README.md +64 -0
  2. package/dist/Dockerfile +86 -0
  3. package/dist/GPU_DEPLOYMENT_README.md +324 -0
  4. package/dist/OPS_AGENT_README.md +174 -0
  5. package/dist/README-H100-VM.md +192 -0
  6. package/dist/README-worker-pools.md +231 -0
  7. package/dist/README.md +8 -0
  8. package/dist/WEB-ELEMENT-REQUESTS-README.md +302 -0
  9. package/dist/append.d.ts +3 -0
  10. package/dist/append.d.ts.map +1 -0
  11. package/dist/append.js +42 -0
  12. package/dist/append.js.map +1 -0
  13. package/dist/audioRoutes.d.ts +2 -0
  14. package/dist/audioRoutes.d.ts.map +1 -0
  15. package/dist/audioRoutes.js +97 -0
  16. package/dist/audioRoutes.js.map +1 -0
  17. package/dist/augment-parallel.d.ts +6 -0
  18. package/dist/augment-parallel.d.ts.map +1 -0
  19. package/dist/augment-parallel.js +128 -0
  20. package/dist/augment-parallel.js.map +1 -0
  21. package/dist/augment-worker.d.ts +2 -0
  22. package/dist/augment-worker.d.ts.map +1 -0
  23. package/dist/augment-worker.js +100 -0
  24. package/dist/augment-worker.js.map +1 -0
  25. package/dist/browerRoutes.d.ts +2 -0
  26. package/dist/browerRoutes.d.ts.map +1 -0
  27. package/dist/browerRoutes.js +323 -0
  28. package/dist/browerRoutes.js.map +1 -0
  29. package/dist/browser-utils/utils.d.ts +6 -0
  30. package/dist/browser-utils/utils.d.ts.map +1 -0
  31. package/dist/browser-utils/utils.js +133 -0
  32. package/dist/browser-utils/utils.js.map +1 -0
  33. package/dist/capture_training_data_endpoints.d.ts +158 -0
  34. package/dist/capture_training_data_endpoints.d.ts.map +1 -0
  35. package/dist/capture_training_data_endpoints.js +1812 -0
  36. package/dist/capture_training_data_endpoints.js.map +1 -0
  37. package/dist/config.json +28 -0
  38. package/dist/configEndpoints.d.ts +2 -0
  39. package/dist/configEndpoints.d.ts.map +1 -0
  40. package/dist/configEndpoints.js +459 -0
  41. package/dist/configEndpoints.js.map +1 -0
  42. package/dist/constants.d.ts +109 -0
  43. package/dist/constants.d.ts.map +1 -0
  44. package/dist/constants.js +110 -0
  45. package/dist/constants.js.map +1 -0
  46. package/dist/docs/workflow_nodes.md +257 -0
  47. package/dist/download.d.ts +11 -0
  48. package/dist/download.d.ts.map +1 -0
  49. package/dist/download.js +31 -0
  50. package/dist/download.js.map +1 -0
  51. package/dist/download.py +61 -0
  52. package/dist/ecosystem.config.json +63 -0
  53. package/dist/email-body-extractor.d.ts +20 -0
  54. package/dist/email-body-extractor.d.ts.map +1 -0
  55. package/dist/email-body-extractor.js +103 -0
  56. package/dist/email-body-extractor.js.map +1 -0
  57. package/dist/express_util.d.ts +2 -0
  58. package/dist/express_util.d.ts.map +1 -0
  59. package/dist/express_util.js +30 -0
  60. package/dist/express_util.js.map +1 -0
  61. package/dist/extension/background.d.ts +2 -0
  62. package/dist/extension/background.d.ts.map +1 -0
  63. package/dist/extension/background.js +268 -0
  64. package/dist/extension/background.js.map +1 -0
  65. package/dist/extension/manifest.json +19 -0
  66. package/dist/extensionUtils.d.ts +2 -0
  67. package/dist/extensionUtils.d.ts.map +1 -0
  68. package/dist/extensionUtils.js +48 -0
  69. package/dist/extensionUtils.js.map +1 -0
  70. package/dist/filter-gmail-poller/README.md +320 -0
  71. package/dist/filter-gmail-poller/demo.d.ts +2 -0
  72. package/dist/filter-gmail-poller/demo.d.ts.map +1 -0
  73. package/dist/filter-gmail-poller/demo.js +79 -0
  74. package/dist/filter-gmail-poller/demo.js.map +1 -0
  75. package/dist/filter-gmail-poller/example-existing-app.d.ts +2 -0
  76. package/dist/filter-gmail-poller/example-existing-app.d.ts.map +1 -0
  77. package/dist/filter-gmail-poller/example-existing-app.js +72 -0
  78. package/dist/filter-gmail-poller/example-existing-app.js.map +1 -0
  79. package/dist/filter-gmail-poller/filter-gmail-poller.d.ts +160 -0
  80. package/dist/filter-gmail-poller/filter-gmail-poller.d.ts.map +1 -0
  81. package/dist/filter-gmail-poller/filter-gmail-poller.js +1048 -0
  82. package/dist/filter-gmail-poller/filter-gmail-poller.js.map +1 -0
  83. package/dist/filter-gmail-poller/index.d.ts +3 -0
  84. package/dist/filter-gmail-poller/index.d.ts.map +1 -0
  85. package/dist/filter-gmail-poller/index.js +18 -0
  86. package/dist/filter-gmail-poller/index.js.map +1 -0
  87. package/dist/filter-gmail-poller/manual-test.d.ts +2 -0
  88. package/dist/filter-gmail-poller/manual-test.d.ts.map +1 -0
  89. package/dist/filter-gmail-poller/manual-test.js +70 -0
  90. package/dist/filter-gmail-poller/manual-test.js.map +1 -0
  91. package/dist/filter-gmail-poller/poller-prompts.d.ts +12 -0
  92. package/dist/filter-gmail-poller/poller-prompts.d.ts.map +1 -0
  93. package/dist/filter-gmail-poller/poller-prompts.js +330 -0
  94. package/dist/filter-gmail-poller/poller-prompts.js.map +1 -0
  95. package/dist/filter-gmail-poller/test.js +69 -0
  96. package/dist/flowframe-auto-firebase-adminsdk.json +13 -0
  97. package/dist/gmail-poller/README-microsoft-email-poller.md +203 -0
  98. package/dist/gmail-poller/README.md +129 -0
  99. package/dist/gmail-poller/example.d.ts +5 -0
  100. package/dist/gmail-poller/example.d.ts.map +1 -0
  101. package/dist/gmail-poller/example.js +83 -0
  102. package/dist/gmail-poller/example.js.map +1 -0
  103. package/dist/gmail-poller/gmail-poller.d.ts +82 -0
  104. package/dist/gmail-poller/gmail-poller.d.ts.map +1 -0
  105. package/dist/gmail-poller/gmail-poller.js +455 -0
  106. package/dist/gmail-poller/gmail-poller.js.map +1 -0
  107. package/dist/gmail-poller/manual-test.d.ts +2 -0
  108. package/dist/gmail-poller/manual-test.d.ts.map +1 -0
  109. package/dist/gmail-poller/manual-test.js +37 -0
  110. package/dist/gmail-poller/manual-test.js.map +1 -0
  111. package/dist/gmail-poller/microsoft-email-example.d.ts +8 -0
  112. package/dist/gmail-poller/microsoft-email-example.d.ts.map +1 -0
  113. package/dist/gmail-poller/microsoft-email-example.js +58 -0
  114. package/dist/gmail-poller/microsoft-email-example.js.map +1 -0
  115. package/dist/gmail-poller/microsoft-email-poller.d.ts +73 -0
  116. package/dist/gmail-poller/microsoft-email-poller.d.ts.map +1 -0
  117. package/dist/gmail-poller/microsoft-email-poller.js +346 -0
  118. package/dist/gmail-poller/microsoft-email-poller.js.map +1 -0
  119. package/dist/gmail-poller/setup-auth.d.ts +3 -0
  120. package/dist/gmail-poller/setup-auth.d.ts.map +1 -0
  121. package/dist/gmail-poller/setup-auth.js +36 -0
  122. package/dist/gmail-poller/setup-auth.js.map +1 -0
  123. package/dist/gmail-poller/test.js +36 -0
  124. package/dist/index.d.ts +10 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +28 -0
  127. package/dist/index.js.map +1 -0
  128. package/dist/inference/augment_levels.d.ts +2 -0
  129. package/dist/inference/augment_levels.d.ts.map +1 -0
  130. package/dist/inference/augment_levels.js +1 -0
  131. package/dist/inference/augment_levels.js.map +1 -0
  132. package/dist/inference/capture-overlay.d.ts +13 -0
  133. package/dist/inference/capture-overlay.d.ts.map +1 -0
  134. package/dist/inference/capture-overlay.js +355 -0
  135. package/dist/inference/capture-overlay.js.map +1 -0
  136. package/dist/inference/capturescreenshot.d.ts +12 -0
  137. package/dist/inference/capturescreenshot.d.ts.map +1 -0
  138. package/dist/inference/capturescreenshot.js +157 -0
  139. package/dist/inference/capturescreenshot.js.map +1 -0
  140. package/dist/jsonHandler.d.ts +37 -0
  141. package/dist/jsonHandler.d.ts.map +1 -0
  142. package/dist/jsonHandler.js +191 -0
  143. package/dist/jsonHandler.js.map +1 -0
  144. package/dist/localStorage.json +11 -0
  145. package/dist/media_data_endpoints.d.ts +2 -0
  146. package/dist/media_data_endpoints.d.ts.map +1 -0
  147. package/dist/media_data_endpoints.js +102 -0
  148. package/dist/media_data_endpoints.js.map +1 -0
  149. package/dist/operations/blender-ops.d.ts +4 -0
  150. package/dist/operations/blender-ops.d.ts.map +1 -0
  151. package/dist/operations/blender-ops.js +55 -0
  152. package/dist/operations/blender-ops.js.map +1 -0
  153. package/dist/operations.d.ts +34 -0
  154. package/dist/operations.d.ts.map +1 -0
  155. package/dist/operations.js +1514 -0
  156. package/dist/operations.js.map +1 -0
  157. package/dist/pdfRoutes.d.ts +2 -0
  158. package/dist/pdfRoutes.d.ts.map +1 -0
  159. package/dist/pdfRoutes.js +56 -0
  160. package/dist/pdfRoutes.js.map +1 -0
  161. package/dist/peers.d.ts +9 -0
  162. package/dist/peers.d.ts.map +1 -0
  163. package/dist/peers.js +70 -0
  164. package/dist/peers.js.map +1 -0
  165. package/dist/playparser.d.ts +2 -0
  166. package/dist/playparser.d.ts.map +1 -0
  167. package/dist/playparser.js +281 -0
  168. package/dist/playparser.js.map +1 -0
  169. package/dist/process.d.ts +4 -0
  170. package/dist/process.d.ts.map +1 -0
  171. package/dist/process.js +375 -0
  172. package/dist/process.js.map +1 -0
  173. package/dist/promptRoutes.d.ts +7 -0
  174. package/dist/promptRoutes.d.ts.map +1 -0
  175. package/dist/promptRoutes.js +68 -0
  176. package/dist/promptRoutes.js.map +1 -0
  177. package/dist/queueManager.d.ts +23 -0
  178. package/dist/queueManager.d.ts.map +1 -0
  179. package/dist/queueManager.js +96 -0
  180. package/dist/queueManager.js.map +1 -0
  181. package/dist/run-flow.d.ts +8 -0
  182. package/dist/run-flow.d.ts.map +1 -0
  183. package/dist/run-flow.js +220 -0
  184. package/dist/run-flow.js.map +1 -0
  185. package/dist/scraper.d.ts +2 -0
  186. package/dist/scraper.d.ts.map +1 -0
  187. package/dist/scraper.js +75 -0
  188. package/dist/scraper.js.map +1 -0
  189. package/dist/scraper_endpoints.d.ts +2 -0
  190. package/dist/scraper_endpoints.d.ts.map +1 -0
  191. package/dist/scraper_endpoints.js +40 -0
  192. package/dist/scraper_endpoints.js.map +1 -0
  193. package/dist/server.d.ts +2 -0
  194. package/dist/server.d.ts.map +1 -0
  195. package/dist/server.js +528 -0
  196. package/dist/server.js.map +1 -0
  197. package/dist/services/ModelContext.d.ts +7 -0
  198. package/dist/services/ModelContext.d.ts.map +1 -0
  199. package/dist/services/ModelContext.js +7 -0
  200. package/dist/services/ModelContext.js.map +1 -0
  201. package/dist/services/agenticUiPlanner.d.ts +27 -0
  202. package/dist/services/agenticUiPlanner.d.ts.map +1 -0
  203. package/dist/services/agenticUiPlanner.js +161 -0
  204. package/dist/services/agenticUiPlanner.js.map +1 -0
  205. package/dist/services/apiKeyService.d.ts +3 -0
  206. package/dist/services/apiKeyService.d.ts.map +1 -0
  207. package/dist/services/apiKeyService.js +7 -0
  208. package/dist/services/apiKeyService.js.map +1 -0
  209. package/dist/services/audioService.d.ts +10 -0
  210. package/dist/services/audioService.d.ts.map +1 -0
  211. package/dist/services/audioService.js +140 -0
  212. package/dist/services/audioService.js.map +1 -0
  213. package/dist/services/autoPromptOptimizer.d.ts +44 -0
  214. package/dist/services/autoPromptOptimizer.d.ts.map +1 -0
  215. package/dist/services/autoPromptOptimizer.js +344 -0
  216. package/dist/services/autoPromptOptimizer.js.map +1 -0
  217. package/dist/services/autoPromptOptimizer.manual-test.d.ts +2 -0
  218. package/dist/services/autoPromptOptimizer.manual-test.d.ts.map +1 -0
  219. package/dist/services/autoPromptOptimizer.manual-test.js +27 -0
  220. package/dist/services/autoPromptOptimizer.manual-test.js.map +1 -0
  221. package/dist/services/chainExecutor.d.ts +26 -0
  222. package/dist/services/chainExecutor.d.ts.map +1 -0
  223. package/dist/services/chainExecutor.js +399 -0
  224. package/dist/services/chainExecutor.js.map +1 -0
  225. package/dist/services/classifyImageQuestion.d.ts +55 -0
  226. package/dist/services/classifyImageQuestion.d.ts.map +1 -0
  227. package/dist/services/classifyImageQuestion.js +428 -0
  228. package/dist/services/classifyImageQuestion.js.map +1 -0
  229. package/dist/services/configuration/executor.d.ts +3 -0
  230. package/dist/services/configuration/executor.d.ts.map +1 -0
  231. package/dist/services/configuration/executor.js +795 -0
  232. package/dist/services/configuration/executor.js.map +1 -0
  233. package/dist/services/error.d.ts +13 -0
  234. package/dist/services/error.d.ts.map +1 -0
  235. package/dist/services/error.js +34 -0
  236. package/dist/services/error.js.map +1 -0
  237. package/dist/services/executor.d.ts +11 -0
  238. package/dist/services/executor.d.ts.map +1 -0
  239. package/dist/services/executor.js +1587 -0
  240. package/dist/services/executor.js.map +1 -0
  241. package/dist/services/extractPdf.d.ts +26 -0
  242. package/dist/services/extractPdf.d.ts.map +1 -0
  243. package/dist/services/extractPdf.js +256 -0
  244. package/dist/services/extractPdf.js.map +1 -0
  245. package/dist/services/generateJsTransformFromPrompt.d.ts +11 -0
  246. package/dist/services/generateJsTransformFromPrompt.d.ts.map +1 -0
  247. package/dist/services/generateJsTransformFromPrompt.js +328 -0
  248. package/dist/services/generateJsTransformFromPrompt.js.map +1 -0
  249. package/dist/services/localizeFirebaseMedia.d.ts +20 -0
  250. package/dist/services/localizeFirebaseMedia.d.ts.map +1 -0
  251. package/dist/services/localizeFirebaseMedia.js +135 -0
  252. package/dist/services/localizeFirebaseMedia.js.map +1 -0
  253. package/dist/services/polyfill_canvas.d.ts +2 -0
  254. package/dist/services/polyfill_canvas.d.ts.map +1 -0
  255. package/dist/services/polyfill_canvas.js +19 -0
  256. package/dist/services/polyfill_canvas.js.map +1 -0
  257. package/dist/services/promptRoutes.d.ts +7 -0
  258. package/dist/services/promptRoutes.d.ts.map +1 -0
  259. package/dist/services/promptRoutes.js +70 -0
  260. package/dist/services/promptRoutes.js.map +1 -0
  261. package/dist/services/runPrompt.d.ts +29 -0
  262. package/dist/services/runPrompt.d.ts.map +1 -0
  263. package/dist/services/runPrompt.js +232 -0
  264. package/dist/services/runPrompt.js.map +1 -0
  265. package/dist/services/schemaInference.d.ts +2 -0
  266. package/dist/services/schemaInference.d.ts.map +1 -0
  267. package/dist/services/schemaInference.js +17 -0
  268. package/dist/services/schemaInference.js.map +1 -0
  269. package/dist/services/self-learning/api.d.ts +2 -0
  270. package/dist/services/self-learning/api.d.ts.map +1 -0
  271. package/dist/services/self-learning/api.js +84 -0
  272. package/dist/services/self-learning/api.js.map +1 -0
  273. package/dist/services/self-learning/autolearn.d.ts +23 -0
  274. package/dist/services/self-learning/autolearn.d.ts.map +1 -0
  275. package/dist/services/self-learning/autolearn.js +308 -0
  276. package/dist/services/self-learning/autolearn.js.map +1 -0
  277. package/dist/services/self-learning/discover.d.ts +11 -0
  278. package/dist/services/self-learning/discover.d.ts.map +1 -0
  279. package/dist/services/self-learning/discover.js +446 -0
  280. package/dist/services/self-learning/discover.js.map +1 -0
  281. package/dist/services/self-learning/image.d.ts +10 -0
  282. package/dist/services/self-learning/image.d.ts.map +1 -0
  283. package/dist/services/self-learning/image.js +38 -0
  284. package/dist/services/self-learning/image.js.map +1 -0
  285. package/dist/services/self-learning/injest.d.ts +25 -0
  286. package/dist/services/self-learning/injest.d.ts.map +1 -0
  287. package/dist/services/self-learning/injest.js +110 -0
  288. package/dist/services/self-learning/injest.js.map +1 -0
  289. package/dist/services/self-learning/learn.d.ts +2 -0
  290. package/dist/services/self-learning/learn.d.ts.map +1 -0
  291. package/dist/services/self-learning/learn.js +145 -0
  292. package/dist/services/self-learning/learn.js.map +1 -0
  293. package/dist/services/self-learning/matcher.d.ts +2 -0
  294. package/dist/services/self-learning/matcher.d.ts.map +1 -0
  295. package/dist/services/self-learning/matcher.js +38 -0
  296. package/dist/services/self-learning/matcher.js.map +1 -0
  297. package/dist/services/self-learning/openai.d.ts +8 -0
  298. package/dist/services/self-learning/openai.d.ts.map +1 -0
  299. package/dist/services/self-learning/openai.js +97 -0
  300. package/dist/services/self-learning/openai.js.map +1 -0
  301. package/dist/services/self-learning/phash.d.ts +5 -0
  302. package/dist/services/self-learning/phash.d.ts.map +1 -0
  303. package/dist/services/self-learning/phash.js +68 -0
  304. package/dist/services/self-learning/phash.js.map +1 -0
  305. package/dist/services/self-learning/recognize.d.ts +17 -0
  306. package/dist/services/self-learning/recognize.d.ts.map +1 -0
  307. package/dist/services/self-learning/recognize.js +116 -0
  308. package/dist/services/self-learning/recognize.js.map +1 -0
  309. package/dist/services/self-learning/record_transition.d.ts +8 -0
  310. package/dist/services/self-learning/record_transition.d.ts.map +1 -0
  311. package/dist/services/self-learning/record_transition.js +20 -0
  312. package/dist/services/self-learning/record_transition.js.map +1 -0
  313. package/dist/services/self-learning/registry.d.ts +4 -0
  314. package/dist/services/self-learning/registry.d.ts.map +1 -0
  315. package/dist/services/self-learning/registry.js +19 -0
  316. package/dist/services/self-learning/registry.js.map +1 -0
  317. package/dist/services/self-learning/schema.d.ts +114 -0
  318. package/dist/services/self-learning/schema.d.ts.map +1 -0
  319. package/dist/services/self-learning/schema.js +70 -0
  320. package/dist/services/self-learning/schema.js.map +1 -0
  321. package/dist/services/self-learning/schemaStrictify.d.ts +2 -0
  322. package/dist/services/self-learning/schemaStrictify.d.ts.map +1 -0
  323. package/dist/services/self-learning/schemaStrictify.js +34 -0
  324. package/dist/services/self-learning/schemaStrictify.js.map +1 -0
  325. package/dist/services/self-learning/transition_graph.d.ts +6 -0
  326. package/dist/services/self-learning/transition_graph.d.ts.map +1 -0
  327. package/dist/services/self-learning/transition_graph.js +83 -0
  328. package/dist/services/self-learning/transition_graph.js.map +1 -0
  329. package/dist/services/self-learning/transition_log.d.ts +3 -0
  330. package/dist/services/self-learning/transition_log.d.ts.map +1 -0
  331. package/dist/services/self-learning/transition_log.js +42 -0
  332. package/dist/services/self-learning/transition_log.js.map +1 -0
  333. package/dist/services/self-learning/util.d.ts +3 -0
  334. package/dist/services/self-learning/util.d.ts.map +1 -0
  335. package/dist/services/self-learning/util.js +11 -0
  336. package/dist/services/self-learning/util.js.map +1 -0
  337. package/dist/services/stepByStepAiPlanner.d.ts +39 -0
  338. package/dist/services/stepByStepAiPlanner.d.ts.map +1 -0
  339. package/dist/services/stepByStepAiPlanner.js +379 -0
  340. package/dist/services/stepByStepAiPlanner.js.map +1 -0
  341. package/dist/services/test-genjs.js +39 -0
  342. package/dist/services/test-genjs.manual-test.d.ts +2 -0
  343. package/dist/services/test-genjs.manual-test.d.ts.map +1 -0
  344. package/dist/services/test-genjs.manual-test.js +40 -0
  345. package/dist/services/test-genjs.manual-test.js.map +1 -0
  346. package/dist/services/uiMapPathFinder.d.ts +13 -0
  347. package/dist/services/uiMapPathFinder.d.ts.map +1 -0
  348. package/dist/services/uiMapPathFinder.js +79 -0
  349. package/dist/services/uiMapPathFinder.js.map +1 -0
  350. package/dist/services/uiMapService.d.ts +26 -0
  351. package/dist/services/uiMapService.d.ts.map +1 -0
  352. package/dist/services/uiMapService.js +275 -0
  353. package/dist/services/uiMapService.js.map +1 -0
  354. package/dist/services/uiPlanner.d.ts +54 -0
  355. package/dist/services/uiPlanner.d.ts.map +1 -0
  356. package/dist/services/uiPlanner.js +558 -0
  357. package/dist/services/uiPlanner.js.map +1 -0
  358. package/dist/services/utilityFunctions.d.ts +80 -0
  359. package/dist/services/utilityFunctions.d.ts.map +1 -0
  360. package/dist/services/utilityFunctions.js +352 -0
  361. package/dist/services/utilityFunctions.js.map +1 -0
  362. package/dist/services/variableGenerator.d.ts +39 -0
  363. package/dist/services/variableGenerator.d.ts.map +1 -0
  364. package/dist/services/variableGenerator.js +157 -0
  365. package/dist/services/variableGenerator.js.map +1 -0
  366. package/dist/services/workflow/build-workflow.d.ts +49 -0
  367. package/dist/services/workflow/build-workflow.d.ts.map +1 -0
  368. package/dist/services/workflow/build-workflow.js +119 -0
  369. package/dist/services/workflow/build-workflow.js.map +1 -0
  370. package/dist/standardRoutes.d.ts +2 -0
  371. package/dist/standardRoutes.d.ts.map +1 -0
  372. package/dist/standardRoutes.js +1495 -0
  373. package/dist/standardRoutes.js.map +1 -0
  374. package/dist/stepWorkflowRoutes.d.ts +2 -0
  375. package/dist/stepWorkflowRoutes.d.ts.map +1 -0
  376. package/dist/stepWorkflowRoutes.js +1007 -0
  377. package/dist/stepWorkflowRoutes.js.map +1 -0
  378. package/dist/storage.d.ts +19 -0
  379. package/dist/storage.d.ts.map +1 -0
  380. package/dist/storage.docker.json +61 -0
  381. package/dist/storage.js +131 -0
  382. package/dist/storage.js.map +1 -0
  383. package/dist/storage.json +78 -0
  384. package/dist/storage_cache/boxes.json +48 -0
  385. package/dist/storage_cache/suno_state.json +3 -0
  386. package/dist/suno_download.d.ts +11 -0
  387. package/dist/suno_download.d.ts.map +1 -0
  388. package/dist/suno_download.js +33 -0
  389. package/dist/suno_download.js.map +1 -0
  390. package/dist/suno_download.py +119 -0
  391. package/dist/test-web-element-requests.d.ts +6 -0
  392. package/dist/test-web-element-requests.d.ts.map +1 -0
  393. package/dist/test-web-element-requests.js +114 -0
  394. package/dist/test-web-element-requests.js.map +1 -0
  395. package/dist/test_pdf_render.d.ts +2 -0
  396. package/dist/test_pdf_render.d.ts.map +1 -0
  397. package/dist/test_pdf_render.js +50 -0
  398. package/dist/test_pdf_render.js.map +1 -0
  399. package/dist/training_data_viewer_endpoints.d.ts +2 -0
  400. package/dist/training_data_viewer_endpoints.d.ts.map +1 -0
  401. package/dist/training_data_viewer_endpoints.js +141 -0
  402. package/dist/training_data_viewer_endpoints.js.map +1 -0
  403. package/dist/utils.d.ts +353 -0
  404. package/dist/utils.d.ts.map +1 -0
  405. package/dist/utils.js +1517 -0
  406. package/dist/utils.js.map +1 -0
  407. package/dist/vm-h100.env.template +55 -0
  408. package/dist/web-element-requests.d.ts +102 -0
  409. package/dist/web-element-requests.d.ts.map +1 -0
  410. package/dist/web-element-requests.js +278 -0
  411. package/dist/web-element-requests.js.map +1 -0
  412. package/dist/workflowRoutes.d.ts +2 -0
  413. package/dist/workflowRoutes.d.ts.map +1 -0
  414. package/dist/workflowRoutes.js +441 -0
  415. package/dist/workflowRoutes.js.map +1 -0
  416. package/package.json +109 -0
@@ -0,0 +1,1007 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import multer from 'multer';
4
+ import { console_log_it } from './utils.js';
5
+ import { localizeFirebaseStorageUrls } from "./services/localizeFirebaseMedia.js";
6
+ // Configure multer for file uploads
7
+ const createMulterConfig = (uploadDir) => {
8
+ // Ensure upload directory exists
9
+ if (!fs.existsSync(uploadDir)) {
10
+ fs.mkdirSync(uploadDir, { recursive: true });
11
+ }
12
+ const storage = multer.diskStorage({
13
+ destination: (req, file, cb) => {
14
+ cb(null, uploadDir);
15
+ },
16
+ filename: (req, file, cb) => {
17
+ // Generate unique filename with timestamp
18
+ const timestamp = Date.now();
19
+ const ext = path.extname(file.originalname);
20
+ const name = path.basename(file.originalname, ext);
21
+ const uniqueName = `${name}-${timestamp}${ext}`;
22
+ cb(null, uniqueName);
23
+ }
24
+ });
25
+ const fileFilter = (req, file, cb) => {
26
+ // Accept video, image, and automation files
27
+ const allowedTypes = [
28
+ 'video/mp4', 'video/webm', 'video/ogg', 'video/mov', 'video/avi',
29
+ 'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
30
+ 'application/json', 'text/plain'
31
+ ];
32
+ const isAutomationFile = file.originalname.endsWith('.automation') || file.originalname.endsWith('.json');
33
+ if (allowedTypes.includes(file.mimetype) || isAutomationFile) {
34
+ cb(null, true);
35
+ }
36
+ else {
37
+ cb(new Error('Invalid file type. Only video, image, and automation files are allowed.'), false);
38
+ }
39
+ };
40
+ return multer({
41
+ storage,
42
+ fileFilter,
43
+ limits: {
44
+ fileSize: 500 * 1024 * 1024 // 500MB limit
45
+ }
46
+ });
47
+ };
48
+ const buildFolderStructure = (dirPath, basePath = dirPath) => {
49
+ const items = [];
50
+ try {
51
+ const entries = fs.readdirSync(dirPath);
52
+ for (const entry of entries) {
53
+ const fullPath = path.join(dirPath, entry);
54
+ const stat = fs.statSync(fullPath);
55
+ const relativePath = path.relative(basePath, fullPath);
56
+ if (stat.isDirectory()) {
57
+ // Recursively build folder structure
58
+ const children = buildFolderStructure(fullPath, basePath);
59
+ items.push({
60
+ id: `folder-${relativePath.replace(/[/\\]/g, '-')}`,
61
+ name: entry,
62
+ type: 'folder',
63
+ children: children,
64
+ icon: '📁',
65
+ path: relativePath,
66
+ lastModified: stat.mtime,
67
+ source: 'local'
68
+ });
69
+ }
70
+ else if (stat.isFile() && (entry.endsWith('.automation') || entry.endsWith('.json'))) {
71
+ // Add config files
72
+ const isWorkflow = entry.endsWith('.automation') || entry.endsWith('.json');
73
+ items.push({
74
+ id: `file-${relativePath.replace(/[/\\]/g, '-')}`,
75
+ name: entry,
76
+ type: 'file',
77
+ icon: isWorkflow ? '🔄' : '📄',
78
+ path: relativePath,
79
+ lastModified: stat.mtime,
80
+ size: stat.size,
81
+ isConfigFile: !isWorkflow,
82
+ isWorkflowFile: isWorkflow,
83
+ source: 'local'
84
+ });
85
+ }
86
+ }
87
+ }
88
+ catch (error) {
89
+ console.error(`Error reading directory ${dirPath}:`, error);
90
+ }
91
+ // Sort folders first, then files, both alphabetically
92
+ return items.sort((a, b) => {
93
+ if (a.type !== b.type) {
94
+ return a.type === 'folder' ? -1 : 1;
95
+ }
96
+ return a.name.localeCompare(b.name);
97
+ });
98
+ };
99
+ export function registerStepWorkflowRoutes(app, getWorkflowsDir, getMediaDir, getUIMapDir, getPromptLibDir) {
100
+ const workflowsDir = getWorkflowsDir();
101
+ const mediaDir = getMediaDir();
102
+ const uiMapDir = getUIMapDir();
103
+ const promptLibDir = getPromptLibDir ? getPromptLibDir() : null;
104
+ if (!workflowsDir || !mediaDir) {
105
+ console_log_it('Error: Workflows or Media directory is not defined');
106
+ return;
107
+ }
108
+ // Ensure directories exist
109
+ if (!fs.existsSync(workflowsDir)) {
110
+ fs.mkdirSync(workflowsDir, { recursive: true });
111
+ }
112
+ if (!fs.existsSync(mediaDir)) {
113
+ fs.mkdirSync(mediaDir, { recursive: true });
114
+ }
115
+ if (promptLibDir && !fs.existsSync(promptLibDir)) {
116
+ fs.mkdirSync(promptLibDir, { recursive: true });
117
+ }
118
+ const upload = createMulterConfig(mediaDir);
119
+ console_log_it('Registering Step Workflow routes...');
120
+ // ═══════════════════════════════════════════════════════════════════════
121
+ // WORKFLOW MANAGEMENT ENDPOINTS
122
+ // ═══════════════════════════════════════════════════════════════════════
123
+ // Get all workflows
124
+ app.get('/api/workflows', (req, res) => {
125
+ try {
126
+ const files = fs.readdirSync(workflowsDir, { recursive: true, withFileTypes: true })
127
+ .filter(file => file.isFile() && (file.name.endsWith('.automation') || file.name.endsWith('.json')))
128
+ .map(file => {
129
+ const filePath = path.join(file.parentPath, file.name);
130
+ const stats = fs.statSync(filePath);
131
+ const relativePath = path.relative(workflowsDir, filePath).replace(/\//g, '//');
132
+ let workflow = {};
133
+ try {
134
+ const content = fs.readFileSync(filePath, 'utf8');
135
+ workflow = JSON.parse(content);
136
+ }
137
+ catch (e) {
138
+ console_log_it(`Error parsing workflow ${file.name}:`, e.message);
139
+ }
140
+ return {
141
+ id: relativePath,
142
+ filename: file.name,
143
+ name: workflow.name || path.basename(file.name, path.extname(file.name)),
144
+ description: workflow.description || '',
145
+ stepCount: workflow.steps ? workflow.steps.length : 0,
146
+ mediaUrl: workflow.url || null,
147
+ createdAt: stats.birthtime,
148
+ modifiedAt: stats.mtime,
149
+ size: stats.size,
150
+ relativePath: relativePath
151
+ };
152
+ })
153
+ .sort((a, b) => b.modifiedAt - a.modifiedAt);
154
+ const folderStructure = buildFolderStructure(workflowsDir, workflowsDir);
155
+ res.json({ success: true, workflows: files, folderStructure });
156
+ }
157
+ catch (error) {
158
+ console_log_it('Error listing workflows:', error);
159
+ res.status(500).json({ success: false, error: error.message });
160
+ }
161
+ });
162
+ // Get specific workflow
163
+ app.get('/api/workflows/:id(*)', (req, res) => {
164
+ try {
165
+ const { id } = req.params;
166
+ let filename = id;
167
+ // Try to find the file with or without extension
168
+ const filePath = path.join(workflowsDir, filename);
169
+ const automationPath = path.join(workflowsDir, `${filename}.automation`);
170
+ const jsonPath = path.join(workflowsDir, `${filename}.json`);
171
+ let targetPath = null;
172
+ // Check exact match first (if id has extension)
173
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
174
+ targetPath = filePath;
175
+ }
176
+ // Check .automation
177
+ else if (fs.existsSync(automationPath)) {
178
+ targetPath = automationPath;
179
+ }
180
+ // Check .json
181
+ else if (fs.existsSync(jsonPath)) {
182
+ targetPath = jsonPath;
183
+ }
184
+ if (!targetPath) {
185
+ return res.status(404).json({ success: false, error: 'Workflow not found' });
186
+ }
187
+ const content = fs.readFileSync(targetPath, 'utf8');
188
+ const workflow = JSON.parse(content);
189
+ res.json({ success: true, workflow });
190
+ }
191
+ catch (error) {
192
+ console_log_it('Error reading workflow:', error);
193
+ res.status(500).json({ success: false, error: error.message });
194
+ }
195
+ });
196
+ // Create or update workflow
197
+ app.post('/api/workflows/:id(*)', async (req, res) => {
198
+ try {
199
+ const { id } = req.params;
200
+ const workflow = req.body;
201
+ // Validate workflow structure
202
+ if (!workflow.steps || !Array.isArray(workflow.steps)) {
203
+ return res.status(400).json({
204
+ success: false,
205
+ error: 'Invalid workflow: steps array is required'
206
+ });
207
+ }
208
+ let filename = id;
209
+ if (!filename.endsWith('.automation') && !filename.endsWith('.json')) {
210
+ filename += '.automation';
211
+ }
212
+ const filePath = path.join(workflowsDir, filename);
213
+ // Ensure directory exists
214
+ const dir = path.dirname(filePath);
215
+ if (!fs.existsSync(dir)) {
216
+ fs.mkdirSync(dir, { recursive: true });
217
+ }
218
+ // Add metadata
219
+ const workflowWithMeta = {
220
+ ...workflow,
221
+ id,
222
+ lastModified: new Date().toISOString(),
223
+ version: workflow.version || '1.0.0'
224
+ };
225
+ try {
226
+ // Get the relative file path of filename
227
+ let relativeFilePath = path.relative(workflowsDir, filePath).replace(/\\/g, '/');
228
+ const result = await localizeFirebaseStorageUrls({
229
+ inputJson: workflowWithMeta,
230
+ baseFolder: mediaDir,
231
+ targetFolder: relativeFilePath,
232
+ extension: 'jpg',
233
+ apiPrefix: '/api/media'
234
+ });
235
+ console.log('Localized Firebase Storage URLs:', result);
236
+ fs.writeFileSync(filePath, JSON.stringify(result.updated, null, 2));
237
+ }
238
+ catch (e) {
239
+ console.error('Error localizing Firebase Storage URLs:', e);
240
+ }
241
+ res.json({ success: true, message: 'Workflow saved successfully' });
242
+ }
243
+ catch (error) {
244
+ console_log_it('Error saving workflow:', error);
245
+ res.status(500).json({ success: false, error: error.message });
246
+ }
247
+ });
248
+ // Delete workflow
249
+ app.delete('/api/workflows/:id(*)', (req, res) => {
250
+ try {
251
+ const { id } = req.params;
252
+ let filename = id;
253
+ // Try to find the file with or without extension
254
+ const filePath = path.join(workflowsDir, filename);
255
+ const automationPath = path.join(workflowsDir, `${filename}.automation`);
256
+ const jsonPath = path.join(workflowsDir, `${filename}.json`);
257
+ let deleted = false;
258
+ // Check exact match first (if id has extension)
259
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
260
+ fs.unlinkSync(filePath);
261
+ deleted = true;
262
+ }
263
+ // Check .automation
264
+ else if (fs.existsSync(automationPath)) {
265
+ fs.unlinkSync(automationPath);
266
+ deleted = true;
267
+ }
268
+ // Check .json
269
+ else if (fs.existsSync(jsonPath)) {
270
+ fs.unlinkSync(jsonPath);
271
+ deleted = true;
272
+ }
273
+ if (!deleted) {
274
+ return res.status(404).json({ success: false, error: 'Workflow not found' });
275
+ }
276
+ res.json({ success: true, message: 'Workflow deleted successfully' });
277
+ }
278
+ catch (error) {
279
+ console_log_it('Error deleting workflow:', error);
280
+ res.status(500).json({ success: false, error: error.message });
281
+ }
282
+ });
283
+ // Duplicate workflow
284
+ app.post('/api/workflows/:id(*)/duplicate', (req, res) => {
285
+ try {
286
+ const { id } = req.params;
287
+ const { newName } = req.body;
288
+ let sourceFilename = id;
289
+ if (!sourceFilename.endsWith('.automation') && !sourceFilename.endsWith('.json')) {
290
+ sourceFilename += '.automation';
291
+ }
292
+ // Try to find source
293
+ let sourcePath = path.join(workflowsDir, sourceFilename);
294
+ if (!fs.existsSync(sourcePath)) {
295
+ // Try .json if .automation failed
296
+ if (sourceFilename.endsWith('.automation')) {
297
+ sourcePath = path.join(workflowsDir, sourceFilename.replace('.automation', '.json'));
298
+ }
299
+ }
300
+ if (!fs.existsSync(sourcePath)) {
301
+ // Try exact match if extension was already there
302
+ sourcePath = path.join(workflowsDir, id);
303
+ }
304
+ if (!fs.existsSync(sourcePath)) {
305
+ return res.status(404).json({ success: false, error: 'Source workflow not found' });
306
+ }
307
+ const content = fs.readFileSync(sourcePath, 'utf8');
308
+ const workflow = JSON.parse(content);
309
+ const newId = newName || `${id}-copy-${Date.now()}`;
310
+ let newFilename = newId;
311
+ if (!newFilename.endsWith('.automation') && !newFilename.endsWith('.json')) {
312
+ newFilename += '.automation';
313
+ }
314
+ const newPath = path.join(workflowsDir, newFilename);
315
+ // Ensure directory exists for new file
316
+ const dir = path.dirname(newPath);
317
+ if (!fs.existsSync(dir)) {
318
+ fs.mkdirSync(dir, { recursive: true });
319
+ }
320
+ const duplicatedWorkflow = {
321
+ ...workflow,
322
+ id: newId,
323
+ name: `${workflow.name || id} (Copy)`,
324
+ lastModified: new Date().toISOString()
325
+ };
326
+ fs.writeFileSync(newPath, JSON.stringify(duplicatedWorkflow, null, 2));
327
+ res.json({ success: true, id: newId, message: 'Workflow duplicated successfully' });
328
+ }
329
+ catch (error) {
330
+ console_log_it('Error duplicating workflow:', error);
331
+ res.status(500).json({ success: false, error: error.message });
332
+ }
333
+ });
334
+ // ═══════════════════════════════════════════════════════════════════════
335
+ // UI MAP ENDPOINTS
336
+ // ═══════════════════════════════════════════════════════════════════════
337
+ // Get all UI Maps
338
+ app.get('/api/ui-maps', (req, res) => {
339
+ try {
340
+ const files = fs.readdirSync(uiMapDir, { recursive: true, withFileTypes: true })
341
+ .filter(file => file.isFile() && file.name.endsWith('.ui_map'))
342
+ .map(file => {
343
+ const filePath = path.join(file.parentPath, file.name);
344
+ const stats = fs.statSync(filePath);
345
+ const relativePath = path.relative(uiMapDir, filePath).replace(/\\/g, '/');
346
+ let content = null;
347
+ try {
348
+ content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
349
+ }
350
+ catch (e) {
351
+ console_log_it(`Error parsing UI Map ${file.name}:`, e.message);
352
+ }
353
+ return {
354
+ id: relativePath,
355
+ filename: file.name,
356
+ name: content?.name || path.basename(file.name, '.ui_map'),
357
+ lastModified: stats.mtime,
358
+ size: stats.size,
359
+ relativePath: relativePath
360
+ };
361
+ })
362
+ .sort((a, b) => b.lastModified - a.lastModified);
363
+ res.json({ success: true, uiMaps: files });
364
+ }
365
+ catch (error) {
366
+ console_log_it('Error listing UI Maps:', error);
367
+ res.status(500).json({ success: false, error: error.message });
368
+ }
369
+ });
370
+ // Get specific UI Map
371
+ app.get('/api/ui-maps/:id(*)', (req, res) => {
372
+ try {
373
+ const { id } = req.params;
374
+ let filename = id;
375
+ if (!filename.endsWith('.ui_map')) {
376
+ filename += '.ui_map';
377
+ }
378
+ const filePath = path.join(uiMapDir, filename);
379
+ if (!fs.existsSync(filePath)) {
380
+ return res.status(404).json({ success: false, error: 'UI Map not found' });
381
+ }
382
+ const content = fs.readFileSync(filePath, 'utf8');
383
+ const uiMap = JSON.parse(content);
384
+ res.json({ success: true, uiMap });
385
+ }
386
+ catch (error) {
387
+ console_log_it('Error reading UI Map:', error);
388
+ res.status(500).json({ success: false, error: error.message });
389
+ }
390
+ });
391
+ // Save UI Map
392
+ app.post('/api/ui-maps/:id(*)', (req, res) => {
393
+ try {
394
+ const { id } = req.params;
395
+ const uiMapData = req.body;
396
+ let filename = id;
397
+ if (!filename.endsWith('.ui_map')) {
398
+ filename += '.ui_map';
399
+ }
400
+ const filePath = path.join(uiMapDir, filename);
401
+ // Ensure directory exists
402
+ const dir = path.dirname(filePath);
403
+ if (!fs.existsSync(dir)) {
404
+ fs.mkdirSync(dir, { recursive: true });
405
+ }
406
+ fs.writeFileSync(filePath, JSON.stringify(uiMapData, null, 2));
407
+ res.json({ success: true, message: 'UI Map saved successfully' });
408
+ }
409
+ catch (error) {
410
+ console_log_it('Error saving UI Map:', error);
411
+ res.status(500).json({ success: false, error: error.message });
412
+ }
413
+ });
414
+ // Delete UI Map
415
+ app.delete('/api/ui-maps/:id(*)', (req, res) => {
416
+ try {
417
+ const { id } = req.params;
418
+ let filename = id;
419
+ if (!filename.endsWith('.ui_map')) {
420
+ filename += '.ui_map';
421
+ }
422
+ const filePath = path.join(uiMapDir, filename);
423
+ if (!fs.existsSync(filePath)) {
424
+ return res.status(404).json({ success: false, error: 'UI Map not found' });
425
+ }
426
+ fs.unlinkSync(filePath);
427
+ res.json({ success: true, message: 'UI Map deleted successfully' });
428
+ }
429
+ catch (error) {
430
+ console_log_it('Error deleting UI Map:', error);
431
+ res.status(500).json({ success: false, error: error.message });
432
+ }
433
+ });
434
+ // ═══════════════════════════════════════════════════════════════════════
435
+ // PROMPT LIB ENDPOINTS
436
+ // ═══════════════════════════════════════════════════════════════════════
437
+ // Get all Prompt Libs
438
+ app.get('/api/prompt-libs', (req, res) => {
439
+ if (!promptLibDir)
440
+ return res.json({ success: true, promptLibs: [] });
441
+ try {
442
+ const files = fs.readdirSync(promptLibDir, { recursive: true, withFileTypes: true })
443
+ .filter(file => file.isFile() && file.name.endsWith('.prompt_lib'))
444
+ .map(file => {
445
+ const filePath = path.join(file.parentPath, file.name);
446
+ const stats = fs.statSync(filePath);
447
+ const relativePath = path.relative(promptLibDir, filePath).replace(/\\/g, '/');
448
+ let content = null;
449
+ try {
450
+ content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
451
+ }
452
+ catch (e) {
453
+ console_log_it(`Error parsing Prompt Lib ${file.name}:`, e.message);
454
+ }
455
+ return {
456
+ id: relativePath,
457
+ filename: file.name,
458
+ name: content?.name || path.basename(file.name, '.prompt_lib'),
459
+ lastModified: stats.mtime,
460
+ size: stats.size,
461
+ relativePath: relativePath
462
+ };
463
+ })
464
+ .sort((a, b) => b.lastModified - a.lastModified);
465
+ res.json({ success: true, promptLibs: files });
466
+ }
467
+ catch (error) {
468
+ console_log_it('Error listing Prompt Libs:', error);
469
+ res.status(500).json({ success: false, error: error.message });
470
+ }
471
+ });
472
+ // Get specific Prompt Lib
473
+ app.get('/api/prompt-libs/:id(*)', (req, res) => {
474
+ if (!promptLibDir)
475
+ return res.status(404).json({ success: false, error: 'Prompt Lib directory not configured' });
476
+ try {
477
+ const { id } = req.params;
478
+ let filename = id;
479
+ if (!filename.endsWith('.prompt_lib')) {
480
+ filename += '.prompt_lib';
481
+ }
482
+ const filePath = path.join(promptLibDir, filename);
483
+ if (!fs.existsSync(filePath)) {
484
+ return res.status(404).json({ success: false, error: 'Prompt Lib not found' });
485
+ }
486
+ const content = fs.readFileSync(filePath, 'utf8');
487
+ const promptLib = JSON.parse(content);
488
+ res.json({ success: true, promptLib });
489
+ }
490
+ catch (error) {
491
+ console_log_it('Error reading Prompt Lib:', error);
492
+ res.status(500).json({ success: false, error: error.message });
493
+ }
494
+ });
495
+ // Save Prompt Lib
496
+ app.post('/api/prompt-libs/:id(*)', (req, res) => {
497
+ if (!promptLibDir)
498
+ return res.status(500).json({ success: false, error: 'Prompt Lib directory not configured' });
499
+ try {
500
+ const { id } = req.params;
501
+ const promptLibData = req.body;
502
+ let filename = id;
503
+ if (!filename.endsWith('.prompt_lib')) {
504
+ filename += '.prompt_lib';
505
+ }
506
+ const filePath = path.join(promptLibDir, filename);
507
+ // Ensure directory exists
508
+ const dir = path.dirname(filePath);
509
+ if (!fs.existsSync(dir)) {
510
+ fs.mkdirSync(dir, { recursive: true });
511
+ }
512
+ fs.writeFileSync(filePath, JSON.stringify(promptLibData, null, 2));
513
+ res.json({ success: true, message: 'Prompt Lib saved successfully' });
514
+ }
515
+ catch (error) {
516
+ console_log_it('Error saving Prompt Lib:', error);
517
+ res.status(500).json({ success: false, error: error.message });
518
+ }
519
+ });
520
+ // Delete Prompt Lib
521
+ app.delete('/api/prompt-libs/:id(*)', (req, res) => {
522
+ if (!promptLibDir)
523
+ return res.status(500).json({ success: false, error: 'Prompt Lib directory not configured' });
524
+ try {
525
+ const { id } = req.params;
526
+ let filename = id;
527
+ if (!filename.endsWith('.prompt_lib')) {
528
+ filename += '.prompt_lib';
529
+ }
530
+ const filePath = path.join(promptLibDir, filename);
531
+ if (!fs.existsSync(filePath)) {
532
+ return res.status(404).json({ success: false, error: 'Prompt Lib not found' });
533
+ }
534
+ fs.unlinkSync(filePath);
535
+ res.json({ success: true, message: 'Prompt Lib deleted successfully' });
536
+ }
537
+ catch (error) {
538
+ console_log_it('Error deleting Prompt Lib:', error);
539
+ res.status(500).json({ success: false, error: error.message });
540
+ }
541
+ });
542
+ // ═══════════════════════════════════════════════════════════════════════
543
+ // MEDIA MANAGEMENT ENDPOINTS
544
+ // ═══════════════════════════════════════════════════════════════════════
545
+ // Upload media file
546
+ app.post('/api/media/upload', (req, res) => {
547
+ console_log_it('=== MEDIA UPLOAD REQUEST START ===');
548
+ console_log_it('Content-Type:', req.headers['content-type']);
549
+ console_log_it('Content-Length:', req.headers['content-length']);
550
+ console_log_it('Media directory:', mediaDir);
551
+ console_log_it('Media directory exists:', fs.existsSync(mediaDir));
552
+ const uploadMiddleware = upload.single('media');
553
+ uploadMiddleware(req, res, (err) => {
554
+ if (err) {
555
+ console_log_it('=== MULTER ERROR ===');
556
+ console_log_it('Error type:', err.constructor.name);
557
+ console_log_it('Error message:', err.message);
558
+ console_log_it('Error code:', err.code);
559
+ if (err instanceof multer.MulterError) {
560
+ if (err.code === 'LIMIT_FILE_SIZE') {
561
+ return res.status(400).json({
562
+ success: false,
563
+ error: 'File too large. Maximum size is 500MB.'
564
+ });
565
+ }
566
+ else if (err.code === 'LIMIT_UNEXPECTED_FILE') {
567
+ return res.status(400).json({
568
+ success: false,
569
+ error: 'Unexpected field name. Use "media" as the field name.'
570
+ });
571
+ }
572
+ }
573
+ return res.status(500).json({
574
+ success: false,
575
+ error: err.message,
576
+ code: err.code || 'UNKNOWN_ERROR'
577
+ });
578
+ }
579
+ try {
580
+ console_log_it('=== MULTER SUCCESS ===');
581
+ console_log_it('req.file:', req.file);
582
+ if (!req.file) {
583
+ console_log_it('No file in request');
584
+ return res.status(400).json({ success: false, error: 'No file uploaded' });
585
+ }
586
+ const ext = path.extname(req.file.filename).toLowerCase();
587
+ const isVideo = ['.mp4', '.webm', '.ogg', '.mov', '.avi'].includes(ext);
588
+ const fileInfo = {
589
+ id: `${isVideo ? 'vid' : 'img'}_${req.file.filename}`, // Add ID field
590
+ filename: req.file.filename,
591
+ originalName: req.file.originalname, // Keep this for MediaLibraryContext
592
+ mimetype: req.file.mimetype,
593
+ size: req.file.size,
594
+ url: `/api/media/${req.file.filename}`,
595
+ uploadedAt: new Date().toISOString(),
596
+ thumbnail: null // Add thumbnail field
597
+ };
598
+ console_log_it('=== UPLOAD SUCCESS ===');
599
+ console_log_it('File info:', fileInfo);
600
+ res.json({ success: true, file: fileInfo });
601
+ }
602
+ catch (processError) {
603
+ console_log_it('=== PROCESSING ERROR ===');
604
+ console_log_it('Processing error:', processError);
605
+ res.status(500).json({
606
+ success: false,
607
+ error: processError.message,
608
+ type: 'PROCESSING_ERROR'
609
+ });
610
+ }
611
+ });
612
+ });
613
+ // Get media file
614
+ app.get('/api/media/:filename(*)', (req, res) => {
615
+ try {
616
+ const { filename } = req.params;
617
+ const filePath = path.join(mediaDir, filename);
618
+ if (!fs.existsSync(filePath)) {
619
+ return res.status(404).json({ success: false, error: 'Media file not found' });
620
+ }
621
+ // Set appropriate headers
622
+ const ext = path.extname(filename).toLowerCase();
623
+ const mimeTypes = {
624
+ '.mp4': 'video/mp4',
625
+ '.webm': 'video/webm',
626
+ '.ogg': 'video/ogg',
627
+ '.mov': 'video/quicktime',
628
+ '.avi': 'video/x-msvideo',
629
+ '.jpg': 'image/jpeg',
630
+ '.jpeg': 'image/jpeg',
631
+ '.png': 'image/png',
632
+ '.gif': 'image/gif',
633
+ '.webp': 'image/webp',
634
+ '.svg': 'image/svg+xml'
635
+ };
636
+ const mimeType = mimeTypes[ext] || 'application/octet-stream';
637
+ res.setHeader('Content-Type', mimeType);
638
+ // Enable range requests for video
639
+ if (mimeType.startsWith('video/')) {
640
+ const stat = fs.statSync(filePath);
641
+ const fileSize = stat.size;
642
+ const range = req.headers.range;
643
+ if (range) {
644
+ const parts = range.replace(/bytes=/, "").split("-");
645
+ const start = parseInt(parts[0], 10);
646
+ const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
647
+ const chunksize = (end - start) + 1;
648
+ res.status(206);
649
+ res.setHeader('Content-Range', `bytes ${start}-${end}/${fileSize}`);
650
+ res.setHeader('Accept-Ranges', 'bytes');
651
+ res.setHeader('Content-Length', chunksize);
652
+ const stream = fs.createReadStream(filePath, { start, end });
653
+ stream.pipe(res);
654
+ }
655
+ else {
656
+ res.setHeader('Content-Length', fileSize);
657
+ fs.createReadStream(filePath).pipe(res);
658
+ }
659
+ }
660
+ else {
661
+ res.sendFile(filePath);
662
+ }
663
+ }
664
+ catch (error) {
665
+ console_log_it('Error serving media:', error);
666
+ res.status(500).json({ success: false, error: error.message });
667
+ }
668
+ });
669
+ // List media files - UPDATE this endpoint to return the expected format
670
+ app.get('/api/media', (req, res) => {
671
+ try {
672
+ const files = fs.readdirSync(mediaDir)
673
+ .filter(file => {
674
+ const ext = path.extname(file).toLowerCase();
675
+ return ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg'].includes(ext);
676
+ })
677
+ .map(file => {
678
+ const filePath = path.join(mediaDir, file);
679
+ const stats = fs.statSync(filePath);
680
+ const ext = path.extname(file).toLowerCase();
681
+ const isVideo = ['.mp4', '.webm', '.ogg', '.mov', '.avi'].includes(ext);
682
+ return {
683
+ id: `${isVideo ? 'vid' : 'img'}_${file}`, // Add ID field that MediaLibraryContext expects
684
+ filename: file,
685
+ url: `/api/media/${file}`,
686
+ type: isVideo ? 'video' : 'image',
687
+ size: stats.size,
688
+ uploadedAt: stats.birthtime.toISOString(), // Convert to ISO string
689
+ thumbnail: null // Add thumbnail field
690
+ };
691
+ })
692
+ .sort((a, b) => new Date(b.uploadedAt) - new Date(a.uploadedAt));
693
+ // Return in the format expected by MediaLibraryContext
694
+ res.json({
695
+ success: true,
696
+ media: files, // Changed from 'files' to 'media'
697
+ count: files.length
698
+ });
699
+ }
700
+ catch (error) {
701
+ console_log_it('Error listing media:', error);
702
+ res.status(500).json({ success: false, error: error.message });
703
+ }
704
+ });
705
+ // Delete media file
706
+ app.delete('/api/media/:filename(*)', (req, res) => {
707
+ try {
708
+ const { filename } = req.params;
709
+ const filePath = path.join(mediaDir, filename);
710
+ if (!fs.existsSync(filePath)) {
711
+ return res.status(404).json({ success: false, error: 'Media file not found' });
712
+ }
713
+ fs.unlinkSync(filePath);
714
+ res.json({ success: true, message: 'Media file deleted successfully' });
715
+ }
716
+ catch (error) {
717
+ console_log_it('Error deleting media:', error);
718
+ res.status(500).json({ success: false, error: error.message });
719
+ }
720
+ });
721
+ // Add a new endpoint to delete media by ID (MediaLibraryContext expects this)
722
+ app.delete('/api/media/:id(*)', (req, res) => {
723
+ try {
724
+ const { id } = req.params;
725
+ // Extract filename from ID (remove img_ or vid_ prefix)
726
+ const filename = id.replace(/^(img_|vid_)/, '');
727
+ const filePath = path.join(mediaDir, filename);
728
+ if (!fs.existsSync(filePath)) {
729
+ return res.status(404).json({ success: false, error: 'Media file not found' });
730
+ }
731
+ fs.unlinkSync(filePath);
732
+ res.json({ success: true, message: 'Media file deleted successfully' });
733
+ }
734
+ catch (error) {
735
+ console_log_it('Error deleting media:', error);
736
+ res.status(500).json({ success: false, error: error.message });
737
+ }
738
+ });
739
+ // Add endpoint to get media info by ID
740
+ app.get('/api/media/info/:id(*)', (req, res) => {
741
+ try {
742
+ const { id } = req.params;
743
+ // Extract filename from ID
744
+ const filename = id.replace(/^(img_|vid_)/, '');
745
+ const filePath = path.join(mediaDir, filename);
746
+ if (!fs.existsSync(filePath)) {
747
+ return res.status(404).json({ success: false, error: 'Media file not found' });
748
+ }
749
+ const stats = fs.statSync(filePath);
750
+ const ext = path.extname(filename).toLowerCase();
751
+ const isVideo = ['.mp4', '.webm', '.ogg', '.mov', '.avi'].includes(ext);
752
+ const mediaInfo = {
753
+ id,
754
+ filename,
755
+ url: `/api/media/${filename}`,
756
+ type: isVideo ? 'video' : 'image',
757
+ size: stats.size,
758
+ uploadedAt: stats.birthtime.toISOString(),
759
+ thumbnail: null
760
+ };
761
+ res.json({ success: true, media: mediaInfo });
762
+ }
763
+ catch (error) {
764
+ console_log_it('Error getting media info:', error);
765
+ res.status(500).json({ success: false, error: error.message });
766
+ }
767
+ });
768
+ // Keep the existing /api/media/:filename endpoint for serving files (don't change this)
769
+ // This serves the actual file content and is different from the info endpoint above
770
+ // ═══════════════════════════════════════════════════════════════════════
771
+ // WORKFLOW EXECUTION ENDPOINTS
772
+ // ═══════════════════════════════════════════════════════════════════════
773
+ // Execute workflow
774
+ app.post('/api/workflows/:id(*)/execute', async (req, res) => {
775
+ try {
776
+ const { id } = req.params;
777
+ const { startStep = 0, endStep, dryRun = false } = req.body;
778
+ let filename = id;
779
+ if (!filename.endsWith('.automation') && !filename.endsWith('.json')) {
780
+ filename += '.automation';
781
+ }
782
+ let filePath = path.join(workflowsDir, filename);
783
+ if (!fs.existsSync(filePath)) {
784
+ // Try .json
785
+ if (filename.endsWith('.automation')) {
786
+ filePath = path.join(workflowsDir, filename.replace('.automation', '.json'));
787
+ }
788
+ }
789
+ if (!fs.existsSync(filePath)) {
790
+ // Try exact match
791
+ filePath = path.join(workflowsDir, id);
792
+ }
793
+ if (!fs.existsSync(filePath)) {
794
+ return res.status(404).json({ success: false, error: 'Workflow not found' });
795
+ }
796
+ const content = fs.readFileSync(filePath, 'utf8');
797
+ const workflow = JSON.parse(content);
798
+ if (!workflow.steps || !Array.isArray(workflow.steps)) {
799
+ return res.status(400).json({ success: false, error: 'Invalid workflow format' });
800
+ }
801
+ const steps = workflow.steps.slice(startStep, endStep);
802
+ const results = [];
803
+ console_log_it(`Executing workflow ${id} - Steps ${startStep} to ${endStep || workflow.steps.length - 1} (Dry run: ${dryRun})`);
804
+ for (let i = 0; i < steps.length; i++) {
805
+ const step = steps[i];
806
+ const stepIndex = startStep + i;
807
+ console_log_it(`Executing step ${stepIndex + 1}: ${step.type}`);
808
+ const stepResult = {
809
+ stepIndex,
810
+ type: step.type,
811
+ description: step.description,
812
+ startTime: Date.now(),
813
+ success: false,
814
+ error: null,
815
+ data: null
816
+ };
817
+ try {
818
+ if (!dryRun) {
819
+ // Execute the actual step here
820
+ // This would integrate with your existing automation system
821
+ stepResult.data = await executeWorkflowStep(step);
822
+ }
823
+ else {
824
+ stepResult.data = { message: 'Dry run - step not executed' };
825
+ }
826
+ stepResult.success = true;
827
+ }
828
+ catch (error) {
829
+ stepResult.error = error.message;
830
+ console_log_it(`Step ${stepIndex + 1} failed:`, error.message);
831
+ if (!req.body.continueOnError) {
832
+ results.push({ ...stepResult, endTime: Date.now() });
833
+ break;
834
+ }
835
+ }
836
+ stepResult.endTime = Date.now();
837
+ results.push(stepResult);
838
+ // Add delay between steps if specified
839
+ if (step.delay && !dryRun) {
840
+ await new Promise(resolve => setTimeout(resolve, step.delay));
841
+ }
842
+ }
843
+ res.json({
844
+ success: true,
845
+ message: 'Workflow execution completed',
846
+ results,
847
+ totalSteps: steps.length,
848
+ successfulSteps: results.filter(r => r.success).length
849
+ });
850
+ }
851
+ catch (error) {
852
+ console_log_it('Error executing workflow:', error);
853
+ res.status(500).json({ success: false, error: error.message });
854
+ }
855
+ });
856
+ // Validate workflow
857
+ app.post('/api/workflows/:id(*)/validate', (req, res) => {
858
+ try {
859
+ const { id } = req.params;
860
+ let filename = id;
861
+ if (!filename.endsWith('.automation') && !filename.endsWith('.json')) {
862
+ filename += '.automation';
863
+ }
864
+ let filePath = path.join(workflowsDir, filename);
865
+ if (!fs.existsSync(filePath)) {
866
+ // Try .json
867
+ if (filename.endsWith('.automation')) {
868
+ filePath = path.join(workflowsDir, filename.replace('.automation', '.json'));
869
+ }
870
+ }
871
+ if (!fs.existsSync(filePath)) {
872
+ // Try exact match
873
+ filePath = path.join(workflowsDir, id);
874
+ }
875
+ if (!fs.existsSync(filePath)) {
876
+ return res.status(404).json({ success: false, error: 'Workflow not found' });
877
+ }
878
+ const content = fs.readFileSync(filePath, 'utf8');
879
+ const workflow = JSON.parse(content);
880
+ const validation = validateWorkflow(workflow);
881
+ res.json({ success: true, validation });
882
+ }
883
+ catch (error) {
884
+ console_log_it('Error validating workflow:', error);
885
+ res.status(500).json({ success: false, error: error.message });
886
+ }
887
+ });
888
+ // Import workflow from file
889
+ app.post('/api/workflows/import', upload.single('workflow'), (req, res) => {
890
+ try {
891
+ if (!req.file) {
892
+ return res.status(400).json({ success: false, error: 'No workflow file uploaded' });
893
+ }
894
+ const content = fs.readFileSync(req.file.path, 'utf8');
895
+ const workflow = JSON.parse(content);
896
+ // Generate unique ID if not provided
897
+ const id = workflow.id || `imported-${Date.now()}`;
898
+ const targetPath = path.join(workflowsDir, `${id}.automation`);
899
+ // Add import metadata
900
+ const importedWorkflow = {
901
+ ...workflow,
902
+ id,
903
+ imported: true,
904
+ importedAt: new Date().toISOString(),
905
+ originalFilename: req.file.originalname
906
+ };
907
+ fs.writeFileSync(targetPath, JSON.stringify(importedWorkflow, null, 2));
908
+ // Clean up uploaded file
909
+ fs.unlinkSync(req.file.path);
910
+ res.json({
911
+ success: true,
912
+ message: 'Workflow imported successfully',
913
+ id,
914
+ stepCount: workflow.steps ? workflow.steps.length : 0
915
+ });
916
+ }
917
+ catch (error) {
918
+ console_log_it('Error importing workflow:', error);
919
+ res.status(500).json({ success: false, error: error.message });
920
+ }
921
+ });
922
+ console_log_it('Step Workflow routes registered successfully');
923
+ }
924
+ // Helper function to execute individual workflow steps
925
+ async function executeWorkflowStep(step) {
926
+ // This function would integrate with your existing automation system
927
+ // For now, it's a placeholder that simulates step execution
928
+ switch (step.type) {
929
+ case 'pause':
930
+ const duration = step.params?.duration || 1000;
931
+ await new Promise(resolve => setTimeout(resolve, duration));
932
+ return { message: `Paused for ${duration}ms` };
933
+ case 'capture':
934
+ // Integrate with your screenshot functionality
935
+ return { message: 'Screenshot captured', imagePath: '/tmp/screenshot.png' };
936
+ case 'ocr':
937
+ // Integrate with your OCR functionality
938
+ return { message: 'OCR analysis completed', boxes: [] };
939
+ case 'move-mouse':
940
+ // Integrate with robotjs mouse movement
941
+ return { message: 'Mouse moved', position: { x: 0, y: 0 } };
942
+ case 'click':
943
+ // Integrate with robotjs click
944
+ return { message: 'Mouse clicked' };
945
+ case 'type':
946
+ // Integrate with robotjs typing
947
+ const text = step.params?.keys || '';
948
+ return { message: `Typed: ${text}` };
949
+ case 'automation':
950
+ // Execute another automation workflow
951
+ const automationId = step.params?.automationId;
952
+ if (!automationId) {
953
+ throw new Error('Automation step requires automationId parameter');
954
+ }
955
+ // This would need to be implemented to actually execute the referenced automation
956
+ return { message: `Automation "${automationId}" executed` };
957
+ default:
958
+ throw new Error(`Unknown step type: ${step.type}`);
959
+ }
960
+ }
961
+ // Helper function to validate workflow structure
962
+ function validateWorkflow(workflow) {
963
+ const errors = [];
964
+ const warnings = [];
965
+ if (!workflow.steps || !Array.isArray(workflow.steps)) {
966
+ errors.push('Workflow must have a steps array');
967
+ return { valid: false, errors, warnings };
968
+ }
969
+ if (workflow.steps.length === 0) {
970
+ warnings.push('Workflow has no steps');
971
+ }
972
+ workflow.steps.forEach((step, index) => {
973
+ if (!step.type) {
974
+ errors.push(`Step ${index + 1}: Missing step type`);
975
+ }
976
+ // Validate step-specific requirements
977
+ switch (step.type) {
978
+ case 'ocr':
979
+ if (!step.params?.region) {
980
+ warnings.push(`Step ${index + 1}: OCR step without region parameter`);
981
+ }
982
+ break;
983
+ case 'move-mouse':
984
+ if (!step.params?.filter && !step.params?.relative && !step.params?.absolute) {
985
+ errors.push(`Step ${index + 1}: Move mouse step needs filter, relative, or absolute parameters`);
986
+ }
987
+ break;
988
+ case 'type':
989
+ if (!step.params?.keys) {
990
+ errors.push(`Step ${index + 1}: Type step missing keys parameter`);
991
+ }
992
+ break;
993
+ case 'automation':
994
+ if (!step.params?.automationId) {
995
+ errors.push(`Step ${index + 1}: Automation step missing automationId parameter`);
996
+ }
997
+ break;
998
+ }
999
+ });
1000
+ return {
1001
+ valid: errors.length === 0,
1002
+ errors,
1003
+ warnings,
1004
+ stepCount: workflow.steps.length
1005
+ };
1006
+ }
1007
+ //# sourceMappingURL=stepWorkflowRoutes.js.map