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,1495 @@
1
+ import { exec, spawn } from 'child_process';
2
+ import { getItem, setItem } from "./storage.js";
3
+ import express from 'express';
4
+ import { MIDJOURNEY_SELECTOR, getDownloadsFolder, moveSocialPorterVideos, findSocialPorterVideos, unzip, readProjectFile, getContext, saveProjectFile, findFilesWithString, findExplorerWindowPosition, getDetectOrientation, readJsonFiles, get, getMode, get_jobs_path, set, findJobs, findVideoJobs, getJobsContext, selectRandom, sanitizeFileName, downloadFile, extractFileNameFromUrl, getVideoDuration, findFileInDirectoryHasInWithAndEndingWith, alignLinesToWords, getLastModifiedTimestampSync, unique, processSunoState, getMediaFileDuration, getFilesToProcess, pause, getVideoDimensions, } from "./utils.js";
5
+ import path from 'path';
6
+ import queue from './queueManager.js';
7
+ import fs from 'fs';
8
+ import serveStatic from 'serve-static';
9
+ import { downloadSunosWithPython } from "./suno_download.js";
10
+ import { processFile, fix, toggleEndCuts } from "./process.js";
11
+ import { operateSunoFilmMouse, operateSunoMouse, operateYoutubeMouse, clearMidjourneyImages, operateMidjourneyToImages, operateMidjourneyDownloadMedia, operateMidjourneyDownloadPublicMedia, operateMouse } from "./operations.js";
12
+ import { getPeerConstants } from "./peers.js";
13
+ import { captureFullScreenshot } from "./inference/capturescreenshot.js";
14
+ import { runImagePromptGrok } from "./services/runPrompt.js";
15
+ import { KEYS } from './constants.js';
16
+ import { processAudio } from './services/audioService.js';
17
+ import { generateTextFromTemplate } from './services/variableGenerator.js';
18
+ import { buildWorkflowDirectory, runWorkflowCLI, installDependencies } from './services/workflow/build-workflow.js';
19
+ import { scanExtensions } from './extensionUtils.js';
20
+ import { recognizeScreen } from './services/self-learning/recognize.js';
21
+ import { generateUIMap } from './services/uiMapService.js';
22
+ const utils = { getJobsContext, unique };
23
+ const jobs_context = getJobsContext();
24
+ const input_bar = '[id="desktop_input_bar"]';
25
+ // Define PROCEDURES if not imported from constants
26
+ const PROCEDURES = {
27
+ MUSIC_VIDEOS: 'MUSIC_VIDEOS'
28
+ };
29
+ export function registerRoutes(app) {
30
+ app.post('/generate-audio', async (req, res) => {
31
+ const { text, voice, filePath, keepExisting } = req.body;
32
+ try {
33
+ if (!text || !voice || !filePath) {
34
+ res.status(400).json({ success: false, error: "Missing required parameters" });
35
+ return;
36
+ }
37
+ let { audioPath, srtPath } = await processAudio(filePath, text, voice, keepExisting);
38
+ res.json({ success: true, audioPath, srtPath });
39
+ }
40
+ catch (error) {
41
+ console.error('Error generating audio:', error);
42
+ res.status(500).json({ success: false, error: error.message });
43
+ }
44
+ });
45
+ app.post('/readDir', async (req, res) => {
46
+ try {
47
+ const { dirPath, depth = 1, fullpaths = false } = req.body;
48
+ if (!dirPath) {
49
+ res.status(400).json({ success: false, error: "dirPath is required" });
50
+ return;
51
+ }
52
+ const getFiles = async (dir, level) => {
53
+ const dirents = await fs.promises.readdir(dir, { withFileTypes: true });
54
+ const files = await Promise.all(dirents.map(async (dirent) => {
55
+ const res = path.resolve(dir, dirent.name);
56
+ const itemPath = fullpaths ? res : (depth > 1 ? path.relative(dirPath, res) : dirent.name);
57
+ if (dirent.isDirectory() && level < depth) {
58
+ const children = await getFiles(res, level + 1);
59
+ return [itemPath, ...children];
60
+ }
61
+ return itemPath;
62
+ }));
63
+ return files.flat();
64
+ };
65
+ const files = await getFiles(dirPath, 1);
66
+ res.json({ success: true, files });
67
+ }
68
+ catch (error) {
69
+ console.error('Error reading directory:', error);
70
+ res.status(500).json({ success: false, error: error.message });
71
+ }
72
+ });
73
+ app.post('/readFiles', async (req, res) => {
74
+ try {
75
+ const { filePaths } = req.body;
76
+ if (!filePaths || !Array.isArray(filePaths)) {
77
+ res.status(400).json({ success: false, error: "filePaths array is required" });
78
+ return;
79
+ }
80
+ const results = {};
81
+ await Promise.all(filePaths.map(async (filePath) => {
82
+ try {
83
+ const content = await fs.promises.readFile(filePath, 'utf-8');
84
+ results[filePath] = content;
85
+ }
86
+ catch (error) {
87
+ results[filePath] = { error: error.message };
88
+ }
89
+ }));
90
+ res.json({ success: true, results });
91
+ }
92
+ catch (error) {
93
+ console.error('Error reading files:', error);
94
+ res.status(500).json({ success: false, error: error.message });
95
+ }
96
+ });
97
+ app.post('/get-video-dimensions', async (req, res) => {
98
+ try {
99
+ const { filePath, filePaths } = req.body;
100
+ if (filePaths && Array.isArray(filePaths)) {
101
+ const results = {};
102
+ await Promise.all(filePaths.map(async (fp) => {
103
+ try {
104
+ const dims = await getVideoDimensions(fp);
105
+ results[fp] = dims;
106
+ }
107
+ catch (err) {
108
+ results[fp] = { error: err.message };
109
+ }
110
+ }));
111
+ res.json(results);
112
+ return;
113
+ }
114
+ if (!filePath) {
115
+ res.status(400).json({ success: false, error: "filePath or filePaths is required" });
116
+ return;
117
+ }
118
+ const dimensions = await getVideoDimensions(filePath);
119
+ res.json({ success: true, ...dimensions });
120
+ }
121
+ catch (error) {
122
+ console.error('Error getting video dimensions:', error);
123
+ res.status(500).json({ success: false, error: error.message });
124
+ }
125
+ });
126
+ app.post('/generate-text-from-template', async (req, res) => {
127
+ try {
128
+ const { template, entities, options = {} } = req.body || {};
129
+ if (typeof template !== 'string' || !template.trim()) {
130
+ res.status(400).json({ success: false, error: 'template is required' });
131
+ return;
132
+ }
133
+ if (!Array.isArray(entities) || entities.length === 0) {
134
+ res.status(400).json({ success: false, error: 'entities must be a non-empty array' });
135
+ return;
136
+ }
137
+ const result = await generateTextFromTemplate(template, entities, options);
138
+ res.json({ success: true, ...result });
139
+ }
140
+ catch (error) {
141
+ console.error('Error generating text from template:', error);
142
+ res.status(500).json({ success: false, error: error.message });
143
+ }
144
+ });
145
+ app.get('/getSelectors', (req, res) => {
146
+ // Customize the selectors as needed.
147
+ console.log(getMode(), 'mode');
148
+ switch (getMode()) {
149
+ case MODES.SUNO:
150
+ case MODES.SUNO_FILM:
151
+ res.json({
152
+ selectors: Object.values(SUNO_SELECTORS)
153
+ });
154
+ break;
155
+ case MODES.YOUTUBE:
156
+ res.json({
157
+ selectors: Object.values(YOUTUBE_SELECTORS)
158
+ });
159
+ break;
160
+ case MODES.CLEAR_MIDJOURNEY_IMAGES:
161
+ res.json({
162
+ selectors: Object.values(MIDJOURNEY_SELECTOR)
163
+ });
164
+ break;
165
+ case MODES.MIDJOURNEY:
166
+ default:
167
+ res.json({
168
+ selectors: Object.values(MIDJOURNEY_SELECTOR)
169
+ });
170
+ break;
171
+ }
172
+ });
173
+ app.get('/send-element-selectors', (req, res) => {
174
+ // Implement the logic to find element selectors
175
+ if (req.body.selectors) {
176
+ let currentSelectors = get(KEYS.element_selectors) || [];
177
+ currentSelectors = unique([...currentSelectors, req.body], (e) => e.tabId);
178
+ set(KEYS.element_selectors, currentSelectors);
179
+ res.json({
180
+ success: true
181
+ });
182
+ }
183
+ else {
184
+ res.status(400).json({ error: 'Selectors are required' });
185
+ }
186
+ });
187
+ app.get('/get-list-selectors', (req, res) => {
188
+ // Customize the selectors as needed.
189
+ switch (getMode()) {
190
+ case MODES.SUNO:
191
+ case MODES.SUNO_FILM:
192
+ let suno_current_name = getItem('suno_current_name');
193
+ if (suno_current_name) {
194
+ res.json({
195
+ selectors: getContext().list_selectors || []
196
+ });
197
+ return;
198
+ }
199
+ break;
200
+ default:
201
+ break;
202
+ }
203
+ res.json({ selectors: [] });
204
+ });
205
+ app.post('/attach-suno-songs', async (req, res) => {
206
+ let current_song = get(KEYS.current_song_name);
207
+ let source_file_path = path.join(get(KEYS.current_folder), getItem('sourceFile'));
208
+ if (fs.existsSync(source_file_path)) {
209
+ if (current_song) {
210
+ let sourceJson = readProjectFile(source_file_path);
211
+ let projectData = sourceJson.find(v => v.name === current_song || v.original_name === current_song);
212
+ if (projectData) {
213
+ projectData.lyrics = get(KEYS.song_lyrics);
214
+ projectData.song_sources = get(KEYS.song_list);
215
+ saveProjectFile(source_file_path, sourceJson);
216
+ }
217
+ }
218
+ }
219
+ res.json({ ok: true });
220
+ });
221
+ app.post('/downloadSunosWithPython', async (req, res) => {
222
+ await downloadSunosWithPython(get(KEYS.sunoDownloadFolder));
223
+ res.json({ ok: true });
224
+ });
225
+ app.post('/fetch-100-name', async (req, res) => {
226
+ const { description } = req.body;
227
+ let ressulo = await generateListOfName(description);
228
+ try {
229
+ return res.json({
230
+ res: JSON.stringify(extractJSONFromFence(ressulo))
231
+ });
232
+ }
233
+ catch (e) {
234
+ return res.json({
235
+ res: '[]'
236
+ });
237
+ }
238
+ });
239
+ // build an initial middleware
240
+ let staticMiddleware;
241
+ setImageFolder();
242
+ // mount a wrapper
243
+ app.use('/images', (req, res, next) => {
244
+ staticMiddleware(req, res, next);
245
+ });
246
+ let staticWebMiddleware = serveStatic(path.join('midjourney', 'html'));
247
+ app.use('/web', (req, res, next) => {
248
+ staticWebMiddleware(req, res, next);
249
+ });
250
+ // whenever you need to switch folders at runtime:
251
+ function setImageFolder() {
252
+ if (get(KEYS.images_folder))
253
+ staticMiddleware = serveStatic(get(KEYS.images_folder));
254
+ }
255
+ app.get('/project', (req, res) => {
256
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
257
+ console.log(project_file);
258
+ let ces = readProjectFile(project_file);
259
+ console.log('getting: jobs');
260
+ res.json(ces);
261
+ });
262
+ Object.values(KEYS).map((param) => {
263
+ app.post('/set-' + param, (req, res) => {
264
+ console.log(`[[set]] ${param}`, 'set-param');
265
+ console.log(` ${req.body[param]}`);
266
+ set(param, req.body[param]);
267
+ if (KEYS.images_folder === param) {
268
+ setImageFolder();
269
+ }
270
+ else if (KEYS.procedure === param) {
271
+ }
272
+ else if (KEYS.sourceFile) {
273
+ getContext().sourceFile = req.body[param];
274
+ let filePath = path.join(get(KEYS.current_folder) || '', get(KEYS.sourceFile) || '');
275
+ if (fs.existsSync(filePath) && (KEYS.sourceFile === param || KEYS.current_folder === param)) {
276
+ let data = readProjectFile(filePath);
277
+ set(KEYS.project_names, data.filter(x => x).map(v => v.name));
278
+ const mySet = new Set(data
279
+ .filter(x => x)
280
+ .map(x => (x.characters || []).filter(c => c)).flat());
281
+ set(KEYS.project_characters, Array.from(mySet));
282
+ }
283
+ }
284
+ if (KEYS.suno_state === param) {
285
+ let suno_state = get(KEYS.suno_state);
286
+ try {
287
+ let project_song_states = [];
288
+ let all_project_songs_ready = true;
289
+ let song_states = [];
290
+ let output_path = path.join(get(KEYS.current_folder), getItem('sourceFile'));
291
+ let projects = readProjectFile(output_path);
292
+ if (false)
293
+ projects.forEach((project, index) => {
294
+ ({
295
+ suno_state, project_song_states, all_project_songs_ready, song_states
296
+ } = processSunoState(suno_state, project_song_states, project, all_project_songs_ready, song_states));
297
+ });
298
+ saveProjectFile(output_path, projects);
299
+ }
300
+ catch (e) {
301
+ console.log(`Error processing suno_state: ${e.message}`, 'suno_state error');
302
+ }
303
+ }
304
+ return res.json({
305
+ [param]: req.body[param]
306
+ });
307
+ });
308
+ app.get('/get-' + param, (req, res) => {
309
+ res.json({ [param]: get(param) });
310
+ });
311
+ app.get('/get-options-' + param, (req, res) => {
312
+ switch (param) {
313
+ case 'firstVideoForUpload':
314
+ let filePath = path.join(get(KEYS.current_folder) || '', get(KEYS.sourceFile) || '');
315
+ if (fs.existsSync(filePath)) {
316
+ let data = readProjectFile(filePath);
317
+ res.json(data.map(v => v.name));
318
+ return;
319
+ }
320
+ default:
321
+ res.json(get(KEYS.project_characters));
322
+ return;
323
+ }
324
+ res.json([]);
325
+ });
326
+ });
327
+ app.post('/setObject', (req, res) => {
328
+ set(req.body.key, req.body.value);
329
+ return res.json({
330
+ [req.body.key]: get(req.body.key)
331
+ });
332
+ });
333
+ app.post('/getObject', (req, res) => {
334
+ return res.json({
335
+ [req.body.key]: get(req.body.key)
336
+ });
337
+ });
338
+ app.post('/set-file-name', (req, res) => {
339
+ const { name } = req.body;
340
+ getContext().sourceFile = name;
341
+ setItem('sourceFile', name);
342
+ console.log(`getContext().sourceFile: ${getContext().sourceFile}`);
343
+ res.json({ ok: true });
344
+ });
345
+ app.post('/process-file', async (req, res) => {
346
+ const { name } = req.body;
347
+ let root_folder = get(KEYS.current_folder);
348
+ let filesToProcess = [name];
349
+ filesToProcess = getFilesToProcess(name, filesToProcess, root_folder);
350
+ filesToProcess.map((fileToProcess) => {
351
+ let temp = path.join(root_folder, fileToProcess);
352
+ console.log(`process file : ${temp}`);
353
+ if (fs.existsSync(temp) && temp.endsWith('.json')) {
354
+ processFile(temp, get_jobs_path(), name);
355
+ console.log(`processed`);
356
+ }
357
+ });
358
+ res.json({ ok: true });
359
+ });
360
+ app.post('/toggle-end-cuts', async (req, res) => {
361
+ const { name } = req.body;
362
+ let root_folder = get(KEYS.current_folder);
363
+ let fileToProcess = path.join(get(KEYS.current_folder), name);
364
+ let filesToProcess = [fileToProcess];
365
+ filesToProcess = getFilesToProcess(name, filesToProcess, root_folder);
366
+ console.log(`toggle-end-cuts : ${fileToProcess}`);
367
+ if (name)
368
+ filesToProcess.map((fileToProcess) => {
369
+ if (fs.existsSync(fileToProcess)) {
370
+ toggleEndCuts(path.join(fileToProcess));
371
+ console.log(`toggle-end-cuts complete`);
372
+ }
373
+ });
374
+ res.json({ ok: true });
375
+ });
376
+ app.get('/get-file-name', (req, res) => {
377
+ res.json({ name: getContext().sourceFile });
378
+ });
379
+ app.post('/select_song_sources', (req, res) => {
380
+ const { projectIndex, selectedSongSources } = req.body;
381
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
382
+ let ces = readProjectFile(project_file);
383
+ ces[projectIndex].selected_song_sources = selectedSongSources;
384
+ saveProjectFile(project_file, ces);
385
+ res.json(ces);
386
+ });
387
+ app.post('/align-text', (req, res) => {
388
+ const {} = req.body;
389
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
390
+ let ces = readProjectFile(project_file);
391
+ for (let projectIndex = 0; projectIndex < ces.length; projectIndex++) {
392
+ ces[projectIndex].processed_lyrics = (ces[projectIndex].lyrics || []).map((lyric, index) => {
393
+ const { alignedWords } = lyric;
394
+ return alignLinesToWords(alignedWords);
395
+ });
396
+ }
397
+ saveProjectFile(project_file, ces);
398
+ });
399
+ app.post('/select_image', (req, res) => {
400
+ const { projectIndex, lyricPromptIndex, imageName } = req.body;
401
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
402
+ let ces = readProjectFile(project_file);
403
+ ces[projectIndex].selected_prompts = ces[projectIndex]?.selected_prompts || [];
404
+ // ces[projectIndex].lyrics.find(lyric => {
405
+ // lyric.selected_prompts = lyric.selected_prompts || [];
406
+ // return lyric.selected_prompts.includes(imageName);
407
+ // })
408
+ if (lyricPromptIndex !== undefined && lyricPromptIndex !== null) {
409
+ if (!ces[projectIndex].lyrics[lyricPromptIndex].selected_prompts) {
410
+ ces[projectIndex].lyrics[lyricPromptIndex].selected_prompts = [];
411
+ }
412
+ if (ces[projectIndex].lyrics[lyricPromptIndex].selected_prompts.includes(imageName)) {
413
+ ces[projectIndex].lyrics[lyricPromptIndex].selected_prompts = ces[projectIndex].lyrics[lyricPromptIndex].selected_prompts.filter(x => x !== imageName);
414
+ }
415
+ else {
416
+ ces[projectIndex].lyrics[lyricPromptIndex].selected_prompts.push(imageName);
417
+ }
418
+ if (!ces[projectIndex].lyrics[lyricPromptIndex].prompts_selection) {
419
+ ces[projectIndex].lyrics[lyricPromptIndex].prompts_selection = {};
420
+ }
421
+ ces[projectIndex].lyrics[lyricPromptIndex].prompts_selection[imageName] = imageName;
422
+ }
423
+ else {
424
+ if (ces[projectIndex].selected_prompts.includes(imageName)) {
425
+ ces[projectIndex].selected_prompts = ces[projectIndex].selected_prompts.filter(x => x !== imageName);
426
+ }
427
+ else {
428
+ ces[projectIndex].selected_prompts.push(imageName);
429
+ }
430
+ }
431
+ saveProjectFile(project_file, ces);
432
+ res.json(ces);
433
+ });
434
+ app.post('/clear_selected', async (req, res) => {
435
+ const {} = req.body;
436
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
437
+ let ces = readProjectFile(project_file);
438
+ ces.map(item => {
439
+ item.selected_prompts = [];
440
+ item.prompts_selection = {};
441
+ item.selected_song_sources = [];
442
+ if (item?.lyrics) {
443
+ item?.lyrics.forEach(lyric => {
444
+ if (lyric.prompts) {
445
+ lyric.selected_prompts = [];
446
+ lyric.prompts_selection = {};
447
+ }
448
+ });
449
+ }
450
+ });
451
+ saveProjectFile(project_file, ces);
452
+ res.json(ces);
453
+ });
454
+ app.post('/select_random_image', async (req, res) => {
455
+ console.log(`[running]`, 'select_random_image');
456
+ const { count = 1 } = req.body;
457
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
458
+ let ces = readProjectFile(project_file);
459
+ console.log(`${project_file}, count: ${count}`, 'project_file');
460
+ jobs_context.jobs = fs.readFileSync(get_jobs_path(), 'utf-8').split('\n').map(v => JSON.parse(v));
461
+ for (let j = 0; j < ces.length; j++) {
462
+ let item = ces[j];
463
+ if (item?.song_sources) {
464
+ for (let i = 0; i < item.song_sources.length; i++) {
465
+ let filename = extractFileNameFromUrl(item.song_sources[i]);
466
+ let audioFilePath = path.join(get(KEYS.audio_folder), sanitizeFileName(item.name), filename);
467
+ if (!fs.existsSync(audioFilePath))
468
+ await downloadFile(item.song_sources[i], audioFilePath, (output, progress) => {
469
+ console.log(`${output}: ${progress}%`);
470
+ });
471
+ }
472
+ }
473
+ }
474
+ ces.map(item => {
475
+ item.selected_prompts = item.selected_prompts || [];
476
+ item.prompts_selection = item.prompts_selection || {};
477
+ item.selected_song_sources = item.selected_song_sources || [];
478
+ item.selected_song_sources = item.selected_song_sources.filter(t => t);
479
+ if (!item.selected_song_sources.length) {
480
+ item.selected_song_sources.push(...selectRandom(item.song_sources || [], 10));
481
+ }
482
+ if (item.prompts)
483
+ item.prompts.map((prompt, promptIndex) => {
484
+ let imageFiles = getImageFilesByPrompt(prompt, get(KEYS.ratio));
485
+ if (imageFiles?.length) {
486
+ if (!imageFiles.find(x => item.selected_prompts.includes(x))) {
487
+ let rando = selectRandom(imageFiles, count);
488
+ if (rando) {
489
+ item.prompts_selection[prompt] = [...rando];
490
+ item.selected_prompts.push(...rando);
491
+ }
492
+ }
493
+ }
494
+ });
495
+ if (item.lyrics) {
496
+ item.lyrics.forEach(item => selectRandomLyricImages(item, count));
497
+ }
498
+ let imageFiles = getImageFilesByPrompt(item.portrait_prompt, get(KEYS.ratio));
499
+ if (imageFiles?.length) {
500
+ if (!imageFiles.find(x => item.selected_prompts.includes(x))) {
501
+ let rando = selectRandom(imageFiles, count);
502
+ if (rando) {
503
+ item.selected_prompts.push(...rando);
504
+ item.prompts_selection[item.portrait_prompt] = [...rando];
505
+ }
506
+ }
507
+ }
508
+ });
509
+ saveProjectFile(project_file, ces);
510
+ console.log(`[done]`, 'select_random_image');
511
+ res.json(ces);
512
+ });
513
+ function selectRandomLyricImages(item, count) {
514
+ if (item.prompts) {
515
+ item.selected_prompts = item.selected_prompts || [];
516
+ item.prompts_selection = item.prompts_selection || {};
517
+ item.prompts.map(prompt => {
518
+ let imageFiles = getImageFilesByPrompt(prompt, get(KEYS.ratio));
519
+ if (imageFiles?.length) {
520
+ if (!imageFiles.find(x => item.selected_prompts.includes(x))) {
521
+ let rando = selectRandom(imageFiles, count);
522
+ if (rando) {
523
+ item.selected_prompts.push(...rando);
524
+ item.prompts_selection[prompt] = [...rando];
525
+ }
526
+ }
527
+ }
528
+ });
529
+ }
530
+ }
531
+ app.post('/image_to_video', (req, res) => {
532
+ const { projectIndex, imageName } = req.body;
533
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
534
+ let ces = readProjectFile(project_file);
535
+ ces[projectIndex].converting_prompts = ces[projectIndex]?.converting_prompts || [];
536
+ if (ces[projectIndex].converting_prompts.includes(imageName)) {
537
+ ces[projectIndex].converting_prompts = ces[projectIndex].converting_prompts.filter(x => x !== imageName);
538
+ }
539
+ else {
540
+ ces[projectIndex].converting_prompts.push(imageName);
541
+ }
542
+ saveProjectFile(project_file, ces);
543
+ res.json(ces);
544
+ });
545
+ app.post('/getAudioDurations', async (req, res) => {
546
+ const { audioFiles, videos } = req.body;
547
+ let results = {};
548
+ for (let i = 0; i < audioFiles.length; i++) {
549
+ let audioFilePath = audioFiles[i];
550
+ if (fs.existsSync(audioFilePath)) {
551
+ results[audioFilePath] = await getMediaFileDuration(audioFilePath);
552
+ }
553
+ }
554
+ for (let i = 0; i < videos.length; i++) {
555
+ let videoFilePath = videos[i];
556
+ if (fs.existsSync(videoFilePath)) {
557
+ results[videoFilePath] = await getMediaFileDuration(videoFilePath);
558
+ }
559
+ }
560
+ res.json(results);
561
+ });
562
+ app.post('/downloadAudio', async (req, res) => {
563
+ console.log(`[running]`, 'downloadAudio');
564
+ const {} = req.body;
565
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
566
+ let ces = readProjectFile(project_file);
567
+ console.log(`${project_file}`, 'project_file');
568
+ jobs_context.jobs = fs.readFileSync(get_jobs_path(), 'utf-8').split('\n').map(v => JSON.parse(v));
569
+ for (let j = 0; j < ces.length; j++) {
570
+ let item = ces[j];
571
+ item.song_sources_information = item.song_sources_information || [];
572
+ if (item?.song_sources) {
573
+ for (let i = 0; i < item.song_sources.length; i++) {
574
+ let filename = extractFileNameFromUrl(item.song_sources[i]);
575
+ let audioFilePath = path.join(get(KEYS.audio_folder), sanitizeFileName(item.name), filename);
576
+ if (!fs.existsSync(audioFilePath)) {
577
+ await downloadFile(item.song_sources[i], audioFilePath, (output, progress) => {
578
+ });
579
+ }
580
+ if (fs.existsSync(audioFilePath)) {
581
+ let stats = fs.statSync(audioFilePath);
582
+ let lastModified = getLastModifiedTimestampSync(audioFilePath);
583
+ item.song_sources_information[i] = {
584
+ url: item.song_sources[i],
585
+ file: filename,
586
+ size: stats.size,
587
+ lastModified,
588
+ duration: await getMediaFileDuration(audioFilePath)
589
+ };
590
+ }
591
+ }
592
+ }
593
+ }
594
+ saveProjectFile(project_file, ces);
595
+ console.log(`[done]`, 'downloadAudio');
596
+ res.json({ ok: true });
597
+ });
598
+ app.post('/processVideoJobs', async (req, res) => {
599
+ let project_file = path.join(get(KEYS.current_folder), get(KEYS.sourceFile));
600
+ let ces = readProjectFile(project_file);
601
+ console.log(`[running]`, 'processVideoJobs');
602
+ jobs_context.jobs = fs.readFileSync(get_jobs_path(), 'utf-8').split('\n').map(v => JSON.parse(v));
603
+ for (let j = 0; j < ces.length; j++) {
604
+ let item = ces[j];
605
+ if (item?.lyrics) {
606
+ for (let i = 0; i < item.lyrics.length; i++) {
607
+ let lyric = item.lyrics[i];
608
+ if (lyric.prompts_selection) {
609
+ lyric.prompts_videos = lyric.prompts_videos || {};
610
+ let promptKeys = Object.keys(lyric.prompts_selection);
611
+ for (let k = 0; k < promptKeys.length; k++) {
612
+ let prompt = promptKeys[k];
613
+ let jobs = findVideoJobs(prompt);
614
+ lyric.prompts_videos[prompt] = {};
615
+ if (jobs) {
616
+ console.log(`jobs: ${jobs?.length}`, 'jobs');
617
+ for (let jobIndex = 0; jobIndex < jobs.length; jobIndex++) {
618
+ let job = jobs[jobIndex];
619
+ for (let i = 0; i < job.batch_size; i++) {
620
+ let file = findFileInDirectoryHasInWithAndEndingWith(get(KEYS.images_folder), `${job.id}_${i}`, '.mp4');
621
+ if (file) {
622
+ lyric.prompts_videos[prompt][job.id] = lyric.prompts_videos[prompt][job.id] || [];
623
+ let duration = await getVideoDuration(path.join(get(KEYS.images_folder), file)).then(duration => {
624
+ return duration;
625
+ });
626
+ lyric.prompts_videos[prompt][job.id].push({ file, ...duration });
627
+ }
628
+ }
629
+ }
630
+ }
631
+ }
632
+ }
633
+ }
634
+ }
635
+ let { prompts } = item;
636
+ if (prompts) {
637
+ for (let i = 0; i < prompts.length; i++) {
638
+ let prompt = prompts[i];
639
+ let jobs = findVideoJobs(prompt);
640
+ item.prompts_videos = item.prompts_videos || {};
641
+ item.prompts_videos[prompt] = {};
642
+ if (jobs) {
643
+ console.log(`jobs: ${jobs?.length}`, 'jobs');
644
+ for (let jobIndex = 0; jobIndex < jobs.length; jobIndex++) {
645
+ let job = jobs[jobIndex];
646
+ for (let i = 0; i < job.batch_size; i++) {
647
+ let file = findFileInDirectoryHasInWithAndEndingWith(get(KEYS.images_folder), `${job.id}_${i}`, '.mp4');
648
+ if (file) {
649
+ item.prompts_videos[prompt][job.id] = item.prompts_videos[prompt][job.id] || [];
650
+ let duration = await getVideoDuration(path.join(get(KEYS.images_folder), file)).then(duration => {
651
+ return duration;
652
+ });
653
+ item.prompts_videos[prompt][job.id].push({ file, ...duration });
654
+ item.prompts_selection = item.prompts_selection || {};
655
+ item.prompts_selection[prompt] = item.prompts_selection[prompt] || [];
656
+ }
657
+ }
658
+ }
659
+ }
660
+ }
661
+ }
662
+ }
663
+ saveProjectFile(project_file, ces);
664
+ console.log(`[done]`, 'processVideoJobs');
665
+ res.json({ ok: true });
666
+ });
667
+ app.post('/take-screenshot', async (req, res) => {
668
+ await pause(() => { }, 1000); // wait for a second to ensure the screen is ready
669
+ const { appName } = req.body;
670
+ console.log(`[running]`, 'take-screenshot');
671
+ let filename = await captureFullScreenshot(path.join(get(KEYS.screen_shot_folder), `${appName}`));
672
+ res.json({
673
+ filename,
674
+ filePath: path.join(get(KEYS.screen_shot_folder), `${appName}`, filename)
675
+ });
676
+ console.log(`Screenshot saved as: ${filename}`, 'take-screenshot');
677
+ // console.log(`[done]`, 'take-screenshot');
678
+ });
679
+ app.post('/recognize-screen-signature', async (req, res) => {
680
+ const { filePath } = req.body;
681
+ console.log(`[running] recognize-screen-signature`, 'recognize-screen-signature');
682
+ try {
683
+ const result = await recognizeScreen(filePath);
684
+ console.log(`[done] recognize-screen-signature`, 'recognize-screen-signature');
685
+ res.json({ result });
686
+ }
687
+ catch (error) {
688
+ console.log(`Error in recognize-screen-signature: ${error.message}`, 'recognize-screen-signature-error');
689
+ res.status(500).json({ error: `Failed to recognize screen signature: ${error.message}` });
690
+ }
691
+ });
692
+ app.post('/analyze-image-grok', async (req, res) => {
693
+ try {
694
+ const { prompt, base64_image } = req.body;
695
+ // Validate inputs
696
+ if (!prompt || typeof prompt !== 'string' || prompt.trim().length === 0) {
697
+ return res.status(400).json({ error: 'Valid prompt is required' });
698
+ }
699
+ if (!base64_image || typeof base64_image !== 'string' || !base64_image.startsWith('data:image/')) {
700
+ return res.status(400).json({ error: 'Valid base64 image data URL is required' });
701
+ }
702
+ console.log(`[running] analyze-image-grok with prompt: ${prompt.substring(0, 50)}...`, 'analyze-image-grok');
703
+ const result = await runImagePromptGrok(prompt, base64_image);
704
+ console.log(`[done] analyze-image-grok`, 'analyze-image-grok');
705
+ res.json({ result });
706
+ }
707
+ catch (error) {
708
+ console.log(`Error in analyze-image-grok: ${error.message}`, 'analyze-image-grok-error');
709
+ res.status(500).json({ error: `Failed to analyze image: ${error.message}` });
710
+ }
711
+ });
712
+ app.post('/delete-files', async (req, res) => {
713
+ try {
714
+ const { filePaths } = req.body;
715
+ // Validate inputs
716
+ if (!Array.isArray(filePaths)) {
717
+ return res.status(400).json({ error: 'filePaths must be an array' });
718
+ }
719
+ if (filePaths.length === 0) {
720
+ return res.status(400).json({ error: 'filePaths array cannot be empty' });
721
+ }
722
+ console.log(`[running] delete-files for ${filePaths.length} files`, 'delete-files');
723
+ const results = [];
724
+ let deletedCount = 0;
725
+ let errorCount = 0;
726
+ for (const filePath of filePaths) {
727
+ try {
728
+ if (typeof filePath !== 'string' || !filePath.trim()) {
729
+ results.push({ filePath, success: false, error: 'Invalid file path' });
730
+ errorCount++;
731
+ continue;
732
+ }
733
+ // Check if file exists before attempting to delete
734
+ if (fs.existsSync(filePath)) {
735
+ fs.unlinkSync(filePath);
736
+ results.push({ filePath, success: true });
737
+ deletedCount++;
738
+ console.log(`Deleted: ${filePath}`, 'delete-files');
739
+ }
740
+ else {
741
+ results.push({ filePath, success: false, error: 'File not found' });
742
+ errorCount++;
743
+ console.log(`File not found: ${filePath}`, 'delete-files');
744
+ }
745
+ }
746
+ catch (error) {
747
+ results.push({ filePath, success: false, error: error.message });
748
+ errorCount++;
749
+ console.log(`Error deleting ${filePath}: ${error.message}`, 'delete-files-error');
750
+ }
751
+ }
752
+ console.log(`[done] delete-files - deleted: ${deletedCount}, errors: ${errorCount}`, 'delete-files');
753
+ res.json({
754
+ success: true,
755
+ total: filePaths.length,
756
+ deleted: deletedCount,
757
+ errors: errorCount,
758
+ results
759
+ });
760
+ }
761
+ catch (error) {
762
+ console.log(`Error in delete-files: ${error.message}`, 'delete-files-error');
763
+ res.status(500).json({ error: `Failed to delete files: ${error.message}` });
764
+ }
765
+ });
766
+ app.post('/clear-directory', async (req, res) => {
767
+ try {
768
+ const { directory } = req.body;
769
+ const directoryPath = directory;
770
+ // Validate inputs
771
+ if (!directoryPath || typeof directoryPath !== 'string') {
772
+ return res.status(400).json({ error: 'directoryPath must be a non-empty string' });
773
+ }
774
+ console.log(`[running] clear-directory for ${directoryPath}`, 'clear-directory');
775
+ // Check if directory exists
776
+ if (!fs.existsSync(directoryPath)) {
777
+ return res.status(404).json({ error: 'Directory not found' });
778
+ }
779
+ // Check if it's actually a directory
780
+ const stats = fs.statSync(directoryPath);
781
+ if (!stats.isDirectory()) {
782
+ return res.status(400).json({ error: 'Path is not a directory' });
783
+ }
784
+ // Read directory contents
785
+ const items = fs.readdirSync(directoryPath);
786
+ const results = [];
787
+ let deletedCount = 0;
788
+ let errorCount = 0;
789
+ for (const item of items) {
790
+ const itemPath = path.join(directoryPath, item);
791
+ try {
792
+ // Only delete files, not subdirectories
793
+ const itemStats = fs.statSync(itemPath);
794
+ if (itemStats.isFile()) {
795
+ fs.unlinkSync(itemPath);
796
+ results.push({ filePath: itemPath, success: true });
797
+ deletedCount++;
798
+ console.log(`Deleted: ${itemPath}`, 'clear-directory');
799
+ }
800
+ else {
801
+ results.push({ filePath: itemPath, success: false, error: 'Is a directory (skipped)' });
802
+ console.log(`Skipped directory: ${itemPath}`, 'clear-directory');
803
+ }
804
+ }
805
+ catch (error) {
806
+ results.push({ filePath: itemPath, success: false, error: error.message });
807
+ errorCount++;
808
+ console.log(`Error deleting ${itemPath}: ${error.message}`, 'clear-directory-error');
809
+ }
810
+ }
811
+ console.log(`[done] clear-directory - deleted: ${deletedCount}, errors: ${errorCount}, total items: ${items.length}`, 'clear-directory');
812
+ res.json({
813
+ success: true,
814
+ directoryPath,
815
+ totalItems: items.length,
816
+ deleted: deletedCount,
817
+ errors: errorCount,
818
+ results
819
+ });
820
+ }
821
+ catch (error) {
822
+ console.log(`Error in clear-directory: ${error.message}`, 'clear-directory-error');
823
+ res.status(500).json({ error: `Failed to clear directory: ${error.message}` });
824
+ }
825
+ });
826
+ app.post('/getImages', (req, res) => {
827
+ const { prompt, lyricPrompt } = req.body;
828
+ let jobs = prompt.trim() ? findJobs(prompt) : [];
829
+ console.log(`jobs: ${jobs.length}/${jobs_context?.jobs?.length}`, 'jobs');
830
+ let imageFiles = jobs.map((job) => {
831
+ return findFilesWithString(get(KEYS.images_folder), job.id);
832
+ }).flat();
833
+ let ljobs = lyricPrompt?.trim() ? findJobs(lyricPrompt) : [];
834
+ console.log(`jobs: ${ljobs.length}/${jobs_context?.jobs?.length}`, 'jobs');
835
+ let limageFiles = ljobs.map((job) => {
836
+ return findFilesWithString(get(KEYS.images_folder), job.id);
837
+ }).flat();
838
+ res.json({ prompts: imageFiles, lyricPrompts: limageFiles });
839
+ });
840
+ app.get('/get-current-source', (req, res) => {
841
+ res.json({ name: getItem('sourceFile') });
842
+ });
843
+ function getImageFilesByPrompt(prompt, ratio) {
844
+ let jobs = jobs_context.jobs.filter(job => getDetectOrientation(job) === ratio).filter(f => `${f.full_command}`.includes(prompt));
845
+ let imageFiles = jobs.map((job) => {
846
+ if (ratio) {
847
+ let orientation = getDetectOrientation(job);
848
+ if (orientation === ratio) {
849
+ jobs_context.jobDetails = jobs_context.jobDetails || {};
850
+ if (job?.files?.[ratio]) {
851
+ return job?.files?.[ratio];
852
+ }
853
+ let temp = findFilesWithString(get(KEYS.images_folder), job.id);
854
+ job.files = job.files || {};
855
+ job.files[ratio] = temp;
856
+ temp.map(t => {
857
+ if (!jobs_context?.jobDetails?.[t]) {
858
+ jobs_context.jobDetails[t] = jobs_context.jobDetails[t] || {};
859
+ job.orientation = getDetectOrientation(job);
860
+ jobs_context.jobDetails[t].job = job;
861
+ }
862
+ });
863
+ return temp;
864
+ }
865
+ }
866
+ return [];
867
+ }).flat();
868
+ console.log(`imageFiles: ${imageFiles.length}`, 'imageFiles');
869
+ return imageFiles;
870
+ }
871
+ app.post('/uploadVideos', async (req, res) => {
872
+ const folderAddress = "pouch";
873
+ const bounds = findExplorerWindowPosition(folderAddress);
874
+ });
875
+ app.post('/get-key-value', (req, res) => {
876
+ res.json({
877
+ value: get(req.body.key),
878
+ [req.body.key]: get(req.body.key)
879
+ });
880
+ });
881
+ app.post('/MJ_DATA_CAPTURED'.toLocaleLowerCase(), (req, res) => {
882
+ let messageBodySplit = req.body.data;
883
+ let processedBody = messageBodySplit.map(t => {
884
+ let v = (t);
885
+ if (!v.fixed || true) {
886
+ v.full_command = fix(v.full_command);
887
+ v.fixed = true;
888
+ }
889
+ return (v);
890
+ });
891
+ console.log(`${processedBody.length}`, 'processedBody');
892
+ let existingJobs = [];
893
+ try {
894
+ let content = fs.readFileSync(get_jobs_path(), 'utf-8');
895
+ let split_content = content.split('\n');
896
+ console.log(`${split_content.length}`, 'split_content.length');
897
+ console.log(`${get_jobs_path()}`, 'jobs');
898
+ existingJobs = split_content.map(d => {
899
+ return JSON.parse(d);
900
+ }).filter(x => newerThan(new Date(x.enqueue_time), 1000 * 60 * 60 * 24 * 45)).sort((a, b) => {
901
+ return new Date(b.enqueue_time) - new Date(a.enqueue_time); // sort by enqueue_time descending
902
+ }); // filter out jobs older than 45 days
903
+ }
904
+ catch (e) {
905
+ console.error(e);
906
+ existingJobs = [];
907
+ }
908
+ processedBody = unique([...processedBody, ...existingJobs], x => x.id);
909
+ fs.writeFileSync(get_jobs_path(), processedBody.map(t => JSON.stringify(t)).join('\n'));
910
+ jobs_context.jobs = processedBody;
911
+ console.log(`${jobs_context.jobs.length}`, 'jobs');
912
+ res.json({ great: true });
913
+ });
914
+ function newerThan(timestamp, duration) {
915
+ const now = Date.now();
916
+ return (now - timestamp) < duration;
917
+ }
918
+ app.post('/update-jobs', express.text({ type: 'text/plain', limit: '1110mb' }), (req, res) => {
919
+ let messageBodySplit = req.body.split('\n');
920
+ if (!req.body.trim()) {
921
+ res.json({ great: true });
922
+ return;
923
+ }
924
+ let processedBody = messageBodySplit.map(t => {
925
+ let v = JSON.parse(t);
926
+ if (!v.fixed) {
927
+ v.full_command = fix(v.full_command);
928
+ v.fixed = true;
929
+ }
930
+ return (v);
931
+ });
932
+ let existingJobs = [];
933
+ try {
934
+ let content = fs.readFileSync(get_jobs_path(), 'utf-8');
935
+ let split_content = content.split('\n');
936
+ existingJobs = split_content.map(d => {
937
+ return JSON.parse(d);
938
+ });
939
+ }
940
+ catch (e) {
941
+ console.error(e);
942
+ existingJobs = [];
943
+ }
944
+ processedBody = unique([...processedBody, ...existingJobs], x => x.id);
945
+ fs.writeFileSync(get_jobs_path(), processedBody.map(t => JSON.stringify(t)).join('\n'));
946
+ jobs_context.jobs = processedBody;
947
+ console.log('running: writing jobs ' + jobs_context.jobs.length, 'jobs');
948
+ res.json({ great: true });
949
+ });
950
+ app.post('/jobs', express.text({ type: 'text/plain', limit: '1110mb' }), (req, res) => {
951
+ let processedBody = req.body.split('\n').map(t => {
952
+ let v = JSON.parse(t);
953
+ if (!v.fixed) {
954
+ v.full_command = fix(v.full_command);
955
+ v.fixed = true;
956
+ }
957
+ return JSON.stringify(v);
958
+ });
959
+ fs.writeFileSync(get_jobs_path(), processedBody.join('\n'));
960
+ jobs_context.jobs = processedBody.map(t => {
961
+ return JSON.parse(t);
962
+ });
963
+ console.log('running: writing jobs ' + jobs_context.jobs.length, 'jobs');
964
+ res.json({ great: true });
965
+ });
966
+ app.post('/unzip', express.text({ type: 'text/plain' }), async (req, res) => {
967
+ console.log('running: unzip');
968
+ try {
969
+ let folder = getDownloadsFolder();
970
+ await unzip(folder, get(KEYS.images_folder));
971
+ await findSocialPorterVideos()
972
+ .then(files => moveSocialPorterVideos(files, get(KEYS.images_folder)))
973
+ .catch(console.error);
974
+ res.send(`Script output:\n${stdout}`);
975
+ }
976
+ catch (error) {
977
+ res.status(500).send(`Error: ${error.message}`);
978
+ }
979
+ });
980
+ app.post('/unzipTopTen', express.text({ type: 'text/plain' }), async (req, res) => {
981
+ console.log('running: unzip');
982
+ try {
983
+ let folder = getDownloadsFolder();
984
+ await unzip(folder, path.join(get(KEYS.images_folder), 'top_ten_videos'));
985
+ await findSocialPorterVideos()
986
+ .then(files => moveSocialPorterVideos(files, path.join(get(KEYS.images_folder), 'top_ten_videos')))
987
+ .catch(console.error);
988
+ res.send(`Script output:\n${stdout}`);
989
+ }
990
+ catch (error) {
991
+ res.status(500).send(`Error: ${error.message}`);
992
+ }
993
+ });
994
+ app.post('/update-positions', async (req, res) => {
995
+ getContext().positions = {};
996
+ console.log(`${new Date(Date.now()).toLocaleDateString()} ${new Date(Date.now()).toLocaleTimeString()}`, 'update-positions');
997
+ if ([
998
+ MODES.MIDJOURNEY_IMAGES_TO_VIDEO,
999
+ MODES.CLEAR_MIDJOURNEY_IMAGES,
1000
+ MODES.MIDJOURNEY_DOWNLOAD_MEDIA,
1001
+ MODES.MIDJOURNEY_DOWNLOAD_PUBLIC_MEDIA,
1002
+ MODES.MIDJOURNEY
1003
+ ].includes(getMode()) && req.body?.location?.includes("midjourney.com")) {
1004
+ getContext().position[getMode()] = req.body;
1005
+ console.log(JSON.stringify(getContext().position[getMode()], null, 3), 'position');
1006
+ }
1007
+ else if (getMode() === MODES.SUNO_FILM && req.body?.location?.includes("https://suno.com")) {
1008
+ getContext().position[getMode()] = req.body;
1009
+ console.log(JSON.stringify(getContext().position[getMode()], null, 3), 'position');
1010
+ }
1011
+ else if ([MODES.YOUTUBE].includes(getMode()) && req.body?.location?.includes(".youtube.com")) {
1012
+ getContext().position[getMode()] = req.body;
1013
+ console.log(JSON.stringify(getContext().position[getMode()], null, 3), 'position');
1014
+ }
1015
+ else if ([MODES.FLOW_FRAME].includes(getMode())) {
1016
+ getContext().position[getMode()] = req.body;
1017
+ }
1018
+ else {
1019
+ console.log('not setting position for mode: ' + getMode(), 'not-position');
1020
+ }
1021
+ console.log(req?.body?.location, 'location');
1022
+ console.log(getMode(), 'mode');
1023
+ res.json({ status: 'success' });
1024
+ });
1025
+ app.get('/', async (req, res) => {
1026
+ res.json({ status: 'success' });
1027
+ });
1028
+ app.get('/get-projects', async (req, res) => {
1029
+ let dir = get(KEYS.current_folder);
1030
+ if (dir) {
1031
+ let jsonFiles = await readJsonFiles(dir);
1032
+ res.json({ projects: jsonFiles.map(jk => path.basename(jk)) });
1033
+ }
1034
+ else {
1035
+ res.json({ projects: [] });
1036
+ }
1037
+ });
1038
+ app.post('/broadcast-stories', async (req, res) => {
1039
+ let dir = get(KEYS.current_folder);
1040
+ const { peers, localIp, localKey } = getPeerConstants();
1041
+ if (dir) {
1042
+ let jsonFiles = await readJsonFiles(dir);
1043
+ let urls = Array.from(peers).map(([_ts, key]) => {
1044
+ return `http://${_ts}`;
1045
+ });
1046
+ for (let j = 0; j < jsonFiles.length; j++) {
1047
+ let jsonFile = jsonFiles[j];
1048
+ for (let i = 0; i < urls.length; i++) {
1049
+ let url = urls[i];
1050
+ if (url !== `http://${localKey}`) {
1051
+ console.log(path.basename(jsonFile), 'broadcasted file');
1052
+ console.log(url, 'broadcasted file url');
1053
+ let res = await fetch(`${url}/receive-broadcasted-stories`, {
1054
+ method: 'POST',
1055
+ headers: { 'Content-Type': 'application/json' },
1056
+ body: JSON.stringify({
1057
+ fileName: path.basename(jsonFile),
1058
+ content: fs.readFileSync(jsonFile, 'utf-8'),
1059
+ last_updated: getLastModifiedTimestampSync(jsonFile)
1060
+ })
1061
+ });
1062
+ console.log((await res.text()), 'broadcasted file result');
1063
+ ;
1064
+ }
1065
+ }
1066
+ }
1067
+ }
1068
+ res.json({ status: 'success' });
1069
+ });
1070
+ app.post('/receive-broadcasted-stories', async (req, res) => {
1071
+ console.log('received broadcast story');
1072
+ const dir = get(KEYS.current_folder);
1073
+ if (!dir) {
1074
+ return res.status(400).json({ error: 'No target folder configured' });
1075
+ }
1076
+ // payload should be { fileName, content, last_updated }
1077
+ const { fileName, content, last_updated } = req.body;
1078
+ if (!fileName || !content || typeof last_updated !== 'number') {
1079
+ console.log('received bad file : ' + fileName, 'received-file-status');
1080
+ return res.status(400).json({ error: 'Invalid payload' });
1081
+ }
1082
+ const targetPath = path.join(dir, fileName);
1083
+ let updated = false;
1084
+ try {
1085
+ if (fs.existsSync(targetPath)) {
1086
+ console.log('overwriting : ' + targetPath, 'received-file-status');
1087
+ // only overwrite if the incoming copy is newer
1088
+ const localTs = getLastModifiedTimestampSync(targetPath);
1089
+ if (last_updated > localTs) {
1090
+ fs.writeFileSync(targetPath, content, 'utf8');
1091
+ updated = true;
1092
+ }
1093
+ }
1094
+ else {
1095
+ // file doesn't exist yet, so write it
1096
+ console.log('newfile : ' + targetPath, 'received-file-status');
1097
+ fs.writeFileSync(targetPath, content, 'utf8');
1098
+ updated = true;
1099
+ }
1100
+ // Optionally, sync the file mtime to the broadcasted timestamp:
1101
+ fs.utimesSync(targetPath, new Date(), new Date(last_updated));
1102
+ res.json({ status: 'ok', updated });
1103
+ }
1104
+ catch (err) {
1105
+ console.log('Error in /receive-broadcasted-stories : ', 'received-file-status');
1106
+ console.error('Error in /receive-broadcasted-stories:', err);
1107
+ res.status(500).json({ error: err.message });
1108
+ }
1109
+ });
1110
+ let promiseQueue = Promise.resolve();
1111
+ // Endpoint to receive positions.
1112
+ app.post('/positions', async (req, res) => {
1113
+ const mode = getContext().mode;
1114
+ const body = req.body;
1115
+ try {
1116
+ promiseQueue = promiseQueue.then(() => {
1117
+ // wrap your various operations into the queue
1118
+ switch (mode) {
1119
+ case MODES.SUNO:
1120
+ return operateSunoMouse(body);
1121
+ case MODES.SUNO_FILM:
1122
+ return operateSunoFilmMouse(body);
1123
+ case MODES.YOUTUBE:
1124
+ return operateYoutubeMouse(body);
1125
+ case MODES.CLEAR_MIDJOURNEY_IMAGES:
1126
+ return clearMidjourneyImages();
1127
+ case MODES.MIDJOURNEY_IMAGES_TO_VIDEO:
1128
+ return operateMidjourneyToImages();
1129
+ case MODES.MIDJOURNEY_DOWNLOAD_MEDIA:
1130
+ return operateMidjourneyDownloadMedia();
1131
+ case MODES.MIDJOURNEY_DOWNLOAD_PUBLIC_MEDIA:
1132
+ return operateMidjourneyDownloadPublicMedia();
1133
+ case MODES.MIDJOURNEY:
1134
+ return operateMouse((body[input_bar]));
1135
+ }
1136
+ }).catch(e => {
1137
+ console.log('', 'mode-filter');
1138
+ console.log(`Error in /positions: ${e.message}`, 'positions-error');
1139
+ });
1140
+ await promiseQueue;
1141
+ console.log(`Operation for mode ${mode} completed successfully`, 'positions-success');
1142
+ res.json({ status: 'success', message: 'Operation finished successfully' });
1143
+ return;
1144
+ }
1145
+ catch (e) {
1146
+ console.error(e);
1147
+ // console.log(e, 'positions-error');
1148
+ console.log(`Error in /positions: ${e.message}`, 'positions-error');
1149
+ console.log(`Stack trace: ${e.stack}`, 'positions-error-stack');
1150
+ res.status(500).json({ status: 'error', message: e.message });
1151
+ return;
1152
+ }
1153
+ });
1154
+ // app.post('/positions', async (req, res) => {
1155
+ // const mode = getContext().mode;
1156
+ // const body = req.body;
1157
+ // try {
1158
+ // // wrap your various operations into the queue
1159
+ // const jobId = queue.enqueue((signal, progress) => {
1160
+ // switch (mode) {
1161
+ // case MODES.SUNO:
1162
+ // return operateSunoMouse(body, signal, progress);
1163
+ // case MODES.SUNO_FILM:
1164
+ // return operateSunoFilmMouse(body, signal, progress);
1165
+ // case MODES.YOUTUBE:
1166
+ // return operateYoutubeMouse(body, signal, progress);
1167
+ // case MODES.CLEAR_MIDJOURNEY_IMAGES:
1168
+ // return clearMidjourneyImages(signal, progress);
1169
+ // case MODES.MIDJOURNEY_IMAGES_TO_VIDEO:
1170
+ // return operateMidjourneyToImages(signal, progress)
1171
+ // case MODES.MIDJOURNEY_DOWNLOAD_MEDIA:
1172
+ // return operateMidjourneyDownloadMedia(signal, progress);
1173
+ // case MODES.MIDJOURNEY_DOWNLOAD_PUBLIC_MEDIA:
1174
+ // return operateMidjourneyDownloadPublicMedia(signal, progress);
1175
+ // case MODES.MIDJOURNEY:
1176
+ // return operateMouse((body[input_bar]), signal, progress);
1177
+ // }
1178
+ // });
1179
+ // let status = 'waiting';
1180
+ // await queue.waitForJobId(jobId, (info) => {
1181
+ // status = info.status;
1182
+ // if (info.status === 'done') {
1183
+ // console.log(`Job ${jobId} completed successfully`, 'positions-success');
1184
+ // } else if (info.status === 'error') {
1185
+ // console.log(`Job ${jobId} failed with error: ${info.error}`, ' positions-error');
1186
+ // }
1187
+ // });
1188
+ // res.json({ status, jobId });
1189
+ // } catch (e) {
1190
+ // console.error(e)
1191
+ // console.log(e, 'positions-error')
1192
+ // }
1193
+ // });
1194
+ app.get('/operations/:jobId/status', (req, res) => {
1195
+ const info = queue.status(+req.params.jobId);
1196
+ if (!info)
1197
+ return res.status(404).json({ error: 'no such job' });
1198
+ res.json(info);
1199
+ });
1200
+ app.post('/operations/:jobId/cancel', (req, res) => {
1201
+ const ok = queue.cancel(+req.params.jobId);
1202
+ res.json({ status: ok ? 'cancelling' : 'not found' });
1203
+ });
1204
+ // **list all jobs**
1205
+ app.get('/operations', (req, res) => {
1206
+ res.json(queue.list());
1207
+ });
1208
+ // Endpoint to receive positions.
1209
+ app.post('/open-ai-positions', async (req, res) => {
1210
+ res.json({ status: 'success' });
1211
+ setOpenAiPositions(req.body);
1212
+ });
1213
+ app.post('/suno-urls', async (req, res) => {
1214
+ const { urls, name } = req.body;
1215
+ console.log(urls);
1216
+ });
1217
+ // Open application by name
1218
+ app.post('/open-app', async (req, res) => {
1219
+ const { appName } = req.body;
1220
+ if (!appName) {
1221
+ return res.status(400).json({ error: 'Application name is required' });
1222
+ }
1223
+ try {
1224
+ if (process.platform === 'darwin') {
1225
+ spawn('open', ['-a', appName], { detached: true, stdio: 'ignore' });
1226
+ }
1227
+ else if (process.platform === 'win32') {
1228
+ spawn('cmd', ['/c', 'start', '""', appName], { detached: true, stdio: 'ignore' });
1229
+ }
1230
+ else {
1231
+ return res.status(400).json({ error: 'Unsupported platform' });
1232
+ }
1233
+ console.log(`Successfully started ${appName}`, 'open-app-success');
1234
+ res.json({ success: true, message: `${appName} started successfully` });
1235
+ }
1236
+ catch (e) {
1237
+ console.log(`Exception starting ${appName}: ${e.message}`, 'open-app-error');
1238
+ res.status(500).json({ error: `Exception: ${e.message}` });
1239
+ }
1240
+ });
1241
+ // Close application by name
1242
+ app.post('/close-app', async (req, res) => {
1243
+ const { appName, force = false } = req.body;
1244
+ if (!appName) {
1245
+ return res.status(400).json({ error: 'Application name is required' });
1246
+ }
1247
+ let command;
1248
+ if (process.platform === 'darwin') {
1249
+ const killSignal = force ? '-KILL' : '-TERM';
1250
+ command = `killall ${killSignal} "${appName}"`;
1251
+ }
1252
+ else if (process.platform === 'win32') {
1253
+ const forceFlag = force ? '/F' : '';
1254
+ command = `taskkill /IM "${appName}.exe" ${forceFlag}`;
1255
+ }
1256
+ else {
1257
+ return res.status(400).json({ error: 'Unsupported platform' });
1258
+ }
1259
+ try {
1260
+ exec(command, (error, stdout, stderr) => {
1261
+ if (error) {
1262
+ console.log(`Error closing ${appName}: ${error.message}`, 'close-app-error');
1263
+ return res.status(404).json({ error: `Application not found or already closed: ${appName}` });
1264
+ }
1265
+ console.log(`Successfully closed ${appName}`, 'close-app-success');
1266
+ res.json({ success: true, message: `${appName} closed successfully` });
1267
+ });
1268
+ }
1269
+ catch (e) {
1270
+ console.log(`Exception closing ${appName}: ${e.message}`, 'close-app-error');
1271
+ res.status(500).json({ error: `Exception: ${e.message}` });
1272
+ }
1273
+ });
1274
+ // Wait for file to stabilize (stop being modified for 20 seconds)
1275
+ app.post('/wait-for-file-stable', async (req, res) => {
1276
+ // Disable request timeout for long-running file monitoring
1277
+ req.setTimeout(0);
1278
+ const { file_path, min_size_mb = 1, max_wait_minutes = 120 } = req.body;
1279
+ if (!file_path) {
1280
+ return res.status(400).json({ error: 'file_path is required' });
1281
+ }
1282
+ const minSizeBytes = min_size_mb * 1024 * 1024; // Convert MB to bytes
1283
+ const checkInterval = 5000; // Check every 5 seconds
1284
+ const stableDuration = 20000; // 20 seconds of no changes
1285
+ const maxWaitTime = max_wait_minutes * 60 * 1000; // Convert minutes to milliseconds
1286
+ let lastModified = null;
1287
+ let stableStart = null;
1288
+ const startTime = Date.now();
1289
+ console.log(`Starting to monitor file: ${file_path} (min size: ${min_size_mb}MB, max wait: ${max_wait_minutes}min)`, 'file-monitor-start');
1290
+ const monitorFile = async () => {
1291
+ try {
1292
+ if (fs.existsSync(file_path)) {
1293
+ const stats = fs.statSync(file_path);
1294
+ const currentModified = stats.mtime.getTime();
1295
+ const currentSize = stats.size;
1296
+ // Check if file meets minimum size requirement
1297
+ if (currentSize < minSizeBytes) {
1298
+ // File too small, reset stability timer
1299
+ lastModified = currentModified;
1300
+ stableStart = null;
1301
+ console.log(`File ${file_path} too small (${(currentSize / 1024 / 1024).toFixed(2)}MB < ${min_size_mb}MB)`, 'file-monitor-small');
1302
+ }
1303
+ else if (lastModified === null || currentModified > lastModified) {
1304
+ // File was modified or first check
1305
+ lastModified = currentModified;
1306
+ stableStart = null;
1307
+ console.log(`File ${file_path} modified at ${new Date(currentModified).toISOString()} (${(currentSize / 1024 / 1024).toFixed(2)}MB)`, 'file-monitor-update');
1308
+ }
1309
+ else if (stableStart === null) {
1310
+ // File hasn't changed and meets size requirement, start counting stability
1311
+ stableStart = Date.now();
1312
+ console.log(`File ${file_path} stable start: ${new Date(stableStart).toISOString()} (${(currentSize / 1024 / 1024).toFixed(2)}MB)`, 'file-monitor-stable-start');
1313
+ }
1314
+ else if (Date.now() - stableStart >= stableDuration) {
1315
+ // File has been stable for required duration and meets size requirement
1316
+ console.log(`File ${file_path} stable for ${stableDuration / 1000}s (${(currentSize / 1024 / 1024).toFixed(2)}MB)`, 'file-monitor-complete');
1317
+ return res.json({
1318
+ file_path,
1319
+ stable: true,
1320
+ file_size: currentSize,
1321
+ file_size_mb: currentSize / (1024 * 1024),
1322
+ last_modified: new Date(currentModified).toISOString()
1323
+ });
1324
+ }
1325
+ }
1326
+ else {
1327
+ // File doesn't exist yet
1328
+ lastModified = null;
1329
+ stableStart = null;
1330
+ }
1331
+ // Check for timeout
1332
+ if (Date.now() - startTime > maxWaitTime) {
1333
+ console.log(`Timeout waiting for file ${file_path} to stabilize`, 'file-monitor-timeout');
1334
+ return res.status(408).json({ error: 'Timeout waiting for file to stabilize' });
1335
+ }
1336
+ // Wait and check again
1337
+ await new Promise(resolve => setTimeout(resolve, checkInterval));
1338
+ await monitorFile();
1339
+ }
1340
+ catch (error) {
1341
+ console.log(`Error monitoring file ${file_path}: ${error.message}`, 'file-monitor-error');
1342
+ return res.status(500).json({ error: `Error monitoring file: ${error.message}` });
1343
+ }
1344
+ };
1345
+ // Start monitoring
1346
+ monitorFile();
1347
+ });
1348
+ // Get node context by node ID
1349
+ app.get('/nodecontext/:nodeId', (req, res) => {
1350
+ try {
1351
+ const { nodeId } = req.params;
1352
+ const valuesFile = path.join(process.cwd(), 'node_values.ndjson');
1353
+ if (!fs.existsSync(valuesFile)) {
1354
+ return res.status(404).json({ error: 'No node values file found' });
1355
+ }
1356
+ const lines = fs.readFileSync(valuesFile, 'utf8').trim().split('\n');
1357
+ // Find the entry for this nodeId
1358
+ for (const line of lines) {
1359
+ try {
1360
+ const entry = JSON.parse(line);
1361
+ if (entry.nodeId === nodeId) {
1362
+ return res.json({
1363
+ nodeId: entry.nodeId,
1364
+ value: entry.value,
1365
+ input: entry.input,
1366
+ timestamp: entry.timestamp
1367
+ });
1368
+ }
1369
+ }
1370
+ catch (e) {
1371
+ // Skip malformed lines
1372
+ continue;
1373
+ }
1374
+ }
1375
+ return res.status(404).json({ error: `No value found for node ${nodeId}` });
1376
+ }
1377
+ catch (err) {
1378
+ console.error('Error retrieving node context:', err);
1379
+ res.status(500).json({ error: 'Internal server error' });
1380
+ }
1381
+ });
1382
+ // Clear node values file
1383
+ app.post('/clear-node-values', async (req, res) => {
1384
+ try {
1385
+ const valuesFile = path.join(process.cwd(), 'node_values.ndjson');
1386
+ // Clear the file by writing an empty string
1387
+ fs.writeFileSync(valuesFile, '', 'utf8');
1388
+ console.log('Node values file cleared successfully', 'clear-node-values');
1389
+ res.json({ success: true, message: 'Node values file cleared successfully' });
1390
+ }
1391
+ catch (err) {
1392
+ console.error('Error clearing node values file:', err);
1393
+ res.status(500).json({ error: 'Failed to clear node values file' });
1394
+ }
1395
+ });
1396
+ // Get settings file contents
1397
+ app.get('/get-settings', (req, res) => {
1398
+ try {
1399
+ const settingsFilePath = get(KEYS.SETTINGS_FILE);
1400
+ if (!settingsFilePath) {
1401
+ console.log('No SETTINGS_FILE path configured', 'get-settings');
1402
+ return res.json({});
1403
+ }
1404
+ if (!fs.existsSync(settingsFilePath)) {
1405
+ console.log(`Settings file does not exist: ${settingsFilePath}`, 'get-settings');
1406
+ return res.json({});
1407
+ }
1408
+ const settingsContent = fs.readFileSync(settingsFilePath, 'utf8');
1409
+ const settings = JSON.parse(settingsContent);
1410
+ console.log(`Successfully loaded settings from: ${settingsFilePath}`, 'get-settings');
1411
+ res.json(settings);
1412
+ }
1413
+ catch (error) {
1414
+ console.error('Error reading settings file:', error);
1415
+ res.status(500).json({ error: `Failed to read settings file: ${error.message}` });
1416
+ }
1417
+ });
1418
+ app.post('/buildWorkflowDirectory', async (req, res) => {
1419
+ const { jsonInput, targetDir } = req.body;
1420
+ if (!jsonInput || !targetDir) {
1421
+ return res.status(400).json({ error: 'Missing jsonInput or targetDir' });
1422
+ }
1423
+ try {
1424
+ const result = await buildWorkflowDirectory(jsonInput, targetDir);
1425
+ res.json(result);
1426
+ }
1427
+ catch (error) {
1428
+ console.error('Error in /buildWorkflowDirectory:', error);
1429
+ res.status(500).json({ error: error.message });
1430
+ }
1431
+ });
1432
+ app.post('/runWorkflowCLI', async (req, res) => {
1433
+ const { targetDir, workflowJsonPath, parameters } = req.body;
1434
+ if (!targetDir) {
1435
+ return res.status(400).json({ error: 'Missing targetDir or workflowJsonPath' });
1436
+ }
1437
+ try {
1438
+ const result = await runWorkflowCLI(targetDir, workflowJsonPath, parameters);
1439
+ res.json(result);
1440
+ }
1441
+ catch (error) {
1442
+ console.error('Error in /runWorkflowCLI:', error);
1443
+ res.status(500).json({ error: error.message });
1444
+ }
1445
+ });
1446
+ app.post('/installDependencies', async (req, res) => {
1447
+ const { targetDir } = req.body;
1448
+ if (!targetDir) {
1449
+ return res.status(400).json({ error: 'Missing targetDir' });
1450
+ }
1451
+ try {
1452
+ const result = await installDependencies(targetDir);
1453
+ res.json(result);
1454
+ }
1455
+ catch (error) {
1456
+ console.error('Error in /installDependencies:', error);
1457
+ res.status(500).json({ error: error.message });
1458
+ }
1459
+ });
1460
+ app.get('/get-extensions', async (req, res) => {
1461
+ const folders = get(KEYS.extension_folders);
1462
+ const extensions = await scanExtensions(folders);
1463
+ res.json({ extensions });
1464
+ });
1465
+ app.post('/generate-ui-map', async (req, res) => {
1466
+ try {
1467
+ const { files } = req.body;
1468
+ if (!files) {
1469
+ return res.status(400).json({ error: 'Files are required' });
1470
+ }
1471
+ console.log(`[running] generate-ui-map for ${files}`, 'generate-ui-map');
1472
+ let workflow_folder = (get(KEYS.workflow_folder));
1473
+ // if the files are relative paths, make them absolute based on workflow_folder
1474
+ const absoluteFiles = files.map(file => {
1475
+ if (!path.isAbsolute(file)) {
1476
+ return path.join(workflow_folder, file);
1477
+ }
1478
+ return file;
1479
+ });
1480
+ console.log(absoluteFiles);
1481
+ const uiMap = await generateUIMap(absoluteFiles);
1482
+ console.log(`[done] generate-ui-map for ${files}`, 'generate-ui-map');
1483
+ res.json({
1484
+ success: true,
1485
+ files,
1486
+ uiMap
1487
+ });
1488
+ }
1489
+ catch (error) {
1490
+ console.log(`Error in generate-ui-map: ${error.message}`, 'generate-ui-map-error');
1491
+ res.status(500).json({ error: `Failed to generate UI map: ${error.message}` });
1492
+ }
1493
+ });
1494
+ }
1495
+ //# sourceMappingURL=standardRoutes.js.map