diff --git a/extensions/metering/config.json b/extensions/metering/config.json index 1624a4ee3..1f5505941 100644 --- a/extensions/metering/config.json +++ b/extensions/metering/config.json @@ -4,8 +4,8 @@ "admin" ], "allowedGlobalUsageUsers": [ - "06ab2f87-aef5-441b-9c60-debbb8d24dda", - "d8fd169b-4e93-484a-bd84-115b5a2f0ed4" + "nj", + "salazareos" ], "priority": 10 } \ No newline at end of file diff --git a/src/backend/src/services/ai/chat/AIChatService.ts b/src/backend/src/services/ai/chat/AIChatService.ts index ab2169c29..d9adac325 100644 --- a/src/backend/src/services/ai/chat/AIChatService.ts +++ b/src/backend/src/services/ai/chat/AIChatService.ts @@ -372,13 +372,26 @@ export class AIChatService extends BaseService { const text = extract_text(parameters.messages); const approximateTokenCount = Math.floor(((text.length / 4) + (text.split(/\s+/).length * (4 / 3))) / 2); // see https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them const approximateInputCost = approximateTokenCount * inputTokenCost; - const usageAllowed = await this.meteringService.hasEnoughCredits(actor, approximateInputCost); + const minimumCredits = model.minimumCredits || 0; + const usageAllowed = await this.meteringService.hasEnoughCredits(actor, Math.max(approximateInputCost, minimumCredits)); // Handle usage limits reached case if ( ! usageAllowed ) { model = usageLimitedModel; } + // block non subscriber only models for non-subscribers + if ( model.subscriberOnly ) { + const eventObject = { actor, userSubscriptionId: '' }; + await this.eventService.emit('metering:getUserSubscription', eventObject); + if ( ! eventObject.userSubscriptionId ) { + //TODO DS: register checker events when we add more of these exclusions + throw APIError.create('permission_denied', undefined, { + message: `The model ${model.id} is only available to subscribers. Please subscribe to access this model.`, + }); + } + } + const availableCredits = await this.meteringService.getRemainingUsage(actor); const maxAllowedOutput = availableCredits - approximateInputCost; diff --git a/src/backend/src/services/ai/chat/providers/OpenRouterProvider/OpenRouterProvider.ts b/src/backend/src/services/ai/chat/providers/OpenRouterProvider/OpenRouterProvider.ts index 6168f8165..dd71ea068 100644 --- a/src/backend/src/services/ai/chat/providers/OpenRouterProvider/OpenRouterProvider.ts +++ b/src/backend/src/services/ai/chat/providers/OpenRouterProvider/OpenRouterProvider.ts @@ -26,6 +26,7 @@ import { kv } from '../../../../../util/kvSingleton.js'; import { MeteringService } from '../../../../MeteringService/MeteringService.js'; import * as OpenAIUtil from '../../../utils/OpenAIUtil.js'; import { IChatModel, IChatProvider } from '../types.js'; +import { OPEN_ROUTER_MODEL_OVERRIDES } from './modelOverrides.js'; export class OpenRouterProvider implements IChatProvider { @@ -154,6 +155,7 @@ export class OpenRouterProvider implements IChatProvider { if ( (model.id as string).includes('openrouter/auto') ) { continue; } + const overridenModel = OPEN_ROUTER_MODEL_OVERRIDES.find(m => m.id === `openrouter:${model.id}`); const microcentCosts = Object.fromEntries(Object.entries(model.pricing).map(([k, v]) => [k, Math.round((v as number < 0 ? 1 : v as number) * 1_000_000 * 100)])) ; coerced_models.push({ id: `openrouter:${model.id}`, @@ -167,6 +169,7 @@ export class OpenRouterProvider implements IChatProvider { tokens: 1_000_000, ...microcentCosts, }, + ...overridenModel, }); } return coerced_models; diff --git a/src/backend/src/services/ai/chat/providers/OpenRouterProvider/modelOverrides.ts b/src/backend/src/services/ai/chat/providers/OpenRouterProvider/modelOverrides.ts new file mode 100644 index 000000000..4d36dedc3 --- /dev/null +++ b/src/backend/src/services/ai/chat/providers/OpenRouterProvider/modelOverrides.ts @@ -0,0 +1,10 @@ +import { toMicroCents } from '../../../../MeteringService/utils.js'; +import { IChatModel } from '../types'; + +export const OPEN_ROUTER_MODEL_OVERRIDES: IChatModel[] = [ + { + id: 'openrouter:perplexity/sonar-deep-research', + subscriberOnly: true, + minimumCredits: toMicroCents(2), + } as IChatModel, +]; \ No newline at end of file diff --git a/src/backend/src/services/ai/chat/providers/types.ts b/src/backend/src/services/ai/chat/providers/types.ts index d63d13a29..a1ec3e2dc 100644 --- a/src/backend/src/services/ai/chat/providers/types.ts +++ b/src/backend/src/services/ai/chat/providers/types.ts @@ -15,6 +15,8 @@ export interface IChatModel extends Record