From 799371e55523fcee5804b5e1902606441f955704 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 31 Aug 2026 15:50:33 +0000
Subject: [PATCH 1/2] =?UTF-8?q?cherry-pick=20of=20#28772=20failed=20?=
=?UTF-8?q?=E2=80=94=20resolve=20conflicts=20manually?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cherry-pick of 3d3b36ff893ba7bb84b46cc96b3a0f738c64eb8f onto release/2.37 had conflicts.
To resolve:
git fetch origin backport/28772-to-2.37
git checkout backport/28772-to-2.37
git cherry-pick -x -m1 3d3b36ff893ba7bb84b46cc96b3a0f738c64eb8f
# resolve conflicts
git push origin backport/28772-to-2.37
From ea65bd950a46d491c5c8f4cfb34cbe79321ce694 Mon Sep 17 00:00:00 2001
From: Ethan <39577870+ethanndickson@users.noreply.github.com>
Date: Mon, 31 Aug 2026 17:49:57 +0200
Subject: [PATCH 2/2] fix(site): remove member-facing Models nav item (#28772)
(cherry picked from commit 3d3b36ff893ba7bb84b46cc96b3a0f738c64eb8f)
---
.../dashboard/DashboardLayout.stories.tsx | 79 -------------------
.../dashboard/Navbar/MobileMenu.stories.tsx | 36 +--------
.../modules/dashboard/Navbar/MobileMenu.tsx | 7 --
site/src/modules/dashboard/Navbar/Navbar.tsx | 6 --
.../dashboard/Navbar/NavbarView.stories.tsx | 34 --------
.../modules/dashboard/Navbar/NavbarView.tsx | 22 +-----
6 files changed, 2 insertions(+), 182 deletions(-)
diff --git a/site/src/modules/dashboard/DashboardLayout.stories.tsx b/site/src/modules/dashboard/DashboardLayout.stories.tsx
index d57b63f83f655..a4fb15928a8c4 100644
--- a/site/src/modules/dashboard/DashboardLayout.stories.tsx
+++ b/site/src/modules/dashboard/DashboardLayout.stories.tsx
@@ -5,15 +5,10 @@ import {
reactRouterParameters,
} from "storybook-addon-remix-react-router";
import { buildInfoKey } from "#/api/queries/buildInfo";
-import { chatModels } from "#/api/queries/chats";
import { deploymentStatsQueryKey } from "#/api/queries/deployment";
import { organizationsPermissions } from "#/api/queries/organizations";
import { updateCheckQueryKey } from "#/api/queries/updateCheck";
import type { UpdateCheckResponse } from "#/api/typesGenerated";
-import {
- MockChatModel,
- MockChatModelProviderDescriptor,
-} from "#/testHelpers/chatModels";
import {
MockBuildInfo,
MockDefaultOrganization,
@@ -55,17 +50,6 @@ const mcpServersRouter = reactRouterParameters({
],
});
-const modelSettingsRouter = reactRouterParameters({
- location: { path: "/" },
- routing: [
- { path: "/", useStoryElement: true },
- {
- path: "/ai/settings/models",
- element:
Organization models
,
- },
- ],
-});
-
const meta: Meta = {
title: "modules/dashboard/DashboardLayout",
component: DashboardLayout,
@@ -124,57 +108,6 @@ export const ForMember: Story = {
},
};
-export const CustomOrganizationRoleCanOpenModels: Story = {
- parameters: {
- pixel: { matrix: pixelWithDesktop },
- user: MockUserMember,
- permissions: MockNoPermissions,
- reactRouter: modelSettingsRouter,
- queries: [
- { key: buildInfoKey, data: MockBuildInfo },
- { key: updateCheckQueryKey, data: MockUpdateCheck },
- { key: deploymentStatsQueryKey, data: MockDeploymentStats },
- {
- key: organizationsPermissions([MockDefaultOrganization.id]).queryKey,
- data: {
- [MockDefaultOrganization.id]: {
- ...MockNoOrganizationPermissions,
- viewChatModelConfigs: true,
- },
- },
- },
- ],
- },
- play: openModels,
-};
-
-export const ACLReadableMemberCanOpenModels: Story = {
- parameters: {
- pixel: { matrix: pixelWithDesktop },
- user: MockUserMember,
- permissions: MockNoPermissions,
- reactRouter: modelSettingsRouter,
- queries: [
- { key: buildInfoKey, data: MockBuildInfo },
- { key: updateCheckQueryKey, data: MockUpdateCheck },
- { key: deploymentStatsQueryKey, data: MockDeploymentStats },
- {
- key: chatModels(MockDefaultOrganization.id).queryKey,
- data: {
- models: [
- {
- ...MockChatModel,
- organization_id: MockDefaultOrganization.id,
- },
- ],
- providers: [MockChatModelProviderDescriptor],
- },
- },
- ],
- },
- play: openModels,
-};
-
export const CustomOrganizationRoleCanOpenMCPServers: Story = {
parameters: {
pixel: { matrix: pixelWithDesktop },
@@ -243,15 +176,3 @@ export const SkipToMainContent: Story = {
await expect(main).toHaveFocus();
},
};
-
-async function openModels({ canvasElement }: { canvasElement: HTMLElement }) {
- const user = userEvent.setup();
- const canvas = within(canvasElement);
- await expect(
- canvas.queryByRole("button", { name: "Admin settings" }),
- ).not.toBeInTheDocument();
- await user.click(canvas.getByRole("link", { name: "Models" }));
- await expect(
- await canvas.findByRole("heading", { name: "Organization models" }),
- ).toBeInTheDocument();
-}
diff --git a/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx b/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx
index b7c5478a29a83..d8391c1f95845 100644
--- a/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx
+++ b/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx
@@ -1,7 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import type { FC } from "react";
-import { expect, fn, userEvent, within } from "storybook/test";
-import { reactRouterParameters } from "storybook-addon-remix-react-router";
+import { fn, userEvent, within } from "storybook/test";
import {
MockPrimaryWorkspaceProxy,
MockProxyLatencies,
@@ -43,7 +42,6 @@ const meta: Meta = {
supportLinks: MockSupportLinks,
onSignOut: fn(),
isDefaultOpen: true,
- canViewModels: false,
adminPermissions: {
canViewDeployment: true,
canViewOrganizations: true,
@@ -98,38 +96,6 @@ export const Member: Story = {
},
};
-export const MemberWithModelAccess: Story = {
- parameters: {
- reactRouter: reactRouterParameters({
- location: { path: "/" },
- routing: [
- { path: "/", useStoryElement: true },
- {
- path: "/ai/settings/models",
- element: Organization models
,
- },
- ],
- }),
- },
- args: {
- user: MockUserMember,
- adminPermissions: {},
- canViewModels: true,
- },
- play: async ({ canvasElement }) => {
- const user = userEvent.setup();
- const canvas = within(canvasElement);
- const body = within(canvasElement.ownerDocument.body);
- await expect(
- body.queryByRole("menuitem", { name: /admin settings/i }),
- ).not.toBeInTheDocument();
- await user.click(body.getByRole("menuitem", { name: "Models" }));
- await expect(
- await canvas.findByRole("heading", { name: "Organization models" }),
- ).toBeInTheDocument();
- },
-};
-
export const ProxySettings: Story = {
play: async ({ canvasElement }) => {
const user = userEvent.setup();
diff --git a/site/src/modules/dashboard/Navbar/MobileMenu.tsx b/site/src/modules/dashboard/Navbar/MobileMenu.tsx
index d09f925c2cc50..b8bd979a74b68 100644
--- a/site/src/modules/dashboard/Navbar/MobileMenu.tsx
+++ b/site/src/modules/dashboard/Navbar/MobileMenu.tsx
@@ -43,7 +43,6 @@ const itemStyles = {
type MobileMenuProps = {
proxyContextValue?: ProxyContextValue;
- canViewModels: boolean;
adminPermissions: AdminSettingsPermissions;
user?: TypesGen.User;
supportLinks?: readonly TypesGen.LinkConfig[];
@@ -53,7 +52,6 @@ type MobileMenuProps = {
export const MobileMenu: FC = ({
adminPermissions,
- canViewModels,
proxyContextValue,
user,
supportLinks,
@@ -89,11 +87,6 @@ export const MobileMenu: FC = ({
Agents
- {canViewModels && (
-
- Models
-
- )}
diff --git a/site/src/modules/dashboard/Navbar/Navbar.tsx b/site/src/modules/dashboard/Navbar/Navbar.tsx
index 4a0024011f660..e21feecc6732c 100644
--- a/site/src/modules/dashboard/Navbar/Navbar.tsx
+++ b/site/src/modules/dashboard/Navbar/Navbar.tsx
@@ -10,7 +10,6 @@ import {
canViewDeploymentSettings,
} from "#/modules/permissions";
import { useCanShareOrganizationMCPServers } from "#/pages/AISettingsPage/MCPServersPage/organizationSharing";
-import { useAccessibleModelOrganizations } from "#/pages/AISettingsPage/ModelsPage/organizationModels";
import { useFeatureVisibility } from "../useFeatureVisibility";
import { NavbarView } from "./NavbarView";
@@ -22,8 +21,6 @@ export const Navbar: React.FC = () => {
const { user: me, permissions, signOut } = useAuthenticated();
const featureVisibility = useFeatureVisibility();
const proxyContextValue = useProxy();
- const accessibleModelOrgsQuery =
- useAccessibleModelOrganizations(organizations);
const canAccessAnyModel = canAccessAnyChatModelConfig(permissions);
const canViewDeployment = canViewDeploymentSettings(permissions);
@@ -51,8 +48,6 @@ export const Navbar: React.FC = () => {
);
const canViewAISettings =
canViewSiteWideAISettings || organizationMCPSharing.canShare;
- const canViewModels =
- !canViewAISettings && accessibleModelOrgsQuery.organizations.length > 0;
const canCreateChat = permissions.createChat;
const uniqueLinks = new Map();
@@ -76,7 +71,6 @@ export const Navbar: React.FC = () => {
canViewAIBridge,
canViewHealth,
}}
- canViewModels={canViewModels}
canCreateChat={canCreateChat}
proxyContextValue={proxyContextValue}
/>
diff --git a/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx b/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
index 563d9dbc4a4ac..09560b7636490 100644
--- a/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
+++ b/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx
@@ -72,7 +72,6 @@ const meta: Meta = {
canViewAIBridge: true,
canViewHealth: true,
},
- canViewModels: false,
canCreateChat: true,
supportLinks: [],
},
@@ -328,39 +327,6 @@ export const ForUserWithoutOrganization: Story = {
},
};
-export const ForMemberWithModelAccess: Story = {
- parameters: {
- pixel: { matrix: pixelWithDesktop },
- reactRouter: reactRouterParameters({
- location: { path: "/" },
- routing: [
- { path: "/", useStoryElement: true },
- {
- path: "/ai/settings/models",
- element: Organization models
,
- },
- ],
- }),
- },
- args: {
- user: MockUserMember,
- adminPermissions: {},
- canViewModels: true,
- canCreateChat: false,
- },
- play: async ({ canvasElement }) => {
- const user = userEvent.setup();
- const canvas = within(canvasElement);
- await expect(
- canvas.queryByRole("button", { name: "Admin settings" }),
- ).not.toBeInTheDocument();
- await user.click(canvas.getByRole("link", { name: "Models" }));
- await expect(
- await canvas.findByRole("heading", { name: "Organization models" }),
- ).toBeInTheDocument();
- },
-};
-
export const ForMember: Story = {
args: {
user: MockUserMember,
diff --git a/site/src/modules/dashboard/Navbar/NavbarView.tsx b/site/src/modules/dashboard/Navbar/NavbarView.tsx
index a51df951659f4..7167570c42477 100644
--- a/site/src/modules/dashboard/Navbar/NavbarView.tsx
+++ b/site/src/modules/dashboard/Navbar/NavbarView.tsx
@@ -33,7 +33,6 @@ interface NavbarViewProps {
onSignOut: () => void;
adminPermissions: AdminSettingsPermissions;
canCreateChat: boolean;
- canViewModels: boolean;
proxyContextValue?: ProxyContextValue;
}
@@ -50,7 +49,6 @@ export const NavbarView: FC = ({
onSignOut,
adminPermissions,
canCreateChat,
- canViewModels,
proxyContextValue,
}) => {
const prerelease = getPrereleaseFlag(buildInfo);
@@ -82,7 +80,6 @@ export const NavbarView: FC = ({
@@ -148,7 +145,6 @@ export const NavbarView: FC = ({
= ({
interface NavItemsProps {
className?: string;
user: TypesGen.User;
- canViewModels: boolean;
canCreateChat: boolean;
}
-const NavItems: FC = ({
- className,
- user,
- canCreateChat,
- canViewModels,
-}) => {
+const NavItems: FC = ({ className, user, canCreateChat }) => {
const location = useLocation();
return (
@@ -197,16 +187,6 @@ const NavItems: FC = ({
Templates
- {canViewModels && (
-
- cn(linkStyles.default, { [linkStyles.active]: isActive })
- }
- to="/ai/settings/models"
- >
- Models
-
- )}
{canCreateChat && (
{