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.
- package/.claude-plugin/marketplace.json +20 -0
- package/.cursor/rules/cursor-rules.mdc +94 -0
- package/.dockerignore +3 -0
- package/.env.example +33 -4
- package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
- package/.github/ISSUE_TEMPLATE/config.yml +2 -2
- package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
- package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
- package/.github/workflows/build-image.yml +2 -1
- package/.github/workflows/e2e.yml +63 -0
- package/CHANGELOG.md +41 -0
- package/CLAUDE_PLUGIN.md +104 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +1 -1
- package/Dockerfile +4 -1
- package/README.md +66 -18
- package/assets/mcpInstallv2.png +0 -0
- package/assets/sampleResponse.png +0 -0
- package/auth/index.html +13 -0
- package/auth/package.json +28 -0
- package/auth/public/favicon.ico +0 -0
- package/auth/src/App.tsx +33 -0
- package/auth/src/components/ErrorCard.tsx +37 -0
- package/auth/src/components/Layout.tsx +13 -0
- package/auth/src/index.css +19 -0
- package/auth/src/lib/broadcastService.ts +115 -0
- package/auth/src/lib/utils.ts +11 -0
- package/auth/src/main.tsx +22 -0
- package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
- package/auth/src/pages/ResetPasswordPage.tsx +11 -0
- package/auth/src/pages/SignInPage.tsx +57 -0
- package/auth/src/pages/SignUpPage.tsx +57 -0
- package/auth/src/pages/VerifyEmailPage.tsx +20 -0
- package/auth/src/vite-env.d.ts +10 -0
- package/auth/tsconfig.json +32 -0
- package/auth/tsconfig.node.json +11 -0
- package/auth/vite.config.ts +25 -0
- package/backend/package.json +9 -9
- package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
- package/backend/src/api/middlewares/rate-limiters.ts +127 -0
- package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
- package/backend/src/api/routes/auth/index.routes.ts +570 -0
- package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
- package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
- package/backend/src/api/routes/database/index.routes.ts +13 -0
- package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
- package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
- package/backend/src/api/routes/docs/index.routes.ts +76 -0
- package/backend/src/api/routes/functions/index.routes.ts +188 -0
- package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
- package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
- package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
- package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
- package/backend/src/api/routes/usage/index.routes.ts +89 -0
- package/backend/src/infra/config/app.config.ts +51 -0
- package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
- package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
- package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
- package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
- package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
- package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
- package/backend/src/infra/security/token.manager.ts +125 -0
- package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
- package/backend/src/providers/ai/openrouter.provider.ts +377 -0
- package/backend/src/providers/email/base.provider.ts +41 -0
- package/backend/src/providers/email/cloud.provider.ts +187 -0
- package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
- package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
- package/backend/src/providers/logs/local.provider.ts +185 -0
- package/backend/src/providers/oauth/base.provider.ts +29 -0
- package/backend/src/providers/oauth/discord.provider.ts +195 -0
- package/backend/src/providers/oauth/facebook.provider.ts +194 -0
- package/backend/src/providers/oauth/github.provider.ts +208 -0
- package/backend/src/providers/oauth/google.provider.ts +249 -0
- package/backend/src/providers/oauth/index.ts +7 -0
- package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
- package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
- package/backend/src/providers/oauth/x.provider.ts +202 -0
- package/backend/src/providers/storage/base.provider.ts +29 -0
- package/backend/src/providers/storage/local.provider.ts +103 -0
- package/backend/src/providers/storage/s3.provider.ts +313 -0
- package/backend/src/server.ts +70 -74
- package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
- package/backend/src/services/ai/ai-model.service.ts +60 -0
- package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
- package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
- package/backend/src/services/ai/helpers.ts +64 -0
- package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
- package/backend/src/services/ai/index.ts +13 -0
- package/backend/src/services/auth/auth-config.service.ts +250 -0
- package/backend/src/services/auth/auth-otp.service.ts +424 -0
- package/backend/src/services/auth/auth.service.ts +1136 -0
- package/backend/src/services/auth/index.ts +4 -0
- package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
- package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
- package/backend/src/services/database/database-table.service.ts +811 -0
- package/backend/src/services/email/email.service.ts +75 -0
- package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
- package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
- package/backend/src/services/logs/log.service.ts +73 -0
- package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
- package/backend/src/services/storage/storage.service.ts +617 -0
- package/backend/src/services/usage/usage.service.ts +149 -0
- package/backend/src/types/auth.ts +66 -2
- package/backend/src/types/email.ts +8 -0
- package/backend/src/types/error-constants.ts +4 -0
- package/backend/src/types/logs.ts +0 -29
- package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
- package/backend/src/utils/environment.ts +9 -3
- package/backend/src/utils/logger.ts +20 -2
- package/backend/src/utils/seed.ts +150 -57
- package/backend/src/utils/sql-parser.ts +1 -1
- package/backend/src/utils/utils.ts +114 -0
- package/backend/src/utils/validations.ts +40 -4
- package/backend/tests/local/test-ai-config.sh +129 -0
- package/backend/tests/local/test-ai-usage.sh +80 -0
- package/backend/tests/local/test-auth-router.sh +1 -1
- package/backend/tests/local/test-e2e.sh +1 -1
- package/backend/tests/local/test-functions.sh +123 -0
- package/backend/tests/local/test-logs.sh +132 -0
- package/backend/tests/local/test-public-bucket.sh +3 -3
- package/backend/tests/local/test-secrets.sh +14 -12
- package/backend/tests/local/test-traditional-rest.sh +2 -2
- package/backend/tests/manual/test-rawsql-modes.sh +244 -0
- package/backend/tests/test-config.sh +37 -1
- package/backend/tests/unit/cloud-token.test.ts +48 -0
- package/backend/tests/unit/constant.test.ts +8 -0
- package/backend/tests/unit/email.test.ts +372 -0
- package/backend/tests/unit/environment.test.ts +59 -0
- package/backend/tests/unit/helpers.test.ts +63 -0
- package/backend/tests/unit/logger.test.ts +22 -0
- package/backend/tests/unit/rate-limit.test.ts +154 -0
- package/backend/tests/unit/response.test.ts +58 -0
- package/backend/tests/unit/sql-parser.test.ts +74 -0
- package/backend/tests/unit/uuid.test.ts +21 -0
- package/backend/tests/unit/validations.test.ts +80 -0
- package/backend/tsconfig.json +1 -1
- package/backend/vitest.config.ts +11 -0
- package/claude-plugin/.claude-plugin/plugin.json +24 -0
- package/claude-plugin/README.md +133 -0
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
- package/docker-compose.prod.yml +60 -4
- package/docker-compose.yml +65 -4
- package/docker-init/db/db-init.sql +6 -34
- package/docker-init/logs/vector.yml +236 -0
- package/docs/README.md +44 -0
- package/docs/changelog.mdx +67 -0
- package/docs/core-concepts/ai/architecture.mdx +373 -0
- package/docs/core-concepts/ai/sdk.mdx +213 -0
- package/docs/core-concepts/authentication/architecture.mdx +278 -0
- package/docs/core-concepts/authentication/sdk.mdx +414 -0
- package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
- package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
- package/docs/core-concepts/database/architecture.mdx +256 -0
- package/docs/core-concepts/database/sdk.mdx +382 -0
- package/docs/core-concepts/functions/architecture.mdx +105 -0
- package/docs/core-concepts/functions/sdk.mdx +184 -0
- package/docs/core-concepts/storage/architecture.mdx +243 -0
- package/docs/core-concepts/storage/sdk.mdx +253 -0
- package/docs/deployment/README.md +94 -0
- package/docs/deployment/deploy-to-aws-ec2.md +565 -0
- package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
- package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
- package/docs/deployment/deploy-to-render.md +441 -0
- package/docs/docs.json +210 -0
- package/docs/examples/framework-guides/nextjs.mdx +131 -0
- package/docs/examples/framework-guides/nuxt.mdx +165 -0
- package/docs/examples/framework-guides/react.mdx +165 -0
- package/docs/examples/framework-guides/svelte.mdx +153 -0
- package/docs/examples/framework-guides/vue.mdx +159 -0
- package/docs/examples/overview.mdx +67 -0
- package/docs/favicon.svg +19 -0
- package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
- package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
- package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
- package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
- package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
- package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
- package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
- package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
- package/docs/images/checks-passed.png +0 -0
- package/docs/images/dashboard-connect-expanded.png +0 -0
- package/docs/images/dashboard-connect.png +0 -0
- package/docs/images/hero-dark.png +0 -0
- package/docs/images/hero-light.png +0 -0
- package/docs/images/icons/ai.svg +4 -0
- package/docs/images/icons/auth.svg +1 -0
- package/docs/images/icons/database.svg +1 -0
- package/docs/images/icons/function.svg +1 -0
- package/docs/images/icons/storage.svg +1 -0
- package/docs/images/logos/nextjs.svg +4 -0
- package/docs/images/logos/nuxt.svg +4 -0
- package/docs/images/logos/react.svg +5 -0
- package/docs/images/logos/svelte.svg +4 -0
- package/docs/images/logos/vue.svg +5 -0
- package/docs/images/mcp-install.png +0 -0
- package/docs/images/onboarding-mcp.png +0 -0
- package/docs/insforge-instructions-sdk.md +55 -374
- package/docs/introduction.mdx +45 -0
- package/docs/logo/dark.svg +22 -0
- package/docs/logo/light.svg +20 -0
- package/docs/partnership.mdx +647 -0
- package/docs/quickstart.mdx +83 -0
- package/docs/showcase/2048-arena.png +0 -0
- package/docs/showcase/framegen-cloud.png +0 -0
- package/docs/showcase/line-connect-race.png +0 -0
- package/docs/showcase/moment-vibe.png +0 -0
- package/docs/showcase/national-flags.png +0 -0
- package/docs/showcase/pokemon-vibe.png +0 -0
- package/docs/showcase/pure-browse-buy.png +0 -0
- package/docs/showcase.mdx +52 -0
- package/docs/snippets/sdk-installation.mdx +22 -0
- package/docs/snippets/service-icons.mdx +27 -0
- package/eslint.config.js +10 -3
- package/frontend/package.json +10 -4
- package/frontend/src/App.tsx +13 -82
- package/frontend/src/assets/icons/connected.svg +3 -0
- package/frontend/src/assets/icons/loader.svg +9 -0
- package/frontend/src/assets/logos/apple.svg +4 -0
- package/frontend/src/assets/logos/discord.svg +1 -1
- package/frontend/src/assets/logos/facebook.svg +3 -0
- package/frontend/src/assets/logos/instagram.svg +2 -0
- package/frontend/src/assets/logos/linkedin.svg +3 -0
- package/frontend/src/assets/logos/microsoft.svg +1 -0
- package/frontend/src/assets/logos/spotify.svg +17 -0
- package/frontend/src/assets/logos/tiktok.svg +6 -0
- package/frontend/src/assets/logos/x.svg +3 -0
- package/frontend/src/components/Checkbox.tsx +27 -29
- package/frontend/src/components/CodeBlock.tsx +55 -2
- package/frontend/src/components/CodeEditor.tsx +92 -0
- package/frontend/src/components/ConfirmDialog.tsx +1 -1
- package/frontend/src/components/ConnectCTA.tsx +38 -0
- package/frontend/src/components/CopyButton.tsx +52 -15
- package/frontend/src/components/ErrorState.tsx +1 -2
- package/frontend/src/components/FeatureSidebar.tsx +6 -6
- package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
- package/frontend/src/components/JsonHighlight.tsx +21 -9
- package/frontend/src/components/ProjectInfoModal.tsx +128 -0
- package/frontend/src/components/PromptDialog.tsx +1 -4
- package/frontend/src/components/SearchInput.tsx +1 -2
- package/frontend/src/components/Stepper.tsx +53 -0
- package/frontend/src/components/ThemeToggle.tsx +3 -3
- package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
- package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
- package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
- package/frontend/src/components/datagrid/index.ts +23 -0
- package/frontend/src/components/index.ts +23 -30
- package/frontend/src/components/layout/AppHeader.tsx +133 -92
- package/frontend/src/components/layout/AppSidebar.tsx +80 -170
- package/frontend/src/components/layout/Layout.tsx +12 -23
- package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
- package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
- package/frontend/src/components/layout/index.ts +5 -0
- package/frontend/src/components/radix/Tooltip.tsx +24 -13
- package/frontend/src/components/radix/index.ts +22 -0
- package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
- package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
- package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
- package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
- package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
- package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
- package/frontend/src/features/ai/components/index.ts +6 -0
- package/frontend/src/features/ai/helpers.ts +57 -71
- package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
- package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
- package/frontend/src/features/ai/page/AIPage.tsx +67 -79
- package/frontend/src/features/ai/services/ai.service.ts +5 -5
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
- package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
- package/frontend/src/features/auth/components/index.ts +5 -0
- package/frontend/src/features/auth/helpers.tsx +200 -0
- package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
- package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
- package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
- package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
- package/frontend/src/features/auth/index.ts +3 -2
- package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
- package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
- package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
- package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
- package/frontend/src/features/auth/services/config.service.ts +19 -0
- package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
- package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
- package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
- package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
- package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
- package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
- package/frontend/src/features/dashboard/components/index.ts +4 -0
- package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
- package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
- package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
- package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
- package/frontend/src/features/dashboard/prompts/index.ts +31 -0
- package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
- package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
- package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
- package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
- package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
- package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
- package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
- package/frontend/src/features/database/components/TableForm.tsx +28 -15
- package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
- package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
- package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
- package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
- package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
- package/frontend/src/features/database/components/index.ts +19 -0
- package/frontend/src/features/database/constants.ts +28 -2
- package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
- package/frontend/src/features/database/helpers.ts +2 -2
- package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
- package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
- package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
- package/frontend/src/features/database/hooks/useRecords.ts +139 -0
- package/frontend/src/features/database/hooks/useTables.ts +131 -0
- package/frontend/src/features/database/index.ts +6 -1
- package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
- package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
- package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
- package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
- package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
- package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
- package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
- package/frontend/src/features/database/services/advance.service.ts +66 -0
- package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
- package/frontend/src/features/database/services/table.service.ts +64 -0
- package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
- package/frontend/src/features/database/templates/crm-system.ts +528 -0
- package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
- package/frontend/src/features/database/templates/index.ts +34 -0
- package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
- package/frontend/src/features/database/templates/notion-clone.ts +483 -0
- package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
- package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
- package/frontend/src/features/functions/components/index.ts +5 -0
- package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
- package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
- package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
- package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
- package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
- package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
- package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
- package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
- package/frontend/src/features/login/page/LoginPage.tsx +16 -23
- package/frontend/src/features/login/services/partnership.service.ts +65 -0
- package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
- package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
- package/frontend/src/features/logs/components/index.ts +2 -0
- package/frontend/src/features/logs/helpers.ts +24 -0
- package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
- package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
- package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
- package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
- package/frontend/src/features/logs/index.ts +8 -2
- package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
- package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
- package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
- package/frontend/src/features/logs/services/audit.service.ts +63 -0
- package/frontend/src/features/logs/services/log.service.ts +15 -110
- package/frontend/src/features/logs/services/usage.service.ts +31 -0
- package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
- package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
- package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
- package/frontend/src/features/onboard/components/index.ts +4 -0
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
- package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
- package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
- package/frontend/src/features/onboard/index.ts +13 -3
- package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
- package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
- package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
- package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
- package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
- package/frontend/src/features/storage/components/index.ts +12 -0
- package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
- package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
- package/frontend/src/features/storage/services/storage.service.ts +22 -1
- package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
- package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
- package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
- package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
- package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
- package/frontend/src/index.css +1 -0
- package/frontend/src/lib/analytics/posthog.tsx +27 -0
- package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
- package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
- package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
- package/frontend/src/lib/hooks/useToast.tsx +6 -2
- package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
- package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
- package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
- package/frontend/src/lib/utils/menuItems.ts +183 -0
- package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
- package/frontend/src/lib/utils/utils.ts +19 -1
- package/frontend/src/vite-env.d.ts +1 -0
- package/frontend/vite.config.ts +5 -3
- package/functions/server.ts +28 -3
- package/functions/worker-template.js +15 -4
- package/i18n/README.ar.md +130 -0
- package/i18n/README.de.md +130 -0
- package/i18n/README.es.md +154 -0
- package/i18n/README.fr.md +134 -0
- package/i18n/README.hi.md +129 -0
- package/i18n/README.ja.md +174 -0
- package/i18n/README.ko.md +137 -0
- package/i18n/README.pt-BR.md +131 -0
- package/i18n/README.ru.md +129 -0
- package/i18n/README.zh-CN.md +133 -0
- package/openapi/ai.yaml +31 -4
- package/openapi/auth.yaml +827 -146
- package/package.json +16 -7
- package/shared-schemas/package.json +1 -1
- package/shared-schemas/src/ai-api.schema.ts +34 -58
- package/shared-schemas/src/ai.schema.ts +5 -0
- package/shared-schemas/src/auth-api.schema.ts +154 -8
- package/shared-schemas/src/auth.schema.ts +42 -6
- package/shared-schemas/src/cloud-events.schema.ts +57 -0
- package/shared-schemas/src/database-api.schema.ts +3 -3
- package/shared-schemas/src/database.schema.ts +1 -1
- package/shared-schemas/src/index.ts +1 -0
- package/shared-schemas/src/logs-api.schema.ts +7 -1
- package/shared-schemas/src/logs.schema.ts +26 -0
- package/shared-schemas/src/metadata.schema.ts +9 -4
- package/test-gemini.sh +35 -0
- package/test-usage-admin.sh +57 -0
- package/test-usage.sh +50 -0
- package/zeabur/README.md +13 -0
- package/zeabur/template.yml +1032 -0
- package/.github/workflows/deploy-aws.yml +0 -130
- package/backend/src/api/routes/agent.ts +0 -29
- package/backend/src/api/routes/auth.oauth.ts +0 -482
- package/backend/src/api/routes/auth.ts +0 -386
- package/backend/src/api/routes/docs.ts +0 -66
- package/backend/src/api/routes/functions.ts +0 -183
- package/backend/src/api/routes/openapi.ts +0 -82
- package/backend/src/api/routes/usage.ts +0 -96
- package/backend/src/core/ai/client.ts +0 -242
- package/backend/src/core/ai/model.ts +0 -117
- package/backend/src/core/auth/auth.ts +0 -781
- package/backend/src/core/database/table.ts +0 -772
- package/backend/src/core/documentation/agent.ts +0 -689
- package/backend/src/core/documentation/openapi.ts +0 -856
- package/backend/src/core/logs/analytics.ts +0 -76
- package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
- package/backend/src/core/storage/storage.ts +0 -923
- package/backend/src/utils/cloud-token.ts +0 -39
- package/backend/src/utils/helpers.ts +0 -49
- package/backend/src/utils/uuid.ts +0 -9
- package/backend/tests/manual/test-better-auth.sh +0 -303
- package/docker-init/db/logs.sql +0 -9
- package/frontend/README.md +0 -112
- package/frontend/src/components/datagrid/index.tsx +0 -20
- package/frontend/src/components/layout/CloudLayout.tsx +0 -95
- package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
- package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
- package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
- package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
- package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
- package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
- package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
- package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
- package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
- package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
- package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
- package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
- package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
- package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
- package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
- package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
- package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
- package/frontend/src/features/metadata/index.ts +0 -0
- package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
- package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
- package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
- package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
- package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
- package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
- package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
- package/frontend/src/features/onboard/types.ts +0 -8
- package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
- package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
- /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
- /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
- /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 '@/
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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 '
|
|
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
|
|
14
|
-
private
|
|
15
|
-
private
|
|
16
|
-
private
|
|
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
|
|
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
|
-
|
|
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
|
|
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 '
|
|
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
|
|
15
|
-
private static aiUsageService =
|
|
16
|
-
private static aiConfigService =
|
|
17
|
-
private static
|
|
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
|
|
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
|
|
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
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
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
|
|
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';
|