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.
- abstra/cli.py +16 -5
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/METADATA +1 -1
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/RECORD +200 -190
- abstra_internals/cloud_api/__init__.py +17 -8
- abstra_internals/consts/filepaths.py +1 -1
- abstra_internals/contracts_generated.py +616 -596
- abstra_internals/controllers/ai.py +89 -1
- abstra_internals/controllers/git.py +307 -0
- abstra_internals/controllers/main.py +10 -6
- abstra_internals/environment.py +6 -0
- abstra_internals/interface/cli/deploy.py +1 -1
- abstra_internals/interface/cli/editor.py +2 -2
- abstra_internals/interface/sdk/ai.py +1 -0
- abstra_internals/repositories/git/__init__.py +25 -0
- abstra_internals/repositories/git/git_test.py +362 -0
- abstra_internals/repositories/git/native.py +578 -0
- abstra_internals/repositories/git/types.py +273 -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/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 +4 -4
- 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.441fcdfd.js → AbstraButton.vue_vue_type_script_setup_true_lang.aefce2d3.js} +2 -2
- abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.28bc9fc9.js +2 -0
- abstra_statics/dist/assets/ApiKeys.3c1e70dc.js +2 -0
- abstra_statics/dist/assets/App.9d8bd2aa.js +2 -0
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.a64c7cee.js +2 -0
- abstra_statics/dist/assets/{BaseLayout.c63dfc2d.js → BaseLayout.72a6c8f2.js} +2 -2
- abstra_statics/dist/assets/{Billing.461db3ef.js → Billing.6b07f282.js} +2 -2
- abstra_statics/dist/assets/{Breadcrumb.27110ec4.js → Breadcrumb.5c786c09.js} +2 -2
- abstra_statics/dist/assets/{Builds.4eecd717.js → Builds.d8c5c61b.js} +2 -2
- abstra_statics/dist/assets/{Card.1d1a9fb7.js → Card.fc77085c.js} +2 -2
- abstra_statics/dist/assets/{CircularLoading.fc66331b.js → CircularLoading.998b223a.js} +2 -2
- abstra_statics/dist/assets/{CloseCircleOutlined.0110bbe2.js → CloseCircleOutlined.9ff269cc.js} +2 -2
- abstra_statics/dist/assets/{ConnectorsView.82e74ae4.css → ConnectorsView.33c5380f.css} +1 -1
- abstra_statics/dist/assets/ConnectorsView.e670738b.js +2 -0
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.3ca66327.js +2 -0
- abstra_statics/dist/assets/ContentLayout.0db8d7fb.js +2 -0
- abstra_statics/dist/assets/{CrudView.c16e2f81.js → CrudView.cc6aeaf0.js} +2 -2
- abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.689d8ce7.js +2 -0
- abstra_statics/dist/assets/{EditorLogin.00a3b3d9.js → EditorLogin.691452b4.js} +2 -2
- abstra_statics/dist/assets/{EditorsView.f7b2843c.js → EditorsView.fcdf0186.js} +2 -2
- abstra_statics/dist/assets/EnvVars.5519b4ce.js +2 -0
- abstra_statics/dist/assets/Error.11fd1f21.js +2 -0
- abstra_statics/dist/assets/ExclamationCircleOutlined.d0aa47da.js +2 -0
- abstra_statics/dist/assets/Files.6ea18d46.js +2 -0
- abstra_statics/dist/assets/{Form.8077681f.js → Form.09de384c.js} +2 -2
- abstra_statics/dist/assets/{FormRunner.055e2c45.js → FormRunner.15be6fa0.js} +2 -2
- abstra_statics/dist/assets/{Home.0ef22910.js → Home.782c5702.js} +2 -2
- abstra_statics/dist/assets/Home.7c495aa9.js +2 -0
- abstra_statics/dist/assets/{Live.e1261458.js → Live.48c10605.js} +2 -2
- abstra_statics/dist/assets/LoadingContainer.82ac3d44.js +2 -0
- abstra_statics/dist/assets/LoadingOutlined.66639b08.js +2 -0
- abstra_statics/dist/assets/Login.4a05f5c5.js +2 -0
- abstra_statics/dist/assets/{Login.041361ea.js → Login.4e852955.js} +2 -2
- 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
- abstra_statics/dist/assets/Logo.65e0b37c.js +2 -0
- abstra_statics/dist/assets/{Logs.f76cde12.js → Logs.7d1acf32.js} +2 -2
- abstra_statics/dist/assets/{LogsController.addd81bf.js → LogsController.0eb2eb30.js} +2 -2
- abstra_statics/dist/assets/Main.0313f4fc.js +2 -0
- abstra_statics/dist/assets/{MockForm.c9441864.js → MockForm.0b819a52.js} +2 -2
- abstra_statics/dist/assets/Navbar.ef64aa09.js +2 -0
- abstra_statics/dist/assets/NewEditor.b9c410fe.css +1 -0
- abstra_statics/dist/assets/NewEditor.c928dbe9.js +8 -0
- abstra_statics/dist/assets/OidcLoginCallback.42a7c4f9.js +2 -0
- abstra_statics/dist/assets/OidcLogoutCallback.35931a68.js +2 -0
- abstra_statics/dist/assets/OmniChat.73d9f6bb.js +6 -0
- abstra_statics/dist/assets/OmniChat.a21fec40.css +1 -0
- abstra_statics/dist/assets/{OnboardingView.fbc4b6fe.js → OnboardingView.25042384.js} +2 -2
- abstra_statics/dist/assets/{Organization.bc495099.js → Organization.66f64939.js} +2 -2
- abstra_statics/dist/assets/Organizations.47868beb.js +2 -0
- abstra_statics/dist/assets/{PhArrowCounterClockwise.vue.156bcd89.js → PhArrowCounterClockwise.vue.78877a50.js} +2 -2
- abstra_statics/dist/assets/{PhArrowSquareOut.vue.d0c95a06.js → PhArrowSquareOut.vue.2ddfc219.js} +2 -2
- abstra_statics/dist/assets/{PhBookBookmark.vue.42e49494.js → PhBookBookmark.vue.41108214.js} +2 -2
- abstra_statics/dist/assets/{PhChats.vue.54d692e4.js → PhChats.vue.71e5cb89.js} +2 -2
- abstra_statics/dist/assets/{PhClockCounterClockwise.vue.d47d66ba.js → PhClockCounterClockwise.vue.854c3cb5.js} +2 -2
- abstra_statics/dist/assets/{PhCopy.vue.a0d9b0ec.js → PhCopy.vue.d116ddfb.js} +2 -2
- abstra_statics/dist/assets/{PhCopySimple.vue.43c74ebe.js → PhCopySimple.vue.5d0f839d.js} +2 -2
- abstra_statics/dist/assets/{PhCube.vue.498c014d.js → PhCube.vue.abf4a034.js} +2 -2
- abstra_statics/dist/assets/PhDatabase.vue.a94d95f6.js +2 -0
- abstra_statics/dist/assets/{PhDotsThreeVertical.vue.0ea03d82.js → PhDotsThreeVertical.vue.5e8ae2a9.js} +2 -2
- abstra_statics/dist/assets/{PhDownloadSimple.vue.c92aeaff.js → PhDownloadSimple.vue.e88f64f1.js} +2 -2
- abstra_statics/dist/assets/{PhFolderPlus.vue.0c210f8d.js → PhFolderPlus.vue.21d377a3.js} +2 -2
- abstra_statics/dist/assets/{PhGear.vue.86c3014a.js → PhGear.vue.363dd83c.js} +2 -2
- abstra_statics/dist/assets/{PhKey.vue.72ce23d3.js → PhKey.vue.23f3a465.js} +2 -2
- abstra_statics/dist/assets/{PhPencil.vue.80ed4b2e.js → PhPencil.vue.feb383e2.js} +2 -2
- abstra_statics/dist/assets/{PhPencilSimple.vue.0046d784.js → PhPencilSimple.vue.ec0eebb4.js} +2 -2
- abstra_statics/dist/assets/{PhRocket.vue.f3302a7e.js → PhRocket.vue.261a42b2.js} +2 -2
- abstra_statics/dist/assets/{PhSignOut.vue.c9150da4.js → PhSignOut.vue.d1d6498f.js} +2 -2
- abstra_statics/dist/assets/{PhSparkle.vue.84ea95fc.js → PhSparkle.vue.b6712d34.js} +2 -2
- abstra_statics/dist/assets/{PhUserList.vue.bce47902.js → PhUserList.vue.e0b8c21b.js} +2 -2
- abstra_statics/dist/assets/{PhUsersThree.vue.0a84dfa4.js → PhUsersThree.vue.8889f957.js} +2 -2
- abstra_statics/dist/assets/PhWarningCircle.vue.2087be7d.js +2 -0
- abstra_statics/dist/assets/{PhWebhooksLogo.vue.a704632d.js → PhWebhooksLogo.vue.d164db1e.js} +2 -2
- abstra_statics/dist/assets/{PlayerConfigProvider.26b585a1.js → PlayerConfigProvider.28e29025.js} +2 -2
- abstra_statics/dist/assets/{PlayerNavbar.0fa6f760.js → PlayerNavbar.aaad1dfd.js} +2 -2
- abstra_statics/dist/assets/Project.2de506d7.js +2 -0
- abstra_statics/dist/assets/{ProjectLogin.934271a6.js → ProjectLogin.22c8b093.js} +2 -2
- abstra_statics/dist/assets/{ProjectSettings.2bf7e6c8.js → ProjectSettings.d065c292.js} +2 -2
- abstra_statics/dist/assets/{ProjectsView.ed31b921.js → ProjectsView.cbd118ac.js} +2 -2
- abstra_statics/dist/assets/{SaveButton.fdf70b31.js → SaveButton.428227de.js} +2 -2
- abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.6d724b05.js +2 -0
- abstra_statics/dist/assets/{Sidebar.e69f49bd.css → Sidebar.29baeab0.css} +1 -1
- abstra_statics/dist/assets/{Sidebar.781afa0a.js → Sidebar.41173d8e.js} +2 -2
- abstra_statics/dist/assets/Sql.90e6e2ba.css +1 -0
- abstra_statics/dist/assets/Sql.c070dd2c.js +5 -0
- abstra_statics/dist/assets/Steps.dd51a108.js +2 -0
- abstra_statics/dist/assets/TableCard.529112b9.css +1 -0
- abstra_statics/dist/assets/TableCard.c9a1cf41.js +2 -0
- abstra_statics/dist/assets/TableEditor.1bc47a95.js +2 -0
- abstra_statics/dist/assets/TableEditor.5853a363.css +1 -0
- abstra_statics/dist/assets/Tables.eff119eb.js +2 -0
- abstra_statics/dist/assets/TablesDiagram.a588e7ff.css +1 -0
- abstra_statics/dist/assets/TablesDiagram.d633acaf.js +15 -0
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.cf7e34c5.js +2 -0
- abstra_statics/dist/assets/{Tasks.ee450480.js → Tasks.c311b05f.js} +2 -2
- abstra_statics/dist/assets/{UploadOutlined.e3072945.js → UploadOutlined.9aa845de.js} +2 -2
- abstra_statics/dist/assets/View.dd7ba25a.js +2 -0
- 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
- abstra_statics/dist/assets/{Watermark.891eee9f.js → Watermark.9c9358e3.js} +2 -2
- abstra_statics/dist/assets/{WebEditor.7409cd48.js → WebEditor.83f2a960.js} +2 -2
- abstra_statics/dist/assets/WidgetPreview.7c6a231c.js +2 -0
- abstra_statics/dist/assets/ant-design.42419021.js +2 -0
- abstra_statics/dist/assets/apiKey.403049eb.js +2 -0
- abstra_statics/dist/assets/asyncComputed.47aec2b5.js +2 -0
- abstra_statics/dist/assets/{build.8fa1a961.js → build.45b511b6.js} +2 -2
- abstra_statics/dist/assets/colorHelpers.50ced1e9.js +2 -0
- abstra_statics/dist/assets/console.f0f09e6f.js +17 -0
- abstra_statics/dist/assets/constants.d569f33d.js +2 -0
- abstra_statics/dist/assets/{contracts.generated.c4057ed0.js → contracts.generated.aefe8d0a.js} +2 -2
- abstra_statics/dist/assets/{cssMode.4c65b876.js → cssMode.23271d4a.js} +2 -2
- abstra_statics/dist/assets/{datetime.e5660676.js → datetime.82608dfb.js} +2 -2
- abstra_statics/dist/assets/dayjs.7f71c60a.js +2 -0
- abstra_statics/dist/assets/editor.02184ced.js +2 -0
- abstra_statics/dist/assets/editor.main.0f931e87.js +2 -0
- abstra_statics/dist/assets/fetch.1b3d01a0.js +2 -0
- abstra_statics/dist/assets/files.8b58ee7e.js +2 -0
- abstra_statics/dist/assets/folder.13d3acac.js +2 -0
- abstra_statics/dist/assets/{freemarker2.1d872d48.js → freemarker2.f79b510b.js} +2 -2
- abstra_statics/dist/assets/{handlebars.41fc6db8.js → handlebars.07d5febe.js} +2 -2
- abstra_statics/dist/assets/{html.967e3c6d.js → html.7d6a59b4.js} +3 -3
- abstra_statics/dist/assets/{htmlMode.d38ab72a.js → htmlMode.7779ff94.js} +2 -2
- abstra_statics/dist/assets/{index.8e871bae.js → index.482df04a.js} +2 -2
- abstra_statics/dist/assets/{index.4b93c8ad.js → index.581e2edd.js} +2 -2
- abstra_statics/dist/assets/index.966ac1b9.js +2 -0
- abstra_statics/dist/assets/{index.9021ba5d.js → index.c7a996a6.js} +2 -2
- abstra_statics/dist/assets/{index.03d222dd.js → index.c8a56795.js} +2 -2
- abstra_statics/dist/assets/{index.5f3f38ed.js → index.d31da2c3.js} +2 -2
- abstra_statics/dist/assets/{index.51dbb698.js → index.d53182ed.js} +2 -2
- abstra_statics/dist/assets/{index.b762f5e8.js → index.e71a5f84.js} +2 -2
- abstra_statics/dist/assets/{javascript.0935bea2.js → javascript.4c528c2c.js} +3 -3
- abstra_statics/dist/assets/{jsonMode.2860b71c.js → jsonMode.d6441e9d.js} +2 -2
- abstra_statics/dist/assets/{jwt-decode.esm.7f2ef0df.js → jwt-decode.esm.54a1ea22.js} +8 -8
- abstra_statics/dist/assets/linters.a0f2aa84.js +2 -0
- abstra_statics/dist/assets/{liquid.1bae5f6b.js → liquid.0c441ad2.js} +2 -2
- abstra_statics/dist/assets/member.2260c37e.js +2 -0
- abstra_statics/dist/assets/{metadata.39f9b9ba.js → metadata.0098e20c.js} +2 -2
- abstra_statics/dist/assets/omniChatStore.dd7a1c46.js +8 -0
- abstra_statics/dist/assets/{organization.a877b653.js → organization.668d1b58.js} +2 -2
- abstra_statics/dist/assets/player.4ab4aed5.js +2 -0
- abstra_statics/dist/assets/{plotly.min.d3f75723.js → plotly.min.2a87d7e2.js} +2 -2
- abstra_statics/dist/assets/polling.b5a32c22.js +2 -0
- abstra_statics/dist/assets/{project.d22a89ee.js → project.1b8374f4.js} +2 -2
- abstra_statics/dist/assets/{python.4c1a1300.js → python.7ac27a56.js} +3 -3
- abstra_statics/dist/assets/{razor.ba8bdb33.js → razor.860a0279.js} +2 -2
- abstra_statics/dist/assets/{record.4ffc477c.js → record.e83a2eb2.js} +2 -2
- abstra_statics/dist/assets/{redirect.ce3c0f65.js → redirect.586749f4.js} +2 -2
- abstra_statics/dist/assets/{repository.360feb8f.js → repository.3a331f0f.js} +2 -2
- abstra_statics/dist/assets/{repository.ab3036a9.js → repository.66c7567c.js} +2 -2
- abstra_statics/dist/assets/router.06ee2b9d.js +2 -0
- abstra_statics/dist/assets/router.4dfadf5d.js +18 -0
- abstra_statics/dist/assets/string.61e11a30.js +2 -0
- abstra_statics/dist/assets/{tables.be1c51f8.js → tables.1bcb1140.js} +2 -2
- abstra_statics/dist/assets/{tasksController.bf12e264.js → tasksController.f3adf725.js} +2 -2
- abstra_statics/dist/assets/{toggleHighContrast.c4e1b24d.js → toggleHighContrast.9535bf54.js} +7 -7
- abstra_statics/dist/assets/{tsMode.da264aae.js → tsMode.c0f9fe1a.js} +2 -2
- abstra_statics/dist/assets/{typescript.db5d7517.js → typescript.310eae6d.js} +3 -3
- abstra_statics/dist/assets/url.f5664225.js +2 -0
- abstra_statics/dist/assets/{useCodebaseEvents.42573b00.js → useCodebaseEvents.276cc8f0.js} +2 -2
- abstra_statics/dist/assets/useTables.18fc3efd.js +2 -0
- abstra_statics/dist/assets/userStore.6ab1e5ac.js +2 -0
- abstra_statics/dist/assets/uuid.5b8ba8af.js +2 -0
- abstra_statics/dist/assets/vue-flow-background.af096866.js +2 -0
- abstra_statics/dist/assets/vue-flow-core.6cb99d32.js +22 -0
- abstra_statics/dist/assets/{vue-quill.esm-bundler.37119951.js → vue-quill.esm-bundler.e3d34d0e.js} +2 -2
- abstra_statics/dist/assets/{workspaceStore.50ef2df1.js → workspaceStore.fac1e9a9.js} +2 -2
- abstra_statics/dist/assets/{xml.94b88503.js → xml.04864db4.js} +3 -3
- abstra_statics/dist/assets/{yaml.73b7d5ce.js → yaml.f30375fe.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/AbstraLogo.vue_vue_type_script_setup_true_lang.3f03a3ef.js +0 -2
- abstra_statics/dist/assets/ApiKeys.cb561e62.js +0 -2
- abstra_statics/dist/assets/App.dc82115f.js +0 -2
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.3640ec1c.js +0 -2
- abstra_statics/dist/assets/ConnectorsView.b428e487.js +0 -2
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.506f28c6.js +0 -2
- abstra_statics/dist/assets/ContentLayout.228d2328.js +0 -2
- abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.61381525.js +0 -2
- abstra_statics/dist/assets/EnvVars.242b97c2.js +0 -2
- abstra_statics/dist/assets/Error.466dbb94.js +0 -2
- abstra_statics/dist/assets/ExclamationCircleOutlined.6d10f60b.js +0 -2
- abstra_statics/dist/assets/Files.104385dd.js +0 -2
- abstra_statics/dist/assets/Home.80c7e349.js +0 -2
- abstra_statics/dist/assets/LoadingContainer.6e2b63e4.js +0 -2
- abstra_statics/dist/assets/LoadingOutlined.cd84d9c9.js +0 -2
- abstra_statics/dist/assets/Login.409f4a11.js +0 -2
- abstra_statics/dist/assets/Logo.2de02c4a.js +0 -2
- abstra_statics/dist/assets/Main.4370ed68.js +0 -2
- abstra_statics/dist/assets/Navbar.07ba9452.js +0 -2
- abstra_statics/dist/assets/NewEditor.769f4459.js +0 -8
- abstra_statics/dist/assets/NewEditor.d6e41a05.css +0 -1
- abstra_statics/dist/assets/OidcLoginCallback.a89857fe.js +0 -2
- abstra_statics/dist/assets/OidcLogoutCallback.d151c695.js +0 -2
- abstra_statics/dist/assets/OmniChat.0f64dfec.css +0 -1
- abstra_statics/dist/assets/OmniChat.d015bfa8.js +0 -6
- abstra_statics/dist/assets/Organizations.b630803f.js +0 -2
- abstra_statics/dist/assets/PhPencilSimpleLine.vue.34633dfa.js +0 -2
- abstra_statics/dist/assets/Project.c03610d3.js +0 -2
- abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.3bbea426.js +0 -2
- abstra_statics/dist/assets/Sql.3cdc910a.css +0 -1
- abstra_statics/dist/assets/Sql.b6aa38ca.js +0 -5
- abstra_statics/dist/assets/Steps.7c7e4a4a.js +0 -2
- abstra_statics/dist/assets/TableEditor.1e680eaf.css +0 -1
- abstra_statics/dist/assets/TableEditor.dc1b4a2d.js +0 -2
- abstra_statics/dist/assets/Tables.de30953b.js +0 -2
- abstra_statics/dist/assets/TablesDiagram.1ec45dd9.css +0 -1
- abstra_statics/dist/assets/TablesDiagram.97d6a43f.js +0 -15
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.63aa07d0.js +0 -2
- abstra_statics/dist/assets/View.617ad8d8.js +0 -2
- abstra_statics/dist/assets/WidgetPreview.99f14714.js +0 -2
- abstra_statics/dist/assets/ant-design.4952c8fb.js +0 -2
- abstra_statics/dist/assets/apiKey.864dc66b.js +0 -2
- abstra_statics/dist/assets/asyncComputed.25309626.js +0 -2
- abstra_statics/dist/assets/colorHelpers.71d6d61d.js +0 -2
- abstra_statics/dist/assets/console.3d4702c3.js +0 -25
- abstra_statics/dist/assets/constants.56e8988f.js +0 -2
- abstra_statics/dist/assets/dayjs.c54f8edb.js +0 -2
- abstra_statics/dist/assets/editor.6d0baf6f.js +0 -2
- abstra_statics/dist/assets/editor.main.65812c73.js +0 -2
- abstra_statics/dist/assets/fetch.5136a62d.js +0 -2
- abstra_statics/dist/assets/folder.d7d65e5b.js +0 -2
- abstra_statics/dist/assets/index.23283fbb.js +0 -2
- abstra_statics/dist/assets/index.58e29274.js +0 -2
- abstra_statics/dist/assets/linters.640d6098.js +0 -2
- abstra_statics/dist/assets/member.b7ac8000.js +0 -2
- abstra_statics/dist/assets/omniChatStore.3431c026.js +0 -8
- abstra_statics/dist/assets/player.30593e18.js +0 -2
- abstra_statics/dist/assets/polling.d1c934c7.js +0 -2
- abstra_statics/dist/assets/router.7f571832.js +0 -2
- abstra_statics/dist/assets/router.8fd5b2ad.js +0 -10
- abstra_statics/dist/assets/string.2ed1cde3.js +0 -2
- abstra_statics/dist/assets/url.8583a595.js +0 -2
- abstra_statics/dist/assets/userStore.73b89fbb.js +0 -2
- abstra_statics/dist/assets/uuid.dadede91.js +0 -2
- abstra_statics/dist/assets/vue-flow-background.d2772d9a.js +0 -22
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/WHEEL +0 -0
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/entry_points.txt +0 -0
- {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=
|
|
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
|
|
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()
|
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"
|
|
@@ -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
|
+
]
|