fix: limit open router expensive models for now (#2407)

* fix: limit open router expensive models for now

* fix: import extension
This commit is contained in:
Daniel Salazar
2026-02-03 14:43:15 -08:00
committed by GitHub
parent 665aee735b
commit e938d5183a
5 changed files with 31 additions and 3 deletions
+2 -2
View File
@@ -4,8 +4,8 @@
"admin"
],
"allowedGlobalUsageUsers": [
"06ab2f87-aef5-441b-9c60-debbb8d24dda",
"d8fd169b-4e93-484a-bd84-115b5a2f0ed4"
"nj",
"salazareos"
],
"priority": 10
}
@@ -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;
@@ -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;
@@ -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,
];
@@ -15,6 +15,8 @@ export interface IChatModel<T extends ModelCost = ModelCost> extends Record<stri
costs: T,
context?: number,
max_tokens: number,
subscriberOnly?: boolean,
minimumCredits?: number,
}
export type PuterMessage = Message | any; // TODO DS: type this more strictly