memma 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 (304) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +116 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +21 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/generate/generateActionHandler.d.ts +3 -0
  8. package/dist/commands/generate/generateActionHandler.d.ts.map +1 -0
  9. package/dist/commands/generate/generateActionHandler.js +63 -0
  10. package/dist/commands/generate/generateActionHandler.js.map +1 -0
  11. package/dist/commands/generate/generateCommand.d.ts +3 -0
  12. package/dist/commands/generate/generateCommand.d.ts.map +1 -0
  13. package/dist/commands/generate/generateCommand.js +10 -0
  14. package/dist/commands/generate/generateCommand.js.map +1 -0
  15. package/dist/commands/generate/helpers/detectFileType.d.ts +2 -0
  16. package/dist/commands/generate/helpers/detectFileType.d.ts.map +1 -0
  17. package/dist/commands/generate/helpers/detectFileType.js +7 -0
  18. package/dist/commands/generate/helpers/detectFileType.js.map +1 -0
  19. package/dist/commands/generate/helpers/displayGenerateSuccessMessage.d.ts +7 -0
  20. package/dist/commands/generate/helpers/displayGenerateSuccessMessage.d.ts.map +1 -0
  21. package/dist/commands/generate/helpers/displayGenerateSuccessMessage.js +5 -0
  22. package/dist/commands/generate/helpers/displayGenerateSuccessMessage.js.map +1 -0
  23. package/dist/commands/generate/helpers/resolveOutputDirectory.d.ts +2 -0
  24. package/dist/commands/generate/helpers/resolveOutputDirectory.d.ts.map +1 -0
  25. package/dist/commands/generate/helpers/resolveOutputDirectory.js +29 -0
  26. package/dist/commands/generate/helpers/resolveOutputDirectory.js.map +1 -0
  27. package/dist/commands/generate/helpers/resolveSourceArgument.d.ts +8 -0
  28. package/dist/commands/generate/helpers/resolveSourceArgument.d.ts.map +1 -0
  29. package/dist/commands/generate/helpers/resolveSourceArgument.js +67 -0
  30. package/dist/commands/generate/helpers/resolveSourceArgument.js.map +1 -0
  31. package/dist/commands/generate/index.d.ts +2 -0
  32. package/dist/commands/generate/index.d.ts.map +1 -0
  33. package/dist/commands/generate/index.js +2 -0
  34. package/dist/commands/generate/index.js.map +1 -0
  35. package/dist/commands/generate/stream/llmResponseHandler.d.ts +9 -0
  36. package/dist/commands/generate/stream/llmResponseHandler.d.ts.map +1 -0
  37. package/dist/commands/generate/stream/llmResponseHandler.js +33 -0
  38. package/dist/commands/generate/stream/llmResponseHandler.js.map +1 -0
  39. package/dist/commands/generate/stream/sseHandler.d.ts +5 -0
  40. package/dist/commands/generate/stream/sseHandler.d.ts.map +1 -0
  41. package/dist/commands/generate/stream/sseHandler.js +28 -0
  42. package/dist/commands/generate/stream/sseHandler.js.map +1 -0
  43. package/dist/commands/generate/stream/statusHandler.d.ts +10 -0
  44. package/dist/commands/generate/stream/statusHandler.d.ts.map +1 -0
  45. package/dist/commands/generate/stream/statusHandler.js +38 -0
  46. package/dist/commands/generate/stream/statusHandler.js.map +1 -0
  47. package/dist/commands/generate/stream/streamGenerateResponse.d.ts +3 -0
  48. package/dist/commands/generate/stream/streamGenerateResponse.d.ts.map +1 -0
  49. package/dist/commands/generate/stream/streamGenerateResponse.js +19 -0
  50. package/dist/commands/generate/stream/streamGenerateResponse.js.map +1 -0
  51. package/dist/commands/generate/write/saveLLMResponse.d.ts +8 -0
  52. package/dist/commands/generate/write/saveLLMResponse.d.ts.map +1 -0
  53. package/dist/commands/generate/write/saveLLMResponse.js +18 -0
  54. package/dist/commands/generate/write/saveLLMResponse.js.map +1 -0
  55. package/dist/commands/generate/write/writeResponseToDir.d.ts +2 -0
  56. package/dist/commands/generate/write/writeResponseToDir.d.ts.map +1 -0
  57. package/dist/commands/generate/write/writeResponseToDir.js +18 -0
  58. package/dist/commands/generate/write/writeResponseToDir.js.map +1 -0
  59. package/dist/commands/generate/write/writeResponseToNewProject.ts.d.ts +3 -0
  60. package/dist/commands/generate/write/writeResponseToNewProject.ts.d.ts.map +1 -0
  61. package/dist/commands/generate/write/writeResponseToNewProject.ts.js +27 -0
  62. package/dist/commands/generate/write/writeResponseToNewProject.ts.js.map +1 -0
  63. package/dist/commands/init/index.d.ts +2 -0
  64. package/dist/commands/init/index.d.ts.map +1 -0
  65. package/dist/commands/init/index.js +2 -0
  66. package/dist/commands/init/index.js.map +1 -0
  67. package/dist/commands/init/initActionHandler.d.ts +2 -0
  68. package/dist/commands/init/initActionHandler.d.ts.map +1 -0
  69. package/dist/commands/init/initActionHandler.js +50 -0
  70. package/dist/commands/init/initActionHandler.js.map +1 -0
  71. package/dist/commands/init/initCommand.d.ts +3 -0
  72. package/dist/commands/init/initCommand.d.ts.map +1 -0
  73. package/dist/commands/init/initCommand.js +6 -0
  74. package/dist/commands/init/initCommand.js.map +1 -0
  75. package/dist/commands/init/memma-config/ensureMemmaConfigurations.d.ts +3 -0
  76. package/dist/commands/init/memma-config/ensureMemmaConfigurations.d.ts.map +1 -0
  77. package/dist/commands/init/memma-config/ensureMemmaConfigurations.js +8 -0
  78. package/dist/commands/init/memma-config/ensureMemmaConfigurations.js.map +1 -0
  79. package/dist/commands/init/memma-config/gatherConfigurationDetails.d.ts +3 -0
  80. package/dist/commands/init/memma-config/gatherConfigurationDetails.d.ts.map +1 -0
  81. package/dist/commands/init/memma-config/gatherConfigurationDetails.js +15 -0
  82. package/dist/commands/init/memma-config/gatherConfigurationDetails.js.map +1 -0
  83. package/dist/commands/init/memma-env/createPythonVirtualEnv.d.ts +2 -0
  84. package/dist/commands/init/memma-env/createPythonVirtualEnv.d.ts.map +1 -0
  85. package/dist/commands/init/memma-env/createPythonVirtualEnv.js +5 -0
  86. package/dist/commands/init/memma-env/createPythonVirtualEnv.js.map +1 -0
  87. package/dist/commands/init/memma-env/ensureMemmaEnvironment.d.ts +3 -0
  88. package/dist/commands/init/memma-env/ensureMemmaEnvironment.d.ts.map +1 -0
  89. package/dist/commands/init/memma-env/ensureMemmaEnvironment.js +21 -0
  90. package/dist/commands/init/memma-env/ensureMemmaEnvironment.js.map +1 -0
  91. package/dist/commands/init/memma-env/getVenvPath.d.ts +2 -0
  92. package/dist/commands/init/memma-env/getVenvPath.d.ts.map +1 -0
  93. package/dist/commands/init/memma-env/getVenvPath.js +9 -0
  94. package/dist/commands/init/memma-env/getVenvPath.js.map +1 -0
  95. package/dist/commands/init/memma-env/index.d.ts +2 -0
  96. package/dist/commands/init/memma-env/index.d.ts.map +1 -0
  97. package/dist/commands/init/memma-env/index.js +2 -0
  98. package/dist/commands/init/memma-env/index.js.map +1 -0
  99. package/dist/commands/init/memma-env/venvExists.d.ts +2 -0
  100. package/dist/commands/init/memma-env/venvExists.d.ts.map +1 -0
  101. package/dist/commands/init/memma-env/venvExists.js +7 -0
  102. package/dist/commands/init/memma-env/venvExists.js.map +1 -0
  103. package/dist/commands/init/messages/displayExitMessages.d.ts +2 -0
  104. package/dist/commands/init/messages/displayExitMessages.d.ts.map +1 -0
  105. package/dist/commands/init/messages/displayExitMessages.js +9 -0
  106. package/dist/commands/init/messages/displayExitMessages.js.map +1 -0
  107. package/dist/commands/init/messages/displayWelcomeMessages.d.ts +2 -0
  108. package/dist/commands/init/messages/displayWelcomeMessages.d.ts.map +1 -0
  109. package/dist/commands/init/messages/displayWelcomeMessages.js +12 -0
  110. package/dist/commands/init/messages/displayWelcomeMessages.js.map +1 -0
  111. package/dist/commands/init/packages/ensureRequirementsFile.d.ts +5 -0
  112. package/dist/commands/init/packages/ensureRequirementsFile.d.ts.map +1 -0
  113. package/dist/commands/init/packages/ensureRequirementsFile.js +11 -0
  114. package/dist/commands/init/packages/ensureRequirementsFile.js.map +1 -0
  115. package/dist/commands/init/packages/index.d.ts +2 -0
  116. package/dist/commands/init/packages/index.d.ts.map +1 -0
  117. package/dist/commands/init/packages/index.js +2 -0
  118. package/dist/commands/init/packages/index.js.map +1 -0
  119. package/dist/commands/init/packages/installPlaywrightBrowserBinaries.d.ts +2 -0
  120. package/dist/commands/init/packages/installPlaywrightBrowserBinaries.d.ts.map +1 -0
  121. package/dist/commands/init/packages/installPlaywrightBrowserBinaries.js +8 -0
  122. package/dist/commands/init/packages/installPlaywrightBrowserBinaries.js.map +1 -0
  123. package/dist/commands/init/packages/installRequiredMemmaPackages.d.ts +2 -0
  124. package/dist/commands/init/packages/installRequiredMemmaPackages.d.ts.map +1 -0
  125. package/dist/commands/init/packages/installRequiredMemmaPackages.js +12 -0
  126. package/dist/commands/init/packages/installRequiredMemmaPackages.js.map +1 -0
  127. package/dist/commands/init/packages/installRequiredPackages.d.ts +2 -0
  128. package/dist/commands/init/packages/installRequiredPackages.d.ts.map +1 -0
  129. package/dist/commands/init/packages/installRequiredPackages.js +5 -0
  130. package/dist/commands/init/packages/installRequiredPackages.js.map +1 -0
  131. package/dist/commands/init/python-env/checkPipInstalled.d.ts +5 -0
  132. package/dist/commands/init/python-env/checkPipInstalled.d.ts.map +1 -0
  133. package/dist/commands/init/python-env/checkPipInstalled.js +17 -0
  134. package/dist/commands/init/python-env/checkPipInstalled.js.map +1 -0
  135. package/dist/commands/init/python-env/detectPython.d.ts +3 -0
  136. package/dist/commands/init/python-env/detectPython.d.ts.map +1 -0
  137. package/dist/commands/init/python-env/detectPython.js +26 -0
  138. package/dist/commands/init/python-env/detectPython.js.map +1 -0
  139. package/dist/commands/init/python-env/detectPythonVersion.d.ts +2 -0
  140. package/dist/commands/init/python-env/detectPythonVersion.d.ts.map +1 -0
  141. package/dist/commands/init/python-env/detectPythonVersion.js +8 -0
  142. package/dist/commands/init/python-env/detectPythonVersion.js.map +1 -0
  143. package/dist/commands/init/python-env/index.d.ts +2 -0
  144. package/dist/commands/init/python-env/index.d.ts.map +1 -0
  145. package/dist/commands/init/python-env/index.js +2 -0
  146. package/dist/commands/init/python-env/index.js.map +1 -0
  147. package/dist/commands/init/python-env/validatePythonEnvironment.d.ts +3 -0
  148. package/dist/commands/init/python-env/validatePythonEnvironment.d.ts.map +1 -0
  149. package/dist/commands/init/python-env/validatePythonEnvironment.js +11 -0
  150. package/dist/commands/init/python-env/validatePythonEnvironment.js.map +1 -0
  151. package/dist/commands/init/scripts/copyMemmaPythonFiles.d.ts +6 -0
  152. package/dist/commands/init/scripts/copyMemmaPythonFiles.d.ts.map +1 -0
  153. package/dist/commands/init/scripts/copyMemmaPythonFiles.js +31 -0
  154. package/dist/commands/init/scripts/copyMemmaPythonFiles.js.map +1 -0
  155. package/dist/commands/reset/deleteMemmaDirectory.d.ts +2 -0
  156. package/dist/commands/reset/deleteMemmaDirectory.d.ts.map +1 -0
  157. package/dist/commands/reset/deleteMemmaDirectory.js +12 -0
  158. package/dist/commands/reset/deleteMemmaDirectory.js.map +1 -0
  159. package/dist/commands/reset/resetActionHandler.d.ts +2 -0
  160. package/dist/commands/reset/resetActionHandler.d.ts.map +1 -0
  161. package/dist/commands/reset/resetActionHandler.js +39 -0
  162. package/dist/commands/reset/resetActionHandler.js.map +1 -0
  163. package/dist/commands/reset/resetCommand.d.ts +3 -0
  164. package/dist/commands/reset/resetCommand.d.ts.map +1 -0
  165. package/dist/commands/reset/resetCommand.js +6 -0
  166. package/dist/commands/reset/resetCommand.js.map +1 -0
  167. package/dist/commands/start/getOrchestratorEnvVariables.d.ts +7 -0
  168. package/dist/commands/start/getOrchestratorEnvVariables.d.ts.map +1 -0
  169. package/dist/commands/start/getOrchestratorEnvVariables.js +12 -0
  170. package/dist/commands/start/getOrchestratorEnvVariables.js.map +1 -0
  171. package/dist/commands/start/index.d.ts +2 -0
  172. package/dist/commands/start/index.d.ts.map +1 -0
  173. package/dist/commands/start/index.js +2 -0
  174. package/dist/commands/start/index.js.map +1 -0
  175. package/dist/commands/start/startActionHandler.d.ts +2 -0
  176. package/dist/commands/start/startActionHandler.d.ts.map +1 -0
  177. package/dist/commands/start/startActionHandler.js +23 -0
  178. package/dist/commands/start/startActionHandler.js.map +1 -0
  179. package/dist/commands/start/startCommand.d.ts +3 -0
  180. package/dist/commands/start/startCommand.d.ts.map +1 -0
  181. package/dist/commands/start/startCommand.js +6 -0
  182. package/dist/commands/start/startCommand.js.map +1 -0
  183. package/dist/commands/start/startMemmaOrchestrator.d.ts +2 -0
  184. package/dist/commands/start/startMemmaOrchestrator.d.ts.map +1 -0
  185. package/dist/commands/start/startMemmaOrchestrator.js +31 -0
  186. package/dist/commands/start/startMemmaOrchestrator.js.map +1 -0
  187. package/dist/commands/start/waitForLocalServerReady.d.ts +2 -0
  188. package/dist/commands/start/waitForLocalServerReady.d.ts.map +1 -0
  189. package/dist/commands/start/waitForLocalServerReady.js +18 -0
  190. package/dist/commands/start/waitForLocalServerReady.js.map +1 -0
  191. package/dist/commands/stop/index.d.ts +2 -0
  192. package/dist/commands/stop/index.d.ts.map +1 -0
  193. package/dist/commands/stop/index.js +2 -0
  194. package/dist/commands/stop/index.js.map +1 -0
  195. package/dist/commands/stop/stopActionHandler.d.ts +2 -0
  196. package/dist/commands/stop/stopActionHandler.d.ts.map +1 -0
  197. package/dist/commands/stop/stopActionHandler.js +22 -0
  198. package/dist/commands/stop/stopActionHandler.js.map +1 -0
  199. package/dist/commands/stop/stopCommand.d.ts +3 -0
  200. package/dist/commands/stop/stopCommand.d.ts.map +1 -0
  201. package/dist/commands/stop/stopCommand.js +6 -0
  202. package/dist/commands/stop/stopCommand.js.map +1 -0
  203. package/dist/commands/stop/stopMemmaOrchestrator.d.ts +2 -0
  204. package/dist/commands/stop/stopMemmaOrchestrator.d.ts.map +1 -0
  205. package/dist/commands/stop/stopMemmaOrchestrator.js +15 -0
  206. package/dist/commands/stop/stopMemmaOrchestrator.js.map +1 -0
  207. package/dist/commands/stop/stopProcess.d.ts +2 -0
  208. package/dist/commands/stop/stopProcess.d.ts.map +1 -0
  209. package/dist/commands/stop/stopProcess.js +21 -0
  210. package/dist/commands/stop/stopProcess.js.map +1 -0
  211. package/dist/constants.d.ts +61 -0
  212. package/dist/constants.d.ts.map +1 -0
  213. package/dist/constants.js +69 -0
  214. package/dist/constants.js.map +1 -0
  215. package/dist/types.d.ts +57 -0
  216. package/dist/types.d.ts.map +1 -0
  217. package/dist/types.js +2 -0
  218. package/dist/types.js.map +1 -0
  219. package/dist/utils/MemmaError.d.ts +4 -0
  220. package/dist/utils/MemmaError.d.ts.map +1 -0
  221. package/dist/utils/MemmaError.js +6 -0
  222. package/dist/utils/MemmaError.js.map +1 -0
  223. package/dist/utils/config/getMemmaConfig.d.ts +3 -0
  224. package/dist/utils/config/getMemmaConfig.d.ts.map +1 -0
  225. package/dist/utils/config/getMemmaConfig.js +12 -0
  226. package/dist/utils/config/getMemmaConfig.js.map +1 -0
  227. package/dist/utils/config/saveMemmaConfig.d.ts +3 -0
  228. package/dist/utils/config/saveMemmaConfig.d.ts.map +1 -0
  229. package/dist/utils/config/saveMemmaConfig.js +7 -0
  230. package/dist/utils/config/saveMemmaConfig.js.map +1 -0
  231. package/dist/utils/consoleMessages.d.ts +2 -0
  232. package/dist/utils/consoleMessages.d.ts.map +1 -0
  233. package/dist/utils/consoleMessages.js +2 -0
  234. package/dist/utils/consoleMessages.js.map +1 -0
  235. package/dist/utils/getMemmaScriptPath.d.ts +2 -0
  236. package/dist/utils/getMemmaScriptPath.d.ts.map +1 -0
  237. package/dist/utils/getMemmaScriptPath.js +6 -0
  238. package/dist/utils/getMemmaScriptPath.js.map +1 -0
  239. package/dist/utils/getPidOnPort.d.ts +2 -0
  240. package/dist/utils/getPidOnPort.d.ts.map +1 -0
  241. package/dist/utils/getPidOnPort.js +36 -0
  242. package/dist/utils/getPidOnPort.js.map +1 -0
  243. package/dist/utils/llm/validateAPIKey.d.ts +4 -0
  244. package/dist/utils/llm/validateAPIKey.d.ts.map +1 -0
  245. package/dist/utils/llm/validateAPIKey.js +46 -0
  246. package/dist/utils/llm/validateAPIKey.js.map +1 -0
  247. package/dist/utils/logger.d.ts +20 -0
  248. package/dist/utils/logger.d.ts.map +1 -0
  249. package/dist/utils/logger.js +91 -0
  250. package/dist/utils/logger.js.map +1 -0
  251. package/dist/utils/logo.d.ts +2 -0
  252. package/dist/utils/logo.d.ts.map +1 -0
  253. package/dist/utils/logo.js +32 -0
  254. package/dist/utils/logo.js.map +1 -0
  255. package/dist/utils/paths.d.ts +3 -0
  256. package/dist/utils/paths.d.ts.map +1 -0
  257. package/dist/utils/paths.js +11 -0
  258. package/dist/utils/paths.js.map +1 -0
  259. package/dist/utils/prompts.d.ts +4 -0
  260. package/dist/utils/prompts.d.ts.map +1 -0
  261. package/dist/utils/prompts.js +34 -0
  262. package/dist/utils/prompts.js.map +1 -0
  263. package/dist/utils/resolveDirectory.d.ts +2 -0
  264. package/dist/utils/resolveDirectory.d.ts.map +1 -0
  265. package/dist/utils/resolveDirectory.js +18 -0
  266. package/dist/utils/resolveDirectory.js.map +1 -0
  267. package/dist/utils/resolveOrchestratorState.d.ts +3 -0
  268. package/dist/utils/resolveOrchestratorState.d.ts.map +1 -0
  269. package/dist/utils/resolveOrchestratorState.js +32 -0
  270. package/dist/utils/resolveOrchestratorState.js.map +1 -0
  271. package/dist/utils/typeGuards.d.ts +8 -0
  272. package/dist/utils/typeGuards.d.ts.map +1 -0
  273. package/dist/utils/typeGuards.js +69 -0
  274. package/dist/utils/typeGuards.js.map +1 -0
  275. package/dist/utils/wait.d.ts +2 -0
  276. package/dist/utils/wait.d.ts.map +1 -0
  277. package/dist/utils/wait.js +22 -0
  278. package/dist/utils/wait.js.map +1 -0
  279. package/package.json +56 -0
  280. package/python/__init__.py +0 -0
  281. package/python/agents/coordinator_agent.py +28 -0
  282. package/python/agents/generator_agent.py +7 -0
  283. package/python/generate/__init__.py +0 -0
  284. package/python/generate/generate_from_url.py +53 -0
  285. package/python/graphs/__init__.py +0 -0
  286. package/python/graphs/memma_graph.py +46 -0
  287. package/python/main.py +75 -0
  288. package/python/nodes/__init__.py +0 -0
  289. package/python/nodes/coordinator_node.py +89 -0
  290. package/python/nodes/generate_node.py +72 -0
  291. package/python/nodes/screenshot_node.py +40 -0
  292. package/python/schemas/__init__.py +5 -0
  293. package/python/schemas/types.py +14 -0
  294. package/python/states/memma_state.py +27 -0
  295. package/python/tools/__init__.py +0 -0
  296. package/python/tools/generate_components.py +9 -0
  297. package/python/tools/generate_screenshot_path.py +39 -0
  298. package/python/tools/inspect_site.py +52 -0
  299. package/python/utils/clean_json_response.py +26 -0
  300. package/python/utils/encode_base64.py +27 -0
  301. package/python/utils/format_image_content.py +40 -0
  302. package/python/utils/llm_loader.py +33 -0
  303. package/python/utils/mime_types.py +8 -0
  304. package/python/utils/prompts.py +8 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,2CAA2C;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAE1D,MAAM,UAAU,WAAW,CAAC,GAAG,QAAkB;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const promptLLMProviderSelection: () => Promise<string>;
2
+ export declare const promptLLMProviderAPIKey: (provider: string) => Promise<string>;
3
+ export declare const confirmMemmaReset: () => Promise<boolean>;
4
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,0BAA0B,uBAWtC,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAU,UAAU,MAAM,oBAW7D,CAAC;AAEF,eAAO,MAAM,iBAAiB,wBAM7B,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { select, confirm, password } from '@inquirer/prompts';
2
+ import { validateAPIKey } from './llm/validateAPIKey.js';
3
+ import { CONFIRM_THEME, PASSWORD_THEME, SELECT_THEME, SUPPORTED_LLMS, } from '../constants.js';
4
+ export const promptLLMProviderSelection = async () => {
5
+ return await select({
6
+ message: 'Which LLM provider would you like to use?',
7
+ choices: Object.entries(SUPPORTED_LLMS).map(([provider, details]) => {
8
+ return {
9
+ name: details.display,
10
+ value: provider,
11
+ };
12
+ }),
13
+ theme: SELECT_THEME,
14
+ });
15
+ };
16
+ export const promptLLMProviderAPIKey = async (provider) => {
17
+ return await password({
18
+ message: `Please enter your ${provider} API key:`,
19
+ mask: '*',
20
+ validate: async (key) => {
21
+ const validKey = await validateAPIKey(provider, key);
22
+ return validKey ? true : `Not a valid ${provider} API key.`;
23
+ },
24
+ theme: PASSWORD_THEME,
25
+ });
26
+ };
27
+ export const confirmMemmaReset = async () => {
28
+ return await confirm({
29
+ message: 'Reset all configurations for Memma?',
30
+ default: false,
31
+ theme: CONFIRM_THEME,
32
+ });
33
+ };
34
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EACL,aAAa,EACb,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,iBAAiB,CAAC;AAEzB,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,IAAI,EAAE;IACnD,OAAO,MAAM,MAAM,CAAC;QAClB,OAAO,EAAE,2CAA2C;QACpD,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE;YAClE,OAAO;gBACL,IAAI,EAAE,OAAO,CAAC,OAAO;gBACrB,KAAK,EAAE,QAAQ;aAChB,CAAC;QACJ,CAAC,CAAC;QACF,KAAK,EAAE,YAAY;KACpB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE;IAChE,OAAO,MAAM,QAAQ,CAAC;QACpB,OAAO,EAAE,qBAAqB,QAAQ,WAAW;QACjD,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,KAAK,EAAE,GAAW,EAA0B,EAAE;YACtD,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAErD,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,QAAQ,WAAW,CAAC;QAC9D,CAAC;QACD,KAAK,EAAE,cAAc;KACtB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;IAC1C,OAAO,MAAM,OAAO,CAAC;QACnB,OAAO,EAAE,qCAAqC;QAC9C,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,aAAa;KACrB,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function resolveDirectory(targetDir?: string): string;
2
+ //# sourceMappingURL=resolveDirectory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveDirectory.d.ts","sourceRoot":"","sources":["../../src/utils/resolveDirectory.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,SAAS,GAAE,MAAY,GAAG,MAAM,CAchE"}
@@ -0,0 +1,18 @@
1
+ import path from 'path';
2
+ import os from 'os';
3
+ // Resolves a specified directory to an absolute path
4
+ // Ex: ./todoList -> /Users/FooBar/Projects/todoList
5
+ export function resolveDirectory(targetDir = '.') {
6
+ // 1. Expand tilde (~)
7
+ if (targetDir.startsWith('~')) {
8
+ const home = os.homedir();
9
+ targetDir = targetDir === '~' ? home : path.join(home, targetDir.slice(2)); // slice removes "~/"
10
+ }
11
+ // 2. Return absolute path as-is
12
+ if (path.isAbsolute(targetDir)) {
13
+ return path.normalize(targetDir);
14
+ }
15
+ // 3. Resolve relative path from current working directory
16
+ return path.resolve(process.cwd(), targetDir);
17
+ }
18
+ //# sourceMappingURL=resolveDirectory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveDirectory.js","sourceRoot":"","sources":["../../src/utils/resolveDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,qDAAqD;AACrD,oDAAoD;AACpD,MAAM,UAAU,gBAAgB,CAAC,YAAoB,GAAG;IACtD,sBAAsB;IACtB,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC1B,SAAS,GAAG,SAAS,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB;IACnG,CAAC;IAED,gCAAgC;IAChC,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,0DAA0D;IAC1D,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { OrchestratorState } from '../types.js';
2
+ export declare function resolveOrchestratorState(): Promise<OrchestratorState>;
3
+ //# sourceMappingURL=resolveOrchestratorState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveOrchestratorState.d.ts","sourceRoot":"","sources":["../../src/utils/resolveOrchestratorState.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CA+B3E"}
@@ -0,0 +1,32 @@
1
+ import { MEMMA_ORCHESTRATOR_PORT } from '../constants.js';
2
+ import { getMemmaConfig } from './config/getMemmaConfig.js';
3
+ import { saveMemmaConfig } from './config/saveMemmaConfig.js';
4
+ import { getPidOnPort } from './getPidOnPort.js';
5
+ export async function resolveOrchestratorState() {
6
+ const config = await getMemmaConfig();
7
+ const currentPid = await getPidOnPort(MEMMA_ORCHESTRATOR_PORT); // PID found on port 23224
8
+ const configPid = config.orchestratorPid; // PID found on memma.config.file
9
+ // Config and port agree: orchestrator is running as expected
10
+ if (configPid && currentPid === configPid) {
11
+ return { state: 'RUNNING', pid: currentPid, config };
12
+ }
13
+ // No config PID, but port is active: typically another process is occupying the port
14
+ if (!configPid && currentPid) {
15
+ return { state: 'UNKNOWN_RUNNING', pid: currentPid, config };
16
+ }
17
+ // Config PID exists and port has a process, but they do not match: unsafe mismatch
18
+ if (configPid && currentPid && configPid !== currentPid) {
19
+ delete config.orchestratorPid; // Deletes recorded PID in config file
20
+ await saveMemmaConfig(config);
21
+ return { state: 'UNKNOWN_RUNNING', pid: currentPid, config };
22
+ }
23
+ // Config claims a PID, but no process is actually running: stale config
24
+ if (configPid && !currentPid) {
25
+ delete config.orchestratorPid; // Deletes recorded PID in config file
26
+ await saveMemmaConfig(config);
27
+ return { state: 'NOT_RUNNING', pid: null, config };
28
+ }
29
+ // Nothing running, no stale config: clean state
30
+ return { state: 'NOT_RUNNING', pid: null, config };
31
+ }
32
+ //# sourceMappingURL=resolveOrchestratorState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveOrchestratorState.js","sourceRoot":"","sources":["../../src/utils/resolveOrchestratorState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,uBAAuB,CAAC,CAAC,CAAC,0BAA0B;IAC1F,MAAM,SAAS,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC,iCAAiC;IAE3E,6DAA6D;IAC7D,IAAI,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IACvD,CAAC;IAED,qFAAqF;IACrF,IAAI,CAAC,SAAS,IAAI,UAAU,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAC/D,CAAC;IAED,mFAAmF;IACnF,IAAI,SAAS,IAAI,UAAU,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QACxD,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC,sCAAsC;QACrE,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAC/D,CAAC;IAED,wEAAwE;IACxE,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC,sCAAsC;QACrE,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;IAED,gDAAgD;IAChD,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ExecaError } from 'execa';
2
+ import { NotRunningOrchestratorState, OrchestratorState, RunningOrchestratorState } from '../types.js';
3
+ export declare const isExecaError: (err: unknown) => err is ExecaError;
4
+ export declare const isNoProcessFoundError: (err: unknown) => boolean;
5
+ export declare function orchestratorIsRunning(orchestratorState: OrchestratorState): orchestratorState is RunningOrchestratorState;
6
+ export declare function assertOrchestratorIsRunning(orchestratorState: OrchestratorState): asserts orchestratorState is RunningOrchestratorState;
7
+ export declare function assertOrchestratorIsNotRunning(orchestratorState: OrchestratorState): asserts orchestratorState is NotRunningOrchestratorState;
8
+ //# sourceMappingURL=typeGuards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeGuards.d.ts","sourceRoot":"","sources":["../../src/utils/typeGuards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,aAAa,CAAC;AAMrB,eAAO,MAAM,YAAY,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,UAOlD,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,KAAK,OAAO,YAOjD,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,iBAAiB,EAAE,iBAAiB,GACnC,iBAAiB,IAAI,wBAAwB,CAiB/C;AAED,wBAAgB,2BAA2B,CACzC,iBAAiB,EAAE,iBAAiB,GACnC,OAAO,CAAC,iBAAiB,IAAI,wBAAwB,CAmBvD;AAED,wBAAgB,8BAA8B,CAC5C,iBAAiB,EAAE,iBAAiB,GACnC,OAAO,CAAC,iBAAiB,IAAI,2BAA2B,CAqB1D"}
@@ -0,0 +1,69 @@
1
+ import { MEMMA_ORCHESTRATOR_PORT } from '../constants.js';
2
+ import { MemmaError } from './MemmaError.js';
3
+ // "execa" package throws error to indicate package not found
4
+ // This type guard checks if the error is from execa and indicates package not found
5
+ export const isExecaError = (err) => {
6
+ return (err instanceof Error &&
7
+ 'exitCode' in err &&
8
+ err.exitCode === 1 &&
9
+ typeof err.exitCode === 'number');
10
+ };
11
+ // lsof exited with code 1 → no process found on port
12
+ export const isNoProcessFoundError = (err) => {
13
+ return (typeof err === 'object' &&
14
+ err !== null &&
15
+ 'exitCode' in err &&
16
+ err.exitCode === 1);
17
+ };
18
+ export function orchestratorIsRunning(orchestratorState) {
19
+ const { state } = orchestratorState;
20
+ switch (state) {
21
+ case 'RUNNING': {
22
+ return true;
23
+ }
24
+ case 'UNKNOWN_RUNNING': {
25
+ return true;
26
+ }
27
+ case 'NOT_RUNNING': {
28
+ return false;
29
+ }
30
+ default: {
31
+ throw new MemmaError('Unknown orchestrator state.');
32
+ }
33
+ }
34
+ }
35
+ export function assertOrchestratorIsRunning(orchestratorState) {
36
+ const { state, pid } = orchestratorState;
37
+ switch (state) {
38
+ case 'RUNNING': {
39
+ return;
40
+ }
41
+ case 'UNKNOWN_RUNNING': {
42
+ throw new MemmaError(`Port ${MEMMA_ORCHESTRATOR_PORT} in use by another process. Check process #${pid}`);
43
+ }
44
+ case 'NOT_RUNNING': {
45
+ throw new MemmaError('Memma orchestrator server not running');
46
+ }
47
+ default: {
48
+ throw new MemmaError('Unknown orchestrator state.');
49
+ }
50
+ }
51
+ }
52
+ export function assertOrchestratorIsNotRunning(orchestratorState) {
53
+ const { state, pid } = orchestratorState;
54
+ switch (state) {
55
+ case 'RUNNING': {
56
+ throw new MemmaError(`Orchestrator running on port ${MEMMA_ORCHESTRATOR_PORT} - PID #${pid}`);
57
+ }
58
+ case 'UNKNOWN_RUNNING': {
59
+ throw new MemmaError(`Port ${MEMMA_ORCHESTRATOR_PORT} in use by another process. Check process #${pid}`);
60
+ }
61
+ case 'NOT_RUNNING': {
62
+ return;
63
+ }
64
+ default: {
65
+ throw new MemmaError('Unknown orchestrator state.');
66
+ }
67
+ }
68
+ }
69
+ //# sourceMappingURL=typeGuards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeGuards.js","sourceRoot":"","sources":["../../src/utils/typeGuards.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,6DAA6D;AAC7D,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAY,EAAqB,EAAE;IAC9D,OAAO,CACL,GAAG,YAAY,KAAK;QACpB,UAAU,IAAI,GAAG;QACjB,GAAG,CAAC,QAAQ,KAAK,CAAC;QAClB,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CACjC,CAAC;AACJ,CAAC,CAAC;AAEF,qDAAqD;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAY,EAAE,EAAE;IACpD,OAAO,CACL,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACZ,UAAU,IAAI,GAAG;QAChB,GAA6B,CAAC,QAAQ,KAAK,CAAC,CAC9C,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,UAAU,qBAAqB,CACnC,iBAAoC;IAEpC,MAAM,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC;IAEpC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,iBAAoC;IAEpC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,iBAAiB,CAAC;IAEzC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,UAAU,CAClB,QAAQ,uBAAuB,8CAA8C,GAAG,EAAE,CACnF,CAAC;QACJ,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,iBAAoC;IAEpC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,iBAAiB,CAAC;IAEzC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,IAAI,UAAU,CAClB,gCAAgC,uBAAuB,WAAW,GAAG,EAAE,CACxE,CAAC;QACJ,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,UAAU,CAClB,QAAQ,uBAAuB,8CAA8C,GAAG,EAAE,CACnF,CAAC;QACJ,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function waitAsyncOperation<T>(callbackFn: (...args: any[]) => Promise<T>, callbackArgs: any[], startMsg: string | ((...args: any[]) => string), endMsg: string | ((result: T) => string)): Promise<T>;
2
+ //# sourceMappingURL=wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../src/utils/wait.ts"],"names":[],"mappings":"AAGA,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,YAAY,EAAE,GAAG,EAAE,EACnB,QAAQ,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,EAC/C,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC,GACvC,OAAO,CAAC,CAAC,CAAC,CAuBZ"}
@@ -0,0 +1,22 @@
1
+ import ora from 'ora';
2
+ import { primary } from './logger.js';
3
+ export async function waitAsyncOperation(callbackFn, callbackArgs, startMsg, endMsg) {
4
+ // Resolve start message if it's a function
5
+ const startMessage = typeof startMsg === 'function' ? startMsg(...callbackArgs) : startMsg;
6
+ const spinner = ora(startMessage).start();
7
+ try {
8
+ const result = await callbackFn(...callbackArgs);
9
+ // Resolve end message if it's a function
10
+ const endMessage = typeof endMsg === 'function' ? endMsg(result) : endMsg;
11
+ spinner.stopAndPersist({
12
+ symbol: primary('✔'),
13
+ text: endMessage,
14
+ });
15
+ return result;
16
+ }
17
+ catch (err) {
18
+ spinner.fail('Operation failed');
19
+ throw err;
20
+ }
21
+ }
22
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/utils/wait.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAA0C,EAC1C,YAAmB,EACnB,QAA+C,EAC/C,MAAwC;IAExC,2CAA2C;IAC3C,MAAM,YAAY,GAChB,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAExE,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,KAAK,EAAE,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,YAAY,CAAC,CAAC;QAEjD,yCAAyC;QACzC,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAE1E,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC;YACpB,IAAI,EAAE,UAAU;SACjB,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACjC,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "memma",
3
+ "version": "0.1.0",
4
+ "description": "Visual-to-Code CLI Tool",
5
+ "keywords": [
6
+ "cli",
7
+ "codegen",
8
+ "ai",
9
+ "agent",
10
+ "visual-to-code"
11
+ ],
12
+ "main": "./dist/cli.js",
13
+ "bin": {
14
+ "memma": "./dist/cli.js"
15
+ },
16
+ "type": "module",
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "start": "ts-node src/cli.ts",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "python"
25
+ ],
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "@anthropic-ai/sdk": "^0.65.0",
29
+ "@inquirer/prompts": "^7.8.6",
30
+ "chalk": "^5.6.2",
31
+ "commander": "^14.0.1",
32
+ "eventsource-parser": "^3.0.6",
33
+ "execa": "^9.6.0",
34
+ "fs-extra": "^11.3.2",
35
+ "gradient-string": "^3.0.0",
36
+ "openai": "^6.2.0",
37
+ "ora": "^9.0.0",
38
+ "semver": "^7.7.2"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/6207als/memma"
43
+ },
44
+ "devDependencies": {
45
+ "@types/commander": "^2.12.0",
46
+ "@types/fs-extra": "^11.0.4",
47
+ "@types/node": "^24.5.0",
48
+ "@types/semver": "^7.7.1",
49
+ "@typescript-eslint/eslint-plugin": "^8.44.0",
50
+ "@typescript-eslint/parser": "^8.44.0",
51
+ "eslint-config-prettier": "^10.1.8",
52
+ "prettier": "^3.6.2",
53
+ "ts-node": "^10.9.2",
54
+ "typescript": "^5.9.2"
55
+ }
56
+ }
File without changes
@@ -0,0 +1,28 @@
1
+ from utils.llm_loader import llm
2
+
3
+ from tools.generate_components import generate_components_tool
4
+ from tools.inspect_site import take_screenshot_tool
5
+
6
+ def create_coordinator_agent():
7
+ """
8
+ Creates the coordinator agent that decides workflow steps.
9
+ This agent ONLY reasons about what to do next.
10
+ """
11
+ system_prompt = """You are a workflow coordinator for Memma, a website replication system.
12
+
13
+ Your job is to analyze the user's request, decide which tool should be called, and call it.
14
+
15
+ Determine which of the following tools should be called and call it:
16
+ - take_screenshot_tool(url) if you need to capture a website screenshot
17
+ - generate_components_tool() if you have a screenshot and need to generate code
18
+
19
+ Otherwise, say "DONE" if the task is complete.
20
+
21
+ You do NOT generate components or analyze screenshots yourself. You only call the tools."""
22
+
23
+ llm_with_tools = llm.bind_tools(
24
+ [take_screenshot_tool, generate_components_tool],
25
+ tool_choice="auto" # Let model decide
26
+ )
27
+
28
+ return llm_with_tools, system_prompt
@@ -0,0 +1,7 @@
1
+ from utils.llm_loader import llm
2
+
3
+ def create_generator_agent():
4
+ """
5
+ Creates a specialist agent for component generation.
6
+ """
7
+ return llm
File without changes
@@ -0,0 +1,53 @@
1
+ from graphs.memma_graph import create_memma_graph
2
+ from states.memma_state import MemmaState
3
+ from utils.encode_base64 import encode_to_base64_from_path
4
+ from utils.prompts import generate_main_prompt
5
+ from schemas.types import GenerateRequestOptions
6
+ from typing import AsyncGenerator, Any, Union
7
+
8
+ async def generate_from_url(url: str, options: GenerateRequestOptions) -> AsyncGenerator[Union[str, dict[str, Any]], None]:
9
+ """
10
+ Execute the coordinator-specialist workflow.
11
+
12
+ Args:
13
+ url: URL (or image file path) of website to replicate
14
+ prompt: Optional custom prompt
15
+
16
+ Returns:
17
+ List of generated components
18
+ """
19
+
20
+ image_data = None
21
+
22
+ if options.localFile:
23
+ image_data = encode_to_base64_from_path(url)
24
+
25
+ # Create the graph / Future: persist graph instance between calls
26
+ graph = create_memma_graph()
27
+
28
+ # Initial state
29
+ initial_state = MemmaState({
30
+ "original_prompt": generate_main_prompt(url),
31
+ "url": url,
32
+ "next_action": "start",
33
+ "image_data": image_data,
34
+ "messages": [],
35
+ "components": []
36
+ })
37
+
38
+ final_state = None
39
+
40
+ async for mode, chunk in graph.astream(initial_state, stream_mode=["custom", "values"]):
41
+ # yield progress/status updates as they come
42
+ if mode == 'values':
43
+ final_state = chunk
44
+ elif mode == 'custom':
45
+ yield chunk
46
+
47
+ # Graph reached END → emit final "done" event
48
+ yield {
49
+ "event": "done",
50
+ "message": "Workflow completed successfully.",
51
+ "llmResponse": final_state["components"] # type: ignore
52
+ }
53
+
File without changes
@@ -0,0 +1,46 @@
1
+ from langgraph.graph import StateGraph, END
2
+ from states.memma_state import MemmaState, ActionState
3
+ from nodes.coordinator_node import coordinator_node
4
+ from nodes.screenshot_node import screenshot_node
5
+ from nodes.generate_node import generator_node
6
+
7
+ def router(state: MemmaState) -> ActionState:
8
+ """
9
+ Routes to the appropriate specialist based on coordinator's decision.
10
+ """
11
+ return state["next_action"]
12
+
13
+
14
+ def create_memma_graph():
15
+ """
16
+ Creates the LangGraph workflow with coordinator-specialist pattern.
17
+
18
+ Graph flow:
19
+ Entry → Coordinator → Router → Specialist → Coordinator → ... → END
20
+ """
21
+ workflow = StateGraph(MemmaState)
22
+
23
+ # Add nodes
24
+ workflow.add_node("coordinator", coordinator_node)
25
+ workflow.add_node("take_screenshot", screenshot_node)
26
+ workflow.add_node("generate_components", generator_node)
27
+
28
+ # Entry point
29
+ workflow.set_entry_point("coordinator")
30
+
31
+ # Coordinator routes to tools/agents or finishes
32
+ workflow.add_conditional_edges(
33
+ "coordinator",
34
+ router,
35
+ {
36
+ "take_screenshot": "take_screenshot",
37
+ "generate_components": "generate_components",
38
+ "finish": END
39
+ }
40
+ )
41
+
42
+ # After each tool, go back to coordinator to determine next steps
43
+ workflow.add_edge("take_screenshot", "coordinator")
44
+ workflow.add_edge("generate_components", "coordinator")
45
+
46
+ return workflow.compile()
package/python/main.py ADDED
@@ -0,0 +1,75 @@
1
+ # type: ignore
2
+
3
+ import datetime
4
+ from pathlib import Path
5
+
6
+ from fastapi import FastAPI
7
+ from fastapi.responses import StreamingResponse
8
+ from pydantic import BaseModel
9
+ import traceback
10
+ import uvicorn
11
+ import json
12
+ import sys
13
+
14
+ from schemas.types import GenerateRequestOptions
15
+ from generate.generate_from_url import generate_from_url
16
+
17
+ app = FastAPI()
18
+
19
+ # Request Model
20
+ class GenerateRequest(BaseModel):
21
+ url: str # URL or local file path
22
+ options: GenerateRequestOptions
23
+
24
+ class GenerateResponse(BaseModel):
25
+ success: bool
26
+ llmResponse: str
27
+ message: str = None
28
+
29
+ @app.post("/generate", response_model=GenerateResponse)
30
+ async def generate_components(req: GenerateRequest):
31
+ """
32
+ Generate React components of a UI using a lightweight multi-agent workflow.
33
+
34
+ The system primarily uses coordinator-specialist pattern:
35
+ 1. Coordinator agent decides which tools/node to call: screenshot_node or generate_node
36
+ 2. Screenshot node captures the website
37
+ 3. Generator nodes creates components using screenshot data and clean context
38
+ """
39
+
40
+ async def event_stream():
41
+ stream_finished = False
42
+ try:
43
+ # Iterate over each chunk yielded by the async generator
44
+ async for update in generate_from_url(req.url, req.options):
45
+ # Send chunk as SSE
46
+ yield f"event: event\ndata: {json.dumps(update)}\n\n"
47
+
48
+ # Fallback: yield a final "done" signal (if generate_from_url doesn’t do it)
49
+ if update.get("event") == "done":
50
+ stream_finished = True
51
+
52
+ except Exception as e:
53
+ tb = traceback.format_exc()
54
+ error_payload = {
55
+ "event": "error",
56
+ "message": str(e),
57
+ "traceback": tb,
58
+ }
59
+ yield f"data: {json.dumps(error_payload)}\n\n"
60
+
61
+ finally:
62
+ # Fallback if "done" event isn't sent
63
+ if not stream_finished:
64
+ yield "event: event\ndata: {\"event\": \"done\"}\n\n"
65
+
66
+ # Return streaming response with text/event-stream media type
67
+ return StreamingResponse(event_stream(), media_type="text/event-stream")
68
+
69
+ @app.get("/health")
70
+ def health_check():
71
+ return {"status": "healthy"}
72
+
73
+ if __name__ == "__main__":
74
+ port = int(sys.argv[1]) if len(sys.argv) > 1 else 5000
75
+ uvicorn.run(app, host="127.0.0.1", port=port)
File without changes
@@ -0,0 +1,89 @@
1
+ from agents.coordinator_agent import create_coordinator_agent
2
+ from langgraph.config import get_stream_writer
3
+ from langchain_core.messages import AIMessage
4
+ from states.memma_state import MemmaState
5
+
6
+ def coordinator_node(state: MemmaState) -> MemmaState:
7
+ """
8
+ Coordinator node that analyzes state and decides next action.
9
+ """
10
+ # initialize StreamWriter if graph is configured to stream
11
+ writer = get_stream_writer()
12
+
13
+ coordinator, system_prompt = create_coordinator_agent()
14
+
15
+ # Build status message
16
+ has_image = bool(state.get('image_data'))
17
+ has_components = bool(state.get('components'))
18
+
19
+ status = f"""Task: {state['original_prompt']}
20
+ URL: {state.get('url', 'Not provided')}
21
+
22
+ Current Status:
23
+ - Screenshot: {'Has been captured' if has_image else 'Not yet captured'}
24
+ - Components: {'Have been generated' if has_components else 'Not yet generated'}
25
+
26
+ What should we do next?"""
27
+
28
+ if writer:
29
+ writer({
30
+ "event": "status",
31
+ "task": "reasoning",
32
+ "progress": "in progress",
33
+ "message": "Thinking..."
34
+ })
35
+
36
+ result = coordinator.invoke([
37
+ {"role": "system", "content": system_prompt},
38
+ {"role": "user", "content": status}
39
+ ])
40
+
41
+ # Check which tool has been called, update "next_action" graph state appropriately
42
+ if isinstance(result, AIMessage) and result.tool_calls:
43
+ tool_call = result.tool_calls[0]
44
+
45
+ if tool_call['name'] == 'take_screenshot_tool':
46
+ url = tool_call['args'].get('url') or state.get('url')
47
+
48
+ if writer:
49
+ writer({
50
+ "event": "status",
51
+ "task": "reasoning",
52
+ "progress": "complete",
53
+ "message": "Decision: Take screenshot of website"
54
+ })
55
+
56
+ return {
57
+ **state,
58
+ "next_action": "take_screenshot",
59
+ "url": url
60
+ }
61
+
62
+ elif tool_call['name'] == 'generate_components_tool':
63
+
64
+ if writer:
65
+ writer({
66
+ "event": "status",
67
+ "task": "reasoning",
68
+ "progress": "complete",
69
+ "message": "Decision: Generate components"
70
+ })
71
+
72
+ return {
73
+ **state,
74
+ "next_action": "generate_components"
75
+ }
76
+
77
+ # No tool call means we're done
78
+ if writer:
79
+ writer({
80
+ "event": "status",
81
+ "task": "reasoning",
82
+ "progress": "complete",
83
+ "message": "Finished"
84
+ })
85
+
86
+ return {
87
+ **state,
88
+ "next_action": "finish"
89
+ }