fuse-io 0.1.30__tar.gz → 0.1.57__tar.gz
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.
- {fuse_io-0.1.30 → fuse_io-0.1.57}/MANIFEST.in +1 -0
- {fuse_io-0.1.30/fuse_io.egg-info → fuse_io-0.1.57}/PKG-INFO +1 -5
- fuse_io-0.1.57/fuse/ai/router.py +43 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/ai/service.py +181 -35
- fuse_io-0.1.57/fuse/alembic/versions/7a0fd1dc4902_remove_superuser.py +33 -0
- fuse_io-0.1.57/fuse/alembic/versions/7edc63646d26_add_credentials_table.py +41 -0
- fuse_io-0.1.57/fuse/alembic/versions/debec76c1cf8_initial_migration.py +114 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/api.py +0 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/crud_user.py +0 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/dependencies.py +0 -6
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/router.py +1 -25
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/schemas.py +0 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/service.py +0 -3
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/cli.py +25 -4
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/config.py +7 -38
- fuse_io-0.1.57/fuse/credentials/models.py +26 -0
- fuse_io-0.1.57/fuse/credentials/router.py +513 -0
- fuse_io-0.1.57/fuse/credentials/service.py +276 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/database.py +3 -4
- fuse_io-0.1.57/fuse/initial_fuse.db +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/logger.py +0 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/main.py +0 -7
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/models.py +2 -1
- fuse_io-0.1.57/fuse/static/404/index.html +1 -0
- fuse_io-0.1.57/fuse/static/404.html +1 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/__next.__PAGE__.txt +2 -2
- fuse_io-0.1.57/fuse/static/__next._full.txt +24 -0
- fuse_io-0.1.57/fuse/static/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/__next._tree.txt +3 -2
- fuse_io-0.1.57/fuse/static/_next/static/AvepNa0wqMBJJaKWx9jp2/_buildManifest.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/bAsbGnh27hobCWq6gYKAq/_ssgManifest.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/1692-a402f4a4fcaf7b29.js +5 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/1704-99cc2ea208d98cb0.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/1950-70f6edfc3f49b339.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/1963-d28a6db5ff807527.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/232.c883d640f7157775.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/2842-88d6ea1ddfa4c472.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/3038-598d667e3d5ea764.js +30 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/3509-92c0624ea5210c8a.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/3794-04fa707794cee3fc.js +2 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/4831-2650d23954cfe85f.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/4bd1b696-e5d7c65570c947b7.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/573-4b72224474d6755a.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/585-b70392236824b164.js +43 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/6040-4e3e79454e3ce7cf.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/7152-7978ade421a25c37.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/7621-20d82d6a1007addd.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/7856-044a4109806f2a2d.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/7988-891258e42d4e9cb9.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/8343-4abaf4b94ff48f9a.js +3 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/8376-ef78e632aabf30d1.js +9 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/8500-98e13bcce54aa7a0.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/8547-58d8503b201666a3.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/9903-a77a05716944e520.js +9 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/ai-create-example/page-70ceb48a63cfca66.js +11 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/analytics/page-992337da93734999.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/credentials/page-7e4cc6437c0633e9.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/dashboard/page-ad0218038e730e18.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/executions/page-ad7f99bd73e489e9.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/help/page-356b1311d0259b76.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/layout-2822b13d2fbf79fc.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/settings/page-21ddbcb4288d11e3.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/templates/page-adcf4c1235f2abd0.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/variables/page-51455efcaf5cf739.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/workflows/page-b2a58db616cdcb70.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/_global-error/page-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/_not-found/page-313af5f7b44a4219.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/auth/layout-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/auth/login/page-8001afc0c0cef789.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/auth/register/page-02132d2e011dbec7.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/credentials-test/page-13091e893fe38fd8.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/error-408c6bff597b9d0e.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/global-error-ab2bae883ee0e860.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/layout-2ac4c5b8cbb2c64d.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/loading-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/oauth/callback/page-cdaebdec1d4c4d97.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/page-502f3458c458bd75.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/[id]/error-b393ec0b558e28ac.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/[id]/loading-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/[id]/page-636e52c0d2fa9d9b.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/error-5a420e4cf1195dbd.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/loading-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/c37d3baf-7f0d73575bc82fee.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/framework-81b2e59ffe13bb24.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/main-832b18574d412547.js +5 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/main-app-14c06b7adeda3bca.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/app-error-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/forbidden-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/not-found-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/unauthorized-bd43e16e28d6b5c5.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/chunks/webpack-03fc999381a8cb79.js +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/css/1cb804ccb5b9c075.css +1 -0
- fuse_io-0.1.57/fuse/static/_next/static/css/4a300d88a66b0638.css +3 -0
- fuse_io-0.1.57/fuse/static/_not-found/__next._full.txt +20 -0
- fuse_io-0.1.57/fuse/static/_not-found/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/_not-found/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_not-found/__next._not-found.txt +1 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_not-found/__next._tree.txt +3 -2
- fuse_io-0.1.57/fuse/static/_not-found/index.html +1 -0
- fuse_io-0.1.57/fuse/static/_not-found/index.txt +20 -0
- fuse_io-0.1.57/fuse/static/ai-create-example/__next.!KG1haW4p.ai-create-example.__PAGE__.txt +9 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/ai-create-example/__next.!KG1haW4p.ai-create-example.txt +1 -1
- {fuse_io-0.1.30/fuse/static/workflows → fuse_io-0.1.57/fuse/static/ai-create-example}/__next.!KG1haW4p.txt +2 -2
- fuse_io-0.1.57/fuse/static/ai-create-example/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/ai-create-example/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/ai-create-example/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/ai-create-example/__next._tree.txt +3 -2
- fuse_io-0.1.57/fuse/static/ai-create-example/index.html +1 -0
- fuse_io-0.1.57/fuse/static/ai-create-example/index.txt +29 -0
- fuse_io-0.1.30/fuse/static/ai-create-example/__next.!KG1haW4p.ai-create-example.__PAGE__.txt → fuse_io-0.1.57/fuse/static/analytics/__next.!KG1haW4p.analytics.__PAGE__.txt +2 -2
- fuse_io-0.1.57/fuse/static/analytics/__next.!KG1haW4p.analytics.txt +4 -0
- {fuse_io-0.1.30/fuse/static/ai-create-example → fuse_io-0.1.57/fuse/static/analytics}/__next.!KG1haW4p.txt +2 -2
- fuse_io-0.1.57/fuse/static/analytics/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/analytics/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/analytics/__next._index.txt +11 -0
- fuse_io-0.1.57/fuse/static/analytics/__next._tree.txt +4 -0
- fuse_io-0.1.57/fuse/static/analytics/index.html +1 -0
- fuse_io-0.1.57/fuse/static/analytics/index.txt +29 -0
- fuse_io-0.1.57/fuse/static/auth/login/__next._full.txt +24 -0
- fuse_io-0.1.57/fuse/static/auth/login/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/auth/login/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/login/__next._tree.txt +3 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/login/__next.auth.login.__PAGE__.txt +2 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/login/__next.auth.login.txt +1 -1
- fuse_io-0.1.57/fuse/static/auth/login/__next.auth.txt +4 -0
- fuse_io-0.1.57/fuse/static/auth/login/index.html +1 -0
- fuse_io-0.1.57/fuse/static/auth/login/index.txt +24 -0
- fuse_io-0.1.57/fuse/static/auth/register/__next._full.txt +24 -0
- fuse_io-0.1.57/fuse/static/auth/register/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/auth/register/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/register/__next._tree.txt +3 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/register/__next.auth.register.__PAGE__.txt +2 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/register/__next.auth.register.txt +1 -1
- fuse_io-0.1.57/fuse/static/auth/register/__next.auth.txt +4 -0
- fuse_io-0.1.57/fuse/static/auth/register/index.html +1 -0
- fuse_io-0.1.57/fuse/static/auth/register/index.txt +24 -0
- fuse_io-0.1.57/fuse/static/credentials/__next.!KG1haW4p.credentials.__PAGE__.txt +9 -0
- fuse_io-0.1.57/fuse/static/credentials/__next.!KG1haW4p.credentials.txt +4 -0
- {fuse_io-0.1.30/fuse/static/dashboard → fuse_io-0.1.57/fuse/static/credentials}/__next.!KG1haW4p.txt +2 -2
- fuse_io-0.1.57/fuse/static/credentials/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/credentials/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/credentials/__next._index.txt +11 -0
- fuse_io-0.1.57/fuse/static/credentials/__next._tree.txt +4 -0
- fuse_io-0.1.57/fuse/static/credentials/index.html +1 -0
- fuse_io-0.1.57/fuse/static/credentials/index.txt +29 -0
- fuse_io-0.1.57/fuse/static/credentials-test/__next._full.txt +24 -0
- fuse_io-0.1.57/fuse/static/credentials-test/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/credentials-test/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/credentials-test/__next._tree.txt +3 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/credentials-test/__next.credentials-test.__PAGE__.txt +2 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/credentials-test/__next.credentials-test.txt +1 -1
- fuse_io-0.1.57/fuse/static/credentials-test/index.html +1 -0
- fuse_io-0.1.57/fuse/static/credentials-test/index.txt +24 -0
- fuse_io-0.1.57/fuse/static/dashboard/__next.!KG1haW4p.dashboard.__PAGE__.txt +9 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/dashboard/__next.!KG1haW4p.dashboard.txt +1 -1
- {fuse_io-0.1.30/fuse/static/settings → fuse_io-0.1.57/fuse/static/dashboard}/__next.!KG1haW4p.txt +2 -2
- fuse_io-0.1.57/fuse/static/dashboard/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/dashboard/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/dashboard/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/dashboard/__next._tree.txt +3 -2
- fuse_io-0.1.57/fuse/static/dashboard/index.html +1 -0
- fuse_io-0.1.57/fuse/static/dashboard/index.txt +29 -0
- fuse_io-0.1.57/fuse/static/executions/__next.!KG1haW4p.executions.__PAGE__.txt +9 -0
- fuse_io-0.1.57/fuse/static/executions/__next.!KG1haW4p.executions.txt +4 -0
- fuse_io-0.1.57/fuse/static/executions/__next.!KG1haW4p.txt +7 -0
- fuse_io-0.1.57/fuse/static/executions/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/executions/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/executions/__next._index.txt +11 -0
- fuse_io-0.1.57/fuse/static/executions/__next._tree.txt +4 -0
- fuse_io-0.1.57/fuse/static/executions/index.html +1 -0
- fuse_io-0.1.57/fuse/static/executions/index.txt +29 -0
- fuse_io-0.1.30/fuse/static/settings/__next.!KG1haW4p.settings.__PAGE__.txt → fuse_io-0.1.57/fuse/static/help/__next.!KG1haW4p.help.__PAGE__.txt +2 -2
- fuse_io-0.1.57/fuse/static/help/__next.!KG1haW4p.help.txt +4 -0
- fuse_io-0.1.57/fuse/static/help/__next.!KG1haW4p.txt +7 -0
- {fuse_io-0.1.30/fuse/static/ai-create-example → fuse_io-0.1.57/fuse/static/help}/__next._full.txt +14 -11
- fuse_io-0.1.57/fuse/static/help/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/help/__next._index.txt +11 -0
- fuse_io-0.1.57/fuse/static/help/__next._tree.txt +4 -0
- fuse_io-0.1.57/fuse/static/help/index.html +1 -0
- {fuse_io-0.1.30/fuse/static/ai-create-example → fuse_io-0.1.57/fuse/static/help}/index.txt +14 -11
- fuse_io-0.1.57/fuse/static/index.html +1 -0
- fuse_io-0.1.57/fuse/static/index.txt +24 -0
- fuse_io-0.1.57/fuse/static/logo.png +0 -0
- fuse_io-0.1.57/fuse/static/oauth/callback/__next._full.txt +24 -0
- fuse_io-0.1.57/fuse/static/oauth/callback/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/oauth/callback/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next._tree.txt +3 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next.oauth.callback.__PAGE__.txt +2 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next.oauth.callback.txt +1 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next.oauth.txt +1 -1
- fuse_io-0.1.57/fuse/static/oauth/callback/index.html +1 -0
- fuse_io-0.1.57/fuse/static/oauth/callback/index.txt +24 -0
- fuse_io-0.1.57/fuse/static/settings/__next.!KG1haW4p.settings.__PAGE__.txt +9 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/settings/__next.!KG1haW4p.settings.txt +1 -1
- fuse_io-0.1.57/fuse/static/settings/__next.!KG1haW4p.txt +7 -0
- fuse_io-0.1.57/fuse/static/settings/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/settings/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/settings/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/settings/__next._tree.txt +3 -2
- fuse_io-0.1.57/fuse/static/settings/index.html +1 -0
- fuse_io-0.1.57/fuse/static/settings/index.txt +29 -0
- fuse_io-0.1.57/fuse/static/templates/__next.!KG1haW4p.templates.__PAGE__.txt +9 -0
- fuse_io-0.1.57/fuse/static/templates/__next.!KG1haW4p.templates.txt +4 -0
- fuse_io-0.1.57/fuse/static/templates/__next.!KG1haW4p.txt +7 -0
- fuse_io-0.1.57/fuse/static/templates/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/templates/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/templates/__next._index.txt +11 -0
- fuse_io-0.1.57/fuse/static/templates/__next._tree.txt +4 -0
- fuse_io-0.1.57/fuse/static/templates/index.html +1 -0
- fuse_io-0.1.57/fuse/static/templates/index.txt +29 -0
- fuse_io-0.1.57/fuse/static/variables/__next.!KG1haW4p.txt +7 -0
- fuse_io-0.1.57/fuse/static/variables/__next.!KG1haW4p.variables.__PAGE__.txt +9 -0
- fuse_io-0.1.57/fuse/static/variables/__next.!KG1haW4p.variables.txt +4 -0
- fuse_io-0.1.57/fuse/static/variables/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/variables/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/variables/__next._index.txt +11 -0
- fuse_io-0.1.57/fuse/static/variables/__next._tree.txt +4 -0
- fuse_io-0.1.57/fuse/static/variables/index.html +1 -0
- fuse_io-0.1.57/fuse/static/variables/index.txt +29 -0
- fuse_io-0.1.57/fuse/static/workflows/__next.!KG1haW4p.txt +7 -0
- fuse_io-0.1.57/fuse/static/workflows/__next.!KG1haW4p.workflows.__PAGE__.txt +10 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/__next.!KG1haW4p.workflows.txt +1 -1
- fuse_io-0.1.57/fuse/static/workflows/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/workflows/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/workflows/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/__next._tree.txt +3 -2
- fuse_io-0.1.57/fuse/static/workflows/index.html +1 -0
- fuse_io-0.1.57/fuse/static/workflows/index.txt +29 -0
- fuse_io-0.1.57/fuse/static/workflows/new/__next._full.txt +29 -0
- fuse_io-0.1.57/fuse/static/workflows/new/__next._head.txt +5 -0
- fuse_io-0.1.57/fuse/static/workflows/new/__next._index.txt +11 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next._tree.txt +3 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next.workflows.$d$id.__PAGE__.txt +2 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next.workflows.$d$id.txt +2 -2
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next.workflows.txt +2 -2
- fuse_io-0.1.57/fuse/static/workflows/new/index.html +1 -0
- fuse_io-0.1.57/fuse/static/workflows/new/index.txt +29 -0
- fuse_io-0.1.57/fuse/users/router.py +129 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/pagination.py +2 -2
- fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/agent.py +125 -0
- fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/chat_model.py +40 -0
- fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/memory.py +33 -0
- fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/tool.py +33 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/base.py +1 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/email.py +2 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/form.py +2 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/manual.py +2 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/rss.py +2 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/schedule.py +2 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/webhook.py +2 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/whatsapp.py +2 -1
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/schemas.py +19 -3
- {fuse_io-0.1.30 → fuse_io-0.1.57/fuse_io.egg-info}/PKG-INFO +1 -5
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/SOURCES.txt +127 -16
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/requires.txt +0 -4
- {fuse_io-0.1.30 → fuse_io-0.1.57}/pyproject.toml +7 -5
- {fuse_io-0.1.30 → fuse_io-0.1.57}/uv.lock +1 -160
- fuse_io-0.1.30/fuse/ai/router.py +0 -35
- fuse_io-0.1.30/fuse/alembic/versions/1439949b74ad_add_edge_handles.py +0 -31
- fuse_io-0.1.30/fuse/alembic/versions/1a31ce608336_add_cascade_delete_relationships.py +0 -37
- fuse_io-0.1.30/fuse/alembic/versions/2c7ca0ca6779_add_hashed_password_field_to_user_model.py +0 -29
- fuse_io-0.1.30/fuse/alembic/versions/82e10e9b2e3f_add_spec_column_to_workflownode_and_.py +0 -34
- fuse_io-0.1.30/fuse/alembic/versions/9426be80e78e_add_workflows.py +0 -66
- fuse_io-0.1.30/fuse/alembic/versions/9c0a54914c78_add_max_length_for_string_varchar_.py +0 -65
- fuse_io-0.1.30/fuse/alembic/versions/ceedbe88ef0d_add_v2_config_columns_to_workflow.py +0 -33
- fuse_io-0.1.30/fuse/alembic/versions/d98dd8ec85a3_edit_replace_id_integers_in_all_models_.py +0 -99
- fuse_io-0.1.30/fuse/alembic/versions/dd21742ef7b0_add_execution_models.py +0 -54
- fuse_io-0.1.30/fuse/alembic/versions/e2412789c190_initialize_models.py +0 -54
- fuse_io-0.1.30/fuse/credentials/router.py +0 -199
- fuse_io-0.1.30/fuse/credentials/service.py +0 -181
- fuse_io-0.1.30/fuse/items/__init__.py +0 -9
- fuse_io-0.1.30/fuse/items/crud_item.py +0 -44
- fuse_io-0.1.30/fuse/items/models.py +0 -19
- fuse_io-0.1.30/fuse/items/router.py +0 -97
- fuse_io-0.1.30/fuse/items/schemas.py +0 -34
- fuse_io-0.1.30/fuse/items/service.py +0 -57
- fuse_io-0.1.30/fuse/static/404/index.html +0 -1
- fuse_io-0.1.30/fuse/static/404.html +0 -1
- fuse_io-0.1.30/fuse/static/__next._full.txt +0 -23
- fuse_io-0.1.30/fuse/static/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/_not-found/__next._full.txt +0 -19
- fuse_io-0.1.30/fuse/static/_not-found/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/_not-found/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/_not-found/index.html +0 -1
- fuse_io-0.1.30/fuse/static/_not-found/index.txt +0 -19
- fuse_io-0.1.30/fuse/static/ai-create-example/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/ai-create-example/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/ai-create-example/index.html +0 -1
- fuse_io-0.1.30/fuse/static/auth/login/__next._full.txt +0 -23
- fuse_io-0.1.30/fuse/static/auth/login/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/auth/login/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/auth/login/__next.auth.txt +0 -4
- fuse_io-0.1.30/fuse/static/auth/login/index.html +0 -1
- fuse_io-0.1.30/fuse/static/auth/login/index.txt +0 -23
- fuse_io-0.1.30/fuse/static/auth/register/__next._full.txt +0 -23
- fuse_io-0.1.30/fuse/static/auth/register/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/auth/register/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/auth/register/__next.auth.txt +0 -4
- fuse_io-0.1.30/fuse/static/auth/register/index.html +0 -1
- fuse_io-0.1.30/fuse/static/auth/register/index.txt +0 -23
- fuse_io-0.1.30/fuse/static/credentials-test/__next._full.txt +0 -23
- fuse_io-0.1.30/fuse/static/credentials-test/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/credentials-test/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/credentials-test/index.html +0 -1
- fuse_io-0.1.30/fuse/static/credentials-test/index.txt +0 -23
- fuse_io-0.1.30/fuse/static/dashboard/__next.!KG1haW4p.dashboard.__PAGE__.txt +0 -9
- fuse_io-0.1.30/fuse/static/dashboard/__next._full.txt +0 -26
- fuse_io-0.1.30/fuse/static/dashboard/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/dashboard/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/dashboard/index.html +0 -1
- fuse_io-0.1.30/fuse/static/dashboard/index.txt +0 -26
- fuse_io-0.1.30/fuse/static/index.html +0 -1
- fuse_io-0.1.30/fuse/static/index.txt +0 -23
- fuse_io-0.1.30/fuse/static/oauth/callback/__next._full.txt +0 -23
- fuse_io-0.1.30/fuse/static/oauth/callback/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/oauth/callback/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/oauth/callback/index.html +0 -1
- fuse_io-0.1.30/fuse/static/oauth/callback/index.txt +0 -23
- fuse_io-0.1.30/fuse/static/settings/__next._full.txt +0 -26
- fuse_io-0.1.30/fuse/static/settings/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/settings/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/settings/index.html +0 -1
- fuse_io-0.1.30/fuse/static/settings/index.txt +0 -26
- fuse_io-0.1.30/fuse/static/workflows/__next.!KG1haW4p.workflows.__PAGE__.txt +0 -10
- fuse_io-0.1.30/fuse/static/workflows/__next._full.txt +0 -29
- fuse_io-0.1.30/fuse/static/workflows/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/workflows/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/workflows/index.html +0 -1
- fuse_io-0.1.30/fuse/static/workflows/index.txt +0 -29
- fuse_io-0.1.30/fuse/static/workflows/new/__next._full.txt +0 -26
- fuse_io-0.1.30/fuse/static/workflows/new/__next._head.txt +0 -7
- fuse_io-0.1.30/fuse/static/workflows/new/__next._index.txt +0 -10
- fuse_io-0.1.30/fuse/static/workflows/new/index.html +0 -1
- fuse_io-0.1.30/fuse/static/workflows/new/index.txt +0 -26
- fuse_io-0.1.30/fuse/users/router.py +0 -234
- fuse_io-0.1.30/fuse/workflows/engine/nodes/ai/agent.py +0 -100
- {fuse_io-0.1.30 → fuse_io-0.1.57}/.python-version +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/LICENSE +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/README.md +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/docs/pypi_publishing_guide.md +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/ai/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/README +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/env.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/script.py.mako +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/versions/.keep +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic.ini +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/models.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/utils.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/backend_pre_start.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/base.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/credentials/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/initial_data.py +0 -0
- {fuse_io-0.1.30/fuse/static/_next/static/bAsbGnh27hobCWq6gYKAq → fuse_io-0.1.57/fuse/static/_next/static/AvepNa0wqMBJJaKWx9jp2}/_ssgManifest.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/bAsbGnh27hobCWq6gYKAq/_buildManifest.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/162-d9110b81661c7d7d.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/232.97b298320d3351e9.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/24-4ee5417b9b9b92a9.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/275-f12d66089f519b01.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/324-771510774da7c693.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/361-1ce2845fa2b2c4a4.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/393-d1b3ea65900fdc5e.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/4-bdc965d7dcca4cab.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/4bd1b696-01b4a2ffa8bac205.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/501-397a9f42b1c4da0e.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/547-1833756cc09c3c28.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/794-803d64bb1ca09460.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/814-18bcbd34c09817f1.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/821-04976ebb62352e45.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/93-2937d48fc52107ef.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/ai-create-example/page-0a2e0f0b4460de7c.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/dashboard/page-7e9db37c6737695c.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/layout-5c636818aa3b7ed1.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/settings/page-00bc4735cc93b9be.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/workflows/page-7c3c63a11ae33eed.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/_global-error/page-116e68079fa76e6f.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/_not-found/page-bae0d4902c5585d3.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/auth/layout-116e68079fa76e6f.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/auth/login/page-546ffaa564d327e9.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/auth/register/page-2748b1af5b1b642a.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/credentials-test/page-1d2c37deaa189b43.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/error-033f2fd59b73a2d7.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/global-error-dcd149dc42c5186b.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/layout-d0d5a6a85d213394.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/loading-116e68079fa76e6f.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/oauth/callback/page-eecedf564f689d93.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/page-606905d313079604.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/[id]/error-66ff5093f583ae94.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/[id]/loading-116e68079fa76e6f.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/[id]/page-5459cee4cb66f5bc.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/error-61dbcd88cc0eff5c.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/loading-116e68079fa76e6f.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/c37d3baf-0fedbf5b6ffcd550.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/framework-3311683cffde0ebf.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/main-app-cf50eb2a7e26453d.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/main-d74776772a65895d.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/webpack-b28a02ce1f174559.js +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/css/59d0dfc36eeea694.css +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/css/d1e1fa7731bfdccb.css +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/636a5ac981f94f8b-s.p.woff2 +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/6fe53d21e6e7ebd8-s.woff2 +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/8ebc6e9dde468c4a-s.woff2 +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/9e7b0a821b9dfcb4-s.woff2 +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/users/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/cache.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/circuit_breaker.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/code_sanitizer.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/feature_flags.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/health.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/rate_limit.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/redis_client.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/request_id.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/security.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/worker.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/code_execution.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/crud_workflow.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/constants.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/core.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/error_handler.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/errors.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/executor.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/graph.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/code.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/data.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/discord.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/email.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/google_sheets.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/http_request.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/slack.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/utility.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/whatsapp.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/ai/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/ai/llm.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/__init__.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/delay.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/if_node.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/loop.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/merge.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/parallel.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/pause.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/switch.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/registry.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/periodic_scheduler.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/runtime/code.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/runtime/http.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/runtime/internal.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/scheduler.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/state.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/logger.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/models.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/router.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/service.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/types.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/utils/templating.py +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/dependency_links.txt +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/entry_points.txt +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/top_level.txt +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/scripts/format.sh +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/scripts/lint.sh +0 -0
- {fuse_io-0.1.30 → fuse_io-0.1.57}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fuse-io
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.57
|
|
4
4
|
Summary: Fuse - Workflow automation. A powerful local-first automation platform with visual builder, AI integration, and extensive node library.
|
|
5
5
|
Author-email: Bibek Timilsina <bibektimilsina@example.com>
|
|
6
6
|
License: MIT
|
|
@@ -42,16 +42,12 @@ Requires-Dist: jinja2>=3.1.6
|
|
|
42
42
|
Requires-Dist: jsonschema>=4.25.1
|
|
43
43
|
Requires-Dist: openai>=2.8.1
|
|
44
44
|
Requires-Dist: passlib>=1.7.4
|
|
45
|
-
Requires-Dist: psycopg>=3.3.2
|
|
46
|
-
Requires-Dist: psycopg-binary>=3.3.2
|
|
47
|
-
Requires-Dist: psycopg2-binary>=2.9.11
|
|
48
45
|
Requires-Dist: pydantic>=2.11.7
|
|
49
46
|
Requires-Dist: pydantic-settings>=2.10.1
|
|
50
47
|
Requires-Dist: pyjwt>=2.10.1
|
|
51
48
|
Requires-Dist: python-multipart>=0.0.20
|
|
52
49
|
Requires-Dist: redis>=7.1.0
|
|
53
50
|
Requires-Dist: rich>=14.2.0
|
|
54
|
-
Requires-Dist: sentry-sdk>=2.37.0
|
|
55
51
|
Requires-Dist: sqlmodel>=0.0.24
|
|
56
52
|
Requires-Dist: tenacity>=9.1.2
|
|
57
53
|
Requires-Dist: uvicorn[standard]>=0.35.0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
from fastapi import APIRouter, HTTPException
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from fuse.auth.dependencies import CurrentUser
|
|
6
|
+
from fuse.workflows.schemas import AIWorkflowRequest, AIWorkflowResponse
|
|
7
|
+
from fuse.ai.service import ai_service
|
|
8
|
+
from fuse.credentials.service import get_full_credential_by_id
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
router = APIRouter()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@router.post("/generate", response_model=AIWorkflowResponse)
|
|
16
|
+
async def generate_workflow_with_ai(
|
|
17
|
+
request: AIWorkflowRequest,
|
|
18
|
+
current_user: CurrentUser,
|
|
19
|
+
) -> Any:
|
|
20
|
+
"""
|
|
21
|
+
Generate workflow with AI using either global keys or user-provided credentials.
|
|
22
|
+
"""
|
|
23
|
+
try:
|
|
24
|
+
credential_data = None
|
|
25
|
+
if request.credential_id:
|
|
26
|
+
credential_data = get_full_credential_by_id(str(request.credential_id))
|
|
27
|
+
if not credential_data:
|
|
28
|
+
raise HTTPException(status_code=404, detail="Credential not found")
|
|
29
|
+
|
|
30
|
+
result = await ai_service.generate_workflow_from_prompt(
|
|
31
|
+
prompt=request.prompt,
|
|
32
|
+
model=request.model,
|
|
33
|
+
current_nodes=request.current_nodes,
|
|
34
|
+
current_edges=request.current_edges,
|
|
35
|
+
credential_data=credential_data,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
return result
|
|
39
|
+
except HTTPException:
|
|
40
|
+
raise
|
|
41
|
+
except Exception as e:
|
|
42
|
+
logger.error(f"AI generation failed: {e}")
|
|
43
|
+
raise HTTPException(status_code=500, detail=f"AI generation failed: {str(e)}")
|
|
@@ -8,6 +8,7 @@ from google import genai
|
|
|
8
8
|
from openai import OpenAI
|
|
9
9
|
from fuse.config import settings
|
|
10
10
|
from fuse.utils.circuit_breaker import CircuitBreakerOpenError, CircuitBreakers
|
|
11
|
+
import httpx
|
|
11
12
|
|
|
12
13
|
logger = logging.getLogger(__name__)
|
|
13
14
|
# Import nodes to ensure they are registered
|
|
@@ -56,32 +57,44 @@ class AIWorkflowService:
|
|
|
56
57
|
model: str = "openrouter",
|
|
57
58
|
current_nodes: Optional[List[dict]] = None,
|
|
58
59
|
current_edges: Optional[List[dict]] = None,
|
|
60
|
+
credential_data: Optional[Dict[str, Any]] = None,
|
|
59
61
|
) -> Dict[str, Any]:
|
|
60
62
|
"""Generate workflow nodes and edges from natural language prompt"""
|
|
61
63
|
system_prompt = self._get_system_prompt(current_nodes, current_edges)
|
|
62
64
|
user_prompt = f"USER REQUEST: {prompt}\n\nPlease generate a workflow JSON based on this request."
|
|
63
65
|
|
|
66
|
+
# Override model provider if credential specifies one
|
|
67
|
+
provider = model
|
|
68
|
+
if credential_data:
|
|
69
|
+
provider = credential_data.get("provider", model)
|
|
70
|
+
|
|
64
71
|
try:
|
|
65
|
-
if
|
|
72
|
+
if provider == "gemini":
|
|
66
73
|
response_text = await self._generate_with_gemini(
|
|
67
|
-
f"{system_prompt}\n\n{user_prompt}"
|
|
74
|
+
f"{system_prompt}\n\n{user_prompt}", credential_data=credential_data
|
|
68
75
|
)
|
|
69
|
-
elif
|
|
76
|
+
elif provider == "openai":
|
|
70
77
|
response_text = await self._generate_with_openai(
|
|
71
|
-
f"{system_prompt}\n\n{user_prompt}"
|
|
78
|
+
f"{system_prompt}\n\n{user_prompt}",
|
|
79
|
+
credential_data=credential_data,
|
|
80
|
+
model_name=model if model != "openai" else "gpt-4",
|
|
72
81
|
)
|
|
73
|
-
elif
|
|
82
|
+
elif provider == "anthropic":
|
|
74
83
|
response_text = await self._generate_with_anthropic(
|
|
75
|
-
f"{system_prompt}\n\n{user_prompt}"
|
|
84
|
+
f"{system_prompt}\n\n{user_prompt}", credential_data=credential_data
|
|
76
85
|
)
|
|
77
|
-
elif
|
|
86
|
+
elif provider == "openrouter":
|
|
78
87
|
response_text = await self._generate_with_openrouter(
|
|
79
|
-
f"{system_prompt}\n\n{user_prompt}"
|
|
88
|
+
f"{system_prompt}\n\n{user_prompt}",
|
|
89
|
+
model=model if model != "openrouter" else "deepseek/deepseek-r1",
|
|
90
|
+
credential_data=credential_data,
|
|
80
91
|
)
|
|
81
92
|
else:
|
|
82
93
|
# Default to openrouter if model is unknown
|
|
83
94
|
response_text = await self._generate_with_openrouter(
|
|
84
|
-
f"{system_prompt}\n\n{user_prompt}",
|
|
95
|
+
f"{system_prompt}\n\n{user_prompt}",
|
|
96
|
+
model=model,
|
|
97
|
+
credential_data=credential_data,
|
|
85
98
|
)
|
|
86
99
|
|
|
87
100
|
return self._parse_ai_response(response_text, current_nodes)
|
|
@@ -229,27 +242,47 @@ Do NOT explain anything
|
|
|
229
242
|
Generate one complete workflow JSON that fully satisfies the user request and strictly follows this schema.
|
|
230
243
|
"""
|
|
231
244
|
|
|
232
|
-
async def _generate_with_gemini(
|
|
245
|
+
async def _generate_with_gemini(
|
|
246
|
+
self, prompt: str, credential_data: Optional[Dict] = None
|
|
247
|
+
) -> str:
|
|
233
248
|
"""Generate using Google Gemini"""
|
|
234
|
-
|
|
249
|
+
client = self.gemini_client
|
|
250
|
+
if credential_data:
|
|
251
|
+
api_key = credential_data.get("data", {}).get("api_key")
|
|
252
|
+
if api_key:
|
|
253
|
+
client = genai.Client(api_key=api_key)
|
|
254
|
+
|
|
255
|
+
if not client:
|
|
235
256
|
raise ValueError(
|
|
236
|
-
"Gemini API key not configured. Please set GOOGLE_AI_API_KEY environment variable."
|
|
257
|
+
"Gemini API key not configured. Please set GOOGLE_AI_API_KEY environment variable or provide a credential."
|
|
237
258
|
)
|
|
238
259
|
async with CircuitBreakers.google():
|
|
239
|
-
response =
|
|
260
|
+
response = client.models.generate_content(
|
|
240
261
|
model="gemini-2.0-flash", contents=prompt
|
|
241
262
|
)
|
|
242
263
|
return response.text
|
|
243
264
|
|
|
244
|
-
async def _generate_with_openai(
|
|
265
|
+
async def _generate_with_openai(
|
|
266
|
+
self,
|
|
267
|
+
prompt: str,
|
|
268
|
+
credential_data: Optional[Dict] = None,
|
|
269
|
+
model_name: str = "gpt-4",
|
|
270
|
+
) -> str:
|
|
245
271
|
"""Generate using OpenAI GPT"""
|
|
246
|
-
|
|
272
|
+
client = self.openai_client
|
|
273
|
+
if credential_data:
|
|
274
|
+
api_key = credential_data.get("data", {}).get("api_key")
|
|
275
|
+
base_url = credential_data.get("data", {}).get("base_url")
|
|
276
|
+
if api_key:
|
|
277
|
+
client = OpenAI(api_key=api_key, base_url=base_url)
|
|
278
|
+
|
|
279
|
+
if not client:
|
|
247
280
|
raise ValueError(
|
|
248
|
-
"OpenAI API key not configured. Please set OPENAI_API_KEY environment variable."
|
|
281
|
+
"OpenAI API key not configured. Please set OPENAI_API_KEY environment variable or provide a credential."
|
|
249
282
|
)
|
|
250
283
|
async with CircuitBreakers.openai():
|
|
251
|
-
response =
|
|
252
|
-
model=
|
|
284
|
+
response = client.chat.completions.create(
|
|
285
|
+
model=model_name,
|
|
253
286
|
messages=[
|
|
254
287
|
{
|
|
255
288
|
"role": "system",
|
|
@@ -261,14 +294,22 @@ Generate one complete workflow JSON that fully satisfies the user request and st
|
|
|
261
294
|
)
|
|
262
295
|
return response.choices[0].message.content
|
|
263
296
|
|
|
264
|
-
async def _generate_with_anthropic(
|
|
297
|
+
async def _generate_with_anthropic(
|
|
298
|
+
self, prompt: str, credential_data: Optional[Dict] = None
|
|
299
|
+
) -> str:
|
|
265
300
|
"""Generate using Anthropic Claude"""
|
|
266
|
-
|
|
301
|
+
client = self.anthropic_client
|
|
302
|
+
if credential_data:
|
|
303
|
+
api_key = credential_data.get("data", {}).get("api_key")
|
|
304
|
+
if api_key:
|
|
305
|
+
client = Anthropic(api_key=api_key)
|
|
306
|
+
|
|
307
|
+
if not client:
|
|
267
308
|
raise ValueError(
|
|
268
|
-
"Anthropic API key not configured. Please set ANTHROPIC_API_KEY environment variable."
|
|
309
|
+
"Anthropic API key not configured. Please set ANTHROPIC_API_KEY environment variable or provide a credential."
|
|
269
310
|
)
|
|
270
311
|
async with CircuitBreakers.anthropic():
|
|
271
|
-
response =
|
|
312
|
+
response = client.messages.create(
|
|
272
313
|
model="claude-3-sonnet-20240229",
|
|
273
314
|
max_tokens=2048,
|
|
274
315
|
messages=[{"role": "user", "content": prompt}],
|
|
@@ -276,17 +317,29 @@ Generate one complete workflow JSON that fully satisfies the user request and st
|
|
|
276
317
|
return response.content[0].text
|
|
277
318
|
|
|
278
319
|
async def _generate_with_openrouter(
|
|
279
|
-
self,
|
|
320
|
+
self,
|
|
321
|
+
prompt: str,
|
|
322
|
+
model: str = "deepseek/deepseek-r1",
|
|
323
|
+
credential_data: Optional[Dict] = None,
|
|
280
324
|
) -> str:
|
|
281
325
|
"""Generate using OpenRouter"""
|
|
282
|
-
|
|
326
|
+
client = self.openrouter_client
|
|
327
|
+
if credential_data:
|
|
328
|
+
api_key = credential_data.get("data", {}).get("api_key")
|
|
329
|
+
if api_key:
|
|
330
|
+
client = OpenAI(
|
|
331
|
+
base_url="https://openrouter.ai/api/v1",
|
|
332
|
+
api_key=api_key,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
if not client:
|
|
283
336
|
raise ValueError(
|
|
284
|
-
"OpenRouter API key not configured. Please set OPENROUTER_API_KEY environment variable."
|
|
337
|
+
"OpenRouter API key not configured. Please set OPENROUTER_API_KEY environment variable or provide a credential."
|
|
285
338
|
)
|
|
286
339
|
|
|
287
340
|
# Use a generic HTTP circuit breaker for OpenRouter
|
|
288
341
|
async with CircuitBreakers.http("openrouter-api"):
|
|
289
|
-
response =
|
|
342
|
+
response = client.chat.completions.create(
|
|
290
343
|
model=model,
|
|
291
344
|
messages=[
|
|
292
345
|
{
|
|
@@ -391,6 +444,7 @@ Generate one complete workflow JSON that fully satisfies the user request and st
|
|
|
391
444
|
logger.error(f"AI execution error: {e}")
|
|
392
445
|
raise e
|
|
393
446
|
|
|
447
|
+
|
|
394
448
|
async def call_llm(
|
|
395
449
|
self,
|
|
396
450
|
messages: Optional[List[Dict[str, str]]] = None,
|
|
@@ -413,21 +467,63 @@ Generate one complete workflow JSON that fully satisfies the user request and st
|
|
|
413
467
|
if user_prompt:
|
|
414
468
|
messages.append({"role": "user", "content": user_prompt})
|
|
415
469
|
|
|
416
|
-
|
|
470
|
+
# Determine provider
|
|
471
|
+
provider = (credential.get("provider") or credential.get("type", "unknown")).lower()
|
|
472
|
+
if provider == "ai_provider":
|
|
473
|
+
provider = credential.get("data", {}).get("provider", "unknown").lower()
|
|
474
|
+
|
|
417
475
|
cred_data = credential.get("data", {})
|
|
418
476
|
api_key = cred_data.get("api_key")
|
|
419
477
|
base_url = cred_data.get("base_url")
|
|
420
478
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
479
|
+
# =========================================================================
|
|
480
|
+
# Google AI (OAuth or API Key)
|
|
481
|
+
# =========================================================================
|
|
482
|
+
if provider == "gemini" or provider == "google_ai":
|
|
483
|
+
access_token = cred_data.get("access_token")
|
|
484
|
+
|
|
485
|
+
# Combine formatting for Gemini
|
|
427
486
|
combined_prompt = ""
|
|
428
487
|
for msg in messages:
|
|
429
488
|
combined_prompt += f"{msg['role'].upper()}: {msg['content']}\n\n"
|
|
430
489
|
|
|
490
|
+
# 1. OAuth Access Token (Google AI Login)
|
|
491
|
+
if access_token:
|
|
492
|
+
try:
|
|
493
|
+
target_model = model or "gemini-1.5-pro-latest"
|
|
494
|
+
if "/" in target_model: target_model = target_model.split("/")[-1]
|
|
495
|
+
|
|
496
|
+
async with httpx.AsyncClient() as client:
|
|
497
|
+
resp = await client.post(
|
|
498
|
+
f"https://generativelanguage.googleapis.com/v1beta/models/{target_model}:generateContent",
|
|
499
|
+
headers={
|
|
500
|
+
"Authorization": f"Bearer {access_token}",
|
|
501
|
+
"Content-Type": "application/json"
|
|
502
|
+
},
|
|
503
|
+
json={
|
|
504
|
+
"contents": [{"parts": [{"text": combined_prompt}]}],
|
|
505
|
+
"generationConfig": {"temperature": temperature, "maxOutputTokens": max_tokens}
|
|
506
|
+
},
|
|
507
|
+
timeout=60.0
|
|
508
|
+
)
|
|
509
|
+
if resp.status_code != 200:
|
|
510
|
+
raise ValueError(f"Google AI OAuth Error: {resp.text}")
|
|
511
|
+
|
|
512
|
+
resp_json = resp.json()
|
|
513
|
+
content = resp_json.get("candidates", [{}])[0].get("content", {}).get("parts", [{}])[0].get("text", "")
|
|
514
|
+
return {
|
|
515
|
+
"content": content,
|
|
516
|
+
"usage": {"total_tokens": 0} # Usage not always returned in simple format
|
|
517
|
+
}
|
|
518
|
+
except Exception as e:
|
|
519
|
+
logger.error(f"Google AI OAuth Failed: {e}")
|
|
520
|
+
raise e
|
|
521
|
+
|
|
522
|
+
# 2. Existing API Key Flow
|
|
523
|
+
client = genai.Client(api_key=api_key) if api_key else self.gemini_client
|
|
524
|
+
if not client:
|
|
525
|
+
raise ValueError("Gemini API key not found and no OAuth token provided.")
|
|
526
|
+
|
|
431
527
|
response = client.models.generate_content(
|
|
432
528
|
model=model or "gemini-2.0-flash",
|
|
433
529
|
contents=combined_prompt,
|
|
@@ -454,8 +550,57 @@ Generate one complete workflow JSON that fully satisfies the user request and st
|
|
|
454
550
|
},
|
|
455
551
|
}
|
|
456
552
|
|
|
553
|
+
# =========================================================================
|
|
554
|
+
# GitHub Copilot
|
|
555
|
+
# =========================================================================
|
|
556
|
+
elif provider == "github_copilot":
|
|
557
|
+
copilot_token = cred_data.get("copilot_token")
|
|
558
|
+
if not copilot_token:
|
|
559
|
+
raise ValueError("GitHub Copilot token missing. Please re-authenticate.")
|
|
560
|
+
|
|
561
|
+
headers = {
|
|
562
|
+
"Authorization": f"Bearer {copilot_token}",
|
|
563
|
+
"Editor-Version": "vscode/1.85.0",
|
|
564
|
+
"User-Agent": "GitHubCopilot/1.138.0",
|
|
565
|
+
"Content-Type": "application/json"
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
# Map standard model names to Copilot internal names?
|
|
569
|
+
# Copilot usually supports 'gpt-4', 'gpt-3.5-turbo'.
|
|
570
|
+
# If user sends 'openai/gpt-4', split it.
|
|
571
|
+
copilot_model = model
|
|
572
|
+
if "/" in model:
|
|
573
|
+
copilot_model = model.split("/")[-1]
|
|
574
|
+
|
|
575
|
+
# Copilot often defaults to specific models if not specified or different names.
|
|
576
|
+
# But the API is OpenAI compatible.
|
|
577
|
+
|
|
578
|
+
payload = {
|
|
579
|
+
"messages": messages,
|
|
580
|
+
"model": copilot_model,
|
|
581
|
+
"temperature": temperature,
|
|
582
|
+
"max_tokens": max_tokens
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
async with httpx.AsyncClient() as client:
|
|
586
|
+
resp = await client.post(
|
|
587
|
+
"https://api.githubcopilot.com/chat/completions",
|
|
588
|
+
headers=headers,
|
|
589
|
+
json=payload,
|
|
590
|
+
timeout=60.0
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
if resp.status_code != 200:
|
|
594
|
+
raise ValueError(f"GitHub Copilot API Error ({resp.status_code}): {resp.text}")
|
|
595
|
+
|
|
596
|
+
resp_json = resp.json()
|
|
597
|
+
return {
|
|
598
|
+
"content": resp_json["choices"][0]["message"]["content"],
|
|
599
|
+
"usage": resp_json.get("usage", {})
|
|
600
|
+
}
|
|
601
|
+
|
|
457
602
|
elif provider == "openai" or (provider == "openrouter" and not base_url):
|
|
458
|
-
#
|
|
603
|
+
# ... (existing OpenAI logic) ...
|
|
459
604
|
actual_base_url = base_url or (
|
|
460
605
|
"https://openrouter.ai/api/v1" if provider == "openrouter" else None
|
|
461
606
|
)
|
|
@@ -484,6 +629,7 @@ Generate one complete workflow JSON that fully satisfies the user request and st
|
|
|
484
629
|
}
|
|
485
630
|
|
|
486
631
|
elif provider == "anthropic":
|
|
632
|
+
# ... (existing Anthropic logic) ...
|
|
487
633
|
client = Anthropic(api_key=api_key) if api_key else self.anthropic_client
|
|
488
634
|
if not client:
|
|
489
635
|
raise ValueError("Anthropic API key not found.")
|
|
@@ -512,7 +658,7 @@ Generate one complete workflow JSON that fully satisfies the user request and st
|
|
|
512
658
|
}
|
|
513
659
|
|
|
514
660
|
elif provider == "ai_provider" or base_url:
|
|
515
|
-
#
|
|
661
|
+
# ... (Rest of existing logic) ...
|
|
516
662
|
client = OpenAI(api_key=api_key, base_url=base_url)
|
|
517
663
|
response = client.chat.completions.create(
|
|
518
664
|
model=model,
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""remove_superuser
|
|
2
|
+
|
|
3
|
+
Revision ID: 7a0fd1dc4902
|
|
4
|
+
Revises: 7edc63646d26
|
|
5
|
+
Create Date: 2026-01-19 17:12:48.459465
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from alembic import op
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
import sqlmodel.sql.sqltypes
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# revision identifiers, used by Alembic.
|
|
14
|
+
revision = '7a0fd1dc4902'
|
|
15
|
+
down_revision = '7edc63646d26'
|
|
16
|
+
branch_labels = None
|
|
17
|
+
depends_on = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def upgrade():
|
|
21
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
22
|
+
with op.batch_alter_table('user', schema=None) as batch_op:
|
|
23
|
+
batch_op.drop_column('is_superuser')
|
|
24
|
+
|
|
25
|
+
# ### end Alembic commands ###
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def downgrade():
|
|
29
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
30
|
+
with op.batch_alter_table('user', schema=None) as batch_op:
|
|
31
|
+
batch_op.add_column(sa.Column('is_superuser', sa.BOOLEAN(), nullable=False))
|
|
32
|
+
|
|
33
|
+
# ### end Alembic commands ###
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""add_credentials_table
|
|
2
|
+
|
|
3
|
+
Revision ID: 7edc63646d26
|
|
4
|
+
Revises: debec76c1cf8
|
|
5
|
+
Create Date: 2026-01-18 21:17:35.367597
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from alembic import op
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
import sqlmodel.sql.sqltypes
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# revision identifiers, used by Alembic.
|
|
14
|
+
revision = '7edc63646d26'
|
|
15
|
+
down_revision = 'debec76c1cf8'
|
|
16
|
+
branch_labels = None
|
|
17
|
+
depends_on = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def upgrade():
|
|
21
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
22
|
+
op.create_table('credentials',
|
|
23
|
+
sa.Column('id', sa.Uuid(), nullable=False),
|
|
24
|
+
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
|
25
|
+
sa.Column('type', sqlmodel.sql.sqltypes.AutoString(length=100), nullable=False),
|
|
26
|
+
sa.Column('data', sa.JSON(), nullable=False),
|
|
27
|
+
sa.Column('owner_id', sa.Uuid(), nullable=False),
|
|
28
|
+
sa.Column('created_at', sa.DateTime(), nullable=False),
|
|
29
|
+
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
|
30
|
+
sa.Column('description', sa.Text(), nullable=True),
|
|
31
|
+
sa.Column('last_used_at', sa.DateTime(), nullable=True),
|
|
32
|
+
sa.ForeignKeyConstraint(['owner_id'], ['user.id'], ondelete='CASCADE'),
|
|
33
|
+
sa.PrimaryKeyConstraint('id')
|
|
34
|
+
)
|
|
35
|
+
# ### end Alembic commands ###
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def downgrade():
|
|
39
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
40
|
+
op.drop_table('credentials')
|
|
41
|
+
# ### end Alembic commands ###
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Initial migration
|
|
2
|
+
|
|
3
|
+
Revision ID: debec76c1cf8
|
|
4
|
+
Revises:
|
|
5
|
+
Create Date: 2026-01-18 13:58:08.905854
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from alembic import op
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
import sqlmodel.sql.sqltypes
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# revision identifiers, used by Alembic.
|
|
14
|
+
revision = 'debec76c1cf8'
|
|
15
|
+
down_revision = None
|
|
16
|
+
branch_labels = None
|
|
17
|
+
depends_on = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def upgrade():
|
|
21
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
22
|
+
op.create_table('user',
|
|
23
|
+
sa.Column('email', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
|
24
|
+
sa.Column('is_active', sa.Boolean(), nullable=False),
|
|
25
|
+
sa.Column('is_superuser', sa.Boolean(), nullable=False),
|
|
26
|
+
sa.Column('full_name', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
|
|
27
|
+
sa.Column('id', sa.Uuid(), nullable=False),
|
|
28
|
+
sa.Column('hashed_password', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
29
|
+
sa.PrimaryKeyConstraint('id')
|
|
30
|
+
)
|
|
31
|
+
with op.batch_alter_table('user', schema=None) as batch_op:
|
|
32
|
+
batch_op.create_index(batch_op.f('ix_user_email'), ['email'], unique=True)
|
|
33
|
+
|
|
34
|
+
op.create_table('workflow',
|
|
35
|
+
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
|
|
36
|
+
sa.Column('description', sqlmodel.sql.sqltypes.AutoString(length=500), nullable=True),
|
|
37
|
+
sa.Column('status', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
38
|
+
sa.Column('tags', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
39
|
+
sa.Column('id', sa.Uuid(), nullable=False),
|
|
40
|
+
sa.Column('owner_id', sa.Uuid(), nullable=False),
|
|
41
|
+
sa.Column('created_at', sa.DateTime(), nullable=False),
|
|
42
|
+
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
|
43
|
+
sa.Column('execution_config', sa.JSON(), nullable=False),
|
|
44
|
+
sa.Column('observability_config', sa.JSON(), nullable=False),
|
|
45
|
+
sa.Column('ai_metadata', sa.JSON(), nullable=False),
|
|
46
|
+
sa.ForeignKeyConstraint(['owner_id'], ['user.id'], ondelete='CASCADE'),
|
|
47
|
+
sa.PrimaryKeyConstraint('id')
|
|
48
|
+
)
|
|
49
|
+
op.create_table('workflow_edges',
|
|
50
|
+
sa.Column('id', sa.Uuid(), nullable=False),
|
|
51
|
+
sa.Column('workflow_id', sa.Uuid(), nullable=False),
|
|
52
|
+
sa.Column('edge_id', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
53
|
+
sa.Column('source', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
54
|
+
sa.Column('target', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
55
|
+
sa.Column('label', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
56
|
+
sa.Column('source_handle', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
57
|
+
sa.Column('target_handle', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
58
|
+
sa.ForeignKeyConstraint(['workflow_id'], ['workflow.id'], ondelete='CASCADE'),
|
|
59
|
+
sa.PrimaryKeyConstraint('id')
|
|
60
|
+
)
|
|
61
|
+
op.create_table('workflow_execution',
|
|
62
|
+
sa.Column('id', sa.Uuid(), nullable=False),
|
|
63
|
+
sa.Column('workflow_id', sa.Uuid(), nullable=False),
|
|
64
|
+
sa.Column('status', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
65
|
+
sa.Column('started_at', sa.DateTime(), nullable=False),
|
|
66
|
+
sa.Column('completed_at', sa.DateTime(), nullable=True),
|
|
67
|
+
sa.Column('error', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
68
|
+
sa.Column('trigger_data', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
69
|
+
sa.ForeignKeyConstraint(['workflow_id'], ['workflow.id'], ondelete='CASCADE'),
|
|
70
|
+
sa.PrimaryKeyConstraint('id')
|
|
71
|
+
)
|
|
72
|
+
op.create_table('workflow_nodes',
|
|
73
|
+
sa.Column('id', sa.Uuid(), nullable=False),
|
|
74
|
+
sa.Column('workflow_id', sa.Uuid(), nullable=False),
|
|
75
|
+
sa.Column('node_id', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
76
|
+
sa.Column('node_type', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
77
|
+
sa.Column('position_x', sa.Float(), nullable=False),
|
|
78
|
+
sa.Column('position_y', sa.Float(), nullable=False),
|
|
79
|
+
sa.Column('label', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
80
|
+
sa.Column('subtitle', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
81
|
+
sa.Column('icon', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
82
|
+
sa.Column('spec', sa.JSON(), nullable=False),
|
|
83
|
+
sa.ForeignKeyConstraint(['workflow_id'], ['workflow.id'], ondelete='CASCADE'),
|
|
84
|
+
sa.PrimaryKeyConstraint('id')
|
|
85
|
+
)
|
|
86
|
+
op.create_table('node_execution',
|
|
87
|
+
sa.Column('id', sa.Uuid(), nullable=False),
|
|
88
|
+
sa.Column('workflow_execution_id', sa.Uuid(), nullable=False),
|
|
89
|
+
sa.Column('node_id', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
90
|
+
sa.Column('node_type', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
91
|
+
sa.Column('status', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
|
92
|
+
sa.Column('started_at', sa.DateTime(), nullable=False),
|
|
93
|
+
sa.Column('completed_at', sa.DateTime(), nullable=True),
|
|
94
|
+
sa.Column('input_data', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
95
|
+
sa.Column('output_data', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
96
|
+
sa.Column('error', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
|
97
|
+
sa.ForeignKeyConstraint(['workflow_execution_id'], ['workflow_execution.id'], ondelete='CASCADE'),
|
|
98
|
+
sa.PrimaryKeyConstraint('id')
|
|
99
|
+
)
|
|
100
|
+
# ### end Alembic commands ###
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def downgrade():
|
|
104
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
105
|
+
op.drop_table('node_execution')
|
|
106
|
+
op.drop_table('workflow_nodes')
|
|
107
|
+
op.drop_table('workflow_execution')
|
|
108
|
+
op.drop_table('workflow_edges')
|
|
109
|
+
op.drop_table('workflow')
|
|
110
|
+
with op.batch_alter_table('user', schema=None) as batch_op:
|
|
111
|
+
batch_op.drop_index(batch_op.f('ix_user_email'))
|
|
112
|
+
|
|
113
|
+
op.drop_table('user')
|
|
114
|
+
# ### end Alembic commands ###
|
|
@@ -2,14 +2,12 @@ from fastapi import APIRouter
|
|
|
2
2
|
|
|
3
3
|
from fuse.auth.router import router as auth_router
|
|
4
4
|
from fuse.users.router import router as users_router
|
|
5
|
-
from fuse.items.router import router as items_router
|
|
6
5
|
from fuse.workflows.router import router as workflows_router
|
|
7
6
|
from fuse.ai.router import router as ai_router
|
|
8
7
|
|
|
9
8
|
api_router = APIRouter()
|
|
10
9
|
api_router.include_router(auth_router, tags=["auth"])
|
|
11
10
|
api_router.include_router(users_router, prefix="/users", tags=["users"])
|
|
12
|
-
api_router.include_router(items_router, prefix="/items", tags=["items"])
|
|
13
11
|
api_router.include_router(ai_router, prefix="/workflows/ai", tags=["ai"])
|
|
14
12
|
api_router.include_router(workflows_router, prefix="/workflows", tags=["workflows"])
|
|
15
13
|
|
|
@@ -61,9 +61,3 @@ def get_current_user(session: SessionDep, token: TokenDep) -> User:
|
|
|
61
61
|
CurrentUser = Annotated[User, Depends(get_current_user)]
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
def get_current_active_superuser(current_user: CurrentUser) -> User:
|
|
65
|
-
if not current_user.is_superuser:
|
|
66
|
-
raise HTTPException(
|
|
67
|
-
status_code=403, detail="The user doesn't have enough privileges"
|
|
68
|
-
)
|
|
69
|
-
return current_user
|