Skip to content

Commit 80ab373

Browse files
committed
Add feature flag for ai models specifically
1 parent 6a4430d commit 80ab373

File tree

4 files changed

+62
-9
lines changed

4 files changed

+62
-9
lines changed

apps/webapp/app/components/navigation/SideMenu.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -479,15 +479,17 @@ export function SideMenu({
479479
data-action="prompts"
480480
isCollapsed={isCollapsed}
481481
/>
482-
<SideMenuItem
483-
name="Models"
484-
icon={CubeIcon}
485-
activeIconColor="text-purple-500"
486-
inactiveIconColor="text-purple-500"
487-
to={v3ModelsPath(organization, project, environment)}
488-
data-action="models"
489-
isCollapsed={isCollapsed}
490-
/>
482+
{(user.admin || user.isImpersonating || featureFlags.hasAiModelsAccess) && (
483+
<SideMenuItem
484+
name="Models"
485+
icon={CubeIcon}
486+
activeIconColor="text-purple-500"
487+
inactiveIconColor="text-purple-500"
488+
to={v3ModelsPath(organization, project, environment)}
489+
data-action="models"
490+
isCollapsed={isCollapsed}
491+
/>
492+
)}
491493
<SideMenuItem
492494
name="AI Metrics"
493495
icon={AIMetricsIcon}

apps/webapp/app/env.server.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,9 @@ const EnvironmentSchema = z
12251225
// AI features (Prompts, Models, AI Metrics sidebar section)
12261226
AI_FEATURES_ENABLED: z.string().default("0"),
12271227

1228+
// AI Models feature (Models sidebar item within AI section)
1229+
AI_MODELS_ENABLED: z.string().default("0"),
1230+
12281231
// Logs page ClickHouse URL (for logs queries)
12291232
LOGS_CLICKHOUSE_URL: z
12301233
.string()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { prisma } from "~/db.server";
2+
import { env } from "~/env.server";
3+
import { FEATURE_FLAG, makeFlag } from "~/v3/featureFlags.server";
4+
5+
export async function canAccessAiModels(options: {
6+
userId: string;
7+
isAdmin: boolean;
8+
isImpersonating: boolean;
9+
organizationSlug: string;
10+
}): Promise<boolean> {
11+
const { userId, isAdmin, isImpersonating, organizationSlug } = options;
12+
13+
// 1. If env var is set then globally enabled
14+
if (env.AI_MODELS_ENABLED === "1") {
15+
return true;
16+
}
17+
18+
// 2. Admins always have access
19+
if (isAdmin || isImpersonating) {
20+
return true;
21+
}
22+
23+
// 3. Check if org/global feature flag is on
24+
const org = await prisma.organization.findFirst({
25+
where: {
26+
slug: organizationSlug,
27+
members: { some: { userId } },
28+
},
29+
select: {
30+
featureFlags: true,
31+
},
32+
});
33+
34+
const flag = makeFlag();
35+
const flagResult = await flag({
36+
key: FEATURE_FLAG.hasAiModelsAccess,
37+
defaultValue: false,
38+
overrides: (org?.featureFlags as Record<string, unknown>) ?? {},
39+
});
40+
if (flagResult) {
41+
return true;
42+
}
43+
44+
// 4. Not enabled anywhere
45+
return false;
46+
}

apps/webapp/app/v3/featureFlags.server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const FEATURE_FLAG = {
88
hasQueryAccess: "hasQueryAccess",
99
hasLogsPageAccess: "hasLogsPageAccess",
1010
hasAiAccess: "hasAiAccess",
11+
hasAiModelsAccess: "hasAiModelsAccess",
1112
} as const;
1213

1314
const FeatureFlagCatalog = {
@@ -17,6 +18,7 @@ const FeatureFlagCatalog = {
1718
[FEATURE_FLAG.hasQueryAccess]: z.coerce.boolean(),
1819
[FEATURE_FLAG.hasLogsPageAccess]: z.coerce.boolean(),
1920
[FEATURE_FLAG.hasAiAccess]: z.coerce.boolean(),
21+
[FEATURE_FLAG.hasAiModelsAccess]: z.coerce.boolean(),
2022
};
2123

2224
type FeatureFlagKey = keyof typeof FeatureFlagCatalog;

0 commit comments

Comments
 (0)