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.
- package/CHANGELOG.md +2 -0
- package/auth/package.json +5 -3
- package/auth/src/lib/broadcastService.ts +115 -117
- package/auth/src/lib/insforge.ts +8 -0
- package/auth/src/main.tsx +2 -4
- package/auth/src/pages/SignInPage.tsx +60 -60
- package/auth/src/pages/SignUpPage.tsx +60 -60
- package/auth/src/pages/VerifyEmailPage.tsx +18 -0
- package/auth/tsconfig.json +2 -1
- package/backend/package.json +10 -6
- package/backend/src/api/middlewares/rate-limiters.ts +127 -127
- package/backend/src/api/routes/ai/index.routes.ts +475 -468
- package/backend/src/api/routes/auth/index.routes.ts +85 -32
- package/backend/src/api/routes/auth/oauth.routes.ts +11 -6
- package/backend/src/api/routes/database/index.routes.ts +2 -0
- package/backend/src/api/routes/database/records.routes.ts +39 -175
- package/backend/src/api/routes/database/rpc.routes.ts +69 -0
- package/backend/src/api/routes/deployments/index.routes.ts +192 -0
- package/backend/src/api/routes/docs/index.routes.ts +3 -2
- package/backend/src/api/routes/email/index.routes.ts +35 -35
- package/backend/src/api/routes/functions/index.routes.ts +3 -3
- package/backend/src/api/routes/metadata/index.routes.ts +26 -0
- package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
- package/backend/src/infra/database/database.manager.ts +0 -10
- package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
- package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
- package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
- package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
- package/backend/src/infra/security/token.manager.ts +1 -4
- package/backend/src/providers/ai/openrouter.provider.ts +12 -3
- package/backend/src/providers/database/base.provider.ts +39 -0
- package/backend/src/providers/database/cloud.provider.ts +159 -0
- package/backend/src/providers/deployments/vercel.provider.ts +516 -0
- package/backend/src/server.ts +19 -7
- package/backend/src/services/ai/ai-config.service.ts +6 -6
- package/backend/src/services/ai/ai-model.service.ts +60 -60
- package/backend/src/services/ai/ai-usage.service.ts +7 -7
- package/backend/src/services/ai/chat-completion.service.ts +415 -220
- package/backend/src/services/ai/helpers.ts +64 -64
- package/backend/src/services/ai/index.ts +13 -13
- package/backend/src/services/auth/auth-config.service.ts +4 -4
- package/backend/src/services/auth/auth-otp.service.ts +6 -6
- package/backend/src/services/auth/auth.service.ts +134 -74
- package/backend/src/services/auth/index.ts +4 -4
- package/backend/src/services/auth/oauth-config.service.ts +12 -12
- package/backend/src/services/database/database-advance.service.ts +19 -55
- package/backend/src/services/database/database-table.service.ts +38 -85
- package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
- package/backend/src/services/deployments/deployment.service.ts +693 -0
- package/backend/src/services/functions/function.service.ts +61 -41
- package/backend/src/services/logs/audit.service.ts +10 -10
- package/backend/src/services/secrets/secret.service.ts +101 -27
- package/backend/src/services/storage/storage.service.ts +30 -30
- package/backend/src/services/usage/usage.service.ts +6 -6
- package/backend/src/types/ai.ts +8 -0
- package/backend/src/types/auth.ts +5 -1
- package/backend/src/types/database.ts +2 -0
- package/backend/src/types/deployments.ts +33 -0
- package/backend/src/types/storage.ts +1 -1
- package/backend/src/types/webhooks.ts +45 -0
- package/backend/src/utils/cookies.ts +34 -35
- package/backend/src/utils/environment.ts +0 -14
- package/backend/src/utils/s3-config-loader.ts +64 -64
- package/backend/src/utils/seed.ts +334 -301
- package/backend/src/utils/sql-parser.ts +126 -0
- package/backend/src/utils/utils.ts +114 -114
- package/backend/src/utils/validations.ts +10 -10
- package/backend/tests/local/test-rpc.sh +141 -0
- package/backend/tests/local/test-secrets.sh +1 -1
- package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
- package/backend/tests/manual/test-rawsql-modes.sh +24 -24
- package/backend/tests/unit/database-advance.test.ts +326 -0
- package/backend/tests/unit/helpers.test.ts +2 -2
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +13 -10
- package/docker-compose.prod.yml +1 -1
- package/docker-compose.yml +1 -1
- package/docs/agent-docs/deployment.md +79 -0
- package/docs/changelog.mdx +165 -72
- package/docs/core-concepts/ai/architecture.mdx +1 -23
- package/docs/core-concepts/ai/sdk.mdx +26 -1
- package/docs/core-concepts/authentication/architecture.mdx +6 -8
- package/docs/core-concepts/authentication/sdk.mdx +387 -91
- package/docs/core-concepts/authentication/ui-components/customization.mdx +460 -256
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +50 -24
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +18 -19
- package/docs/core-concepts/authentication/ui-components/react.mdx +26 -19
- package/docs/core-concepts/database/architecture.mdx +58 -21
- package/docs/core-concepts/database/pgvector.mdx +138 -0
- package/docs/core-concepts/database/sdk.mdx +17 -17
- package/docs/core-concepts/deployments/architecture.mdx +152 -0
- package/docs/core-concepts/email/architecture.mdx +4 -2
- package/docs/core-concepts/functions/architecture.mdx +1 -1
- package/docs/core-concepts/functions/sdk.mdx +0 -1
- package/docs/core-concepts/realtime/architecture.mdx +1 -1
- package/docs/core-concepts/storage/architecture.mdx +1 -1
- package/docs/core-concepts/storage/sdk.mdx +25 -25
- package/docs/docs.json +14 -6
- package/docs/favicon.png +0 -0
- package/docs/favicon.svg +3 -18
- package/docs/images/changelog/dec-2025/apple-oauth.mp4 +0 -0
- package/docs/images/changelog/dec-2025/moreModels.png +0 -0
- package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
- package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
- package/docs/images/changelog/dec-2025/realtime2.png +0 -0
- package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
- package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
- package/docs/images/mcp-setup/claude-code-connect.png +0 -0
- package/docs/images/mcp-setup/cline-1.png +0 -0
- package/docs/images/mcp-setup/cline-2.png +0 -0
- package/docs/images/mcp-setup/cline-3.png +0 -0
- package/docs/images/mcp-setup/connect-project.png +0 -0
- package/docs/images/mcp-setup/copilot-1.png +0 -0
- package/docs/images/mcp-setup/copilot-2.png +0 -0
- package/docs/images/mcp-setup/copilot-3.png +0 -0
- package/docs/images/mcp-setup/mcp-json-1.png +0 -0
- package/docs/images/mcp-setup/mcp-json-2.png +0 -0
- package/docs/images/mcp-setup/qoder-1.png +0 -0
- package/docs/images/mcp-setup/qoder-2.png +0 -0
- package/docs/images/mcp-setup/roocode-1.png +0 -0
- package/docs/images/mcp-setup/roocode-2.png +0 -0
- package/docs/images/mcp-setup/trae-1.png +0 -0
- package/docs/images/mcp-setup/trae-2.png +0 -0
- package/docs/images/mcp-setup/trae-3.png +0 -0
- package/docs/images/mcp-setup/trae-4.png +0 -0
- package/docs/images/mcp-setup/trae-5.png +0 -0
- package/docs/images/mcp-setup/windsurf-1.png +0 -0
- package/docs/images/mcp-setup/windsurf-2.png +0 -0
- package/docs/insforge-instructions-sdk.md +7 -3
- package/docs/introduction.mdx +9 -8
- package/docs/mcp-setup.mdx +332 -0
- package/docs/oauth-server.mdx +563 -0
- package/docs/partnership.mdx +79 -10
- package/docs/quickstart.mdx +1 -1
- package/docs/vscode-extension.mdx +74 -0
- package/eslint.config.js +1 -0
- package/examples/response-examples.md +1 -1
- package/frontend/package.json +1 -1
- package/frontend/src/App.tsx +8 -3
- package/frontend/src/assets/logos/antigravity.svg +1 -0
- package/frontend/src/assets/logos/copilot.svg +10 -0
- package/frontend/src/assets/logos/deepseek.svg +139 -0
- package/frontend/src/assets/logos/kiro.svg +9 -0
- package/frontend/src/assets/logos/qoder.svg +4 -0
- package/frontend/src/assets/logos/qwen.svg +15 -0
- package/frontend/src/components/CodeBlock.tsx +2 -2
- package/frontend/src/components/ConnectCTA.tsx +3 -2
- package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
- package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
- package/frontend/src/components/datagrid/index.ts +1 -1
- package/frontend/src/components/index.ts +0 -1
- package/frontend/src/components/layout/AppHeader.tsx +4 -27
- package/frontend/src/components/layout/AppSidebar.tsx +85 -100
- package/frontend/src/components/layout/Layout.tsx +34 -32
- package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
- package/frontend/src/components/radix/Select.tsx +151 -151
- package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
- package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
- package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
- package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
- package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
- package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
- package/frontend/src/features/ai/components/index.ts +6 -6
- package/frontend/src/features/ai/helpers.ts +147 -141
- package/frontend/src/features/ai/pages/AIPage.tsx +166 -166
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +55 -31
- package/frontend/src/features/auth/components/index.ts +5 -5
- package/frontend/src/features/auth/pages/AuthMethodsPage.tsx +275 -275
- package/frontend/src/features/dashboard/pages/DashboardPage.tsx +1 -1
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
- package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
- package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
- package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
- package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
- package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
- package/frontend/src/features/database/constants.ts +16 -28
- package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
- package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
- package/frontend/src/features/database/hooks/useTables.ts +5 -7
- package/frontend/src/features/database/pages/FunctionsPage.tsx +0 -5
- package/frontend/src/features/database/pages/IndexesPage.tsx +0 -5
- package/frontend/src/features/database/pages/PoliciesPage.tsx +0 -5
- package/frontend/src/features/database/pages/SQLEditorPage.tsx +2 -2
- package/frontend/src/features/database/pages/TriggersPage.tsx +0 -5
- package/frontend/src/features/database/services/advance.service.ts +1 -15
- package/frontend/src/features/database/services/record.service.ts +4 -20
- package/frontend/src/features/database/services/table.service.ts +1 -4
- package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
- package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
- package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
- package/frontend/src/features/database/templates/notion-clone.ts +8 -8
- package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
- package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
- package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
- package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
- package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
- package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
- package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
- package/frontend/src/features/functions/components/index.ts +5 -5
- package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
- package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
- package/frontend/src/features/functions/pages/SecretsPage.tsx +118 -118
- package/frontend/src/features/functions/services/function.service.ts +8 -25
- package/frontend/src/features/functions/services/secret.service.ts +23 -41
- package/frontend/src/features/login/pages/CloudLoginPage.tsx +125 -118
- package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
- package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
- package/frontend/src/features/logs/components/index.ts +1 -0
- package/frontend/src/features/logs/pages/LogsPage.tsx +36 -6
- package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
- package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
- package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
- package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
- package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
- package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
- package/frontend/src/features/onboard/components/index.ts +9 -4
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
- package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
- package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
- package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
- package/frontend/src/features/onboard/index.ts +17 -13
- package/frontend/src/features/settings/pages/SettingsPage.tsx +349 -0
- package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +21 -8
- package/frontend/src/features/visualizer/pages/VisualizerPage.tsx +10 -1
- package/frontend/src/index.css +249 -249
- package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
- package/frontend/src/lib/hooks/useMetadata.ts +45 -1
- package/frontend/src/lib/hooks/useModal.tsx +2 -0
- package/frontend/src/lib/routing/AppRoutes.tsx +103 -99
- package/frontend/src/lib/services/metadata.service.ts +20 -3
- package/frontend/src/lib/utils/menuItems.ts +223 -207
- package/frontend/src/lib/utils/utils.ts +196 -196
- package/functions/server.ts +315 -315
- package/functions/worker-template.js +1 -1
- package/openapi/ai.yaml +115 -5
- package/openapi/auth.yaml +97 -17
- package/openapi/logs.yaml +0 -2
- package/openapi/metadata.yaml +0 -2
- package/openapi/records.yaml +21 -21
- package/openapi/tables.yaml +1 -2
- package/package.json +1 -1
- package/shared-schemas/package.json +1 -1
- package/shared-schemas/src/ai-api.schema.ts +251 -143
- package/shared-schemas/src/ai.schema.ts +63 -63
- package/shared-schemas/src/auth-api.schema.ts +34 -6
- package/shared-schemas/src/auth.schema.ts +17 -10
- package/shared-schemas/src/cloud-events.schema.ts +26 -0
- package/shared-schemas/src/deployments-api.schema.ts +55 -0
- package/shared-schemas/src/deployments.schema.ts +30 -0
- package/shared-schemas/src/docs.schema.ts +8 -2
- package/shared-schemas/src/email-api.schema.ts +30 -30
- package/shared-schemas/src/functions-api.schema.ts +13 -4
- package/shared-schemas/src/functions.schema.ts +1 -1
- package/shared-schemas/src/index.ts +22 -18
- package/shared-schemas/src/metadata.schema.ts +30 -4
- package/shared-schemas/src/secrets-api.schema.ts +44 -0
- package/shared-schemas/src/secrets.schema.ts +15 -0
- package/zeabur/README.md +13 -0
- package/zeabur/template.yml +20 -51
- package/backend/src/types/profile.ts +0 -55
- package/frontend/src/components/ProjectInfoModal.tsx +0 -128
package/backend/src/server.ts
CHANGED
|
@@ -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',
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
|
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
|
|
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
|
|
66
|
-
LEFT JOIN
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
241
|
-
LEFT JOIN
|
|
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
|
|