mirror of
https://github.com/supabase/supabase.git
synced 2026-09-22 13:37:53 +08:00
9b17ce8f2c
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Feature / chore: hide assistant model selection in the UI and default chats to GPT-5.6 Luna. ## What is the current behavior? The assistant composer exposes a model picker. Paid orgs default to `gpt-5.3-codex`; everyone else defaults to `gpt-5.4-nano`. ## What is the new behavior? - The model picker is hidden in the assistant composer and Explorer home. - Chats default to `gpt-5.6-luna` with `reasoningEffort: medium`. - Model selection plumbing is kept (registry, entitlements, `setModel`, generate-v4 request body) so a requested model can still be honored when provided. - Other completion endpoints still use `gpt-5.4-nano`. ## Additional context Model selector UI can be re-enabled by passing `selectedModel` / `onSelectModel` to `AssistantChatForm`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for the GPT-5.6 Luna model with medium reasoning capability. * Made GPT-5.6 Luna the default assistant model. * **Improvements** * Simplified assistant chat by removing model selection from the primary chat experience. * Updated model fallback behavior to use the standard assistant model. * Chat forms can now optionally display model selection when configured. * **Tests** * Updated model coverage and assistant chat tests for the new defaults and behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
165 lines
6.3 KiB
TypeScript
165 lines
6.3 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
ASSISTANT_MODELS,
|
|
DEFAULT_ASSISTANT_ADVANCE_MODEL_ID,
|
|
DEFAULT_ASSISTANT_BASE_MODEL_ID,
|
|
DEFAULT_COMPLETION_MODEL,
|
|
defaultAssistantModelId,
|
|
getAssistantModelEntry,
|
|
getDefaultModelForProvider,
|
|
isAdvanceOnlyModelId,
|
|
isAssistantBaseModelId,
|
|
isKnownAssistantModelId,
|
|
openaiModelEntry,
|
|
PROVIDERS,
|
|
} from './model.utils'
|
|
import type { ProviderName } from './model.utils'
|
|
|
|
describe('model.utils', () => {
|
|
describe('getDefaultModelForProvider', () => {
|
|
it('should return correct default for bedrock provider', () => {
|
|
const result = getDefaultModelForProvider('bedrock')
|
|
expect(result).toBe('openai.gpt-oss-120b-1:0')
|
|
})
|
|
|
|
it('should return correct default for openai provider', () => {
|
|
const result = getDefaultModelForProvider('openai')
|
|
expect(result).toBe('gpt-5.4-nano')
|
|
})
|
|
|
|
it('should return undefined for unknown provider', () => {
|
|
const result = getDefaultModelForProvider('unknown' as ProviderName)
|
|
expect(result).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe('PROVIDERS registry', () => {
|
|
it('should have bedrock provider with models', () => {
|
|
expect(PROVIDERS.bedrock).toBeDefined()
|
|
expect(PROVIDERS.bedrock.models).toBeDefined()
|
|
expect(Object.keys(PROVIDERS.bedrock.models)).toContain(
|
|
'anthropic.claude-3-7-sonnet-20250219-v1:0'
|
|
)
|
|
expect(Object.keys(PROVIDERS.bedrock.models)).toContain('openai.gpt-oss-120b-1:0')
|
|
})
|
|
|
|
it('should have openai provider with models', () => {
|
|
expect(PROVIDERS.openai).toBeDefined()
|
|
expect(PROVIDERS.openai.models).toBeDefined()
|
|
expect(Object.keys(PROVIDERS.openai.models)).toContain('gpt-5.6-luna')
|
|
expect(Object.keys(PROVIDERS.openai.models)).toContain('gpt-5.4-nano')
|
|
expect(Object.keys(PROVIDERS.openai.models)).toContain('gpt-5.3-codex')
|
|
})
|
|
|
|
it('should have exactly one default model per provider', () => {
|
|
const providers: ProviderName[] = ['bedrock', 'openai']
|
|
|
|
providers.forEach((provider) => {
|
|
const models = PROVIDERS[provider].models
|
|
const defaultModels = Object.entries(models).filter(([_, config]) => config.default)
|
|
expect(defaultModels.length).toBe(1)
|
|
})
|
|
})
|
|
|
|
it('should have valid model configurations', () => {
|
|
const providers: ProviderName[] = ['bedrock', 'openai']
|
|
|
|
providers.forEach((provider) => {
|
|
const models = PROVIDERS[provider].models
|
|
Object.entries(models).forEach(([_modelId, config]) => {
|
|
expect(config).toHaveProperty('default')
|
|
expect(typeof config.default).toBe('boolean')
|
|
})
|
|
})
|
|
})
|
|
|
|
it('should have bedrock model with systemProviderOptions', () => {
|
|
const sonnetModel = PROVIDERS.bedrock.models['anthropic.claude-3-7-sonnet-20250219-v1:0']
|
|
expect(sonnetModel.systemProviderOptions).toBeDefined()
|
|
expect(sonnetModel.systemProviderOptions?.bedrock).toBeDefined()
|
|
expect(sonnetModel.systemProviderOptions?.bedrock?.cachePoint).toEqual({
|
|
type: 'default',
|
|
})
|
|
})
|
|
|
|
it('should have openai provider with providerOptions', () => {
|
|
expect(PROVIDERS.openai.providerOptions).toBeDefined()
|
|
expect(PROVIDERS.openai.providerOptions?.openai).toBeDefined()
|
|
expect(PROVIDERS.openai.providerOptions?.openai?.reasoningEffort).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe('assistant model registry', () => {
|
|
it('should have non-empty base and advance tiers', () => {
|
|
expect(
|
|
ASSISTANT_MODELS.filter((m) => !m.requiresAdvanceModelEntitlement).length
|
|
).toBeGreaterThan(0)
|
|
expect(
|
|
ASSISTANT_MODELS.filter((m) => m.requiresAdvanceModelEntitlement).length
|
|
).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('all model IDs should be unique', () => {
|
|
const ids = ASSISTANT_MODELS.map((m) => m.id)
|
|
expect(new Set(ids).size).toBe(ids.length)
|
|
})
|
|
|
|
it('should have all models in openai provider registry', () => {
|
|
ASSISTANT_MODELS.forEach((entry) => {
|
|
expect(Object.keys(PROVIDERS.openai.models)).toContain(entry.id)
|
|
})
|
|
})
|
|
|
|
it('defaults should satisfy unions', () => {
|
|
expect(DEFAULT_ASSISTANT_BASE_MODEL_ID).toBe('gpt-5.6-luna')
|
|
expect(DEFAULT_ASSISTANT_ADVANCE_MODEL_ID).toBe('gpt-5.3-codex')
|
|
expect(defaultAssistantModelId(false)).toBe(DEFAULT_ASSISTANT_BASE_MODEL_ID)
|
|
expect(defaultAssistantModelId(true)).toBe(DEFAULT_ASSISTANT_BASE_MODEL_ID)
|
|
})
|
|
|
|
it('isAssistantBaseModelId / isAdvanceOnlyModelId', () => {
|
|
expect(isAssistantBaseModelId('gpt-5.6-luna')).toBe(true)
|
|
expect(isAssistantBaseModelId('gpt-5.4-nano')).toBe(true)
|
|
expect(isAssistantBaseModelId('gpt-5.3-codex')).toBe(false)
|
|
expect(isAdvanceOnlyModelId('gpt-5.3-codex')).toBe(true)
|
|
expect(isAdvanceOnlyModelId('gpt-5.4-nano')).toBe(false)
|
|
expect(isAdvanceOnlyModelId('gpt-5.6-luna')).toBe(false)
|
|
})
|
|
|
|
it('isKnownAssistantModelId', () => {
|
|
expect(isKnownAssistantModelId('gpt-5.6-luna')).toBe(true)
|
|
expect(isKnownAssistantModelId('gpt-5.4-nano')).toBe(true)
|
|
expect(isKnownAssistantModelId('gpt-5.3-codex')).toBe(true)
|
|
expect(isKnownAssistantModelId('gpt-5')).toBe(false)
|
|
expect(isKnownAssistantModelId('gpt-5-mini')).toBe(false)
|
|
expect(isKnownAssistantModelId('unknown')).toBe(false)
|
|
})
|
|
|
|
it('getAssistantModelEntry returns config for known ids', () => {
|
|
expect(getAssistantModelEntry('gpt-5.6-luna').reasoningEffort).toBe('medium')
|
|
expect(getAssistantModelEntry('gpt-5.4-nano').reasoningEffort).toBe('low')
|
|
expect(getAssistantModelEntry('gpt-5.3-codex').reasoningEffort).toBe('low')
|
|
expect(getAssistantModelEntry('gpt-5.6-luna')).toEqual(
|
|
ASSISTANT_MODELS.find((m) => m.id === 'gpt-5.6-luna')
|
|
)
|
|
})
|
|
|
|
it('DEFAULT_COMPLETION_MODEL is gpt-5.4-nano with no reasoning effort', () => {
|
|
expect(DEFAULT_COMPLETION_MODEL.id).toBe('gpt-5.4-nano')
|
|
expect(DEFAULT_COMPLETION_MODEL.reasoningEffort).toBe('none')
|
|
})
|
|
|
|
it('openaiModelEntry enforces valid reasoning effort at compile time', () => {
|
|
const withEffort = openaiModelEntry({
|
|
id: 'gpt-5.6-luna',
|
|
reasoningEffort: 'low',
|
|
})
|
|
expect(withEffort.reasoningEffort).toBe('low')
|
|
|
|
const withoutEffort = openaiModelEntry({ id: 'gpt-5.6-luna' })
|
|
expect(withoutEffort.reasoningEffort).toBeUndefined()
|
|
})
|
|
})
|
|
})
|