abstra 3.23.12__py3-none-any.whl → 3.24.1__py3-none-any.whl

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 (266) hide show
  1. abstra/cli.py +16 -5
  2. {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/METADATA +1 -1
  3. {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/RECORD +200 -190
  4. abstra_internals/cloud_api/__init__.py +17 -8
  5. abstra_internals/consts/filepaths.py +1 -1
  6. abstra_internals/contracts_generated.py +616 -596
  7. abstra_internals/controllers/ai.py +89 -1
  8. abstra_internals/controllers/git.py +307 -0
  9. abstra_internals/controllers/main.py +10 -6
  10. abstra_internals/environment.py +6 -0
  11. abstra_internals/interface/cli/deploy.py +1 -1
  12. abstra_internals/interface/cli/editor.py +2 -2
  13. abstra_internals/interface/sdk/ai.py +1 -0
  14. abstra_internals/repositories/git/__init__.py +25 -0
  15. abstra_internals/repositories/git/git_test.py +362 -0
  16. abstra_internals/repositories/git/native.py +578 -0
  17. abstra_internals/repositories/git/types.py +273 -0
  18. abstra_internals/repositories/linter/rules/env_in_bundle.py +5 -5
  19. abstra_internals/repositories/linter/rules/env_in_bundle_test.py +6 -6
  20. abstra_internals/repositories/linter/rules/venv_in_bundle.py +9 -16
  21. abstra_internals/server/blueprints/editor.py +4 -0
  22. abstra_internals/server/routes/git.py +190 -0
  23. abstra_internals/server/routes/workspace.py +1 -1
  24. abstra_internals/services/file_watcher.py +32 -13
  25. abstra_internals/services/fs.py +4 -4
  26. abstra_internals/services/fs_test.py +4 -6
  27. abstra_internals/templates/__init__.py +0 -11
  28. abstra_statics/dist/assets/{AbstraButton.vue_vue_type_script_setup_true_lang.441fcdfd.js → AbstraButton.vue_vue_type_script_setup_true_lang.aefce2d3.js} +2 -2
  29. abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.28bc9fc9.js +2 -0
  30. abstra_statics/dist/assets/ApiKeys.3c1e70dc.js +2 -0
  31. abstra_statics/dist/assets/App.9d8bd2aa.js +2 -0
  32. abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.a64c7cee.js +2 -0
  33. abstra_statics/dist/assets/{BaseLayout.c63dfc2d.js → BaseLayout.72a6c8f2.js} +2 -2
  34. abstra_statics/dist/assets/{Billing.461db3ef.js → Billing.6b07f282.js} +2 -2
  35. abstra_statics/dist/assets/{Breadcrumb.27110ec4.js → Breadcrumb.5c786c09.js} +2 -2
  36. abstra_statics/dist/assets/{Builds.4eecd717.js → Builds.d8c5c61b.js} +2 -2
  37. abstra_statics/dist/assets/{Card.1d1a9fb7.js → Card.fc77085c.js} +2 -2
  38. abstra_statics/dist/assets/{CircularLoading.fc66331b.js → CircularLoading.998b223a.js} +2 -2
  39. abstra_statics/dist/assets/{CloseCircleOutlined.0110bbe2.js → CloseCircleOutlined.9ff269cc.js} +2 -2
  40. abstra_statics/dist/assets/{ConnectorsView.82e74ae4.css → ConnectorsView.33c5380f.css} +1 -1
  41. abstra_statics/dist/assets/ConnectorsView.e670738b.js +2 -0
  42. abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.3ca66327.js +2 -0
  43. abstra_statics/dist/assets/ContentLayout.0db8d7fb.js +2 -0
  44. abstra_statics/dist/assets/{CrudView.c16e2f81.js → CrudView.cc6aeaf0.js} +2 -2
  45. abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.689d8ce7.js +2 -0
  46. abstra_statics/dist/assets/{EditorLogin.00a3b3d9.js → EditorLogin.691452b4.js} +2 -2
  47. abstra_statics/dist/assets/{EditorsView.f7b2843c.js → EditorsView.fcdf0186.js} +2 -2
  48. abstra_statics/dist/assets/EnvVars.5519b4ce.js +2 -0
  49. abstra_statics/dist/assets/Error.11fd1f21.js +2 -0
  50. abstra_statics/dist/assets/ExclamationCircleOutlined.d0aa47da.js +2 -0
  51. abstra_statics/dist/assets/Files.6ea18d46.js +2 -0
  52. abstra_statics/dist/assets/{Form.8077681f.js → Form.09de384c.js} +2 -2
  53. abstra_statics/dist/assets/{FormRunner.055e2c45.js → FormRunner.15be6fa0.js} +2 -2
  54. abstra_statics/dist/assets/{Home.0ef22910.js → Home.782c5702.js} +2 -2
  55. abstra_statics/dist/assets/Home.7c495aa9.js +2 -0
  56. abstra_statics/dist/assets/{Live.e1261458.js → Live.48c10605.js} +2 -2
  57. abstra_statics/dist/assets/LoadingContainer.82ac3d44.js +2 -0
  58. abstra_statics/dist/assets/LoadingOutlined.66639b08.js +2 -0
  59. abstra_statics/dist/assets/Login.4a05f5c5.js +2 -0
  60. abstra_statics/dist/assets/{Login.041361ea.js → Login.4e852955.js} +2 -2
  61. abstra_statics/dist/assets/{Login.vue_vue_type_script_setup_true_lang.c2eb444c.js → Login.vue_vue_type_script_setup_true_lang.5161f328.js} +2 -2
  62. abstra_statics/dist/assets/Logo.65e0b37c.js +2 -0
  63. abstra_statics/dist/assets/{Logs.f76cde12.js → Logs.7d1acf32.js} +2 -2
  64. abstra_statics/dist/assets/{LogsController.addd81bf.js → LogsController.0eb2eb30.js} +2 -2
  65. abstra_statics/dist/assets/Main.0313f4fc.js +2 -0
  66. abstra_statics/dist/assets/{MockForm.c9441864.js → MockForm.0b819a52.js} +2 -2
  67. abstra_statics/dist/assets/Navbar.ef64aa09.js +2 -0
  68. abstra_statics/dist/assets/NewEditor.b9c410fe.css +1 -0
  69. abstra_statics/dist/assets/NewEditor.c928dbe9.js +8 -0
  70. abstra_statics/dist/assets/OidcLoginCallback.42a7c4f9.js +2 -0
  71. abstra_statics/dist/assets/OidcLogoutCallback.35931a68.js +2 -0
  72. abstra_statics/dist/assets/OmniChat.73d9f6bb.js +6 -0
  73. abstra_statics/dist/assets/OmniChat.a21fec40.css +1 -0
  74. abstra_statics/dist/assets/{OnboardingView.fbc4b6fe.js → OnboardingView.25042384.js} +2 -2
  75. abstra_statics/dist/assets/{Organization.bc495099.js → Organization.66f64939.js} +2 -2
  76. abstra_statics/dist/assets/Organizations.47868beb.js +2 -0
  77. abstra_statics/dist/assets/{PhArrowCounterClockwise.vue.156bcd89.js → PhArrowCounterClockwise.vue.78877a50.js} +2 -2
  78. abstra_statics/dist/assets/{PhArrowSquareOut.vue.d0c95a06.js → PhArrowSquareOut.vue.2ddfc219.js} +2 -2
  79. abstra_statics/dist/assets/{PhBookBookmark.vue.42e49494.js → PhBookBookmark.vue.41108214.js} +2 -2
  80. abstra_statics/dist/assets/{PhChats.vue.54d692e4.js → PhChats.vue.71e5cb89.js} +2 -2
  81. abstra_statics/dist/assets/{PhClockCounterClockwise.vue.d47d66ba.js → PhClockCounterClockwise.vue.854c3cb5.js} +2 -2
  82. abstra_statics/dist/assets/{PhCopy.vue.a0d9b0ec.js → PhCopy.vue.d116ddfb.js} +2 -2
  83. abstra_statics/dist/assets/{PhCopySimple.vue.43c74ebe.js → PhCopySimple.vue.5d0f839d.js} +2 -2
  84. abstra_statics/dist/assets/{PhCube.vue.498c014d.js → PhCube.vue.abf4a034.js} +2 -2
  85. abstra_statics/dist/assets/PhDatabase.vue.a94d95f6.js +2 -0
  86. abstra_statics/dist/assets/{PhDotsThreeVertical.vue.0ea03d82.js → PhDotsThreeVertical.vue.5e8ae2a9.js} +2 -2
  87. abstra_statics/dist/assets/{PhDownloadSimple.vue.c92aeaff.js → PhDownloadSimple.vue.e88f64f1.js} +2 -2
  88. abstra_statics/dist/assets/{PhFolderPlus.vue.0c210f8d.js → PhFolderPlus.vue.21d377a3.js} +2 -2
  89. abstra_statics/dist/assets/{PhGear.vue.86c3014a.js → PhGear.vue.363dd83c.js} +2 -2
  90. abstra_statics/dist/assets/{PhKey.vue.72ce23d3.js → PhKey.vue.23f3a465.js} +2 -2
  91. abstra_statics/dist/assets/{PhPencil.vue.80ed4b2e.js → PhPencil.vue.feb383e2.js} +2 -2
  92. abstra_statics/dist/assets/{PhPencilSimple.vue.0046d784.js → PhPencilSimple.vue.ec0eebb4.js} +2 -2
  93. abstra_statics/dist/assets/{PhRocket.vue.f3302a7e.js → PhRocket.vue.261a42b2.js} +2 -2
  94. abstra_statics/dist/assets/{PhSignOut.vue.c9150da4.js → PhSignOut.vue.d1d6498f.js} +2 -2
  95. abstra_statics/dist/assets/{PhSparkle.vue.84ea95fc.js → PhSparkle.vue.b6712d34.js} +2 -2
  96. abstra_statics/dist/assets/{PhUserList.vue.bce47902.js → PhUserList.vue.e0b8c21b.js} +2 -2
  97. abstra_statics/dist/assets/{PhUsersThree.vue.0a84dfa4.js → PhUsersThree.vue.8889f957.js} +2 -2
  98. abstra_statics/dist/assets/PhWarningCircle.vue.2087be7d.js +2 -0
  99. abstra_statics/dist/assets/{PhWebhooksLogo.vue.a704632d.js → PhWebhooksLogo.vue.d164db1e.js} +2 -2
  100. abstra_statics/dist/assets/{PlayerConfigProvider.26b585a1.js → PlayerConfigProvider.28e29025.js} +2 -2
  101. abstra_statics/dist/assets/{PlayerNavbar.0fa6f760.js → PlayerNavbar.aaad1dfd.js} +2 -2
  102. abstra_statics/dist/assets/Project.2de506d7.js +2 -0
  103. abstra_statics/dist/assets/{ProjectLogin.934271a6.js → ProjectLogin.22c8b093.js} +2 -2
  104. abstra_statics/dist/assets/{ProjectSettings.2bf7e6c8.js → ProjectSettings.d065c292.js} +2 -2
  105. abstra_statics/dist/assets/{ProjectsView.ed31b921.js → ProjectsView.cbd118ac.js} +2 -2
  106. abstra_statics/dist/assets/{SaveButton.fdf70b31.js → SaveButton.428227de.js} +2 -2
  107. abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.6d724b05.js +2 -0
  108. abstra_statics/dist/assets/{Sidebar.e69f49bd.css → Sidebar.29baeab0.css} +1 -1
  109. abstra_statics/dist/assets/{Sidebar.781afa0a.js → Sidebar.41173d8e.js} +2 -2
  110. abstra_statics/dist/assets/Sql.90e6e2ba.css +1 -0
  111. abstra_statics/dist/assets/Sql.c070dd2c.js +5 -0
  112. abstra_statics/dist/assets/Steps.dd51a108.js +2 -0
  113. abstra_statics/dist/assets/TableCard.529112b9.css +1 -0
  114. abstra_statics/dist/assets/TableCard.c9a1cf41.js +2 -0
  115. abstra_statics/dist/assets/TableEditor.1bc47a95.js +2 -0
  116. abstra_statics/dist/assets/TableEditor.5853a363.css +1 -0
  117. abstra_statics/dist/assets/Tables.eff119eb.js +2 -0
  118. abstra_statics/dist/assets/TablesDiagram.a588e7ff.css +1 -0
  119. abstra_statics/dist/assets/TablesDiagram.d633acaf.js +15 -0
  120. abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.cf7e34c5.js +2 -0
  121. abstra_statics/dist/assets/{Tasks.ee450480.js → Tasks.c311b05f.js} +2 -2
  122. abstra_statics/dist/assets/{UploadOutlined.e3072945.js → UploadOutlined.9aa845de.js} +2 -2
  123. abstra_statics/dist/assets/View.dd7ba25a.js +2 -0
  124. abstra_statics/dist/assets/{View.vue_vue_type_script_setup_true_lang.ee5d447b.js → View.vue_vue_type_script_setup_true_lang.e6563207.js} +2 -2
  125. abstra_statics/dist/assets/{Watermark.891eee9f.js → Watermark.9c9358e3.js} +2 -2
  126. abstra_statics/dist/assets/{WebEditor.7409cd48.js → WebEditor.83f2a960.js} +2 -2
  127. abstra_statics/dist/assets/WidgetPreview.7c6a231c.js +2 -0
  128. abstra_statics/dist/assets/ant-design.42419021.js +2 -0
  129. abstra_statics/dist/assets/apiKey.403049eb.js +2 -0
  130. abstra_statics/dist/assets/asyncComputed.47aec2b5.js +2 -0
  131. abstra_statics/dist/assets/{build.8fa1a961.js → build.45b511b6.js} +2 -2
  132. abstra_statics/dist/assets/colorHelpers.50ced1e9.js +2 -0
  133. abstra_statics/dist/assets/console.f0f09e6f.js +17 -0
  134. abstra_statics/dist/assets/constants.d569f33d.js +2 -0
  135. abstra_statics/dist/assets/{contracts.generated.c4057ed0.js → contracts.generated.aefe8d0a.js} +2 -2
  136. abstra_statics/dist/assets/{cssMode.4c65b876.js → cssMode.23271d4a.js} +2 -2
  137. abstra_statics/dist/assets/{datetime.e5660676.js → datetime.82608dfb.js} +2 -2
  138. abstra_statics/dist/assets/dayjs.7f71c60a.js +2 -0
  139. abstra_statics/dist/assets/editor.02184ced.js +2 -0
  140. abstra_statics/dist/assets/editor.main.0f931e87.js +2 -0
  141. abstra_statics/dist/assets/fetch.1b3d01a0.js +2 -0
  142. abstra_statics/dist/assets/files.8b58ee7e.js +2 -0
  143. abstra_statics/dist/assets/folder.13d3acac.js +2 -0
  144. abstra_statics/dist/assets/{freemarker2.1d872d48.js → freemarker2.f79b510b.js} +2 -2
  145. abstra_statics/dist/assets/{handlebars.41fc6db8.js → handlebars.07d5febe.js} +2 -2
  146. abstra_statics/dist/assets/{html.967e3c6d.js → html.7d6a59b4.js} +3 -3
  147. abstra_statics/dist/assets/{htmlMode.d38ab72a.js → htmlMode.7779ff94.js} +2 -2
  148. abstra_statics/dist/assets/{index.8e871bae.js → index.482df04a.js} +2 -2
  149. abstra_statics/dist/assets/{index.4b93c8ad.js → index.581e2edd.js} +2 -2
  150. abstra_statics/dist/assets/index.966ac1b9.js +2 -0
  151. abstra_statics/dist/assets/{index.9021ba5d.js → index.c7a996a6.js} +2 -2
  152. abstra_statics/dist/assets/{index.03d222dd.js → index.c8a56795.js} +2 -2
  153. abstra_statics/dist/assets/{index.5f3f38ed.js → index.d31da2c3.js} +2 -2
  154. abstra_statics/dist/assets/{index.51dbb698.js → index.d53182ed.js} +2 -2
  155. abstra_statics/dist/assets/{index.b762f5e8.js → index.e71a5f84.js} +2 -2
  156. abstra_statics/dist/assets/{javascript.0935bea2.js → javascript.4c528c2c.js} +3 -3
  157. abstra_statics/dist/assets/{jsonMode.2860b71c.js → jsonMode.d6441e9d.js} +2 -2
  158. abstra_statics/dist/assets/{jwt-decode.esm.7f2ef0df.js → jwt-decode.esm.54a1ea22.js} +8 -8
  159. abstra_statics/dist/assets/linters.a0f2aa84.js +2 -0
  160. abstra_statics/dist/assets/{liquid.1bae5f6b.js → liquid.0c441ad2.js} +2 -2
  161. abstra_statics/dist/assets/member.2260c37e.js +2 -0
  162. abstra_statics/dist/assets/{metadata.39f9b9ba.js → metadata.0098e20c.js} +2 -2
  163. abstra_statics/dist/assets/omniChatStore.dd7a1c46.js +8 -0
  164. abstra_statics/dist/assets/{organization.a877b653.js → organization.668d1b58.js} +2 -2
  165. abstra_statics/dist/assets/player.4ab4aed5.js +2 -0
  166. abstra_statics/dist/assets/{plotly.min.d3f75723.js → plotly.min.2a87d7e2.js} +2 -2
  167. abstra_statics/dist/assets/polling.b5a32c22.js +2 -0
  168. abstra_statics/dist/assets/{project.d22a89ee.js → project.1b8374f4.js} +2 -2
  169. abstra_statics/dist/assets/{python.4c1a1300.js → python.7ac27a56.js} +3 -3
  170. abstra_statics/dist/assets/{razor.ba8bdb33.js → razor.860a0279.js} +2 -2
  171. abstra_statics/dist/assets/{record.4ffc477c.js → record.e83a2eb2.js} +2 -2
  172. abstra_statics/dist/assets/{redirect.ce3c0f65.js → redirect.586749f4.js} +2 -2
  173. abstra_statics/dist/assets/{repository.360feb8f.js → repository.3a331f0f.js} +2 -2
  174. abstra_statics/dist/assets/{repository.ab3036a9.js → repository.66c7567c.js} +2 -2
  175. abstra_statics/dist/assets/router.06ee2b9d.js +2 -0
  176. abstra_statics/dist/assets/router.4dfadf5d.js +18 -0
  177. abstra_statics/dist/assets/string.61e11a30.js +2 -0
  178. abstra_statics/dist/assets/{tables.be1c51f8.js → tables.1bcb1140.js} +2 -2
  179. abstra_statics/dist/assets/{tasksController.bf12e264.js → tasksController.f3adf725.js} +2 -2
  180. abstra_statics/dist/assets/{toggleHighContrast.c4e1b24d.js → toggleHighContrast.9535bf54.js} +7 -7
  181. abstra_statics/dist/assets/{tsMode.da264aae.js → tsMode.c0f9fe1a.js} +2 -2
  182. abstra_statics/dist/assets/{typescript.db5d7517.js → typescript.310eae6d.js} +3 -3
  183. abstra_statics/dist/assets/url.f5664225.js +2 -0
  184. abstra_statics/dist/assets/{useCodebaseEvents.42573b00.js → useCodebaseEvents.276cc8f0.js} +2 -2
  185. abstra_statics/dist/assets/useTables.18fc3efd.js +2 -0
  186. abstra_statics/dist/assets/userStore.6ab1e5ac.js +2 -0
  187. abstra_statics/dist/assets/uuid.5b8ba8af.js +2 -0
  188. abstra_statics/dist/assets/vue-flow-background.af096866.js +2 -0
  189. abstra_statics/dist/assets/vue-flow-core.6cb99d32.js +22 -0
  190. abstra_statics/dist/assets/{vue-quill.esm-bundler.37119951.js → vue-quill.esm-bundler.e3d34d0e.js} +2 -2
  191. abstra_statics/dist/assets/{workspaceStore.50ef2df1.js → workspaceStore.fac1e9a9.js} +2 -2
  192. abstra_statics/dist/assets/{xml.94b88503.js → xml.04864db4.js} +3 -3
  193. abstra_statics/dist/assets/{yaml.73b7d5ce.js → yaml.f30375fe.js} +3 -3
  194. abstra_statics/dist/console.html +14 -15
  195. abstra_statics/dist/editor.html +13 -13
  196. abstra_statics/dist/player.html +9 -9
  197. tests/e2e/test_crud_files.py +1 -0
  198. abstra_internals/templates/abstraignore +0 -8
  199. abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.3f03a3ef.js +0 -2
  200. abstra_statics/dist/assets/ApiKeys.cb561e62.js +0 -2
  201. abstra_statics/dist/assets/App.dc82115f.js +0 -2
  202. abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.3640ec1c.js +0 -2
  203. abstra_statics/dist/assets/ConnectorsView.b428e487.js +0 -2
  204. abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.506f28c6.js +0 -2
  205. abstra_statics/dist/assets/ContentLayout.228d2328.js +0 -2
  206. abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.61381525.js +0 -2
  207. abstra_statics/dist/assets/EnvVars.242b97c2.js +0 -2
  208. abstra_statics/dist/assets/Error.466dbb94.js +0 -2
  209. abstra_statics/dist/assets/ExclamationCircleOutlined.6d10f60b.js +0 -2
  210. abstra_statics/dist/assets/Files.104385dd.js +0 -2
  211. abstra_statics/dist/assets/Home.80c7e349.js +0 -2
  212. abstra_statics/dist/assets/LoadingContainer.6e2b63e4.js +0 -2
  213. abstra_statics/dist/assets/LoadingOutlined.cd84d9c9.js +0 -2
  214. abstra_statics/dist/assets/Login.409f4a11.js +0 -2
  215. abstra_statics/dist/assets/Logo.2de02c4a.js +0 -2
  216. abstra_statics/dist/assets/Main.4370ed68.js +0 -2
  217. abstra_statics/dist/assets/Navbar.07ba9452.js +0 -2
  218. abstra_statics/dist/assets/NewEditor.769f4459.js +0 -8
  219. abstra_statics/dist/assets/NewEditor.d6e41a05.css +0 -1
  220. abstra_statics/dist/assets/OidcLoginCallback.a89857fe.js +0 -2
  221. abstra_statics/dist/assets/OidcLogoutCallback.d151c695.js +0 -2
  222. abstra_statics/dist/assets/OmniChat.0f64dfec.css +0 -1
  223. abstra_statics/dist/assets/OmniChat.d015bfa8.js +0 -6
  224. abstra_statics/dist/assets/Organizations.b630803f.js +0 -2
  225. abstra_statics/dist/assets/PhPencilSimpleLine.vue.34633dfa.js +0 -2
  226. abstra_statics/dist/assets/Project.c03610d3.js +0 -2
  227. abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.3bbea426.js +0 -2
  228. abstra_statics/dist/assets/Sql.3cdc910a.css +0 -1
  229. abstra_statics/dist/assets/Sql.b6aa38ca.js +0 -5
  230. abstra_statics/dist/assets/Steps.7c7e4a4a.js +0 -2
  231. abstra_statics/dist/assets/TableEditor.1e680eaf.css +0 -1
  232. abstra_statics/dist/assets/TableEditor.dc1b4a2d.js +0 -2
  233. abstra_statics/dist/assets/Tables.de30953b.js +0 -2
  234. abstra_statics/dist/assets/TablesDiagram.1ec45dd9.css +0 -1
  235. abstra_statics/dist/assets/TablesDiagram.97d6a43f.js +0 -15
  236. abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.63aa07d0.js +0 -2
  237. abstra_statics/dist/assets/View.617ad8d8.js +0 -2
  238. abstra_statics/dist/assets/WidgetPreview.99f14714.js +0 -2
  239. abstra_statics/dist/assets/ant-design.4952c8fb.js +0 -2
  240. abstra_statics/dist/assets/apiKey.864dc66b.js +0 -2
  241. abstra_statics/dist/assets/asyncComputed.25309626.js +0 -2
  242. abstra_statics/dist/assets/colorHelpers.71d6d61d.js +0 -2
  243. abstra_statics/dist/assets/console.3d4702c3.js +0 -25
  244. abstra_statics/dist/assets/constants.56e8988f.js +0 -2
  245. abstra_statics/dist/assets/dayjs.c54f8edb.js +0 -2
  246. abstra_statics/dist/assets/editor.6d0baf6f.js +0 -2
  247. abstra_statics/dist/assets/editor.main.65812c73.js +0 -2
  248. abstra_statics/dist/assets/fetch.5136a62d.js +0 -2
  249. abstra_statics/dist/assets/folder.d7d65e5b.js +0 -2
  250. abstra_statics/dist/assets/index.23283fbb.js +0 -2
  251. abstra_statics/dist/assets/index.58e29274.js +0 -2
  252. abstra_statics/dist/assets/linters.640d6098.js +0 -2
  253. abstra_statics/dist/assets/member.b7ac8000.js +0 -2
  254. abstra_statics/dist/assets/omniChatStore.3431c026.js +0 -8
  255. abstra_statics/dist/assets/player.30593e18.js +0 -2
  256. abstra_statics/dist/assets/polling.d1c934c7.js +0 -2
  257. abstra_statics/dist/assets/router.7f571832.js +0 -2
  258. abstra_statics/dist/assets/router.8fd5b2ad.js +0 -10
  259. abstra_statics/dist/assets/string.2ed1cde3.js +0 -2
  260. abstra_statics/dist/assets/url.8583a595.js +0 -2
  261. abstra_statics/dist/assets/userStore.73b89fbb.js +0 -2
  262. abstra_statics/dist/assets/uuid.dadede91.js +0 -2
  263. abstra_statics/dist/assets/vue-flow-background.d2772d9a.js +0 -22
  264. {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/WHEEL +0 -0
  265. {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/entry_points.txt +0 -0
  266. {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,17 @@
1
+ import base64
2
+ import io
1
3
  from dataclasses import dataclass
2
4
  from typing import Any, Dict, List
3
5
 
6
+ import pypdfium2 as pdfium
7
+
4
8
  from abstra_internals.cloud_api import get_session_path, get_tunnel_secret_key
5
9
  from abstra_internals.contracts_generated import (
6
10
  AbstraLibApiAiStreamRequest,
7
11
  CloudApiCliAiV2StreamRequest,
12
+ CloudApiCliAiV2StreamRequestContentItem,
13
+ CloudApiCliAiV2StreamRequestContentItemAssistantFileInput,
14
+ CloudApiCliAiV2StreamRequestContentItemAssistantTextInput,
8
15
  )
9
16
  from abstra_internals.controllers.main import MainController
10
17
  from abstra_internals.credentials import resolve_headers
@@ -71,15 +78,96 @@ class AiController:
71
78
  self.controller = controller
72
79
  self.repos = controller.repositories
73
80
 
81
+ def _extract_pdf_images(self, pdf_bytes: bytes) -> List[bytes]:
82
+ images = []
83
+ pdf_io = io.BytesIO(pdf_bytes)
84
+ for page in pdfium.PdfDocument(pdf_io):
85
+ bitmap = page.render(
86
+ scale=4, # 288 dpi
87
+ rotation=0,
88
+ )
89
+ pil_image = bitmap.to_pil()
90
+ image_io = io.BytesIO()
91
+ pil_image.save(image_io, format="png")
92
+ image_io.seek(0)
93
+ images.append(image_io.read())
94
+ return images
95
+
96
+ def _process_pdf_content(
97
+ self, pdf_file: CloudApiCliAiV2StreamRequestContentItemAssistantFileInput
98
+ ) -> List[CloudApiCliAiV2StreamRequestContentItem]:
99
+ processed_items = []
100
+ try:
101
+ pdf_bytes = base64.b64decode(pdf_file.file_content)
102
+ images = self._extract_pdf_images(pdf_bytes)
103
+
104
+ processed_items.append(
105
+ CloudApiCliAiV2StreamRequestContentItemAssistantTextInput(
106
+ type="text",
107
+ text=f"[PDF Document: {pdf_file.file_name} - {len(images)} page(s)]",
108
+ )
109
+ )
110
+
111
+ for idx, image_bytes in enumerate(images, 1):
112
+ image_base64 = base64.b64encode(image_bytes).decode("utf-8")
113
+ processed_items.append(
114
+ CloudApiCliAiV2StreamRequestContentItemAssistantFileInput(
115
+ type="file",
116
+ file_name=f"{pdf_file.file_name}_page_{idx}.png",
117
+ file_content=image_base64,
118
+ )
119
+ )
120
+ except Exception as e:
121
+ print(f"Error extracting PDF images: {e}")
122
+ processed_items.append(
123
+ CloudApiCliAiV2StreamRequestContentItemAssistantTextInput(
124
+ type="text",
125
+ text=f"[PDF Document: {pdf_file.file_name}]\nNote: Could not extract images from this PDF.",
126
+ )
127
+ )
128
+ return processed_items
129
+
130
+ def _process_content(
131
+ self, content: List[CloudApiCliAiV2StreamRequestContentItem]
132
+ ) -> List[CloudApiCliAiV2StreamRequestContentItem]:
133
+ processed_content = []
134
+
135
+ for item in content:
136
+ if isinstance(
137
+ item, CloudApiCliAiV2StreamRequestContentItemAssistantTextInput
138
+ ):
139
+ processed_content.append(item)
140
+ continue
141
+
142
+ if not item.file_name.lower().endswith(".pdf"):
143
+ processed_content.append(item)
144
+ continue
145
+
146
+ try:
147
+ processed_pdf_items = self._process_pdf_content(item)
148
+ processed_content.extend(processed_pdf_items)
149
+ except Exception as e:
150
+ print(f"Error extracting PDF images: {e}")
151
+ processed_content.append(
152
+ CloudApiCliAiV2StreamRequestContentItemAssistantTextInput(
153
+ type="text",
154
+ text=f"[PDF Document: {item.file_name}]\nNote: Could not extract images from this PDF.",
155
+ )
156
+ )
157
+
158
+ return processed_content
159
+
74
160
  def send_ai_message(
75
161
  self,
76
162
  body: AbstraLibApiAiStreamRequest,
77
163
  ):
78
164
  try:
165
+ processed_content = self._process_content(body.content)
166
+
79
167
  yield from self.repos.ai.get_ai_messages(
80
168
  CloudApiCliAiV2StreamRequest(
81
169
  conversation_id=body.conversation_id,
82
- content=body.content,
170
+ content=processed_content,
83
171
  context={
84
172
  **body.context,
85
173
  "libVersion": str(get_local_package_version()),
@@ -0,0 +1,307 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict, Optional
3
+
4
+ import requests
5
+
6
+ from abstra_internals.credentials import get_credentials
7
+ from abstra_internals.environment import CLOUD_API_CLI_URL, REMOTE_GIT_URL, REMOTE_NAME
8
+ from abstra_internals.repositories.git import (
9
+ AheadBehindInfo,
10
+ GitCommit,
11
+ GitStatusResponse,
12
+ RemoteGitStatus,
13
+ create_git_repository,
14
+ )
15
+ from abstra_internals.settings import Settings
16
+
17
+
18
+ class EmailProvider(ABC):
19
+ """Interface that requires a get_email method."""
20
+
21
+ @abstractmethod
22
+ def get_email(self) -> str:
23
+ pass
24
+
25
+
26
+ class DefaultEmailProvider(EmailProvider):
27
+ """Concrete implementation with a default email."""
28
+
29
+ def get_email(self) -> str:
30
+ return "abstra@mail.com"
31
+
32
+
33
+ class GitController:
34
+ def __init__(self, email_provider: EmailProvider = DefaultEmailProvider()):
35
+ self.git_repository = create_git_repository(Settings.root_path)
36
+ self.email_provider = email_provider
37
+ self.git_email = email_provider.get_email()
38
+
39
+ def _ensure_authentication(self) -> bool:
40
+ try:
41
+ if self.git_email is None:
42
+ self.git_email = self.email_provider.get_email()
43
+
44
+ if self.git_email is None:
45
+ print("No email available for git configuration")
46
+ return False
47
+
48
+ self.git_repository.configure_git_user(
49
+ fallback_email=self.git_email,
50
+ fallback_name=self.git_email.split("@")[0],
51
+ )
52
+
53
+ credentials = get_credentials()
54
+ if not credentials:
55
+ return False
56
+
57
+ if self.git_repository.has_remote(REMOTE_NAME):
58
+ if not self.git_repository.set_remote_url(REMOTE_NAME, REMOTE_GIT_URL):
59
+ return False
60
+ else:
61
+ if not self.git_repository.add_remote(REMOTE_NAME, REMOTE_GIT_URL):
62
+ return False
63
+
64
+ config_key = f"http.{REMOTE_GIT_URL}.extraHeader"
65
+ config_value = f"Api-Authorization: Bearer {credentials}"
66
+
67
+ if self.git_repository.get_git_config(config_key) == config_value:
68
+ return True
69
+
70
+ return self.git_repository.set_git_config(config_key, config_value)
71
+
72
+ except Exception as e:
73
+ print(f"Authentication setup failed: {e}")
74
+ return False
75
+
76
+ def _fetch_remote_status(self, branch: str = "main") -> RemoteGitStatus:
77
+ try:
78
+ credentials = get_credentials()
79
+ if not credentials:
80
+ return RemoteGitStatus(
81
+ success=False, message="No authentication credentials available"
82
+ )
83
+
84
+ api_url = f"{CLOUD_API_CLI_URL}/git/status"
85
+ headers = {"Api-Authorization": f"Bearer {credentials}"}
86
+ params = {"branch": branch}
87
+
88
+ response = requests.get(api_url, headers=headers, params=params, timeout=10)
89
+
90
+ if response.status_code == 200:
91
+ try:
92
+ data = response.json()
93
+
94
+ if not isinstance(data, dict):
95
+ return RemoteGitStatus(
96
+ success=False,
97
+ message=f"Unexpected response format. Expected dict, got {type(data).__name__}",
98
+ )
99
+
100
+ return RemoteGitStatus(
101
+ success=data.get("success", True),
102
+ remote_commit=data.get("remote_commit"),
103
+ branch=data.get("branch", branch),
104
+ has_commits=data.get("has_commits", False),
105
+ available_branches=data.get("available_branches", [branch]),
106
+ message=data.get("message"),
107
+ ahead_behind=None,
108
+ )
109
+ except ValueError as json_error:
110
+ return RemoteGitStatus(
111
+ success=False, message=f"Invalid JSON response: {json_error}"
112
+ )
113
+ else:
114
+ response_text = (
115
+ response.text[:200] if response.text else "No response body"
116
+ )
117
+ return RemoteGitStatus(
118
+ success=False,
119
+ message=f"API call failed with status {response.status_code}: {response_text}",
120
+ )
121
+
122
+ except Exception as e:
123
+ return RemoteGitStatus(
124
+ success=False, message=f"Error fetching remote status: {str(e)}"
125
+ )
126
+
127
+ def get_status(self) -> Dict[str, Any]:
128
+ self._ensure_authentication()
129
+
130
+ status = self.git_repository.get_repository_status()
131
+
132
+ remote_status = None
133
+
134
+ if status.available:
135
+ remote_status = self._fetch_remote_status()
136
+
137
+ if (
138
+ remote_status.success
139
+ and remote_status.remote_commit
140
+ and status.last_commit
141
+ and remote_status.remote_commit != status.last_commit.hash
142
+ ):
143
+ try:
144
+ ahead, behind = self.git_repository.get_ahead_behind_count(
145
+ status.last_commit.hash, remote_status.remote_commit
146
+ )
147
+ remote_status.ahead_behind = AheadBehindInfo(
148
+ ahead=ahead, behind=behind
149
+ )
150
+ except Exception as e:
151
+ print(f"Failed to calculate ahead/behind: {e}")
152
+
153
+ remote_status.has_conflicts = self.git_repository.check_merge_conflicts(
154
+ remote_status.remote_commit
155
+ )
156
+
157
+ if remote_status.ahead_behind:
158
+ remote_status.has_remote_changes = (
159
+ remote_status.ahead_behind.behind > 0
160
+ )
161
+ else:
162
+ remote_status.has_remote_changes = (
163
+ remote_status.remote_commit != status.last_commit.hash
164
+ )
165
+
166
+ status_response = GitStatusResponse(
167
+ available=status.available,
168
+ git_installed=status.git_installed,
169
+ is_monorepo=status.is_monorepo,
170
+ branch=status.branch,
171
+ branches=status.branches,
172
+ last_commit=status.last_commit,
173
+ has_changes=status.has_changes,
174
+ changed_files=status.changed_files,
175
+ changed_files_with_status=status.changed_files_with_status,
176
+ remote_status=remote_status,
177
+ )
178
+
179
+ return status_response.to_dict()
180
+
181
+ def checkout_branch(self, branch_name: str) -> Dict[str, Any]:
182
+ success = self.git_repository.checkout_branch(branch_name)
183
+
184
+ message = (
185
+ f"Switched to branch '{branch_name}'"
186
+ if success
187
+ else f"Failed to switch to branch '{branch_name}'"
188
+ )
189
+
190
+ return {"success": success, "message": message}
191
+
192
+ def checkout_commit(self, commit_hash: str) -> Dict[str, Any]:
193
+ success = self.git_repository.checkout_commit(commit_hash)
194
+
195
+ message = (
196
+ f"Switched to commit '{commit_hash[:8]}'"
197
+ if success
198
+ else f"Failed to switch to commit '{commit_hash[:8]}'"
199
+ )
200
+
201
+ return {"success": success, "message": message}
202
+
203
+ def pull_changes(
204
+ self, strategy: str, allow_unrelated: bool, conflict_resolution: Optional[str]
205
+ ) -> Dict[str, Any]:
206
+ self._ensure_authentication()
207
+
208
+ success = self.git_repository.pull_changes(
209
+ strategy=strategy,
210
+ allow_unrelated=allow_unrelated,
211
+ conflict_resolution=conflict_resolution,
212
+ )
213
+
214
+ message = "Successfully pulled changes" if success else "Failed to pull changes"
215
+
216
+ return {"success": success, "message": message}
217
+
218
+ def commit_changes(self, message: str) -> Dict[str, Any]:
219
+ commit_message = message.strip()
220
+ if not commit_message:
221
+ return {"success": False, "message": "Commit message cannot be empty"}
222
+
223
+ success = self.git_repository.commit_changes(commit_message)
224
+
225
+ message = (
226
+ f"Successfully committed changes: {commit_message}"
227
+ if success
228
+ else "Failed to commit changes"
229
+ )
230
+
231
+ return {"success": success, "message": message}
232
+
233
+ def stash_changes(self, message: str = "WIP") -> Dict[str, Any]:
234
+ success = self.git_repository.stash_changes(message)
235
+
236
+ message = (
237
+ "Successfully stashed changes" if success else "Failed to stash changes"
238
+ )
239
+
240
+ return {"success": success, "message": message}
241
+
242
+ def get_commit_history(
243
+ self, limit: int = 10, offset: int = 0, branch: Optional[str] = None
244
+ ) -> Dict[str, Any]:
245
+ commits = self.git_repository.get_commit_history(
246
+ limit=limit, offset=offset, branch=branch
247
+ )
248
+
249
+ return {
250
+ "commits": [self._format_commit(commit) for commit in commits],
251
+ "hasMore": len(commits) == limit,
252
+ }
253
+
254
+ def push_and_deploy(self, branch: str = "main") -> Dict[str, Any]:
255
+ self._ensure_authentication()
256
+
257
+ success = self.git_repository.push_and_deploy(branch)
258
+
259
+ message = (
260
+ f"Successfully deployed branch '{branch}' to Abstra"
261
+ if success
262
+ else f"Failed to deploy branch '{branch}' to Abstra. Push operation failed."
263
+ )
264
+
265
+ return {"success": success, "message": message}
266
+
267
+ def get_remotes(self) -> Dict[str, Any]:
268
+ remotes = self.git_repository.get_remotes()
269
+
270
+ return {"remotes": remotes, "hasAbstraRemote": REMOTE_NAME in remotes}
271
+
272
+ def revert_commit(self, commit_hash: str) -> Dict[str, Any]:
273
+ if not commit_hash.strip():
274
+ return {"success": False, "message": "Commit hash is required"}
275
+
276
+ commits = self.git_repository.get_commit_history(limit=200)
277
+ commit_to_revert = next(
278
+ (c for c in commits if c.hash.startswith(commit_hash)), None
279
+ )
280
+
281
+ if not commit_to_revert:
282
+ return {"success": False, "message": f"Commit {commit_hash[:8]} not found"}
283
+
284
+ try:
285
+ success = self.git_repository.revert_commit(commit_hash)
286
+
287
+ message = (
288
+ f"Successfully restored content from commit: {commit_to_revert.message}. A new commit was created with the content from that version."
289
+ if success
290
+ else f"Failed to restore content from commit {commit_hash[:8]}. Make sure there are no uncommitted changes and the commit exists."
291
+ )
292
+
293
+ return {"success": success, "message": message}
294
+
295
+ except Exception as e:
296
+ return {
297
+ "success": False,
298
+ "message": f"Error restoring content from commit {commit_hash[:8]}: {str(e)}",
299
+ }
300
+
301
+ def _format_commit(self, commit: GitCommit) -> Dict[str, str]:
302
+ return {
303
+ "hash": commit.hash,
304
+ "message": commit.message,
305
+ "author": commit.author,
306
+ "date": commit.date,
307
+ }
@@ -26,7 +26,7 @@ from abstra_internals.entities.execution_context import (
26
26
  Response,
27
27
  ScriptContext,
28
28
  )
29
- from abstra_internals.interface.cli.deploy import deploy
29
+ from abstra_internals.interface.cli.deploy import deploy_without_git
30
30
  from abstra_internals.logger import AbstraLogger
31
31
  from abstra_internals.repositories.email import EmailRepository
32
32
  from abstra_internals.repositories.execution import ExecutionFilter, ExecutionRepository
@@ -54,7 +54,6 @@ from abstra_internals.services.fs import FileSystemService
54
54
  from abstra_internals.services.requirements import RequirementsRepository
55
55
  from abstra_internals.settings import Settings
56
56
  from abstra_internals.templates import (
57
- ensure_abstraignore,
58
57
  ensure_dotenv,
59
58
  ensure_gitignore,
60
59
  new_form_code,
@@ -126,7 +125,6 @@ class MainController:
126
125
  repositories.project.initialize_or_migrate()
127
126
 
128
127
  RequirementsRepository.ensure("abstra")
129
- ensure_abstraignore(Settings.root_path)
130
128
  ensure_gitignore(Settings.root_path)
131
129
  ensure_dotenv(Settings.root_path)
132
130
 
@@ -143,7 +141,7 @@ class MainController:
143
141
  self.execution_logs_repository = repositories.execution_logs
144
142
  self.linter_repository = repositories.linter
145
143
 
146
- def deploy(self):
144
+ def deploy_without_git(self):
147
145
  self.linter_repository.update_checks()
148
146
  issues = self.linter_repository.get_blocking_checks()
149
147
 
@@ -152,7 +150,7 @@ class MainController:
152
150
  "Please fix all linter issues before deploying your project."
153
151
  )
154
152
 
155
- deploy()
153
+ deploy_without_git()
156
154
 
157
155
  def reset_repositories(self):
158
156
  self.execution_repository.clear()
@@ -541,7 +539,7 @@ class MainController:
541
539
  ```
542
540
 
543
541
  Note:
544
- - Respects .gitignore and .gitignore patterns when use_ignore=True
542
+ - Respects .gitignore patterns when use_ignore=True
545
543
  - Image mode supports: .png, .jpg, .jpeg, .gif, .svg, .webp, .jfif, .pjp, .pjpeg
546
544
  - Module mode uses Python's pkgutil.iter_modules for discovery
547
545
  - Paths are always relative to the project root directory
@@ -1432,6 +1430,12 @@ class MainController:
1432
1430
  return {"logged": False, "reason": "NO_API_TOKEN"}
1433
1431
  return get_api_key_info(headers)
1434
1432
 
1433
+ def get_email(self):
1434
+ login = self.get_login()
1435
+ if login.get("logged"):
1436
+ return login.get("info", {}).get("email")
1437
+ return None
1438
+
1435
1439
  def create_login(self, token):
1436
1440
  set_credentials(token)
1437
1441
  return self.get_login()
@@ -110,3 +110,9 @@ SERVER_UUID = lambda: os.getenv(__SERVER_UUID_ENV__) # noqa: E731
110
110
 
111
111
  def set_SERVER_UUID(server_uuid: str):
112
112
  os.environ[__SERVER_UUID_ENV__] = server_uuid
113
+
114
+
115
+ # GIT
116
+ FORCE_GIT_CLIENT = os.getenv("ABSTRA_FORCE_GIT_CLIENT")
117
+ REMOTE_GIT_URL = f"{CLOUD_API_CLI_URL}/git/repo.git"
118
+ REMOTE_NAME = "abstra"
@@ -28,7 +28,7 @@ def _upload_file(url: str, file_path: pathlib.Path):
28
28
  requests.put(url=url, data=f.read())
29
29
 
30
30
 
31
- def deploy():
31
+ def deploy_without_git():
32
32
  headers = resolve_headers()
33
33
  if not headers:
34
34
  print(
@@ -80,7 +80,7 @@ def ensure_certificates():
80
80
  print(f"Failed to restore certificates: {update_e}")
81
81
 
82
82
 
83
- def editor(headless: bool):
83
+ def editor(headless: bool, verbose: bool = False):
84
84
  ensure_certificates()
85
85
 
86
86
  load_dotenv(Settings.root_path / ".env")
@@ -119,6 +119,6 @@ def editor(headless: bool):
119
119
  if not headless:
120
120
  background_open_editor()
121
121
 
122
- connect_tunnel()
122
+ connect_tunnel(verbose=verbose)
123
123
 
124
124
  server.serve_forever()
@@ -84,6 +84,7 @@ def parse_nfse(document_path: Union["Path", str]) -> CloudApiCliModelsNfseRespon
84
84
  - razao_social_prestador/razao_social_tomador: Company names
85
85
  - valor_liquido_centavos/valor_total_centavos: Net/total amounts in cents
86
86
  - numero_nota: Invoice number
87
+ - codigo_servico: Service code number
87
88
  - data_emissao: Issue date (YYYY-MM-DD)
88
89
  - descricao: Service description
89
90
  - endereco_prestador/endereco_tomador: Full addresses
@@ -0,0 +1,25 @@
1
+ from .native import NativeGitRepository
2
+ from .types import (
3
+ AheadBehindInfo,
4
+ GitCommit,
5
+ GitRepositoryInterface,
6
+ GitStatus,
7
+ GitStatusResponse,
8
+ RemoteGitStatus,
9
+ )
10
+
11
+
12
+ def create_git_repository(working_directory) -> GitRepositoryInterface:
13
+ return NativeGitRepository(working_directory)
14
+
15
+
16
+ __all__ = [
17
+ "GitCommit",
18
+ "GitStatus",
19
+ "RemoteGitStatus",
20
+ "GitStatusResponse",
21
+ "GitRepositoryInterface",
22
+ "NativeGitRepository",
23
+ "create_git_repository",
24
+ "AheadBehindInfo",
25
+ ]