fix: let people do negative markups for free models

This commit is contained in:
Ridhwan Hussain
2026-06-10 15:46:14 +01:00
parent ba6e9c6a02
commit d5e5cfc5ff
5 changed files with 15 additions and 11 deletions

View File

@@ -80,9 +80,10 @@ export const validateCreditSystem = (
const defaultMarkup = newConfig.default_markup;
if (defaultMarkup != null) {
const parsedDefaultMarkup = Number(defaultMarkup);
if (Number.isNaN(parsedDefaultMarkup) || parsedDefaultMarkup < 0) {
if (Number.isNaN(parsedDefaultMarkup) || parsedDefaultMarkup < -100) {
throw new RecaseError({
message: "Default markup should be a non-negative number",
message:
"Default markup must be -100 or greater (-100 makes usage free)",
code: ErrCode.InvalidFeature,
statusCode: 400,
});
@@ -94,9 +95,10 @@ export const validateCreditSystem = (
if (providerMarkups != null) {
for (const [provider, entry] of Object.entries(providerMarkups)) {
const markup = Number(entry?.markup);
if (!provider || Number.isNaN(markup) || markup < 0) {
if (!provider || Number.isNaN(markup) || markup < -100) {
throw new RecaseError({
message: "Provider markups must be non-negative numbers",
message:
"Provider markups must be -100 or greater (-100 makes usage free)",
code: ErrCode.InvalidFeature,
statusCode: 400,
});

View File

@@ -50,8 +50,9 @@ export const ApiFeatureV1Schema = z.object({
description: "Per-model markup overrides for AI credit systems.",
}),
default_markup: z.number().min(0).optional().meta({
description: "Default percentage markup for AI credit systems.",
default_markup: z.number().min(-100).optional().meta({
description:
"Default percentage markup for AI credit systems. Use -100 to make usage free.",
}),
provider_markups: ProviderMarkupsSchema.optional().meta({

View File

@@ -55,9 +55,9 @@ export const BaseFeatureV1ParamsSchema = z.object({
"Per-model markup overrides for AI credit systems. Maps model IDs to their markup configuration.",
}),
default_markup: z.number().min(0).optional().meta({
default_markup: z.number().min(-100).optional().meta({
description:
"Default percentage markup for this AI credit system. Used when no model or provider markup applies.",
"Default percentage markup for this AI credit system. Used when no model or provider markup applies. Use -100 to make usage free.",
}),
provider_markups: ProviderMarkupsSchema.optional().meta({

View File

@@ -0,0 +1 @@
ALTER TABLE "features" ADD COLUMN "model_markups" jsonb DEFAULT null;

View File

@@ -8,7 +8,7 @@ export const CreditSchemaItemSchema = z.object({
});
const MarkupEntrySchema = z.object({
markup: z.number().min(0), // percentage markup, e.g. 20 for 20%
markup: z.number().min(-100), // percentage markup, e.g. 20 for 20%, -100 for free
});
export const ProviderMarkupsSchema = z
@@ -26,7 +26,7 @@ export const CreditSystemConfigSchema = z.object({
}),
),
usage_type: z.nativeEnum(FeatureUsageType),
default_markup: z.number().min(0).optional(),
default_markup: z.number().min(-100).optional(),
provider_markups: ProviderMarkupsSchema,
});
@@ -34,7 +34,7 @@ export const ModelMarkupsSchema = z
.record(
z.string(), // Represents the model name in "provider/model" format, e.g. "anthropic/claude-2"
MarkupEntrySchema.extend({
markup: z.number().min(0).optional(), // Omit to inherit provider/global markup
markup: z.number().min(-100).optional(), // Omit to inherit provider/global markup
input_cost: z.number().min(0).optional(), // $/M tokens, required for custom/ models
output_cost: z.number().min(0).optional(), // $/M tokens, required for custom/ models
}),