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.
Files changed (468) hide show
  1. {fuse_io-0.1.30 → fuse_io-0.1.57}/MANIFEST.in +1 -0
  2. {fuse_io-0.1.30/fuse_io.egg-info → fuse_io-0.1.57}/PKG-INFO +1 -5
  3. fuse_io-0.1.57/fuse/ai/router.py +43 -0
  4. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/ai/service.py +181 -35
  5. fuse_io-0.1.57/fuse/alembic/versions/7a0fd1dc4902_remove_superuser.py +33 -0
  6. fuse_io-0.1.57/fuse/alembic/versions/7edc63646d26_add_credentials_table.py +41 -0
  7. fuse_io-0.1.57/fuse/alembic/versions/debec76c1cf8_initial_migration.py +114 -0
  8. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/api.py +0 -2
  9. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/crud_user.py +0 -2
  10. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/dependencies.py +0 -6
  11. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/router.py +1 -25
  12. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/schemas.py +0 -1
  13. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/service.py +0 -3
  14. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/cli.py +25 -4
  15. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/config.py +7 -38
  16. fuse_io-0.1.57/fuse/credentials/models.py +26 -0
  17. fuse_io-0.1.57/fuse/credentials/router.py +513 -0
  18. fuse_io-0.1.57/fuse/credentials/service.py +276 -0
  19. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/database.py +3 -4
  20. fuse_io-0.1.57/fuse/initial_fuse.db +0 -0
  21. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/logger.py +0 -1
  22. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/main.py +0 -7
  23. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/models.py +2 -1
  24. fuse_io-0.1.57/fuse/static/404/index.html +1 -0
  25. fuse_io-0.1.57/fuse/static/404.html +1 -0
  26. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/__next.__PAGE__.txt +2 -2
  27. fuse_io-0.1.57/fuse/static/__next._full.txt +24 -0
  28. fuse_io-0.1.57/fuse/static/__next._head.txt +5 -0
  29. fuse_io-0.1.57/fuse/static/__next._index.txt +11 -0
  30. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/__next._tree.txt +3 -2
  31. fuse_io-0.1.57/fuse/static/_next/static/AvepNa0wqMBJJaKWx9jp2/_buildManifest.js +1 -0
  32. fuse_io-0.1.57/fuse/static/_next/static/bAsbGnh27hobCWq6gYKAq/_ssgManifest.js +1 -0
  33. fuse_io-0.1.57/fuse/static/_next/static/chunks/1692-a402f4a4fcaf7b29.js +5 -0
  34. fuse_io-0.1.57/fuse/static/_next/static/chunks/1704-99cc2ea208d98cb0.js +1 -0
  35. fuse_io-0.1.57/fuse/static/_next/static/chunks/1950-70f6edfc3f49b339.js +1 -0
  36. fuse_io-0.1.57/fuse/static/_next/static/chunks/1963-d28a6db5ff807527.js +1 -0
  37. fuse_io-0.1.57/fuse/static/_next/static/chunks/232.c883d640f7157775.js +1 -0
  38. fuse_io-0.1.57/fuse/static/_next/static/chunks/2842-88d6ea1ddfa4c472.js +1 -0
  39. fuse_io-0.1.57/fuse/static/_next/static/chunks/3038-598d667e3d5ea764.js +30 -0
  40. fuse_io-0.1.57/fuse/static/_next/static/chunks/3509-92c0624ea5210c8a.js +1 -0
  41. fuse_io-0.1.57/fuse/static/_next/static/chunks/3794-04fa707794cee3fc.js +2 -0
  42. fuse_io-0.1.57/fuse/static/_next/static/chunks/4831-2650d23954cfe85f.js +1 -0
  43. fuse_io-0.1.57/fuse/static/_next/static/chunks/4bd1b696-e5d7c65570c947b7.js +1 -0
  44. fuse_io-0.1.57/fuse/static/_next/static/chunks/573-4b72224474d6755a.js +1 -0
  45. fuse_io-0.1.57/fuse/static/_next/static/chunks/585-b70392236824b164.js +43 -0
  46. fuse_io-0.1.57/fuse/static/_next/static/chunks/6040-4e3e79454e3ce7cf.js +1 -0
  47. fuse_io-0.1.57/fuse/static/_next/static/chunks/7152-7978ade421a25c37.js +1 -0
  48. fuse_io-0.1.57/fuse/static/_next/static/chunks/7621-20d82d6a1007addd.js +1 -0
  49. fuse_io-0.1.57/fuse/static/_next/static/chunks/7856-044a4109806f2a2d.js +1 -0
  50. fuse_io-0.1.57/fuse/static/_next/static/chunks/7988-891258e42d4e9cb9.js +1 -0
  51. fuse_io-0.1.57/fuse/static/_next/static/chunks/8343-4abaf4b94ff48f9a.js +3 -0
  52. fuse_io-0.1.57/fuse/static/_next/static/chunks/8376-ef78e632aabf30d1.js +9 -0
  53. fuse_io-0.1.57/fuse/static/_next/static/chunks/8500-98e13bcce54aa7a0.js +1 -0
  54. fuse_io-0.1.57/fuse/static/_next/static/chunks/8547-58d8503b201666a3.js +1 -0
  55. fuse_io-0.1.57/fuse/static/_next/static/chunks/9903-a77a05716944e520.js +9 -0
  56. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/ai-create-example/page-70ceb48a63cfca66.js +11 -0
  57. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/analytics/page-992337da93734999.js +1 -0
  58. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/credentials/page-7e4cc6437c0633e9.js +1 -0
  59. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/dashboard/page-ad0218038e730e18.js +1 -0
  60. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/executions/page-ad7f99bd73e489e9.js +1 -0
  61. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/help/page-356b1311d0259b76.js +1 -0
  62. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/layout-2822b13d2fbf79fc.js +1 -0
  63. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/settings/page-21ddbcb4288d11e3.js +1 -0
  64. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/templates/page-adcf4c1235f2abd0.js +1 -0
  65. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/variables/page-51455efcaf5cf739.js +1 -0
  66. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/(main)/workflows/page-b2a58db616cdcb70.js +1 -0
  67. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/_global-error/page-bd43e16e28d6b5c5.js +1 -0
  68. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/_not-found/page-313af5f7b44a4219.js +1 -0
  69. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/auth/layout-bd43e16e28d6b5c5.js +1 -0
  70. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/auth/login/page-8001afc0c0cef789.js +1 -0
  71. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/auth/register/page-02132d2e011dbec7.js +1 -0
  72. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/credentials-test/page-13091e893fe38fd8.js +1 -0
  73. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/error-408c6bff597b9d0e.js +1 -0
  74. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/global-error-ab2bae883ee0e860.js +1 -0
  75. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/layout-2ac4c5b8cbb2c64d.js +1 -0
  76. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/loading-bd43e16e28d6b5c5.js +1 -0
  77. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/oauth/callback/page-cdaebdec1d4c4d97.js +1 -0
  78. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/page-502f3458c458bd75.js +1 -0
  79. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/[id]/error-b393ec0b558e28ac.js +1 -0
  80. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/[id]/loading-bd43e16e28d6b5c5.js +1 -0
  81. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/[id]/page-636e52c0d2fa9d9b.js +1 -0
  82. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/error-5a420e4cf1195dbd.js +1 -0
  83. fuse_io-0.1.57/fuse/static/_next/static/chunks/app/workflows/loading-bd43e16e28d6b5c5.js +1 -0
  84. fuse_io-0.1.57/fuse/static/_next/static/chunks/c37d3baf-7f0d73575bc82fee.js +1 -0
  85. fuse_io-0.1.57/fuse/static/_next/static/chunks/framework-81b2e59ffe13bb24.js +1 -0
  86. fuse_io-0.1.57/fuse/static/_next/static/chunks/main-832b18574d412547.js +5 -0
  87. fuse_io-0.1.57/fuse/static/_next/static/chunks/main-app-14c06b7adeda3bca.js +1 -0
  88. fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/app-error-bd43e16e28d6b5c5.js +1 -0
  89. fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/forbidden-bd43e16e28d6b5c5.js +1 -0
  90. fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/not-found-bd43e16e28d6b5c5.js +1 -0
  91. fuse_io-0.1.57/fuse/static/_next/static/chunks/next/dist/client/components/builtin/unauthorized-bd43e16e28d6b5c5.js +1 -0
  92. fuse_io-0.1.57/fuse/static/_next/static/chunks/webpack-03fc999381a8cb79.js +1 -0
  93. fuse_io-0.1.57/fuse/static/_next/static/css/1cb804ccb5b9c075.css +1 -0
  94. fuse_io-0.1.57/fuse/static/_next/static/css/4a300d88a66b0638.css +3 -0
  95. fuse_io-0.1.57/fuse/static/_not-found/__next._full.txt +20 -0
  96. fuse_io-0.1.57/fuse/static/_not-found/__next._head.txt +5 -0
  97. fuse_io-0.1.57/fuse/static/_not-found/__next._index.txt +11 -0
  98. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
  99. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_not-found/__next._not-found.txt +1 -1
  100. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_not-found/__next._tree.txt +3 -2
  101. fuse_io-0.1.57/fuse/static/_not-found/index.html +1 -0
  102. fuse_io-0.1.57/fuse/static/_not-found/index.txt +20 -0
  103. fuse_io-0.1.57/fuse/static/ai-create-example/__next.!KG1haW4p.ai-create-example.__PAGE__.txt +9 -0
  104. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/ai-create-example/__next.!KG1haW4p.ai-create-example.txt +1 -1
  105. {fuse_io-0.1.30/fuse/static/workflows → fuse_io-0.1.57/fuse/static/ai-create-example}/__next.!KG1haW4p.txt +2 -2
  106. fuse_io-0.1.57/fuse/static/ai-create-example/__next._full.txt +29 -0
  107. fuse_io-0.1.57/fuse/static/ai-create-example/__next._head.txt +5 -0
  108. fuse_io-0.1.57/fuse/static/ai-create-example/__next._index.txt +11 -0
  109. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/ai-create-example/__next._tree.txt +3 -2
  110. fuse_io-0.1.57/fuse/static/ai-create-example/index.html +1 -0
  111. fuse_io-0.1.57/fuse/static/ai-create-example/index.txt +29 -0
  112. 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
  113. fuse_io-0.1.57/fuse/static/analytics/__next.!KG1haW4p.analytics.txt +4 -0
  114. {fuse_io-0.1.30/fuse/static/ai-create-example → fuse_io-0.1.57/fuse/static/analytics}/__next.!KG1haW4p.txt +2 -2
  115. fuse_io-0.1.57/fuse/static/analytics/__next._full.txt +29 -0
  116. fuse_io-0.1.57/fuse/static/analytics/__next._head.txt +5 -0
  117. fuse_io-0.1.57/fuse/static/analytics/__next._index.txt +11 -0
  118. fuse_io-0.1.57/fuse/static/analytics/__next._tree.txt +4 -0
  119. fuse_io-0.1.57/fuse/static/analytics/index.html +1 -0
  120. fuse_io-0.1.57/fuse/static/analytics/index.txt +29 -0
  121. fuse_io-0.1.57/fuse/static/auth/login/__next._full.txt +24 -0
  122. fuse_io-0.1.57/fuse/static/auth/login/__next._head.txt +5 -0
  123. fuse_io-0.1.57/fuse/static/auth/login/__next._index.txt +11 -0
  124. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/login/__next._tree.txt +3 -2
  125. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/login/__next.auth.login.__PAGE__.txt +2 -2
  126. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/login/__next.auth.login.txt +1 -1
  127. fuse_io-0.1.57/fuse/static/auth/login/__next.auth.txt +4 -0
  128. fuse_io-0.1.57/fuse/static/auth/login/index.html +1 -0
  129. fuse_io-0.1.57/fuse/static/auth/login/index.txt +24 -0
  130. fuse_io-0.1.57/fuse/static/auth/register/__next._full.txt +24 -0
  131. fuse_io-0.1.57/fuse/static/auth/register/__next._head.txt +5 -0
  132. fuse_io-0.1.57/fuse/static/auth/register/__next._index.txt +11 -0
  133. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/register/__next._tree.txt +3 -2
  134. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/register/__next.auth.register.__PAGE__.txt +2 -2
  135. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/auth/register/__next.auth.register.txt +1 -1
  136. fuse_io-0.1.57/fuse/static/auth/register/__next.auth.txt +4 -0
  137. fuse_io-0.1.57/fuse/static/auth/register/index.html +1 -0
  138. fuse_io-0.1.57/fuse/static/auth/register/index.txt +24 -0
  139. fuse_io-0.1.57/fuse/static/credentials/__next.!KG1haW4p.credentials.__PAGE__.txt +9 -0
  140. fuse_io-0.1.57/fuse/static/credentials/__next.!KG1haW4p.credentials.txt +4 -0
  141. {fuse_io-0.1.30/fuse/static/dashboard → fuse_io-0.1.57/fuse/static/credentials}/__next.!KG1haW4p.txt +2 -2
  142. fuse_io-0.1.57/fuse/static/credentials/__next._full.txt +29 -0
  143. fuse_io-0.1.57/fuse/static/credentials/__next._head.txt +5 -0
  144. fuse_io-0.1.57/fuse/static/credentials/__next._index.txt +11 -0
  145. fuse_io-0.1.57/fuse/static/credentials/__next._tree.txt +4 -0
  146. fuse_io-0.1.57/fuse/static/credentials/index.html +1 -0
  147. fuse_io-0.1.57/fuse/static/credentials/index.txt +29 -0
  148. fuse_io-0.1.57/fuse/static/credentials-test/__next._full.txt +24 -0
  149. fuse_io-0.1.57/fuse/static/credentials-test/__next._head.txt +5 -0
  150. fuse_io-0.1.57/fuse/static/credentials-test/__next._index.txt +11 -0
  151. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/credentials-test/__next._tree.txt +3 -2
  152. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/credentials-test/__next.credentials-test.__PAGE__.txt +2 -2
  153. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/credentials-test/__next.credentials-test.txt +1 -1
  154. fuse_io-0.1.57/fuse/static/credentials-test/index.html +1 -0
  155. fuse_io-0.1.57/fuse/static/credentials-test/index.txt +24 -0
  156. fuse_io-0.1.57/fuse/static/dashboard/__next.!KG1haW4p.dashboard.__PAGE__.txt +9 -0
  157. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/dashboard/__next.!KG1haW4p.dashboard.txt +1 -1
  158. {fuse_io-0.1.30/fuse/static/settings → fuse_io-0.1.57/fuse/static/dashboard}/__next.!KG1haW4p.txt +2 -2
  159. fuse_io-0.1.57/fuse/static/dashboard/__next._full.txt +29 -0
  160. fuse_io-0.1.57/fuse/static/dashboard/__next._head.txt +5 -0
  161. fuse_io-0.1.57/fuse/static/dashboard/__next._index.txt +11 -0
  162. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/dashboard/__next._tree.txt +3 -2
  163. fuse_io-0.1.57/fuse/static/dashboard/index.html +1 -0
  164. fuse_io-0.1.57/fuse/static/dashboard/index.txt +29 -0
  165. fuse_io-0.1.57/fuse/static/executions/__next.!KG1haW4p.executions.__PAGE__.txt +9 -0
  166. fuse_io-0.1.57/fuse/static/executions/__next.!KG1haW4p.executions.txt +4 -0
  167. fuse_io-0.1.57/fuse/static/executions/__next.!KG1haW4p.txt +7 -0
  168. fuse_io-0.1.57/fuse/static/executions/__next._full.txt +29 -0
  169. fuse_io-0.1.57/fuse/static/executions/__next._head.txt +5 -0
  170. fuse_io-0.1.57/fuse/static/executions/__next._index.txt +11 -0
  171. fuse_io-0.1.57/fuse/static/executions/__next._tree.txt +4 -0
  172. fuse_io-0.1.57/fuse/static/executions/index.html +1 -0
  173. fuse_io-0.1.57/fuse/static/executions/index.txt +29 -0
  174. 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
  175. fuse_io-0.1.57/fuse/static/help/__next.!KG1haW4p.help.txt +4 -0
  176. fuse_io-0.1.57/fuse/static/help/__next.!KG1haW4p.txt +7 -0
  177. {fuse_io-0.1.30/fuse/static/ai-create-example → fuse_io-0.1.57/fuse/static/help}/__next._full.txt +14 -11
  178. fuse_io-0.1.57/fuse/static/help/__next._head.txt +5 -0
  179. fuse_io-0.1.57/fuse/static/help/__next._index.txt +11 -0
  180. fuse_io-0.1.57/fuse/static/help/__next._tree.txt +4 -0
  181. fuse_io-0.1.57/fuse/static/help/index.html +1 -0
  182. {fuse_io-0.1.30/fuse/static/ai-create-example → fuse_io-0.1.57/fuse/static/help}/index.txt +14 -11
  183. fuse_io-0.1.57/fuse/static/index.html +1 -0
  184. fuse_io-0.1.57/fuse/static/index.txt +24 -0
  185. fuse_io-0.1.57/fuse/static/logo.png +0 -0
  186. fuse_io-0.1.57/fuse/static/oauth/callback/__next._full.txt +24 -0
  187. fuse_io-0.1.57/fuse/static/oauth/callback/__next._head.txt +5 -0
  188. fuse_io-0.1.57/fuse/static/oauth/callback/__next._index.txt +11 -0
  189. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next._tree.txt +3 -2
  190. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next.oauth.callback.__PAGE__.txt +2 -2
  191. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next.oauth.callback.txt +1 -1
  192. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/oauth/callback/__next.oauth.txt +1 -1
  193. fuse_io-0.1.57/fuse/static/oauth/callback/index.html +1 -0
  194. fuse_io-0.1.57/fuse/static/oauth/callback/index.txt +24 -0
  195. fuse_io-0.1.57/fuse/static/settings/__next.!KG1haW4p.settings.__PAGE__.txt +9 -0
  196. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/settings/__next.!KG1haW4p.settings.txt +1 -1
  197. fuse_io-0.1.57/fuse/static/settings/__next.!KG1haW4p.txt +7 -0
  198. fuse_io-0.1.57/fuse/static/settings/__next._full.txt +29 -0
  199. fuse_io-0.1.57/fuse/static/settings/__next._head.txt +5 -0
  200. fuse_io-0.1.57/fuse/static/settings/__next._index.txt +11 -0
  201. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/settings/__next._tree.txt +3 -2
  202. fuse_io-0.1.57/fuse/static/settings/index.html +1 -0
  203. fuse_io-0.1.57/fuse/static/settings/index.txt +29 -0
  204. fuse_io-0.1.57/fuse/static/templates/__next.!KG1haW4p.templates.__PAGE__.txt +9 -0
  205. fuse_io-0.1.57/fuse/static/templates/__next.!KG1haW4p.templates.txt +4 -0
  206. fuse_io-0.1.57/fuse/static/templates/__next.!KG1haW4p.txt +7 -0
  207. fuse_io-0.1.57/fuse/static/templates/__next._full.txt +29 -0
  208. fuse_io-0.1.57/fuse/static/templates/__next._head.txt +5 -0
  209. fuse_io-0.1.57/fuse/static/templates/__next._index.txt +11 -0
  210. fuse_io-0.1.57/fuse/static/templates/__next._tree.txt +4 -0
  211. fuse_io-0.1.57/fuse/static/templates/index.html +1 -0
  212. fuse_io-0.1.57/fuse/static/templates/index.txt +29 -0
  213. fuse_io-0.1.57/fuse/static/variables/__next.!KG1haW4p.txt +7 -0
  214. fuse_io-0.1.57/fuse/static/variables/__next.!KG1haW4p.variables.__PAGE__.txt +9 -0
  215. fuse_io-0.1.57/fuse/static/variables/__next.!KG1haW4p.variables.txt +4 -0
  216. fuse_io-0.1.57/fuse/static/variables/__next._full.txt +29 -0
  217. fuse_io-0.1.57/fuse/static/variables/__next._head.txt +5 -0
  218. fuse_io-0.1.57/fuse/static/variables/__next._index.txt +11 -0
  219. fuse_io-0.1.57/fuse/static/variables/__next._tree.txt +4 -0
  220. fuse_io-0.1.57/fuse/static/variables/index.html +1 -0
  221. fuse_io-0.1.57/fuse/static/variables/index.txt +29 -0
  222. fuse_io-0.1.57/fuse/static/workflows/__next.!KG1haW4p.txt +7 -0
  223. fuse_io-0.1.57/fuse/static/workflows/__next.!KG1haW4p.workflows.__PAGE__.txt +10 -0
  224. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/__next.!KG1haW4p.workflows.txt +1 -1
  225. fuse_io-0.1.57/fuse/static/workflows/__next._full.txt +29 -0
  226. fuse_io-0.1.57/fuse/static/workflows/__next._head.txt +5 -0
  227. fuse_io-0.1.57/fuse/static/workflows/__next._index.txt +11 -0
  228. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/__next._tree.txt +3 -2
  229. fuse_io-0.1.57/fuse/static/workflows/index.html +1 -0
  230. fuse_io-0.1.57/fuse/static/workflows/index.txt +29 -0
  231. fuse_io-0.1.57/fuse/static/workflows/new/__next._full.txt +29 -0
  232. fuse_io-0.1.57/fuse/static/workflows/new/__next._head.txt +5 -0
  233. fuse_io-0.1.57/fuse/static/workflows/new/__next._index.txt +11 -0
  234. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next._tree.txt +3 -2
  235. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next.workflows.$d$id.__PAGE__.txt +2 -2
  236. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next.workflows.$d$id.txt +2 -2
  237. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/workflows/new/__next.workflows.txt +2 -2
  238. fuse_io-0.1.57/fuse/static/workflows/new/index.html +1 -0
  239. fuse_io-0.1.57/fuse/static/workflows/new/index.txt +29 -0
  240. fuse_io-0.1.57/fuse/users/router.py +129 -0
  241. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/pagination.py +2 -2
  242. fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/agent.py +125 -0
  243. fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/chat_model.py +40 -0
  244. fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/memory.py +33 -0
  245. fuse_io-0.1.57/fuse/workflows/engine/nodes/ai/tool.py +33 -0
  246. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/base.py +1 -0
  247. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/email.py +2 -1
  248. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/form.py +2 -1
  249. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/manual.py +2 -1
  250. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/rss.py +2 -1
  251. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/schedule.py +2 -1
  252. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/webhook.py +2 -1
  253. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/triggers/whatsapp.py +2 -1
  254. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/schemas.py +19 -3
  255. {fuse_io-0.1.30 → fuse_io-0.1.57/fuse_io.egg-info}/PKG-INFO +1 -5
  256. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/SOURCES.txt +127 -16
  257. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/requires.txt +0 -4
  258. {fuse_io-0.1.30 → fuse_io-0.1.57}/pyproject.toml +7 -5
  259. {fuse_io-0.1.30 → fuse_io-0.1.57}/uv.lock +1 -160
  260. fuse_io-0.1.30/fuse/ai/router.py +0 -35
  261. fuse_io-0.1.30/fuse/alembic/versions/1439949b74ad_add_edge_handles.py +0 -31
  262. fuse_io-0.1.30/fuse/alembic/versions/1a31ce608336_add_cascade_delete_relationships.py +0 -37
  263. fuse_io-0.1.30/fuse/alembic/versions/2c7ca0ca6779_add_hashed_password_field_to_user_model.py +0 -29
  264. fuse_io-0.1.30/fuse/alembic/versions/82e10e9b2e3f_add_spec_column_to_workflownode_and_.py +0 -34
  265. fuse_io-0.1.30/fuse/alembic/versions/9426be80e78e_add_workflows.py +0 -66
  266. fuse_io-0.1.30/fuse/alembic/versions/9c0a54914c78_add_max_length_for_string_varchar_.py +0 -65
  267. fuse_io-0.1.30/fuse/alembic/versions/ceedbe88ef0d_add_v2_config_columns_to_workflow.py +0 -33
  268. fuse_io-0.1.30/fuse/alembic/versions/d98dd8ec85a3_edit_replace_id_integers_in_all_models_.py +0 -99
  269. fuse_io-0.1.30/fuse/alembic/versions/dd21742ef7b0_add_execution_models.py +0 -54
  270. fuse_io-0.1.30/fuse/alembic/versions/e2412789c190_initialize_models.py +0 -54
  271. fuse_io-0.1.30/fuse/credentials/router.py +0 -199
  272. fuse_io-0.1.30/fuse/credentials/service.py +0 -181
  273. fuse_io-0.1.30/fuse/items/__init__.py +0 -9
  274. fuse_io-0.1.30/fuse/items/crud_item.py +0 -44
  275. fuse_io-0.1.30/fuse/items/models.py +0 -19
  276. fuse_io-0.1.30/fuse/items/router.py +0 -97
  277. fuse_io-0.1.30/fuse/items/schemas.py +0 -34
  278. fuse_io-0.1.30/fuse/items/service.py +0 -57
  279. fuse_io-0.1.30/fuse/static/404/index.html +0 -1
  280. fuse_io-0.1.30/fuse/static/404.html +0 -1
  281. fuse_io-0.1.30/fuse/static/__next._full.txt +0 -23
  282. fuse_io-0.1.30/fuse/static/__next._head.txt +0 -7
  283. fuse_io-0.1.30/fuse/static/__next._index.txt +0 -10
  284. fuse_io-0.1.30/fuse/static/_not-found/__next._full.txt +0 -19
  285. fuse_io-0.1.30/fuse/static/_not-found/__next._head.txt +0 -7
  286. fuse_io-0.1.30/fuse/static/_not-found/__next._index.txt +0 -10
  287. fuse_io-0.1.30/fuse/static/_not-found/index.html +0 -1
  288. fuse_io-0.1.30/fuse/static/_not-found/index.txt +0 -19
  289. fuse_io-0.1.30/fuse/static/ai-create-example/__next._head.txt +0 -7
  290. fuse_io-0.1.30/fuse/static/ai-create-example/__next._index.txt +0 -10
  291. fuse_io-0.1.30/fuse/static/ai-create-example/index.html +0 -1
  292. fuse_io-0.1.30/fuse/static/auth/login/__next._full.txt +0 -23
  293. fuse_io-0.1.30/fuse/static/auth/login/__next._head.txt +0 -7
  294. fuse_io-0.1.30/fuse/static/auth/login/__next._index.txt +0 -10
  295. fuse_io-0.1.30/fuse/static/auth/login/__next.auth.txt +0 -4
  296. fuse_io-0.1.30/fuse/static/auth/login/index.html +0 -1
  297. fuse_io-0.1.30/fuse/static/auth/login/index.txt +0 -23
  298. fuse_io-0.1.30/fuse/static/auth/register/__next._full.txt +0 -23
  299. fuse_io-0.1.30/fuse/static/auth/register/__next._head.txt +0 -7
  300. fuse_io-0.1.30/fuse/static/auth/register/__next._index.txt +0 -10
  301. fuse_io-0.1.30/fuse/static/auth/register/__next.auth.txt +0 -4
  302. fuse_io-0.1.30/fuse/static/auth/register/index.html +0 -1
  303. fuse_io-0.1.30/fuse/static/auth/register/index.txt +0 -23
  304. fuse_io-0.1.30/fuse/static/credentials-test/__next._full.txt +0 -23
  305. fuse_io-0.1.30/fuse/static/credentials-test/__next._head.txt +0 -7
  306. fuse_io-0.1.30/fuse/static/credentials-test/__next._index.txt +0 -10
  307. fuse_io-0.1.30/fuse/static/credentials-test/index.html +0 -1
  308. fuse_io-0.1.30/fuse/static/credentials-test/index.txt +0 -23
  309. fuse_io-0.1.30/fuse/static/dashboard/__next.!KG1haW4p.dashboard.__PAGE__.txt +0 -9
  310. fuse_io-0.1.30/fuse/static/dashboard/__next._full.txt +0 -26
  311. fuse_io-0.1.30/fuse/static/dashboard/__next._head.txt +0 -7
  312. fuse_io-0.1.30/fuse/static/dashboard/__next._index.txt +0 -10
  313. fuse_io-0.1.30/fuse/static/dashboard/index.html +0 -1
  314. fuse_io-0.1.30/fuse/static/dashboard/index.txt +0 -26
  315. fuse_io-0.1.30/fuse/static/index.html +0 -1
  316. fuse_io-0.1.30/fuse/static/index.txt +0 -23
  317. fuse_io-0.1.30/fuse/static/oauth/callback/__next._full.txt +0 -23
  318. fuse_io-0.1.30/fuse/static/oauth/callback/__next._head.txt +0 -7
  319. fuse_io-0.1.30/fuse/static/oauth/callback/__next._index.txt +0 -10
  320. fuse_io-0.1.30/fuse/static/oauth/callback/index.html +0 -1
  321. fuse_io-0.1.30/fuse/static/oauth/callback/index.txt +0 -23
  322. fuse_io-0.1.30/fuse/static/settings/__next._full.txt +0 -26
  323. fuse_io-0.1.30/fuse/static/settings/__next._head.txt +0 -7
  324. fuse_io-0.1.30/fuse/static/settings/__next._index.txt +0 -10
  325. fuse_io-0.1.30/fuse/static/settings/index.html +0 -1
  326. fuse_io-0.1.30/fuse/static/settings/index.txt +0 -26
  327. fuse_io-0.1.30/fuse/static/workflows/__next.!KG1haW4p.workflows.__PAGE__.txt +0 -10
  328. fuse_io-0.1.30/fuse/static/workflows/__next._full.txt +0 -29
  329. fuse_io-0.1.30/fuse/static/workflows/__next._head.txt +0 -7
  330. fuse_io-0.1.30/fuse/static/workflows/__next._index.txt +0 -10
  331. fuse_io-0.1.30/fuse/static/workflows/index.html +0 -1
  332. fuse_io-0.1.30/fuse/static/workflows/index.txt +0 -29
  333. fuse_io-0.1.30/fuse/static/workflows/new/__next._full.txt +0 -26
  334. fuse_io-0.1.30/fuse/static/workflows/new/__next._head.txt +0 -7
  335. fuse_io-0.1.30/fuse/static/workflows/new/__next._index.txt +0 -10
  336. fuse_io-0.1.30/fuse/static/workflows/new/index.html +0 -1
  337. fuse_io-0.1.30/fuse/static/workflows/new/index.txt +0 -26
  338. fuse_io-0.1.30/fuse/users/router.py +0 -234
  339. fuse_io-0.1.30/fuse/workflows/engine/nodes/ai/agent.py +0 -100
  340. {fuse_io-0.1.30 → fuse_io-0.1.57}/.python-version +0 -0
  341. {fuse_io-0.1.30 → fuse_io-0.1.57}/LICENSE +0 -0
  342. {fuse_io-0.1.30 → fuse_io-0.1.57}/README.md +0 -0
  343. {fuse_io-0.1.30 → fuse_io-0.1.57}/docs/pypi_publishing_guide.md +0 -0
  344. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/__init__.py +0 -0
  345. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/ai/__init__.py +0 -0
  346. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/README +0 -0
  347. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/env.py +0 -0
  348. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/script.py.mako +0 -0
  349. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic/versions/.keep +0 -0
  350. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/alembic.ini +0 -0
  351. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/__init__.py +0 -0
  352. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/models.py +0 -0
  353. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/auth/utils.py +0 -0
  354. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/backend_pre_start.py +0 -0
  355. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/base.py +0 -0
  356. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/credentials/__init__.py +0 -0
  357. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/initial_data.py +0 -0
  358. {fuse_io-0.1.30/fuse/static/_next/static/bAsbGnh27hobCWq6gYKAq → fuse_io-0.1.57/fuse/static/_next/static/AvepNa0wqMBJJaKWx9jp2}/_ssgManifest.js +0 -0
  359. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/bAsbGnh27hobCWq6gYKAq/_buildManifest.js +0 -0
  360. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/162-d9110b81661c7d7d.js +0 -0
  361. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/232.97b298320d3351e9.js +0 -0
  362. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/24-4ee5417b9b9b92a9.js +0 -0
  363. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/275-f12d66089f519b01.js +0 -0
  364. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/324-771510774da7c693.js +0 -0
  365. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/361-1ce2845fa2b2c4a4.js +0 -0
  366. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/393-d1b3ea65900fdc5e.js +0 -0
  367. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/4-bdc965d7dcca4cab.js +0 -0
  368. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/4bd1b696-01b4a2ffa8bac205.js +0 -0
  369. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/501-397a9f42b1c4da0e.js +0 -0
  370. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/547-1833756cc09c3c28.js +0 -0
  371. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/794-803d64bb1ca09460.js +0 -0
  372. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/814-18bcbd34c09817f1.js +0 -0
  373. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/821-04976ebb62352e45.js +0 -0
  374. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/93-2937d48fc52107ef.js +0 -0
  375. {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
  376. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/dashboard/page-7e9db37c6737695c.js +0 -0
  377. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/layout-5c636818aa3b7ed1.js +0 -0
  378. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/settings/page-00bc4735cc93b9be.js +0 -0
  379. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/(main)/workflows/page-7c3c63a11ae33eed.js +0 -0
  380. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/_global-error/page-116e68079fa76e6f.js +0 -0
  381. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/_not-found/page-bae0d4902c5585d3.js +0 -0
  382. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/auth/layout-116e68079fa76e6f.js +0 -0
  383. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/auth/login/page-546ffaa564d327e9.js +0 -0
  384. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/auth/register/page-2748b1af5b1b642a.js +0 -0
  385. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/credentials-test/page-1d2c37deaa189b43.js +0 -0
  386. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/error-033f2fd59b73a2d7.js +0 -0
  387. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/global-error-dcd149dc42c5186b.js +0 -0
  388. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/layout-d0d5a6a85d213394.js +0 -0
  389. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/loading-116e68079fa76e6f.js +0 -0
  390. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/oauth/callback/page-eecedf564f689d93.js +0 -0
  391. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/page-606905d313079604.js +0 -0
  392. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/[id]/error-66ff5093f583ae94.js +0 -0
  393. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/[id]/loading-116e68079fa76e6f.js +0 -0
  394. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/[id]/page-5459cee4cb66f5bc.js +0 -0
  395. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/error-61dbcd88cc0eff5c.js +0 -0
  396. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/app/workflows/loading-116e68079fa76e6f.js +0 -0
  397. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/c37d3baf-0fedbf5b6ffcd550.js +0 -0
  398. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/framework-3311683cffde0ebf.js +0 -0
  399. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/main-app-cf50eb2a7e26453d.js +0 -0
  400. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/main-d74776772a65895d.js +0 -0
  401. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  402. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/chunks/webpack-b28a02ce1f174559.js +0 -0
  403. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/css/59d0dfc36eeea694.css +0 -0
  404. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/css/d1e1fa7731bfdccb.css +0 -0
  405. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/636a5ac981f94f8b-s.p.woff2 +0 -0
  406. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/6fe53d21e6e7ebd8-s.woff2 +0 -0
  407. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/8ebc6e9dde468c4a-s.woff2 +0 -0
  408. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/static/_next/static/media/9e7b0a821b9dfcb4-s.woff2 +0 -0
  409. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/users/__init__.py +0 -0
  410. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/cache.py +0 -0
  411. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/circuit_breaker.py +0 -0
  412. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/code_sanitizer.py +0 -0
  413. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/feature_flags.py +0 -0
  414. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/health.py +0 -0
  415. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/rate_limit.py +0 -0
  416. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/redis_client.py +0 -0
  417. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/request_id.py +0 -0
  418. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/utils/security.py +0 -0
  419. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/worker.py +0 -0
  420. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/__init__.py +0 -0
  421. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/code_execution.py +0 -0
  422. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/crud_workflow.py +0 -0
  423. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/__init__.py +0 -0
  424. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/constants.py +0 -0
  425. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/core.py +0 -0
  426. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/error_handler.py +0 -0
  427. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/errors.py +0 -0
  428. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/executor.py +0 -0
  429. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/graph.py +0 -0
  430. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/__init__.py +0 -0
  431. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/code.py +0 -0
  432. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/data.py +0 -0
  433. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/discord.py +0 -0
  434. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/email.py +0 -0
  435. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/google_sheets.py +0 -0
  436. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/http_request.py +0 -0
  437. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/slack.py +0 -0
  438. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/utility.py +0 -0
  439. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/actions/whatsapp.py +0 -0
  440. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/ai/__init__.py +0 -0
  441. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/ai/llm.py +0 -0
  442. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/__init__.py +0 -0
  443. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/delay.py +0 -0
  444. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/if_node.py +0 -0
  445. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/loop.py +0 -0
  446. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/merge.py +0 -0
  447. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/parallel.py +0 -0
  448. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/pause.py +0 -0
  449. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/logic/switch.py +0 -0
  450. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/nodes/registry.py +0 -0
  451. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/periodic_scheduler.py +0 -0
  452. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/runtime/code.py +0 -0
  453. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/runtime/http.py +0 -0
  454. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/runtime/internal.py +0 -0
  455. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/scheduler.py +0 -0
  456. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/engine/state.py +0 -0
  457. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/logger.py +0 -0
  458. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/models.py +0 -0
  459. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/router.py +0 -0
  460. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/service.py +0 -0
  461. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/types.py +0 -0
  462. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse/workflows/utils/templating.py +0 -0
  463. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/dependency_links.txt +0 -0
  464. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/entry_points.txt +0 -0
  465. {fuse_io-0.1.30 → fuse_io-0.1.57}/fuse_io.egg-info/top_level.txt +0 -0
  466. {fuse_io-0.1.30 → fuse_io-0.1.57}/scripts/format.sh +0 -0
  467. {fuse_io-0.1.30 → fuse_io-0.1.57}/scripts/lint.sh +0 -0
  468. {fuse_io-0.1.30 → fuse_io-0.1.57}/setup.cfg +0 -0
@@ -18,3 +18,4 @@ global-exclude build/*
18
18
  global-exclude *.egg-info
19
19
  global-exclude fuse.db
20
20
  global-exclude .env
21
+ global-exclude credentials_storage.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fuse-io
3
- Version: 0.1.30
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 model == "gemini":
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 model == "openai":
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 model == "anthropic":
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 model == "openrouter":
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}", model=model
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(self, prompt: str) -> str:
245
+ async def _generate_with_gemini(
246
+ self, prompt: str, credential_data: Optional[Dict] = None
247
+ ) -> str:
233
248
  """Generate using Google Gemini"""
234
- if not self.gemini_client:
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 = self.gemini_client.models.generate_content(
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(self, prompt: str) -> str:
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
- if not self.openai_client:
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 = self.openai_client.chat.completions.create(
252
- model="gpt-4",
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(self, prompt: str) -> str:
297
+ async def _generate_with_anthropic(
298
+ self, prompt: str, credential_data: Optional[Dict] = None
299
+ ) -> str:
265
300
  """Generate using Anthropic Claude"""
266
- if not self.anthropic_client:
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 = self.anthropic_client.messages.create(
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, prompt: str, model: str = "deepseek/deepseek-r1"
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
- if not self.openrouter_client:
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 = self.openrouter_client.chat.completions.create(
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
- provider = (credential.get("provider") or "unknown").lower()
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
- if provider == "gemini":
422
- client = genai.Client(api_key=api_key) if api_key else self.gemini_client
423
- if not client:
424
- raise ValueError("Gemini API key not found.")
425
-
426
- # Combine messages for Gemini (it uses a slightly different format)
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
- # Default OpenAI or OpenRouter if no custom base_url
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
- # Generic OpenAI-compatible provider
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
 
@@ -56,8 +56,6 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
56
56
  def is_active(self, user: User) -> bool:
57
57
  return user.is_active
58
58
 
59
- def is_superuser(self, user: User) -> bool:
60
- return user.is_superuser
61
59
 
62
60
 
63
61
  user = CRUDUser(User)
@@ -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