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,60 @@
1
+ import { isCloudEnvironment } from '@/utils/environment.js';
2
+ import { AIClientService } from '@/providers/ai/openrouter.provider.js';
3
+ import type { RawOpenRouterModel } from '@/types/ai.js';
4
+ import type { AIModelSchema } from '@insforge/shared-schemas';
5
+ import { calculatePriceLevel, filterAndSortModalities, getProviderOrder } from './helpers.js';
6
+
7
+ export class AIModelService {
8
+ /**
9
+ * Get all available AI models
10
+ * Fetches from cloud API if in cloud environment, otherwise from OpenRouter directly
11
+ */
12
+ static async getModels(): Promise<AIModelSchema[]> {
13
+ const credentialsService = AIClientService.getInstance();
14
+ const configured = credentialsService.isConfigured();
15
+
16
+ if (!configured) {
17
+ return [];
18
+ }
19
+
20
+ // Get API key from credentials service
21
+ const apiKey = await credentialsService.getApiKey();
22
+
23
+ // Determine the API endpoint based on environment
24
+ const apiUrl = isCloudEnvironment()
25
+ ? 'https://api.insforge.dev/ai/v1/models'
26
+ : 'https://openrouter.ai/api/v1/models/user';
27
+
28
+ // Fetch models from the appropriate endpoint
29
+ const response = await fetch(apiUrl, {
30
+ headers: {
31
+ Authorization: `Bearer ${apiKey}`,
32
+ },
33
+ });
34
+
35
+ if (!response.ok) {
36
+ throw new Error(`Failed to fetch models: ${response.statusText}`);
37
+ }
38
+
39
+ const data = (await response.json()) as { data: RawOpenRouterModel[] };
40
+ const rawModels = data.data || [];
41
+
42
+ const models: AIModelSchema[] = rawModels
43
+ .map((rawModel) => ({
44
+ id: rawModel.id, // OpenRouter provided model ID
45
+ modelId: rawModel.id,
46
+ provider: 'openrouter',
47
+ inputModality: filterAndSortModalities(rawModel.architecture?.input_modalities || []),
48
+ outputModality: filterAndSortModalities(rawModel.architecture?.output_modalities || []),
49
+ priceLevel: calculatePriceLevel(rawModel.pricing),
50
+ }))
51
+ .sort((a, b) => {
52
+ const [aCompany = '', bCompany = ''] = [a.id.split('/')[0], b.id.split('/')[0]];
53
+
54
+ const orderDiff = getProviderOrder(aCompany) - getProviderOrder(bCompany);
55
+ return orderDiff !== 0 ? orderDiff : a.id.localeCompare(b.id);
56
+ });
57
+
58
+ return models || [];
59
+ }
60
+ }
@@ -1,5 +1,5 @@
1
1
  import { Pool } from 'pg';
2
- import { DatabaseManager } from '@/core/database/manager.js';
2
+ import { DatabaseManager } from '@/infra/database/database.manager.js';
3
3
  import logger from '@/utils/logger.js';
4
4
  import type {
5
5
  AIUsageDataSchema,
@@ -9,8 +9,18 @@ import type {
9
9
  } from '@insforge/shared-schemas';
10
10
 
11
11
  export class AIUsageService {
12
+ private static instance: AIUsageService;
12
13
  private pool: Pool | null = null;
13
14
 
15
+ private constructor() {}
16
+
17
+ public static getInstance(): AIUsageService {
18
+ if (!AIUsageService.instance) {
19
+ AIUsageService.instance = new AIUsageService();
20
+ }
21
+ return AIUsageService.instance;
22
+ }
23
+
14
24
  private getPool(): Pool {
15
25
  if (!this.pool) {
16
26
  this.pool = DatabaseManager.getInstance().getPool();
@@ -19,9 +29,8 @@ export class AIUsageService {
19
29
  }
20
30
 
21
31
  async trackUsage(data: AIUsageDataSchema): Promise<{ id: string }> {
22
- const client = await this.getPool().connect();
23
32
  try {
24
- const result = await client.query(
33
+ const result = await this.getPool().query(
25
34
  `INSERT INTO _ai_usage (config_id, input_tokens, output_tokens, image_count, image_resolution)
26
35
  VALUES ($1, $2, $3, $4, $5)
27
36
  RETURNING id`,
@@ -46,8 +55,6 @@ export class AIUsageService {
46
55
  } catch (error) {
47
56
  logger.error('Failed to track AI usage', { error, data });
48
57
  throw new Error('Failed to track AI usage');
49
- } finally {
50
- client.release();
51
58
  }
52
59
  }
53
60
 
@@ -59,9 +66,8 @@ export class AIUsageService {
59
66
  ): Promise<{ id: string }> {
60
67
  const totalTokens = (inputTokens || 0) + (outputTokens || 0);
61
68
 
62
- const client = await this.getPool().connect();
63
69
  try {
64
- const usageResult = await client.query(
70
+ const usageResult = await this.getPool().query(
65
71
  `INSERT INTO _ai_usage (config_id, input_tokens, output_tokens, model_id)
66
72
  VALUES ($1, $2, $3, $4)
67
73
  RETURNING id`,
@@ -81,8 +87,6 @@ export class AIUsageService {
81
87
  } catch (error) {
82
88
  logger.error('Failed to track chat usage', { error, configId });
83
89
  throw new Error('Failed to track chat usage');
84
- } finally {
85
- client.release();
86
90
  }
87
91
  }
88
92
 
@@ -94,9 +98,8 @@ export class AIUsageService {
94
98
  outputTokens?: number,
95
99
  modelId?: string
96
100
  ): Promise<{ id: string }> {
97
- const client = await this.getPool().connect();
98
101
  try {
99
- const usageResult = await client.query(
102
+ const usageResult = await this.getPool().query(
100
103
  `INSERT INTO _ai_usage (config_id, image_count, image_resolution, input_tokens, output_tokens, model_id)
101
104
  VALUES ($1, $2, $3, $4, $5, $6)
102
105
  RETURNING id`,
@@ -124,8 +127,6 @@ export class AIUsageService {
124
127
  } catch (error) {
125
128
  logger.error('Failed to track image usage', { error, configId });
126
129
  throw new Error('Failed to track image usage');
127
- } finally {
128
- client.release();
129
130
  }
130
131
  }
131
132
 
@@ -134,10 +135,9 @@ export class AIUsageService {
134
135
  startDate?: Date,
135
136
  endDate?: Date
136
137
  ): Promise<AIUsageRecordSchema[]> {
137
- const client = await this.getPool().connect();
138
138
  try {
139
139
  let query = `
140
- SELECT id, config_id as "configId", input_tokens as "inputTokens",
140
+ SELECT id, config_id as "configId", input_tokens as "inputTokens",
141
141
  output_tokens as "outputTokens", image_count as "imageCount",
142
142
  image_resolution as "imageResolution", created_at as "createdAt"
143
143
  FROM _ai_usage
@@ -158,14 +158,12 @@ export class AIUsageService {
158
158
 
159
159
  query += ' ORDER BY created_at DESC';
160
160
 
161
- const result = await client.query(query, params);
161
+ const result = await this.getPool().query(query, params);
162
162
 
163
163
  return result.rows;
164
164
  } catch (error) {
165
165
  logger.error('Failed to fetch usage by config', { error, configId });
166
166
  throw new Error('Failed to fetch usage records');
167
- } finally {
168
- client.release();
169
167
  }
170
168
  }
171
169
 
@@ -174,10 +172,9 @@ export class AIUsageService {
174
172
  startDate?: Date,
175
173
  endDate?: Date
176
174
  ): Promise<AIUsageSummarySchema> {
177
- const client = await this.getPool().connect();
178
175
  try {
179
176
  let query = `
180
- SELECT
177
+ SELECT
181
178
  COALESCE(SUM(input_tokens), 0) as "totalInputTokens",
182
179
  COALESCE(SUM(output_tokens), 0) as "totalOutputTokens",
183
180
  COALESCE(SUM(COALESCE(input_tokens, 0) + COALESCE(output_tokens, 0)), 0) as "totalTokens",
@@ -204,7 +201,7 @@ export class AIUsageService {
204
201
  query += ` AND created_at <= $${params.length}`;
205
202
  }
206
203
 
207
- const result = await client.query(query, params);
204
+ const result = await this.getPool().query(query, params);
208
205
 
209
206
  return {
210
207
  totalInputTokens: parseInt(result.rows[0].totalInputTokens),
@@ -216,8 +213,6 @@ export class AIUsageService {
216
213
  } catch (error) {
217
214
  logger.error('Failed to fetch usage summary', { error, configId });
218
215
  throw new Error('Failed to fetch usage summary');
219
- } finally {
220
- client.release();
221
216
  }
222
217
  }
223
218
 
@@ -227,21 +222,21 @@ export class AIUsageService {
227
222
  limit?: number,
228
223
  offset?: number
229
224
  ): Promise<ListAIUsageResponse> {
230
- const client = await this.getPool().connect();
231
225
  try {
232
226
  let query = `
233
- SELECT
234
- u.id,
235
- u.config_id as "configId",
236
- u.input_tokens as "inputTokens",
237
- u.output_tokens as "outputTokens",
227
+ SELECT
228
+ u.id,
229
+ u.config_id as "configId",
230
+ u.input_tokens as "inputTokens",
231
+ u.output_tokens as "outputTokens",
238
232
  u.image_count as "imageCount",
239
- u.image_resolution as "imageResolution",
233
+ u.image_resolution as "imageResolution",
240
234
  u.created_at as "createdAt",
241
235
  u.model_id as "modelId",
242
236
  COALESCE(u.model_id, c.model_id) as "model",
243
237
  c.provider,
244
- c.modality
238
+ c.input_modality as "inputModality",
239
+ c.output_modality as "outputModality"
245
240
  FROM _ai_usage u
246
241
  LEFT JOIN _ai_configs c ON u.config_id = c.id
247
242
  WHERE 1=1
@@ -260,7 +255,7 @@ export class AIUsageService {
260
255
  }
261
256
 
262
257
  const countQuery = `SELECT COUNT(*) as total FROM (${query}) as subquery`;
263
- const countResult = await client.query(countQuery, params);
258
+ const countResult = await this.getPool().query(countQuery, params);
264
259
 
265
260
  query += ' ORDER BY u.created_at DESC';
266
261
 
@@ -274,7 +269,7 @@ export class AIUsageService {
274
269
  query += ` OFFSET $${params.length}`;
275
270
  }
276
271
 
277
- const result = await client.query(query, params);
272
+ const result = await this.getPool().query(query, params);
278
273
 
279
274
  return {
280
275
  records: result.rows,
@@ -283,8 +278,6 @@ export class AIUsageService {
283
278
  } catch (error) {
284
279
  logger.error('Failed to fetch all usage records', { error });
285
280
  throw new Error('Failed to fetch usage records');
286
- } finally {
287
- client.release();
288
281
  }
289
282
  }
290
283
  }
@@ -1,19 +1,29 @@
1
1
  import OpenAI from 'openai';
2
- import { AIUsageService } from './usage';
3
- import { AIConfigService } from './config';
4
- import { AIClientService } from './client';
2
+ import { AIUsageService } from './ai-usage.service.js';
3
+ import { AIConfigService } from './ai-config.service.js';
4
+ import { AIClientService } from '@/providers/ai/openrouter.provider.js';
5
5
  import type {
6
6
  AIConfigurationSchema,
7
7
  ChatCompletionResponse,
8
8
  ChatMessageSchema,
9
9
  } from '@insforge/shared-schemas';
10
10
  import logger from '@/utils/logger.js';
11
- import { ChatCompletionOptions } from '@/types/ai';
11
+ import { ChatCompletionOptions } from '@/types/ai.js';
12
12
 
13
- export class ChatService {
14
- private aiUsageService = new AIUsageService();
15
- private aiConfigService = new AIConfigService();
16
- private aiCredentialsService = AIClientService.getInstance();
13
+ export class ChatCompletionService {
14
+ private static instance: ChatCompletionService;
15
+ private aiUsageService = AIUsageService.getInstance();
16
+ private aiConfigService = AIConfigService.getInstance();
17
+ private aiClientService = AIClientService.getInstance();
18
+
19
+ private constructor() {}
20
+
21
+ public static getInstance(): ChatCompletionService {
22
+ if (!ChatCompletionService.instance) {
23
+ ChatCompletionService.instance = new ChatCompletionService();
24
+ }
25
+ return ChatCompletionService.instance;
26
+ }
17
27
 
18
28
  /**
19
29
  * Format messages for OpenAI API with multimodal support
@@ -31,8 +41,8 @@ export class ChatService {
31
41
 
32
42
  // Format conversation messages
33
43
  for (const msg of messages) {
34
- // Check if message has images
35
- if (msg.images && msg.images.length > 0) {
44
+ // Check if message has images (legacy format), new format image is within the content array
45
+ if (msg.images && msg.images.length && typeof msg.content === 'string') {
36
46
  // Build multimodal content array
37
47
  const content = [
38
48
  { type: 'text', text: msg.content },
@@ -47,11 +57,11 @@ export class ChatService {
47
57
  content,
48
58
  } as OpenAI.Chat.ChatCompletionMessageParam);
49
59
  } else {
50
- // Simple text message
60
+ // Simple text message or new format (content array)
51
61
  formattedMessages.push({
52
62
  role: msg.role as 'system' | 'user' | 'assistant',
53
63
  content: msg.content,
54
- });
64
+ } as OpenAI.Chat.ChatCompletionMessageParam);
55
65
  }
56
66
  }
57
67
 
@@ -81,23 +91,24 @@ export class ChatService {
81
91
  options: ChatCompletionOptions
82
92
  ): Promise<ChatCompletionResponse> {
83
93
  try {
84
- // Get the client (handles validation and initialization automatically)
85
- const client = await this.aiCredentialsService.getClient();
86
-
87
94
  // Validate model and get config
88
95
  const aiConfig = await this.validateAndGetConfig(options.model);
89
96
 
90
97
  // Apply system prompt from config if available
91
98
  const formattedMessages = this.formatMessages(messages, aiConfig?.systemPrompt);
92
-
93
- const response = await client.chat.completions.create({
99
+ const request: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming = {
94
100
  model: options.model,
95
101
  messages: formattedMessages,
96
102
  temperature: options.temperature ?? 0.7,
97
103
  max_tokens: options.maxTokens ?? 4096,
98
104
  top_p: options.topP,
99
105
  stream: false,
100
- });
106
+ };
107
+
108
+ // Send request with automatic renewal and retry logic
109
+ const response = await this.aiClientService.sendRequest((client) =>
110
+ client.chat.completions.create(request)
111
+ );
101
112
 
102
113
  // Extract token usage if available
103
114
  const tokenUsage = response.usage
@@ -122,7 +133,7 @@ export class ChatService {
122
133
  text: response.choices[0]?.message?.content || '',
123
134
  metadata: {
124
135
  model: options.model,
125
- ...tokenUsage,
136
+ usage: tokenUsage,
126
137
  },
127
138
  };
128
139
  } catch (error) {
@@ -146,23 +157,25 @@ export class ChatService {
146
157
  tokenUsage?: { promptTokens?: number; completionTokens?: number; totalTokens?: number };
147
158
  }> {
148
159
  try {
149
- // Get the client (handles validation and initialization automatically)
150
- const client = await this.aiCredentialsService.getClient();
151
-
152
160
  // Validate model and get config
153
161
  const aiConfig = await this.validateAndGetConfig(options.model);
154
162
 
155
163
  // Apply system prompt from config if available
156
164
  const formattedMessages = this.formatMessages(messages, aiConfig?.systemPrompt);
157
165
 
158
- const stream = await client.chat.completions.create({
166
+ const request: OpenAI.Chat.ChatCompletionCreateParamsStreaming = {
159
167
  model: options.model,
160
168
  messages: formattedMessages,
161
169
  temperature: options.temperature ?? 0.7,
162
170
  max_tokens: options.maxTokens ?? 4096,
163
171
  top_p: options.topP,
164
172
  stream: true,
165
- });
173
+ };
174
+
175
+ // Send request with automatic renewal and retry logic
176
+ const stream = await this.aiClientService.sendRequest((client) =>
177
+ client.chat.completions.create(request)
178
+ );
166
179
 
167
180
  const tokenUsage = {
168
181
  promptTokens: 0,
@@ -0,0 +1,64 @@
1
+ import type { RawOpenRouterModel } from '@/types/ai.js';
2
+ import type { ModalitySchema } from '@insforge/shared-schemas';
3
+
4
+ const MODALITY_ORDER = ['text', 'image', 'audio', 'video', 'file'];
5
+ const PROVIDER_ORDER: Record<string, number> = {
6
+ openai: 1,
7
+ anthropic: 2,
8
+ google: 3,
9
+ amazon: 4,
10
+ };
11
+
12
+ /**
13
+ * Sort modalities by predefined order
14
+ */
15
+ export function sortModalities(modalities: string[]): string[] {
16
+ return [...modalities].sort((a, b) => {
17
+ const aIndex = MODALITY_ORDER.indexOf(a);
18
+ const bIndex = MODALITY_ORDER.indexOf(b);
19
+ return aIndex - bIndex;
20
+ });
21
+ }
22
+
23
+ /**
24
+ * Filter to only supported modalities and sort
25
+ */
26
+ export function filterAndSortModalities(modalities: string[]): ModalitySchema[] {
27
+ const supportedModalities: ModalitySchema[] = ['text', 'image'];
28
+ const filtered = modalities.filter((m): m is ModalitySchema =>
29
+ supportedModalities.includes(m as ModalitySchema)
30
+ );
31
+ return sortModalities(filtered) as ModalitySchema[];
32
+ }
33
+
34
+ /**
35
+ * Calculate price level (0-3)
36
+ */
37
+ export function calculatePriceLevel(pricing: RawOpenRouterModel['pricing']): number {
38
+ if (!pricing) {
39
+ return 0;
40
+ }
41
+ if (pricing.prompt === '0' && pricing.completion === '0') {
42
+ return 0;
43
+ }
44
+
45
+ const promptCostPerToken = parseFloat(pricing.prompt) || 0;
46
+ const completionCostPerToken = parseFloat(pricing.completion) || 0;
47
+ const avgCostPer1M = ((promptCostPerToken + completionCostPerToken) / 2) * 1000000;
48
+
49
+ if (avgCostPer1M <= 3) {
50
+ return 1;
51
+ }
52
+ if (avgCostPer1M <= 15) {
53
+ return 2;
54
+ }
55
+ return 3;
56
+ }
57
+
58
+ /**
59
+ * Get provider order for sorting
60
+ */
61
+ export function getProviderOrder(modelId: string): number {
62
+ const companyId = modelId.split('/')[0]?.toLowerCase() || '';
63
+ return PROVIDER_ORDER[companyId] || 999;
64
+ }
@@ -1,20 +1,20 @@
1
1
  import OpenAI from 'openai';
2
2
 
3
- import { AIUsageService } from './usage';
4
- import { AIConfigService } from './config';
5
- import { AIClientService } from './client';
3
+ import { AIUsageService } from './ai-usage.service.js';
4
+ import { AIConfigService } from './ai-config.service.js';
5
+ import { AIClientService } from '@/providers/ai/openrouter.provider.js';
6
6
  import type {
7
7
  AIConfigurationSchema,
8
8
  ImageGenerationRequest,
9
9
  ImageGenerationResponse,
10
10
  } from '@insforge/shared-schemas';
11
11
  import logger from '@/utils/logger.js';
12
- import { OpenRouterImageMessage } from '@/types/ai';
12
+ import { OpenRouterImageMessage } from '@/types/ai.js';
13
13
 
14
- export class ImageService {
15
- private static aiUsageService = new AIUsageService();
16
- private static aiConfigService = new AIConfigService();
17
- private static aiCredentialsService = AIClientService.getInstance();
14
+ export class ImageGenerationService {
15
+ private static aiUsageService = AIUsageService.getInstance();
16
+ private static aiConfigService = AIConfigService.getInstance();
17
+ private static aiClientService = AIClientService.getInstance();
18
18
 
19
19
  /**
20
20
  * Validate model and get config
@@ -22,7 +22,7 @@ export class ImageService {
22
22
  private static async validateAndGetConfig(
23
23
  modelId: string
24
24
  ): Promise<AIConfigurationSchema | null> {
25
- const aiConfig = await ImageService.aiConfigService.findByModelId(modelId);
25
+ const aiConfig = await ImageGenerationService.aiConfigService.findByModelId(modelId);
26
26
  if (!aiConfig) {
27
27
  throw new Error(
28
28
  `Model ${modelId} is not enabled. Please contact your administrator to enable this model.`
@@ -36,11 +36,8 @@ export class ImageService {
36
36
  * @param options - Image generation options
37
37
  */
38
38
  static async generate(options: ImageGenerationRequest): Promise<ImageGenerationResponse> {
39
- // Get the client (handles validation and initialization automatically)
40
- const client = await this.aiCredentialsService.getClient();
41
-
42
39
  // Validate model and get config
43
- const aiConfig = await ImageService.validateAndGetConfig(options.model);
40
+ const aiConfig = await ImageGenerationService.validateAndGetConfig(options.model);
44
41
 
45
42
  const model = options.model;
46
43
 
@@ -77,10 +74,11 @@ export class ImageService {
77
74
  modalities: ['text', 'image'],
78
75
  };
79
76
 
80
- // Use OpenRouter's standard chat completions API
81
- // Cast the extended request to the base OpenAI type for the SDK call
82
- const response = (await client.chat.completions.create(
83
- request as OpenAI.Chat.ChatCompletionCreateParamsNonStreaming
77
+ // Send request with automatic renewal and retry logic
78
+ const response = (await this.aiClientService.sendRequest((client) =>
79
+ client.chat.completions.create(
80
+ request as OpenAI.Chat.ChatCompletionCreateParamsNonStreaming
81
+ )
84
82
  )) as OpenAI.Chat.ChatCompletion;
85
83
 
86
84
  // Initialize the result
@@ -99,7 +97,7 @@ export class ImageService {
99
97
  };
100
98
 
101
99
  // Process the OpenAI-compatible response
102
- if (response.choices && response.choices.length > 0) {
100
+ if (response.choices && response.choices.length) {
103
101
  for (const choice of response.choices) {
104
102
  const message = choice.message;
105
103
 
@@ -135,7 +133,7 @@ export class ImageService {
135
133
  const inputTokens = result.metadata?.usage?.promptTokens;
136
134
  const outputTokens = result.metadata?.usage?.completionTokens;
137
135
 
138
- await ImageService.aiUsageService.trackImageGenerationUsage(
136
+ await ImageGenerationService.aiUsageService.trackImageGenerationUsage(
139
137
  aiConfig.id,
140
138
  result.images.length,
141
139
  undefined, // image resolution not available from OpenRouter
@@ -0,0 +1,13 @@
1
+ export { AIConfigService } from './ai-config.service.js';
2
+ export { AIModelService } from './ai-model.service.js';
3
+ export { AIUsageService } from './ai-usage.service.js';
4
+ export { ChatCompletionService } from './chat-completion.service.js';
5
+ export { ImageGenerationService } from './image-generation.service.js';
6
+
7
+ // Helper functions
8
+ export {
9
+ sortModalities,
10
+ filterAndSortModalities,
11
+ calculatePriceLevel,
12
+ getProviderOrder,
13
+ } from './helpers.js';