From d0b6b4c16c97ff428e1c801f69de0c9efcf50bb5 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:40:21 +0000 Subject: [PATCH 1/3] fix(ai-gateway): filter team models requiring data collection Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- .../lib/organizations/organization-models.ts | 8 ++++++ .../organization-settings-router.test.ts | 27 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/apps/web/src/lib/organizations/organization-models.ts b/apps/web/src/lib/organizations/organization-models.ts index fd604b91fd..49e15e19a2 100644 --- a/apps/web/src/lib/organizations/organization-models.ts +++ b/apps/web/src/lib/organizations/organization-models.ts @@ -10,6 +10,7 @@ import { getDirectByokModelsForOrganization } from '@/lib/ai-gateway/providers/d import { getOrganizationById } from '@/lib/organizations/organizations'; import { getEffectiveModelRestrictions } from '@/lib/organizations/model-restrictions'; import { listAvailableExperimentModels } from '@/lib/ai-gateway/experiments/list-available-experiment-models'; +import { hasBestEffortGuessDataCollectionRequirement } from '@/lib/ai-gateway/is-free-model'; export async function getAvailableModelsForOrganization( organizationId: string @@ -40,6 +41,13 @@ export async function getAvailableModelsForOrganization( filteredModels = models; } + if (organization.plan === 'teams' && organization.settings.data_collection === 'deny') { + const dataCollectionRequirements = await Promise.all( + filteredModels.map(model => hasBestEffortGuessDataCollectionRequirement(model.id)) + ); + filteredModels = filteredModels.filter((_, index) => !dataCollectionRequirements[index]); + } + if (organization.plan !== 'enterprise' && organization.settings.data_collection !== 'deny') { filteredModels.push(...(await listAvailableExperimentModels())); } diff --git a/apps/web/src/routers/organizations/organization-settings-router.test.ts b/apps/web/src/routers/organizations/organization-settings-router.test.ts index c14dcfd112..d5a1ce9847 100644 --- a/apps/web/src/routers/organizations/organization-settings-router.test.ts +++ b/apps/web/src/routers/organizations/organization-settings-router.test.ts @@ -386,6 +386,33 @@ describe('organizations settings trpc router', () => { 'anthropic/claude-3-opus', ]); }); + + it('should exclude data-collection-required models for teams orgs that deny collection', async () => { + const openRouterModelsResponse = { + data: [ + makeOpenRouterModel('openai/gpt-4o'), + makeOpenRouterModel('openai/gpt-4o:free'), + ], + } satisfies OpenRouterModelsResponse; + + mockedGetEnhancedOpenRouterModels.mockResolvedValue(openRouterModelsResponse); + + const teamsOrg = await createTestOrganization( + 'Teams Org Denying Data Collection', + owner.id, + 0, + { data_collection: 'deny' }, + true + ); + await addUserToOrganization(teamsOrg.id, member.id, 'member'); + + const caller = await createCallerForUser(member.id); + const result = await caller.organizations.settings.listAvailableModels({ + organizationId: teamsOrg.id, + }); + + expect(result.data.map(model => model.id)).toEqual(['openai/gpt-4o']); + }); }); describe('updateDefaultModel procedure', () => { From b508b52c47e84a703cd7ad61d5c42cc508f73320 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:41:37 +0000 Subject: [PATCH 2/3] style(ai-gateway): format model filtering test Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- .../organizations/organization-settings-router.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/web/src/routers/organizations/organization-settings-router.test.ts b/apps/web/src/routers/organizations/organization-settings-router.test.ts index d5a1ce9847..4774a0fc94 100644 --- a/apps/web/src/routers/organizations/organization-settings-router.test.ts +++ b/apps/web/src/routers/organizations/organization-settings-router.test.ts @@ -389,10 +389,7 @@ describe('organizations settings trpc router', () => { it('should exclude data-collection-required models for teams orgs that deny collection', async () => { const openRouterModelsResponse = { - data: [ - makeOpenRouterModel('openai/gpt-4o'), - makeOpenRouterModel('openai/gpt-4o:free'), - ], + data: [makeOpenRouterModel('openai/gpt-4o'), makeOpenRouterModel('openai/gpt-4o:free')], } satisfies OpenRouterModelsResponse; mockedGetEnhancedOpenRouterModels.mockResolvedValue(openRouterModelsResponse); From 840f05faa46f52b9c4dd8a9fc5612f39cd7fabeb Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Wed, 17 Jun 2026 18:42:39 +0000 Subject: [PATCH 3/3] refactor(ai-gateway): use model training metadata Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- apps/web/src/lib/organizations/organization-models.ts | 6 +----- .../organizations/organization-settings-router.test.ts | 8 +++++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/web/src/lib/organizations/organization-models.ts b/apps/web/src/lib/organizations/organization-models.ts index 49e15e19a2..8f5a31e180 100644 --- a/apps/web/src/lib/organizations/organization-models.ts +++ b/apps/web/src/lib/organizations/organization-models.ts @@ -10,7 +10,6 @@ import { getDirectByokModelsForOrganization } from '@/lib/ai-gateway/providers/d import { getOrganizationById } from '@/lib/organizations/organizations'; import { getEffectiveModelRestrictions } from '@/lib/organizations/model-restrictions'; import { listAvailableExperimentModels } from '@/lib/ai-gateway/experiments/list-available-experiment-models'; -import { hasBestEffortGuessDataCollectionRequirement } from '@/lib/ai-gateway/is-free-model'; export async function getAvailableModelsForOrganization( organizationId: string @@ -42,10 +41,7 @@ export async function getAvailableModelsForOrganization( } if (organization.plan === 'teams' && organization.settings.data_collection === 'deny') { - const dataCollectionRequirements = await Promise.all( - filteredModels.map(model => hasBestEffortGuessDataCollectionRequirement(model.id)) - ); - filteredModels = filteredModels.filter((_, index) => !dataCollectionRequirements[index]); + filteredModels = filteredModels.filter(model => model.mayTrainOnYourPrompts !== true); } if (organization.plan !== 'enterprise' && organization.settings.data_collection !== 'deny') { diff --git a/apps/web/src/routers/organizations/organization-settings-router.test.ts b/apps/web/src/routers/organizations/organization-settings-router.test.ts index 4774a0fc94..e9fac0f99b 100644 --- a/apps/web/src/routers/organizations/organization-settings-router.test.ts +++ b/apps/web/src/routers/organizations/organization-settings-router.test.ts @@ -389,7 +389,13 @@ describe('organizations settings trpc router', () => { it('should exclude data-collection-required models for teams orgs that deny collection', async () => { const openRouterModelsResponse = { - data: [makeOpenRouterModel('openai/gpt-4o'), makeOpenRouterModel('openai/gpt-4o:free')], + data: [ + makeOpenRouterModel('openai/gpt-4o'), + { + ...makeOpenRouterModel('openai/gpt-4o:free'), + mayTrainOnYourPrompts: true, + }, + ], } satisfies OpenRouterModelsResponse; mockedGetEnhancedOpenRouterModels.mockResolvedValue(openRouterModelsResponse);