insforge 0.3.2 → 1.2.10

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 (507) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.cursor/rules/cursor-rules.mdc +94 -0
  3. package/.dockerignore +3 -0
  4. package/.env.example +33 -4
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
  6. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
  8. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  9. package/.github/workflows/build-image.yml +2 -1
  10. package/.github/workflows/e2e.yml +63 -0
  11. package/CHANGELOG.md +41 -0
  12. package/CLAUDE_PLUGIN.md +104 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/Dockerfile +4 -1
  16. package/README.md +66 -18
  17. package/assets/mcpInstallv2.png +0 -0
  18. package/assets/sampleResponse.png +0 -0
  19. package/auth/index.html +13 -0
  20. package/auth/package.json +28 -0
  21. package/auth/public/favicon.ico +0 -0
  22. package/auth/src/App.tsx +33 -0
  23. package/auth/src/components/ErrorCard.tsx +37 -0
  24. package/auth/src/components/Layout.tsx +13 -0
  25. package/auth/src/index.css +19 -0
  26. package/auth/src/lib/broadcastService.ts +115 -0
  27. package/auth/src/lib/utils.ts +11 -0
  28. package/auth/src/main.tsx +22 -0
  29. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  30. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  31. package/auth/src/pages/SignInPage.tsx +57 -0
  32. package/auth/src/pages/SignUpPage.tsx +57 -0
  33. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  34. package/auth/src/vite-env.d.ts +10 -0
  35. package/auth/tsconfig.json +32 -0
  36. package/auth/tsconfig.node.json +11 -0
  37. package/auth/vite.config.ts +25 -0
  38. package/backend/package.json +9 -9
  39. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  40. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  41. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
  42. package/backend/src/api/routes/auth/index.routes.ts +570 -0
  43. package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
  44. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
  45. package/backend/src/api/routes/database/index.routes.ts +13 -0
  46. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
  47. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
  48. package/backend/src/api/routes/docs/index.routes.ts +76 -0
  49. package/backend/src/api/routes/functions/index.routes.ts +188 -0
  50. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  51. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
  52. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  53. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
  54. package/backend/src/api/routes/usage/index.routes.ts +89 -0
  55. package/backend/src/infra/config/app.config.ts +51 -0
  56. package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
  57. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  58. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  59. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  60. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  61. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  62. package/backend/src/infra/security/token.manager.ts +125 -0
  63. package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
  64. package/backend/src/providers/ai/openrouter.provider.ts +377 -0
  65. package/backend/src/providers/email/base.provider.ts +41 -0
  66. package/backend/src/providers/email/cloud.provider.ts +187 -0
  67. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  68. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  69. package/backend/src/providers/logs/local.provider.ts +185 -0
  70. package/backend/src/providers/oauth/base.provider.ts +29 -0
  71. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  72. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  73. package/backend/src/providers/oauth/github.provider.ts +208 -0
  74. package/backend/src/providers/oauth/google.provider.ts +249 -0
  75. package/backend/src/providers/oauth/index.ts +7 -0
  76. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  77. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  78. package/backend/src/providers/oauth/x.provider.ts +202 -0
  79. package/backend/src/providers/storage/base.provider.ts +29 -0
  80. package/backend/src/providers/storage/local.provider.ts +103 -0
  81. package/backend/src/providers/storage/s3.provider.ts +313 -0
  82. package/backend/src/server.ts +70 -74
  83. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  84. package/backend/src/services/ai/ai-model.service.ts +60 -0
  85. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  86. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  87. package/backend/src/services/ai/helpers.ts +64 -0
  88. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  89. package/backend/src/services/ai/index.ts +13 -0
  90. package/backend/src/services/auth/auth-config.service.ts +250 -0
  91. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  92. package/backend/src/services/auth/auth.service.ts +1136 -0
  93. package/backend/src/services/auth/index.ts +4 -0
  94. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  95. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  96. package/backend/src/services/database/database-table.service.ts +811 -0
  97. package/backend/src/services/email/email.service.ts +75 -0
  98. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  99. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  100. package/backend/src/services/logs/log.service.ts +73 -0
  101. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  102. package/backend/src/services/storage/storage.service.ts +617 -0
  103. package/backend/src/services/usage/usage.service.ts +149 -0
  104. package/backend/src/types/auth.ts +66 -2
  105. package/backend/src/types/email.ts +8 -0
  106. package/backend/src/types/error-constants.ts +4 -0
  107. package/backend/src/types/logs.ts +0 -29
  108. package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
  109. package/backend/src/utils/environment.ts +9 -3
  110. package/backend/src/utils/logger.ts +20 -2
  111. package/backend/src/utils/seed.ts +150 -57
  112. package/backend/src/utils/sql-parser.ts +1 -1
  113. package/backend/src/utils/utils.ts +114 -0
  114. package/backend/src/utils/validations.ts +40 -4
  115. package/backend/tests/local/test-ai-config.sh +129 -0
  116. package/backend/tests/local/test-ai-usage.sh +80 -0
  117. package/backend/tests/local/test-auth-router.sh +1 -1
  118. package/backend/tests/local/test-e2e.sh +1 -1
  119. package/backend/tests/local/test-functions.sh +123 -0
  120. package/backend/tests/local/test-logs.sh +132 -0
  121. package/backend/tests/local/test-public-bucket.sh +3 -3
  122. package/backend/tests/local/test-secrets.sh +14 -12
  123. package/backend/tests/local/test-traditional-rest.sh +2 -2
  124. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  125. package/backend/tests/test-config.sh +37 -1
  126. package/backend/tests/unit/cloud-token.test.ts +48 -0
  127. package/backend/tests/unit/constant.test.ts +8 -0
  128. package/backend/tests/unit/email.test.ts +372 -0
  129. package/backend/tests/unit/environment.test.ts +59 -0
  130. package/backend/tests/unit/helpers.test.ts +63 -0
  131. package/backend/tests/unit/logger.test.ts +22 -0
  132. package/backend/tests/unit/rate-limit.test.ts +154 -0
  133. package/backend/tests/unit/response.test.ts +58 -0
  134. package/backend/tests/unit/sql-parser.test.ts +74 -0
  135. package/backend/tests/unit/uuid.test.ts +21 -0
  136. package/backend/tests/unit/validations.test.ts +80 -0
  137. package/backend/tsconfig.json +1 -1
  138. package/backend/vitest.config.ts +11 -0
  139. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  140. package/claude-plugin/README.md +133 -0
  141. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  142. package/docker-compose.prod.yml +60 -4
  143. package/docker-compose.yml +65 -4
  144. package/docker-init/db/db-init.sql +6 -34
  145. package/docker-init/logs/vector.yml +236 -0
  146. package/docs/README.md +44 -0
  147. package/docs/changelog.mdx +67 -0
  148. package/docs/core-concepts/ai/architecture.mdx +373 -0
  149. package/docs/core-concepts/ai/sdk.mdx +213 -0
  150. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  151. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  152. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  153. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  154. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  155. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  156. package/docs/core-concepts/database/architecture.mdx +256 -0
  157. package/docs/core-concepts/database/sdk.mdx +382 -0
  158. package/docs/core-concepts/functions/architecture.mdx +105 -0
  159. package/docs/core-concepts/functions/sdk.mdx +184 -0
  160. package/docs/core-concepts/storage/architecture.mdx +243 -0
  161. package/docs/core-concepts/storage/sdk.mdx +253 -0
  162. package/docs/deployment/README.md +94 -0
  163. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  164. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  165. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  166. package/docs/deployment/deploy-to-render.md +441 -0
  167. package/docs/docs.json +210 -0
  168. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  169. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  170. package/docs/examples/framework-guides/react.mdx +165 -0
  171. package/docs/examples/framework-guides/svelte.mdx +153 -0
  172. package/docs/examples/framework-guides/vue.mdx +159 -0
  173. package/docs/examples/overview.mdx +67 -0
  174. package/docs/favicon.svg +19 -0
  175. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  176. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  177. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  178. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  179. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  180. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  181. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  182. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  183. package/docs/images/checks-passed.png +0 -0
  184. package/docs/images/dashboard-connect-expanded.png +0 -0
  185. package/docs/images/dashboard-connect.png +0 -0
  186. package/docs/images/hero-dark.png +0 -0
  187. package/docs/images/hero-light.png +0 -0
  188. package/docs/images/icons/ai.svg +4 -0
  189. package/docs/images/icons/auth.svg +1 -0
  190. package/docs/images/icons/database.svg +1 -0
  191. package/docs/images/icons/function.svg +1 -0
  192. package/docs/images/icons/storage.svg +1 -0
  193. package/docs/images/logos/nextjs.svg +4 -0
  194. package/docs/images/logos/nuxt.svg +4 -0
  195. package/docs/images/logos/react.svg +5 -0
  196. package/docs/images/logos/svelte.svg +4 -0
  197. package/docs/images/logos/vue.svg +5 -0
  198. package/docs/images/mcp-install.png +0 -0
  199. package/docs/images/onboarding-mcp.png +0 -0
  200. package/docs/insforge-instructions-sdk.md +55 -374
  201. package/docs/introduction.mdx +45 -0
  202. package/docs/logo/dark.svg +22 -0
  203. package/docs/logo/light.svg +20 -0
  204. package/docs/partnership.mdx +647 -0
  205. package/docs/quickstart.mdx +83 -0
  206. package/docs/showcase/2048-arena.png +0 -0
  207. package/docs/showcase/framegen-cloud.png +0 -0
  208. package/docs/showcase/line-connect-race.png +0 -0
  209. package/docs/showcase/moment-vibe.png +0 -0
  210. package/docs/showcase/national-flags.png +0 -0
  211. package/docs/showcase/pokemon-vibe.png +0 -0
  212. package/docs/showcase/pure-browse-buy.png +0 -0
  213. package/docs/showcase.mdx +52 -0
  214. package/docs/snippets/sdk-installation.mdx +22 -0
  215. package/docs/snippets/service-icons.mdx +27 -0
  216. package/eslint.config.js +10 -3
  217. package/frontend/package.json +10 -4
  218. package/frontend/src/App.tsx +13 -82
  219. package/frontend/src/assets/icons/connected.svg +3 -0
  220. package/frontend/src/assets/icons/loader.svg +9 -0
  221. package/frontend/src/assets/logos/apple.svg +4 -0
  222. package/frontend/src/assets/logos/discord.svg +1 -1
  223. package/frontend/src/assets/logos/facebook.svg +3 -0
  224. package/frontend/src/assets/logos/instagram.svg +2 -0
  225. package/frontend/src/assets/logos/linkedin.svg +3 -0
  226. package/frontend/src/assets/logos/microsoft.svg +1 -0
  227. package/frontend/src/assets/logos/spotify.svg +17 -0
  228. package/frontend/src/assets/logos/tiktok.svg +6 -0
  229. package/frontend/src/assets/logos/x.svg +3 -0
  230. package/frontend/src/components/Checkbox.tsx +27 -29
  231. package/frontend/src/components/CodeBlock.tsx +55 -2
  232. package/frontend/src/components/CodeEditor.tsx +92 -0
  233. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  234. package/frontend/src/components/ConnectCTA.tsx +38 -0
  235. package/frontend/src/components/CopyButton.tsx +52 -15
  236. package/frontend/src/components/ErrorState.tsx +1 -2
  237. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  238. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  239. package/frontend/src/components/JsonHighlight.tsx +21 -9
  240. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  241. package/frontend/src/components/PromptDialog.tsx +1 -4
  242. package/frontend/src/components/SearchInput.tsx +1 -2
  243. package/frontend/src/components/Stepper.tsx +53 -0
  244. package/frontend/src/components/ThemeToggle.tsx +3 -3
  245. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  246. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  247. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  248. package/frontend/src/components/datagrid/index.ts +23 -0
  249. package/frontend/src/components/index.ts +23 -30
  250. package/frontend/src/components/layout/AppHeader.tsx +133 -92
  251. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  252. package/frontend/src/components/layout/Layout.tsx +12 -23
  253. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  254. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  255. package/frontend/src/components/layout/index.ts +5 -0
  256. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  257. package/frontend/src/components/radix/index.ts +22 -0
  258. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  259. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  260. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  261. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  262. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  263. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  264. package/frontend/src/features/ai/components/index.ts +6 -0
  265. package/frontend/src/features/ai/helpers.ts +57 -71
  266. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  267. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  268. package/frontend/src/features/ai/page/AIPage.tsx +67 -79
  269. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  270. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  271. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
  272. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  273. package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
  274. package/frontend/src/features/auth/components/index.ts +5 -0
  275. package/frontend/src/features/auth/helpers.tsx +200 -0
  276. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  277. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  278. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  279. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  280. package/frontend/src/features/auth/index.ts +3 -2
  281. package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
  282. package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
  283. package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
  284. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  285. package/frontend/src/features/auth/services/config.service.ts +19 -0
  286. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  287. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  288. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  289. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  290. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  291. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  292. package/frontend/src/features/dashboard/components/index.ts +4 -0
  293. package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
  294. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  295. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  296. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  297. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  298. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  299. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  300. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  301. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  302. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  303. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  304. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  305. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  306. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  307. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  308. package/frontend/src/features/database/components/TableForm.tsx +28 -15
  309. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  310. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  311. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  312. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  313. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  314. package/frontend/src/features/database/components/index.ts +19 -0
  315. package/frontend/src/features/database/constants.ts +28 -2
  316. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  317. package/frontend/src/features/database/helpers.ts +2 -2
  318. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  319. package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
  320. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  321. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  322. package/frontend/src/features/database/hooks/useTables.ts +131 -0
  323. package/frontend/src/features/database/index.ts +6 -1
  324. package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
  325. package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
  326. package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
  327. package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
  328. package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
  329. package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
  330. package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
  331. package/frontend/src/features/database/services/advance.service.ts +66 -0
  332. package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
  333. package/frontend/src/features/database/services/table.service.ts +64 -0
  334. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  335. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  336. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  337. package/frontend/src/features/database/templates/index.ts +34 -0
  338. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  339. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  340. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  341. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  342. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  343. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  344. package/frontend/src/features/functions/components/index.ts +5 -0
  345. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  346. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  347. package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
  348. package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
  349. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  350. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  351. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  352. package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
  353. package/frontend/src/features/login/page/LoginPage.tsx +16 -23
  354. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  355. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  356. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  357. package/frontend/src/features/logs/components/index.ts +2 -0
  358. package/frontend/src/features/logs/helpers.ts +24 -0
  359. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  360. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  361. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  362. package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
  363. package/frontend/src/features/logs/index.ts +8 -2
  364. package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
  365. package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
  366. package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
  367. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  368. package/frontend/src/features/logs/services/log.service.ts +15 -110
  369. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  370. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  371. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  372. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  373. package/frontend/src/features/onboard/components/index.ts +4 -0
  374. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  375. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  376. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  377. package/frontend/src/features/onboard/index.ts +13 -3
  378. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  379. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  380. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  381. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  382. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  383. package/frontend/src/features/storage/components/index.ts +12 -0
  384. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  385. package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
  386. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  387. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  388. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  389. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  390. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  391. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  392. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
  393. package/frontend/src/index.css +1 -0
  394. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  395. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  396. package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
  397. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  398. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  399. package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
  400. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  401. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  402. package/frontend/src/lib/utils/menuItems.ts +183 -0
  403. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  404. package/frontend/src/lib/utils/utils.ts +19 -1
  405. package/frontend/src/vite-env.d.ts +1 -0
  406. package/frontend/vite.config.ts +5 -3
  407. package/functions/server.ts +28 -3
  408. package/functions/worker-template.js +15 -4
  409. package/i18n/README.ar.md +130 -0
  410. package/i18n/README.de.md +130 -0
  411. package/i18n/README.es.md +154 -0
  412. package/i18n/README.fr.md +134 -0
  413. package/i18n/README.hi.md +129 -0
  414. package/i18n/README.ja.md +174 -0
  415. package/i18n/README.ko.md +137 -0
  416. package/i18n/README.pt-BR.md +131 -0
  417. package/i18n/README.ru.md +129 -0
  418. package/i18n/README.zh-CN.md +133 -0
  419. package/openapi/ai.yaml +31 -4
  420. package/openapi/auth.yaml +827 -146
  421. package/package.json +16 -7
  422. package/shared-schemas/package.json +1 -1
  423. package/shared-schemas/src/ai-api.schema.ts +34 -58
  424. package/shared-schemas/src/ai.schema.ts +5 -0
  425. package/shared-schemas/src/auth-api.schema.ts +154 -8
  426. package/shared-schemas/src/auth.schema.ts +42 -6
  427. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  428. package/shared-schemas/src/database-api.schema.ts +3 -3
  429. package/shared-schemas/src/database.schema.ts +1 -1
  430. package/shared-schemas/src/index.ts +1 -0
  431. package/shared-schemas/src/logs-api.schema.ts +7 -1
  432. package/shared-schemas/src/logs.schema.ts +26 -0
  433. package/shared-schemas/src/metadata.schema.ts +9 -4
  434. package/test-gemini.sh +35 -0
  435. package/test-usage-admin.sh +57 -0
  436. package/test-usage.sh +50 -0
  437. package/zeabur/README.md +13 -0
  438. package/zeabur/template.yml +1032 -0
  439. package/.github/workflows/deploy-aws.yml +0 -130
  440. package/backend/src/api/routes/agent.ts +0 -29
  441. package/backend/src/api/routes/auth.oauth.ts +0 -482
  442. package/backend/src/api/routes/auth.ts +0 -386
  443. package/backend/src/api/routes/docs.ts +0 -66
  444. package/backend/src/api/routes/functions.ts +0 -183
  445. package/backend/src/api/routes/openapi.ts +0 -82
  446. package/backend/src/api/routes/usage.ts +0 -96
  447. package/backend/src/core/ai/client.ts +0 -242
  448. package/backend/src/core/ai/model.ts +0 -117
  449. package/backend/src/core/auth/auth.ts +0 -781
  450. package/backend/src/core/database/table.ts +0 -772
  451. package/backend/src/core/documentation/agent.ts +0 -689
  452. package/backend/src/core/documentation/openapi.ts +0 -856
  453. package/backend/src/core/logs/analytics.ts +0 -76
  454. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  455. package/backend/src/core/storage/storage.ts +0 -923
  456. package/backend/src/utils/cloud-token.ts +0 -39
  457. package/backend/src/utils/helpers.ts +0 -49
  458. package/backend/src/utils/uuid.ts +0 -9
  459. package/backend/tests/manual/test-better-auth.sh +0 -303
  460. package/docker-init/db/logs.sql +0 -9
  461. package/frontend/README.md +0 -112
  462. package/frontend/src/components/datagrid/index.tsx +0 -20
  463. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  464. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  465. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  466. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  467. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  468. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  469. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  470. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  471. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  472. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  473. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  474. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  475. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  476. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  477. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  478. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  479. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  480. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  481. package/frontend/src/features/metadata/index.ts +0 -0
  482. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  483. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  484. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  485. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  486. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  487. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  488. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  489. package/frontend/src/features/onboard/types.ts +0 -8
  490. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  491. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  492. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  493. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  494. /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
  495. /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
  496. /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
  497. /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
  498. /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
  499. /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
  500. /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
  501. /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
  502. /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
  503. /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
  504. /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
  505. /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
  506. /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
  507. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -0,0 +1,118 @@
1
+ import { useEffect } from 'react';
2
+ import { useForm } from 'react-hook-form';
3
+ import { zodResolver } from '@hookform/resolvers/zod';
4
+ import {
5
+ Button,
6
+ Dialog,
7
+ DialogContent,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogFooter,
11
+ Label,
12
+ Textarea,
13
+ } from '@/components';
14
+ import {
15
+ UpdateAIConfigurationRequest,
16
+ updateAIConfigurationRequestSchema,
17
+ } from '@insforge/shared-schemas';
18
+
19
+ interface SystemPromptDialogProps {
20
+ open: boolean;
21
+ onOpenChange: (open: boolean) => void;
22
+ initialSystemPrompt: string | null | undefined;
23
+ onSuccess: (data: UpdateAIConfigurationRequest) => void;
24
+ }
25
+
26
+ export function SystemPromptDialog({
27
+ open,
28
+ onOpenChange,
29
+ initialSystemPrompt,
30
+ onSuccess,
31
+ }: SystemPromptDialogProps) {
32
+ const form = useForm<UpdateAIConfigurationRequest>({
33
+ resolver: zodResolver(updateAIConfigurationRequestSchema),
34
+ defaultValues: {
35
+ systemPrompt: initialSystemPrompt ?? null,
36
+ },
37
+ });
38
+
39
+ // Reset form when dialog opens with new data
40
+ useEffect(() => {
41
+ if (open) {
42
+ form.reset({
43
+ systemPrompt: initialSystemPrompt ?? null,
44
+ });
45
+ }
46
+ }, [open, initialSystemPrompt, form]);
47
+
48
+ const handleFormSubmit = (e: React.FormEvent) => {
49
+ e.preventDefault();
50
+ void form.handleSubmit((data: UpdateAIConfigurationRequest) => {
51
+ onSuccess(data);
52
+ onOpenChange(false);
53
+ })();
54
+ };
55
+
56
+ const handleCancel = () => {
57
+ onOpenChange(false);
58
+ };
59
+
60
+ return (
61
+ <Dialog open={open} onOpenChange={onOpenChange}>
62
+ <DialogContent
63
+ aria-describedby={undefined}
64
+ className="max-w-[600px] p-0 gap-0 border-zinc-200 shadow-[0px_1px_3px_0px_rgba(0,0,0,0.1)]"
65
+ >
66
+ <DialogHeader className="px-6 py-3 flex flex-col gap-1 justify-start border-b border-zinc-200 dark:border-neutral-700">
67
+ <DialogTitle className="text-lg font-semibold text-zinc-950 dark:text-white">
68
+ Edit System Prompt
69
+ </DialogTitle>
70
+ </DialogHeader>
71
+
72
+ <form id="system-prompt-form" onSubmit={handleFormSubmit} className="flex flex-col">
73
+ <div className="flex flex-col gap-6 p-6">
74
+ <div className="flex flex-row gap-10 items-start">
75
+ <Label
76
+ htmlFor="systemPrompt"
77
+ className="text-sm font-normal text-zinc-950 dark:text-neutral-50 whitespace-nowrap"
78
+ >
79
+ System Prompt
80
+ </Label>
81
+ <div className="flex flex-col gap-1 w-full">
82
+ <Textarea
83
+ id="systemPrompt"
84
+ {...form.register('systemPrompt')}
85
+ placeholder="Enter system prompt..."
86
+ className="w-full min-h-[160px] resize-none bg-transparent dark:bg-neutral-900 dark:text-white dark:placeholder:text-neutral-400 dark:border-neutral-700 focus:outline-none"
87
+ />
88
+ {form.formState.errors.systemPrompt && (
89
+ <p className="text-sm text-red-600 dark:text-red-500">
90
+ {form.formState.errors.systemPrompt.message}
91
+ </p>
92
+ )}
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </form>
97
+
98
+ <DialogFooter className="p-6 gap-3 border-t border-zinc-200 dark:border-neutral-700">
99
+ <Button
100
+ type="button"
101
+ variant="outline"
102
+ onClick={handleCancel}
103
+ className="h-9 px-3 py-2 rounded-sm text-sm font-medium dark:bg-neutral-600 dark:text-zinc-300 dark:border-neutral-600 dark:hover:bg-neutral-700"
104
+ >
105
+ Cancel
106
+ </Button>
107
+ <Button
108
+ type="submit"
109
+ form="system-prompt-form"
110
+ className="h-9 px-3 py-2 rounded-sm text-sm font-medium bg-zinc-950 text-white hover:bg-zinc-800 disabled:opacity-40 dark:bg-emerald-300 dark:text-zinc-950 dark:hover:bg-emerald-400"
111
+ >
112
+ Save
113
+ </Button>
114
+ </DialogFooter>
115
+ </DialogContent>
116
+ </Dialog>
117
+ );
118
+ }
@@ -0,0 +1,6 @@
1
+ export { AIModelCard } from './AIConfigCard';
2
+ export { default as AIEmptyState } from './AIEmptyState';
3
+ export { ModalityFilterSidebar } from './ModalityFilterSidebar';
4
+ export { ModelSelectionDialog } from './ModelSelectionDialog';
5
+ export { ModelSelectionGrid } from './ModelSelectionGrid';
6
+ export { SystemPromptDialog } from './SystemPromptDialog';
@@ -1,26 +1,21 @@
1
- import { OpenRouterModel, ModalitySchema } from '@insforge/shared-schemas';
2
-
3
- // Type for pricing information from OpenRouter model
4
- type ModelPricing = {
5
- prompt: string;
6
- completion: string;
7
- image?: string;
8
- request?: string;
9
- webSearch?: string;
10
- internalReasoning?: string;
11
- inputCacheRead?: string;
12
- inputCacheWrite?: string;
13
- };
14
-
15
- export type ModelPriceLevel = 'FREE' | '$' | '$$' | '$$$';
16
-
1
+ import {
2
+ ModalitySchema,
3
+ AIModelSchema,
4
+ AIConfigurationWithUsageSchema,
5
+ } from '@insforge/shared-schemas';
17
6
  export interface ModelOption {
18
- value: string;
19
- label: string;
20
- company: string;
21
- priceLevel: ModelPriceLevel;
22
- priceColor: string;
7
+ id: string;
8
+ modelId: string;
9
+ modelName: string;
10
+ providerName: string;
23
11
  logo: React.ComponentType<React.SVGProps<SVGSVGElement>> | undefined;
12
+ inputModality: ModalitySchema[];
13
+ outputModality: ModalitySchema[];
14
+ priceLevel?: number;
15
+ usageStats?: {
16
+ totalRequests: number;
17
+ };
18
+ systemPrompt?: string | null;
24
19
  }
25
20
 
26
21
  import { Type, Image } from 'lucide-react';
@@ -66,7 +61,7 @@ export const getProviderDisplayName = (providerId: string): string => {
66
61
  openrouter: 'OpenRouter',
67
62
  azure: 'Azure',
68
63
  amazon: 'Amazon',
69
- xai: 'xAI',
64
+ 'x-ai': 'xAI',
70
65
  huggingface: 'HuggingFace',
71
66
  };
72
67
 
@@ -83,73 +78,64 @@ export const getProviderLogo = (
83
78
  anthropic: ClaudeIcon,
84
79
  openai: OpenAIIcon,
85
80
  google: GeminiIcon,
86
- xai: GrokIcon,
81
+ 'x-ai': GrokIcon,
87
82
  amazon: AmazonIcon,
88
83
  };
89
84
  return logoMap[providerId];
90
85
  };
91
86
 
92
- // Calculate price level based on pricing data
93
- export const calculatePriceLevel = (
94
- pricing: ModelPricing | undefined | null
95
- ): { level: ModelPriceLevel; color: string } => {
96
- if (!pricing) {
97
- return { level: 'FREE', color: 'text-green-400' };
98
- }
99
-
100
- // Check if it's free
101
- if (pricing.prompt === '0' && pricing.completion === '0') {
102
- return { level: 'FREE', color: 'text-green-400' };
103
- }
104
-
105
- // Calculate average cost per 1M tokens (prompt + completion)
106
- // Convert from per-token to per-1M-tokens
107
- const promptCostPerToken = parseFloat(pricing.prompt) || 0;
108
- const completionCostPerToken = parseFloat(pricing.completion) || 0;
109
- const promptCostPer1M = promptCostPerToken * 1000000;
110
- const completionCostPer1M = completionCostPerToken * 1000000;
111
- const avgCostPer1M = (promptCostPer1M + completionCostPer1M) / 2;
112
-
113
- // Adjusted thresholds based on actual pricing data and user feedback
114
- if (avgCostPer1M <= 3) {
115
- return { level: '$', color: 'text-green-400' };
116
- } // ≤$3/1M tokens (Haiku, Gemini Flash, etc.)
117
- if (avgCostPer1M <= 15) {
118
- return { level: '$$', color: 'text-amber-400' };
119
- } // ≤$15/1M tokens (GPT-4o, Claude Sonnet, etc.)
120
- return { level: '$$$', color: 'text-red-400' }; // >$15/1M tokens (Claude Opus, etc.)
121
- };
122
-
123
87
  // Helper function to filter AI models based on selected modalities
124
88
  export const filterModelsByModalities = (
125
- models: OpenRouterModel[],
89
+ models: AIModelSchema[],
126
90
  selectedInputModalities: ModalitySchema[],
127
91
  selectedOutputModalities: ModalitySchema[]
128
- ): OpenRouterModel[] => {
92
+ ): AIModelSchema[] => {
129
93
  if (!models?.length) {
130
94
  return [];
131
95
  }
132
96
 
133
- return models
134
- .filter((model) => {
135
- const inputModalities = new Set(model.architecture?.inputModalities || []);
136
- const outputModalities = new Set(model.architecture?.outputModalities || []);
137
- return (
138
- selectedInputModalities.every((m) => inputModalities.has(m)) &&
139
- selectedOutputModalities.every((m) => outputModalities.has(m))
140
- );
141
- })
142
- .sort((a, b) => a.name.localeCompare(b.name));
97
+ return models.filter((model) => {
98
+ const inputModalities = new Set(model.inputModality);
99
+ const outputModalities = new Set(model.outputModality);
100
+ return (
101
+ selectedInputModalities.every((m) => inputModalities.has(m)) &&
102
+ selectedOutputModalities.every((m) => outputModalities.has(m))
103
+ );
104
+ });
143
105
  };
144
106
 
145
107
  // Helper function to get friendly model name from model ID
146
- export const getFriendlyModelName = (modelId: string): string => {
147
- // Extract the model name part (after the last slash)
148
- const modelName = modelId.split('/').pop() || modelId;
149
-
108
+ export const getFriendlyModelName = (rawModelName: string): string => {
150
109
  // Convert kebab-case to Title Case
151
- return modelName
110
+ return rawModelName
152
111
  .split('-')
153
112
  .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
154
113
  .join(' ');
155
114
  };
115
+
116
+ export function toModelOption(model: AIModelSchema | AIConfigurationWithUsageSchema): ModelOption {
117
+ const [rawProviderId, rawModelName] = model.modelId.split('/');
118
+
119
+ return {
120
+ ...model,
121
+ modelName: getFriendlyModelName(rawModelName),
122
+ providerName: getProviderDisplayName(rawProviderId),
123
+ logo: getProviderLogo(rawProviderId),
124
+ };
125
+ }
126
+
127
+ // Sort models with configured ones at the end
128
+ export const sortModelsByConfigurationStatus = (
129
+ models: ModelOption[],
130
+ configuredModelIds: string[]
131
+ ): ModelOption[] => {
132
+ return [...models].sort((a, b) => {
133
+ const aConfigured = configuredModelIds.includes(a.modelId);
134
+ const bConfigured = configuredModelIds.includes(b.modelId);
135
+
136
+ if (aConfigured === bConfigured) {
137
+ return 0;
138
+ }
139
+ return aConfigured ? 1 : -1;
140
+ });
141
+ };
@@ -1,22 +1,19 @@
1
1
  import { useMemo, useCallback } from 'react';
2
2
  import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
3
3
  import { aiService } from '@/features/ai/services/ai.service';
4
- import { authService } from '@/features/auth/services/auth.service';
5
4
  import {
6
- ListModelsResponse,
7
- AIConfigurationWithUsageSchema,
8
5
  CreateAIConfigurationRequest,
9
6
  UpdateAIConfigurationRequest,
10
7
  ModalitySchema,
11
- type OpenRouterModel,
8
+ AIModelSchema,
9
+ AIConfigurationWithUsageSchema,
12
10
  } from '@insforge/shared-schemas';
13
11
  import { useToast } from '@/lib/hooks/useToast';
14
12
  import {
15
- getProviderLogo,
16
- calculatePriceLevel,
17
- getProviderDisplayName,
18
13
  filterModelsByModalities,
14
+ sortModelsByConfigurationStatus,
19
15
  type ModelOption,
16
+ toModelOption,
20
17
  } from '../helpers';
21
18
 
22
19
  interface UseAIConfigsOptions {
@@ -31,10 +28,9 @@ export function useAIConfigs(options: UseAIConfigsOptions = {}) {
31
28
  // Fetch AI models configuration
32
29
  const {
33
30
  data: modelsData,
34
- isLoading,
35
- error,
36
- refetch,
37
- } = useQuery<ListModelsResponse>({
31
+ isLoading: isLoadingModels,
32
+ error: modelsError,
33
+ } = useQuery<AIModelSchema[]>({
38
34
  queryKey: ['ai-models'],
39
35
  queryFn: () => aiService.getModels(),
40
36
  enabled: enabled,
@@ -46,7 +42,6 @@ export function useAIConfigs(options: UseAIConfigsOptions = {}) {
46
42
  data: configurations,
47
43
  isLoading: isLoadingConfigurations,
48
44
  error: configurationsError,
49
- refetch: refetchConfigurations,
50
45
  } = useQuery<AIConfigurationWithUsageSchema[]>({
51
46
  queryKey: ['ai-configurations'],
52
47
  queryFn: () => aiService.listConfigurations(),
@@ -54,14 +49,6 @@ export function useAIConfigs(options: UseAIConfigsOptions = {}) {
54
49
  staleTime: 5 * 60 * 1000, // Cache for 5 minutes
55
50
  });
56
51
 
57
- // Fetch anonymous token (shared across all configs)
58
- const { data: anonTokenData, isLoading: isLoadingAnonToken } = useQuery({
59
- queryKey: ['anon-token'],
60
- queryFn: () => authService.generateAnonToken(),
61
- enabled: enabled,
62
- staleTime: 30 * 60 * 1000, // Cache for 30 minutes since token never expires
63
- });
64
-
65
52
  // Create configuration mutation
66
53
  const createConfigurationMutation = useMutation({
67
54
  mutationFn: (data: CreateAIConfigurationRequest) => aiService.createConfiguration(data),
@@ -99,123 +86,62 @@ export function useAIConfigs(options: UseAIConfigsOptions = {}) {
99
86
  },
100
87
  });
101
88
 
102
- // Extract configured providers (memoized to maintain referential stability)
103
- const configuredTextProviders = useMemo(
104
- () => modelsData?.text?.filter((p) => p.configured) || [],
105
- [modelsData?.text]
106
- );
107
- const configuredImageProviders = useMemo(
108
- () => modelsData?.image?.filter((p) => p.configured) || [],
109
- [modelsData?.image]
89
+ // Convert configurations to ModelOptions
90
+ const configurationOptions = useMemo(
91
+ () => (configurations || []).map(toModelOption),
92
+ [configurations]
110
93
  );
111
94
 
112
- // Extract unconfigured providers
113
- const unconfiguredTextProviders = modelsData?.text?.filter((p) => !p.configured) || [];
114
- const unconfiguredImageProviders = modelsData?.image?.filter((p) => !p.configured) || [];
115
-
116
- // Get all available models (flat list)
117
- const allTextModels = modelsData?.text?.flatMap((p) => p.models) || [];
118
- const allImageModels = modelsData?.image?.flatMap((p) => p.models) || [];
119
-
120
- // All configured models from all providers (flattened with deduplication)
121
- const allConfiguredModels = useMemo(() => {
122
- const uniqueModels = new Map<string, OpenRouterModel>();
123
-
124
- [...configuredTextProviders, ...configuredImageProviders].forEach((provider) => {
125
- provider.models.forEach((model) => {
126
- // Only add if we haven't seen this model.id before
127
- if (!uniqueModels.has(model.id)) {
128
- uniqueModels.set(model.id, model);
129
- }
130
- });
131
- });
95
+ // Get configured model IDs for filtering
96
+ const configuredModelIds = useMemo(
97
+ () => configurations?.map((config) => config.modelId) || [],
98
+ [configurations]
99
+ );
132
100
 
133
- return Array.from(uniqueModels.values());
134
- }, [configuredTextProviders, configuredImageProviders]);
101
+ // All available models from all providers
102
+ const allAvailableModels = useMemo(() => modelsData || [], [modelsData]);
135
103
 
136
104
  // Helper function to get filtered and processed models
137
105
  const getFilteredModels = useCallback(
138
106
  (inputModality: ModalitySchema[], outputModality: ModalitySchema[]): ModelOption[] => {
139
- const filteredRawModels = filterModelsByModalities(
140
- allConfiguredModels,
141
- inputModality,
142
- outputModality
143
- );
144
-
145
- return filteredRawModels.map((model) => {
146
- const companyId = model.id.split('/')[0];
147
- const priceInfo = calculatePriceLevel(model.pricing);
148
-
149
- return {
150
- value: model.id,
151
- label: model.name,
152
- company: getProviderDisplayName(companyId),
153
- priceLevel: priceInfo.level,
154
- priceColor: priceInfo.color,
155
- logo: getProviderLogo(companyId),
156
- };
157
- });
107
+ // If both modality arrays are empty, return all models
108
+ const shouldFilter = inputModality.length || outputModality.length;
109
+
110
+ const filteredRawModels = shouldFilter
111
+ ? filterModelsByModalities(allAvailableModels, inputModality, outputModality)
112
+ : allAvailableModels;
113
+
114
+ // Convert to ModelOption using centralized converter
115
+ const modelOptions = filteredRawModels.map(toModelOption);
116
+
117
+ // Sort with configured models at the end
118
+ return sortModelsByConfigurationStatus(modelOptions, configuredModelIds);
158
119
  },
159
- [allConfiguredModels]
120
+ [allAvailableModels, configuredModelIds]
160
121
  );
161
122
 
162
- // Check if any providers are configured
163
- const hasConfiguredTextProviders = configuredTextProviders.length > 0;
164
- const hasConfiguredImageProviders = configuredImageProviders.length > 0;
165
- const hasAnyConfiguration = hasConfiguredTextProviders || hasConfiguredImageProviders;
166
-
167
123
  return {
168
- // Raw data
169
- modelsData,
170
- isLoading,
171
- error,
172
-
173
- // Providers by type
174
- textProviders: modelsData?.text || [],
175
- imageProviders: modelsData?.image || [],
124
+ // Models data
125
+ isLoadingModels,
126
+ modelsError,
176
127
 
177
128
  // Configured providers
178
- configuredTextProviders,
179
- configuredImageProviders,
180
- allConfiguredModels,
181
-
182
- // Unconfigured providers
183
- unconfiguredTextProviders,
184
- unconfiguredImageProviders,
185
-
186
- // Models lists
187
- allTextModels,
188
- allImageModels,
189
-
190
- // Status checks
191
- hasConfiguredTextProviders,
192
- hasConfiguredImageProviders,
193
- hasAnyConfiguration,
129
+ allAvailableModels,
194
130
 
195
131
  // Configurations data
196
- configurations: configurations || [],
197
132
  isLoadingConfigurations,
198
133
  configurationsError,
199
134
 
200
- // Anonymous token data
201
- anonKey: anonTokenData?.accessToken,
202
- isLoadingAnonToken,
203
-
204
135
  // Configuration mutations
205
136
  createConfiguration: createConfigurationMutation.mutate,
206
137
  updateConfiguration: updateConfigurationMutation.mutate,
207
138
  deleteConfiguration: deleteConfigurationMutation.mutate,
208
139
 
209
- // Mutation states
210
- isCreating: createConfigurationMutation.isPending,
211
- isUpdating: updateConfigurationMutation.isPending,
212
- isDeleting: deleteConfigurationMutation.isPending,
213
-
214
- // Operations
215
- refetch,
216
- refetchConfigurations,
217
-
218
140
  // Helper functions
219
141
  getFilteredModels,
142
+
143
+ // Return converted configurations instead of raw data
144
+ configurationOptions,
145
+ configuredModelIds,
220
146
  };
221
147
  }
@@ -70,8 +70,6 @@ export function useAIRemainingCredits(enabled = true) {
70
70
  queryKey: ['ai-remaining-credits'],
71
71
  queryFn: () => aiService.getRemainingCredits(),
72
72
  enabled: enabled,
73
- staleTime: 30 * 1000, // Cache for 30 seconds
74
- refetchInterval: 60 * 1000, // Refetch every minute
75
73
  retry: false,
76
74
  });
77
75
  }