insforge 1.3.0 → 1.4.8

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 (269) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/auth/package.json +5 -3
  3. package/auth/src/lib/broadcastService.ts +115 -117
  4. package/auth/src/lib/insforge.ts +8 -0
  5. package/auth/src/main.tsx +2 -4
  6. package/auth/src/pages/SignInPage.tsx +60 -60
  7. package/auth/src/pages/SignUpPage.tsx +60 -60
  8. package/auth/src/pages/VerifyEmailPage.tsx +18 -0
  9. package/auth/tsconfig.json +2 -1
  10. package/backend/package.json +10 -6
  11. package/backend/src/api/middlewares/rate-limiters.ts +127 -127
  12. package/backend/src/api/routes/ai/index.routes.ts +475 -468
  13. package/backend/src/api/routes/auth/index.routes.ts +85 -32
  14. package/backend/src/api/routes/auth/oauth.routes.ts +11 -6
  15. package/backend/src/api/routes/database/index.routes.ts +2 -0
  16. package/backend/src/api/routes/database/records.routes.ts +39 -175
  17. package/backend/src/api/routes/database/rpc.routes.ts +69 -0
  18. package/backend/src/api/routes/deployments/index.routes.ts +192 -0
  19. package/backend/src/api/routes/docs/index.routes.ts +3 -2
  20. package/backend/src/api/routes/email/index.routes.ts +35 -35
  21. package/backend/src/api/routes/functions/index.routes.ts +3 -3
  22. package/backend/src/api/routes/metadata/index.routes.ts +26 -0
  23. package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
  24. package/backend/src/infra/database/database.manager.ts +0 -10
  25. package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
  26. package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
  27. package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
  28. package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
  29. package/backend/src/infra/security/token.manager.ts +1 -4
  30. package/backend/src/providers/ai/openrouter.provider.ts +12 -3
  31. package/backend/src/providers/database/base.provider.ts +39 -0
  32. package/backend/src/providers/database/cloud.provider.ts +159 -0
  33. package/backend/src/providers/deployments/vercel.provider.ts +516 -0
  34. package/backend/src/server.ts +19 -7
  35. package/backend/src/services/ai/ai-config.service.ts +6 -6
  36. package/backend/src/services/ai/ai-model.service.ts +60 -60
  37. package/backend/src/services/ai/ai-usage.service.ts +7 -7
  38. package/backend/src/services/ai/chat-completion.service.ts +415 -220
  39. package/backend/src/services/ai/helpers.ts +64 -64
  40. package/backend/src/services/ai/index.ts +13 -13
  41. package/backend/src/services/auth/auth-config.service.ts +4 -4
  42. package/backend/src/services/auth/auth-otp.service.ts +6 -6
  43. package/backend/src/services/auth/auth.service.ts +134 -74
  44. package/backend/src/services/auth/index.ts +4 -4
  45. package/backend/src/services/auth/oauth-config.service.ts +12 -12
  46. package/backend/src/services/database/database-advance.service.ts +19 -55
  47. package/backend/src/services/database/database-table.service.ts +38 -85
  48. package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
  49. package/backend/src/services/deployments/deployment.service.ts +693 -0
  50. package/backend/src/services/functions/function.service.ts +61 -41
  51. package/backend/src/services/logs/audit.service.ts +10 -10
  52. package/backend/src/services/secrets/secret.service.ts +101 -27
  53. package/backend/src/services/storage/storage.service.ts +30 -30
  54. package/backend/src/services/usage/usage.service.ts +6 -6
  55. package/backend/src/types/ai.ts +8 -0
  56. package/backend/src/types/auth.ts +5 -1
  57. package/backend/src/types/database.ts +2 -0
  58. package/backend/src/types/deployments.ts +33 -0
  59. package/backend/src/types/storage.ts +1 -1
  60. package/backend/src/types/webhooks.ts +45 -0
  61. package/backend/src/utils/cookies.ts +34 -35
  62. package/backend/src/utils/environment.ts +0 -14
  63. package/backend/src/utils/s3-config-loader.ts +64 -64
  64. package/backend/src/utils/seed.ts +334 -301
  65. package/backend/src/utils/sql-parser.ts +126 -0
  66. package/backend/src/utils/utils.ts +114 -114
  67. package/backend/src/utils/validations.ts +10 -10
  68. package/backend/tests/local/test-rpc.sh +141 -0
  69. package/backend/tests/local/test-secrets.sh +1 -1
  70. package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
  71. package/backend/tests/manual/test-rawsql-modes.sh +24 -24
  72. package/backend/tests/unit/database-advance.test.ts +326 -0
  73. package/backend/tests/unit/helpers.test.ts +2 -2
  74. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +13 -10
  75. package/docker-compose.prod.yml +1 -1
  76. package/docker-compose.yml +1 -1
  77. package/docs/agent-docs/deployment.md +79 -0
  78. package/docs/changelog.mdx +165 -72
  79. package/docs/core-concepts/ai/architecture.mdx +1 -23
  80. package/docs/core-concepts/ai/sdk.mdx +26 -1
  81. package/docs/core-concepts/authentication/architecture.mdx +6 -8
  82. package/docs/core-concepts/authentication/sdk.mdx +387 -91
  83. package/docs/core-concepts/authentication/ui-components/customization.mdx +460 -256
  84. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +50 -24
  85. package/docs/core-concepts/authentication/ui-components/react-router.mdx +18 -19
  86. package/docs/core-concepts/authentication/ui-components/react.mdx +26 -19
  87. package/docs/core-concepts/database/architecture.mdx +58 -21
  88. package/docs/core-concepts/database/pgvector.mdx +138 -0
  89. package/docs/core-concepts/database/sdk.mdx +17 -17
  90. package/docs/core-concepts/deployments/architecture.mdx +152 -0
  91. package/docs/core-concepts/email/architecture.mdx +4 -2
  92. package/docs/core-concepts/functions/architecture.mdx +1 -1
  93. package/docs/core-concepts/functions/sdk.mdx +0 -1
  94. package/docs/core-concepts/realtime/architecture.mdx +1 -1
  95. package/docs/core-concepts/storage/architecture.mdx +1 -1
  96. package/docs/core-concepts/storage/sdk.mdx +25 -25
  97. package/docs/docs.json +14 -6
  98. package/docs/favicon.png +0 -0
  99. package/docs/favicon.svg +3 -18
  100. package/docs/images/changelog/dec-2025/apple-oauth.mp4 +0 -0
  101. package/docs/images/changelog/dec-2025/moreModels.png +0 -0
  102. package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
  103. package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
  104. package/docs/images/changelog/dec-2025/realtime2.png +0 -0
  105. package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
  106. package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
  107. package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
  108. package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
  109. package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
  110. package/docs/images/mcp-setup/claude-code-connect.png +0 -0
  111. package/docs/images/mcp-setup/cline-1.png +0 -0
  112. package/docs/images/mcp-setup/cline-2.png +0 -0
  113. package/docs/images/mcp-setup/cline-3.png +0 -0
  114. package/docs/images/mcp-setup/connect-project.png +0 -0
  115. package/docs/images/mcp-setup/copilot-1.png +0 -0
  116. package/docs/images/mcp-setup/copilot-2.png +0 -0
  117. package/docs/images/mcp-setup/copilot-3.png +0 -0
  118. package/docs/images/mcp-setup/mcp-json-1.png +0 -0
  119. package/docs/images/mcp-setup/mcp-json-2.png +0 -0
  120. package/docs/images/mcp-setup/qoder-1.png +0 -0
  121. package/docs/images/mcp-setup/qoder-2.png +0 -0
  122. package/docs/images/mcp-setup/roocode-1.png +0 -0
  123. package/docs/images/mcp-setup/roocode-2.png +0 -0
  124. package/docs/images/mcp-setup/trae-1.png +0 -0
  125. package/docs/images/mcp-setup/trae-2.png +0 -0
  126. package/docs/images/mcp-setup/trae-3.png +0 -0
  127. package/docs/images/mcp-setup/trae-4.png +0 -0
  128. package/docs/images/mcp-setup/trae-5.png +0 -0
  129. package/docs/images/mcp-setup/windsurf-1.png +0 -0
  130. package/docs/images/mcp-setup/windsurf-2.png +0 -0
  131. package/docs/insforge-instructions-sdk.md +7 -3
  132. package/docs/introduction.mdx +9 -8
  133. package/docs/mcp-setup.mdx +332 -0
  134. package/docs/oauth-server.mdx +563 -0
  135. package/docs/partnership.mdx +79 -10
  136. package/docs/quickstart.mdx +1 -1
  137. package/docs/vscode-extension.mdx +74 -0
  138. package/eslint.config.js +1 -0
  139. package/examples/response-examples.md +1 -1
  140. package/frontend/package.json +1 -1
  141. package/frontend/src/App.tsx +8 -3
  142. package/frontend/src/assets/logos/antigravity.svg +1 -0
  143. package/frontend/src/assets/logos/copilot.svg +10 -0
  144. package/frontend/src/assets/logos/deepseek.svg +139 -0
  145. package/frontend/src/assets/logos/kiro.svg +9 -0
  146. package/frontend/src/assets/logos/qoder.svg +4 -0
  147. package/frontend/src/assets/logos/qwen.svg +15 -0
  148. package/frontend/src/components/CodeBlock.tsx +2 -2
  149. package/frontend/src/components/ConnectCTA.tsx +3 -2
  150. package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
  151. package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
  152. package/frontend/src/components/datagrid/index.ts +1 -1
  153. package/frontend/src/components/index.ts +0 -1
  154. package/frontend/src/components/layout/AppHeader.tsx +4 -27
  155. package/frontend/src/components/layout/AppSidebar.tsx +85 -100
  156. package/frontend/src/components/layout/Layout.tsx +34 -32
  157. package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
  158. package/frontend/src/components/radix/Select.tsx +151 -151
  159. package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
  160. package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
  161. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
  162. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
  163. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
  164. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
  165. package/frontend/src/features/ai/components/index.ts +6 -6
  166. package/frontend/src/features/ai/helpers.ts +147 -141
  167. package/frontend/src/features/ai/pages/AIPage.tsx +166 -166
  168. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
  169. package/frontend/src/features/auth/components/UsersDataGrid.tsx +55 -31
  170. package/frontend/src/features/auth/components/index.ts +5 -5
  171. package/frontend/src/features/auth/pages/AuthMethodsPage.tsx +275 -275
  172. package/frontend/src/features/dashboard/pages/DashboardPage.tsx +1 -1
  173. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
  174. package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
  175. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
  176. package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
  177. package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
  178. package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
  179. package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
  180. package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
  181. package/frontend/src/features/database/constants.ts +16 -28
  182. package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
  183. package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
  184. package/frontend/src/features/database/hooks/useTables.ts +5 -7
  185. package/frontend/src/features/database/pages/FunctionsPage.tsx +0 -5
  186. package/frontend/src/features/database/pages/IndexesPage.tsx +0 -5
  187. package/frontend/src/features/database/pages/PoliciesPage.tsx +0 -5
  188. package/frontend/src/features/database/pages/SQLEditorPage.tsx +2 -2
  189. package/frontend/src/features/database/pages/TriggersPage.tsx +0 -5
  190. package/frontend/src/features/database/services/advance.service.ts +1 -15
  191. package/frontend/src/features/database/services/record.service.ts +4 -20
  192. package/frontend/src/features/database/services/table.service.ts +1 -4
  193. package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
  194. package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
  195. package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
  196. package/frontend/src/features/database/templates/notion-clone.ts +8 -8
  197. package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
  198. package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
  199. package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
  200. package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
  201. package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
  202. package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
  203. package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
  204. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
  205. package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
  206. package/frontend/src/features/functions/components/index.ts +5 -5
  207. package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
  208. package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
  209. package/frontend/src/features/functions/pages/SecretsPage.tsx +118 -118
  210. package/frontend/src/features/functions/services/function.service.ts +8 -25
  211. package/frontend/src/features/functions/services/secret.service.ts +23 -41
  212. package/frontend/src/features/login/pages/CloudLoginPage.tsx +125 -118
  213. package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
  214. package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
  215. package/frontend/src/features/logs/components/index.ts +1 -0
  216. package/frontend/src/features/logs/pages/LogsPage.tsx +36 -6
  217. package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
  218. package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
  219. package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
  220. package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
  221. package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
  222. package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
  223. package/frontend/src/features/onboard/components/index.ts +9 -4
  224. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
  225. package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
  226. package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
  227. package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
  228. package/frontend/src/features/onboard/index.ts +17 -13
  229. package/frontend/src/features/settings/pages/SettingsPage.tsx +349 -0
  230. package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
  231. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +21 -8
  232. package/frontend/src/features/visualizer/pages/VisualizerPage.tsx +10 -1
  233. package/frontend/src/index.css +249 -249
  234. package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
  235. package/frontend/src/lib/hooks/useMetadata.ts +45 -1
  236. package/frontend/src/lib/hooks/useModal.tsx +2 -0
  237. package/frontend/src/lib/routing/AppRoutes.tsx +103 -99
  238. package/frontend/src/lib/services/metadata.service.ts +20 -3
  239. package/frontend/src/lib/utils/menuItems.ts +223 -207
  240. package/frontend/src/lib/utils/utils.ts +196 -196
  241. package/functions/server.ts +315 -315
  242. package/functions/worker-template.js +1 -1
  243. package/openapi/ai.yaml +115 -5
  244. package/openapi/auth.yaml +97 -17
  245. package/openapi/logs.yaml +0 -2
  246. package/openapi/metadata.yaml +0 -2
  247. package/openapi/records.yaml +21 -21
  248. package/openapi/tables.yaml +1 -2
  249. package/package.json +1 -1
  250. package/shared-schemas/package.json +1 -1
  251. package/shared-schemas/src/ai-api.schema.ts +251 -143
  252. package/shared-schemas/src/ai.schema.ts +63 -63
  253. package/shared-schemas/src/auth-api.schema.ts +34 -6
  254. package/shared-schemas/src/auth.schema.ts +17 -10
  255. package/shared-schemas/src/cloud-events.schema.ts +26 -0
  256. package/shared-schemas/src/deployments-api.schema.ts +55 -0
  257. package/shared-schemas/src/deployments.schema.ts +30 -0
  258. package/shared-schemas/src/docs.schema.ts +8 -2
  259. package/shared-schemas/src/email-api.schema.ts +30 -30
  260. package/shared-schemas/src/functions-api.schema.ts +13 -4
  261. package/shared-schemas/src/functions.schema.ts +1 -1
  262. package/shared-schemas/src/index.ts +22 -18
  263. package/shared-schemas/src/metadata.schema.ts +30 -4
  264. package/shared-schemas/src/secrets-api.schema.ts +44 -0
  265. package/shared-schemas/src/secrets.schema.ts +15 -0
  266. package/zeabur/README.md +13 -0
  267. package/zeabur/template.yml +20 -51
  268. package/backend/src/types/profile.ts +0 -55
  269. package/frontend/src/components/ProjectInfoModal.tsx +0 -128
@@ -18,7 +18,10 @@ import { usageRouter } from '@/api/routes/usage/index.routes.js';
18
18
  import { aiRouter } from '@/api/routes/ai/index.routes.js';
19
19
  import { realtimeRouter } from '@/api/routes/realtime/index.routes.js';
20
20
  import { emailRouter } from '@/api/routes/email/index.routes.js';
21
+ import { deploymentsRouter } from '@/api/routes/deployments/index.routes.js';
22
+ import { webhooksRouter } from '@/api/routes/webhooks/index.routes.js';
21
23
  import { errorMiddleware } from '@/api/middlewares/error.js';
24
+ import { isCloudEnvironment } from '@/utils/environment.js';
22
25
  import { RealtimeManager } from '@/infra/realtime/realtime.manager.js';
23
26
  import fetch, { HeadersInit } from 'node-fetch';
24
27
  import { DatabaseManager } from '@/infra/database/database.manager.js';
@@ -28,7 +31,6 @@ import { SocketManager } from '@/infra/socket/socket.manager.js';
28
31
  import { seedBackend } from '@/utils/seed.js';
29
32
  import logger from '@/utils/logger.js';
30
33
  import { initSqlParser } from '@/utils/sql-parser.js';
31
- import { isProduction } from './utils/environment.js';
32
34
  import packageJson from '../../package.json';
33
35
 
34
36
  const __filename = fileURLToPath(import.meta.url);
@@ -62,7 +64,7 @@ export async function createApp() {
62
64
  const app = express();
63
65
 
64
66
  // Enable trust proxy setting for rate limiting behind proxies/load balancers
65
- app.set('trust proxy', true);
67
+ app.set('trust proxy', 2);
66
68
 
67
69
  const limiter = rateLimit({
68
70
  windowMs: 15 * 60 * 1000,
@@ -78,9 +80,7 @@ export async function createApp() {
78
80
  })
79
81
  );
80
82
  app.use(cookieParser()); // Parse cookies for refresh token handling
81
- if (isProduction()) {
82
- app.use(limiter);
83
- }
83
+ app.use(limiter);
84
84
  app.use((req: Request, res: Response, next: NextFunction) => {
85
85
  const startTime = Date.now();
86
86
  const originalSend = res.send;
@@ -150,7 +150,11 @@ export async function createApp() {
150
150
  next();
151
151
  });
152
152
 
153
- // Apply JSON middleware
153
+ // Mount webhooks with raw body parser BEFORE JSON middleware
154
+ // This ensures signature verification uses the original bytes
155
+ app.use('/api/webhooks', express.raw({ type: 'application/json' }), webhooksRouter);
156
+
157
+ // Apply JSON middleware for all other routes
154
158
  app.use(express.json({ limit: '100mb' }));
155
159
  app.use(express.urlencoded({ extended: true, limit: '10mb' }));
156
160
 
@@ -180,6 +184,7 @@ export async function createApp() {
180
184
  apiRouter.use('/ai', aiRouter);
181
185
  apiRouter.use('/realtime', realtimeRouter);
182
186
  apiRouter.use('/email', emailRouter);
187
+ apiRouter.use('/deployments', deploymentsRouter);
183
188
 
184
189
  // Mount all API routes under /api prefix
185
190
  app.use('/api', apiRouter);
@@ -230,11 +235,18 @@ export async function createApp() {
230
235
  app.get('/auth*', (_req: Request, res: Response) => {
231
236
  res.sendFile(path.join(authAppPath, 'index.html'));
232
237
  });
233
- } else if (!isProduction()) {
238
+ } else {
234
239
  const authAppUrl = process.env.AUTH_APP_URL || 'http://localhost:7132';
235
240
  logger.info('Auth app not built, proxying to development server', { authAppUrl });
236
241
  }
237
242
 
243
+ // Redirect root to dashboard login (only for non-insforge cloud environments)
244
+ if (!isCloudEnvironment()) {
245
+ app.get('/', (_req: Request, res: Response) => {
246
+ res.redirect('/dashboard/login');
247
+ });
248
+ }
249
+
238
250
  // Serve main frontend if it exists
239
251
  const frontendPath = path.join(__dirname, 'frontend');
240
252
  if (fs.existsSync(frontendPath)) {
@@ -32,7 +32,7 @@ export class AIConfigService {
32
32
  ): Promise<{ id: string }> {
33
33
  try {
34
34
  const result = await this.getPool().query(
35
- `INSERT INTO _ai_configs (input_modality, output_modality, provider, model_id, system_prompt)
35
+ `INSERT INTO ai.configs (input_modality, output_modality, provider, model_id, system_prompt)
36
36
  VALUES ($1, $2, $3, $4, $5)
37
37
  RETURNING id`,
38
38
  [inputModality, outputModality, provider, modelId, systemPrompt || null]
@@ -62,8 +62,8 @@ export class AIConfigService {
62
62
  COALESCE(SUM(u.input_tokens + u.output_tokens), 0)::INTEGER as "totalTokens",
63
63
  COALESCE(SUM(u.image_count), 0)::INTEGER as "totalImageCount",
64
64
  COALESCE(COUNT(u.id), 0)::INTEGER as "totalRequests"
65
- FROM _ai_configs c
66
- LEFT JOIN _ai_usage u ON c.id = u.config_id
65
+ FROM ai.configs c
66
+ LEFT JOIN ai.usage u ON c.id = u.config_id
67
67
  GROUP BY c.id, c.input_modality, c.output_modality, c.provider, c.model_id, c.system_prompt, c.created_at
68
68
  ORDER BY c.created_at DESC`
69
69
  );
@@ -92,7 +92,7 @@ export class AIConfigService {
92
92
  async update(id: string, systemPrompt: string | null): Promise<boolean> {
93
93
  try {
94
94
  const result = await this.getPool().query(
95
- `UPDATE _ai_configs
95
+ `UPDATE ai.configs
96
96
  SET system_prompt = $1, updated_at = NOW()
97
97
  WHERE id = $2`,
98
98
  [systemPrompt, id]
@@ -111,7 +111,7 @@ export class AIConfigService {
111
111
 
112
112
  async delete(id: string): Promise<boolean> {
113
113
  try {
114
- const result = await this.getPool().query('DELETE FROM _ai_configs WHERE id = $1', [id]);
114
+ const result = await this.getPool().query('DELETE FROM ai.configs WHERE id = $1', [id]);
115
115
 
116
116
  const success = (result.rowCount ?? 0) > 0;
117
117
  if (success) {
@@ -128,7 +128,7 @@ export class AIConfigService {
128
128
  try {
129
129
  const result = await this.getPool().query(
130
130
  `SELECT id, input_modality as "inputModality", output_modality as "outputModality", provider, model_id as "modelId", system_prompt as "systemPrompt", created_at, updated_at
131
- FROM _ai_configs
131
+ FROM ai.configs
132
132
  WHERE model_id = $1`,
133
133
  [modelId]
134
134
  );
@@ -1,60 +1,60 @@
1
- import { isCloudEnvironment } from '@/utils/environment.js';
2
- import { OpenRouterProvider } 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 openRouterProvider = OpenRouterProvider.getInstance();
14
- const configured = openRouterProvider.isConfigured();
15
-
16
- if (!configured) {
17
- return [];
18
- }
19
-
20
- // Get API key from OpenRouter provider
21
- const apiKey = await openRouterProvider.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
+ import { isCloudEnvironment } from '@/utils/environment.js';
2
+ import { OpenRouterProvider } 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 openRouterProvider = OpenRouterProvider.getInstance();
14
+ const configured = openRouterProvider.isConfigured();
15
+
16
+ if (!configured) {
17
+ return [];
18
+ }
19
+
20
+ // Get API key from OpenRouter provider
21
+ const apiKey = await openRouterProvider.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
+ }
@@ -31,7 +31,7 @@ export class AIUsageService {
31
31
  async trackUsage(data: AIUsageDataSchema): Promise<{ id: string }> {
32
32
  try {
33
33
  const result = await this.getPool().query(
34
- `INSERT INTO _ai_usage (config_id, input_tokens, output_tokens, image_count, image_resolution)
34
+ `INSERT INTO ai.usage (config_id, input_tokens, output_tokens, image_count, image_resolution)
35
35
  VALUES ($1, $2, $3, $4, $5)
36
36
  RETURNING id`,
37
37
  [
@@ -68,7 +68,7 @@ export class AIUsageService {
68
68
 
69
69
  try {
70
70
  const usageResult = await this.getPool().query(
71
- `INSERT INTO _ai_usage (config_id, input_tokens, output_tokens, model_id)
71
+ `INSERT INTO ai.usage (config_id, input_tokens, output_tokens, model_id)
72
72
  VALUES ($1, $2, $3, $4)
73
73
  RETURNING id`,
74
74
  [configId, inputTokens || null, outputTokens || null, modelId || null]
@@ -100,7 +100,7 @@ export class AIUsageService {
100
100
  ): Promise<{ id: string }> {
101
101
  try {
102
102
  const usageResult = await this.getPool().query(
103
- `INSERT INTO _ai_usage (config_id, image_count, image_resolution, input_tokens, output_tokens, model_id)
103
+ `INSERT INTO ai.usage (config_id, image_count, image_resolution, input_tokens, output_tokens, model_id)
104
104
  VALUES ($1, $2, $3, $4, $5, $6)
105
105
  RETURNING id`,
106
106
  [
@@ -140,7 +140,7 @@ export class AIUsageService {
140
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
- FROM _ai_usage
143
+ FROM ai.usage
144
144
  WHERE config_id = $1
145
145
  `;
146
146
 
@@ -180,7 +180,7 @@ export class AIUsageService {
180
180
  COALESCE(SUM(COALESCE(input_tokens, 0) + COALESCE(output_tokens, 0)), 0) as "totalTokens",
181
181
  COALESCE(SUM(image_count), 0) as "totalImageCount",
182
182
  COUNT(*) as "totalRequests"
183
- FROM _ai_usage
183
+ FROM ai.usage
184
184
  WHERE 1=1
185
185
  `;
186
186
 
@@ -237,8 +237,8 @@ export class AIUsageService {
237
237
  c.provider,
238
238
  c.input_modality as "inputModality",
239
239
  c.output_modality as "outputModality"
240
- FROM _ai_usage u
241
- LEFT JOIN _ai_configs c ON u.config_id = c.id
240
+ FROM ai.usage u
241
+ LEFT JOIN ai.configs c ON u.config_id = c.id
242
242
  WHERE 1=1
243
243
  `;
244
244