Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
1 line
70 KiB
JSON
1 line
70 KiB
JSON
{"repo": "actus7/modelhub", "files": {"server/providers/xiaomitoken.ts": {"426bccb40dd31e659550f629c1ff7f983ad0f8fc": {"t": 1785595149.943059, "n": 2185, "h": "dfb0236e02434e8c", "c": "import { createProviderApp } from '../lib/provider-core'\nimport { chatViaOpenAiCompatible, createOpenAiFetchModels, testViaOpenAiModels } from '../lib/openai-compatible'\n\nconst XIAOMI_TOKEN_PLAN_API_KEY = 'XIAOMI_TOKEN_PLAN_API_KEY'\nconst XIAOMI_TOKEN_PLAN_BASE_URL = process.env.XIAOMI_TOKEN_PLAN_BASE_URL || 'https://api.xiaomimimo.com'\nconst XIAOMI_TOKEN_PLAN_CHAT_URL = process.env.XIAOMI_TOKEN_PLAN_CHAT_URL || `${XIAOMI_TOKEN_PLAN_BASE_URL}/v1/chat/completions`\nconst XIAOMI_TOKEN_PLAN_MODELS_URL = process.env.XIAOMI_TOKEN_PLAN_MODELS_URL || `${XIAOMI_TOKEN_PLAN_BASE_URL}/v1/models`\n\nexport const models = [\n { capabilities: { documents: true, images: false, tools: true }, id: 'mimo-v2.5-pro', name: 'MiMo V2.5 Pro (Token Plan)' },\n { capabilities: { documents: true, images: false, tools: true }, id: 'mimo-v2-pro', name: 'MiMo V2 Pro (Token Plan)' },\n { capabilities: { documents: true, images: false, tools: true, fast: true }, id: 'mimo-v2.5', name: 'MiMo V2.5 (Token Plan)' },\n { capabilities: { documents: true, images: true, tools: true }, id: 'mimo-v2-omni', name: 'MiMo V2 Omni (Token Plan)' },\n { capabilities: { documents: true, images: false, tools: true, fast: true }, id: 'mimo-v2-flash', name: 'MiMo V2 Flash (Token Plan)' },\n]\n\n/** Exportado para o registry usar a mesma config (URLs/env) deste arquivo. */\nexport const fetchModels = createOpenAiFetchModels({\n modelsUrl: XIAOMI_TOKEN_PLAN_MODELS_URL,\n apiKeyEnv: XIAOMI_TOKEN_PLAN_API_KEY,\n providerName: 'Xiaomi MiMo Token Plan',\n})\n\nconst app = createProviderApp({\n providerId: 'xiaomitoken',\n basePath: '/xiaomitoken',\n models,\n defaultModel: models[0].id,\n chat: async (messages, modelId, rawBody, credentials) =>\n chatViaOpenAiCompatible(\n { providerName: 'Xiaomi MiMo Token Plan', chatUrl: XIAOMI_TOKEN_PLAN_CHAT_URL, apiKeyEnv: XIAOMI_TOKEN_PLAN_API_KEY },\n { messages, modelId, rawBody },\n credentials,\n ),\n fetchModels,\n testCredentials: (credentials) =>\n testViaOpenAiModels(\n { modelsUrl: XIAOMI_TOKEN_PLAN_MODELS_URL, apiKeyEnv: XIAOMI_TOKEN_PLAN_API_KEY, providerName: 'Xiaomi MiMo Token Plan' },\n credentials,\n ),\n})\n\nexport default app.fetch\n"}}, "README_EN.md": {"f64f3527c540ab16f2772ada41dec64216c3ad18": {"t": 1785747256.479305, "n": 10477, "h": "156c0e7ef69aa3c0", "c": "<p align=\"right\"><a href=\"README.md\">Português</a></p>\n\n<div align=\"center\">\n <img src=\"public/logo.png\" alt=\"ModelHub\" width=\"120\" height=\"120\" />\n\n <h1>ModelHub</h1>\n\n <p><strong>Unified gateway for multiple AI providers with an OpenAI-compatible API.</strong></p>\n\n <p>\n <a href=\"https://github.com/actus7/modelhub/actions/workflows/ci.yml\"><img alt=\"CI\" src=\"https://github.com/actus7/modelhub/actions/workflows/ci.yml/badge.svg\" /></a>\n <a href=\"LICENSE\"><img alt=\"MIT License\" src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" /></a>\n <a href=\"https://nodejs.org\"><img alt=\"Node.js >= 22\" src=\"https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen\" /></a>\n <a href=\"https://nextjs.org/\"><img alt=\"Next.js 16.2\" src=\"https://img.shields.io/badge/Next.js-16.2-black\" /></a>\n <a href=\"https://www.typescriptlang.org/\"><img alt=\"TypeScript 5\" src=\"https://img.shields.io/badge/TypeScript-5.x-blue\" /></a>\n <a href=\"https://hono.dev/\"><img alt=\"Hono 4\" src=\"https://img.shields.io/badge/Hono-4.x-E36002?logo=hono&logoColor=white\" /></a>\n <a href=\"https://www.prisma.io/\"><img alt=\"Prisma 7\" src=\"https://img.shields.io/badge/Prisma-7.x-2D3748?logo=prisma&logoColor=white\" /></a>\n <a href=\"https://neon.tech\"><img alt=\"Powered by Neon\" src=\"https://img.shields.io/badge/Powered%20by-Neon-00E599?logo=neon&logoColor=white\" /></a>\n <a href=\"https://vercel.com/\"><img alt=\"Deploy on Vercel\" src=\"https://img.shields.io/badge/Deploy-Vercel-000000?logo=vercel&logoColor=white\" /></a>\n </p>\n\n <p>\n <a href=\"#overview\">Overview</a> ·\n <a href=\"#features\">Features</a> ·\n <a href=\"#quickstart\">Quickstart</a> ·\n <a href=\"#api\">API</a> ·\n <a href=\"#architecture\">Architecture</a> ·\n <a href=\"#deploy\">Deploy</a>\n </p>\n\n <p>\n <a href=\"https://vercel.com/new/clone?repository-url=https://github.com/actus7/modelhub\"><img alt=\"Deploy with Vercel\" src=\"https://vercel.com/button\" /></a>\n </p>\n</div>\n\n---\n\n## Overview\n\nModelHub centralizes OpenAI, Google, Groq, Mistral, OpenRouter and other providers into a single open-source platform. It delivers an OpenAI-compatible API, authenticated web chat, secure credential management, and a usage dashboard.\n\nInstead of each application integrating multiple providers separately, ModelHub standardizes authentication, routing, logs, costs, model catalog, and fallbacks.\n\n## Features\n\n<table>\n <tr>\n <td><strong>OpenAI-compatible API</strong><br />Use <code>/v1/chat/completions</code> and <code>/v1/models</code> with existing clients.</td>\n <td><strong>Web chat</strong><br />Authenticated interface to chat with configured models.</td>\n </tr>\n <tr>\n <td><strong>Secure credentials</strong><br />ModelHub API keys and provider keys encrypted per user.</td>\n <td><strong>Usage dashboard</strong><br />Requests, estimated costs, status codes, tokens, and recent logs.</td>\n </tr>\n <tr>\n <td><strong>Smart routing</strong><br />Tiers by complexity, per-task overrides, and automatic fallbacks.</td>\n <td><strong>Chat attachments</strong><br />Support for images, PDFs, and documents.</td>\n </tr>\n <tr>\n <td><strong>Dynamic catalog</strong><br />Local models and remote search when the provider supports it.</td>\n <td><strong>Production-ready</strong><br />Rate limiting, cooldown, security headers, CI, and Vercel deploy.</td>\n </tr>\n</table>\n\n## Providers\n\nThe catalog lives in `server/lib/catalog.ts` and each adapter lives in `server/providers/`.\n\n| Supported | |\n|---|---|\n| OpenAI | Google AI Studio |\n| Groq | Mistral / Codestral |\n| OpenRouter | HuggingFace |\n| DeepSeek | Perplexity |\n| Together AI | Fireworks AI |\n| Cohere | Cloudflare Workers AI |\n| Ollama / Ollama Cloud | GitHub Models |\n| GitHub Copilot | Qwen / Qwen Token Plan |\n| Z.ai / Z.ai Coding Plan | Moonshot / Kimi |\n| NVIDIA NIM | Pollinations / Puter |\n\nBroken or duplicate providers should be removed from both the catalog and the registry so they don't appear on the integrations screen.\n\n## Quickstart\n\n### Requirements\n\n- Node.js >= 22\n- pnpm >= 10\n- PostgreSQL Neon\n- Configured Neon Auth account\n- `ENCRYPTION_KEY` with 64 hex characters\n- Keys for the providers you intend to use\n\n### Local installation\n\n```bash\ngit clone https://github.com/actus7/modelhub.git\ncd modelhub\npnpm install\ncp .env.example .env\npnpm prisma:migrate\npnpm dev\n```\n\nVisit `http://localhost:3000`.\n\n`pnpm install` automatically runs `pnpm prisma:generate` via `postinstall`.\n\n## Environment variables\n\nSee `.env.example` for the full list.\n\nRequired:\n\n```env\nDATABASE_URL=\"postgresql://...\"\nDIRECT_URL=\"postgresql://...\"\nNEON_AUTH_BASE_URL=\"https://...\"\nNEON_AUTH_COOKIE_SECRET=\"...\"\nENCRYPTION_KEY=\"64_hex_chars\"\n```\n\nCommon optional:\n\n```env\nOPENAI_API_KEY=\"sk-...\"\nGOOGLE_AI_STUDIO_API_KEY=\"AIza...\"\nOPENROUTER_API_KEY=\"sk-or-...\"\nGROQ_API_KEY=\"gsk_...\"\nMISTRAL_API_KEY=\"sk-...\"\nDEEPSEEK_API_KEY=\"sk-...\"\n```\n\nWithout a global key, users can still register their own credentials on the **Integrations** screen when the provider requires authentication.\n\n## Commands\n\n```bash\npnpm dev # local server at localhost:3000\npnpm build # production build\npnpm build:vercel # build used on Vercel\npnpm start # runs the generated build\npnpm lint # ESLint\npnpm typecheck # TypeScript without emit\npnpm test # Vitest\npnpm test:coverage # Vitest with coverage\npnpm prisma:generate # generates Prisma Client\npnpm prisma:migrate # local Prisma migration\npnpm prisma:push # push schema in development\n```\n\n## API\n\n### Chat completions\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_MODELHUB_API_KEY\" \\\n -d '{\n \"model\": \"openai/gpt-4o-mini\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Hello!\"}\n ]\n }'\n```\n\n### Streaming\n\n```bash\ncurl -N -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_MODELHUB_API_KEY\" \\\n -d '{\n \"model\": \"mistral/codestral-latest\",\n \"stream\": true,\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Explain a debounce function in TypeScript.\"}\n ]\n }'\n```\n\n### List models\n\n```bash\ncurl http://localhost:3000/v1/models \\\n -H \"Authorization: Bearer YOUR_MODELHUB_API_KEY\"\n```\n\nThe `model` field follows the `provider/model` format, for example:\n\n- `openai/gpt-4o-mini`\n- `googleaistudio/gemini-2.5-flash`\n- `mistral/codestral-latest`\n- `openrouter/openai/gpt-oss-20b:free`\n\n## Web interface\n\n| Route | Description |\n|---|---|\n| `/chat` | Chat with configured providers |\n| `/setup` | Integrations and credentials per provider |\n| `/dashboard` | API keys, usage, costs, logs, and routing |\n| `/account` | Account information |\n| `/playground` | Compare and test providers |\n\nAuthenticated routes are protected by `proxy.ts`.\n\n## Architecture\n\n```text\napp/ Next.js App Router\napp/(app)/ authenticated routes\ncomponents/ React components\ncomponents/chat/ chat UI\ncomponents/dashboard/ dashboard, API keys, routing, and analytics\ncomponents/setup/ integrations screen\ncomponents/ui/ shadcn/ui and base components\nlib/ shared helpers\nlib/auth/ Neon Auth client/server\nserver/app.ts main Hono app\nserver/route-handler.ts bridge between Next.js and Hono\nserver/routes/ /user, /v1, conversations, etc. routes\nserver/providers/ provider adapters\nserver/lib/openai-compatible.ts utility for OpenAI-compatible providers\nserver/lib/routing/ routing, tiers, health, and suggestions\nserver/lib/security.ts CORS, rate limit, and headers\nserver/lib/db.ts Prisma + Neon adapter\nprisma/schema.prisma database schema\nprisma/migrations/ migrations\n```\n\nThe application uses two layers:\n\n1. **Next.js 16 App Router** for pages, layouts, frontend authentication, and Vercel integration.\n2. **Hono** for the gateway API, providers, user, and OpenAI-compatible routes.\n\n## Database\n\nThe database is PostgreSQL via Neon, accessed with Prisma 7 and `@prisma/adapter-neon`.\n\nKey models: `User`, `ApiKey`, `ProviderCredential`, `Conversation`, `Message`, `ConversationAttachment`, `UsageLog`, `UserMemory`, and `UserSettings`.\n\nFor schema changes:\n\n```bash\npnpm prisma:migrate\npnpm prisma:generate\n```\n\n## Security\n\n- ModelHub API keys are stored by hash/prefix.\n- Provider credentials are encrypted with `ENCRYPTION_KEY`.\n- Error logs are scrubbed to prevent secret leakage.\n- Rate limiting and cooldown reduce abuse and failure loops.\n- Never commit `.env`, tokens, or real keys.\n\nTo report vulnerabilities, see `SECURITY.md`.\n\n## CI/CD\n\nGitHub Actions runs on PRs and pushes to `main`/`develop`:\n\n- Lint (`pnpm lint`)\n- Type check (`pnpm typecheck`)\n- Tests (`pnpm test`)\n- Production dependency security audit (`pnpm audit --prod --audit-level=high`)\n- Build (`pnpm build`)\n- CodeQL\n- Optional Dependency Review via the `ENABLE_DEPENDENCY_REVIEW=true` variable\n\nVercel automatically generates previews for PRs.\n\n## Deploy\n\n### Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/actus7/modelhub)\n\n1. Connect the repository on Vercel.\n2. Configure the required environment variables.\n3. Ensure the build uses `pnpm build` or `pnpm build:vercel`, depending on the Vercel project.\n4. Run database migrations before promoting to production when there are changes in `prisma/migrations/`.\n\n### Docker\n\nIf using Docker, pass `.env` at runtime:\n\n```bash\ndocker build -t modelhub .\ndocker run --env-file .env -p 3000:3000 modelhub\n```\n\n## Contributing\n\nSee `CONTRIBUTING.md`.\n\n```bash\ngit checkout -b fix/my-change\npnpm test\npnpm lint\npnpm typecheck\n```\n\nUse Conventional Commits:\n\n```text\nfeat(chat): add support for new attachment\nfix(providers): remove broken integration\ndocs(readme): update setup instructions\n```\n\n## Support the project\n\nModelHub requires continuous maintenance, infrastructure, and testing with multiple AI APIs. Your sponsorship helps cover these costs and keeps the project open and up to date.\n\n[Sponsor ModelHub on GitHub Sponsors](https://github.com/sponsors/actus7).\n\n## License\n\nMIT. See `LICENSE`.\n\n## Acknowledgements\n\nNext.js · Hono · Prisma · Neon · shadcn/ui · Vitest · Open-source community\n"}, "426bccb40dd31e659550f629c1ff7f983ad0f8fc": {"t": 1785771880.8012154, "n": 10477, "h": "156c0e7ef69aa3c0", "c": "<p align=\"right\"><a href=\"README.md\">Português</a></p>\n\n<div align=\"center\">\n <img src=\"public/logo.png\" alt=\"ModelHub\" width=\"120\" height=\"120\" />\n\n <h1>ModelHub</h1>\n\n <p><strong>Unified gateway for multiple AI providers with an OpenAI-compatible API.</strong></p>\n\n <p>\n <a href=\"https://github.com/actus7/modelhub/actions/workflows/ci.yml\"><img alt=\"CI\" src=\"https://github.com/actus7/modelhub/actions/workflows/ci.yml/badge.svg\" /></a>\n <a href=\"LICENSE\"><img alt=\"MIT License\" src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" /></a>\n <a href=\"https://nodejs.org\"><img alt=\"Node.js >= 22\" src=\"https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen\" /></a>\n <a href=\"https://nextjs.org/\"><img alt=\"Next.js 16.2\" src=\"https://img.shields.io/badge/Next.js-16.2-black\" /></a>\n <a href=\"https://www.typescriptlang.org/\"><img alt=\"TypeScript 5\" src=\"https://img.shields.io/badge/TypeScript-5.x-blue\" /></a>\n <a href=\"https://hono.dev/\"><img alt=\"Hono 4\" src=\"https://img.shields.io/badge/Hono-4.x-E36002?logo=hono&logoColor=white\" /></a>\n <a href=\"https://www.prisma.io/\"><img alt=\"Prisma 7\" src=\"https://img.shields.io/badge/Prisma-7.x-2D3748?logo=prisma&logoColor=white\" /></a>\n <a href=\"https://neon.tech\"><img alt=\"Powered by Neon\" src=\"https://img.shields.io/badge/Powered%20by-Neon-00E599?logo=neon&logoColor=white\" /></a>\n <a href=\"https://vercel.com/\"><img alt=\"Deploy on Vercel\" src=\"https://img.shields.io/badge/Deploy-Vercel-000000?logo=vercel&logoColor=white\" /></a>\n </p>\n\n <p>\n <a href=\"#overview\">Overview</a> ·\n <a href=\"#features\">Features</a> ·\n <a href=\"#quickstart\">Quickstart</a> ·\n <a href=\"#api\">API</a> ·\n <a href=\"#architecture\">Architecture</a> ·\n <a href=\"#deploy\">Deploy</a>\n </p>\n\n <p>\n <a href=\"https://vercel.com/new/clone?repository-url=https://github.com/actus7/modelhub\"><img alt=\"Deploy with Vercel\" src=\"https://vercel.com/button\" /></a>\n </p>\n</div>\n\n---\n\n## Overview\n\nModelHub centralizes OpenAI, Google, Groq, Mistral, OpenRouter and other providers into a single open-source platform. It delivers an OpenAI-compatible API, authenticated web chat, secure credential management, and a usage dashboard.\n\nInstead of each application integrating multiple providers separately, ModelHub standardizes authentication, routing, logs, costs, model catalog, and fallbacks.\n\n## Features\n\n<table>\n <tr>\n <td><strong>OpenAI-compatible API</strong><br />Use <code>/v1/chat/completions</code> and <code>/v1/models</code> with existing clients.</td>\n <td><strong>Web chat</strong><br />Authenticated interface to chat with configured models.</td>\n </tr>\n <tr>\n <td><strong>Secure credentials</strong><br />ModelHub API keys and provider keys encrypted per user.</td>\n <td><strong>Usage dashboard</strong><br />Requests, estimated costs, status codes, tokens, and recent logs.</td>\n </tr>\n <tr>\n <td><strong>Smart routing</strong><br />Tiers by complexity, per-task overrides, and automatic fallbacks.</td>\n <td><strong>Chat attachments</strong><br />Support for images, PDFs, and documents.</td>\n </tr>\n <tr>\n <td><strong>Dynamic catalog</strong><br />Local models and remote search when the provider supports it.</td>\n <td><strong>Production-ready</strong><br />Rate limiting, cooldown, security headers, CI, and Vercel deploy.</td>\n </tr>\n</table>\n\n## Providers\n\nThe catalog lives in `server/lib/catalog.ts` and each adapter lives in `server/providers/`.\n\n| Supported | |\n|---|---|\n| OpenAI | Google AI Studio |\n| Groq | Mistral / Codestral |\n| OpenRouter | HuggingFace |\n| DeepSeek | Perplexity |\n| Together AI | Fireworks AI |\n| Cohere | Cloudflare Workers AI |\n| Ollama / Ollama Cloud | GitHub Models |\n| GitHub Copilot | Qwen / Qwen Token Plan |\n| Z.ai / Z.ai Coding Plan | Moonshot / Kimi |\n| NVIDIA NIM | Pollinations / Puter |\n\nBroken or duplicate providers should be removed from both the catalog and the registry so they don't appear on the integrations screen.\n\n## Quickstart\n\n### Requirements\n\n- Node.js >= 22\n- pnpm >= 10\n- PostgreSQL Neon\n- Configured Neon Auth account\n- `ENCRYPTION_KEY` with 64 hex characters\n- Keys for the providers you intend to use\n\n### Local installation\n\n```bash\ngit clone https://github.com/actus7/modelhub.git\ncd modelhub\npnpm install\ncp .env.example .env\npnpm prisma:migrate\npnpm dev\n```\n\nVisit `http://localhost:3000`.\n\n`pnpm install` automatically runs `pnpm prisma:generate` via `postinstall`.\n\n## Environment variables\n\nSee `.env.example` for the full list.\n\nRequired:\n\n```env\nDATABASE_URL=\"postgresql://...\"\nDIRECT_URL=\"postgresql://...\"\nNEON_AUTH_BASE_URL=\"https://...\"\nNEON_AUTH_COOKIE_SECRET=\"...\"\nENCRYPTION_KEY=\"64_hex_chars\"\n```\n\nCommon optional:\n\n```env\nOPENAI_API_KEY=\"sk-...\"\nGOOGLE_AI_STUDIO_API_KEY=\"AIza...\"\nOPENROUTER_API_KEY=\"sk-or-...\"\nGROQ_API_KEY=\"gsk_...\"\nMISTRAL_API_KEY=\"sk-...\"\nDEEPSEEK_API_KEY=\"sk-...\"\n```\n\nWithout a global key, users can still register their own credentials on the **Integrations** screen when the provider requires authentication.\n\n## Commands\n\n```bash\npnpm dev # local server at localhost:3000\npnpm build # production build\npnpm build:vercel # build used on Vercel\npnpm start # runs the generated build\npnpm lint # ESLint\npnpm typecheck # TypeScript without emit\npnpm test # Vitest\npnpm test:coverage # Vitest with coverage\npnpm prisma:generate # generates Prisma Client\npnpm prisma:migrate # local Prisma migration\npnpm prisma:push # push schema in development\n```\n\n## API\n\n### Chat completions\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_MODELHUB_API_KEY\" \\\n -d '{\n \"model\": \"openai/gpt-4o-mini\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Hello!\"}\n ]\n }'\n```\n\n### Streaming\n\n```bash\ncurl -N -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_MODELHUB_API_KEY\" \\\n -d '{\n \"model\": \"mistral/codestral-latest\",\n \"stream\": true,\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Explain a debounce function in TypeScript.\"}\n ]\n }'\n```\n\n### List models\n\n```bash\ncurl http://localhost:3000/v1/models \\\n -H \"Authorization: Bearer YOUR_MODELHUB_API_KEY\"\n```\n\nThe `model` field follows the `provider/model` format, for example:\n\n- `openai/gpt-4o-mini`\n- `googleaistudio/gemini-2.5-flash`\n- `mistral/codestral-latest`\n- `openrouter/openai/gpt-oss-20b:free`\n\n## Web interface\n\n| Route | Description |\n|---|---|\n| `/chat` | Chat with configured providers |\n| `/setup` | Integrations and credentials per provider |\n| `/dashboard` | API keys, usage, costs, logs, and routing |\n| `/account` | Account information |\n| `/playground` | Compare and test providers |\n\nAuthenticated routes are protected by `proxy.ts`.\n\n## Architecture\n\n```text\napp/ Next.js App Router\napp/(app)/ authenticated routes\ncomponents/ React components\ncomponents/chat/ chat UI\ncomponents/dashboard/ dashboard, API keys, routing, and analytics\ncomponents/setup/ integrations screen\ncomponents/ui/ shadcn/ui and base components\nlib/ shared helpers\nlib/auth/ Neon Auth client/server\nserver/app.ts main Hono app\nserver/route-handler.ts bridge between Next.js and Hono\nserver/routes/ /user, /v1, conversations, etc. routes\nserver/providers/ provider adapters\nserver/lib/openai-compatible.ts utility for OpenAI-compatible providers\nserver/lib/routing/ routing, tiers, health, and suggestions\nserver/lib/security.ts CORS, rate limit, and headers\nserver/lib/db.ts Prisma + Neon adapter\nprisma/schema.prisma database schema\nprisma/migrations/ migrations\n```\n\nThe application uses two layers:\n\n1. **Next.js 16 App Router** for pages, layouts, frontend authentication, and Vercel integration.\n2. **Hono** for the gateway API, providers, user, and OpenAI-compatible routes.\n\n## Database\n\nThe database is PostgreSQL via Neon, accessed with Prisma 7 and `@prisma/adapter-neon`.\n\nKey models: `User`, `ApiKey`, `ProviderCredential`, `Conversation`, `Message`, `ConversationAttachment`, `UsageLog`, `UserMemory`, and `UserSettings`.\n\nFor schema changes:\n\n```bash\npnpm prisma:migrate\npnpm prisma:generate\n```\n\n## Security\n\n- ModelHub API keys are stored by hash/prefix.\n- Provider credentials are encrypted with `ENCRYPTION_KEY`.\n- Error logs are scrubbed to prevent secret leakage.\n- Rate limiting and cooldown reduce abuse and failure loops.\n- Never commit `.env`, tokens, or real keys.\n\nTo report vulnerabilities, see `SECURITY.md`.\n\n## CI/CD\n\nGitHub Actions runs on PRs and pushes to `main`/`develop`:\n\n- Lint (`pnpm lint`)\n- Type check (`pnpm typecheck`)\n- Tests (`pnpm test`)\n- Production dependency security audit (`pnpm audit --prod --audit-level=high`)\n- Build (`pnpm build`)\n- CodeQL\n- Optional Dependency Review via the `ENABLE_DEPENDENCY_REVIEW=true` variable\n\nVercel automatically generates previews for PRs.\n\n## Deploy\n\n### Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/actus7/modelhub)\n\n1. Connect the repository on Vercel.\n2. Configure the required environment variables.\n3. Ensure the build uses `pnpm build` or `pnpm build:vercel`, depending on the Vercel project.\n4. Run database migrations before promoting to production when there are changes in `prisma/migrations/`.\n\n### Docker\n\nIf using Docker, pass `.env` at runtime:\n\n```bash\ndocker build -t modelhub .\ndocker run --env-file .env -p 3000:3000 modelhub\n```\n\n## Contributing\n\nSee `CONTRIBUTING.md`.\n\n```bash\ngit checkout -b fix/my-change\npnpm test\npnpm lint\npnpm typecheck\n```\n\nUse Conventional Commits:\n\n```text\nfeat(chat): add support for new attachment\nfix(providers): remove broken integration\ndocs(readme): update setup instructions\n```\n\n## Support the project\n\nModelHub requires continuous maintenance, infrastructure, and testing with multiple AI APIs. Your sponsorship helps cover these costs and keeps the project open and up to date.\n\n[Sponsor ModelHub on GitHub Sponsors](https://github.com/sponsors/actus7).\n\n## License\n\nMIT. See `LICENSE`.\n\n## Acknowledgements\n\nNext.js · Hono · Prisma · Neon · shadcn/ui · Vitest · Open-source community\n"}, "f01e3e419da14a32cab77d3c2a5ecd3669d5f236": {"t": 1785771883.7732656, "n": 5209, "h": "e38c1579caea30af", "c": "<p align=\"right\"><a href=\"README.md\">Portugues</a></p>\n\n# ModelHub\n\n<div align=\"center\">\n\n\n\n**Unified hub for multiple AI models with OpenAI-compatible API**\n\n[](https://github.com/actus7/modelhub/actions/workflows/ci.yml)\n[](https://opensource.org/licenses/MIT)\n[](https://nodejs.org)\n[](https://www.typescriptlang.org/)\n[](https://nextjs.org/)\n[](https://github.com/actus7/modelhub/pulls)\n[](https://hono.dev/)\n[](https://www.prisma.io/)\n[](https://neon.tech)\n[](https://vercel.com/)\n\n[Features](#features) |\n[Installation](#installation) |\n[Documentation](#documentation) |\n[Contributing](#contributing) |\n[License](#license)\n\n</div>\n\n---\n\n## About\n\nModelHub is an open-source platform that unifies access to multiple AI providers (OpenAI, Anthropic, Google, Groq, Mistral, and others) through a single OpenAI-compatible API. It includes a built-in chat interface, secure credential management, and a robust authentication system.\n\n### Features\n\n- **Unified API Gateway** - OpenAI-compatible interface for multiple providers\n- **Built-in Chat** - Modern web interface for interacting with AI models\n- **Secure Authentication** - Complete system with Neon Auth\n- **Credential Management** - Encrypted storage for API keys\n- **Usage Dashboard** - Monitor consumption and costs in real time\n- **Attachment Support** - Upload images, PDFs, and documents\n- **Multi-tenant** - Support for multiple users and organizations\n- **Easy Deploy** - Ready for Vercel, Docker, and other platforms\n- **TypeScript** - Fully typed for better DX\n- **Tested** - Test coverage with Vitest\n\n### Supported Providers\n\n- OpenAI (GPT-4, GPT-3.5, etc.)\n- Anthropic (Claude 3.5, Claude 3, etc.)\n- Google AI (Gemini Pro, Gemini Flash)\n- Groq (Llama, Mixtral)\n- Mistral AI\n- Cohere\n- HuggingFace\n- OpenRouter\n- Vercel AI Gateway\n\n## Installation\n\n### Prerequisites\n\n- Node.js >= 22.0.0\n- pnpm >= 10.0.0\n- [Neon](https://neon.tech) account (serverless PostgreSQL)\n- API keys for the providers you want to use\n\n### Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/actus7/modelhub.git\ncd modelhub\n\n# Install dependencies\npnpm install\n\n# Set up environment variables\ncp .env.example .env\n# Edit .env with your credentials\n\n# Run database migrations\npnpm prisma:migrate\n\n# Start the development server\npnpm dev\n```\n\nVisit http://localhost:3000\n\n### Docker\n\n```bash\ndocker build -t modelhub .\ndocker run -p 3000:3000 --env-file .env modelhub\n```\n\n### Deploy to Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/actus7/modelhub)\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Quick Start](docs/QUICKSTART.md) | Get up and running in minutes |\n| [API Reference](docs/API.md) | Complete API documentation |\n| [Architecture](docs/ARCHITECTURE.md) | Technical architecture overview |\n| [Deployment](docs/DEPLOYMENT.md) | Deploy guides (Vercel, Docker, VPS) |\n| [Examples](docs/EXAMPLES.md) | Practical usage examples |\n| [FAQ](docs/FAQ.md) | Frequently asked questions |\n\n### API Usage\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"model\": \"openrouter/openai/gpt-oss-20b:free\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\n## Contributing\n\nContributions are very welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'feat: add AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\nThis project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.\n\n## Security\n\nTo report security vulnerabilities, see [SECURITY.md](SECURITY.md).\n\n## License\n\nThis project is licensed under the MIT License - see [LICENSE](LICENSE) for details.\n\n## Acknowledgements\n\n- [Next.js](https://nextjs.org/) - React Framework\n- [Prisma](https://www.prisma.io/) - ORM\n- [Neon](https://neon.tech/) - PostgreSQL Serverless\n- [shadcn/ui](https://ui.shadcn.com/) - UI Components\n- [Hono](https://hono.dev/) - Web Framework\n\n---\n\n<div align=\"center\">\n\n**[Back to top](#modelhub)**\n\nMade with care by the ModelHub community\n\n</div>\n"}, "652ba9a7ad4b6460dba5adedaf7cbeb935ef795e": {"t": 1785771885.173578, "n": 4751, "h": "c1e1f03de52f8084", "c": "<p align=\"right\"><a href=\"README.md\">Portugues</a></p>\n\n# ModelHub\n\n<div align=\"center\">\n\n\n\n**Unified hub for multiple AI models with OpenAI-compatible API**\n\n[](https://github.com/actus7/modelhub/actions/workflows/ci.yml)\n[](https://opensource.org/licenses/MIT)\n[](https://nodejs.org)\n[](https://www.typescriptlang.org/)\n[](https://nextjs.org/)\n[](https://github.com/actus7/modelhub/pulls)\n\n[Features](#features) |\n[Installation](#installation) |\n[Documentation](#documentation) |\n[Contributing](#contributing) |\n[License](#license)\n\n</div>\n\n---\n\n## About\n\nModelHub is an open-source platform that unifies access to multiple AI providers (OpenAI, Anthropic, Google, Groq, Mistral, and others) through a single OpenAI-compatible API. It includes a built-in chat interface, secure credential management, and a robust authentication system.\n\n### Features\n\n- **Unified API Gateway** - OpenAI-compatible interface for multiple providers\n- **Built-in Chat** - Modern web interface for interacting with AI models\n- **Secure Authentication** - Complete system with Neon Auth\n- **Credential Management** - Encrypted storage for API keys\n- **Usage Dashboard** - Monitor consumption and costs in real time\n- **Attachment Support** - Upload images, PDFs, and documents\n- **Multi-tenant** - Support for multiple users and organizations\n- **Easy Deploy** - Ready for Vercel, Docker, and other platforms\n- **TypeScript** - Fully typed for better DX\n- **Tested** - Test coverage with Vitest\n\n### Supported Providers\n\n- OpenAI (GPT-4, GPT-3.5, etc.)\n- Anthropic (Claude 3.5, Claude 3, etc.)\n- Google AI (Gemini Pro, Gemini Flash)\n- Groq (Llama, Mixtral)\n- Mistral AI\n- Cohere\n- HuggingFace\n- OpenRouter\n- Vercel AI Gateway\n\n## Installation\n\n### Prerequisites\n\n- Node.js >= 22.0.0\n- pnpm >= 10.0.0\n- [Neon](https://neon.tech) account (serverless PostgreSQL)\n- API keys for the providers you want to use\n\n### Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/actus7/modelhub.git\ncd modelhub\n\n# Install dependencies\npnpm install\n\n# Set up environment variables\ncp .env.example .env\n# Edit .env with your credentials\n\n# Run database migrations\npnpm prisma:migrate\n\n# Start the development server\npnpm dev\n```\n\nVisit http://localhost:3000\n\n### Docker\n\n```bash\ndocker build -t modelhub .\ndocker run -p 3000:3000 --env-file .env modelhub\n```\n\n### Deploy to Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/actus7/modelhub)\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Quick Start](docs/QUICKSTART.md) | Get up and running in minutes |\n| [API Reference](docs/API.md) | Complete API documentation |\n| [Architecture](docs/ARCHITECTURE.md) | Technical architecture overview |\n| [Deployment](docs/DEPLOYMENT.md) | Deploy guides (Vercel, Docker, VPS) |\n| [Examples](docs/EXAMPLES.md) | Practical usage examples |\n| [FAQ](docs/FAQ.md) | Frequently asked questions |\n\n### API Usage\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"model\": \"openrouter/openai/gpt-oss-20b:free\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\n## Contributing\n\nContributions are very welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'feat: add AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\nThis project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.\n\n## Security\n\nTo report security vulnerabilities, see [SECURITY.md](SECURITY.md).\n\n## License\n\nThis project is licensed under the MIT License - see [LICENSE](LICENSE) for details.\n\n## Acknowledgements\n\n- [Next.js](https://nextjs.org/) - React Framework\n- [Prisma](https://www.prisma.io/) - ORM\n- [Neon](https://neon.tech/) - PostgreSQL Serverless\n- [shadcn/ui](https://ui.shadcn.com/) - UI Components\n- [Hono](https://hono.dev/) - Web Framework\n\n---\n\n<div align=\"center\">\n\n**[Back to top](#modelhub)**\n\nMade with care by the ModelHub community\n\n</div>\n"}, "7d01730129090d5e7be28aa34ac8edbe1a644f17": {"t": 1785771886.346727, "n": 4771, "h": "d45bb8c5da178ffc", "c": "<p align=\"right\"><a href=\"README.md\">Portugues</a></p>\n\n# ModelHub\n\n<div align=\"center\">\n\n\n\n**Unified hub for multiple AI models with OpenAI-compatible API**\n\n[](https://github.com/Geeks-Zone/modelhub/actions/workflows/ci.yml)\n[](https://opensource.org/licenses/MIT)\n[](https://nodejs.org)\n[](https://www.typescriptlang.org/)\n[](https://nextjs.org/)\n[](https://github.com/Geeks-Zone/modelhub/pulls)\n\n[Features](#features) |\n[Installation](#installation) |\n[Documentation](#documentation) |\n[Contributing](#contributing) |\n[License](#license)\n\n</div>\n\n---\n\n## About\n\nModelHub is an open-source platform that unifies access to multiple AI providers (OpenAI, Anthropic, Google, Groq, Mistral, and others) through a single OpenAI-compatible API. It includes a built-in chat interface, secure credential management, and a robust authentication system.\n\n### Features\n\n- **Unified API Gateway** - OpenAI-compatible interface for multiple providers\n- **Built-in Chat** - Modern web interface for interacting with AI models\n- **Secure Authentication** - Complete system with Neon Auth\n- **Credential Management** - Encrypted storage for API keys\n- **Usage Dashboard** - Monitor consumption and costs in real time\n- **Attachment Support** - Upload images, PDFs, and documents\n- **Multi-tenant** - Support for multiple users and organizations\n- **Easy Deploy** - Ready for Vercel, Docker, and other platforms\n- **TypeScript** - Fully typed for better DX\n- **Tested** - Test coverage with Vitest\n\n### Supported Providers\n\n- OpenAI (GPT-4, GPT-3.5, etc.)\n- Anthropic (Claude 3.5, Claude 3, etc.)\n- Google AI (Gemini Pro, Gemini Flash)\n- Groq (Llama, Mixtral)\n- Mistral AI\n- Cohere\n- HuggingFace\n- OpenRouter\n- Vercel AI Gateway\n\n## Installation\n\n### Prerequisites\n\n- Node.js >= 22.0.0\n- pnpm >= 10.0.0\n- [Neon](https://neon.tech) account (serverless PostgreSQL)\n- API keys for the providers you want to use\n\n### Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/Geeks-Zone/modelhub.git\ncd modelhub\n\n# Install dependencies\npnpm install\n\n# Set up environment variables\ncp .env.example .env\n# Edit .env with your credentials\n\n# Run database migrations\npnpm prisma:migrate\n\n# Start the development server\npnpm dev\n```\n\nVisit http://localhost:3000\n\n### Docker\n\n```bash\ndocker build -t modelhub .\ndocker run -p 3000:3000 --env-file .env modelhub\n```\n\n### Deploy to Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/Geeks-Zone/modelhub)\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Quick Start](docs/QUICKSTART.md) | Get up and running in minutes |\n| [API Reference](docs/API.md) | Complete API documentation |\n| [Architecture](docs/ARCHITECTURE.md) | Technical architecture overview |\n| [Deployment](docs/DEPLOYMENT.md) | Deploy guides (Vercel, Docker, VPS) |\n| [Examples](docs/EXAMPLES.md) | Practical usage examples |\n| [FAQ](docs/FAQ.md) | Frequently asked questions |\n\n### API Usage\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"model\": \"openrouter/openai/gpt-oss-20b:free\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\n## Contributing\n\nContributions are very welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'feat: add AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\nThis project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.\n\n## Security\n\nTo report security vulnerabilities, see [SECURITY.md](SECURITY.md).\n\n## License\n\nThis project is licensed under the MIT License - see [LICENSE](LICENSE) for details.\n\n## Acknowledgements\n\n- [Next.js](https://nextjs.org/) - React Framework\n- [Prisma](https://www.prisma.io/) - ORM\n- [Neon](https://neon.tech/) - PostgreSQL Serverless\n- [shadcn/ui](https://ui.shadcn.com/) - UI Components\n- [Hono](https://hono.dev/) - Web Framework\n\n---\n\n<div align=\"center\">\n\n**[Back to top](#modelhub)**\n\nMade with care by the ModelHub community\n\n</div>\n"}, "c3d09e2d02cb77e3d4903c1ea50c8b65d6dd5941": {"t": 1785771887.6072927, "n": 5735, "h": "7bd2ca373cef08f7", "c": "<p align=\"right\"><a href=\"README.md\">Portugues</a></p>\n\n# ModelHub\n\n<div align=\"center\">\n\n\n\n**Unified hub for multiple AI models with OpenAI-compatible API**\n\n[](https://github.com/Geeks-Zone/modelhub/actions/workflows/ci.yml)\n[](https://opensource.org/licenses/MIT)\n[](https://nodejs.org)\n[](https://www.typescriptlang.org/)\n[](https://nextjs.org/)\n[](https://github.com/Geeks-Zone/modelhub/pulls)\n\n[Features](#features) |\n[Installation](#installation) |\n[Documentation](#documentation) |\n[Contributing](#contributing) |\n[License](#license)\n\n</div>\n\n---\n\n## About\n\nModelHub is an open-source platform that unifies access to multiple AI providers (OpenAI, Anthropic, Google, Groq, Mistral, and others) through a single OpenAI-compatible API. It includes a built-in chat interface, secure credential management, and a robust authentication system.\n\n### Features\n\n- **Unified API Gateway** - OpenAI-compatible interface for multiple providers\n- **Built-in Chat** - Modern web interface for interacting with AI models\n- **Secure Authentication** - Complete system with Neon Auth\n- **Credential Management** - Encrypted storage for API keys\n- **Usage Dashboard** - Monitor consumption and costs in real time\n- **Attachment Support** - Upload images, PDFs, and documents\n- **Multi-tenant** - Support for multiple users and organizations\n- **Easy Deploy** - Ready for Vercel, Docker, and other platforms\n- **TypeScript** - Fully typed for better DX\n- **Tested** - Test coverage with Vitest\n\n### Supported Providers\n\n- OpenAI (GPT-4, GPT-3.5, etc.)\n- Anthropic (Claude 3.5, Claude 3, etc.)\n- Google AI (Gemini Pro, Gemini Flash)\n- Groq (Llama, Mixtral)\n- Mistral AI\n- Cohere\n- HuggingFace\n- OpenRouter\n- Vercel AI Gateway\n\n## Installation\n\n### Prerequisites\n\n- Node.js >= 22.0.0\n- pnpm >= 10.0.0\n- [Neon](https://neon.tech) account (serverless PostgreSQL)\n- API keys for the providers you want to use\n\n### Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/Geeks-Zone/modelhub.git\ncd modelhub\n\n# Install dependencies\npnpm install\n\n# Set up environment variables\ncp .env.example .env\n# Edit .env with your credentials\n\n# Run database migrations\npnpm prisma:migrate\n\n# Start the development server\npnpm dev\n```\n\nVisit http://localhost:3000\n\n### Docker\n\n```bash\ndocker build -t modelhub .\ndocker run -p 3000:3000 --env-file .env modelhub\n```\n\n### Deploy to Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/Geeks-Zone/modelhub)\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Quick Start](docs/QUICKSTART.md) | Get up and running in minutes |\n| [API Reference](docs/API.md) | Complete API documentation |\n| [Architecture](docs/ARCHITECTURE.md) | Technical architecture overview |\n| [Deployment](docs/DEPLOYMENT.md) | Deploy guides (Vercel, Docker, VPS) |\n| [Examples](docs/EXAMPLES.md) | Practical usage examples |\n| [FAQ](docs/FAQ.md) | Frequently asked questions |\n\n### API Usage\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"model\": \"openrouter/openai/gpt-oss-20b:free\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\n### OpenClaw (OpenAI-compatible mode)\n\nMinimal OpenClaw configuration:\n\n- **Base URL:** `https://YOUR_MODELHUB/v1`\n- **API:** OpenAI-compatible chat completions\n- **Auth:** `Authorization: Bearer <MODELHUB_API_KEY>`\n- **Model:** use `provider/model-id` (example: `openrouter/openai/gpt-oss-20b:free`)\n\nRecommended presets:\n\n- **Coding:** reasoning + tool-use models\n- **Low cost:** `:free`, `mini`, `flash`\n- **Long context:** `128k+` / long-context models\n\nQuick troubleshooting:\n\n- **401/403 auth:** validate API key and Bearer header\n- **invalid model:** run `GET /v1/models` and use the returned `id` exactly\n- **timeouts:** switch to a low-cost/flash model and reduce `max_tokens`\n\n### OpenClaw (ModelHub CLI bootstrap)\n\n```bash\nmodelhub openclaw setup --base-url http://localhost:3000 --api-key YOUR_API_KEY\nmodelhub openclaw login --api-key YOUR_API_KEY\nmodelhub openclaw models\nmodelhub openclaw use openrouter/openai/gpt-oss-20b:free\nmodelhub doctor\n```\n\n## Contributing\n\nContributions are very welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'feat: add AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\nThis project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.\n\n## Security\n\nTo report security vulnerabilities, see [SECURITY.md](SECURITY.md).\n\n## License\n\nThis project is licensed under the MIT License - see [LICENSE](LICENSE) for details.\n\n## Acknowledgements\n\n- [Next.js](https://nextjs.org/) - React Framework\n- [Prisma](https://www.prisma.io/) - ORM\n- [Neon](https://neon.tech/) - PostgreSQL Serverless\n- [shadcn/ui](https://ui.shadcn.com/) - UI Components\n- [Hono](https://hono.dev/) - Web Framework\n\n---\n\n<div align=\"center\">\n\n**[Back to top](#modelhub)**\n\nMade with care by the ModelHub community\n\n</div>\n"}, "8fcd618bd2cf0f5a74256d20e97875beb85a67f7": {"t": 1785771888.7942276, "n": 4742, "h": "7a0b57cf83245dec", "c": "<p align=\"right\"><a href=\"README.md\">Portugues</a></p>\n\n# ModelHub\n\n<div align=\"center\">\n\n\n\n**Unified hub for multiple AI models with OpenAI-compatible API**\n\n[](https://github.com/Geeks-Zone/modelhub/actions/workflows/ci.yml)\n[](https://opensource.org/licenses/MIT)\n[](https://nodejs.org)\n[](https://www.typescriptlang.org/)\n[](https://nextjs.org/)\n[](https://github.com/Geeks-Zone/modelhub/pulls)\n\n[Features](#features) |\n[Installation](#installation) |\n[Documentation](#documentation) |\n[Contributing](#contributing) |\n[License](#license)\n\n</div>\n\n---\n\n## About\n\nModelHub is an open-source platform that unifies access to multiple AI providers (OpenAI, Anthropic, Google, Groq, Mistral, and others) through a single OpenAI-compatible API. It includes a built-in chat interface, secure credential management, and a robust authentication system.\n\n### Features\n\n- **Unified API Gateway** - OpenAI-compatible interface for multiple providers\n- **Built-in Chat** - Modern web interface for interacting with AI models\n- **Secure Authentication** - Complete system with Neon Auth\n- **Credential Management** - Encrypted storage for API keys\n- **Usage Dashboard** - Monitor consumption and costs in real time\n- **Attachment Support** - Upload images, PDFs, and documents\n- **Multi-tenant** - Support for multiple users and organizations\n- **Easy Deploy** - Ready for Vercel, Docker, and other platforms\n- **TypeScript** - Fully typed for better DX\n- **Tested** - Test coverage with Vitest\n\n### Supported Providers\n\n- OpenAI (GPT-4, GPT-3.5, etc.)\n- Anthropic (Claude 3.5, Claude 3, etc.)\n- Google AI (Gemini Pro, Gemini Flash)\n- Groq (Llama, Mixtral)\n- Mistral AI\n- Cohere\n- HuggingFace\n- OpenRouter\n- Vercel AI Gateway\n\n## Installation\n\n### Prerequisites\n\n- Node.js >= 22.0.0\n- pnpm >= 10.0.0\n- [Neon](https://neon.tech) account (serverless PostgreSQL)\n- API keys for the providers you want to use\n\n### Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/Geeks-Zone/modelhub.git\ncd modelhub\n\n# Install dependencies\npnpm install\n\n# Set up environment variables\ncp .env.example .env\n# Edit .env with your credentials\n\n# Run database migrations\npnpm prisma:migrate\n\n# Start the development server\npnpm dev\n```\n\nVisit http://localhost:3000\n\n### Docker\n\n```bash\ndocker build -t modelhub .\ndocker run -p 3000:3000 --env-file .env modelhub\n```\n\n### Deploy to Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/Geeks-Zone/modelhub)\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Quick Start](docs/QUICKSTART.md) | Get up and running in minutes |\n| [API Reference](docs/API.md) | Complete API documentation |\n| [Architecture](docs/ARCHITECTURE.md) | Technical architecture overview |\n| [Deployment](docs/DEPLOYMENT.md) | Deploy guides (Vercel, Docker, VPS) |\n| [Examples](docs/EXAMPLES.md) | Practical usage examples |\n| [FAQ](docs/FAQ.md) | Frequently asked questions |\n\n### API Usage\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"model\": \"gpt-4\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\n## Contributing\n\nContributions are very welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'feat: add AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\nThis project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.\n\n## Security\n\nTo report security vulnerabilities, see [SECURITY.md](SECURITY.md).\n\n## License\n\nThis project is licensed under the MIT License - see [LICENSE](LICENSE) for details.\n\n## Acknowledgements\n\n- [Next.js](https://nextjs.org/) - React Framework\n- [Prisma](https://www.prisma.io/) - ORM\n- [Neon](https://neon.tech/) - PostgreSQL Serverless\n- [shadcn/ui](https://ui.shadcn.com/) - UI Components\n- [Hono](https://hono.dev/) - Web Framework\n\n---\n\n<div align=\"center\">\n\n**[Back to top](#modelhub)**\n\nMade with care by the ModelHub community\n\n</div>\n"}, "6fa534bd3c0bac5f96324910d0bcea05c4dee5a2": {"t": 1785771891.1977572, "n": 4722, "h": "7307fa2eaa7a21c7", "c": "<p align=\"right\"><a href=\"README.md\">Portugues</a></p>\n\n# ModelHub\n\n<div align=\"center\">\n\n\n\n**Unified hub for multiple AI models with OpenAI-compatible API**\n\n[](https://github.com/actus7/modelhub/actions/workflows/ci.yml)\n[](https://opensource.org/licenses/MIT)\n[](https://nodejs.org)\n[](https://www.typescriptlang.org/)\n[](https://nextjs.org/)\n[](https://github.com/actus7/modelhub/pulls)\n\n[Features](#features) |\n[Installation](#installation) |\n[Documentation](#documentation) |\n[Contributing](#contributing) |\n[License](#license)\n\n</div>\n\n---\n\n## About\n\nModelHub is an open-source platform that unifies access to multiple AI providers (OpenAI, Anthropic, Google, Groq, Mistral, and others) through a single OpenAI-compatible API. It includes a built-in chat interface, secure credential management, and a robust authentication system.\n\n### Features\n\n- **Unified API Gateway** - OpenAI-compatible interface for multiple providers\n- **Built-in Chat** - Modern web interface for interacting with AI models\n- **Secure Authentication** - Complete system with Neon Auth\n- **Credential Management** - Encrypted storage for API keys\n- **Usage Dashboard** - Monitor consumption and costs in real time\n- **Attachment Support** - Upload images, PDFs, and documents\n- **Multi-tenant** - Support for multiple users and organizations\n- **Easy Deploy** - Ready for Vercel, Docker, and other platforms\n- **TypeScript** - Fully typed for better DX\n- **Tested** - Test coverage with Vitest\n\n### Supported Providers\n\n- OpenAI (GPT-4, GPT-3.5, etc.)\n- Anthropic (Claude 3.5, Claude 3, etc.)\n- Google AI (Gemini Pro, Gemini Flash)\n- Groq (Llama, Mixtral)\n- Mistral AI\n- Cohere\n- HuggingFace\n- OpenRouter\n- Vercel AI Gateway\n\n## Installation\n\n### Prerequisites\n\n- Node.js >= 22.0.0\n- pnpm >= 10.0.0\n- [Neon](https://neon.tech) account (serverless PostgreSQL)\n- API keys for the providers you want to use\n\n### Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/actus7/modelhub.git\ncd modelhub\n\n# Install dependencies\npnpm install\n\n# Set up environment variables\ncp .env.example .env\n# Edit .env with your credentials\n\n# Run database migrations\npnpm prisma:migrate\n\n# Start the development server\npnpm dev\n```\n\nVisit http://localhost:3000\n\n### Docker\n\n```bash\ndocker build -t modelhub .\ndocker run -p 3000:3000 --env-file .env modelhub\n```\n\n### Deploy to Vercel\n\n[](https://vercel.com/new/clone?repository-url=https://github.com/actus7/modelhub)\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Quick Start](docs/QUICKSTART.md) | Get up and running in minutes |\n| [API Reference](docs/API.md) | Complete API documentation |\n| [Architecture](docs/ARCHITECTURE.md) | Technical architecture overview |\n| [Deployment](docs/DEPLOYMENT.md) | Deploy guides (Vercel, Docker, VPS) |\n| [Examples](docs/EXAMPLES.md) | Practical usage examples |\n| [FAQ](docs/FAQ.md) | Frequently asked questions |\n\n### API Usage\n\n```bash\ncurl -X POST http://localhost:3000/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"model\": \"gpt-4\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\n## Contributing\n\nContributions are very welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'feat: add AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\nThis project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.\n\n## Security\n\nTo report security vulnerabilities, see [SECURITY.md](SECURITY.md).\n\n## License\n\nThis project is licensed under the MIT License - see [LICENSE](LICENSE) for details.\n\n## Acknowledgements\n\n- [Next.js](https://nextjs.org/) - React Framework\n- [Prisma](https://www.prisma.io/) - ORM\n- [Neon](https://neon.tech/) - PostgreSQL Serverless\n- [shadcn/ui](https://ui.shadcn.com/) - UI Components\n- [Hono](https://hono.dev/) - Web Framework\n\n---\n\n<div align=\"center\">\n\n**[Back to top](#modelhub)**\n\nMade with care by the ModelHub community\n\n</div>\n"}}, "server/lib/routing/tier-suggest.test.ts": {"426bccb40dd31e659550f629c1ff7f983ad0f8fc": {"t": 1786067781.1953983, "n": 7177, "h": "c358cb9d2d79e0d5", "c": "import { beforeEach, describe, expect, it, vi } from \"vitest\"\n\nconst registryMocks = vi.hoisted(() => ({\n getProviderModels: vi.fn(),\n isProviderAvailableViaExternalApi: vi.fn(() => true),\n}))\n\nvi.mock(\"../../providers/registry\", () => ({\n getProviderModels: registryMocks.getProviderModels,\n isProviderAvailableViaExternalApi:\n registryMocks.isProviderAvailableViaExternalApi,\n providerRegistry: {\n anthropic: {},\n groq: {},\n openai: {},\n },\n}))\n\nvi.mock(\"../catalog\", () => ({\n isProviderEnabled: vi.fn(() => true),\n}))\n\nvi.mock(\"../openrouter-pricing\", () => ({\n ensureOpenRouterPricingFresh: vi.fn(),\n getOpenRouterPrice: vi.fn(() => null),\n}))\n\nimport {\n fillLane,\n isChatModel,\n paramBillions,\n pickTiers,\n scoreModel,\n suggestTierAssignments,\n type ModelCandidate,\n} from \"./tier-suggest\"\n\nconst candidate = (\n providerId: string,\n modelId: string,\n overrides: Partial<ModelCandidate> = {},\n): ModelCandidate => ({\n providerId,\n modelId,\n score: 50,\n isReasoning: false,\n outputPer1M: null,\n signals: [],\n ...overrides,\n})\n\nbeforeEach(() => {\n vi.clearAllMocks()\n registryMocks.getProviderModels.mockImplementation(\n async (providerId: string) => {\n if (providerId === \"groq\") {\n return [\n {\n capabilities: { documents: true, images: false },\n id: \"llama-3.1-8b-instant\",\n name: \"Llama 8B\",\n },\n {\n capabilities: { documents: true, images: false },\n id: \"llama-guard-3-8b\",\n name: \"Llama Guard\",\n },\n ]\n }\n if (providerId === \"openai\") {\n return [\n {\n capabilities: { documents: true, images: false },\n id: \"o3\",\n name: \"o3\",\n },\n ]\n }\n return []\n },\n )\n})\n\ndescribe(\"paramBillions\", () => {\n it(\"lê a contagem de parâmetros dos identificadores reais dos catálogos\", () => {\n expect(paramBillions(\"@cf/meta/llama-3.2-3b-instruct\")).toBe(3)\n expect(paramBillions(\"gpt-oss-120b\")).toBe(120)\n expect(paramBillions(\"gemma-4-31b\")).toBe(31)\n expect(paramBillions(\"deepseek-r1-distill-qwen-32b\")).toBe(32)\n })\n\n it(\"ignora sufixos numéricos que não são contagem de parâmetros\", () => {\n // `fp8` não é \"8b\"; `4o` e `4.7` não têm o sufixo b.\n expect(paramBillions(\"llama-3.1-8b-instruct-fp8\")).toBe(8)\n expect(paramBillions(\"gpt-4o\")).toBeNull()\n expect(paramBillions(\"zai-glm-4.7\")).toBeNull()\n })\n})\n\ndescribe(\"isChatModel\", () => {\n it(\"descarta modelos que não atendem chat completions\", () => {\n expect(isChatModel(\"@cf/meta/llama-guard-3-8b\")).toBe(false)\n expect(isChatModel(\"@cf/google/gemma-2b-it-lora\")).toBe(false)\n expect(isChatModel(\"text-embedding-3-large\")).toBe(false)\n expect(isChatModel(\"@cf/openai/whisper\")).toBe(false)\n })\n\n it(\"mantém modelos de chat\", () => {\n expect(isChatModel(\"@cf/meta/llama-3.2-3b-instruct\")).toBe(true)\n expect(isChatModel(\"gpt-oss-120b\")).toBe(true)\n })\n})\n\ndescribe(\"scoreModel\", () => {\n it(\"rankeia por contagem de parâmetros quando o preço é desconhecido\", () => {\n // O caso que quebrava antes: sem preço na tabela, tudo empatava.\n const big = scoreModel(\"cerebras\", \"gpt-oss-120b\").score\n const small = scoreModel(\n \"cloudflare\",\n \"@cf/meta/llama-3.2-1b-instruct\",\n ).score\n expect(big).toBeGreaterThan(small)\n })\n\n it(\"bonifica raciocínio explícito\", () => {\n expect(scoreModel(\"openai\", \"o3-mini\").score).toBeGreaterThan(\n scoreModel(\"openai\", \"gpt-4o-mini\").score,\n )\n expect(scoreModel(\"openai\", \"o3\").isReasoning).toBe(true)\n })\n\n it('não confunde \"pro\" dentro de outra palavra com família topo de linha', () => {\n expect(scoreModel(\"x\", \"prompt-tuned-thing\").signals).toContain(\n \"sem sinal no identificador\",\n )\n })\n\n it(\"explica o motivo do score para o preview\", () => {\n expect(scoreModel(\"cerebras\", \"gpt-oss-120b\").signals).toContain(\n \"120B parâmetros\",\n )\n })\n})\n\ndescribe(\"fillLane\", () => {\n it(\"prioriza providers distintos antes de repetir\", () => {\n const pool = [\n candidate(\"groq\", \"a\"),\n candidate(\"groq\", \"b\"),\n candidate(\"cerebras\", \"c\"),\n ]\n expect(fillLane(pool, 3).map((item) => item.modelId)).toEqual([\n \"a\",\n \"c\",\n \"b\",\n ])\n })\n\n it(\"respeita o limite de vagas\", () => {\n const pool = [candidate(\"a\", \"1\"), candidate(\"b\", \"2\"), candidate(\"c\", \"3\")]\n expect(fillLane(pool, 2)).toHaveLength(2)\n })\n})\n\ndescribe(\"pickTiers\", () => {\n it(\"retorna vazio sem candidatos\", () => {\n expect(pickTiers([])).toEqual({})\n })\n\n it(\"preenche a lane com principal + fallbacks\", () => {\n const candidates = [\n candidate(\"groq\", \"llama-3.1-8b\", { score: 48 }),\n candidate(\"cerebras\", \"gemma-4-31b\", { score: 45 }),\n candidate(\"cloudflare\", \"mistral-7b\", { score: 44 }),\n ]\n expect(pickTiers(candidates, 3).standard).toHaveLength(3)\n })\n\n it(\"coloca o modelo mais capaz da faixa como principal\", () => {\n const candidates = [\n candidate(\"groq\", \"fraco\", { score: 42 }),\n candidate(\"cerebras\", \"forte\", { score: 60 }),\n ]\n expect(pickTiers(candidates, 2).standard?.[0]?.modelId).toBe(\"forte\")\n })\n\n it(\"prefere modelo de raciocínio para reasoning mesmo com score menor\", () => {\n const candidates = [\n candidate(\"deepseek\", \"deepseek-reasoner\", {\n score: 68,\n isReasoning: true,\n }),\n candidate(\"anthropic\", \"claude-opus\", { score: 93 }),\n ]\n const reasoning = pickTiers(candidates, 2).reasoning\n expect(reasoning?.map((slot) => slot.modelId)).toContain(\n \"deepseek-reasoner\",\n )\n })\n\n it(\"usa os candidatos mais próximos quando nenhuma faixa casa\", () => {\n const candidates = [candidate(\"groq\", \"unico\", { score: 50 })]\n const tiers = pickTiers(candidates, 3)\n // Um catálogo de um modelo só preenche todas as lanes com ele.\n expect(tiers.simple?.[0]?.modelId).toBe(\"unico\")\n expect(tiers.reasoning?.[0]?.modelId).toBe(\"unico\")\n })\n})\n\ndescribe(\"suggestTierAssignments\", () => {\n it(\"sugere tiers apenas a partir das fontes configuradas\", async () => {\n const tiers = await suggestTierAssignments({\n sources: [\n {\n cacheKeySuffix: \"user-1:groq\",\n credentials: { GROQ_API_KEY: \"sk-test\" },\n providerId: \"groq\",\n },\n ],\n })\n\n expect(registryMocks.getProviderModels).toHaveBeenCalledTimes(1)\n expect(registryMocks.getProviderModels).toHaveBeenCalledWith(\"groq\", {\n cacheKeySuffix: \"user-1:groq\",\n credentials: { GROQ_API_KEY: \"sk-test\" },\n })\n const slots = Object.values(tiers).flat()\n expect(slots.length).toBeGreaterThan(0)\n expect(slots.every((slot) => slot?.providerId === \"groq\")).toBe(true)\n })\n\n it(\"nunca sugere um modelo que não é de chat\", async () => {\n const tiers = await suggestTierAssignments({\n sources: [\n { cacheKeySuffix: \"user-1:groq\", credentials: {}, providerId: \"groq\" },\n ],\n })\n\n const modelIds = Object.values(tiers)\n .flat()\n .map((slot) => slot?.modelId)\n expect(modelIds).not.toContain(\"llama-guard-3-8b\")\n })\n})\n"}, "f64f3527c540ab16f2772ada41dec64216c3ad18": {"t": 1786068448.517296, "n": 7177, "h": "c358cb9d2d79e0d5", "c": "import { beforeEach, describe, expect, it, vi } from \"vitest\"\n\nconst registryMocks = vi.hoisted(() => ({\n getProviderModels: vi.fn(),\n isProviderAvailableViaExternalApi: vi.fn(() => true),\n}))\n\nvi.mock(\"../../providers/registry\", () => ({\n getProviderModels: registryMocks.getProviderModels,\n isProviderAvailableViaExternalApi:\n registryMocks.isProviderAvailableViaExternalApi,\n providerRegistry: {\n anthropic: {},\n groq: {},\n openai: {},\n },\n}))\n\nvi.mock(\"../catalog\", () => ({\n isProviderEnabled: vi.fn(() => true),\n}))\n\nvi.mock(\"../openrouter-pricing\", () => ({\n ensureOpenRouterPricingFresh: vi.fn(),\n getOpenRouterPrice: vi.fn(() => null),\n}))\n\nimport {\n fillLane,\n isChatModel,\n paramBillions,\n pickTiers,\n scoreModel,\n suggestTierAssignments,\n type ModelCandidate,\n} from \"./tier-suggest\"\n\nconst candidate = (\n providerId: string,\n modelId: string,\n overrides: Partial<ModelCandidate> = {},\n): ModelCandidate => ({\n providerId,\n modelId,\n score: 50,\n isReasoning: false,\n outputPer1M: null,\n signals: [],\n ...overrides,\n})\n\nbeforeEach(() => {\n vi.clearAllMocks()\n registryMocks.getProviderModels.mockImplementation(\n async (providerId: string) => {\n if (providerId === \"groq\") {\n return [\n {\n capabilities: { documents: true, images: false },\n id: \"llama-3.1-8b-instant\",\n name: \"Llama 8B\",\n },\n {\n capabilities: { documents: true, images: false },\n id: \"llama-guard-3-8b\",\n name: \"Llama Guard\",\n },\n ]\n }\n if (providerId === \"openai\") {\n return [\n {\n capabilities: { documents: true, images: false },\n id: \"o3\",\n name: \"o3\",\n },\n ]\n }\n return []\n },\n )\n})\n\ndescribe(\"paramBillions\", () => {\n it(\"lê a contagem de parâmetros dos identificadores reais dos catálogos\", () => {\n expect(paramBillions(\"@cf/meta/llama-3.2-3b-instruct\")).toBe(3)\n expect(paramBillions(\"gpt-oss-120b\")).toBe(120)\n expect(paramBillions(\"gemma-4-31b\")).toBe(31)\n expect(paramBillions(\"deepseek-r1-distill-qwen-32b\")).toBe(32)\n })\n\n it(\"ignora sufixos numéricos que não são contagem de parâmetros\", () => {\n // `fp8` não é \"8b\"; `4o` e `4.7` não têm o sufixo b.\n expect(paramBillions(\"llama-3.1-8b-instruct-fp8\")).toBe(8)\n expect(paramBillions(\"gpt-4o\")).toBeNull()\n expect(paramBillions(\"zai-glm-4.7\")).toBeNull()\n })\n})\n\ndescribe(\"isChatModel\", () => {\n it(\"descarta modelos que não atendem chat completions\", () => {\n expect(isChatModel(\"@cf/meta/llama-guard-3-8b\")).toBe(false)\n expect(isChatModel(\"@cf/google/gemma-2b-it-lora\")).toBe(false)\n expect(isChatModel(\"text-embedding-3-large\")).toBe(false)\n expect(isChatModel(\"@cf/openai/whisper\")).toBe(false)\n })\n\n it(\"mantém modelos de chat\", () => {\n expect(isChatModel(\"@cf/meta/llama-3.2-3b-instruct\")).toBe(true)\n expect(isChatModel(\"gpt-oss-120b\")).toBe(true)\n })\n})\n\ndescribe(\"scoreModel\", () => {\n it(\"rankeia por contagem de parâmetros quando o preço é desconhecido\", () => {\n // O caso que quebrava antes: sem preço na tabela, tudo empatava.\n const big = scoreModel(\"cerebras\", \"gpt-oss-120b\").score\n const small = scoreModel(\n \"cloudflare\",\n \"@cf/meta/llama-3.2-1b-instruct\",\n ).score\n expect(big).toBeGreaterThan(small)\n })\n\n it(\"bonifica raciocínio explícito\", () => {\n expect(scoreModel(\"openai\", \"o3-mini\").score).toBeGreaterThan(\n scoreModel(\"openai\", \"gpt-4o-mini\").score,\n )\n expect(scoreModel(\"openai\", \"o3\").isReasoning).toBe(true)\n })\n\n it('não confunde \"pro\" dentro de outra palavra com família topo de linha', () => {\n expect(scoreModel(\"x\", \"prompt-tuned-thing\").signals).toContain(\n \"sem sinal no identificador\",\n )\n })\n\n it(\"explica o motivo do score para o preview\", () => {\n expect(scoreModel(\"cerebras\", \"gpt-oss-120b\").signals).toContain(\n \"120B parâmetros\",\n )\n })\n})\n\ndescribe(\"fillLane\", () => {\n it(\"prioriza providers distintos antes de repetir\", () => {\n const pool = [\n candidate(\"groq\", \"a\"),\n candidate(\"groq\", \"b\"),\n candidate(\"cerebras\", \"c\"),\n ]\n expect(fillLane(pool, 3).map((item) => item.modelId)).toEqual([\n \"a\",\n \"c\",\n \"b\",\n ])\n })\n\n it(\"respeita o limite de vagas\", () => {\n const pool = [candidate(\"a\", \"1\"), candidate(\"b\", \"2\"), candidate(\"c\", \"3\")]\n expect(fillLane(pool, 2)).toHaveLength(2)\n })\n})\n\ndescribe(\"pickTiers\", () => {\n it(\"retorna vazio sem candidatos\", () => {\n expect(pickTiers([])).toEqual({})\n })\n\n it(\"preenche a lane com principal + fallbacks\", () => {\n const candidates = [\n candidate(\"groq\", \"llama-3.1-8b\", { score: 48 }),\n candidate(\"cerebras\", \"gemma-4-31b\", { score: 45 }),\n candidate(\"cloudflare\", \"mistral-7b\", { score: 44 }),\n ]\n expect(pickTiers(candidates, 3).standard).toHaveLength(3)\n })\n\n it(\"coloca o modelo mais capaz da faixa como principal\", () => {\n const candidates = [\n candidate(\"groq\", \"fraco\", { score: 42 }),\n candidate(\"cerebras\", \"forte\", { score: 60 }),\n ]\n expect(pickTiers(candidates, 2).standard?.[0]?.modelId).toBe(\"forte\")\n })\n\n it(\"prefere modelo de raciocínio para reasoning mesmo com score menor\", () => {\n const candidates = [\n candidate(\"deepseek\", \"deepseek-reasoner\", {\n score: 68,\n isReasoning: true,\n }),\n candidate(\"anthropic\", \"claude-opus\", { score: 93 }),\n ]\n const reasoning = pickTiers(candidates, 2).reasoning\n expect(reasoning?.map((slot) => slot.modelId)).toContain(\n \"deepseek-reasoner\",\n )\n })\n\n it(\"usa os candidatos mais próximos quando nenhuma faixa casa\", () => {\n const candidates = [candidate(\"groq\", \"unico\", { score: 50 })]\n const tiers = pickTiers(candidates, 3)\n // Um catálogo de um modelo só preenche todas as lanes com ele.\n expect(tiers.simple?.[0]?.modelId).toBe(\"unico\")\n expect(tiers.reasoning?.[0]?.modelId).toBe(\"unico\")\n })\n})\n\ndescribe(\"suggestTierAssignments\", () => {\n it(\"sugere tiers apenas a partir das fontes configuradas\", async () => {\n const tiers = await suggestTierAssignments({\n sources: [\n {\n cacheKeySuffix: \"user-1:groq\",\n credentials: { GROQ_API_KEY: \"sk-test\" },\n providerId: \"groq\",\n },\n ],\n })\n\n expect(registryMocks.getProviderModels).toHaveBeenCalledTimes(1)\n expect(registryMocks.getProviderModels).toHaveBeenCalledWith(\"groq\", {\n cacheKeySuffix: \"user-1:groq\",\n credentials: { GROQ_API_KEY: \"sk-test\" },\n })\n const slots = Object.values(tiers).flat()\n expect(slots.length).toBeGreaterThan(0)\n expect(slots.every((slot) => slot?.providerId === \"groq\")).toBe(true)\n })\n\n it(\"nunca sugere um modelo que não é de chat\", async () => {\n const tiers = await suggestTierAssignments({\n sources: [\n { cacheKeySuffix: \"user-1:groq\", credentials: {}, providerId: \"groq\" },\n ],\n })\n\n const modelIds = Object.values(tiers)\n .flat()\n .map((slot) => slot?.modelId)\n expect(modelIds).not.toContain(\"llama-guard-3-8b\")\n })\n})\n"}}}} |