abstra 3.23.11__py3-none-any.whl → 3.24.0__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.
Potentially problematic release.
This version of abstra might be problematic. Click here for more details.
- abstra/ai.py +2 -0
- abstra/cli.py +8 -3
- {abstra-3.23.11.dist-info → abstra-3.24.0.dist-info}/METADATA +2 -1
- {abstra-3.23.11.dist-info → abstra-3.24.0.dist-info}/RECORD +201 -191
- abstra_internals/consts/filepaths.py +1 -1
- abstra_internals/contracts_generated.py +5382 -5233
- abstra_internals/controllers/ai.py +23 -15
- abstra_internals/controllers/git.py +305 -0
- abstra_internals/controllers/main.py +10 -6
- abstra_internals/entities/forms/template.py +2 -2
- abstra_internals/environment.py +6 -0
- abstra_internals/interface/cli/deploy.py +1 -1
- abstra_internals/interface/sdk/ai.py +157 -19
- abstra_internals/repositories/git/__init__.py +38 -0
- abstra_internals/repositories/git/dulwich.py +1353 -0
- abstra_internals/repositories/git/git_test.py +1572 -0
- abstra_internals/repositories/git/native.py +578 -0
- abstra_internals/repositories/git/types.py +267 -0
- abstra_internals/repositories/linter/rules/env_in_bundle.py +5 -5
- abstra_internals/repositories/linter/rules/env_in_bundle_test.py +6 -6
- abstra_internals/repositories/linter/rules/venv_in_bundle.py +9 -16
- abstra_internals/server/blueprints/editor.py +4 -0
- abstra_internals/server/routes/ai.py +1 -18
- abstra_internals/server/routes/git.py +190 -0
- abstra_internals/server/routes/workspace.py +1 -1
- abstra_internals/services/file_watcher.py +32 -13
- abstra_internals/services/fs.py +8 -5
- abstra_internals/services/fs_test.py +4 -6
- abstra_internals/templates/__init__.py +0 -11
- abstra_statics/dist/assets/AbstraButton.vue_vue_type_script_setup_true_lang.eb8ccb64.js +2 -0
- abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.9f98292e.js +2 -0
- abstra_statics/dist/assets/ApiKeys.e975c4f3.js +2 -0
- abstra_statics/dist/assets/App.f62faff6.js +2 -0
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.5aa45ac1.js +2 -0
- abstra_statics/dist/assets/BaseLayout.1ec2c96d.js +2 -0
- abstra_statics/dist/assets/Billing.60adc9fa.js +2 -0
- abstra_statics/dist/assets/{Breadcrumb.f11a16d0.js → Breadcrumb.26dec5f7.js} +2 -2
- abstra_statics/dist/assets/{Builds.2bf5dad8.js → Builds.f86210bc.js} +2 -2
- abstra_statics/dist/assets/{Card.6caecaa4.js → Card.6cfffb80.js} +2 -2
- abstra_statics/dist/assets/{CircularLoading.bc88c029.js → CircularLoading.a13d6a76.js} +2 -2
- abstra_statics/dist/assets/CloseCircleOutlined.30bc25a8.js +2 -0
- abstra_statics/dist/assets/{ConnectorsView.aeb00ce8.css → ConnectorsView.33c5380f.css} +1 -1
- abstra_statics/dist/assets/ConnectorsView.eb4c769f.js +2 -0
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.8d2e4672.js +2 -0
- abstra_statics/dist/assets/ContentLayout.d03fee5b.js +2 -0
- abstra_statics/dist/assets/{CrudView.79588134.js → CrudView.c0824225.js} +2 -2
- abstra_statics/dist/assets/{DocsButton.vue_vue_type_script_setup_true_lang.6566ff97.js → DocsButton.vue_vue_type_script_setup_true_lang.3668aee4.js} +2 -2
- abstra_statics/dist/assets/{EditorLogin.e704b2ee.js → EditorLogin.46db248f.js} +2 -2
- abstra_statics/dist/assets/EditorsView.e72621fa.js +2 -0
- abstra_statics/dist/assets/EnvVars.f9f9d61f.js +2 -0
- abstra_statics/dist/assets/{Error.f378696f.js → Error.864f05b3.js} +2 -2
- abstra_statics/dist/assets/ExclamationCircleOutlined.a489b996.js +2 -0
- abstra_statics/dist/assets/{Files.06a52abd.js → Files.afe615e1.js} +2 -2
- abstra_statics/dist/assets/Form.556d0de2.js +2 -0
- abstra_statics/dist/assets/{FormRunner.2b75fd4d.js → FormRunner.7f56a8c6.js} +2 -2
- abstra_statics/dist/assets/Home.287d17f8.js +2 -0
- abstra_statics/dist/assets/Home.5b7e9c23.js +2 -0
- abstra_statics/dist/assets/{Live.08670b33.js → Live.50bacfea.js} +2 -2
- abstra_statics/dist/assets/LoadingContainer.ebace8de.js +2 -0
- abstra_statics/dist/assets/{LoadingOutlined.659d6aae.js → LoadingOutlined.9e949112.js} +2 -2
- abstra_statics/dist/assets/{Login.8491c4b7.js → Login.536a3067.js} +2 -2
- abstra_statics/dist/assets/Login.bec408c9.js +2 -0
- abstra_statics/dist/assets/{Login.vue_vue_type_script_setup_true_lang.eb94ecc3.js → Login.vue_vue_type_script_setup_true_lang.1c3f108d.js} +2 -2
- abstra_statics/dist/assets/{Logo.a32d36e7.js → Logo.82d6ab70.js} +2 -2
- abstra_statics/dist/assets/{Logs.030c8a19.js → Logs.f6135084.js} +2 -2
- abstra_statics/dist/assets/{LogsController.7e2c0c7a.js → LogsController.6b666816.js} +2 -2
- abstra_statics/dist/assets/Main.77b115f8.js +2 -0
- abstra_statics/dist/assets/{MockForm.8b56fd25.js → MockForm.deda9355.js} +2 -2
- abstra_statics/dist/assets/Navbar.4a6f2b09.js +2 -0
- abstra_statics/dist/assets/NewEditor.5f84de86.css +1 -0
- abstra_statics/dist/assets/NewEditor.e558e47d.js +8 -0
- abstra_statics/dist/assets/OidcLoginCallback.7f514b45.js +2 -0
- abstra_statics/dist/assets/OidcLogoutCallback.038813a1.js +2 -0
- abstra_statics/dist/assets/OmniChat.05ba8d8a.css +1 -0
- abstra_statics/dist/assets/OmniChat.60d98deb.js +6 -0
- abstra_statics/dist/assets/{OnboardingView.262e82cc.js → OnboardingView.9413ee50.js} +2 -2
- abstra_statics/dist/assets/{Organization.4f3ccb55.js → Organization.7203cc0b.js} +2 -2
- abstra_statics/dist/assets/Organizations.91220ca0.js +2 -0
- abstra_statics/dist/assets/{PhArrowCounterClockwise.vue.a1a917b9.js → PhArrowCounterClockwise.vue.8090d021.js} +2 -2
- abstra_statics/dist/assets/{PhArrowSquareOut.vue.eb4455ba.js → PhArrowSquareOut.vue.26582195.js} +2 -2
- abstra_statics/dist/assets/{PhBookBookmark.vue.7bb66888.js → PhBookBookmark.vue.5b7ab079.js} +2 -2
- abstra_statics/dist/assets/{PhChats.vue.88d84608.js → PhChats.vue.b5df7174.js} +2 -2
- abstra_statics/dist/assets/{PhClockCounterClockwise.vue.02d85ea5.js → PhClockCounterClockwise.vue.812311ad.js} +2 -2
- abstra_statics/dist/assets/{PhCopy.vue.5664181e.js → PhCopy.vue.59b0f1b4.js} +2 -2
- abstra_statics/dist/assets/{PhCopySimple.vue.beb69d1f.js → PhCopySimple.vue.d41d9160.js} +2 -2
- abstra_statics/dist/assets/{PhCube.vue.8de1132a.js → PhCube.vue.63ae7d32.js} +2 -2
- abstra_statics/dist/assets/PhDatabase.vue.edfcb96b.js +2 -0
- abstra_statics/dist/assets/{PhDotsThreeVertical.vue.9e306480.js → PhDotsThreeVertical.vue.ab4580a5.js} +2 -2
- abstra_statics/dist/assets/PhDownloadSimple.vue.c2eaaad1.js +2 -0
- abstra_statics/dist/assets/{PhFolderPlus.vue.658105d4.js → PhFolderPlus.vue.05ba4a5c.js} +2 -2
- abstra_statics/dist/assets/{PhGear.vue.68bce043.js → PhGear.vue.0e4a6135.js} +2 -2
- abstra_statics/dist/assets/{PhKey.vue.3f5192b6.js → PhKey.vue.b2c184d1.js} +2 -2
- abstra_statics/dist/assets/{PhPencil.vue.ee28fb6e.js → PhPencil.vue.2f2fe576.js} +2 -2
- abstra_statics/dist/assets/{PhPencilSimple.vue.148807f6.js → PhPencilSimple.vue.cc8620ae.js} +2 -2
- abstra_statics/dist/assets/{PhRocket.vue.7ba12859.js → PhRocket.vue.e397203c.js} +2 -2
- abstra_statics/dist/assets/{PhSignOut.vue.aa78b6eb.js → PhSignOut.vue.a271f14b.js} +2 -2
- abstra_statics/dist/assets/{PhSparkle.vue.7820be45.js → PhSparkle.vue.726defa2.js} +2 -2
- abstra_statics/dist/assets/{PhUserList.vue.04f21cbe.js → PhUserList.vue.6a29f16d.js} +2 -2
- abstra_statics/dist/assets/{PhUsersThree.vue.8b11b97d.js → PhUsersThree.vue.275d13ab.js} +2 -2
- abstra_statics/dist/assets/PhWarningCircle.vue.3b1aca1b.js +2 -0
- abstra_statics/dist/assets/{PhWebhooksLogo.vue.9e20d559.js → PhWebhooksLogo.vue.5e772aac.js} +2 -2
- abstra_statics/dist/assets/{PlayerConfigProvider.0915b29f.js → PlayerConfigProvider.e90a2b41.js} +2 -2
- abstra_statics/dist/assets/{PlayerNavbar.78cf73f2.js → PlayerNavbar.11ec1844.js} +2 -2
- abstra_statics/dist/assets/Project.c16740fb.js +2 -0
- abstra_statics/dist/assets/ProjectLogin.e7a6f444.js +2 -0
- abstra_statics/dist/assets/{ProjectSettings.f9bf9124.js → ProjectSettings.52c19693.js} +2 -2
- abstra_statics/dist/assets/{ProjectsView.407ea382.js → ProjectsView.22fa7a8e.js} +2 -2
- abstra_statics/dist/assets/{SaveButton.e70cd09e.js → SaveButton.719393d2.js} +2 -2
- abstra_statics/dist/assets/{ScrollArea.vue_vue_type_script_setup_true_lang.cf352882.js → ScrollArea.vue_vue_type_script_setup_true_lang.d4028954.js} +2 -2
- abstra_statics/dist/assets/{Sidebar.e69f49bd.css → Sidebar.29baeab0.css} +1 -1
- abstra_statics/dist/assets/{Sidebar.ce129494.js → Sidebar.5cb8e04e.js} +2 -2
- abstra_statics/dist/assets/Sql.23d80bad.js +5 -0
- abstra_statics/dist/assets/Sql.90e6e2ba.css +1 -0
- abstra_statics/dist/assets/Steps.8e5d201a.js +2 -0
- abstra_statics/dist/assets/TableCard.529112b9.css +1 -0
- abstra_statics/dist/assets/TableCard.59f95f8f.js +2 -0
- abstra_statics/dist/assets/TableEditor.5853a363.css +1 -0
- abstra_statics/dist/assets/TableEditor.8539f984.js +2 -0
- abstra_statics/dist/assets/Tables.44d953f7.js +2 -0
- abstra_statics/dist/assets/TablesDiagram.8e47383c.js +15 -0
- abstra_statics/dist/assets/TablesDiagram.a588e7ff.css +1 -0
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.6866fb32.js +2 -0
- abstra_statics/dist/assets/{Tasks.c9ba3095.js → Tasks.09551b19.js} +2 -2
- abstra_statics/dist/assets/{UploadOutlined.c563b054.js → UploadOutlined.eab75eb0.js} +2 -2
- abstra_statics/dist/assets/View.5fd7ddf0.js +2 -0
- abstra_statics/dist/assets/{View.vue_vue_type_script_setup_true_lang.a00f21c8.js → View.vue_vue_type_script_setup_true_lang.a904f400.js} +2 -2
- abstra_statics/dist/assets/{Watermark.c71c105b.js → Watermark.ab3d818f.js} +2 -2
- abstra_statics/dist/assets/WebEditor.d6ec6392.js +2 -0
- abstra_statics/dist/assets/{WidgetPreview.8bd406f7.js → WidgetPreview.86b31dec.js} +2 -2
- abstra_statics/dist/assets/{ant-design.06b818ab.js → ant-design.a865486e.js} +2 -2
- abstra_statics/dist/assets/apiKey.72f497ca.js +2 -0
- abstra_statics/dist/assets/{asyncComputed.bfb7341c.js → asyncComputed.cf5282fc.js} +2 -2
- abstra_statics/dist/assets/{build.aef51d48.js → build.df2d55cc.js} +2 -2
- abstra_statics/dist/assets/colorHelpers.37d9932b.js +2 -0
- abstra_statics/dist/assets/console.2bf7f04d.js +17 -0
- abstra_statics/dist/assets/{constants.b75d9567.js → constants.7d38ec8b.js} +2 -2
- abstra_statics/dist/assets/contracts.generated.590b1102.js +2 -0
- abstra_statics/dist/assets/{cssMode.0aa24dcd.js → cssMode.7133c7cb.js} +2 -2
- abstra_statics/dist/assets/{datetime.46141396.js → datetime.8de2ff28.js} +2 -2
- abstra_statics/dist/assets/dayjs.f18bbbca.js +2 -0
- abstra_statics/dist/assets/editor.3a4714e3.js +2 -0
- abstra_statics/dist/assets/editor.main.9c635b9a.js +2 -0
- abstra_statics/dist/assets/fetch.89fd5b7b.js +2 -0
- abstra_statics/dist/assets/{folder.fe6adcd2.js → folder.d8e23009.js} +2 -2
- abstra_statics/dist/assets/{freemarker2.8bd96640.js → freemarker2.6698d1ea.js} +2 -2
- abstra_statics/dist/assets/{handlebars.e5dd9b19.js → handlebars.a6c42dc0.js} +2 -2
- abstra_statics/dist/assets/{html.7bcef916.js → html.493a5410.js} +2 -2
- abstra_statics/dist/assets/{htmlMode.ce91c230.js → htmlMode.a28b2fca.js} +2 -2
- abstra_statics/dist/assets/{index.fe015dd3.js → index.2af3391c.js} +2 -2
- abstra_statics/dist/assets/{index.57a61691.js → index.4176fe88.js} +2 -2
- abstra_statics/dist/assets/{index.16664500.js → index.4d20c159.js} +2 -2
- abstra_statics/dist/assets/{index.ee218f7a.js → index.5d6b1e62.js} +2 -2
- abstra_statics/dist/assets/{index.06cad1f2.js → index.79ce3bf1.js} +2 -2
- abstra_statics/dist/assets/{index.161ccee5.js → index.c34a405a.js} +2 -2
- abstra_statics/dist/assets/index.fb182bd1.js +2 -0
- abstra_statics/dist/assets/{index.005bab7f.js → index.fb49354b.js} +2 -2
- abstra_statics/dist/assets/{javascript.4d5c0a37.js → javascript.3a36cf17.js} +2 -2
- abstra_statics/dist/assets/{jsonMode.0942a255.js → jsonMode.bead6ac8.js} +2 -2
- abstra_statics/dist/assets/{jwt-decode.esm.e1e8e181.js → jwt-decode.esm.d4517a10.js} +8 -8
- abstra_statics/dist/assets/{linters.39cc198f.js → linters.2f3141cb.js} +2 -2
- abstra_statics/dist/assets/{liquid.884b015e.js → liquid.0c337fae.js} +3 -3
- abstra_statics/dist/assets/member.48d6f2cd.js +2 -0
- abstra_statics/dist/assets/{metadata.034775c8.js → metadata.c3aed6e1.js} +2 -2
- abstra_statics/dist/assets/omniChatStore.c53bcca2.js +8 -0
- abstra_statics/dist/assets/{organization.a29009bc.js → organization.928c9bef.js} +2 -2
- abstra_statics/dist/assets/player.d3aeafc5.js +2 -0
- abstra_statics/dist/assets/{plotly.min.df1e817c.js → plotly.min.7225d3a0.js} +2 -2
- abstra_statics/dist/assets/{polling.84bf96db.js → polling.82ee6b45.js} +2 -2
- abstra_statics/dist/assets/{project.a9ad86e9.js → project.619b7244.js} +2 -2
- abstra_statics/dist/assets/{python.17c791bf.js → python.05764499.js} +3 -3
- abstra_statics/dist/assets/{razor.4b071c3b.js → razor.81a45581.js} +2 -2
- abstra_statics/dist/assets/record.7f43486c.js +2 -0
- abstra_statics/dist/assets/{redirect.cd158e43.js → redirect.f028a879.js} +2 -2
- abstra_statics/dist/assets/repository.9534db4b.js +2 -0
- abstra_statics/dist/assets/repository.c15239ce.js +2 -0
- abstra_statics/dist/assets/router.262190ec.js +2 -0
- abstra_statics/dist/assets/router.424f7da9.js +18 -0
- abstra_statics/dist/assets/string.0acf5572.js +2 -0
- abstra_statics/dist/assets/{tables.928d4c4a.js → tables.1f68ec62.js} +2 -2
- abstra_statics/dist/assets/{tasksController.95334db5.js → tasksController.371896de.js} +2 -2
- abstra_statics/dist/assets/{toggleHighContrast.67a76682.js → toggleHighContrast.0d0e5662.js} +7 -7
- abstra_statics/dist/assets/{tsMode.bd4befb2.js → tsMode.6eadbf06.js} +2 -2
- abstra_statics/dist/assets/{typescript.b5722de7.js → typescript.1670e287.js} +2 -2
- abstra_statics/dist/assets/url.e8732f77.js +2 -0
- abstra_statics/dist/assets/{useCodebaseEvents.47e4fcfe.js → useCodebaseEvents.53dec1f2.js} +2 -2
- abstra_statics/dist/assets/useTables.4f034cf8.js +2 -0
- abstra_statics/dist/assets/userStore.31024da3.js +2 -0
- abstra_statics/dist/assets/uuid.bde15ce7.js +2 -0
- abstra_statics/dist/assets/vue-flow-background.818c7852.js +2 -0
- abstra_statics/dist/assets/vue-flow-core.1180ec83.js +22 -0
- abstra_statics/dist/assets/{vue-quill.esm-bundler.d6a7c536.js → vue-quill.esm-bundler.c4f04985.js} +2 -2
- abstra_statics/dist/assets/{workspaceStore.cca10750.js → workspaceStore.6244d03d.js} +2 -2
- abstra_statics/dist/assets/{xml.0a62ffce.js → xml.f2867af8.js} +3 -3
- abstra_statics/dist/assets/{yaml.1efc213f.js → yaml.5427bb1b.js} +3 -3
- abstra_statics/dist/console.html +14 -15
- abstra_statics/dist/editor.html +13 -13
- abstra_statics/dist/player.html +9 -9
- tests/e2e/test_crud_files.py +1 -0
- abstra_internals/templates/abstraignore +0 -8
- abstra_statics/dist/assets/AbstraButton.vue_vue_type_script_setup_true_lang.3fce0fbb.js +0 -2
- abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.4fb1f88a.js +0 -2
- abstra_statics/dist/assets/ApiKeys.56b97ced.js +0 -2
- abstra_statics/dist/assets/App.bd5ec032.js +0 -2
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.79524273.js +0 -2
- abstra_statics/dist/assets/BaseLayout.ac22ef55.js +0 -2
- abstra_statics/dist/assets/Billing.2c39d133.js +0 -2
- abstra_statics/dist/assets/CloseCircleOutlined.12f63f77.js +0 -2
- abstra_statics/dist/assets/ConnectorsView.97a8c63b.js +0 -2
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.48b29302.js +0 -2
- abstra_statics/dist/assets/ContentLayout.072b3790.js +0 -2
- abstra_statics/dist/assets/EditorsView.987a7eda.js +0 -2
- abstra_statics/dist/assets/EnvVars.c5e84d82.js +0 -2
- abstra_statics/dist/assets/ExclamationCircleOutlined.f9a25080.js +0 -2
- abstra_statics/dist/assets/Form.4633ab8e.js +0 -2
- abstra_statics/dist/assets/Home.a883da25.js +0 -2
- abstra_statics/dist/assets/Home.d122da63.js +0 -2
- abstra_statics/dist/assets/LoadingContainer.b11f052c.js +0 -2
- abstra_statics/dist/assets/Login.84d39327.js +0 -2
- abstra_statics/dist/assets/Main.70db8614.js +0 -2
- abstra_statics/dist/assets/Navbar.6acd9007.js +0 -2
- abstra_statics/dist/assets/NewEditor.15e29eac.js +0 -8
- abstra_statics/dist/assets/NewEditor.6dd8f03b.css +0 -1
- abstra_statics/dist/assets/OidcLoginCallback.b65a6f9f.js +0 -2
- abstra_statics/dist/assets/OidcLogoutCallback.dabd09cf.js +0 -2
- abstra_statics/dist/assets/OmniChat.078af315.css +0 -1
- abstra_statics/dist/assets/OmniChat.6ed96f8e.js +0 -6
- abstra_statics/dist/assets/Organizations.d90dd629.js +0 -2
- abstra_statics/dist/assets/PhDownloadSimple.vue.6192bb0e.js +0 -2
- abstra_statics/dist/assets/PhPencilSimpleLine.vue.af76e884.js +0 -2
- abstra_statics/dist/assets/Project.34c75b7c.js +0 -2
- abstra_statics/dist/assets/ProjectLogin.9b8cb3d1.js +0 -2
- abstra_statics/dist/assets/Sql.3cdc910a.css +0 -1
- abstra_statics/dist/assets/Sql.4e31662a.js +0 -5
- abstra_statics/dist/assets/Steps.4c850501.js +0 -2
- abstra_statics/dist/assets/TableEditor.1e680eaf.css +0 -1
- abstra_statics/dist/assets/TableEditor.e7371677.js +0 -2
- abstra_statics/dist/assets/Tables.f2c23e20.js +0 -2
- abstra_statics/dist/assets/TablesDiagram.1ec45dd9.css +0 -1
- abstra_statics/dist/assets/TablesDiagram.8297ec4b.js +0 -15
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.ec94f9e7.js +0 -2
- abstra_statics/dist/assets/View.4c3c38ba.js +0 -2
- abstra_statics/dist/assets/WebEditor.4ef39590.js +0 -2
- abstra_statics/dist/assets/apiKey.e3aa9e16.js +0 -2
- abstra_statics/dist/assets/colorHelpers.e94da383.js +0 -2
- abstra_statics/dist/assets/console.86947afb.js +0 -25
- abstra_statics/dist/assets/contracts.generated.7508e893.js +0 -2
- abstra_statics/dist/assets/dayjs.b4dc8227.js +0 -2
- abstra_statics/dist/assets/editor.4f4b7594.js +0 -2
- abstra_statics/dist/assets/editor.main.340c0a2d.js +0 -2
- abstra_statics/dist/assets/fetch.cfa094a0.js +0 -2
- abstra_statics/dist/assets/index.a884598f.js +0 -2
- abstra_statics/dist/assets/index.eb8f01b7.js +0 -2
- abstra_statics/dist/assets/member.af05829c.js +0 -2
- abstra_statics/dist/assets/omniChatStore.19fcae1a.js +0 -8
- abstra_statics/dist/assets/player.b9e54e21.js +0 -2
- abstra_statics/dist/assets/record.06867f70.js +0 -2
- abstra_statics/dist/assets/repository.40cf87c6.js +0 -2
- abstra_statics/dist/assets/repository.ecf19994.js +0 -2
- abstra_statics/dist/assets/router.8ccbba96.js +0 -10
- abstra_statics/dist/assets/router.c00c99d7.js +0 -2
- abstra_statics/dist/assets/string.ea3b2597.js +0 -2
- abstra_statics/dist/assets/url.62ce842c.js +0 -2
- abstra_statics/dist/assets/userStore.51f1e2d0.js +0 -2
- abstra_statics/dist/assets/uuid.f4308f15.js +0 -2
- abstra_statics/dist/assets/vue-flow-background.03bf6b4b.js +0 -22
- {abstra-3.23.11.dist-info → abstra-3.24.0.dist-info}/WHEEL +0 -0
- {abstra-3.23.11.dist-info → abstra-3.24.0.dist-info}/entry_points.txt +0 -0
- {abstra-3.23.11.dist-info → abstra-3.24.0.dist-info}/top_level.txt +0 -0
|
@@ -14,6 +14,8 @@ from abstra_internals.utils.file import silent_traverse_code
|
|
|
14
14
|
from abstra_internals.utils.packages import get_local_package_version
|
|
15
15
|
from abstra_internals.utils.paths import get_relative_path
|
|
16
16
|
|
|
17
|
+
RETRY_FLAG = "abstra__trigger__retry"
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
@dataclass
|
|
19
21
|
class PythonFile:
|
|
@@ -73,22 +75,28 @@ class AiController:
|
|
|
73
75
|
self,
|
|
74
76
|
body: AbstraLibApiAiStreamRequest,
|
|
75
77
|
):
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
try:
|
|
79
|
+
yield from self.repos.ai.get_ai_messages(
|
|
80
|
+
CloudApiCliAiV2StreamRequest(
|
|
81
|
+
conversation_id=body.conversation_id,
|
|
82
|
+
content=body.content,
|
|
83
|
+
context={
|
|
84
|
+
**body.context,
|
|
85
|
+
"libVersion": str(get_local_package_version()),
|
|
86
|
+
"knownIssues": [
|
|
87
|
+
i.to_dict()
|
|
88
|
+
for i in self.repos.linter.find_issues_in_codebase()
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
secret_key=get_tunnel_secret_key(),
|
|
92
|
+
tunnel_session_path=get_session_path(),
|
|
93
|
+
human_approval=body.human_approval,
|
|
94
|
+
)
|
|
90
95
|
)
|
|
91
|
-
|
|
96
|
+
except Exception as e:
|
|
97
|
+
print(f"Error in send_ai_message: {e}")
|
|
98
|
+
yield RETRY_FLAG
|
|
99
|
+
return
|
|
92
100
|
|
|
93
101
|
def get_history(self, limit: int, offset: int):
|
|
94
102
|
headers = resolve_headers()
|
|
@@ -0,0 +1,305 @@
|
|
|
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
|
+
branch=status.branch,
|
|
169
|
+
branches=status.branches,
|
|
170
|
+
last_commit=status.last_commit,
|
|
171
|
+
has_changes=status.has_changes,
|
|
172
|
+
changed_files=status.changed_files,
|
|
173
|
+
changed_files_with_status=status.changed_files_with_status,
|
|
174
|
+
remote_status=remote_status,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return status_response.to_dict()
|
|
178
|
+
|
|
179
|
+
def checkout_branch(self, branch_name: str) -> Dict[str, Any]:
|
|
180
|
+
success = self.git_repository.checkout_branch(branch_name)
|
|
181
|
+
|
|
182
|
+
message = (
|
|
183
|
+
f"Switched to branch '{branch_name}'"
|
|
184
|
+
if success
|
|
185
|
+
else f"Failed to switch to branch '{branch_name}'"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
return {"success": success, "message": message}
|
|
189
|
+
|
|
190
|
+
def checkout_commit(self, commit_hash: str) -> Dict[str, Any]:
|
|
191
|
+
success = self.git_repository.checkout_commit(commit_hash)
|
|
192
|
+
|
|
193
|
+
message = (
|
|
194
|
+
f"Switched to commit '{commit_hash[:8]}'"
|
|
195
|
+
if success
|
|
196
|
+
else f"Failed to switch to commit '{commit_hash[:8]}'"
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
return {"success": success, "message": message}
|
|
200
|
+
|
|
201
|
+
def pull_changes(
|
|
202
|
+
self, strategy: str, allow_unrelated: bool, conflict_resolution: Optional[str]
|
|
203
|
+
) -> Dict[str, Any]:
|
|
204
|
+
self._ensure_authentication()
|
|
205
|
+
|
|
206
|
+
success = self.git_repository.pull_changes(
|
|
207
|
+
strategy=strategy,
|
|
208
|
+
allow_unrelated=allow_unrelated,
|
|
209
|
+
conflict_resolution=conflict_resolution,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
message = "Successfully pulled changes" if success else "Failed to pull changes"
|
|
213
|
+
|
|
214
|
+
return {"success": success, "message": message}
|
|
215
|
+
|
|
216
|
+
def commit_changes(self, message: str) -> Dict[str, Any]:
|
|
217
|
+
commit_message = message.strip()
|
|
218
|
+
if not commit_message:
|
|
219
|
+
return {"success": False, "message": "Commit message cannot be empty"}
|
|
220
|
+
|
|
221
|
+
success = self.git_repository.commit_changes(commit_message)
|
|
222
|
+
|
|
223
|
+
message = (
|
|
224
|
+
f"Successfully committed changes: {commit_message}"
|
|
225
|
+
if success
|
|
226
|
+
else "Failed to commit changes"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
return {"success": success, "message": message}
|
|
230
|
+
|
|
231
|
+
def stash_changes(self, message: str = "WIP") -> Dict[str, Any]:
|
|
232
|
+
success = self.git_repository.stash_changes(message)
|
|
233
|
+
|
|
234
|
+
message = (
|
|
235
|
+
"Successfully stashed changes" if success else "Failed to stash changes"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
return {"success": success, "message": message}
|
|
239
|
+
|
|
240
|
+
def get_commit_history(
|
|
241
|
+
self, limit: int = 10, offset: int = 0, branch: Optional[str] = None
|
|
242
|
+
) -> Dict[str, Any]:
|
|
243
|
+
commits = self.git_repository.get_commit_history(
|
|
244
|
+
limit=limit, offset=offset, branch=branch
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
"commits": [self._format_commit(commit) for commit in commits],
|
|
249
|
+
"hasMore": len(commits) == limit,
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
def push_and_deploy(self, branch: str = "main") -> Dict[str, Any]:
|
|
253
|
+
self._ensure_authentication()
|
|
254
|
+
|
|
255
|
+
success = self.git_repository.push_and_deploy(branch)
|
|
256
|
+
|
|
257
|
+
message = (
|
|
258
|
+
f"Successfully deployed branch '{branch}' to Abstra"
|
|
259
|
+
if success
|
|
260
|
+
else f"Failed to deploy branch '{branch}' to Abstra. Push operation failed."
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
return {"success": success, "message": message}
|
|
264
|
+
|
|
265
|
+
def get_remotes(self) -> Dict[str, Any]:
|
|
266
|
+
remotes = self.git_repository.get_remotes()
|
|
267
|
+
|
|
268
|
+
return {"remotes": remotes, "hasAbstraRemote": REMOTE_NAME in remotes}
|
|
269
|
+
|
|
270
|
+
def revert_commit(self, commit_hash: str) -> Dict[str, Any]:
|
|
271
|
+
if not commit_hash.strip():
|
|
272
|
+
return {"success": False, "message": "Commit hash is required"}
|
|
273
|
+
|
|
274
|
+
commits = self.git_repository.get_commit_history(limit=200)
|
|
275
|
+
commit_to_revert = next(
|
|
276
|
+
(c for c in commits if c.hash.startswith(commit_hash)), None
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
if not commit_to_revert:
|
|
280
|
+
return {"success": False, "message": f"Commit {commit_hash[:8]} not found"}
|
|
281
|
+
|
|
282
|
+
try:
|
|
283
|
+
success = self.git_repository.revert_commit(commit_hash)
|
|
284
|
+
|
|
285
|
+
message = (
|
|
286
|
+
f"Successfully restored content from commit: {commit_to_revert.message}. A new commit was created with the content from that version."
|
|
287
|
+
if success
|
|
288
|
+
else f"Failed to restore content from commit {commit_hash[:8]}. Make sure there are no uncommitted changes and the commit exists."
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
return {"success": success, "message": message}
|
|
292
|
+
|
|
293
|
+
except Exception as e:
|
|
294
|
+
return {
|
|
295
|
+
"success": False,
|
|
296
|
+
"message": f"Error restoring content from commit {commit_hash[:8]}: {str(e)}",
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
def _format_commit(self, commit: GitCommit) -> Dict[str, str]:
|
|
300
|
+
return {
|
|
301
|
+
"hash": commit.hash,
|
|
302
|
+
"message": commit.message,
|
|
303
|
+
"author": commit.author,
|
|
304
|
+
"date": commit.date,
|
|
305
|
+
}
|
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
|
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()
|
|
@@ -24,11 +24,11 @@ class Button:
|
|
|
24
24
|
|
|
25
25
|
Unlike automatic navigation buttons (NextButton/BackButton), custom Button widgets give you full control over widget behavior within a page and can be used to implement complex conditional logic based on user choices.
|
|
26
26
|
|
|
27
|
-
## How Button State Works
|
|
27
|
+
## How Button State Works ##
|
|
28
28
|
|
|
29
29
|
When a user clicks a button, the button's key is set to `True` in the form state. You can then check this state using `state.get("button_key")` to determine which button was pressed and conditionally render different widgets or forms.
|
|
30
30
|
|
|
31
|
-
## Usage Pattern
|
|
31
|
+
## Usage Pattern ##
|
|
32
32
|
|
|
33
33
|
Buttons are optionally returned from your Page function (a function that returns a list of widgets). You have two options:
|
|
34
34
|
|
abstra_internals/environment.py
CHANGED
|
@@ -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"
|