Skip to content

Commit ff42b48

Browse files
committed
Share benchmark super-user eligibility with Plan and knowledge graphs
1 parent 405add8 commit ff42b48

19 files changed

Lines changed: 137 additions & 69 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ export default async function OrganizationLayout({
7878
),
7979
isTableRowTtlEnabled(),
8080
isMothershipModelSelectorEnabled(),
81-
isPlanModeEnabled(),
81+
isPlanModeEnabled(session.user.id),
8282
isDashboardsEnabled(organizationId),
83-
isMemorySpacesEnabled(),
83+
isMemorySpacesEnabled(session.user.id),
8484
canUseBenchmarks(session.user.id),
8585
])
8686
const initialSidebarCollapsed = cookieStore.get('sidebar_collapsed')?.value === '1'

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export default async function WorkspaceLayout({
8181
),
8282
isTableRowTtlEnabled(),
8383
isMothershipModelSelectorEnabled(),
84-
isPlanModeEnabled(),
84+
isPlanModeEnabled(session.user.id),
8585
resolveOrganizationEntryPath(session),
8686
isDashboardsEnabled(hostContext.hostOrganizationId),
8787
prefetchWorkspaceAccess(queryClient, workspaceId, principal),

‎apps/sim/bootstrap.ts‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
import { loadRuntimeSecrets } from '@sim/runtime-secrets'
77

88
await loadRuntimeSecrets()
9-
// Explicit runtime configuration wins over deployment defaults.
10-
process.env.MSHIP_PLAN_MODE ??=
11-
process.env.MSHIP_PLAN_MODE_DEFAULT ?? (process.env.NODE_ENV === 'development' ? 'true' : 'false')
129
// `server.js` is the Next standalone build artifact, a sibling of this file in
1310
// the image; it does not exist at type-check time, so the specifier is held in a
1411
// variable to keep it out of static module resolution.

‎apps/sim/lib/core/config/env.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,6 @@ export const env = createEnv({
600600
// AgentMail - Mothership Email Inbox
601601
AGENTMAIL_API_KEY: z.string().min(1).optional(), // AgentMail API key for mothership email inbox
602602
AGENTMAIL_DOMAIN: z.string().optional(), // Custom domain for AgentMail inboxes (default: agentmail.to)
603-
MSHIP_PLAN_MODE: z.boolean().optional(),
604603
DASHBOARDS: z.boolean().optional(),
605604
MSHIP_COMPUTER_USE: z.boolean().optional(),
606605
MSHIP_MODEL_SELECTOR: z.boolean().optional(),

‎apps/sim/lib/core/config/feature-flags.test.ts‎

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ setEnv({
4343
TABLES_V2_API: undefined,
4444
TABLE_ROW_TTL: undefined,
4545
MSHIP_MODEL_SELECTOR: undefined,
46-
MSHIP_PLAN_MODE: undefined,
4746
MSHIP_COMPUTER_USE: undefined,
4847
AGENT_MEMORY_HISTORY: undefined,
4948
CREDENTIAL_GROUPS: undefined,
@@ -378,20 +377,16 @@ describe('table-row-ttl flag', () => {
378377
})
379378
})
380379

381-
describe('Mothership model and Plan flags', () => {
380+
describe('Mothership model selector flag', () => {
382381
beforeEach(() => {
383382
setEnvFlags({ isAppConfigEnabled: false })
384383
envRef.MSHIP_MODEL_SELECTOR = undefined
385-
envRef.MSHIP_PLAN_MODE = undefined
386384
})
387385

388386
it('defaults off without AppConfig and accepts explicit self-hosted settings', async () => {
389387
expect(await isFeatureEnabled('mothership-model-selector')).toBe(false)
390-
expect(await isFeatureEnabled('mothership-plan-mode')).toBe(false)
391388
envRef.MSHIP_MODEL_SELECTOR = true
392-
envRef.MSHIP_PLAN_MODE = true
393389
expect(await isFeatureEnabled('mothership-model-selector')).toBe(true)
394-
expect(await isFeatureEnabled('mothership-plan-mode')).toBe(true)
395390
})
396391

397392
it.each(['sim-dev', 'sim-staging', 'sim-production'])(
@@ -403,10 +398,8 @@ describe('Mothership model and Plan flags', () => {
403398
for (const value of [true, false]) {
404399
withAppConfig({
405400
'mothership-model-selector': { enabled: value },
406-
'mothership-plan-mode': { enabled: value },
407401
})
408402
expect(await isFeatureEnabled('mothership-model-selector')).toBe(value)
409-
expect(await isFeatureEnabled('mothership-plan-mode')).toBe(value)
410403
}
411404
} finally {
412405
envRef.APPCONFIG_APPLICATION = previous

‎apps/sim/lib/core/config/feature-flags.ts‎

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,6 @@ const FEATURE_FLAGS = {
6868
'models. Global on/off only; disabled uses Astra with simplified effort labels.',
6969
fallback: 'MSHIP_MODEL_SELECTOR',
7070
},
71-
'mothership-memory-spaces': {
72-
description: 'Enable private Graphiti memory and its graph-management settings in Mothership.',
73-
fallback: null,
74-
},
75-
'mothership-plan-mode': {
76-
description:
77-
'Show and admit Mothership Plan conversations. Global on/off only, shared by organization ' +
78-
'and workspace surfaces.',
79-
fallback: 'MSHIP_PLAN_MODE',
80-
},
8171
'agent-memory-history': {
8272
description:
8373
'Capture durable Workflow Agent tool history and continue existing retries. Supports workspace rollout targeting; version-aware memory storage remains active when capture is disabled.',

‎apps/sim/lib/mothership/chat/application/admit-turn.test.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { copilotChats, copilotRuns, member } from '@sim/db/schema'
1+
import { copilotChats, copilotRuns, member, settings, user } from '@sim/db/schema'
22
import {
33
dbChainMockFns,
44
queueTableRows,
@@ -122,6 +122,9 @@ describe('organization turn admission through current private-chat authorization
122122
it.each(['agent', 'assistant', 'plan'] as const)(
123123
'switches the same chat to %s atomically with turn admission',
124124
async (mode) => {
125+
setEnvFlags({ isMothershipBenchmarkEnabled: true })
126+
queueTableRows(user, [{ role: 'admin' }])
127+
queueTableRows(settings, [{ superUserModeEnabled: true }])
125128
queueTableRows(copilotChats, [{ ...chat, mode: mode === 'agent' ? 'assistant' : 'agent' }])
126129
queueTableRows(member, [{ role: 'owner' }])
127130
if (mode !== 'assistant') queueTableRows(member, [{ role: 'owner' }])

‎apps/sim/lib/mothership/chat/application/create-workspace-chat.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { db } from '@sim/db'
33
import { copilotChats } from '@sim/db/schema'
44
import { defineAuthorizedWorkspaceUseCase } from '@/lib/core/application/authorized-workspace-use-case'
55
import { defineWorkspaceOperation } from '@/lib/core/application/workspace-operation'
6+
import { OrchestrationError } from '@/lib/core/orchestration/types'
67
import { publishChatStatusChanged } from '@/lib/mothership/chat-status'
78
import { MOTHERSHIP_CHAT_DEFAULT_MODEL } from '@/lib/mothership/constants'
9+
import { isPlanModeEnabled } from '@/lib/mothership/feature-flags'
810
import { selectedMemorySpaceForNewChat } from '@/lib/mothership/memory/spaces'
911
import { resolveActiveWorkspaceApplicationContext } from '@/lib/workspaces/application/workspace-context'
1012

@@ -25,6 +27,8 @@ export const createWorkspaceChat = defineAuthorizedWorkspaceUseCase({
2527
authorizationOptions: {},
2628
async execute({ principal, context, input }) {
2729
const userId = requirePrincipalSubjectUserId(principal)
30+
if (input.mode === 'plan' && !(await isPlanModeEnabled(userId)))
31+
throw new OrchestrationError('not_found', 'Plan mode is unavailable')
2832
const [chat] = await db
2933
.insert(copilotChats)
3034
.values({

‎apps/sim/lib/mothership/chat/organization-chats.test.ts‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { dbChainMockFns, resetDbChainMock, resetEnvFlagsMock, setEnvFlags } from '@sim/testing'
1+
import { settings, user } from '@sim/db/schema'
2+
import {
3+
dbChainMockFns,
4+
queueTableRows,
5+
resetDbChainMock,
6+
resetEnvFlagsMock,
7+
setEnvFlags,
8+
} from '@sim/testing'
29
import { createSessionPrincipal } from '@sim/testing/factories/principal.factory'
310
import {
411
knowledgeAvailabilityMock,
@@ -207,10 +214,12 @@ describe('organization Build admission', () => {
207214
async ({ role, billing, denied, allowed }) => {
208215
authorize.mockResolvedValue({ userId: 'member-1', organizationId: 'org-1', role })
209216
permissionConfig.mockResolvedValue({ disableWorkspaceCreation: denied })
210-
setEnvFlags({ isBillingEnabled: billing })
217+
setEnvFlags({ isBillingEnabled: billing, isMothershipBenchmarkEnabled: true })
211218
dbChainMockFns.returning.mockResolvedValue([{ id: 'new-chat' }])
212219
for (const mode of ['agent', 'plan'] as const) {
213220
for (const operation of [authorizeOrganizationChat, createOrganizationChat]) {
221+
queueTableRows(user, [{ role: 'admin' }])
222+
queueTableRows(settings, [{ superUserModeEnabled: true }])
214223
const result = operation.execute({
215224
principal: session,
216225
input: { organizationId: 'org-1', mode },

‎apps/sim/lib/mothership/chat/organization-chats.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { OrchestrationError } from '@/lib/core/orchestration/types'
1010
import { listMothershipChats } from '@/lib/mothership/chat/list-mothership-chats'
1111
import { publishChatStatusChanged } from '@/lib/mothership/chat-status'
1212
import { MOTHERSHIP_CHAT_DEFAULT_MODEL } from '@/lib/mothership/constants'
13+
import { isPlanModeEnabled } from '@/lib/mothership/feature-flags'
1314
import { selectedMemorySpaceForNewChat } from '@/lib/mothership/memory/spaces'
1415
import { ORGANIZATION_SECRETS_AUDIENCE } from '@/lib/organization-secrets/application/operations'
1516
import { getUserPermissionConfigForOrganization } from '@/lib/permission-groups/resolve.server'
@@ -72,6 +73,8 @@ export const authorizeOrganizationChat = {
7273
)
7374
if (input.mode === 'agent' || input.mode === 'plan')
7475
await requireOrganizationBuildPermission(context)
76+
if (input.mode === 'plan' && !(await isPlanModeEnabled(context.userId)))
77+
throw new OrchestrationError('not_found', 'Plan mode is unavailable')
7578
return context
7679
},
7780
}
@@ -122,6 +125,8 @@ export const createOrganizationChat = {
122125
)
123126
if (input.mode === 'agent' || input.mode === 'plan')
124127
await requireOrganizationBuildPermission(context)
128+
if (input.mode === 'plan' && !(await isPlanModeEnabled(context.userId)))
129+
throw new OrchestrationError('not_found', 'Plan mode is unavailable')
125130
return createOrganizationChatRecord(context, input.mode ?? 'assistant')
126131
},
127132
}

0 commit comments

Comments
 (0)