mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-02 13:22:11 +03:00
New free providers: - LongCat AI (lc/): 50M tokens/day free during public beta - Pollinations AI (pol/): no API key needed, GPT-5/Claude/DeepSeek/Llama free - Cloudflare Workers AI (cf/): 10K Neurons/day, ~150 LLM responses, Whisper free - Scaleway AI (scw/): 1M free tokens for new accounts (EU/GDPR, Paris) - AI/ML API (aiml/): $0.025/day credits, 200+ models via single endpoint Provider metadata updates: - Together AI: hasFree=true + 3 permanently free model IDs (Llama 70B, Vision, DeepSeek) - Gemini: hasFree=true + freeNote (1,500 req/day free, no credit card) - NVIDIA NIM: already had hasFree=true, confirmed correct New executors: - open-sse/executors/pollinations.ts: optional auth (no key support) - open-sse/executors/cloudflare-ai.ts: dynamic URL with accountId credential Documentation: - README.md: 11-provider Ultimate Free Stack, 4 new pricing table rows - README.md: LongCat/Pollinations/Cloudflare AI/Scaleway provider detail sections - docs/i18n/pt-BR/README.md: updated pricing table + 4 new free provider sections - docs/i18n/cs/README.md: combo stack updated Tests: 821/821 pass (no regressions)
60 lines
2.1 KiB
TypeScript
60 lines
2.1 KiB
TypeScript
import { BaseExecutor } from "./base.ts";
|
|
import { PROVIDERS } from "../config/constants.ts";
|
|
|
|
/**
|
|
* CloudflareAIExecutor — handles dynamic URL construction with accountId.
|
|
* Cloudflare Workers AI uses the authenticated user's account ID in the URL.
|
|
*
|
|
* URL pattern: https://api.cloudflare.com/client/v4/accounts/{accountId}/ai/v1/chat/completions
|
|
* Auth: Bearer <API Token>
|
|
* Docs: https://developers.cloudflare.com/workers-ai/
|
|
*
|
|
* Free tier: 10,000 Neurons/day = ~150 LLM responses or 500s Whisper audio
|
|
* API Token: dash.cloudflare.com/profile/api-tokens
|
|
* Account ID: right sidebar of dash.cloudflare.com
|
|
*/
|
|
export class CloudflareAIExecutor extends BaseExecutor {
|
|
constructor() {
|
|
super("cloudflare-ai", PROVIDERS["cloudflare-ai"] || { format: "openai" });
|
|
}
|
|
|
|
buildUrl(_model: string, _stream: boolean, _urlIndex = 0, credentials: any = null): string {
|
|
// Account ID can be stored in providerSpecificData or at top level credentials
|
|
const accountId =
|
|
credentials?.providerSpecificData?.accountId ||
|
|
credentials?.accountId ||
|
|
process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
|
|
if (!accountId) {
|
|
throw new Error(
|
|
"Cloudflare Workers AI requires an Account ID. " +
|
|
"Add it in provider settings under 'Account ID'. " +
|
|
"Find it at: https://dash.cloudflare.com (right sidebar)."
|
|
);
|
|
}
|
|
|
|
return `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1/chat/completions`;
|
|
}
|
|
|
|
buildHeaders(credentials: any, stream = true): Record<string, string> {
|
|
const headers: Record<string, string> = {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${credentials.apiKey || credentials.accessToken}`,
|
|
};
|
|
|
|
if (stream) {
|
|
headers["Accept"] = "text/event-stream";
|
|
}
|
|
|
|
return headers;
|
|
}
|
|
|
|
transformRequest(_model: string, body: any, _stream: boolean, _credentials: any): any {
|
|
// Cloudflare uses full model paths like @cf/meta/llama-3.3-70b-instruct
|
|
// No transformation needed — user sends the full Cloudflare model path.
|
|
return body;
|
|
}
|
|
}
|
|
|
|
export default CloudflareAIExecutor;
|