feat(web): gate /create and /refine slash commands behind feature preview flag (#37094)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Crazywoola
2026-06-08 02:32:52 +00:00
committed by GitHub
co-authored by Claude Opus 4.8
parent a88c15c906
commit db1aa683bc
12 changed files with 643 additions and 62 deletions
+4
View File
@@ -84,6 +84,10 @@ NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL=true
# Default is false for security reasons to prevent conflicts with regular text
NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX=false
# Enable preview features still in development (currently the /create and
# /refine slash commands in the "Go to Anything" command palette)
NEXT_PUBLIC_ENABLE_FEATURE_PREVIEW=false
# The maximum number of tree node depth for workflow
NEXT_PUBLIC_MAX_TREE_DEPTH=50
@@ -9,6 +9,7 @@ const {
mockRegister,
mockSearch,
mockUnregister,
featureFlag,
} = vi.hoisted(() => ({
mockSetTheme: vi.fn(),
mockSetLocale: vi.fn(),
@@ -16,6 +17,14 @@ const {
mockRegister: vi.fn(),
mockSearch: vi.fn(),
mockUnregister: vi.fn(),
// Mutable holder so each test can flip the feature-preview flag before render.
featureFlag: { enabled: false },
}))
vi.mock('@/config', () => ({
get ENABLE_FEATURE_PREVIEW() {
return featureFlag.enabled
},
}))
vi.mock('next-themes', () => ({
@@ -92,9 +101,47 @@ describe('slashAction', () => {
describe('SlashCommandProvider', () => {
beforeEach(() => {
vi.clearAllMocks()
// Default: feature preview off, so /create and /refine are NOT registered.
featureFlag.enabled = false
})
it('should register commands on mount and unregister them on unmount', () => {
it('should not register the /create and /refine preview commands when the feature flag is off', () => {
const { unmount } = render(<SlashCommandProvider />)
expect(mockRegister.mock.calls.map(call => call[0].name)).toEqual([
'theme',
'language',
'forum',
'docs',
'community',
'account',
'zen',
'go',
])
expect(mockRegister).toHaveBeenCalledWith(expect.objectContaining({ name: 'theme' }), { setTheme: mockSetTheme })
expect(mockRegister).toHaveBeenCalledWith(expect.objectContaining({ name: 'language' }), { setLocale: mockSetLocale })
unmount()
// Unregister is always called for the preview commands (a no-op when they
// were never registered) so toggling the flag off mid-session stays clean.
expect(mockUnregister.mock.calls.map(call => call[0])).toEqual([
'theme',
'language',
'forum',
'docs',
'community',
'account',
'zen',
'go',
'create',
'refine',
])
})
it('should register the /create and /refine preview commands when the feature flag is on', () => {
featureFlag.enabled = true
const { unmount } = render(<SlashCommandProvider />)
expect(mockRegister.mock.calls.map(call => call[0].name)).toEqual([
@@ -109,8 +156,6 @@ describe('SlashCommandProvider', () => {
'create',
'refine',
])
expect(mockRegister).toHaveBeenCalledWith(expect.objectContaining({ name: 'theme' }), { setTheme: mockSetTheme })
expect(mockRegister).toHaveBeenCalledWith(expect.objectContaining({ name: 'language' }), { setLocale: mockSetLocale })
unmount()
@@ -3,6 +3,7 @@ import type { ActionItem } from '../types'
import { useTheme } from 'next-themes'
import { useEffect } from 'react'
import { getI18n } from 'react-i18next'
import { ENABLE_FEATURE_PREVIEW } from '@/config'
import { setLocaleOnClient } from '@/i18n-config'
import { accountCommand } from './account'
import { executeCommand } from './command-bus'
@@ -52,8 +53,11 @@ const registerSlashCommands = (deps: Record<string, any>) => {
slashCommandRegistry.register(accountCommand, {})
slashCommandRegistry.register(zenCommand, {})
slashCommandRegistry.register(goCommand, {})
slashCommandRegistry.register(createCommand, {})
slashCommandRegistry.register(refineCommand, {})
// `/create` and `/refine` are preview features, gated behind a flag.
if (ENABLE_FEATURE_PREVIEW) {
slashCommandRegistry.register(createCommand, {})
slashCommandRegistry.register(refineCommand, {})
}
}
const unregisterSlashCommands = () => {
@@ -66,6 +70,7 @@ const unregisterSlashCommands = () => {
slashCommandRegistry.unregister('account')
slashCommandRegistry.unregister('zen')
slashCommandRegistry.unregister('go')
// No-op when the preview flag is off and these were never registered.
slashCommandRegistry.unregister('create')
slashCommandRegistry.unregister('refine')
}
+1
View File
@@ -314,6 +314,7 @@ export const ENABLE_WEBSITE_JINAREADER = env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREAD
export const ENABLE_WEBSITE_FIRECRAWL = env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL
export const ENABLE_WEBSITE_WATERCRAWL = env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL
export const ENABLE_SINGLE_DOLLAR_LATEX = env.NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX
export const ENABLE_FEATURE_PREVIEW = env.NEXT_PUBLIC_ENABLE_FEATURE_PREVIEW
export const VALUE_SELECTOR_DELIMITER = '@@@'
+1
View File
@@ -55,6 +55,7 @@ export NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER=${ENABLE_WEBSITE_JINAREADER:-true}
export NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL=${ENABLE_WEBSITE_FIRECRAWL:-true}
export NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL=${ENABLE_WEBSITE_WATERCRAWL:-true}
export NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX=${NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX:-false}
export NEXT_PUBLIC_ENABLE_FEATURE_PREVIEW=${NEXT_PUBLIC_ENABLE_FEATURE_PREVIEW:-false}
export NEXT_PUBLIC_LOOP_NODE_MAX_COUNT=${LOOP_NODE_MAX_COUNT}
export NEXT_PUBLIC_MAX_PARALLEL_LIMIT=${MAX_PARALLEL_LIMIT}
export NEXT_PUBLIC_MAX_ITERATIONS_NUM=${MAX_ITERATIONS_NUM}
+7
View File
@@ -63,6 +63,12 @@ const clientSchema = {
* The deployment edition, SELF_HOSTED
*/
NEXT_PUBLIC_EDITION: z.enum(['SELF_HOSTED', 'CLOUD']).default('SELF_HOSTED'),
/**
* Enable preview features that are still in development.
* Currently gates the `/create` and `/refine` slash commands in the
* "Go to Anything" command palette (Cmd/Ctrl+K).
*/
NEXT_PUBLIC_ENABLE_FEATURE_PREVIEW: coercedBoolean.default(false),
/**
* Cloud-only system-features defaults.
@@ -190,6 +196,7 @@ export const env = createEnv({
NEXT_PUBLIC_DEPLOY_ENV: isServer ? process.env.NEXT_PUBLIC_DEPLOY_ENV : getRuntimeEnvFromBody('deployEnv'),
NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON: isServer ? process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON : getRuntimeEnvFromBody('disableUploadImageAsIcon'),
NEXT_PUBLIC_EDITION: isServer ? process.env.NEXT_PUBLIC_EDITION : getRuntimeEnvFromBody('edition'),
NEXT_PUBLIC_ENABLE_FEATURE_PREVIEW: isServer ? process.env.NEXT_PUBLIC_ENABLE_FEATURE_PREVIEW : getRuntimeEnvFromBody('enableFeaturePreview'),
/**
* Cloud-only system-features defaults.