Skip to content

Commit 19e8407

Browse files
committed
fix(mothership): resolve model and Plan controls from AppConfig
1 parent ddb9ca6 commit 19e8407

29 files changed

Lines changed: 225 additions & 135 deletions

‎apps/sim/app/o/[organizationId]/home/components/composer/composer.test.tsx‎

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ vi.mock('@/lib/core/config/deployment-shape', () => ({
4040
useDeploymentShape: () => ({
4141
features: {
4242
liveEnterpriseSearch: mocks.live,
43-
planMode: mocks.plan,
44-
mothershipModelSelector: mocks.advanced,
4543
},
4644
}),
4745
getDeploymentShape: () => ({ features: { liveEnterpriseSearch: mocks.live } }),
@@ -89,6 +87,7 @@ vi.mock('@/app/o/[organizationId]/providers/organization-provider', () => ({
8987
}))
9088

9189
import { Composer } from '@/app/o/[organizationId]/home/components/composer/composer'
90+
import { FeatureFlagsProvider } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider'
9291
import { useFileAttachments } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-file-attachments'
9392

9493
let root: Root
@@ -228,7 +227,15 @@ async function render(
228227
await act(async () =>
229228
root.render(
230229
<QueryClientProvider client={queryClient}>
231-
<Harness />
230+
<FeatureFlagsProvider
231+
flags={{
232+
'table-row-ttl': false,
233+
'mothership-model-selector': mocks.advanced,
234+
'mothership-plan-mode': mocks.plan,
235+
}}
236+
>
237+
<Harness />
238+
</FeatureFlagsProvider>
232239
</QueryClientProvider>
233240
)
234241
)
@@ -479,7 +486,15 @@ it('keeps restored queued skills scoped when replacing a draft', async () => {
479486
await act(async () =>
480487
root.render(
481488
<QueryClientProvider client={queryClient}>
482-
<Harness />
489+
<FeatureFlagsProvider
490+
flags={{
491+
'table-row-ttl': false,
492+
'mothership-model-selector': mocks.advanced,
493+
'mothership-plan-mode': mocks.plan,
494+
}}
495+
>
496+
<Harness />
497+
</FeatureFlagsProvider>
483498
</QueryClientProvider>
484499
)
485500
)

‎apps/sim/app/o/[organizationId]/home/organization-home.test.tsx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ const mocks = vi.hoisted(() => ({
3030
selectResource: vi.fn(),
3131
activeResource: null as string | null,
3232
}))
33+
vi.mock('@/app/workspace/[workspaceId]/providers/feature-flags-provider', () => ({
34+
useFeatureFlag: (name: string) => (name === 'mothership-plan-mode' ? mocks.plan : false),
35+
}))
3336
vi.mock('@/lib/core/config/deployment-shape', () => ({
3437
useDeploymentShape: () => ({
35-
features: { liveEnterpriseSearch: mocks.live, planMode: mocks.plan },
38+
features: { liveEnterpriseSearch: mocks.live },
3639
}),
3740
getDeploymentShape: () => ({ features: { liveEnterpriseSearch: mocks.live } }),
3841
}))

‎apps/sim/app/o/[organizationId]/home/organization-home.tsx‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { requestJson } from '@/lib/api/client/request'
99
import type { WorkspaceSearchFilters } from '@/lib/api/contracts/knowledge'
1010
import { getWorkspaceHostContextContract } from '@/lib/api/contracts/workspaces'
1111
import { useSession } from '@/lib/auth/auth-client'
12-
import { getDeploymentShape, useDeploymentShape } from '@/lib/core/config/deployment-shape'
12+
import { getDeploymentShape } from '@/lib/core/config/deployment-shape'
1313
import { MothershipHandoffStorage } from '@/lib/core/utils/browser-storage'
1414
import { getMothershipAttachmentPreviewUrl } from '@/lib/mothership/chat/attachment-preview'
1515
import { createSearchResource } from '@/lib/mothership/resources/search'
@@ -35,6 +35,7 @@ import type {
3535
FileAttachmentForApi,
3636
WorkspaceResourceRef,
3737
} from '@/app/workspace/[workspaceId]/home/types'
38+
import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider'
3839
import { useFileAttachments } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-file-attachments'
3940
import { mentionifyIntegrations } from '@/blocks/integration-matcher'
4041
import { useMarkMothershipChatRead } from '@/hooks/queries/mothership-chats'
@@ -80,7 +81,7 @@ function OrganizationHomeContent({
8081
)
8182
const rememberMode = useOrganizationChatModeStore((state) => state.setMode)
8283
const [selectedMode, setSelectedMode] = useState<ChatRequestMode | null>(null)
83-
const planEnabled = useDeploymentShape().features.planMode === true
84+
const planEnabled = useFeatureFlag('mothership-plan-mode')
8485
const requestMode =
8586
selectedMode ??
8687
(urlSearchLevel && searchAccess.memberScoped && !chatId ? 'assistant' : undefined) ??

‎apps/sim/app/o/[organizationId]/layout.tsx‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { cookies } from 'next/headers'
33
import { redirect } from 'next/navigation'
44
import { getSession } from '@/lib/auth'
55
import { getActiveOrganizationId } from '@/lib/auth/session-response'
6+
import { isMothershipModelSelectorEnabled, isPlanModeEnabled } from '@/lib/mothership/feature-flags'
67
import { organizationRoutes, WORKSPACE_SETTINGS_PATH } from '@/lib/navigation/paths'
78
import { getOrganizationSurfaceContext } from '@/lib/organizations/surface'
89
import { isTableRowTtlEnabled } from '@/lib/table/ttl-availability'
@@ -53,20 +54,28 @@ export default async function OrganizationLayout({
5354
if (!context.mothershipAvailable && !context.searchAccess.memberScoped)
5455
redirect(WORKSPACE_SETTINGS_PATH)
5556

56-
const [, tableRowTtlEnabled] = await Promise.all([
57+
const [, tableRowTtlEnabled, modelSelectorEnabled, planModeEnabled] = await Promise.all([
5758
prefetchOrganizationSidebar(
5859
queryClient,
5960
organizationId,
6061
{ kind: 'session', userId: session.user.id, sessionId: session.session.id },
6162
getActiveOrganizationId(session)
6263
),
6364
isTableRowTtlEnabled(),
65+
isMothershipModelSelectorEnabled(),
66+
isPlanModeEnabled(),
6467
])
6568
const initialSidebarCollapsed = cookieStore.get('sidebar_collapsed')?.value === '1'
6669

6770
return (
6871
<HydrationBoundary state={dehydrate(queryClient)}>
69-
<FeatureFlagsProvider flags={{ 'table-row-ttl': tableRowTtlEnabled }}>
72+
<FeatureFlagsProvider
73+
flags={{
74+
'table-row-ttl': tableRowTtlEnabled,
75+
'mothership-model-selector': modelSelectorEnabled,
76+
'mothership-plan-mode': planModeEnabled,
77+
}}
78+
>
7079
<OrganizationProvider context={context}>
7180
<GlobalCommandsProvider>
7281
<div className='workspace-root flex h-screen w-full flex-col overflow-hidden bg-[var(--surface-1)]'>

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/conversation-mode-selector.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import { useState } from 'react'
44
import { ChipDropdown, cn, Tooltip } from '@sim/emcn'
55
import { Search } from '@sim/emcn/icons'
6-
import { useDeploymentShape } from '@/lib/core/config/deployment-shape'
76
import type { ChatRequestMode } from '@/app/workspace/[workspaceId]/home/types'
7+
import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider'
88

99
interface ConversationModeSelectorProps {
1010
value: ChatRequestMode
@@ -18,7 +18,7 @@ export function ConversationModeSelector({
1818
searchEnabled = false,
1919
onChange,
2020
}: ConversationModeSelectorProps) {
21-
const planEnabled = useDeploymentShape().features.planMode === true
21+
const planEnabled = useFeatureFlag('mothership-plan-mode')
2222
const [open, setOpen] = useState(false)
2323
const search = value === 'assistant'
2424
const options = [

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ import {
99
DropdownMenuRadioGroup,
1010
DropdownMenuTrigger,
1111
} from '@sim/emcn'
12-
import { useDeploymentShape } from '@/lib/core/config/deployment-shape'
1312
import {
1413
MOTHERSHIP_MODEL_OPTIONS,
1514
MOTHERSHIP_SIMPLE_EFFORT_OPTIONS,
1615
mothershipEffortOptions,
1716
resolveMothershipModelSettings,
1817
} from '@/lib/mothership/model-options'
1918
import { FastModeToggle } from '@/app/workspace/[workspaceId]/home/components/user-input/components/fast-mode-toggle'
19+
import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider'
2020
import { useMothershipEffortStore } from '@/stores/mothership-effort/store'
2121

2222
/** Reasoning effort and Fast mode for Build chat composers. */
2323
export function ModelSelector() {
24-
const advanced = useDeploymentShape().features.mothershipModelSelector === true
24+
const advanced = useFeatureFlag('mothership-model-selector')
2525
const selection = useMothershipEffortStore((state) => state.modelSelection)
2626
const setModel = useMothershipEffortStore((state) => state.setModel)
2727
const setFastMode = useMothershipEffortStore((state) => state.setFastMode)

‎apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.mount-send.test.tsx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ const { mockRequestJson, mockExecuteWorkflow, navigationMocks } = vi.hoisted(()
4343
},
4444
}))
4545

46+
vi.mock('@/app/workspace/[workspaceId]/providers/feature-flags-provider', () => ({
47+
useFeatureFlag: () => false,
48+
}))
49+
4650
vi.mock('next/navigation', () => navigationMocks)
4751
vi.mock('@/lib/auth/auth-client', async (importOriginal) => ({
4852
...(await importOriginal<typeof import('@/lib/auth/auth-client')>()),

‎apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import {
2121
} from '@/app/workspace/[workspaceId]/home/hooks/use-chat'
2222
import type { ContentBlock } from '@/app/workspace/[workspaceId]/home/types'
2323

24+
vi.mock('@/app/workspace/[workspaceId]/providers/feature-flags-provider', () => ({
25+
useFeatureFlag: () => false,
26+
}))
27+
2428
vi.mock('next/navigation', () => ({
2529
usePathname: () => '/workspace/workspace-1/home',
2630
useRouter: () => ({

‎apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ import {
106106
} from '@/app/workspace/[workspaceId]/home/hooks/stream'
107107
import { useNativeActiveTabIds } from '@/app/workspace/[workspaceId]/home/hooks/use-desktop-tab-resources'
108108
import { resolveEffectiveResourceId } from '@/app/workspace/[workspaceId]/home/resource-view-policy'
109+
import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider'
109110
import {
110111
fetchMothershipChatHistory,
111112
type MothershipChatHistory,
@@ -652,6 +653,7 @@ export function useChat(
652653
initialChatId?: string,
653654
options?: UseChatOptions
654655
): UseChatReturn {
656+
const modelSelectorEnabled = useFeatureFlag('mothership-model-selector')
655657
const workspaceId = typeof owner === 'string' ? owner : undefined
656658
const organizationId = typeof owner === 'string' ? undefined : owner.organizationId
657659
const scopeKey = typeof owner === 'string' ? owner : `organization:${owner.organizationId}`
@@ -3673,7 +3675,7 @@ export function useChat(
36733675
? {
36743676
...resolveMothershipModelSettings(
36753677
useMothershipEffortStore.getState(),
3676-
getDeploymentShape().features.mothershipModelSelector === true
3678+
modelSelectorEnabled
36773679
),
36783680
}
36793681
: {}),
@@ -3882,6 +3884,7 @@ export function useChat(
38823884
scopeKey,
38833885
queryClient,
38843886
upsertChatHistory,
3887+
modelSelectorEnabled,
38853888
processSSEStream,
38863889
finalize,
38873890
resumeOrFinalize,

‎apps/sim/app/workspace/[workspaceId]/layout.tsx‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { cookies } from 'next/headers'
33
import { redirect } from 'next/navigation'
44
import { getSession } from '@/lib/auth'
55
import { getActiveOrganizationId } from '@/lib/auth/session-response'
6+
import { isMothershipModelSelectorEnabled, isPlanModeEnabled } from '@/lib/mothership/feature-flags'
67
import { isTableRowTtlEnabled } from '@/lib/table/ttl-availability'
78
import { getQueryClient } from '@/app/_shell/providers/get-query-client'
89
import { ImpersonationBanner } from '@/app/workspace/[workspaceId]/components/impersonation-banner'
@@ -48,7 +49,14 @@ export default async function WorkspaceLayout({
4849
}
4950

5051
const activeOrganizationId = getActiveOrganizationId(session)
51-
const [cookieStore, initialOrgSettings, , tableRowTtlEnabled] = await Promise.all([
52+
const [
53+
cookieStore,
54+
initialOrgSettings,
55+
,
56+
tableRowTtlEnabled,
57+
modelSelectorEnabled,
58+
planModeEnabled,
59+
] = await Promise.all([
5260
cookies(),
5361
hostContext.hostOrganizationId
5462
? getOrgWhitelabelSettings(hostContext.hostOrganizationId)
@@ -61,6 +69,8 @@ export default async function WorkspaceLayout({
6169
activeOrganizationId
6270
),
6371
isTableRowTtlEnabled(),
72+
isMothershipModelSelectorEnabled(),
73+
isPlanModeEnabled(),
6474
prefetchWorkspaceAccess(queryClient, workspaceId, {
6575
kind: 'session',
6676
userId: session.user.id,
@@ -71,7 +81,13 @@ export default async function WorkspaceLayout({
7181

7282
return (
7383
<HydrationBoundary state={dehydrate(queryClient)}>
74-
<FeatureFlagsProvider flags={{ 'table-row-ttl': tableRowTtlEnabled }}>
84+
<FeatureFlagsProvider
85+
flags={{
86+
'table-row-ttl': tableRowTtlEnabled,
87+
'mothership-model-selector': modelSelectorEnabled,
88+
'mothership-plan-mode': planModeEnabled,
89+
}}
90+
>
7591
<WorkspaceHostProvider workspaceId={workspaceId} initialContext={hostContext}>
7692
<BrandingProvider
7793
hostOrganizationId={hostContext.hostOrganizationId}

0 commit comments

Comments
 (0)