From 7a9553f21503d6820c997886cf397d340f638e11 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 22:02:43 +0000 Subject: [PATCH 1/7] feat(models): restrict trinity thinking free to kiloclaw and openclaw Add exclusive_to field to KiloExclusiveModel to restrict model access by feature. Set exclusive_to ['kiloclaw', 'openclaw'] for trinity large thinking free. Filter excluded models from /models endpoints when feature header is set. Block proxy requests with 403 when feature does not match, suggesting kilo-auto/free as an alternative. --- apps/web/src/app/api/openrouter/[...path]/route.ts | 9 +++++++++ apps/web/src/app/api/openrouter/models/route.ts | 13 ++++++++++--- .../src/app/api/organizations/[id]/models/route.ts | 9 ++++++++- apps/web/src/lib/llm-proxy-helpers.ts | 5 +++++ apps/web/src/lib/models.ts | 14 ++++++++++++++ apps/web/src/lib/providers/arcee.ts | 1 + apps/web/src/lib/providers/kilo-exclusive-model.ts | 3 +++ 7 files changed, 50 insertions(+), 4 deletions(-) diff --git a/apps/web/src/app/api/openrouter/[...path]/route.ts b/apps/web/src/app/api/openrouter/[...path]/route.ts index 4e8c1452a..0340454ba 100644 --- a/apps/web/src/app/api/openrouter/[...path]/route.ts +++ b/apps/web/src/app/api/openrouter/[...path]/route.ts @@ -23,6 +23,7 @@ import { sentryRootSpan } from '@/lib/getRootSpan'; import { isFreeModel, isDeadFreeModel, + isExcludedForFeature, isKiloExclusiveFreeModel, isKiloStealthModel, } from '@/lib/models'; @@ -32,6 +33,7 @@ import { checkOrganizationModelRestrictions, dataCollectionRequiredResponse, extractFraudAndProjectHeaders, + featureExclusiveModelResponse, invalidPathResponse, invalidRequestResponse, makeErrorReadable, @@ -383,6 +385,13 @@ export async function POST(request: NextRequest): Promise getDirectByokModelsForUser(userId), @@ -28,15 +30,19 @@ async function tryGetUserFromAuth() { * curl -vvv 'http://localhost:3000/api/openrouter/models' */ export async function GET( - _request: NextRequest + request: NextRequest ): Promise> { + const feature = validateFeatureHeader(request.headers.get(FEATURE_HEADER)); const auth = await tryGetUserFromAuth(); try { const result = auth?.organizationId ? await getAvailableModelsForOrganization(auth.organizationId) : null; if (result) { - return NextResponse.json(result); + return NextResponse.json({ + ...result, + data: result.data.filter(m => !isExcludedForFeature(m.id, feature)), + }); } const data = await getEnhancedOpenRouterModels(); @@ -44,7 +50,8 @@ export async function GET( return NextResponse.json(data); } const byokModels = auth?.user ? await getDirectByokModels(auth.user.id) : []; - return NextResponse.json({ data: data.data.concat(byokModels) }); + const allModels = data.data.concat(byokModels).filter(m => !isExcludedForFeature(m.id, feature)); + return NextResponse.json({ data: allModels }); } catch (error) { captureException(error, { tags: { endpoint: 'openrouter/models' }, diff --git a/apps/web/src/app/api/organizations/[id]/models/route.ts b/apps/web/src/app/api/organizations/[id]/models/route.ts index 295f785a1..d65a93b75 100644 --- a/apps/web/src/app/api/organizations/[id]/models/route.ts +++ b/apps/web/src/app/api/organizations/[id]/models/route.ts @@ -1,11 +1,18 @@ import type { NextRequest } from 'next/server'; import type { OpenRouterModelsResponse } from '@/lib/organizations/organization-types'; import { handleTRPCRequest } from '@/lib/trpc-route-handler'; +import { FEATURE_HEADER, validateFeatureHeader } from '@/lib/feature-detection'; +import { isExcludedForFeature } from '@/lib/models'; export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { const organizationId = (await params).id; + const feature = validateFeatureHeader(request.headers.get(FEATURE_HEADER)); return handleTRPCRequest(request, async caller => { - return caller.organizations.settings.listAvailableModels({ organizationId }); + const result = await caller.organizations.settings.listAvailableModels({ organizationId }); + return { + ...result, + data: result.data.filter(m => !isExcludedForFeature(m.id, feature)), + }; }); } diff --git a/apps/web/src/lib/llm-proxy-helpers.ts b/apps/web/src/lib/llm-proxy-helpers.ts index 011039a72..46632ae44 100644 --- a/apps/web/src/lib/llm-proxy-helpers.ts +++ b/apps/web/src/lib/llm-proxy-helpers.ts @@ -263,6 +263,11 @@ export function modelDoesNotExistResponse() { ); } +export function featureExclusiveModelResponse() { + const error = `This model is only available in KiloClaw and OpenClaw. Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; + return NextResponse.json({ error, message: error }, { status: 403 }); +} + export function storeAndPreviousResponseIdIsNotSupported() { const error = 'The store and previous_response_id fields are not supported.'; return NextResponse.json({ error, message: error }, { status: 400 }); diff --git a/apps/web/src/lib/models.ts b/apps/web/src/lib/models.ts index 7a485c903..c9f6eaad2 100644 --- a/apps/web/src/lib/models.ts +++ b/apps/web/src/lib/models.ts @@ -2,6 +2,7 @@ * Utility functions for working with AI models */ +import type { FeatureValue } from '@/lib/feature-detection'; import { KILO_AUTO_BALANCED_MODEL, KILO_AUTO_FREE_MODEL, @@ -91,3 +92,16 @@ export function isDeadFreeModel(model: string): boolean { export function findKiloExclusiveModel(model: string): KiloExclusiveModel | null { return kiloExclusiveModels.find(m => m.public_id === model && m.status !== 'disabled') ?? null; } + +/** + * Returns true if the model should be excluded from results for the given feature. + * A model is excluded when it has an `exclusive_to` restriction, the feature is known, + * and the feature is not in `exclusive_to`. + * When feature is null (no header sent), the model is always included. + */ +export function isExcludedForFeature(modelId: string, feature: FeatureValue | null): boolean { + const model = kiloExclusiveModels.find(m => m.public_id === modelId); + if (!model?.exclusive_to?.length) return false; + if (!feature) return false; + return !model.exclusive_to.includes(feature); +} diff --git a/apps/web/src/lib/providers/arcee.ts b/apps/web/src/lib/providers/arcee.ts index 3dc740e92..b73a0fc48 100644 --- a/apps/web/src/lib/providers/arcee.ts +++ b/apps/web/src/lib/providers/arcee.ts @@ -13,4 +13,5 @@ export const trinity_large_thinking_free_model: KiloExclusiveModel = { internal_id: 'arcee-ai/trinity-large-thinking', inference_provider: 'arcee-ai', pricing: null, + exclusive_to: ['kiloclaw', 'openclaw'], }; diff --git a/apps/web/src/lib/providers/kilo-exclusive-model.ts b/apps/web/src/lib/providers/kilo-exclusive-model.ts index e6a1361c4..3056273ae 100644 --- a/apps/web/src/lib/providers/kilo-exclusive-model.ts +++ b/apps/web/src/lib/providers/kilo-exclusive-model.ts @@ -1,3 +1,4 @@ +import type { FeatureValue } from '@/lib/feature-detection'; import type { OpenRouterInferenceProviderId } from '@/lib/providers/openrouter/inference-provider-id'; import type { ProviderId } from '@/lib/providers/types'; @@ -30,6 +31,8 @@ export type KiloExclusiveModel = { internal_id: string; inference_provider: OpenRouterInferenceProviderId | null; pricing: Pricing | null; + /** If set, only requests from these features are allowed to use this model. */ + exclusive_to?: ReadonlyArray; }; function formatPricePerMillionAsPerToken(price: number): string; From 8b87896fef56519c16c1d6fd23559b3509cd103b Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 22:07:00 +0000 Subject: [PATCH 2/7] style: fix oxfmt formatting in models route --- apps/web/src/app/api/openrouter/models/route.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/app/api/openrouter/models/route.ts b/apps/web/src/app/api/openrouter/models/route.ts index d691c34b9..e1b42acbe 100644 --- a/apps/web/src/app/api/openrouter/models/route.ts +++ b/apps/web/src/app/api/openrouter/models/route.ts @@ -50,7 +50,9 @@ export async function GET( return NextResponse.json(data); } const byokModels = auth?.user ? await getDirectByokModels(auth.user.id) : []; - const allModels = data.data.concat(byokModels).filter(m => !isExcludedForFeature(m.id, feature)); + const allModels = data.data + .concat(byokModels) + .filter(m => !isExcludedForFeature(m.id, feature)); return NextResponse.json({ data: allModels }); } catch (error) { captureException(error, { From 4f114680b94c241436f62025dc04889c054cf702 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 22:13:59 +0000 Subject: [PATCH 3/7] fix: move feature exclusivity check before rate limiting --- .../web/src/app/api/openrouter/[...path]/route.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/web/src/app/api/openrouter/[...path]/route.ts b/apps/web/src/app/api/openrouter/[...path]/route.ts index 0340454ba..66cb0048e 100644 --- a/apps/web/src/app/api/openrouter/[...path]/route.ts +++ b/apps/web/src/app/api/openrouter/[...path]/route.ts @@ -229,6 +229,14 @@ export async function POST(request: NextRequest): Promise Date: Tue, 14 Apr 2026 08:25:35 +0000 Subject: [PATCH 4/7] refactor(models): exclusive_to required, add filterByFeature helper, interpolate features in error - Make exclusive_to non-optional on KiloExclusiveModel (empty array = no restriction); add exclusive_to: [] to all existing model definitions - Extract filterByFeature() helper to replace repeated inline filter expressions - Pass exclusive_to values to featureExclusiveModelResponse so the error message interpolates the allowed feature names instead of hard-coding them --- apps/web/src/app/api/openrouter/[...path]/route.ts | 5 ++++- apps/web/src/app/api/openrouter/models/route.ts | 9 +++------ .../src/app/api/organizations/[id]/models/route.ts | 7 ++----- apps/web/src/lib/llm-proxy-helpers.ts | 4 ++-- apps/web/src/lib/models.ts | 14 +++++++++++--- apps/web/src/lib/providers/anthropic.constants.ts | 1 + apps/web/src/lib/providers/bytedance.ts | 1 + apps/web/src/lib/providers/kilo-exclusive-model.ts | 4 ++-- apps/web/src/lib/providers/minimax.ts | 1 + apps/web/src/lib/providers/morph.ts | 1 + apps/web/src/lib/providers/openai.ts | 1 + apps/web/src/lib/providers/qwen.ts | 1 + apps/web/src/lib/providers/stepfun.ts | 1 + apps/web/src/lib/providers/xai.ts | 1 + 14 files changed, 32 insertions(+), 19 deletions(-) diff --git a/apps/web/src/app/api/openrouter/[...path]/route.ts b/apps/web/src/app/api/openrouter/[...path]/route.ts index 66cb0048e..165f2ae8b 100644 --- a/apps/web/src/app/api/openrouter/[...path]/route.ts +++ b/apps/web/src/app/api/openrouter/[...path]/route.ts @@ -26,6 +26,7 @@ import { isExcludedForFeature, isKiloExclusiveFreeModel, isKiloStealthModel, + kiloExclusiveModels, } from '@/lib/models'; import { accountForMicrodollarUsage, @@ -234,7 +235,9 @@ export async function POST(request: NextRequest): Promise m.public_id === originalModelIdLowerCased)?.exclusive_to ?? []; + return featureExclusiveModelResponse(exclusiveTo); } // Extract IP for all requests (needed for free model rate limiting) diff --git a/apps/web/src/app/api/openrouter/models/route.ts b/apps/web/src/app/api/openrouter/models/route.ts index e1b42acbe..ec6e6e7ee 100644 --- a/apps/web/src/app/api/openrouter/models/route.ts +++ b/apps/web/src/app/api/openrouter/models/route.ts @@ -8,7 +8,7 @@ import { getDirectByokModelsForUser } from '@/lib/providers/direct-byok'; import { unstable_cache } from 'next/cache'; import { getAvailableModelsForOrganization } from '@/lib/organizations/organization-models'; import { FEATURE_HEADER, validateFeatureHeader } from '@/lib/feature-detection'; -import { isExcludedForFeature } from '@/lib/models'; +import { filterByFeature } from '@/lib/models'; const getDirectByokModels = unstable_cache( (userId: string) => getDirectByokModelsForUser(userId), @@ -41,7 +41,7 @@ export async function GET( if (result) { return NextResponse.json({ ...result, - data: result.data.filter(m => !isExcludedForFeature(m.id, feature)), + data: filterByFeature(result.data, feature), }); } @@ -50,10 +50,7 @@ export async function GET( return NextResponse.json(data); } const byokModels = auth?.user ? await getDirectByokModels(auth.user.id) : []; - const allModels = data.data - .concat(byokModels) - .filter(m => !isExcludedForFeature(m.id, feature)); - return NextResponse.json({ data: allModels }); + return NextResponse.json({ data: filterByFeature(data.data.concat(byokModels), feature) }); } catch (error) { captureException(error, { tags: { endpoint: 'openrouter/models' }, diff --git a/apps/web/src/app/api/organizations/[id]/models/route.ts b/apps/web/src/app/api/organizations/[id]/models/route.ts index d65a93b75..cbeea6729 100644 --- a/apps/web/src/app/api/organizations/[id]/models/route.ts +++ b/apps/web/src/app/api/organizations/[id]/models/route.ts @@ -2,7 +2,7 @@ import type { NextRequest } from 'next/server'; import type { OpenRouterModelsResponse } from '@/lib/organizations/organization-types'; import { handleTRPCRequest } from '@/lib/trpc-route-handler'; import { FEATURE_HEADER, validateFeatureHeader } from '@/lib/feature-detection'; -import { isExcludedForFeature } from '@/lib/models'; +import { filterByFeature } from '@/lib/models'; export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { const organizationId = (await params).id; @@ -10,9 +10,6 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{ return handleTRPCRequest(request, async caller => { const result = await caller.organizations.settings.listAvailableModels({ organizationId }); - return { - ...result, - data: result.data.filter(m => !isExcludedForFeature(m.id, feature)), - }; + return { ...result, data: filterByFeature(result.data, feature) }; }); } diff --git a/apps/web/src/lib/llm-proxy-helpers.ts b/apps/web/src/lib/llm-proxy-helpers.ts index 46632ae44..294c2bcf0 100644 --- a/apps/web/src/lib/llm-proxy-helpers.ts +++ b/apps/web/src/lib/llm-proxy-helpers.ts @@ -263,8 +263,8 @@ export function modelDoesNotExistResponse() { ); } -export function featureExclusiveModelResponse() { - const error = `This model is only available in KiloClaw and OpenClaw. Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; +export function featureExclusiveModelResponse(exclusiveTo: ReadonlyArray) { + const error = `This model is only available for ${exclusiveTo.join(', ')}. Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; return NextResponse.json({ error, message: error }, { status: 403 }); } diff --git a/apps/web/src/lib/models.ts b/apps/web/src/lib/models.ts index c9f6eaad2..cd718721c 100644 --- a/apps/web/src/lib/models.ts +++ b/apps/web/src/lib/models.ts @@ -94,14 +94,22 @@ export function findKiloExclusiveModel(model: string): KiloExclusiveModel | null } /** - * Returns true if the model should be excluded from results for the given feature. - * A model is excluded when it has an `exclusive_to` restriction, the feature is known, + * Returns true if the model should be excluded for the given feature. + * A model is excluded when its `exclusive_to` list is non-empty, the feature is known, * and the feature is not in `exclusive_to`. * When feature is null (no header sent), the model is always included. */ export function isExcludedForFeature(modelId: string, feature: FeatureValue | null): boolean { const model = kiloExclusiveModels.find(m => m.public_id === modelId); - if (!model?.exclusive_to?.length) return false; + if (!model?.exclusive_to.length) return false; if (!feature) return false; return !model.exclusive_to.includes(feature); } + +/** Filters out models that are not available for the given feature. */ +export function filterByFeature( + models: T[], + feature: FeatureValue | null +): T[] { + return models.filter(m => !isExcludedForFeature(m.id, feature)); +} diff --git a/apps/web/src/lib/providers/anthropic.constants.ts b/apps/web/src/lib/providers/anthropic.constants.ts index c5ce8cfa7..7eeb7b99c 100644 --- a/apps/web/src/lib/providers/anthropic.constants.ts +++ b/apps/web/src/lib/providers/anthropic.constants.ts @@ -20,4 +20,5 @@ export const claude_sonnet_clawsetup_model: KiloExclusiveModel = { flags: ['reasoning', 'vision'], inference_provider: null, pricing: null, + exclusive_to: [], }; diff --git a/apps/web/src/lib/providers/bytedance.ts b/apps/web/src/lib/providers/bytedance.ts index 6c4bc3f4f..60086b6e6 100644 --- a/apps/web/src/lib/providers/bytedance.ts +++ b/apps/web/src/lib/providers/bytedance.ts @@ -13,4 +13,5 @@ export const seed_20_pro_free_model: KiloExclusiveModel = { internal_id: 'seed-2-0-pro-260328', inference_provider: 'seed', pricing: null, + exclusive_to: [], }; diff --git a/apps/web/src/lib/providers/kilo-exclusive-model.ts b/apps/web/src/lib/providers/kilo-exclusive-model.ts index 3056273ae..44111ec2e 100644 --- a/apps/web/src/lib/providers/kilo-exclusive-model.ts +++ b/apps/web/src/lib/providers/kilo-exclusive-model.ts @@ -31,8 +31,8 @@ export type KiloExclusiveModel = { internal_id: string; inference_provider: OpenRouterInferenceProviderId | null; pricing: Pricing | null; - /** If set, only requests from these features are allowed to use this model. */ - exclusive_to?: ReadonlyArray; + /** Features allowed to use this model. Empty array means no restriction. */ + exclusive_to: ReadonlyArray; }; function formatPricePerMillionAsPerToken(price: number): string; diff --git a/apps/web/src/lib/providers/minimax.ts b/apps/web/src/lib/providers/minimax.ts index 7840618c7..1ab672e95 100644 --- a/apps/web/src/lib/providers/minimax.ts +++ b/apps/web/src/lib/providers/minimax.ts @@ -13,6 +13,7 @@ export const minimax_m25_free_model: KiloExclusiveModel = { internal_id: 'minimax/minimax-m2.5', inference_provider: null, pricing: null, + exclusive_to: [], }; export function isMinimaxModel(model: string) { diff --git a/apps/web/src/lib/providers/morph.ts b/apps/web/src/lib/providers/morph.ts index 783cc5fee..05b1e1f32 100644 --- a/apps/web/src/lib/providers/morph.ts +++ b/apps/web/src/lib/providers/morph.ts @@ -13,4 +13,5 @@ export const morph_warp_grep_free_model: KiloExclusiveModel = { internal_id: 'morph-warp-grep-v2', inference_provider: 'morph', pricing: null, + exclusive_to: [], }; diff --git a/apps/web/src/lib/providers/openai.ts b/apps/web/src/lib/providers/openai.ts index 072297254..5ecd76f3b 100644 --- a/apps/web/src/lib/providers/openai.ts +++ b/apps/web/src/lib/providers/openai.ts @@ -25,4 +25,5 @@ export const gpt_oss_20b_free_model: KiloExclusiveModel = { internal_id: 'openai/gpt-oss-20b', inference_provider: null, pricing: null, + exclusive_to: [], }; diff --git a/apps/web/src/lib/providers/qwen.ts b/apps/web/src/lib/providers/qwen.ts index 5eadbc219..ca1ca3f45 100644 --- a/apps/web/src/lib/providers/qwen.ts +++ b/apps/web/src/lib/providers/qwen.ts @@ -37,4 +37,5 @@ export const qwen36_plus_model: KiloExclusiveModel = { ); }, }, + exclusive_to: [], }; diff --git a/apps/web/src/lib/providers/stepfun.ts b/apps/web/src/lib/providers/stepfun.ts index b9ed71660..28d6eb833 100644 --- a/apps/web/src/lib/providers/stepfun.ts +++ b/apps/web/src/lib/providers/stepfun.ts @@ -17,4 +17,5 @@ export const stepfun_35_flash_free_model: KiloExclusiveModel = { internal_id: 'stepfun/step-3.5-flash', inference_provider: null, pricing: null, + exclusive_to: [], }; diff --git a/apps/web/src/lib/providers/xai.ts b/apps/web/src/lib/providers/xai.ts index f56217518..ea82adfed 100644 --- a/apps/web/src/lib/providers/xai.ts +++ b/apps/web/src/lib/providers/xai.ts @@ -14,6 +14,7 @@ export const grok_code_fast_1_optimized_free_model: KiloExclusiveModel = { internal_id: 'x-ai/grok-code-fast-1:optimized', inference_provider: 'stealth', pricing: null, + exclusive_to: [], }; export function isXaiModel(requestedModel: string) { From 6c09919521cabef91bb63bf9c5961194d40b3aa7 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:17:28 +0000 Subject: [PATCH 5/7] refactor: move exclusiveTo lookup into featureExclusiveModelResponse, add model id to message --- apps/web/src/app/api/openrouter/[...path]/route.ts | 5 +---- apps/web/src/lib/llm-proxy-helpers.ts | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/web/src/app/api/openrouter/[...path]/route.ts b/apps/web/src/app/api/openrouter/[...path]/route.ts index 165f2ae8b..731082e1a 100644 --- a/apps/web/src/app/api/openrouter/[...path]/route.ts +++ b/apps/web/src/app/api/openrouter/[...path]/route.ts @@ -26,7 +26,6 @@ import { isExcludedForFeature, isKiloExclusiveFreeModel, isKiloStealthModel, - kiloExclusiveModels, } from '@/lib/models'; import { accountForMicrodollarUsage, @@ -235,9 +234,7 @@ export async function POST(request: NextRequest): Promise m.public_id === originalModelIdLowerCased)?.exclusive_to ?? []; - return featureExclusiveModelResponse(exclusiveTo); + return featureExclusiveModelResponse(originalModelIdLowerCased); } // Extract IP for all requests (needed for free model rate limiting) diff --git a/apps/web/src/lib/llm-proxy-helpers.ts b/apps/web/src/lib/llm-proxy-helpers.ts index 294c2bcf0..51a2f6cd7 100644 --- a/apps/web/src/lib/llm-proxy-helpers.ts +++ b/apps/web/src/lib/llm-proxy-helpers.ts @@ -263,8 +263,10 @@ export function modelDoesNotExistResponse() { ); } -export function featureExclusiveModelResponse(exclusiveTo: ReadonlyArray) { - const error = `This model is only available for ${exclusiveTo.join(', ')}. Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; +export function featureExclusiveModelResponse(modelId: string) { + const exclusiveTo = + kiloExclusiveModels.find(m => m.public_id === modelId)?.exclusive_to ?? []; + const error = `${modelId} is only available for ${exclusiveTo.join(', ')}. Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; return NextResponse.json({ error, message: error }, { status: 403 }); } From 1eb06ff3899d86ba0511063325932fcdab5bfaf5 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:20:43 +0000 Subject: [PATCH 6/7] style: fix oxfmt line length in featureExclusiveModelResponse --- apps/web/src/lib/llm-proxy-helpers.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/lib/llm-proxy-helpers.ts b/apps/web/src/lib/llm-proxy-helpers.ts index 51a2f6cd7..d22ba835f 100644 --- a/apps/web/src/lib/llm-proxy-helpers.ts +++ b/apps/web/src/lib/llm-proxy-helpers.ts @@ -266,7 +266,9 @@ export function modelDoesNotExistResponse() { export function featureExclusiveModelResponse(modelId: string) { const exclusiveTo = kiloExclusiveModels.find(m => m.public_id === modelId)?.exclusive_to ?? []; - const error = `${modelId} is only available for ${exclusiveTo.join(', ')}. Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; + const error = + `${modelId} is only available for ${exclusiveTo.join(', ')}. ` + + `Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; return NextResponse.json({ error, message: error }, { status: 403 }); } From 9b04a4611a8fb95a3d21d1d0188e8b8f3ab7dfdb Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:24:45 +0000 Subject: [PATCH 7/7] style: use single-line template literal to satisfy oxfmt --- apps/web/src/lib/llm-proxy-helpers.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/web/src/lib/llm-proxy-helpers.ts b/apps/web/src/lib/llm-proxy-helpers.ts index d22ba835f..4e957d5ee 100644 --- a/apps/web/src/lib/llm-proxy-helpers.ts +++ b/apps/web/src/lib/llm-proxy-helpers.ts @@ -264,11 +264,8 @@ export function modelDoesNotExistResponse() { } export function featureExclusiveModelResponse(modelId: string) { - const exclusiveTo = - kiloExclusiveModels.find(m => m.public_id === modelId)?.exclusive_to ?? []; - const error = - `${modelId} is only available for ${exclusiveTo.join(', ')}. ` + - `Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; + const exclusiveTo = kiloExclusiveModels.find(m => m.public_id === modelId)?.exclusive_to ?? []; + const error = `${modelId} is only available for ${exclusiveTo.join(', ')}. Use ${KILO_AUTO_FREE_MODEL.id} as a free alternative.`; return NextResponse.json({ error, message: error }, { status: 403 }); }